diff options
author | unknown <davi@mysql.com/endora.local> | 2008-02-07 19:58:06 -0200 |
---|---|---|
committer | unknown <davi@mysql.com/endora.local> | 2008-02-07 19:58:06 -0200 |
commit | d9831ae5329d6916667ee9beb885c3e4c35c4018 (patch) | |
tree | 8ec03724213bdbbf26572c207c4b29a76055757f /sql/stacktrace.c | |
parent | ee0b7f38567bf8661d89500b67d115d8a1cb53f8 (diff) | |
download | mariadb-git-d9831ae5329d6916667ee9beb885c3e4c35c4018.tar.gz |
Bug#31891 Meaningful stack trace
On crashes generate a user-friendly resolved and demangled stack
trace when libc provides the necessary functions (newer libc on i386,
x86_64, powerpc, ia64, alpha and s390). Otherwise print a numeric
stack trace as before, relying on resolve_stack_dump utility.
configure.in:
Add check for backtrace headers, backtrace functions and if
__cxa_demangle (libstdc++) is available at link time.
sql/mysqld.cc:
Print the value of the THD::killed variable when dumping. In
some circumstances knowing if the thread was killed makes
debugging easier.
sql/stacktrace.c:
Use the glibc backtrace function when available and demangle
C++ function names if the __cxa_demangle function is available.
sql/stacktrace.h:
Locally export and wrap in C linkage the C++ function __cxa_demangle
if available.
Diffstat (limited to 'sql/stacktrace.c')
-rw-r--r-- | sql/stacktrace.c | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/sql/stacktrace.c b/sql/stacktrace.c index b1267e20774..3d718dfd9d2 100644 --- a/sql/stacktrace.c +++ b/sql/stacktrace.c @@ -17,11 +17,16 @@ #include "stacktrace.h" #include <signal.h> #include <my_pthread.h> +#include <m_string.h> #ifdef HAVE_STACKTRACE #include <unistd.h> #include <strings.h> +#if HAVE_EXECINFO_H +#include <execinfo.h> +#endif + #define PTR_SANE(p) ((p) && (char*)(p) >= heap_start && (char*)(p) <= heap_end) char *heap_start; @@ -93,9 +98,68 @@ inline uint32* find_prev_pc(uint32* pc, uchar** fp) } #endif /* defined(__alpha__) && defined(__GNUC__) */ +#if BACKTRACE_DEMANGLE +static void my_demangle_symbols(char **addrs, int n) +{ + int status, i; + char *begin, *end, *demangled; + + for (i= 0; i < n; i++) + { + demangled= NULL; + begin= strchr(addrs[i], '('); + end= begin ? strchr(begin, '+') : NULL; + + if (begin && end) + { + *begin++= *end++= '\0'; + demangled= my_demangle(begin, &status); + if (!demangled || status) + { + demangled= NULL; + begin[-1]= '('; + end[-1]= '+'; + } + } + + if (demangled) + fprintf(stderr, "%s(%s+%s\n", addrs[i], demangled, end); + else + fprintf(stderr, "%s\n", addrs[i]); + } +} +#endif + + +#if HAVE_BACKTRACE +static void backtrace_current_thread(void) +{ + void *addrs[128]; + char **strings= NULL; + int n = backtrace(addrs, array_elements(addrs)); +#if BACKTRACE_DEMANGLE + if ((strings= backtrace_symbols(addrs, n))) + { + my_demangle_symbols(strings, n); + free(strings); + } +#endif +#if HAVE_BACKTRACE_SYMBOLS_FD + if (!strings) + { + backtrace_symbols_fd(addrs, n, fileno(stderr)); + } +#endif +} +#endif + void print_stacktrace(uchar* stack_bottom, ulong thread_stack) { +#if HAVE_BACKTRACE + backtrace_current_thread(); + return; +#endif uchar** fp; uint frame_count = 0, sigreturn_frame_count; #if defined(__alpha__) && defined(__GNUC__) |