diff --git a/include/test.mk b/include/test.mk index 93e3818c1..ddb0575b8 100644 --- a/include/test.mk +++ b/include/test.mk @@ -13,6 +13,8 @@ DEBUG_PRINTS ?= 0 OPTIMIZATIONS=-O2 -ggdb CFLAGS_LTO = CFLAGS_GCOV = +LIBS = -lefivar + CFLAGS = $(OPTIMIZATIONS) -std=gnu11 \ -isystem $(TOPDIR)/include/system \ $(EFI_INCLUDES) \ @@ -46,6 +48,11 @@ CFLAGS = $(OPTIMIZATIONS) -std=gnu11 \ -DSHIM_UNIT_TEST \ "-DDEFAULT_DEBUG_PRINT_STATE=$(DEBUG_PRINTS)" +ifneq ($(origin ENABLE_LIBUNWIND), undefined) +CFLAGS += -DENABLE_LIBUNWIND +LIBS += -lunwind +endif + # On some systems (e.g. Arch Linux), limits.h is in the "include-fixed" instead # of the "include" directory CFLAGS += -isystem $(shell $(CC) $(ARCH_CFLAGS) -print-file-name=include-fixed) @@ -109,7 +116,7 @@ tests := $(patsubst %.c,%,$(wildcard test-*.c)) $(tests) :: test-% : | libefi-test.a $(tests) :: test-% : test.c test-%.c $(test-%_FILES) - $(CC) $(CFLAGS) -o $@ $(sort $^ $(wildcard $*.c) $(test-$*_FILES)) libefi-test.a -lefivar + $(CC) $(CFLAGS) -o $@ $(sort $^ $(wildcard $*.c) $(test-$*_FILES)) libefi-test.a $(LIBS) $(VALGRIND) ./$@ test : $(tests) diff --git a/test-load-options.c b/test-load-options.c index dfabe861f..de22c55e0 100644 --- a/test-load-options.c +++ b/test-load-options.c @@ -14,7 +14,6 @@ #include "shim.h" -#include #include #include diff --git a/test-str.c b/test-str.c index 30f8dd0b4..e2c55b5e5 100644 --- a/test-str.c +++ b/test-str.c @@ -931,7 +931,7 @@ test_strncpy(void) memset(s0, 0, sizeof(s0)); memcpy(s0, s, sizeof(s)); -#if __GNUC_PREREQ(8, 1) +#if GNUC_PREREQ(8, 1) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wstringop-truncation" #endif @@ -1033,7 +1033,7 @@ test_strncpy(void) assert_equal_return(s1[16], '\000', -1, "got %#02hhx expected %02hhx\n"); assert_equal_return(s1[17], '0', -1, "got %#02hhx expected %02hhx\n"); assert_equal_return(s1[18], '1', -1, "got %#02hhx expected %02hhx\n"); -#if __GNUC_PREREQ(8, 1) +#if GNUC_PREREQ(8, 1) # pragma GCC diagnostic pop #endif return 0; diff --git a/test.c b/test.c index c7978fa2c..e64e8ec67 100644 --- a/test.c +++ b/test.c @@ -6,10 +6,20 @@ #include "shim.h" -#include #include #include +#if defined(ENABLE_LIBUNWIND) +#include +#include +/* no backtrace() prototype in libunwind.h, however the library adds the symbol */ +extern int backtrace(void **buffer, int size); +#elif defined(__GLIBC__) +#include +#else +static int backtrace(void **buffer, int size) { (void)buffer; (void)size; return 0; } +#endif + #define BT_BUF_SIZE (4096/sizeof(void *)) static void *frames[BT_BUF_SIZE] = { 0, }; @@ -20,19 +30,33 @@ int debug = DEFAULT_DEBUG_PRINT_STATE; void print_traceback(int skip) { - int nptrs; - char **strings; - - nptrs = backtrace(frames, BT_BUF_SIZE); - if (nptrs < skip) + int nptrs = backtrace(frames, BT_BUF_SIZE); + if (nptrs <= skip) return; - strings = backtrace_symbols(frames, nptrs); - for (int i = skip; strings != NULL && i < nptrs; i++) { - printf("%p %s\n", (void *)frames[i], strings[i]); +#if defined(ENABLE_LIBUNWIND) + for (int i = skip; i < nptrs; ++i) { + void *addr = frames[i]; + Dl_info dlinfo; + + if (!dladdr(addr, &dlinfo)) { + printf("%p\n", addr); + continue; + } + + ptrdiff_t offset = addr - dlinfo.dli_saddr; + printf("%p %s(%s%c%#tx)\n", addr, + dlinfo.dli_fname ?: "", + dlinfo.dli_sname ?: "", + offset < 0 ? '-' : '+', + offset < 0 ? -offset : offset); } - if (strings) - free(strings); +#elif defined(__GLIBC__) + char **strings = backtrace_symbols(frames, nptrs); + for (int i = skip; strings != NULL && i < nptrs; i++) + printf("%p %s\n", (void *)frames[i], strings[i]); + free(strings); +#endif } #pragma GCC diagnostic ignored "-Wunused-parameter"