1
/* Copyright (C) 2000 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
/* Workaround for Bug#32082: VOID redefinition on Win results in compile errors*/
17
#define DONT_DEFINE_VOID 1
19
#include <my_global.h>
20
#include "stacktrace.h"
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"
22
24
#include <signal.h>
23
#include <my_pthread.h>
25
#include "drizzled/internal/my_pthread.h"
26
#include "drizzled/internal/m_string.h"
25
27
#ifdef HAVE_STACKTRACE
26
28
#include <unistd.h>
27
29
#include <strings.h>
61
71
#define SIGRETURN_FRAME_OFFSET 23
64
#if defined(__alpha__) && defined(__GNUC__)
66
The only way to backtrace without a symbol table on alpha
67
is to find stq fp,N(sp), and the first byte
68
of the instruction opcode will give us the value of N. From this
69
we can find where the old value of fp is stored
72
#define MAX_INSTR_IN_FUNC 10000
74
inline uchar** find_prev_fp(uint32* pc, uchar** fp)
77
for (i = 0; i < MAX_INSTR_IN_FUNC; ++i,--pc)
79
uchar* p = (uchar*)pc;
80
if (p[2] == 222 && p[3] == 35)
82
return (uchar**)((uchar*)fp - *(short int*)p);
88
inline uint32* find_prev_pc(uint32* pc, uchar** fp)
91
for (i = 0; i < MAX_INSTR_IN_FUNC; ++i,--pc)
94
if (p[1] == 0 && p[2] == 94 && p[3] == -73)
96
uint32* prev_pc = (uint32*)*((fp+p[0]/sizeof(fp)));
102
#endif /* defined(__alpha__) && defined(__GNUC__) */
104
75
#if BACKTRACE_DEMANGLE
105
76
static void my_demangle_symbols(char **addrs, int n)
160
void print_stacktrace(uchar* stack_bottom, ulong thread_stack)
131
void print_stacktrace(unsigned char* stack_bottom, size_t thread_stack)
162
133
#if HAVE_BACKTRACE
163
134
backtrace_current_thread();
167
uint frame_count = 0, sigreturn_frame_count;
168
#if defined(__alpha__) && defined(__GNUC__)
138
uint32_t frame_count = 0, sigreturn_frame_count;
174
141
__asm __volatile__ ("movl %%ebp,%0"
178
145
#ifdef __x86_64__
179
146
__asm __volatile__ ("movq %%rbp,%0"
183
#if defined(__alpha__) && defined(__GNUC__)
184
__asm __volatile__ ("mov $30,%0"
195
if (!stack_bottom || (uchar*) stack_bottom > (uchar*) &fp)
157
if (!stack_bottom || (unsigned char*) stack_bottom > (unsigned char*) &fp)
197
ulong tmp= min(0x10000,thread_stack);
159
ulong tmp= min((size_t)0x10000,thread_stack);
198
160
/* Assume that the stack starts at the previous even 65K */
199
stack_bottom= (uchar*) (((ulong) &fp + tmp) &
161
stack_bottom= (unsigned char*) (((ulong) &fp + tmp) &
200
162
~(ulong) 0xFFFF);
201
163
fprintf(stderr, "Cannot determine thread, fp=%p, backtrace may not be correct.\n", (void *)fp);
203
if (fp > (uchar**) stack_bottom ||
204
fp < (uchar**) stack_bottom - thread_stack)
165
if (fp > (unsigned char**) stack_bottom ||
166
fp < (unsigned char**) stack_bottom - thread_stack)
206
168
fprintf(stderr, "Bogus stack limit or frame pointer,\
207
fp=%p, stack_bottom=%p, thread_stack=%ld, aborting backtrace.\n",
208
(void *)fp, (void *)stack_bottom, thread_stack);
169
fp=%p, stack_bottom=%p, thread_stack=%"PRIu64", aborting backtrace.\n",
170
(void *)fp, (void *)stack_bottom, (uint64_t)thread_stack);
212
174
fprintf(stderr, "Stack range sanity check OK, backtrace follows:\n");
213
#if defined(__alpha__) && defined(__GNUC__)
214
fprintf(stderr, "Warning: Alpha stacks are difficult -\
215
will be taking some wild guesses, stack trace may be incorrect or \
216
terminate abruptly\n");
217
/* On Alpha, we need to get pc */
218
__asm __volatile__ ("bsr %0, do_next; do_next: "
221
#endif /* __alpha__ */
223
176
/* We are 1 frame above signal frame with NPTL and 2 frames above with LT */
224
177
sigreturn_frame_count = thd_lib_detected == THD_LIB_LT ? 2 : 1;
226
while (fp < (uchar**) stack_bottom)
179
while (fp < (unsigned char**) stack_bottom)
228
181
#if defined(__i386__) || defined(__x86_64__)
229
uchar** new_fp = (uchar**)*fp;
182
unsigned char** new_fp = (unsigned char**)*fp;
230
183
fprintf(stderr, "%p\n", frame_count == sigreturn_frame_count ?
231
*(fp + SIGRETURN_FRAME_OFFSET) : *(fp + 1));
184
*(fp + SIGRETURN_FRAME_OFFSET) : *(fp + 1));
232
185
#endif /* defined(__386__) || defined(__x86_64__) */
234
#if defined(__alpha__) && defined(__GNUC__)
235
uchar** new_fp = find_prev_fp(pc, fp);
236
if (frame_count == sigreturn_frame_count - 1)
243
pc = find_prev_pc(pc, fp);
245
fprintf(stderr, "%p\n", pc);
248
fprintf(stderr, "Not smart enough to deal with the rest\
255
fprintf(stderr, "Not smart enough to deal with the rest of this stack\n");
258
#endif /* defined(__alpha__) && defined(__GNUC__) */
259
187
if (new_fp <= fp )
261
189
fprintf(stderr, "New value of fp=%p failed sanity check,\