summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <kaa@polly.local>2006-08-25 17:59:47 +0400
committerunknown <kaa@polly.local>2006-08-25 17:59:47 +0400
commited6b3e6b041102261deea538dec16e2c37869971 (patch)
tree4c51781ae2d6ddf69ab4e2bbcce995a2da5c2e0b
parent029af2b126a629cc7fe231df5eb336e806e841e1 (diff)
downloadmariadb-git-ed6b3e6b041102261deea538dec16e2c37869971.tar.gz
Added stacktrace dumps for x86_64 (bug #21250)
Fixed stacktrace dumps for i386/NPTL
-rw-r--r--sql/stacktrace.c51
-rw-r--r--sql/stacktrace.h8
2 files changed, 42 insertions, 17 deletions
diff --git a/sql/stacktrace.c b/sql/stacktrace.c
index 838f547dc02..d82c7c2a384 100644
--- a/sql/stacktrace.c
+++ b/sql/stacktrace.c
@@ -21,6 +21,7 @@
#ifdef HAVE_STACKTRACE
#include <unistd.h>
+#include <strings.h>
#define PTR_SANE(p) ((p) && (char*)(p) >= heap_start && (char*)(p) <= heap_end)
@@ -44,7 +45,25 @@ void safe_print_str(const char* name, const char* val, int max_len)
}
#ifdef TARGET_OS_LINUX
-#define SIGRETURN_FRAME_COUNT 2
+
+#ifdef __i386__
+#define SIGRETURN_FRAME_OFFSET 17
+#endif
+
+#ifdef __x86_64__
+#define SIGRETURN_FRAME_OFFSET 23
+#endif
+
+static my_bool is_nptl;
+
+/* Check if we are using NPTL or LinuxThreads on Linux */
+void check_thread_lib(void)
+{
+ char buf[5];
+
+ confstr(_CS_GNU_LIBPTHREAD_VERSION, buf, sizeof(buf));
+ is_nptl = !strncasecmp(buf, "NPTL", sizeof(buf));
+}
#if defined(__alpha__) && defined(__GNUC__)
/*
@@ -90,7 +109,7 @@ inline uint32* find_prev_pc(uint32* pc, uchar** fp)
void print_stacktrace(gptr stack_bottom, ulong thread_stack)
{
uchar** fp;
- uint frame_count = 0;
+ uint frame_count = 0, sigreturn_frame_count;
#if defined(__alpha__) && defined(__GNUC__)
uint32* pc;
#endif
@@ -100,28 +119,27 @@ void print_stacktrace(gptr stack_bottom, ulong thread_stack)
Attempting backtrace. You can use the following information to find out\n\
where mysqld died. If you see no messages after this, something went\n\
terribly wrong...\n");
-#ifdef __i386__
+#ifdef __i386__
__asm __volatile__ ("movl %%ebp,%0"
:"=r"(fp)
:"r"(fp));
- if (!fp)
- {
- fprintf(stderr, "frame pointer (ebp) is NULL, did you compile with\n\
--fomit-frame-pointer? Aborting backtrace!\n");
- return;
- }
+#endif
+#ifdef __x86_64__
+ __asm __volatile__ ("movq %%rbp,%0"
+ :"=r"(fp)
+ :"r"(fp));
#endif
#if defined(__alpha__) && defined(__GNUC__)
__asm __volatile__ ("mov $30,%0"
:"=r"(fp)
:"r"(fp));
+#endif
if (!fp)
{
- fprintf(stderr, "frame pointer (fp) is NULL, did you compile with\n\
+ fprintf(stderr, "frame pointer is NULL, did you compile with\n\
-fomit-frame-pointer? Aborting backtrace!\n");
return;
}
-#endif /* __alpha__ */
if (!stack_bottom || (gptr) stack_bottom > (gptr) &fp)
{
@@ -151,13 +169,16 @@ terribly wrong...\n");
:"r"(pc));
#endif /* __alpha__ */
+ /* We are 1 frame above signal frame with NPTL and 2 frames above with LT */
+ sigreturn_frame_count = is_nptl ? 1 : 2;
+
while (fp < (uchar**) stack_bottom)
{
-#ifdef __i386__
+#if defined(__i386__) || defined(__x86_64__)
uchar** new_fp = (uchar**)*fp;
- fprintf(stderr, "%p\n", frame_count == SIGRETURN_FRAME_COUNT ?
- *(fp+17) : *(fp+1));
-#endif /* __386__ */
+ fprintf(stderr, "%p\n", frame_count == sigreturn_frame_count ?
+ *(fp + SIGRETURN_FRAME_OFFSET) : *(fp + 1));
+#endif /* defined(__386__) || defined(__x86_64__) */
#if defined(__alpha__) && defined(__GNUC__)
uchar** new_fp = find_prev_fp(pc, fp);
diff --git a/sql/stacktrace.h b/sql/stacktrace.h
index d5d1e05ef0e..527d10d70a2 100644
--- a/sql/stacktrace.h
+++ b/sql/stacktrace.h
@@ -19,16 +19,20 @@ extern "C" {
#endif
#ifdef TARGET_OS_LINUX
-#if defined(HAVE_STACKTRACE) || (defined (__i386__) || (defined(__alpha__) && defined(__GNUC__)))
+#if defined(HAVE_STACKTRACE) || (defined (__x86_64__) || defined (__i386__) || (defined(__alpha__) && defined(__GNUC__)))
#undef HAVE_STACKTRACE
#define HAVE_STACKTRACE
extern char* __bss_start;
extern char* heap_start;
-#define init_stacktrace() { heap_start = (char*) &__bss_start; }
+#define init_stacktrace() do { \
+ heap_start = (char*) &__bss_start; \
+ check_thread_lib(); \
+ } while(0);
void print_stacktrace(gptr stack_bottom, ulong thread_stack);
void safe_print_str(const char* name, const char* val, int max_len);
+void check_thread_lib(void);
#endif /* (defined (__i386__) || (defined(__alpha__) && defined(__GNUC__))) */
#endif /* TARGET_OS_LINUX */