Bug #21250: esolve stack traces on AMD64 (backport to mysql-4.1)
This commit is contained in:
parent
635281619b
commit
f4265f7a57
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#ifdef HAVE_STACKTRACE
|
#ifdef HAVE_STACKTRACE
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <strings.h>
|
||||||
|
|
||||||
#define PTR_SANE(p) ((p) && (char*)(p) >= heap_start && (char*)(p) <= heap_end)
|
#define PTR_SANE(p) ((p) && (char*)(p) >= heap_start && (char*)(p) <= heap_end)
|
||||||
|
|
||||||
@ -44,7 +45,29 @@ void safe_print_str(const char* name, const char* val, int max_len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TARGET_OS_LINUX
|
#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];
|
||||||
|
|
||||||
|
#ifdef _CS_GNU_LIBPTHREAD_VERSION
|
||||||
|
confstr(_CS_GNU_LIBPTHREAD_VERSION, buf, sizeof(buf));
|
||||||
|
is_nptl = !strncasecmp(buf, "NPTL", sizeof(buf));
|
||||||
|
#else
|
||||||
|
is_nptl = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(__alpha__) && defined(__GNUC__)
|
#if defined(__alpha__) && defined(__GNUC__)
|
||||||
/*
|
/*
|
||||||
@ -90,7 +113,7 @@ inline uint32* find_prev_pc(uint32* pc, uchar** fp)
|
|||||||
void print_stacktrace(gptr stack_bottom, ulong thread_stack)
|
void print_stacktrace(gptr stack_bottom, ulong thread_stack)
|
||||||
{
|
{
|
||||||
uchar** fp;
|
uchar** fp;
|
||||||
uint frame_count = 0;
|
uint frame_count = 0, sigreturn_frame_count;
|
||||||
#if defined(__alpha__) && defined(__GNUC__)
|
#if defined(__alpha__) && defined(__GNUC__)
|
||||||
uint32* pc;
|
uint32* pc;
|
||||||
#endif
|
#endif
|
||||||
@ -100,28 +123,27 @@ void print_stacktrace(gptr stack_bottom, ulong thread_stack)
|
|||||||
Attempting backtrace. You can use the following information to find out\n\
|
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\
|
where mysqld died. If you see no messages after this, something went\n\
|
||||||
terribly wrong...\n");
|
terribly wrong...\n");
|
||||||
#ifdef __i386__
|
#ifdef __i386__
|
||||||
__asm __volatile__ ("movl %%ebp,%0"
|
__asm __volatile__ ("movl %%ebp,%0"
|
||||||
:"=r"(fp)
|
:"=r"(fp)
|
||||||
:"r"(fp));
|
:"r"(fp));
|
||||||
if (!fp)
|
#endif
|
||||||
{
|
#ifdef __x86_64__
|
||||||
fprintf(stderr, "frame pointer (ebp) is NULL, did you compile with\n\
|
__asm __volatile__ ("movq %%rbp,%0"
|
||||||
-fomit-frame-pointer? Aborting backtrace!\n");
|
:"=r"(fp)
|
||||||
return;
|
:"r"(fp));
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
#if defined(__alpha__) && defined(__GNUC__)
|
#if defined(__alpha__) && defined(__GNUC__)
|
||||||
__asm __volatile__ ("mov $30,%0"
|
__asm __volatile__ ("mov $30,%0"
|
||||||
:"=r"(fp)
|
:"=r"(fp)
|
||||||
:"r"(fp));
|
:"r"(fp));
|
||||||
|
#endif
|
||||||
if (!fp)
|
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");
|
-fomit-frame-pointer? Aborting backtrace!\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif /* __alpha__ */
|
|
||||||
|
|
||||||
if (!stack_bottom || (gptr) stack_bottom > (gptr) &fp)
|
if (!stack_bottom || (gptr) stack_bottom > (gptr) &fp)
|
||||||
{
|
{
|
||||||
@ -151,13 +173,16 @@ terribly wrong...\n");
|
|||||||
:"r"(pc));
|
:"r"(pc));
|
||||||
#endif /* __alpha__ */
|
#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)
|
while (fp < (uchar**) stack_bottom)
|
||||||
{
|
{
|
||||||
#ifdef __i386__
|
#if defined(__i386__) || defined(__x86_64__)
|
||||||
uchar** new_fp = (uchar**)*fp;
|
uchar** new_fp = (uchar**)*fp;
|
||||||
fprintf(stderr, "%p\n", frame_count == SIGRETURN_FRAME_COUNT ?
|
fprintf(stderr, "%p\n", frame_count == sigreturn_frame_count ?
|
||||||
*(fp+17) : *(fp+1));
|
*(fp + SIGRETURN_FRAME_OFFSET) : *(fp + 1));
|
||||||
#endif /* __386__ */
|
#endif /* defined(__386__) || defined(__x86_64__) */
|
||||||
|
|
||||||
#if defined(__alpha__) && defined(__GNUC__)
|
#if defined(__alpha__) && defined(__GNUC__)
|
||||||
uchar** new_fp = find_prev_fp(pc, fp);
|
uchar** new_fp = find_prev_fp(pc, fp);
|
||||||
|
@ -19,16 +19,20 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef TARGET_OS_LINUX
|
#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
|
#undef HAVE_STACKTRACE
|
||||||
#define HAVE_STACKTRACE
|
#define HAVE_STACKTRACE
|
||||||
|
|
||||||
extern char* __bss_start;
|
extern char* __bss_start;
|
||||||
extern char* heap_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 print_stacktrace(gptr stack_bottom, ulong thread_stack);
|
||||||
void safe_print_str(const char* name, const char* val, int max_len);
|
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 /* (defined (__i386__) || (defined(__alpha__) && defined(__GNUC__))) */
|
||||||
#endif /* TARGET_OS_LINUX */
|
#endif /* TARGET_OS_LINUX */
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user