1
/*****************************************************************************
3
Copyright (C) 2013 SkySQL Ab. All Rights Reserved.
6
This program is free software; you can redistribute it and/or modify it under
7
the terms of the GNU General Public License as published by the Free Software
8
Foundation; version 2 of the License.
10
This program is distributed in the hope that it will be useful, but WITHOUT
11
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14
You should have received a copy of the GNU General Public License along with
15
this program; if not, write to the Free Software Foundation, Inc.,
16
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
*****************************************************************************/
20
#include "os0thread.h"
22
#if defined (__linux__) && HAVE_BACKTRACE && HAVE_BACKTRACE_SYMBOLS
44
/* Since kernel version 2.2 the undocumented parameter to the signal handler has been declared
45
obsolete in adherence with POSIX.1b. A more correct way to retrieve additional information is
46
to use the SA_SIGINFO option when setting the handler */
49
#ifndef USE_SIGCONTEXT
50
/* get REG_EIP / REG_RIP from ucontext.h */
57
#if (defined (__x86_64__))
59
#define REG_RIP REG_INDEX(rip) /* seems to be 16 */
65
#define OS_STACKTRACE_MAX_DEPTH 128
67
/***************************************************************//**
68
Prints stacktrace for this thread.
77
void* array[OS_STACKTRACE_MAX_DEPTH];
80
void* caller_address = NULL;
82
/* Get the address at the time the signal was raised */
83
#if defined(__x86_64__)
84
ucontext_t* uc = (ucontext_t*) ucontext;
85
caller_address = (void*) uc->uc_mcontext.gregs[REG_RIP] ;
86
#elif defined(__hppa__)
87
ucontext_t* uc = (ucontext_t*) ucontext;
88
caller_address = (void*) uc->uc_mcontext.sc_iaoq[0] & ~0x3UL ;
89
#elif (defined (__ppc__)) || (defined (__powerpc__))
90
ucontext_t* uc = (ucontext_t*) ucontext;
91
caller_address = (void*) uc->uc_mcontext.regs->nip ;
92
#elif defined(__sparc__)
93
struct sigcontext* sc = (struct sigcontext*) ucontext;
95
caller_address = (void*) sc->sigc_regs.tpc ;
97
caller_address = (void*) sc->si_regs.pc ;
99
#elif defined(__i386__)
100
ucontext_t* uc = (ucontext_t*) ucontext;
101
caller_address = (void*) uc->uc_mcontext.gregs[REG_EIP] ;
103
/* Unsupported return */
107
fprintf(stderr, "InnoDB: signal %d (%s), address is %p from %p\n",
108
sig_num, strsignal(sig_num), info->si_addr,
109
(void *)caller_address);
111
size = backtrace(array, OS_STACKTRACE_MAX_DEPTH);
113
/* overwrite sigaction with caller's address */
114
array[1] = caller_address;
116
messages = backtrace_symbols(array, size);
119
"InnoDB: Stacktrace for Thread %lu \n",
120
(ulong) os_thread_pf(os_thread_get_curr_id()));
122
/* skip first stack frame (points here) */
123
for (i = 1; i < size && messages != NULL; ++i)
125
fprintf(stderr, "InnoDB: [bt]: (%d) %s\n", i, messages[i]);
131
#endif /* __linux__ */