From 81013f0c7029809fce525986999411550b7b7766 Mon Sep 17 00:00:00 2001 From: Alexander Egorenkov Date: Wed, 24 Nov 2021 15:15:39 +0100 Subject: [PATCH] zdump/zg: Convert error and abort macros to functions which can be mocked MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change allows mocking of error/abort macros in unit tests. Being able to do this in unit tests, enables us to test error conditions w/o terminating the unit test runner. The new error functions do not have "noreturn" attribute because this would make mocking of them in unit tests impossible. We must not compile these functions as noreturn because we need to return from them in unit tests and returning from a noreturn function is an undefined behavior in the C++ standard! For more details: - ISO/IEC 14882:2017, Chapter 10.6.8 "Noreturn attribute"" - https://en.cppreference.com/w/cpp/language/attributes/noreturn. Signed-off-by: Alexander Egorenkov Signed-off-by: Jan Höppner --- zdump/Makefile | 2 +- zdump/dfi.c | 2 ++ zdump/zg.h | 34 ++++++----------------- zdump/zg_error.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 27 deletions(-) create mode 100644 zdump/zg_error.c diff --git a/zdump/Makefile b/zdump/Makefile index 1e822933..3d6817a0 100644 --- a/zdump/Makefile +++ b/zdump/Makefile @@ -41,7 +41,7 @@ check_dep_zlib: all: check_dep_fuse check_dep_zlib zgetdump -OBJECTS = zgetdump.o opts.o zg.o \ +OBJECTS = zgetdump.o opts.o zg.o zg_error.o \ dfi.o dfi_mem_chunk.o dfi_vmcoreinfo.o \ dfi_lkcd.o dfi_elf.o \ dfi_s390.o dfi_s390_ext.o\ diff --git a/zdump/dfi.c b/zdump/dfi.c index 5564c43e..0a52c355 100644 --- a/zdump/dfi.c +++ b/zdump/dfi.c @@ -286,6 +286,7 @@ const char *dfi_arch_str(enum dfi_arch arch) return "unknown"; } ABORT("dfi_arch_str: Invalid dfi arch: %d", arch); + return NULL; /* UNREACHABLE */ } /* @@ -784,6 +785,7 @@ int dfi_init(void) i++; } ERR_EXIT("No valid dump found on \"%s\"", g.opts.device); + return -1; /* UNREACHABLE */ } /* diff --git a/zdump/zg.h b/zdump/zg.h index 558dde55..627bb9ca 100644 --- a/zdump/zg.h +++ b/zdump/zg.h @@ -71,34 +71,16 @@ void zg_progress(u64 addr); /* * Error and print functions */ -#define ERR(x...) \ -do { \ - fprintf(stderr, "%s: ", "zgetdump"); \ - fprintf(stderr, x); \ - fprintf(stderr, "\n"); \ -} while (0) -#define ERR_EXIT(x...) \ -do { \ - ERR(x); \ - zg_exit(1); \ -} while (0) +void zg_err(const char *fmt, ...); +void zg_err_exit(const char *fmt, ...); +void zg_err_exit_errno(const char *fmt, ...); +void zg_abort(const char *fmt, ...); -#define ABORT(x...) \ -do { \ - ERR("Internal Error: " x); \ - abort(); \ -} while (0) - -#define ERR_EXIT_ERRNO(x...) \ - do { \ - fflush(stdout); \ - fprintf(stderr, "%s: ", "zgetdump"); \ - fprintf(stderr, x); \ - fprintf(stderr, " (%s)", strerror(errno)); \ - fprintf(stderr, "\n"); \ - zg_exit(1); \ - } while (0) +#define ERR(fmt, ...) zg_err(fmt, ## __VA_ARGS__) +#define ERR_EXIT(fmt, ...) zg_err_exit(fmt, ## __VA_ARGS__) +#define ERR_EXIT_ERRNO(fmt, ...) zg_err_exit_errno(fmt, ## __VA_ARGS__) +#define ABORT(fmt, ...) zg_abort(fmt, ## __VA_ARGS__) #define STDERR(x...) \ do { \ diff --git a/zdump/zg_error.c b/zdump/zg_error.c new file mode 100644 index 00000000..99cbd611 --- /dev/null +++ b/zdump/zg_error.c @@ -0,0 +1,70 @@ +/* + * Copyright IBM Corp. 2001, 2017, 2021 + * + * s390-tools is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include + +#include "lib/util_libc.h" +#include "zg.h" + +static inline void _zg_err(const char *fmt, va_list ap) +{ + fprintf(stderr, "%s: ", "zgetdump"); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); +} + +static inline void _zg_err_errno(const char *fmt, va_list ap) +{ + fflush(stdout); + fprintf(stderr, "%s: ", "zgetdump"); + vfprintf(stderr, fmt, ap); + fprintf(stderr, " (%s)", strerror(errno)); + fprintf(stderr, "\n"); +} + +void zg_err(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + _zg_err(fmt, ap); + va_end(ap); +} + +void zg_err_exit(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + _zg_err(fmt, ap); + va_end(ap); + zg_exit(1); +} + +void zg_err_exit_errno(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + _zg_err_errno(fmt, ap); + va_end(ap); + zg_exit(1); +} + +void zg_abort(const char *fmt, ...) +{ + char *newfmt; + va_list ap; + + newfmt = util_strcat_realloc(util_strdup("Internal Error: "), fmt); + va_start(ap, fmt); + _zg_err(newfmt, ap); + va_end(ap); + free(newfmt); + + abort(); +}