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
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
20
#include "drizzled/global.h"
19
21
#include "stacktrace.h"
21
23
#include <signal.h>
60
66
#define SIGRETURN_FRAME_OFFSET 23
63
#if defined(__alpha__) && defined(__GNUC__)
65
The only way to backtrace without a symbol table on alpha
66
is to find stq fp,N(sp), and the first byte
67
of the instruction opcode will give us the value of N. From this
68
we can find where the old value of fp is stored
71
#define MAX_INSTR_IN_FUNC 10000
73
inline uchar** find_prev_fp(uint32* pc, uchar** fp)
76
for (i = 0; i < MAX_INSTR_IN_FUNC; ++i,--pc)
78
uchar* p = (uchar*)pc;
79
if (p[2] == 222 && p[3] == 35)
81
return (uchar**)((uchar*)fp - *(short int*)p);
87
inline uint32* find_prev_pc(uint32* pc, uchar** fp)
90
for (i = 0; i < MAX_INSTR_IN_FUNC; ++i,--pc)
93
if (p[1] == 0 && p[2] == 94 && p[3] == -73)
95
uint32* prev_pc = (uint32*)*((fp+p[0]/sizeof(fp)));
101
#endif /* defined(__alpha__) && defined(__GNUC__) */
103
70
#if BACKTRACE_DEMANGLE
104
71
static void my_demangle_symbols(char **addrs, int n)
159
void print_stacktrace(uchar* stack_bottom, ulong thread_stack)
126
void print_stacktrace(unsigned char* stack_bottom, size_t thread_stack)
161
128
#if HAVE_BACKTRACE
162
129
backtrace_current_thread();
166
uint frame_count = 0, sigreturn_frame_count;
167
#if defined(__alpha__) && defined(__GNUC__)
133
uint32_t frame_count = 0, sigreturn_frame_count;
173
136
__asm __volatile__ ("movl %%ebp,%0"
177
140
#ifdef __x86_64__
178
141
__asm __volatile__ ("movq %%rbp,%0"
182
#if defined(__alpha__) && defined(__GNUC__)
183
__asm __volatile__ ("mov $30,%0"
194
if (!stack_bottom || (uchar*) stack_bottom > (uchar*) &fp)
152
if (!stack_bottom || (unsigned char*) stack_bottom > (unsigned char*) &fp)
196
ulong tmp= min(0x10000,thread_stack);
154
ulong tmp= min((size_t)0x10000,thread_stack);
197
155
/* Assume that the stack starts at the previous even 65K */
198
stack_bottom= (uchar*) (((ulong) &fp + tmp) &
156
stack_bottom= (unsigned char*) (((ulong) &fp + tmp) &
199
157
~(ulong) 0xFFFF);
200
158
fprintf(stderr, "Cannot determine thread, fp=%p, backtrace may not be correct.\n", (void *)fp);
202
if (fp > (uchar**) stack_bottom ||
203
fp < (uchar**) stack_bottom - thread_stack)
160
if (fp > (unsigned char**) stack_bottom ||
161
fp < (unsigned char**) stack_bottom - thread_stack)
205
163
fprintf(stderr, "Bogus stack limit or frame pointer,\
206
fp=%p, stack_bottom=%p, thread_stack=%ld, aborting backtrace.\n",
207
(void *)fp, (void *)stack_bottom, thread_stack);
164
fp=%p, stack_bottom=%p, thread_stack=%"PRIu64", aborting backtrace.\n",
165
(void *)fp, (void *)stack_bottom, (uint64_t)thread_stack);
211
169
fprintf(stderr, "Stack range sanity check OK, backtrace follows:\n");
212
#if defined(__alpha__) && defined(__GNUC__)
213
fprintf(stderr, "Warning: Alpha stacks are difficult -\
214
will be taking some wild guesses, stack trace may be incorrect or \
215
terminate abruptly\n");
216
/* On Alpha, we need to get pc */
217
__asm __volatile__ ("bsr %0, do_next; do_next: "
220
#endif /* __alpha__ */
222
171
/* We are 1 frame above signal frame with NPTL and 2 frames above with LT */
223
172
sigreturn_frame_count = thd_lib_detected == THD_LIB_LT ? 2 : 1;
225
while (fp < (uchar**) stack_bottom)
174
while (fp < (unsigned char**) stack_bottom)
227
176
#if defined(__i386__) || defined(__x86_64__)
228
uchar** new_fp = (uchar**)*fp;
177
unsigned char** new_fp = (unsigned char**)*fp;
229
178
fprintf(stderr, "%p\n", frame_count == sigreturn_frame_count ?
230
*(fp + SIGRETURN_FRAME_OFFSET) : *(fp + 1));
179
*(fp + SIGRETURN_FRAME_OFFSET) : *(fp + 1));
231
180
#endif /* defined(__386__) || defined(__x86_64__) */
233
#if defined(__alpha__) && defined(__GNUC__)
234
uchar** new_fp = find_prev_fp(pc, fp);
235
if (frame_count == sigreturn_frame_count - 1)
242
pc = find_prev_pc(pc, fp);
244
fprintf(stderr, "%p\n", pc);
247
fprintf(stderr, "Not smart enough to deal with the rest\
254
fprintf(stderr, "Not smart enough to deal with the rest of this stack\n");
257
#endif /* defined(__alpha__) && defined(__GNUC__) */
258
182
if (new_fp <= fp )
260
184
fprintf(stderr, "New value of fp=%p failed sanity check,\