1
/* - mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008 Sun Microsystems, Inc.
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; version 2 of the License.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
#include "drizzled/stacktrace.h"
25
#include "drizzled/internal/my_pthread.h"
26
#include "drizzled/internal/m_string.h"
27
#ifdef HAVE_STACKTRACE
39
#if defined(BACKTRACE_DEMANGLE)
43
#include "drizzled/definitions.h"
50
#define PTR_SANE(p) ((p) && (char*)(p) >= heap_start && (char*)(p) <= heap_end)
54
void safe_print_str(const char* name, const char* val, int max_len)
56
char *heap_end= (char*) sbrk(0);
57
fprintf(stderr, "%s at %p ", name, val);
61
fprintf(stderr, " is invalid pointer\n");
65
fprintf(stderr, "= ");
66
for (; max_len && PTR_SANE(val) && *val; --max_len)
67
fputc(*val++, stderr);
71
#ifdef TARGET_OS_LINUX
74
#define SIGRETURN_FRAME_OFFSET 17
78
#define SIGRETURN_FRAME_OFFSET 23
81
#if defined(BACKTRACE_DEMANGLE)
83
static inline char *my_demangle(const char *mangled_name, int *status)
85
return abi::__cxa_demangle(mangled_name, NULL, NULL, status);
88
static void my_demangle_symbols(char **addrs, int n)
91
char *begin, *end, *demangled;
93
for (i= 0; i < n; i++)
96
begin= strchr(addrs[i], '(');
97
end= begin ? strchr(begin, '+') : NULL;
101
*begin++= *end++= '\0';
102
demangled= my_demangle(begin, &status);
103
if (!demangled || status)
112
fprintf(stderr, "%s(%s+%s\n", addrs[i], demangled, end);
114
fprintf(stderr, "%s\n", addrs[i]);
121
static void backtrace_current_thread(void)
124
char **strings= NULL;
125
int n = backtrace(addrs, array_elements(addrs));
126
#if BACKTRACE_DEMANGLE
127
if ((strings= backtrace_symbols(addrs, n)))
129
my_demangle_symbols(strings, n);
133
#if HAVE_BACKTRACE_SYMBOLS_FD
136
backtrace_symbols_fd(addrs, n, fileno(stderr));
143
void print_stacktrace(unsigned char* stack_bottom, size_t thread_stack)
146
backtrace_current_thread();
150
uint32_t frame_count = 0, sigreturn_frame_count;
153
__asm __volatile__ ("movl %%ebp,%0"
158
__asm __volatile__ ("movq %%rbp,%0"
164
fprintf(stderr, "frame pointer is NULL, did you compile with\n"
165
"-fomit-frame-pointer? Aborting backtrace!\n");
169
if (!stack_bottom || (unsigned char*) stack_bottom > (unsigned char*) &fp)
171
ulong tmp= min((size_t)0x10000,thread_stack);
172
/* Assume that the stack starts at the previous even 65K */
173
stack_bottom= (unsigned char*) (((ulong) &fp + tmp) &
175
fprintf(stderr, "Cannot determine thread, fp=%p, backtrace may not be correct.\n", (void *)fp);
177
if (fp > (unsigned char**) stack_bottom ||
178
fp < (unsigned char**) stack_bottom - thread_stack)
180
fprintf(stderr, "Bogus stack limit or frame pointer, "
181
"fp=%p, stack_bottom=%p, thread_stack=%"PRIu64", "
182
"aborting backtrace.\n",
183
(void *)fp, (void *)stack_bottom, (uint64_t)thread_stack);
187
fprintf(stderr, "Stack range sanity check OK, backtrace follows:\n");
189
/* We are 1 frame above signal frame with NPTL and 2 frames above with LT */
190
sigreturn_frame_count = internal::thd_lib_detected == THD_LIB_LT ? 2 : 1;
192
while (fp < (unsigned char**) stack_bottom)
194
#if defined(__i386__) || defined(__x86_64__)
195
unsigned char** new_fp = (unsigned char**)*fp;
196
fprintf(stderr, "%p\n", frame_count == sigreturn_frame_count ?
197
*(fp + SIGRETURN_FRAME_OFFSET) : *(fp + 1));
198
#endif /* defined(__386__) || defined(__x86_64__) */
202
fprintf(stderr, "New value of fp=%p failed sanity check, "
203
"terminating stack trace!\n", (void *)new_fp);
210
fprintf(stderr, "Stack trace seems successful - bottom reached\n");
214
"Please read http://dev.mysql.com/doc/refman/5.1/en/resolve-stack-dump.html\n"
215
"and follow instructions on how to resolve the stack trace.\n"
216
"Resolved stack trace is much more helpful in diagnosing the\n"
217
"problem, so please do resolve it\n");
219
#endif /* TARGET_OS_LINUX */
221
} /* namespace drizzled */
223
#endif /* HAVE_STACKTRACE */
225
/* Produce a core for the thread */
230
void write_core(int sig)
232
signal(sig, SIG_DFL);
235
For GCOV build, crashing will prevent the writing of code coverage
236
information from this process, causing gcov output to be incomplete.
237
So we force the writing of coverage information here before terminating.
239
extern void __gcov_flush(void);
242
pthread_kill(pthread_self(), sig);
243
#if defined(P_MYID) && !defined(SCO)
244
/* On Solaris, the above kill is not enough */
245
sigsend(P_PID,P_MYID,sig);
249
} /* namespace drizzled */