From e39e09910fc8e369e24f6a0cabaeb9356dbfae08 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 28 Aug 2018 14:04:25 +0200 Subject: lib/core: Use libdw to decode stack trace with debugging symbols, v2. libdw is a new dependency built from the elfutils package. It provides us a way to generate line numbers and file names from the instruction pointer. elfutils is LGPLv3 or GPLv2, so it's ok to link against it. Before: IGT-Version: 1.23-g8ae86abd419d (x86_64) (Linux: 4.16.0-1-amd64 x86_64) Starting subtest: fail-result (meta_test:29661) CRITICAL: Test assertion failure function test_result, file ../tests/meta_test.c:94: (meta_test:29661) CRITICAL: Failed assertion: result == 1 (meta_test:29661) CRITICAL: error: 0 != 1 Stack trace: #0 [__igt_fail_assert+0x20a] #1 [test_result+0x7a] #2 [__real_main120+0x240] #3 [main+0x4a] #4 (../csu/libc-start.c) __libc_start_main:344 #5 [_start+0x2a] After: IGT-Version: 1.23-g8ae86abd419d (x86_64) (Linux: 4.16.0-1-amd64 x86_64) Starting subtest: fail-result (meta_test:1357) CRITICAL: Test assertion failure function test_result, file ../tests/meta_test.c:94: (meta_test:1357) CRITICAL: Failed assertion: result == 1 (meta_test:1357) CRITICAL: error: 0 != 1 Stack trace: #0 ../lib/igt_core.c:1467 __igt_fail_assert() #1 ../tests/meta_test.c:95 test_result() #2 ../tests/meta_test.c:137 __real_main120() #3 ../tests/meta_test.c:120 main() #4 ../csu/libc-start.c:344 __libc_start_main() #5 [_start+0x2a] Changes since v1: - Add libdw dependency to readme. - Change backtrace format slightly. Cc: Petri Latvala Signed-off-by: Maarten Lankhorst [mlankhorst: Add description about libdw in commit msg, name -> dwfl_name] Reviewed-by: Petri Latvala --- README | 1 + configure.ac | 1 + lib/Makefile.am | 2 ++ lib/igt_core.c | 50 +++++++++++++++++++++++++++++++++++++++++++++----- lib/meson.build | 1 + meson.build | 1 + 6 files changed, 51 insertions(+), 5 deletions(-) diff --git a/README b/README index c71ecedd..f8ba5c71 100644 --- a/README +++ b/README @@ -148,6 +148,7 @@ the default configuration (package names may vary): libpciaccess-dev libprocps-dev libunwind-dev + libdw-dev python-docutils x11proto-dri2-dev xutils-dev diff --git a/configure.ac b/configure.ac index 72f35994..c75ef284 100644 --- a/configure.ac +++ b/configure.ac @@ -128,6 +128,7 @@ PKG_CHECK_MODULES(PCIACCESS, [pciaccess >= 0.10]) PKG_CHECK_MODULES(KMOD, [libkmod]) PKG_CHECK_MODULES(PROCPS, [libprocps]) PKG_CHECK_MODULES(LIBUNWIND, [libunwind]) +PKG_CHECK_MODULES(LIBDW, [libdw]) PKG_CHECK_MODULES(SSL, [openssl]) PKG_CHECK_MODULES(VALGRIND, [valgrind], [have_valgrind=yes], [have_valgrind=no]) diff --git a/lib/Makefile.am b/lib/Makefile.am index 6251bdb8..388b8b00 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -60,6 +60,7 @@ AM_CFLAGS = \ $(DRM_CFLAGS) \ $(PCIACCESS_CFLAGS) \ $(LIBUNWIND_CFLAGS) \ + $(LIBDW_CFLAGS) \ $(GSL_CFLAGS) \ $(KMOD_CFLAGS) \ $(PROCPS_CFLAGS) \ @@ -86,6 +87,7 @@ libintel_tools_la_LIBADD = \ $(CAIRO_LIBS) \ $(LIBUDEV_LIBS) \ $(LIBUNWIND_LIBS) \ + $(LIBDW_LIBS) \ $(TIMER_LIBS) \ $(XMLRPC_LIBS) \ $(LIBUDEV_LIBS) \ diff --git a/lib/igt_core.c b/lib/igt_core.c index c52c0818..23bb858f 100644 --- a/lib/igt_core.c +++ b/lib/igt_core.c @@ -73,6 +73,7 @@ #define UNW_LOCAL_ONLY #include +#include #ifdef HAVE_LIBGEN_H #include /* for basename() on Solaris */ @@ -1212,20 +1213,59 @@ static void print_backtrace(void) unw_context_t uc; int stack_num = 0; + Dwfl_Callbacks cbs = { + .find_elf = dwfl_linux_proc_find_elf, + .find_debuginfo = dwfl_standard_find_debuginfo, + }; + + Dwfl *dwfl = dwfl_begin(&cbs); + + if (dwfl_linux_proc_report(dwfl, getpid())) { + dwfl_end(dwfl); + dwfl = NULL; + } else + dwfl_report_end(dwfl, NULL, NULL); + igt_info("Stack trace:\n"); unw_getcontext(&uc); unw_init_local(&cursor, &uc); while (unw_step(&cursor) > 0) { char name[255]; - unw_word_t off; + unw_word_t off, ip; + Dwfl_Module *mod = NULL; - if (unw_get_proc_name(&cursor, name, 255, &off) < 0) - strcpy(name, ""); + unw_get_reg(&cursor, UNW_REG_IP, &ip); + + if (dwfl) + mod = dwfl_addrmodule(dwfl, ip); - igt_info(" #%d [%s+0x%x]\n", stack_num++, name, - (unsigned int) off); + if (mod) { + const char *src, *dwfl_name; + Dwfl_Line *line; + int lineno; + GElf_Sym sym; + + line = dwfl_module_getsrc(mod, ip); + dwfl_name = dwfl_module_addrsym(mod, ip, &sym, NULL); + + if (line && dwfl_name) { + src = dwfl_lineinfo(line, NULL, &lineno, NULL, NULL, NULL); + igt_info(" #%d %s:%d %s()\n", stack_num++, src, lineno, dwfl_name); + continue; + } + } + + if (unw_get_proc_name(&cursor, name, 255, &off) < 0) + igt_info(" #%d [+0x%x]\n", stack_num++, + (unsigned int) ip); + else + igt_info(" #%d [%s+0x%x]\n", stack_num++, name, + (unsigned int) off); } + + if (dwfl) + dwfl_end(dwfl); } static const char hex[] = "0123456789abcdef"; diff --git a/lib/meson.build b/lib/meson.build index 6b554c68..e60e5e02 100644 --- a/lib/meson.build +++ b/lib/meson.build @@ -60,6 +60,7 @@ lib_deps = [ libprocps, libudev, libunwind, + libdw, pciaccess, pthreads, math, diff --git a/meson.build b/meson.build index 7278c438..faf1b764 100644 --- a/meson.build +++ b/meson.build @@ -103,6 +103,7 @@ pciaccess = dependency('pciaccess', version : '>=0.10') libkmod = dependency('libkmod') libprocps = dependency('libprocps', required : true) libunwind = dependency('libunwind', required : true) +libdw = dependency('libdw', required : true) ssl = dependency('openssl', required : true) valgrind = null_dep -- cgit v1.2.3