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 // The prefix used for mangled symbols, per the Itanium C++ ABI:
47 // http://www.codesourcery.com/cxx-abi/abi.html#mangling
48 const char kMangledSymbolPrefix
[] = "_Z";
50 // Characters that can be used for symbols, generated by Ruby:
51 // (('a'..'z').to_a+('A'..'Z').to_a+('0'..'9').to_a + ['_']).join
52 const char kSymbolCharacters
[] =
53 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
55 #if !defined(USE_SYMBOLIZE)
56 // Demangles C++ symbols in the given text. Example:
58 // "out/Debug/base_unittests(_ZN10StackTraceC1Ev+0x20) [0x817778c]"
60 // "out/Debug/base_unittests(StackTrace::StackTrace()+0x20) [0x817778c]"
61 void DemangleSymbols(std::string
* text
) {
62 // Note: code in this function is NOT async-signal safe (std::string uses
63 // malloc internally).
65 #if defined(__GLIBCXX__)
67 std::string::size_type search_from
= 0;
68 while (search_from
< text
->size()) {
69 // Look for the start of a mangled symbol, from search_from.
70 std::string::size_type mangled_start
=
71 text
->find(kMangledSymbolPrefix
, search_from
);
72 if (mangled_start
== std::string::npos
) {
73 break; // Mangled symbol not found.
76 // Look for the end of the mangled symbol.
77 std::string::size_type mangled_end
=
78 text
->find_first_not_of(kSymbolCharacters
, mangled_start
);
79 if (mangled_end
== std::string::npos
) {
80 mangled_end
= text
->size();
82 std::string mangled_symbol
=
83 text
->substr(mangled_start
, mangled_end
- mangled_start
);
85 // Try to demangle the mangled symbol candidate.
87 scoped_ptr_malloc
<char> demangled_symbol(
88 abi::__cxa_demangle(mangled_symbol
.c_str(), NULL
, 0, &status
));
89 if (status
== 0) { // Demangling is successful.
90 // Remove the mangled symbol.
91 text
->erase(mangled_start
, mangled_end
- mangled_start
);
92 // Insert the demangled symbol.
93 text
->insert(mangled_start
, demangled_symbol
.get());
94 // Next time, we'll start right after the demangled symbol we inserted.
95 search_from
= mangled_start
+ strlen(demangled_symbol
.get());
97 // Failed to demangle. Retry after the "_Z" we just found.
98 search_from
= mangled_start
+ 2;
102 #endif // defined(__GLIBCXX__)
104 #endif // !defined(USE_SYMBOLIZE)
106 class BacktraceOutputHandler
{
108 virtual void HandleOutput(const char* output
) = 0;
111 virtual ~BacktraceOutputHandler() {}
114 void OutputPointer(void* pointer
, BacktraceOutputHandler
* handler
) {
115 char buf
[1024] = { '\0' };
116 handler
->HandleOutput(" [0x");
117 internal::itoa_r(reinterpret_cast<intptr_t>(pointer
),
118 buf
, sizeof(buf
), 16, 12);
119 handler
->HandleOutput(buf
);
120 handler
->HandleOutput("]");
123 void ProcessBacktrace(void *const *trace
,
125 BacktraceOutputHandler
* handler
) {
126 // NOTE: This code MUST be async-signal safe (it's used by in-process
127 // stack dumping signal handler). NO malloc or stdio is allowed here.
129 #if defined(USE_SYMBOLIZE)
130 for (int i
= 0; i
< size
; ++i
) {
131 OutputPointer(trace
[i
], handler
);
132 handler
->HandleOutput(" ");
134 char buf
[1024] = { '\0' };
136 // Subtract by one as return address of function may be in the next
137 // function when a function is annotated as noreturn.
138 void* address
= static_cast<char*>(trace
[i
]) - 1;
139 if (google::Symbolize(address
, buf
, sizeof(buf
)))
140 handler
->HandleOutput(buf
);
142 handler
->HandleOutput("<unknown>");
144 handler
->HandleOutput("\n");
147 bool printed
= false;
149 // Below part is async-signal unsafe (uses malloc), so execute it only
150 // when we are not executing the signal handler.
151 if (in_signal_handler
== 0) {
152 scoped_ptr_malloc
<char*> trace_symbols(backtrace_symbols(trace
, size
));
153 if (trace_symbols
.get()) {
154 for (int i
= 0; i
< size
; ++i
) {
155 std::string trace_symbol
= trace_symbols
.get()[i
];
156 DemangleSymbols(&trace_symbol
);
157 handler
->HandleOutput(trace_symbol
.c_str());
158 handler
->HandleOutput("\n");
166 for (int i
= 0; i
< size
; ++i
) {
167 OutputPointer(trace
[i
], handler
);
168 handler
->HandleOutput("\n");
171 #endif // defined(USE_SYMBOLIZE)
174 void PrintToStderr(const char* output
) {
175 // NOTE: This code MUST be async-signal safe (it's used by in-process
176 // stack dumping signal handler). NO malloc or stdio is allowed here.
177 ignore_result(HANDLE_EINTR(write(STDERR_FILENO
, output
, strlen(output
))));
180 void StackDumpSignalHandler(int signal
, siginfo_t
* info
, void* void_context
) {
181 // NOTE: This code MUST be async-signal safe.
182 // NO malloc or stdio is allowed here.
184 // Record the fact that we are in the signal handler now, so that the rest
185 // of StackTrace can behave in an async-signal-safe manner.
186 in_signal_handler
= 1;
191 PrintToStderr("Received signal ");
192 char buf
[1024] = { 0 };
193 internal::itoa_r(signal
, buf
, sizeof(buf
), 10, 0);
195 if (signal
== SIGBUS
) {
196 if (info
->si_code
== BUS_ADRALN
)
197 PrintToStderr(" BUS_ADRALN ");
198 else if (info
->si_code
== BUS_ADRERR
)
199 PrintToStderr(" BUS_ADRERR ");
200 else if (info
->si_code
== BUS_OBJERR
)
201 PrintToStderr(" BUS_OBJERR ");
203 PrintToStderr(" <unknown> ");
204 } else if (signal
== SIGFPE
) {
205 if (info
->si_code
== FPE_FLTDIV
)
206 PrintToStderr(" FPE_FLTDIV ");
207 else if (info
->si_code
== FPE_FLTINV
)
208 PrintToStderr(" FPE_FLTINV ");
209 else if (info
->si_code
== FPE_FLTOVF
)
210 PrintToStderr(" FPE_FLTOVF ");
211 else if (info
->si_code
== FPE_FLTRES
)
212 PrintToStderr(" FPE_FLTRES ");
213 else if (info
->si_code
== FPE_FLTSUB
)
214 PrintToStderr(" FPE_FLTSUB ");
215 else if (info
->si_code
== FPE_FLTUND
)
216 PrintToStderr(" FPE_FLTUND ");
217 else if (info
->si_code
== FPE_INTDIV
)
218 PrintToStderr(" FPE_INTDIV ");
219 else if (info
->si_code
== FPE_INTOVF
)
220 PrintToStderr(" FPE_INTOVF ");
222 PrintToStderr(" <unknown> ");
223 } else if (signal
== SIGILL
) {
224 if (info
->si_code
== ILL_BADSTK
)
225 PrintToStderr(" ILL_BADSTK ");
226 else if (info
->si_code
== ILL_COPROC
)
227 PrintToStderr(" ILL_COPROC ");
228 else if (info
->si_code
== ILL_ILLOPN
)
229 PrintToStderr(" ILL_ILLOPN ");
230 else if (info
->si_code
== ILL_ILLADR
)
231 PrintToStderr(" ILL_ILLADR ");
232 else if (info
->si_code
== ILL_ILLTRP
)
233 PrintToStderr(" ILL_ILLTRP ");
234 else if (info
->si_code
== ILL_PRVOPC
)
235 PrintToStderr(" ILL_PRVOPC ");
236 else if (info
->si_code
== ILL_PRVREG
)
237 PrintToStderr(" ILL_PRVREG ");
239 PrintToStderr(" <unknown> ");
240 } else if (signal
== SIGSEGV
) {
241 if (info
->si_code
== SEGV_MAPERR
)
242 PrintToStderr(" SEGV_MAPERR ");
243 else if (info
->si_code
== SEGV_ACCERR
)
244 PrintToStderr(" SEGV_ACCERR ");
246 PrintToStderr(" <unknown> ");
248 if (signal
== SIGBUS
|| signal
== SIGFPE
||
249 signal
== SIGILL
|| signal
== SIGSEGV
) {
250 internal::itoa_r(reinterpret_cast<intptr_t>(info
->si_addr
),
251 buf
, sizeof(buf
), 16, 12);
256 debug::StackTrace().PrintBacktrace();
258 #if defined(OS_LINUX)
259 #if ARCH_CPU_X86_FAMILY
260 ucontext_t
* context
= reinterpret_cast<ucontext_t
*>(void_context
);
266 { " gs: ", context
->uc_mcontext
.gregs
[REG_GS
] },
267 { " fs: ", context
->uc_mcontext
.gregs
[REG_FS
] },
268 { " es: ", context
->uc_mcontext
.gregs
[REG_ES
] },
269 { " ds: ", context
->uc_mcontext
.gregs
[REG_DS
] },
270 { " edi: ", context
->uc_mcontext
.gregs
[REG_EDI
] },
271 { " esi: ", context
->uc_mcontext
.gregs
[REG_ESI
] },
272 { " ebp: ", context
->uc_mcontext
.gregs
[REG_EBP
] },
273 { " esp: ", context
->uc_mcontext
.gregs
[REG_ESP
] },
274 { " ebx: ", context
->uc_mcontext
.gregs
[REG_EBX
] },
275 { " edx: ", context
->uc_mcontext
.gregs
[REG_EDX
] },
276 { " ecx: ", context
->uc_mcontext
.gregs
[REG_ECX
] },
277 { " eax: ", context
->uc_mcontext
.gregs
[REG_EAX
] },
278 { " trp: ", context
->uc_mcontext
.gregs
[REG_TRAPNO
] },
279 { " err: ", context
->uc_mcontext
.gregs
[REG_ERR
] },
280 { " ip: ", context
->uc_mcontext
.gregs
[REG_EIP
] },
281 { " cs: ", context
->uc_mcontext
.gregs
[REG_CS
] },
282 { " efl: ", context
->uc_mcontext
.gregs
[REG_EFL
] },
283 { " usp: ", context
->uc_mcontext
.gregs
[REG_UESP
] },
284 { " ss: ", context
->uc_mcontext
.gregs
[REG_SS
] },
285 #elif ARCH_CPU_64_BITS
286 { " r8: ", context
->uc_mcontext
.gregs
[REG_R8
] },
287 { " r9: ", context
->uc_mcontext
.gregs
[REG_R9
] },
288 { " r10: ", context
->uc_mcontext
.gregs
[REG_R10
] },
289 { " r11: ", context
->uc_mcontext
.gregs
[REG_R11
] },
290 { " r12: ", context
->uc_mcontext
.gregs
[REG_R12
] },
291 { " r13: ", context
->uc_mcontext
.gregs
[REG_R13
] },
292 { " r14: ", context
->uc_mcontext
.gregs
[REG_R14
] },
293 { " r15: ", context
->uc_mcontext
.gregs
[REG_R15
] },
294 { " di: ", context
->uc_mcontext
.gregs
[REG_RDI
] },
295 { " si: ", context
->uc_mcontext
.gregs
[REG_RSI
] },
296 { " bp: ", context
->uc_mcontext
.gregs
[REG_RBP
] },
297 { " bx: ", context
->uc_mcontext
.gregs
[REG_RBX
] },
298 { " dx: ", context
->uc_mcontext
.gregs
[REG_RDX
] },
299 { " ax: ", context
->uc_mcontext
.gregs
[REG_RAX
] },
300 { " cx: ", context
->uc_mcontext
.gregs
[REG_RCX
] },
301 { " sp: ", context
->uc_mcontext
.gregs
[REG_RSP
] },
302 { " ip: ", context
->uc_mcontext
.gregs
[REG_RIP
] },
303 { " efl: ", context
->uc_mcontext
.gregs
[REG_EFL
] },
304 { " cgf: ", context
->uc_mcontext
.gregs
[REG_CSGSFS
] },
305 { " erf: ", context
->uc_mcontext
.gregs
[REG_ERR
] },
306 { " trp: ", context
->uc_mcontext
.gregs
[REG_TRAPNO
] },
307 { " msk: ", context
->uc_mcontext
.gregs
[REG_OLDMASK
] },
308 { " cr2: ", context
->uc_mcontext
.gregs
[REG_CR2
] },
313 const int kRegisterPadding
= 8;
314 #elif ARCH_CPU_64_BITS
315 const int kRegisterPadding
= 16;
318 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(registers
); i
++) {
319 PrintToStderr(registers
[i
].label
);
320 internal::itoa_r(registers
[i
].value
, buf
, sizeof(buf
),
321 16, kRegisterPadding
);
324 if ((i
+ 1) % 4 == 0)
329 #elif defined(OS_MACOSX)
330 // TODO(shess): Port to 64-bit.
331 #if ARCH_CPU_X86_FAMILY && ARCH_CPU_32_BITS
332 ucontext_t
* context
= reinterpret_cast<ucontext_t
*>(void_context
);
335 // NOTE: Even |snprintf()| is not on the approved list for signal
336 // handlers, but buffered I/O is definitely not on the list due to
337 // potential for |malloc()|.
338 len
= static_cast<size_t>(
339 snprintf(buf
, sizeof(buf
),
340 "ax: %x, bx: %x, cx: %x, dx: %x\n",
341 context
->uc_mcontext
->__ss
.__eax
,
342 context
->uc_mcontext
->__ss
.__ebx
,
343 context
->uc_mcontext
->__ss
.__ecx
,
344 context
->uc_mcontext
->__ss
.__edx
));
345 write(STDERR_FILENO
, buf
, std::min(len
, sizeof(buf
) - 1));
347 len
= static_cast<size_t>(
348 snprintf(buf
, sizeof(buf
),
349 "di: %x, si: %x, bp: %x, sp: %x, ss: %x, flags: %x\n",
350 context
->uc_mcontext
->__ss
.__edi
,
351 context
->uc_mcontext
->__ss
.__esi
,
352 context
->uc_mcontext
->__ss
.__ebp
,
353 context
->uc_mcontext
->__ss
.__esp
,
354 context
->uc_mcontext
->__ss
.__ss
,
355 context
->uc_mcontext
->__ss
.__eflags
));
356 write(STDERR_FILENO
, buf
, std::min(len
, sizeof(buf
) - 1));
358 len
= static_cast<size_t>(
359 snprintf(buf
, sizeof(buf
),
360 "ip: %x, cs: %x, ds: %x, es: %x, fs: %x, gs: %x\n",
361 context
->uc_mcontext
->__ss
.__eip
,
362 context
->uc_mcontext
->__ss
.__cs
,
363 context
->uc_mcontext
->__ss
.__ds
,
364 context
->uc_mcontext
->__ss
.__es
,
365 context
->uc_mcontext
->__ss
.__fs
,
366 context
->uc_mcontext
->__ss
.__gs
));
367 write(STDERR_FILENO
, buf
, std::min(len
, sizeof(buf
) - 1));
368 #endif // ARCH_CPU_32_BITS
369 #endif // defined(OS_MACOSX)
373 class PrintBacktraceOutputHandler
: public BacktraceOutputHandler
{
375 PrintBacktraceOutputHandler() {}
377 virtual void HandleOutput(const char* output
) OVERRIDE
{
378 // NOTE: This code MUST be async-signal safe (it's used by in-process
379 // stack dumping signal handler). NO malloc or stdio is allowed here.
380 PrintToStderr(output
);
384 DISALLOW_COPY_AND_ASSIGN(PrintBacktraceOutputHandler
);
387 class StreamBacktraceOutputHandler
: public BacktraceOutputHandler
{
389 explicit StreamBacktraceOutputHandler(std::ostream
* os
) : os_(os
) {
392 virtual void HandleOutput(const char* output
) OVERRIDE
{
399 DISALLOW_COPY_AND_ASSIGN(StreamBacktraceOutputHandler
);
402 void WarmUpBacktrace() {
403 // Warm up stack trace infrastructure. It turns out that on the first
404 // call glibc initializes some internal data structures using pthread_once,
405 // and even backtrace() can call malloc(), leading to hangs.
407 // Example stack trace snippet (with tcmalloc):
409 // #8 0x0000000000a173b5 in tc_malloc
410 // at ./third_party/tcmalloc/chromium/src/debugallocation.cc:1161
411 // #9 0x00007ffff7de7900 in _dl_map_object_deps at dl-deps.c:517
412 // #10 0x00007ffff7ded8a9 in dl_open_worker at dl-open.c:262
413 // #11 0x00007ffff7de9176 in _dl_catch_error at dl-error.c:178
414 // #12 0x00007ffff7ded31a in _dl_open (file=0x7ffff625e298 "libgcc_s.so.1")
416 // #13 0x00007ffff6215602 in do_dlopen at dl-libc.c:89
417 // #14 0x00007ffff7de9176 in _dl_catch_error at dl-error.c:178
418 // #15 0x00007ffff62156c4 in dlerror_run at dl-libc.c:48
419 // #16 __GI___libc_dlopen_mode at dl-libc.c:165
420 // #17 0x00007ffff61ef8f5 in init
421 // at ../sysdeps/x86_64/../ia64/backtrace.c:53
422 // #18 0x00007ffff6aad400 in pthread_once
423 // at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S:104
424 // #19 0x00007ffff61efa14 in __GI___backtrace
425 // at ../sysdeps/x86_64/../ia64/backtrace.c:104
426 // #20 0x0000000000752a54 in base::debug::StackTrace::StackTrace
427 // at base/debug/stack_trace_posix.cc:175
428 // #21 0x00000000007a4ae5 in
429 // base::(anonymous namespace)::StackDumpSignalHandler
430 // at base/process_util_posix.cc:172
431 // #22 <signal handler called>
432 StackTrace stack_trace
;
438 bool EnableInProcessStackDumping() {
439 // When running in an application, our code typically expects SIGPIPE
440 // to be ignored. Therefore, when testing that same code, it should run
441 // with SIGPIPE ignored as well.
442 struct sigaction sigpipe_action
;
443 memset(&sigpipe_action
, 0, sizeof(sigpipe_action
));
444 sigpipe_action
.sa_handler
= SIG_IGN
;
445 sigemptyset(&sigpipe_action
.sa_mask
);
446 bool success
= (sigaction(SIGPIPE
, &sigpipe_action
, NULL
) == 0);
448 // Avoid hangs during backtrace initialization, see above.
451 struct sigaction action
;
452 memset(&action
, 0, sizeof(action
));
453 action
.sa_flags
= SA_RESETHAND
| SA_SIGINFO
;
454 action
.sa_sigaction
= &StackDumpSignalHandler
;
455 sigemptyset(&action
.sa_mask
);
457 success
&= (sigaction(SIGILL
, &action
, NULL
) == 0);
458 success
&= (sigaction(SIGABRT
, &action
, NULL
) == 0);
459 success
&= (sigaction(SIGFPE
, &action
, NULL
) == 0);
460 success
&= (sigaction(SIGBUS
, &action
, NULL
) == 0);
461 success
&= (sigaction(SIGSEGV
, &action
, NULL
) == 0);
462 success
&= (sigaction(SIGSYS
, &action
, NULL
) == 0);
466 #endif // !defined(OS_IOS)
468 StackTrace::StackTrace() {
469 // NOTE: This code MUST be async-signal safe (it's used by in-process
470 // stack dumping signal handler). NO malloc or stdio is allowed here.
472 // Though the backtrace API man page does not list any possible negative
473 // return values, we take no chance.
474 count_
= std::max(backtrace(trace_
, arraysize(trace_
)), 0);
477 void StackTrace::PrintBacktrace() const {
478 // NOTE: This code MUST be async-signal safe (it's used by in-process
479 // stack dumping signal handler). NO malloc or stdio is allowed here.
481 PrintBacktraceOutputHandler handler
;
482 ProcessBacktrace(trace_
, count_
, &handler
);
485 void StackTrace::OutputToStream(std::ostream
* os
) const {
486 StreamBacktraceOutputHandler
handler(os
);
487 ProcessBacktrace(trace_
, count_
, &handler
);
492 // NOTE: code from sandbox/linux/seccomp-bpf/demo.cc.
493 char *itoa_r(intptr_t i
, char *buf
, size_t sz
, int base
, size_t padding
) {
494 // Make sure we can write at least one NUL byte.
499 if (base
< 2 || base
> 16) {
508 // Handle negative numbers (only for base 10).
509 if (i
< 0 && base
== 10) {
512 // Make sure we can write the '-' character.
520 // Loop until we have converted the entire number. Output at least one
521 // character (i.e. '0').
524 // Make sure there is still enough space left in our output buffer.
530 // Output the next digit.
531 *ptr
++ = "0123456789abcdef"[j
% base
];
536 } while (j
> 0 || padding
> 0);
538 // Terminate the output with a NUL character.
541 // Conversion to ASCII actually resulted in the digits being in reverse
542 // order. We can't easily generate them in forward order, as we can't tell
543 // the number of characters needed until we are done converting.
544 // So, now, we reverse the string (except for the possible "-" sign).
545 while (--ptr
> start
) {
553 } // namespace internal