1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/debug/stack_trace.h"
13 #include <sys/param.h>
15 #include <sys/types.h>
20 #if defined(__GLIBCXX__)
24 #if defined(OS_MACOSX)
25 #include <AvailabilityMacros.h>
28 #include "base/basictypes.h"
29 #include "base/debug/debugger.h"
30 #include "base/logging.h"
31 #include "base/memory/scoped_ptr.h"
32 #include "base/posix/eintr_wrapper.h"
33 #include "base/strings/string_number_conversions.h"
35 #if defined(USE_SYMBOLIZE)
36 #include "base/third_party/symbolize/symbolize.h"
44 volatile sig_atomic_t in_signal_handler
= 0;
46 #if !defined(USE_SYMBOLIZE) && defined(__GLIBCXX__)
47 // The prefix used for mangled symbols, per the Itanium C++ ABI:
48 // http://www.codesourcery.com/cxx-abi/abi.html#mangling
49 const char kMangledSymbolPrefix
[] = "_Z";
51 // Characters that can be used for symbols, generated by Ruby:
52 // (('a'..'z').to_a+('A'..'Z').to_a+('0'..'9').to_a + ['_']).join
53 const char kSymbolCharacters
[] =
54 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
55 #endif // !defined(USE_SYMBOLIZE) && defined(__GLIBCXX__)
57 #if !defined(USE_SYMBOLIZE)
58 // Demangles C++ symbols in the given text. Example:
60 // "out/Debug/base_unittests(_ZN10StackTraceC1Ev+0x20) [0x817778c]"
62 // "out/Debug/base_unittests(StackTrace::StackTrace()+0x20) [0x817778c]"
63 void DemangleSymbols(std::string
* text
) {
64 // Note: code in this function is NOT async-signal safe (std::string uses
65 // malloc internally).
67 #if defined(__GLIBCXX__)
69 std::string::size_type search_from
= 0;
70 while (search_from
< text
->size()) {
71 // Look for the start of a mangled symbol, from search_from.
72 std::string::size_type mangled_start
=
73 text
->find(kMangledSymbolPrefix
, search_from
);
74 if (mangled_start
== std::string::npos
) {
75 break; // Mangled symbol not found.
78 // Look for the end of the mangled symbol.
79 std::string::size_type mangled_end
=
80 text
->find_first_not_of(kSymbolCharacters
, mangled_start
);
81 if (mangled_end
== std::string::npos
) {
82 mangled_end
= text
->size();
84 std::string mangled_symbol
=
85 text
->substr(mangled_start
, mangled_end
- mangled_start
);
87 // Try to demangle the mangled symbol candidate.
89 scoped_ptr_malloc
<char> demangled_symbol(
90 abi::__cxa_demangle(mangled_symbol
.c_str(), NULL
, 0, &status
));
91 if (status
== 0) { // Demangling is successful.
92 // Remove the mangled symbol.
93 text
->erase(mangled_start
, mangled_end
- mangled_start
);
94 // Insert the demangled symbol.
95 text
->insert(mangled_start
, demangled_symbol
.get());
96 // Next time, we'll start right after the demangled symbol we inserted.
97 search_from
= mangled_start
+ strlen(demangled_symbol
.get());
99 // Failed to demangle. Retry after the "_Z" we just found.
100 search_from
= mangled_start
+ 2;
104 #endif // defined(__GLIBCXX__)
106 #endif // !defined(USE_SYMBOLIZE)
108 class BacktraceOutputHandler
{
110 virtual void HandleOutput(const char* output
) = 0;
113 virtual ~BacktraceOutputHandler() {}
116 void OutputPointer(void* pointer
, BacktraceOutputHandler
* handler
) {
117 char buf
[1024] = { '\0' };
118 handler
->HandleOutput(" [0x");
119 internal::itoa_r(reinterpret_cast<intptr_t>(pointer
),
120 buf
, sizeof(buf
), 16, 12);
121 handler
->HandleOutput(buf
);
122 handler
->HandleOutput("]");
125 void ProcessBacktrace(void *const *trace
,
127 BacktraceOutputHandler
* handler
) {
128 // NOTE: This code MUST be async-signal safe (it's used by in-process
129 // stack dumping signal handler). NO malloc or stdio is allowed here.
131 #if defined(USE_SYMBOLIZE)
132 for (int i
= 0; i
< size
; ++i
) {
133 OutputPointer(trace
[i
], handler
);
134 handler
->HandleOutput(" ");
136 char buf
[1024] = { '\0' };
138 // Subtract by one as return address of function may be in the next
139 // function when a function is annotated as noreturn.
140 void* address
= static_cast<char*>(trace
[i
]) - 1;
141 if (google::Symbolize(address
, buf
, sizeof(buf
)))
142 handler
->HandleOutput(buf
);
144 handler
->HandleOutput("<unknown>");
146 handler
->HandleOutput("\n");
149 bool printed
= false;
151 // Below part is async-signal unsafe (uses malloc), so execute it only
152 // when we are not executing the signal handler.
153 if (in_signal_handler
== 0) {
154 scoped_ptr_malloc
<char*> trace_symbols(backtrace_symbols(trace
, size
));
155 if (trace_symbols
.get()) {
156 for (int i
= 0; i
< size
; ++i
) {
157 std::string trace_symbol
= trace_symbols
.get()[i
];
158 DemangleSymbols(&trace_symbol
);
159 handler
->HandleOutput(trace_symbol
.c_str());
160 handler
->HandleOutput("\n");
168 for (int i
= 0; i
< size
; ++i
) {
169 OutputPointer(trace
[i
], handler
);
170 handler
->HandleOutput("\n");
173 #endif // defined(USE_SYMBOLIZE)
176 void PrintToStderr(const char* output
) {
177 // NOTE: This code MUST be async-signal safe (it's used by in-process
178 // stack dumping signal handler). NO malloc or stdio is allowed here.
179 ignore_result(HANDLE_EINTR(write(STDERR_FILENO
, output
, strlen(output
))));
183 void StackDumpSignalHandler(int signal
, siginfo_t
* info
, void* void_context
) {
184 // NOTE: This code MUST be async-signal safe.
185 // NO malloc or stdio is allowed here.
187 // Record the fact that we are in the signal handler now, so that the rest
188 // of StackTrace can behave in an async-signal-safe manner.
189 in_signal_handler
= 1;
194 PrintToStderr("Received signal ");
195 char buf
[1024] = { 0 };
196 internal::itoa_r(signal
, buf
, sizeof(buf
), 10, 0);
198 if (signal
== SIGBUS
) {
199 if (info
->si_code
== BUS_ADRALN
)
200 PrintToStderr(" BUS_ADRALN ");
201 else if (info
->si_code
== BUS_ADRERR
)
202 PrintToStderr(" BUS_ADRERR ");
203 else if (info
->si_code
== BUS_OBJERR
)
204 PrintToStderr(" BUS_OBJERR ");
206 PrintToStderr(" <unknown> ");
207 } else if (signal
== SIGFPE
) {
208 if (info
->si_code
== FPE_FLTDIV
)
209 PrintToStderr(" FPE_FLTDIV ");
210 else if (info
->si_code
== FPE_FLTINV
)
211 PrintToStderr(" FPE_FLTINV ");
212 else if (info
->si_code
== FPE_FLTOVF
)
213 PrintToStderr(" FPE_FLTOVF ");
214 else if (info
->si_code
== FPE_FLTRES
)
215 PrintToStderr(" FPE_FLTRES ");
216 else if (info
->si_code
== FPE_FLTSUB
)
217 PrintToStderr(" FPE_FLTSUB ");
218 else if (info
->si_code
== FPE_FLTUND
)
219 PrintToStderr(" FPE_FLTUND ");
220 else if (info
->si_code
== FPE_INTDIV
)
221 PrintToStderr(" FPE_INTDIV ");
222 else if (info
->si_code
== FPE_INTOVF
)
223 PrintToStderr(" FPE_INTOVF ");
225 PrintToStderr(" <unknown> ");
226 } else if (signal
== SIGILL
) {
227 if (info
->si_code
== ILL_BADSTK
)
228 PrintToStderr(" ILL_BADSTK ");
229 else if (info
->si_code
== ILL_COPROC
)
230 PrintToStderr(" ILL_COPROC ");
231 else if (info
->si_code
== ILL_ILLOPN
)
232 PrintToStderr(" ILL_ILLOPN ");
233 else if (info
->si_code
== ILL_ILLADR
)
234 PrintToStderr(" ILL_ILLADR ");
235 else if (info
->si_code
== ILL_ILLTRP
)
236 PrintToStderr(" ILL_ILLTRP ");
237 else if (info
->si_code
== ILL_PRVOPC
)
238 PrintToStderr(" ILL_PRVOPC ");
239 else if (info
->si_code
== ILL_PRVREG
)
240 PrintToStderr(" ILL_PRVREG ");
242 PrintToStderr(" <unknown> ");
243 } else if (signal
== SIGSEGV
) {
244 if (info
->si_code
== SEGV_MAPERR
)
245 PrintToStderr(" SEGV_MAPERR ");
246 else if (info
->si_code
== SEGV_ACCERR
)
247 PrintToStderr(" SEGV_ACCERR ");
249 PrintToStderr(" <unknown> ");
251 if (signal
== SIGBUS
|| signal
== SIGFPE
||
252 signal
== SIGILL
|| signal
== SIGSEGV
) {
253 internal::itoa_r(reinterpret_cast<intptr_t>(info
->si_addr
),
254 buf
, sizeof(buf
), 16, 12);
259 debug::StackTrace().Print();
261 #if defined(OS_LINUX)
262 #if ARCH_CPU_X86_FAMILY
263 ucontext_t
* context
= reinterpret_cast<ucontext_t
*>(void_context
);
269 { " gs: ", context
->uc_mcontext
.gregs
[REG_GS
] },
270 { " fs: ", context
->uc_mcontext
.gregs
[REG_FS
] },
271 { " es: ", context
->uc_mcontext
.gregs
[REG_ES
] },
272 { " ds: ", context
->uc_mcontext
.gregs
[REG_DS
] },
273 { " edi: ", context
->uc_mcontext
.gregs
[REG_EDI
] },
274 { " esi: ", context
->uc_mcontext
.gregs
[REG_ESI
] },
275 { " ebp: ", context
->uc_mcontext
.gregs
[REG_EBP
] },
276 { " esp: ", context
->uc_mcontext
.gregs
[REG_ESP
] },
277 { " ebx: ", context
->uc_mcontext
.gregs
[REG_EBX
] },
278 { " edx: ", context
->uc_mcontext
.gregs
[REG_EDX
] },
279 { " ecx: ", context
->uc_mcontext
.gregs
[REG_ECX
] },
280 { " eax: ", context
->uc_mcontext
.gregs
[REG_EAX
] },
281 { " trp: ", context
->uc_mcontext
.gregs
[REG_TRAPNO
] },
282 { " err: ", context
->uc_mcontext
.gregs
[REG_ERR
] },
283 { " ip: ", context
->uc_mcontext
.gregs
[REG_EIP
] },
284 { " cs: ", context
->uc_mcontext
.gregs
[REG_CS
] },
285 { " efl: ", context
->uc_mcontext
.gregs
[REG_EFL
] },
286 { " usp: ", context
->uc_mcontext
.gregs
[REG_UESP
] },
287 { " ss: ", context
->uc_mcontext
.gregs
[REG_SS
] },
288 #elif ARCH_CPU_64_BITS
289 { " r8: ", context
->uc_mcontext
.gregs
[REG_R8
] },
290 { " r9: ", context
->uc_mcontext
.gregs
[REG_R9
] },
291 { " r10: ", context
->uc_mcontext
.gregs
[REG_R10
] },
292 { " r11: ", context
->uc_mcontext
.gregs
[REG_R11
] },
293 { " r12: ", context
->uc_mcontext
.gregs
[REG_R12
] },
294 { " r13: ", context
->uc_mcontext
.gregs
[REG_R13
] },
295 { " r14: ", context
->uc_mcontext
.gregs
[REG_R14
] },
296 { " r15: ", context
->uc_mcontext
.gregs
[REG_R15
] },
297 { " di: ", context
->uc_mcontext
.gregs
[REG_RDI
] },
298 { " si: ", context
->uc_mcontext
.gregs
[REG_RSI
] },
299 { " bp: ", context
->uc_mcontext
.gregs
[REG_RBP
] },
300 { " bx: ", context
->uc_mcontext
.gregs
[REG_RBX
] },
301 { " dx: ", context
->uc_mcontext
.gregs
[REG_RDX
] },
302 { " ax: ", context
->uc_mcontext
.gregs
[REG_RAX
] },
303 { " cx: ", context
->uc_mcontext
.gregs
[REG_RCX
] },
304 { " sp: ", context
->uc_mcontext
.gregs
[REG_RSP
] },
305 { " ip: ", context
->uc_mcontext
.gregs
[REG_RIP
] },
306 { " efl: ", context
->uc_mcontext
.gregs
[REG_EFL
] },
307 { " cgf: ", context
->uc_mcontext
.gregs
[REG_CSGSFS
] },
308 { " erf: ", context
->uc_mcontext
.gregs
[REG_ERR
] },
309 { " trp: ", context
->uc_mcontext
.gregs
[REG_TRAPNO
] },
310 { " msk: ", context
->uc_mcontext
.gregs
[REG_OLDMASK
] },
311 { " cr2: ", context
->uc_mcontext
.gregs
[REG_CR2
] },
316 const int kRegisterPadding
= 8;
317 #elif ARCH_CPU_64_BITS
318 const int kRegisterPadding
= 16;
321 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(registers
); i
++) {
322 PrintToStderr(registers
[i
].label
);
323 internal::itoa_r(registers
[i
].value
, buf
, sizeof(buf
),
324 16, kRegisterPadding
);
327 if ((i
+ 1) % 4 == 0)
332 #elif defined(OS_MACOSX)
333 // TODO(shess): Port to 64-bit.
334 #if ARCH_CPU_X86_FAMILY && ARCH_CPU_32_BITS
335 ucontext_t
* context
= reinterpret_cast<ucontext_t
*>(void_context
);
338 // NOTE: Even |snprintf()| is not on the approved list for signal
339 // handlers, but buffered I/O is definitely not on the list due to
340 // potential for |malloc()|.
341 len
= static_cast<size_t>(
342 snprintf(buf
, sizeof(buf
),
343 "ax: %x, bx: %x, cx: %x, dx: %x\n",
344 context
->uc_mcontext
->__ss
.__eax
,
345 context
->uc_mcontext
->__ss
.__ebx
,
346 context
->uc_mcontext
->__ss
.__ecx
,
347 context
->uc_mcontext
->__ss
.__edx
));
348 write(STDERR_FILENO
, buf
, std::min(len
, sizeof(buf
) - 1));
350 len
= static_cast<size_t>(
351 snprintf(buf
, sizeof(buf
),
352 "di: %x, si: %x, bp: %x, sp: %x, ss: %x, flags: %x\n",
353 context
->uc_mcontext
->__ss
.__edi
,
354 context
->uc_mcontext
->__ss
.__esi
,
355 context
->uc_mcontext
->__ss
.__ebp
,
356 context
->uc_mcontext
->__ss
.__esp
,
357 context
->uc_mcontext
->__ss
.__ss
,
358 context
->uc_mcontext
->__ss
.__eflags
));
359 write(STDERR_FILENO
, buf
, std::min(len
, sizeof(buf
) - 1));
361 len
= static_cast<size_t>(
362 snprintf(buf
, sizeof(buf
),
363 "ip: %x, cs: %x, ds: %x, es: %x, fs: %x, gs: %x\n",
364 context
->uc_mcontext
->__ss
.__eip
,
365 context
->uc_mcontext
->__ss
.__cs
,
366 context
->uc_mcontext
->__ss
.__ds
,
367 context
->uc_mcontext
->__ss
.__es
,
368 context
->uc_mcontext
->__ss
.__fs
,
369 context
->uc_mcontext
->__ss
.__gs
));
370 write(STDERR_FILENO
, buf
, std::min(len
, sizeof(buf
) - 1));
371 #endif // ARCH_CPU_32_BITS
372 #endif // defined(OS_MACOSX)
375 #endif // !defined(OS_IOS)
377 class PrintBacktraceOutputHandler
: public BacktraceOutputHandler
{
379 PrintBacktraceOutputHandler() {}
381 virtual void HandleOutput(const char* output
) OVERRIDE
{
382 // NOTE: This code MUST be async-signal safe (it's used by in-process
383 // stack dumping signal handler). NO malloc or stdio is allowed here.
384 PrintToStderr(output
);
388 DISALLOW_COPY_AND_ASSIGN(PrintBacktraceOutputHandler
);
391 class StreamBacktraceOutputHandler
: public BacktraceOutputHandler
{
393 explicit StreamBacktraceOutputHandler(std::ostream
* os
) : os_(os
) {
396 virtual void HandleOutput(const char* output
) OVERRIDE
{
403 DISALLOW_COPY_AND_ASSIGN(StreamBacktraceOutputHandler
);
407 void WarmUpBacktrace() {
408 // Warm up stack trace infrastructure. It turns out that on the first
409 // call glibc initializes some internal data structures using pthread_once,
410 // and even backtrace() can call malloc(), leading to hangs.
412 // Example stack trace snippet (with tcmalloc):
414 // #8 0x0000000000a173b5 in tc_malloc
415 // at ./third_party/tcmalloc/chromium/src/debugallocation.cc:1161
416 // #9 0x00007ffff7de7900 in _dl_map_object_deps at dl-deps.c:517
417 // #10 0x00007ffff7ded8a9 in dl_open_worker at dl-open.c:262
418 // #11 0x00007ffff7de9176 in _dl_catch_error at dl-error.c:178
419 // #12 0x00007ffff7ded31a in _dl_open (file=0x7ffff625e298 "libgcc_s.so.1")
421 // #13 0x00007ffff6215602 in do_dlopen at dl-libc.c:89
422 // #14 0x00007ffff7de9176 in _dl_catch_error at dl-error.c:178
423 // #15 0x00007ffff62156c4 in dlerror_run at dl-libc.c:48
424 // #16 __GI___libc_dlopen_mode at dl-libc.c:165
425 // #17 0x00007ffff61ef8f5 in init
426 // at ../sysdeps/x86_64/../ia64/backtrace.c:53
427 // #18 0x00007ffff6aad400 in pthread_once
428 // at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S:104
429 // #19 0x00007ffff61efa14 in __GI___backtrace
430 // at ../sysdeps/x86_64/../ia64/backtrace.c:104
431 // #20 0x0000000000752a54 in base::debug::StackTrace::StackTrace
432 // at base/debug/stack_trace_posix.cc:175
433 // #21 0x00000000007a4ae5 in
434 // base::(anonymous namespace)::StackDumpSignalHandler
435 // at base/process_util_posix.cc:172
436 // #22 <signal handler called>
437 StackTrace stack_trace
;
439 #endif // !defined(OS_IOS)
444 bool EnableInProcessStackDumping() {
445 // When running in an application, our code typically expects SIGPIPE
446 // to be ignored. Therefore, when testing that same code, it should run
447 // with SIGPIPE ignored as well.
448 struct sigaction sigpipe_action
;
449 memset(&sigpipe_action
, 0, sizeof(sigpipe_action
));
450 sigpipe_action
.sa_handler
= SIG_IGN
;
451 sigemptyset(&sigpipe_action
.sa_mask
);
452 bool success
= (sigaction(SIGPIPE
, &sigpipe_action
, NULL
) == 0);
454 // Avoid hangs during backtrace initialization, see above.
457 struct sigaction action
;
458 memset(&action
, 0, sizeof(action
));
459 action
.sa_flags
= SA_RESETHAND
| SA_SIGINFO
;
460 action
.sa_sigaction
= &StackDumpSignalHandler
;
461 sigemptyset(&action
.sa_mask
);
463 success
&= (sigaction(SIGILL
, &action
, NULL
) == 0);
464 success
&= (sigaction(SIGABRT
, &action
, NULL
) == 0);
465 success
&= (sigaction(SIGFPE
, &action
, NULL
) == 0);
466 success
&= (sigaction(SIGBUS
, &action
, NULL
) == 0);
467 success
&= (sigaction(SIGSEGV
, &action
, NULL
) == 0);
468 success
&= (sigaction(SIGSYS
, &action
, NULL
) == 0);
472 #endif // !defined(OS_IOS)
474 StackTrace::StackTrace() {
475 // NOTE: This code MUST be async-signal safe (it's used by in-process
476 // stack dumping signal handler). NO malloc or stdio is allowed here.
478 // Though the backtrace API man page does not list any possible negative
479 // return values, we take no chance.
480 count_
= std::max(backtrace(trace_
, arraysize(trace_
)), 0);
483 void StackTrace::Print() const {
484 // NOTE: This code MUST be async-signal safe (it's used by in-process
485 // stack dumping signal handler). NO malloc or stdio is allowed here.
487 PrintBacktraceOutputHandler handler
;
488 ProcessBacktrace(trace_
, count_
, &handler
);
491 void StackTrace::OutputToStream(std::ostream
* os
) const {
492 StreamBacktraceOutputHandler
handler(os
);
493 ProcessBacktrace(trace_
, count_
, &handler
);
498 // NOTE: code from sandbox/linux/seccomp-bpf/demo.cc.
499 char *itoa_r(intptr_t i
, char *buf
, size_t sz
, int base
, size_t padding
) {
500 // Make sure we can write at least one NUL byte.
505 if (base
< 2 || base
> 16) {
514 // Handle negative numbers (only for base 10).
515 if (i
< 0 && base
== 10) {
518 // Make sure we can write the '-' character.
526 // Loop until we have converted the entire number. Output at least one
527 // character (i.e. '0').
530 // Make sure there is still enough space left in our output buffer.
536 // Output the next digit.
537 *ptr
++ = "0123456789abcdef"[j
% base
];
542 } while (j
> 0 || padding
> 0);
544 // Terminate the output with a NUL character.
547 // Conversion to ASCII actually resulted in the digits being in reverse
548 // order. We can't easily generate them in forward order, as we can't tell
549 // the number of characters needed until we are done converting.
550 // So, now, we reverse the string (except for the possible "-" sign).
551 while (--ptr
> start
) {
559 } // namespace internal