>From Jan Kratochvil: There is a longterm plan to obsolete libunwind from Fedora by new elfutils unwinder. But xorg-x11-server does not even need any external (non-glibc) unwinder.
According to e21e183059df5975e7086850d1931edb2c1bbd06 you do only self-backtrace (called local unwinding by libunwind). glibc backtrace() can do the same. According to the sample backtrace in the patch above the backtrace addresses there are the same in before/after cases, libunwind only adds resolving of address -> symbol name there, IIUC. address -> symbol name resolving can be done with RH-supported elfutils package. X.Org Bug 70746 <http://bugs.freedesktop.org/show_bug.cgi?id=70746> Cc: Marcin Slusarz <[email protected]> Cc: Jan Kratochvil <[email protected]> Signed-off-by: Peter Hutterer <[email protected]> --- This may need some extra linux checks... configure.ac | 10 ++++-- include/dix-config.h.in | 3 ++ os/backtrace.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 99 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index d36aefc..0e589f8 100644 --- a/configure.ac +++ b/configure.ac @@ -308,6 +308,12 @@ AC_CHECK_HEADER([execinfo.h],[ ])] ) +dnl elfutils for backtrace symbol lookup +AC_CHECK_HEADER([elfutils/libdwfl.h], + [AC_DEFINE(HAVE_ELFUTILS, 1, [Has elfutils]) + ELFUTILS_LIBS="-ldw"]) +AC_SUBST(ELFUTILS_LIBS) + dnl --------------------------------------------------------------------------- dnl Bus options and CPU capabilities. Replaces logic in dnl hw/xfree86/os-support/bus/Makefile.am, among others. @@ -1339,10 +1345,10 @@ AC_DEFINE(BIGREQS, 1, [Support BigRequests extension]) if test "x$SPECIAL_DTRACE_OBJECTS" = "xyes" ; then DIX_LIB='$(top_builddir)/dix/dix.O' - OS_LIB='$(top_builddir)/os/os.O $(SHA1_LIBS) $(DLOPEN_LIBS)' + OS_LIB='$(top_builddir)/os/os.O $(SHA1_LIBS) $(DLOPEN_LIBS) $(ELFUTILS_LIBS)' else DIX_LIB='$(top_builddir)/dix/libdix.la' - OS_LIB='$(top_builddir)/os/libos.la' + OS_LIB='$(top_builddir)/os/libos.la $(ELFUTILS_LIBS)' fi AC_SUBST([DIX_LIB]) AC_SUBST([OS_LIB]) diff --git a/include/dix-config.h.in b/include/dix-config.h.in index e1cb9eb..c7c0a8a 100644 --- a/include/dix-config.h.in +++ b/include/dix-config.h.in @@ -60,6 +60,9 @@ /* Has backtrace support */ #undef HAVE_BACKTRACE +/* Has elfutils */ +#undef HAVE_ELFUTILS + /* Define to 1 if you have the <byteswap.h> header file. */ #undef HAVE_BYTESWAP_H diff --git a/os/backtrace.c b/os/backtrace.c index c807bd2..acf110a 100644 --- a/os/backtrace.c +++ b/os/backtrace.c @@ -37,6 +37,89 @@ #include <dlfcn.h> #include <execinfo.h> +#ifdef HAVE_ELFUTILS +#include <unistd.h> +#include <elfutils/libdwfl.h> + +static Dwfl* +dwfl_get(void) +{ + static char *debuginfo_path; + static Dwfl *dwfl; + + static const Dwfl_Callbacks proc_callbacks = { + .find_debuginfo = dwfl_standard_find_debuginfo, + .debuginfo_path = &debuginfo_path, + .find_elf = dwfl_linux_proc_find_elf, + }; + + if (dwfl) + return dwfl; + + dwfl = dwfl_begin(&proc_callbacks); + if (!dwfl) + return NULL; + + errno = 0; + if (dwfl_linux_proc_report(dwfl, getpid ()) != 0 || + dwfl_report_end(dwfl, NULL, NULL) != 0) + { + ErrorFSigSafe("dwfl reporting: %s\n", sterror(errno)); + dwfl_end(dwfl); + dwfl = NULL; + abort(); + } + + return dwfl; +} + +struct getmodules_callback_arg { + void *addr; + const char *name; +}; + +static int +getmodules_callback(Dwfl_Module *module, + void **userdata, + const char *module_name, + Dwarf_Addr module_low_addr, void *arg) +{ + struct getmodules_callback_arg *cbarg = arg; + cbarg->name = dwfl_module_addrname(module, (GElf_Addr)cbarg->addr); + return cbarg->name ? DWARF_CB_ABORT : DWARF_CB_OK; +} + +static const char* +addr_lookup(void *addr) +{ + Dwfl *dwfl = dwfl_get(); + struct getmodules_callback_arg arg; + + arg.name = NULL; + arg.addr = addr; + dwfl_getmodules(dwfl, getmodules_callback, &arg, 0); + return arg.name; +} +#endif + +static const char* +symbol_name(void *addr, void *fbase) +{ + const char *name = NULL; + +#ifdef HAVE_ELFUTILS + name = addr_lookup(addr); +#endif + + if (!name) { + static char buf[20]; + sprintf(buf, "%p", fbase); + name = buf; + } + + return name; +} + void xorg_backtrace(void) { @@ -66,15 +149,17 @@ xorg_backtrace(void) (unsigned int)((char *) array[i] - (char *) info.dli_saddr), array[i]); - else + else { + const char *name = symbol_name(array[i], info.dli_fbase); ErrorFSigSafe( - "%u: %s (%p+0x%x) [%p]\n", + "%u: %s (%s+0x%x) [%p]\n", i, mod, - info.dli_fbase, + name, (unsigned int)((char *) array[i] - (char *) info.dli_fbase), array[i]); + } } ErrorFSigSafe("\n"); } -- 1.8.3.1 _______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
