summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2018-04-10 16:35:07 +1200
committerKarolin Seeger <kseeger@samba.org>2018-06-04 09:55:29 +0200
commit5733e906fa3a55b7676d2229ed322777f94229d3 (patch)
tree142ab7ded9c467e01b84716ac54a62552438cb26 /lib
parentd14cd61f45564b0a85a1946eb0e39fac02fa227d (diff)
downloadsamba-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.c104
-rw-r--r--lib/util/fault.h1
-rw-r--r--lib/util/wscript_configure1
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')