~drizzle-trunk/drizzle/development

467 by Monty Taylor
Made sql_state and stacktrace compile as C++. drizzled/ is pure c++ now.
1
/* - mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
398.1.6 by Monty Taylor
Removed __alpha__ references.
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
 */
1 by brian
clean slate
19
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
20
#include "config.h"
21
#include "drizzled/stacktrace.h"
22
#include <cstddef>
1 by brian
clean slate
23
24
#include <signal.h>
1241.9.64 by Monty Taylor
Moved remaining non-public portions of mysys and mystrings to drizzled/internal.
25
#include "drizzled/internal/my_pthread.h"
26
#include "drizzled/internal/m_string.h"
1 by brian
clean slate
27
#ifdef HAVE_STACKTRACE
28
#include <unistd.h>
29
#include <strings.h>
30
31
#if HAVE_EXECINFO_H
32
#include <execinfo.h>
33
#endif
34
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
35
#include <cstring>
36
#include <cstdio>
1067.4.11 by Nathan Williams
Converted last usage of cmin to std::min.
37
#include <algorithm>
38
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
39
#include "drizzled/definitions.h"
40
1067.4.11 by Nathan Williams
Converted last usage of cmin to std::min.
41
using namespace std;
42
1 by brian
clean slate
43
#define PTR_SANE(p) ((p) && (char*)(p) >= heap_start && (char*)(p) <= heap_end)
44
45
char *heap_start;
46
47
void safe_print_str(const char* name, const char* val, int max_len)
48
{
49
  char *heap_end= (char*) sbrk(0);
50
  fprintf(stderr, "%s at %p ", name, val);
51
52
  if (!PTR_SANE(val))
53
  {
54
    fprintf(stderr, " is invalid pointer\n");
55
    return;
56
  }
57
58
  fprintf(stderr, "= ");
59
  for (; max_len && PTR_SANE(val) && *val; --max_len)
60
    fputc(*val++, stderr);
61
  fputc('\n', stderr);
62
}
63
64
#ifdef TARGET_OS_LINUX
65
66
#ifdef __i386__
67
#define SIGRETURN_FRAME_OFFSET 17
68
#endif
69
70
#ifdef __x86_64__
71
#define SIGRETURN_FRAME_OFFSET 23
72
#endif
73
74
75
#if BACKTRACE_DEMANGLE
76
static void my_demangle_symbols(char **addrs, int n)
77
{
78
  int status, i;
79
  char *begin, *end, *demangled;
80
81
  for (i= 0; i < n; i++)
82
  {
83
    demangled= NULL;
84
    begin= strchr(addrs[i], '(');
85
    end= begin ? strchr(begin, '+') : NULL;
86
87
    if (begin && end)
88
    {
89
      *begin++= *end++= '\0';
90
      demangled= my_demangle(begin, &status);
91
      if (!demangled || status)
92
      {
93
        demangled= NULL;
94
        begin[-1]= '(';
95
        end[-1]= '+';
96
      }
97
    }
98
99
    if (demangled)
100
      fprintf(stderr, "%s(%s+%s\n", addrs[i], demangled, end);
101
    else
102
      fprintf(stderr, "%s\n", addrs[i]);
103
  }
104
}
105
#endif
106
107
108
#if HAVE_BACKTRACE
109
static void backtrace_current_thread(void)
110
{
111
  void *addrs[128];
112
  char **strings= NULL;
113
  int n = backtrace(addrs, array_elements(addrs));
114
#if BACKTRACE_DEMANGLE
115
  if ((strings= backtrace_symbols(addrs, n)))
116
  {
117
    my_demangle_symbols(strings, n);
118
    free(strings);
119
  }
120
#endif
121
#if HAVE_BACKTRACE_SYMBOLS_FD
122
  if (!strings)
123
  {
124
    backtrace_symbols_fd(addrs, n, fileno(stderr));
125
  }
126
#endif
127
}
128
#endif
129
130
629.2.7 by Monty Taylor
Fixed a couple of memory buffer size issues.
131
void  print_stacktrace(unsigned char* stack_bottom, size_t thread_stack)
1 by brian
clean slate
132
{
133
#if HAVE_BACKTRACE
134
  backtrace_current_thread();
135
  return;
136
#endif
481 by Brian Aker
Remove all of uchar.
137
  unsigned char** fp;
482 by Brian Aker
Remove uint.
138
  uint32_t frame_count = 0, sigreturn_frame_count;
1 by brian
clean slate
139
140
#ifdef __i386__
141
  __asm __volatile__ ("movl %%ebp,%0"
398.1.6 by Monty Taylor
Removed __alpha__ references.
142
                      :"=r"(fp)
143
                      :"r"(fp));
1 by brian
clean slate
144
#endif
145
#ifdef __x86_64__
146
  __asm __volatile__ ("movq %%rbp,%0"
398.1.6 by Monty Taylor
Removed __alpha__ references.
147
                      :"=r"(fp)
148
                      :"r"(fp));
1 by brian
clean slate
149
#endif
150
  if (!fp)
151
  {
152
    fprintf(stderr, "frame pointer is NULL, did you compile with\n\
153
-fomit-frame-pointer? Aborting backtrace!\n");
154
    return;
155
  }
156
481 by Brian Aker
Remove all of uchar.
157
  if (!stack_bottom || (unsigned char*) stack_bottom > (unsigned char*) &fp)
1 by brian
clean slate
158
  {
1067.4.11 by Nathan Williams
Converted last usage of cmin to std::min.
159
    ulong tmp= min((size_t)0x10000,thread_stack);
1 by brian
clean slate
160
    /* Assume that the stack starts at the previous even 65K */
481 by Brian Aker
Remove all of uchar.
161
    stack_bottom= (unsigned char*) (((ulong) &fp + tmp) &
1 by brian
clean slate
162
			  ~(ulong) 0xFFFF);
77.1.54 by Monty Taylor
More warnings cleanups.
163
    fprintf(stderr, "Cannot determine thread, fp=%p, backtrace may not be correct.\n", (void *)fp);
1 by brian
clean slate
164
  }
481 by Brian Aker
Remove all of uchar.
165
  if (fp > (unsigned char**) stack_bottom ||
166
      fp < (unsigned char**) stack_bottom - thread_stack)
1 by brian
clean slate
167
  {
168
    fprintf(stderr, "Bogus stack limit or frame pointer,\
632.1.9 by Monty
Cast size_t up to uint64_t to print. Man I really want to fix all of this...
169
 fp=%p, stack_bottom=%p, thread_stack=%"PRIu64", aborting backtrace.\n",
170
	    (void *)fp, (void *)stack_bottom, (uint64_t)thread_stack);
1 by brian
clean slate
171
    return;
172
  }
173
174
  fprintf(stderr, "Stack range sanity check OK, backtrace follows:\n");
175
176
  /* We are 1 frame above signal frame with NPTL and 2 frames above with LT */
177
  sigreturn_frame_count = thd_lib_detected == THD_LIB_LT ? 2 : 1;
178
481 by Brian Aker
Remove all of uchar.
179
  while (fp < (unsigned char**) stack_bottom)
1 by brian
clean slate
180
  {
181
#if defined(__i386__) || defined(__x86_64__)
481 by Brian Aker
Remove all of uchar.
182
    unsigned char** new_fp = (unsigned char**)*fp;
1 by brian
clean slate
183
    fprintf(stderr, "%p\n", frame_count == sigreturn_frame_count ?
398.1.6 by Monty Taylor
Removed __alpha__ references.
184
            *(fp + SIGRETURN_FRAME_OFFSET) : *(fp + 1));
1 by brian
clean slate
185
#endif /* defined(__386__)  || defined(__x86_64__) */
186
187
    if (new_fp <= fp )
188
    {
189
      fprintf(stderr, "New value of fp=%p failed sanity check,\
77.1.54 by Monty Taylor
More warnings cleanups.
190
 terminating stack trace!\n", (void *)new_fp);
1 by brian
clean slate
191
      goto end;
192
    }
193
    fp = new_fp;
194
    ++frame_count;
195
  }
196
197
  fprintf(stderr, "Stack trace seems successful - bottom reached\n");
198
199
end:
200
  fprintf(stderr,
201
          "Please read http://dev.mysql.com/doc/refman/5.1/en/resolve-stack-dump.html\n"
202
          "and follow instructions on how to resolve the stack trace.\n"
203
          "Resolved stack trace is much more helpful in diagnosing the\n"
204
          "problem, so please do resolve it\n");
205
}
206
#endif /* TARGET_OS_LINUX */
207
#endif /* HAVE_STACKTRACE */
208
209
/* Produce a core for the thread */
210
211
void write_core(int sig)
212
{
213
  signal(sig, SIG_DFL);
214
#ifdef HAVE_gcov
215
  /*
216
    For GCOV build, crashing will prevent the writing of code coverage
217
    information from this process, causing gcov output to be incomplete.
218
    So we force the writing of coverage information here before terminating.
219
  */
220
  extern void __gcov_flush(void);
221
  __gcov_flush();
222
#endif
223
  pthread_kill(pthread_self(), sig);
224
#if defined(P_MYID) && !defined(SCO)
225
  /* On Solaris, the above kill is not enough */
226
  sigsend(P_PID,P_MYID,sig);
227
#endif
228
}