~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/stacktrace.cc

Merge Monty.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2000 MySQL AB
2
 
 
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.
6
 
 
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.
11
 
 
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 */
15
 
 
16
 
/* Workaround for Bug#32082: VOID redefinition on Win results in compile errors*/
17
 
#define DONT_DEFINE_VOID 1
18
 
 
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:
 
3
 *
 
4
 *  Copyright (C) 2008 Sun Microsystems, Inc.
 
5
 *
 
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.
 
9
 *
 
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.
 
14
 *
 
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
 
18
 */
 
19
 
 
20
#include "config.h"
 
21
#include "drizzled/stacktrace.h"
 
22
#include <cstddef>
21
23
 
22
24
#include <signal.h>
23
 
#include <my_pthread.h>
24
 
#include <m_string.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>
30
32
#include <execinfo.h>
31
33
#endif
32
34
 
 
35
#include <cstring>
 
36
#include <cstdio>
 
37
#include <algorithm>
 
38
 
 
39
#include "drizzled/definitions.h"
 
40
 
 
41
using namespace std;
 
42
 
33
43
#define PTR_SANE(p) ((p) && (char*)(p) >= heap_start && (char*)(p) <= heap_end)
34
44
 
35
45
char *heap_start;
61
71
#define SIGRETURN_FRAME_OFFSET 23
62
72
#endif
63
73
 
64
 
#if defined(__alpha__) && defined(__GNUC__)
65
 
/*
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
70
 
*/
71
 
 
72
 
#define MAX_INSTR_IN_FUNC  10000
73
 
 
74
 
inline uchar** find_prev_fp(uint32* pc, uchar** fp)
75
 
{
76
 
  int i;
77
 
  for (i = 0; i < MAX_INSTR_IN_FUNC; ++i,--pc)
78
 
  {
79
 
    uchar* p = (uchar*)pc;
80
 
    if (p[2] == 222 &&  p[3] == 35)
81
 
    {
82
 
      return (uchar**)((uchar*)fp - *(short int*)p);
83
 
    }
84
 
  }
85
 
  return 0;
86
 
}
87
 
 
88
 
inline uint32* find_prev_pc(uint32* pc, uchar** fp)
89
 
{
90
 
  int i;
91
 
  for (i = 0; i < MAX_INSTR_IN_FUNC; ++i,--pc)
92
 
  {
93
 
    char* p = (char*)pc;
94
 
    if (p[1] == 0 && p[2] == 94 &&  p[3] == -73)
95
 
    {
96
 
      uint32* prev_pc = (uint32*)*((fp+p[0]/sizeof(fp)));
97
 
      return prev_pc;
98
 
    }
99
 
  }
100
 
  return 0;
101
 
}
102
 
#endif /* defined(__alpha__) && defined(__GNUC__) */
103
74
 
104
75
#if BACKTRACE_DEMANGLE
105
76
static void my_demangle_symbols(char **addrs, int n)
157
128
#endif
158
129
 
159
130
 
160
 
void  print_stacktrace(uchar* stack_bottom, ulong thread_stack)
 
131
void  print_stacktrace(unsigned char* stack_bottom, size_t thread_stack)
161
132
{
162
133
#if HAVE_BACKTRACE
163
134
  backtrace_current_thread();
164
135
  return;
165
136
#endif
166
 
  uchar** fp;
167
 
  uint frame_count = 0, sigreturn_frame_count;
168
 
#if defined(__alpha__) && defined(__GNUC__)
169
 
  uint32* pc;
170
 
#endif
171
 
 
 
137
  unsigned char** fp;
 
138
  uint32_t frame_count = 0, sigreturn_frame_count;
172
139
 
173
140
#ifdef __i386__
174
141
  __asm __volatile__ ("movl %%ebp,%0"
175
 
                      :"=r"(fp)
176
 
                      :"r"(fp));
 
142
                      :"=r"(fp)
 
143
                      :"r"(fp));
177
144
#endif
178
145
#ifdef __x86_64__
179
146
  __asm __volatile__ ("movq %%rbp,%0"
180
 
                      :"=r"(fp)
181
 
                      :"r"(fp));
182
 
#endif
183
 
#if defined(__alpha__) && defined(__GNUC__) 
184
 
  __asm __volatile__ ("mov $30,%0"
185
 
                      :"=r"(fp)
186
 
                      :"r"(fp));
 
147
                      :"=r"(fp)
 
148
                      :"r"(fp));
187
149
#endif
188
150
  if (!fp)
189
151
  {
192
154
    return;
193
155
  }
194
156
 
195
 
  if (!stack_bottom || (uchar*) stack_bottom > (uchar*) &fp)
 
157
  if (!stack_bottom || (unsigned char*) stack_bottom > (unsigned char*) &fp)
196
158
  {
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);
202
164
  }
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)
205
167
  {
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);
209
171
    return;
210
172
  }
211
173
 
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: "
219
 
                      :"=r"(pc)
220
 
                      :"r"(pc));
221
 
#endif  /* __alpha__ */
222
175
 
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;
225
178
 
226
 
  while (fp < (uchar**) stack_bottom)
 
179
  while (fp < (unsigned char**) stack_bottom)
227
180
  {
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__) */
233
186
 
234
 
#if defined(__alpha__) && defined(__GNUC__)
235
 
    uchar** new_fp = find_prev_fp(pc, fp);
236
 
    if (frame_count == sigreturn_frame_count - 1)
237
 
    {
238
 
      new_fp += 90;
239
 
    }
240
 
 
241
 
    if (fp && pc)
242
 
    {
243
 
      pc = find_prev_pc(pc, fp);
244
 
      if (pc)
245
 
        fprintf(stderr, "%p\n", pc);
246
 
      else
247
 
      {
248
 
        fprintf(stderr, "Not smart enough to deal with the rest\
249
 
 of this stack\n");
250
 
        goto end;
251
 
      }
252
 
    }
253
 
    else
254
 
    {
255
 
      fprintf(stderr, "Not smart enough to deal with the rest of this stack\n");
256
 
      goto end;
257
 
    }
258
 
#endif /* defined(__alpha__) && defined(__GNUC__) */
259
187
    if (new_fp <= fp )
260
188
    {
261
189
      fprintf(stderr, "New value of fp=%p failed sanity check,\