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