diff options
author | Andrew Bartlett <abartlet@samba.org> | 2018-04-10 16:35:07 +1200 |
---|---|---|
committer | Karolin Seeger <kseeger@samba.org> | 2018-06-04 09:55:29 +0200 |
commit | 5733e906fa3a55b7676d2229ed322777f94229d3 (patch) | |
tree | 142ab7ded9c467e01b84716ac54a62552438cb26 /lib | |
parent | d14cd61f45564b0a85a1946eb0e39fac02fa227d (diff) | |
download | samba-5733e906fa3a55b7676d2229ed322777f94229d3.tar.gz |
lib/util: Move log_stack_trace() to common code
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
BUG: https://bugzilla.samba.org/show_bug.cgi?id=13454
(cherry picked from commit bf9551902afdb32310db4a3381964c435dd08bf0)
Diffstat (limited to 'lib')
-rw-r--r-- | lib/util/fault.c | 104 | ||||
-rw-r--r-- | lib/util/fault.h | 1 | ||||
-rw-r--r-- | lib/util/wscript_configure | 1 |
3 files changed, 106 insertions, 0 deletions
diff --git a/lib/util/fault.c b/lib/util/fault.c index fef82a3fcf7..e539aff9e7b 100644 --- a/lib/util/fault.c +++ b/lib/util/fault.c @@ -3,6 +3,7 @@ Critical Fault handling Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Tim Prouty 2009 + Copyright (C) James Peach 2006 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -170,3 +171,106 @@ _PUBLIC_ void smb_panic(const char *why) } smb_panic_default(why); } + + + +/******************************************************************* + Print a backtrace of the stack to the debug log. This function + DELIBERATELY LEAKS MEMORY. The expectation is that you should + exit shortly after calling it. +********************************************************************/ + +/* Buffer size to use when printing backtraces */ +#define BACKTRACE_STACK_SIZE 64 + + +#ifdef HAVE_LIBUNWIND_H +#include <libunwind.h> +#endif + +#ifdef HAVE_EXECINFO_H +#include <execinfo.h> +#endif + +void log_stack_trace(void) +{ +#ifdef HAVE_LIBUNWIND + /* Try to use libunwind before any other technique since on ia64 + * libunwind correctly walks the stack in more circumstances than + * backtrace. + */ + unw_cursor_t cursor; + unw_context_t uc; + unsigned i = 0; + + char procname[256]; + unw_word_t ip, sp, off; + + procname[sizeof(procname) - 1] = '\0'; + + if (unw_getcontext(&uc) != 0) { + goto libunwind_failed; + } + + if (unw_init_local(&cursor, &uc) != 0) { + goto libunwind_failed; + } + + DEBUG(0, ("BACKTRACE:\n")); + + do { + ip = sp = 0; + unw_get_reg(&cursor, UNW_REG_IP, &ip); + unw_get_reg(&cursor, UNW_REG_SP, &sp); + + switch (unw_get_proc_name(&cursor, + procname, sizeof(procname) - 1, &off) ) { + case 0: + /* Name found. */ + case -UNW_ENOMEM: + /* Name truncated. */ + DEBUGADD(0, (" #%u %s + %#llx [ip=%#llx] [sp=%#llx]\n", + i, procname, (long long)off, + (long long)ip, (long long) sp)); + break; + default: + /* case -UNW_ENOINFO: */ + /* case -UNW_EUNSPEC: */ + /* No symbol name found. */ + DEBUGADD(0, (" #%u %s [ip=%#llx] [sp=%#llx]\n", + i, "<unknown symbol>", + (long long)ip, (long long) sp)); + } + ++i; + } while (unw_step(&cursor) > 0); + + return; + +libunwind_failed: + DEBUG(0, ("unable to produce a stack trace with libunwind\n")); + +#elif HAVE_BACKTRACE_SYMBOLS + void *backtrace_stack[BACKTRACE_STACK_SIZE]; + size_t backtrace_size; + char **backtrace_strings; + + /* get the backtrace (stack frames) */ + backtrace_size = backtrace(backtrace_stack,BACKTRACE_STACK_SIZE); + backtrace_strings = backtrace_symbols(backtrace_stack, backtrace_size); + + DEBUG(0, ("BACKTRACE: %lu stack frames:\n", + (unsigned long)backtrace_size)); + + if (backtrace_strings) { + int i; + + for (i = 0; i < backtrace_size; i++) + DEBUGADD(0, (" #%u %s\n", i, backtrace_strings[i])); + + /* Leak the backtrace_strings, rather than risk what free() might do */ + } + +#else + DEBUG(0, ("unable to produce a stack trace on this platform\n")); +#endif +} diff --git a/lib/util/fault.h b/lib/util/fault.h index 0ac6cb9ceb5..dfa339b7650 100644 --- a/lib/util/fault.h +++ b/lib/util/fault.h @@ -53,5 +53,6 @@ void fault_setup(void); void fault_setup_disable(void); _NORETURN_ void smb_panic(const char *reason); +void log_stack_trace(void); #endif /* _SAMBA_FAULT_H_ */ diff --git a/lib/util/wscript_configure b/lib/util/wscript_configure index 8e5a59c8480..2a8dbef699b 100644 --- a/lib/util/wscript_configure +++ b/lib/util/wscript_configure @@ -6,6 +6,7 @@ if Options.options.disable_fault_handling: # backtrace could be in libexecinfo or in libc conf.CHECK_FUNCS_IN('backtrace backtrace_symbols', 'execinfo', checklibc=True, headers='execinfo.h') +conf.CHECK_HEADERS('execinfo.h libunwind.h') conf.CHECK_STRUCTURE_MEMBER('struct statvfs', 'f_frsize', define='HAVE_FRSIZE', headers='sys/statvfs.h') |