28#if V8_LIBC_GLIBC || V8_LIBC_BSD || V8_LIBC_UCLIBC || V8_OS_SOLARIS
29#define HAVE_EXECINFO_H 1
37#include <AvailabilityMacros.h>
57char*
itoa_r(intptr_t
i,
char* buf,
size_t sz,
int base,
size_t padding);
63volatile sig_atomic_t in_signal_handler = 0;
64bool dump_stack_in_signal_handler =
true;
68const char kMangledSymbolPrefix[] =
"_Z";
72const char kSymbolCharacters[] =
73 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
81void DemangleSymbols(std::string* text) {
86 std::string::size_type search_from = 0;
87 while (search_from < text->
size()) {
89 std::string::size_type mangled_start =
90 text->find(kMangledSymbolPrefix, search_from);
91 if (mangled_start == std::string::npos) {
96 std::string::size_type mangled_end =
97 text->find_first_not_of(kSymbolCharacters, mangled_start);
98 if (mangled_end == std::string::npos) {
99 mangled_end = text->size();
101 std::string mangled_symbol =
102 text->substr(mangled_start, mangled_end - mangled_start);
106 std::unique_ptr<char, FreeDeleter> demangled_symbol(
107 abi::__cxa_demangle(mangled_symbol.c_str(),
nullptr,
nullptr, &status));
110 text->erase(mangled_start, mangled_end - mangled_start);
112 text->insert(mangled_start, demangled_symbol.get());
114 search_from = mangled_start + strlen(demangled_symbol.get());
117 search_from = mangled_start + 2;
123class BacktraceOutputHandler {
125 virtual void HandleOutput(
const char* output) = 0;
130 virtual int OutputFileDescriptor()
const {
return 0; }
133 virtual ~BacktraceOutputHandler() =
default;
137void OutputPointer(
void* pointer, BacktraceOutputHandler* handler) {
140 char buf[17] = {
'\0'};
141 handler->HandleOutput(
"0x");
144 handler->HandleOutput(buf);
147void ProcessBacktrace(
void*
const* trace,
size_t size,
148 BacktraceOutputHandler* handler) {
151 handler->HandleOutput(
"\n");
152 handler->HandleOutput(
"==== C stack trace ===============================\n");
153 handler->HandleOutput(
"\n");
155 bool printed =
false;
159 if (in_signal_handler == 0) {
160 std::unique_ptr<char*, FreeDeleter> trace_symbols(
161 backtrace_symbols(trace,
static_cast<int>(size)));
163 for (
size_t i = 0;
i <
size; ++
i) {
164 std::string trace_symbol = trace_symbols.get()[
i];
165 DemangleSymbols(&trace_symbol);
166 handler->HandleOutput(
" ");
167 handler->HandleOutput(trace_symbol.c_str());
168 handler->HandleOutput(
"\n");
173 }
else if (handler->OutputFileDescriptor() != 0) {
178 backtrace_symbols_fd(trace,
static_cast<int>(size),
179 handler->OutputFileDescriptor());
184 for (
size_t i = 0;
i <
size; ++
i) {
185 handler->HandleOutput(
" [");
186 OutputPointer(trace[
i], handler);
187 handler->HandleOutput(
"]\n");
193void PrintToStderr(
const char* output) {
196 ssize_t return_val = write(STDERR_FILENO, output, strlen(output));
200void StackDumpSignalHandler(
int signal, siginfo_t* info,
void* void_context) {
206 in_signal_handler = 1;
208 PrintToStderr(
"Received signal ");
209 char buf[1024] = {0};
212 if (signal == SIGBUS) {
213 if (info->si_code == BUS_ADRALN)
214 PrintToStderr(
" BUS_ADRALN ");
215 else if (info->si_code == BUS_ADRERR)
216 PrintToStderr(
" BUS_ADRERR ");
217 else if (info->si_code == BUS_OBJERR)
218 PrintToStderr(
" BUS_OBJERR ");
220 PrintToStderr(
" <unknown> ");
221 }
else if (signal == SIGFPE) {
222 if (info->si_code == FPE_FLTDIV)
223 PrintToStderr(
" FPE_FLTDIV ");
224 else if (info->si_code == FPE_FLTINV)
225 PrintToStderr(
" FPE_FLTINV ");
226 else if (info->si_code == FPE_FLTOVF)
227 PrintToStderr(
" FPE_FLTOVF ");
228 else if (info->si_code == FPE_FLTRES)
229 PrintToStderr(
" FPE_FLTRES ");
230 else if (info->si_code == FPE_FLTSUB)
231 PrintToStderr(
" FPE_FLTSUB ");
232 else if (info->si_code == FPE_FLTUND)
233 PrintToStderr(
" FPE_FLTUND ");
234 else if (info->si_code == FPE_INTDIV)
235 PrintToStderr(
" FPE_INTDIV ");
236 else if (info->si_code == FPE_INTOVF)
237 PrintToStderr(
" FPE_INTOVF ");
239 PrintToStderr(
" <unknown> ");
240 }
else if (signal == SIGILL) {
241 if (info->si_code == ILL_BADSTK)
242 PrintToStderr(
" ILL_BADSTK ");
243 else if (info->si_code == ILL_COPROC)
244 PrintToStderr(
" ILL_COPROC ");
245 else if (info->si_code == ILL_ILLOPN)
246 PrintToStderr(
" ILL_ILLOPN ");
247 else if (info->si_code == ILL_ILLADR)
248 PrintToStderr(
" ILL_ILLADR ");
249 else if (info->si_code == ILL_ILLTRP)
250 PrintToStderr(
" ILL_ILLTRP ");
251 else if (info->si_code == ILL_PRVOPC)
252 PrintToStderr(
" ILL_PRVOPC ");
253 else if (info->si_code == ILL_PRVREG)
254 PrintToStderr(
" ILL_PRVREG ");
256 PrintToStderr(
" <unknown> ");
257 }
else if (signal == SIGSEGV) {
258 if (info->si_code == SEGV_MAPERR)
259 PrintToStderr(
" SEGV_MAPERR ");
260 else if (info->si_code == SEGV_ACCERR)
261 PrintToStderr(
" SEGV_ACCERR ");
263 PrintToStderr(
" <unknown> ");
265 if (signal == SIGBUS || signal == SIGFPE || signal == SIGILL ||
268 sizeof(buf), 16, 12);
272 if (dump_stack_in_signal_handler) {
273 debug::StackTrace().Print();
274 PrintToStderr(
"[end of stack trace]\n");
277 if (::signal(signal, SIG_DFL) == SIG_ERR) _exit(1);
280class PrintBacktraceOutputHandler :
public BacktraceOutputHandler {
282 PrintBacktraceOutputHandler() =
default;
283 PrintBacktraceOutputHandler(
const PrintBacktraceOutputHandler&) =
delete;
284 PrintBacktraceOutputHandler& operator=(
const PrintBacktraceOutputHandler&) =
287 void HandleOutput(
const char* output)
override {
290 PrintToStderr(output);
293 int OutputFileDescriptor()
const override {
return STDERR_FILENO; }
296class StreamBacktraceOutputHandler :
public BacktraceOutputHandler {
298 explicit StreamBacktraceOutputHandler(std::ostream* os) :
os_(os) {}
299 StreamBacktraceOutputHandler(
const StreamBacktraceOutputHandler&) =
delete;
300 StreamBacktraceOutputHandler& operator=(
const StreamBacktraceOutputHandler&) =
303 void HandleOutput(
const char* output)
override { (*os_) << output; }
309void WarmUpBacktrace() {
339 StackTrace stack_trace;
348 struct sigaction sigpipe_action;
349 memset(&sigpipe_action, 0,
sizeof(sigpipe_action));
350 sigpipe_action.sa_handler = SIG_IGN;
351 sigemptyset(&sigpipe_action.sa_mask);
352 bool success = (sigaction(SIGPIPE, &sigpipe_action,
nullptr) == 0);
357 struct sigaction action;
358 memset(&action, 0,
sizeof(action));
363 action.sa_flags = SA_RESETHAND | SA_SIGINFO | SA_ONSTACK;
364 action.sa_sigaction = &StackDumpSignalHandler;
365 sigemptyset(&action.sa_mask);
367 success &= (sigaction(SIGILL, &action,
nullptr) == 0);
368 success &= (sigaction(SIGABRT, &action,
nullptr) == 0);
369 success &= (sigaction(SIGFPE, &action,
nullptr) == 0);
370 success &= (sigaction(SIGBUS, &action,
nullptr) == 0);
371 success &= (sigaction(SIGSEGV, &action,
nullptr) == 0);
372 success &= (sigaction(SIGSYS, &action,
nullptr) == 0);
374 dump_stack_in_signal_handler =
true;
380 dump_stack_in_signal_handler =
false;
401 PrintBacktraceOutputHandler
handler;
408 StreamBacktraceOutputHandler
handler(os);
416char*
itoa_r(intptr_t
i,
char* buf,
size_t sz,
int base,
size_t padding) {
419 if (n > sz)
return nullptr;
421 if (base < 2 || base > 16) {
431 if (
i < 0 &&
base == 10) {
433 j =
static_cast<uintptr_t
>(-(
i + 1)) + 1;
454 *ptr++ =
"0123456789abcdef"[j %
base];
457 if (padding > 0) padding--;
458 }
while (j > 0 || padding > 0);
467 while (--ptr >
start) {
void OutputToStream(std::ostream *os) const
void * trace_[kMaxTraces]
char * itoa_r(intptr_t i, char *buf, size_t sz, int base, size_t padding)
V8_BASE_EXPORT bool EnableInProcessStackDumping()
V8_BASE_EXPORT void DisableSignalStackDump()