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. 4 5#include "base/debug/stack_trace.h" 6 7#include <errno.h> 8#include <fcntl.h> 9#include <signal.h> 10#include <stddef.h> 11#include <stdint.h> 12#include <stdio.h> 13#include <stdlib.h> 14#include <sys/param.h> 15#include <sys/stat.h> 16#include <sys/types.h> 17#include <unistd.h> 18 19#include <map> 20#include <ostream> 21#include <string> 22#include <vector> 23 24#if defined(__GLIBCXX__) 25#include <cxxabi.h> 26#endif 27#if !defined(__UCLIBC__) 28#include <execinfo.h> 29#endif 30 31#if defined(OS_MACOSX) 32#include <AvailabilityMacros.h> 33#endif 34 35#include "base/debug/debugger.h" 36#include "base/debug/proc_maps_linux.h" 37#include "base/logging.h" 38#include "base/macros.h" 39#include "base/memory/scoped_ptr.h" 40#include "base/memory/singleton.h" 41#include "base/numerics/safe_conversions.h" 42#include "base/posix/eintr_wrapper.h" 43#include "base/strings/string_number_conversions.h" 44#include "build/build_config.h" 45 46#if defined(USE_SYMBOLIZE) 47#error "symbolize support was removed from libchrome" 48#endif 49 50namespace base { 51namespace debug { 52 53namespace { 54 55volatile sig_atomic_t in_signal_handler = 0; 56 57#if !defined(USE_SYMBOLIZE) && defined(__GLIBCXX__) 58// The prefix used for mangled symbols, per the Itanium C++ ABI: 59// http://www.codesourcery.com/cxx-abi/abi.html#mangling 60const char kMangledSymbolPrefix[] = "_Z"; 61 62// Characters that can be used for symbols, generated by Ruby: 63// (('a'..'z').to_a+('A'..'Z').to_a+('0'..'9').to_a + ['_']).join 64const char kSymbolCharacters[] = 65 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; 66#endif // !defined(USE_SYMBOLIZE) && defined(__GLIBCXX__) 67 68#if !defined(USE_SYMBOLIZE) 69// Demangles C++ symbols in the given text. Example: 70// 71// "out/Debug/base_unittests(_ZN10StackTraceC1Ev+0x20) [0x817778c]" 72// => 73// "out/Debug/base_unittests(StackTrace::StackTrace()+0x20) [0x817778c]" 74#if defined(__GLIBCXX__) && !defined(__UCLIBC__) 75void DemangleSymbols(std::string* text) { 76 // Note: code in this function is NOT async-signal safe (std::string uses 77 // malloc internally). 78 std::string::size_type search_from = 0; 79 while (search_from < text->size()) { 80 // Look for the start of a mangled symbol, from search_from. 81 std::string::size_type mangled_start = 82 text->find(kMangledSymbolPrefix, search_from); 83 if (mangled_start == std::string::npos) { 84 break; // Mangled symbol not found. 85 } 86 87 // Look for the end of the mangled symbol. 88 std::string::size_type mangled_end = 89 text->find_first_not_of(kSymbolCharacters, mangled_start); 90 if (mangled_end == std::string::npos) { 91 mangled_end = text->size(); 92 } 93 std::string mangled_symbol = 94 text->substr(mangled_start, mangled_end - mangled_start); 95 96 // Try to demangle the mangled symbol candidate. 97 int status = 0; 98 scoped_ptr<char, base::FreeDeleter> demangled_symbol( 99 abi::__cxa_demangle(mangled_symbol.c_str(), NULL, 0, &status)); 100 if (status == 0) { // Demangling is successful. 101 // Remove the mangled symbol. 102 text->erase(mangled_start, mangled_end - mangled_start); 103 // Insert the demangled symbol. 104 text->insert(mangled_start, demangled_symbol.get()); 105 // Next time, we'll start right after the demangled symbol we inserted. 106 search_from = mangled_start + strlen(demangled_symbol.get()); 107 } else { 108 // Failed to demangle. Retry after the "_Z" we just found. 109 search_from = mangled_start + 2; 110 } 111 } 112} 113#elif !defined(__UCLIBC__) 114void DemangleSymbols(std::string* /* text */) {} 115#endif // defined(__GLIBCXX__) && !defined(__UCLIBC__) 116 117#endif // !defined(USE_SYMBOLIZE) 118 119class BacktraceOutputHandler { 120 public: 121 virtual void HandleOutput(const char* output) = 0; 122 123 protected: 124 virtual ~BacktraceOutputHandler() {} 125}; 126 127#if defined(USE_SYMBOLIZE) || !defined(__UCLIBC__) 128void OutputPointer(void* pointer, BacktraceOutputHandler* handler) { 129 // This should be more than enough to store a 64-bit number in hex: 130 // 16 hex digits + 1 for null-terminator. 131 char buf[17] = { '\0' }; 132 handler->HandleOutput("0x"); 133 internal::itoa_r(reinterpret_cast<intptr_t>(pointer), 134 buf, sizeof(buf), 16, 12); 135 handler->HandleOutput(buf); 136} 137#endif // defined(USE_SYMBOLIZE) || !defined(__UCLIBC__) 138 139#if defined(USE_SYMBOLIZE) 140void OutputFrameId(intptr_t frame_id, BacktraceOutputHandler* handler) { 141 // Max unsigned 64-bit number in decimal has 20 digits (18446744073709551615). 142 // Hence, 30 digits should be more than enough to represent it in decimal 143 // (including the null-terminator). 144 char buf[30] = { '\0' }; 145 handler->HandleOutput("#"); 146 internal::itoa_r(frame_id, buf, sizeof(buf), 10, 1); 147 handler->HandleOutput(buf); 148} 149#endif // defined(USE_SYMBOLIZE) 150 151#if !defined(__UCLIBC__) 152void ProcessBacktrace(void *const * trace, 153 size_t size, 154 BacktraceOutputHandler* handler) { 155 (void)trace; // unused based on build context below. 156 (void)size; // unusud based on build context below. 157 (void)handler; // unused based on build context below. 158 // NOTE: This code MUST be async-signal safe (it's used by in-process 159 // stack dumping signal handler). NO malloc or stdio is allowed here. 160 161#if defined(USE_SYMBOLIZE) 162 for (size_t i = 0; i < size; ++i) { 163 OutputFrameId(i, handler); 164 handler->HandleOutput(" "); 165 OutputPointer(trace[i], handler); 166 handler->HandleOutput(" "); 167 168 char buf[1024] = { '\0' }; 169 170 // Subtract by one as return address of function may be in the next 171 // function when a function is annotated as noreturn. 172 void* address = static_cast<char*>(trace[i]) - 1; 173 if (google::Symbolize(address, buf, sizeof(buf))) 174 handler->HandleOutput(buf); 175 else 176 handler->HandleOutput("<unknown>"); 177 178 handler->HandleOutput("\n"); 179 } 180#elif !defined(__UCLIBC__) 181 bool printed = false; 182 183 // Below part is async-signal unsafe (uses malloc), so execute it only 184 // when we are not executing the signal handler. 185 if (in_signal_handler == 0) { 186 scoped_ptr<char*, FreeDeleter> 187 trace_symbols(backtrace_symbols(trace, size)); 188 if (trace_symbols.get()) { 189 for (size_t i = 0; i < size; ++i) { 190 std::string trace_symbol = trace_symbols.get()[i]; 191 DemangleSymbols(&trace_symbol); 192 handler->HandleOutput(trace_symbol.c_str()); 193 handler->HandleOutput("\n"); 194 } 195 196 printed = true; 197 } 198 } 199 200 if (!printed) { 201 for (size_t i = 0; i < size; ++i) { 202 handler->HandleOutput(" ["); 203 OutputPointer(trace[i], handler); 204 handler->HandleOutput("]\n"); 205 } 206 } 207#endif // defined(USE_SYMBOLIZE) 208} 209#endif // !defined(__UCLIBC__) 210 211void PrintToStderr(const char* output) { 212 // NOTE: This code MUST be async-signal safe (it's used by in-process 213 // stack dumping signal handler). NO malloc or stdio is allowed here. 214 ignore_result(HANDLE_EINTR(write(STDERR_FILENO, output, strlen(output)))); 215} 216 217void StackDumpSignalHandler(int signal, 218 siginfo_t* info, 219 void* void_context) { 220 (void)void_context; // unused depending on build context 221 // NOTE: This code MUST be async-signal safe. 222 // NO malloc or stdio is allowed here. 223 224 // Record the fact that we are in the signal handler now, so that the rest 225 // of StackTrace can behave in an async-signal-safe manner. 226 in_signal_handler = 1; 227 228 if (BeingDebugged()) 229 BreakDebugger(); 230 231 PrintToStderr("Received signal "); 232 char buf[1024] = { 0 }; 233 internal::itoa_r(signal, buf, sizeof(buf), 10, 0); 234 PrintToStderr(buf); 235 if (signal == SIGBUS) { 236 if (info->si_code == BUS_ADRALN) 237 PrintToStderr(" BUS_ADRALN "); 238 else if (info->si_code == BUS_ADRERR) 239 PrintToStderr(" BUS_ADRERR "); 240 else if (info->si_code == BUS_OBJERR) 241 PrintToStderr(" BUS_OBJERR "); 242 else 243 PrintToStderr(" <unknown> "); 244 } else if (signal == SIGFPE) { 245 if (info->si_code == FPE_FLTDIV) 246 PrintToStderr(" FPE_FLTDIV "); 247 else if (info->si_code == FPE_FLTINV) 248 PrintToStderr(" FPE_FLTINV "); 249 else if (info->si_code == FPE_FLTOVF) 250 PrintToStderr(" FPE_FLTOVF "); 251 else if (info->si_code == FPE_FLTRES) 252 PrintToStderr(" FPE_FLTRES "); 253 else if (info->si_code == FPE_FLTSUB) 254 PrintToStderr(" FPE_FLTSUB "); 255 else if (info->si_code == FPE_FLTUND) 256 PrintToStderr(" FPE_FLTUND "); 257 else if (info->si_code == FPE_INTDIV) 258 PrintToStderr(" FPE_INTDIV "); 259 else if (info->si_code == FPE_INTOVF) 260 PrintToStderr(" FPE_INTOVF "); 261 else 262 PrintToStderr(" <unknown> "); 263 } else if (signal == SIGILL) { 264 if (info->si_code == ILL_BADSTK) 265 PrintToStderr(" ILL_BADSTK "); 266 else if (info->si_code == ILL_COPROC) 267 PrintToStderr(" ILL_COPROC "); 268 else if (info->si_code == ILL_ILLOPN) 269 PrintToStderr(" ILL_ILLOPN "); 270 else if (info->si_code == ILL_ILLADR) 271 PrintToStderr(" ILL_ILLADR "); 272 else if (info->si_code == ILL_ILLTRP) 273 PrintToStderr(" ILL_ILLTRP "); 274 else if (info->si_code == ILL_PRVOPC) 275 PrintToStderr(" ILL_PRVOPC "); 276 else if (info->si_code == ILL_PRVREG) 277 PrintToStderr(" ILL_PRVREG "); 278 else 279 PrintToStderr(" <unknown> "); 280 } else if (signal == SIGSEGV) { 281 if (info->si_code == SEGV_MAPERR) 282 PrintToStderr(" SEGV_MAPERR "); 283 else if (info->si_code == SEGV_ACCERR) 284 PrintToStderr(" SEGV_ACCERR "); 285 else 286 PrintToStderr(" <unknown> "); 287 } 288 if (signal == SIGBUS || signal == SIGFPE || 289 signal == SIGILL || signal == SIGSEGV) { 290 internal::itoa_r(reinterpret_cast<intptr_t>(info->si_addr), 291 buf, sizeof(buf), 16, 12); 292 PrintToStderr(buf); 293 } 294 PrintToStderr("\n"); 295 296#if defined(CFI_ENFORCEMENT) 297 if (signal == SIGILL && info->si_code == ILL_ILLOPN) { 298 PrintToStderr( 299 "CFI: Most likely a control flow integrity violation; for more " 300 "information see:\n"); 301 PrintToStderr( 302 "https://www.chromium.org/developers/testing/control-flow-integrity\n"); 303 } 304#endif 305 306 debug::StackTrace().Print(); 307 308#if defined(OS_LINUX) 309#if ARCH_CPU_X86_FAMILY 310 ucontext_t* context = reinterpret_cast<ucontext_t*>(void_context); 311 const struct { 312 const char* label; 313 greg_t value; 314 } registers[] = { 315#if ARCH_CPU_32_BITS 316 { " gs: ", context->uc_mcontext.gregs[REG_GS] }, 317 { " fs: ", context->uc_mcontext.gregs[REG_FS] }, 318 { " es: ", context->uc_mcontext.gregs[REG_ES] }, 319 { " ds: ", context->uc_mcontext.gregs[REG_DS] }, 320 { " edi: ", context->uc_mcontext.gregs[REG_EDI] }, 321 { " esi: ", context->uc_mcontext.gregs[REG_ESI] }, 322 { " ebp: ", context->uc_mcontext.gregs[REG_EBP] }, 323 { " esp: ", context->uc_mcontext.gregs[REG_ESP] }, 324 { " ebx: ", context->uc_mcontext.gregs[REG_EBX] }, 325 { " edx: ", context->uc_mcontext.gregs[REG_EDX] }, 326 { " ecx: ", context->uc_mcontext.gregs[REG_ECX] }, 327 { " eax: ", context->uc_mcontext.gregs[REG_EAX] }, 328 { " trp: ", context->uc_mcontext.gregs[REG_TRAPNO] }, 329 { " err: ", context->uc_mcontext.gregs[REG_ERR] }, 330 { " ip: ", context->uc_mcontext.gregs[REG_EIP] }, 331 { " cs: ", context->uc_mcontext.gregs[REG_CS] }, 332 { " efl: ", context->uc_mcontext.gregs[REG_EFL] }, 333 { " usp: ", context->uc_mcontext.gregs[REG_UESP] }, 334 { " ss: ", context->uc_mcontext.gregs[REG_SS] }, 335#elif ARCH_CPU_64_BITS 336 { " r8: ", context->uc_mcontext.gregs[REG_R8] }, 337 { " r9: ", context->uc_mcontext.gregs[REG_R9] }, 338 { " r10: ", context->uc_mcontext.gregs[REG_R10] }, 339 { " r11: ", context->uc_mcontext.gregs[REG_R11] }, 340 { " r12: ", context->uc_mcontext.gregs[REG_R12] }, 341 { " r13: ", context->uc_mcontext.gregs[REG_R13] }, 342 { " r14: ", context->uc_mcontext.gregs[REG_R14] }, 343 { " r15: ", context->uc_mcontext.gregs[REG_R15] }, 344 { " di: ", context->uc_mcontext.gregs[REG_RDI] }, 345 { " si: ", context->uc_mcontext.gregs[REG_RSI] }, 346 { " bp: ", context->uc_mcontext.gregs[REG_RBP] }, 347 { " bx: ", context->uc_mcontext.gregs[REG_RBX] }, 348 { " dx: ", context->uc_mcontext.gregs[REG_RDX] }, 349 { " ax: ", context->uc_mcontext.gregs[REG_RAX] }, 350 { " cx: ", context->uc_mcontext.gregs[REG_RCX] }, 351 { " sp: ", context->uc_mcontext.gregs[REG_RSP] }, 352 { " ip: ", context->uc_mcontext.gregs[REG_RIP] }, 353 { " efl: ", context->uc_mcontext.gregs[REG_EFL] }, 354 { " cgf: ", context->uc_mcontext.gregs[REG_CSGSFS] }, 355 { " erf: ", context->uc_mcontext.gregs[REG_ERR] }, 356 { " trp: ", context->uc_mcontext.gregs[REG_TRAPNO] }, 357 { " msk: ", context->uc_mcontext.gregs[REG_OLDMASK] }, 358 { " cr2: ", context->uc_mcontext.gregs[REG_CR2] }, 359#endif // ARCH_CPU_32_BITS 360 }; 361 362#if ARCH_CPU_32_BITS 363 const int kRegisterPadding = 8; 364#elif ARCH_CPU_64_BITS 365 const int kRegisterPadding = 16; 366#endif 367 368 for (size_t i = 0; i < arraysize(registers); i++) { 369 PrintToStderr(registers[i].label); 370 internal::itoa_r(registers[i].value, buf, sizeof(buf), 371 16, kRegisterPadding); 372 PrintToStderr(buf); 373 374 if ((i + 1) % 4 == 0) 375 PrintToStderr("\n"); 376 } 377 PrintToStderr("\n"); 378#endif // ARCH_CPU_X86_FAMILY 379#endif // defined(OS_LINUX) 380 381 PrintToStderr("[end of stack trace]\n"); 382 383#if defined(OS_MACOSX) && !defined(OS_IOS) 384 if (::signal(signal, SIG_DFL) == SIG_ERR) 385 _exit(1); 386#else 387 // Non-Mac OSes should probably reraise the signal as well, but the Linux 388 // sandbox tests break on CrOS devices. 389 // https://code.google.com/p/chromium/issues/detail?id=551681 390 _exit(1); 391#endif // defined(OS_MACOSX) && !defined(OS_IOS) 392} 393 394class PrintBacktraceOutputHandler : public BacktraceOutputHandler { 395 public: 396 PrintBacktraceOutputHandler() {} 397 398 void HandleOutput(const char* output) override { 399 // NOTE: This code MUST be async-signal safe (it's used by in-process 400 // stack dumping signal handler). NO malloc or stdio is allowed here. 401 PrintToStderr(output); 402 } 403 404 private: 405 DISALLOW_COPY_AND_ASSIGN(PrintBacktraceOutputHandler); 406}; 407 408class StreamBacktraceOutputHandler : public BacktraceOutputHandler { 409 public: 410 explicit StreamBacktraceOutputHandler(std::ostream* os) : os_(os) { 411 } 412 413 void HandleOutput(const char* output) override { (*os_) << output; } 414 415 private: 416 std::ostream* os_; 417 418 DISALLOW_COPY_AND_ASSIGN(StreamBacktraceOutputHandler); 419}; 420 421void WarmUpBacktrace() { 422 // Warm up stack trace infrastructure. It turns out that on the first 423 // call glibc initializes some internal data structures using pthread_once, 424 // and even backtrace() can call malloc(), leading to hangs. 425 // 426 // Example stack trace snippet (with tcmalloc): 427 // 428 // #8 0x0000000000a173b5 in tc_malloc 429 // at ./third_party/tcmalloc/chromium/src/debugallocation.cc:1161 430 // #9 0x00007ffff7de7900 in _dl_map_object_deps at dl-deps.c:517 431 // #10 0x00007ffff7ded8a9 in dl_open_worker at dl-open.c:262 432 // #11 0x00007ffff7de9176 in _dl_catch_error at dl-error.c:178 433 // #12 0x00007ffff7ded31a in _dl_open (file=0x7ffff625e298 "libgcc_s.so.1") 434 // at dl-open.c:639 435 // #13 0x00007ffff6215602 in do_dlopen at dl-libc.c:89 436 // #14 0x00007ffff7de9176 in _dl_catch_error at dl-error.c:178 437 // #15 0x00007ffff62156c4 in dlerror_run at dl-libc.c:48 438 // #16 __GI___libc_dlopen_mode at dl-libc.c:165 439 // #17 0x00007ffff61ef8f5 in init 440 // at ../sysdeps/x86_64/../ia64/backtrace.c:53 441 // #18 0x00007ffff6aad400 in pthread_once 442 // at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S:104 443 // #19 0x00007ffff61efa14 in __GI___backtrace 444 // at ../sysdeps/x86_64/../ia64/backtrace.c:104 445 // #20 0x0000000000752a54 in base::debug::StackTrace::StackTrace 446 // at base/debug/stack_trace_posix.cc:175 447 // #21 0x00000000007a4ae5 in 448 // base::(anonymous namespace)::StackDumpSignalHandler 449 // at base/process_util_posix.cc:172 450 // #22 <signal handler called> 451 StackTrace stack_trace; 452} 453 454} // namespace 455 456#if defined(USE_SYMBOLIZE) 457 458// class SandboxSymbolizeHelper. 459// 460// The purpose of this class is to prepare and install a "file open" callback 461// needed by the stack trace symbolization code 462// (base/third_party/symbolize/symbolize.h) so that it can function properly 463// in a sandboxed process. The caveat is that this class must be instantiated 464// before the sandboxing is enabled so that it can get the chance to open all 465// the object files that are loaded in the virtual address space of the current 466// process. 467class SandboxSymbolizeHelper { 468 public: 469 // Returns the singleton instance. 470 static SandboxSymbolizeHelper* GetInstance() { 471 return Singleton<SandboxSymbolizeHelper>::get(); 472 } 473 474 private: 475 friend struct DefaultSingletonTraits<SandboxSymbolizeHelper>; 476 477 SandboxSymbolizeHelper() 478 : is_initialized_(false) { 479 Init(); 480 } 481 482 ~SandboxSymbolizeHelper() { 483 UnregisterCallback(); 484 CloseObjectFiles(); 485 } 486 487 // Returns a O_RDONLY file descriptor for |file_path| if it was opened 488 // successfully during the initialization. The file is repositioned at 489 // offset 0. 490 // IMPORTANT: This function must be async-signal-safe because it can be 491 // called from a signal handler (symbolizing stack frames for a crash). 492 int GetFileDescriptor(const char* file_path) { 493 int fd = -1; 494 495#if !defined(OFFICIAL_BUILD) 496 if (file_path) { 497 // The assumption here is that iterating over std::map<std::string, int> 498 // using a const_iterator does not allocate dynamic memory, hense it is 499 // async-signal-safe. 500 std::map<std::string, int>::const_iterator it; 501 for (it = modules_.begin(); it != modules_.end(); ++it) { 502 if (strcmp((it->first).c_str(), file_path) == 0) { 503 // POSIX.1-2004 requires an implementation to guarantee that dup() 504 // is async-signal-safe. 505 fd = dup(it->second); 506 break; 507 } 508 } 509 // POSIX.1-2004 requires an implementation to guarantee that lseek() 510 // is async-signal-safe. 511 if (fd >= 0 && lseek(fd, 0, SEEK_SET) < 0) { 512 // Failed to seek. 513 fd = -1; 514 } 515 } 516#endif // !defined(OFFICIAL_BUILD) 517 518 return fd; 519 } 520 521 // Searches for the object file (from /proc/self/maps) that contains 522 // the specified pc. If found, sets |start_address| to the start address 523 // of where this object file is mapped in memory, sets the module base 524 // address into |base_address|, copies the object file name into 525 // |out_file_name|, and attempts to open the object file. If the object 526 // file is opened successfully, returns the file descriptor. Otherwise, 527 // returns -1. |out_file_name_size| is the size of the file name buffer 528 // (including the null terminator). 529 // IMPORTANT: This function must be async-signal-safe because it can be 530 // called from a signal handler (symbolizing stack frames for a crash). 531 static int OpenObjectFileContainingPc(uint64_t pc, uint64_t& start_address, 532 uint64_t& base_address, char* file_path, 533 int file_path_size) { 534 // This method can only be called after the singleton is instantiated. 535 // This is ensured by the following facts: 536 // * This is the only static method in this class, it is private, and 537 // the class has no friends (except for the DefaultSingletonTraits). 538 // The compiler guarantees that it can only be called after the 539 // singleton is instantiated. 540 // * This method is used as a callback for the stack tracing code and 541 // the callback registration is done in the constructor, so logically 542 // it cannot be called before the singleton is created. 543 SandboxSymbolizeHelper* instance = GetInstance(); 544 545 // The assumption here is that iterating over 546 // std::vector<MappedMemoryRegion> using a const_iterator does not allocate 547 // dynamic memory, hence it is async-signal-safe. 548 std::vector<MappedMemoryRegion>::const_iterator it; 549 bool is_first = true; 550 for (it = instance->regions_.begin(); it != instance->regions_.end(); 551 ++it, is_first = false) { 552 const MappedMemoryRegion& region = *it; 553 if (region.start <= pc && pc < region.end) { 554 start_address = region.start; 555 // Don't subtract 'start_address' from the first entry: 556 // * If a binary is compiled w/o -pie, then the first entry in 557 // process maps is likely the binary itself (all dynamic libs 558 // are mapped higher in address space). For such a binary, 559 // instruction offset in binary coincides with the actual 560 // instruction address in virtual memory (as code section 561 // is mapped to a fixed memory range). 562 // * If a binary is compiled with -pie, all the modules are 563 // mapped high at address space (in particular, higher than 564 // shadow memory of the tool), so the module can't be the 565 // first entry. 566 base_address = (is_first ? 0U : start_address) - region.offset; 567 if (file_path && file_path_size > 0) { 568 strncpy(file_path, region.path.c_str(), file_path_size); 569 // Ensure null termination. 570 file_path[file_path_size - 1] = '\0'; 571 } 572 return instance->GetFileDescriptor(region.path.c_str()); 573 } 574 } 575 return -1; 576 } 577 578 // Parses /proc/self/maps in order to compile a list of all object file names 579 // for the modules that are loaded in the current process. 580 // Returns true on success. 581 bool CacheMemoryRegions() { 582 // Reads /proc/self/maps. 583 std::string contents; 584 if (!ReadProcMaps(&contents)) { 585 LOG(ERROR) << "Failed to read /proc/self/maps"; 586 return false; 587 } 588 589 // Parses /proc/self/maps. 590 if (!ParseProcMaps(contents, ®ions_)) { 591 LOG(ERROR) << "Failed to parse the contents of /proc/self/maps"; 592 return false; 593 } 594 595 is_initialized_ = true; 596 return true; 597 } 598 599 // Opens all object files and caches their file descriptors. 600 void OpenSymbolFiles() { 601 // Pre-opening and caching the file descriptors of all loaded modules is 602 // not safe for production builds. Hence it is only done in non-official 603 // builds. For more details, take a look at: http://crbug.com/341966. 604#if !defined(OFFICIAL_BUILD) 605 // Open the object files for all read-only executable regions and cache 606 // their file descriptors. 607 std::vector<MappedMemoryRegion>::const_iterator it; 608 for (it = regions_.begin(); it != regions_.end(); ++it) { 609 const MappedMemoryRegion& region = *it; 610 // Only interesed in read-only executable regions. 611 if ((region.permissions & MappedMemoryRegion::READ) == 612 MappedMemoryRegion::READ && 613 (region.permissions & MappedMemoryRegion::WRITE) == 0 && 614 (region.permissions & MappedMemoryRegion::EXECUTE) == 615 MappedMemoryRegion::EXECUTE) { 616 if (region.path.empty()) { 617 // Skip regions with empty file names. 618 continue; 619 } 620 if (region.path[0] == '[') { 621 // Skip pseudo-paths, like [stack], [vdso], [heap], etc ... 622 continue; 623 } 624 // Avoid duplicates. 625 if (modules_.find(region.path) == modules_.end()) { 626 int fd = open(region.path.c_str(), O_RDONLY | O_CLOEXEC); 627 if (fd >= 0) { 628 modules_.insert(std::make_pair(region.path, fd)); 629 } else { 630 LOG(WARNING) << "Failed to open file: " << region.path 631 << "\n Error: " << strerror(errno); 632 } 633 } 634 } 635 } 636#endif // !defined(OFFICIAL_BUILD) 637 } 638 639 // Initializes and installs the symbolization callback. 640 void Init() { 641 if (CacheMemoryRegions()) { 642 OpenSymbolFiles(); 643 google::InstallSymbolizeOpenObjectFileCallback( 644 &OpenObjectFileContainingPc); 645 } 646 } 647 648 // Unregister symbolization callback. 649 void UnregisterCallback() { 650 if (is_initialized_) { 651 google::InstallSymbolizeOpenObjectFileCallback(NULL); 652 is_initialized_ = false; 653 } 654 } 655 656 // Closes all file descriptors owned by this instance. 657 void CloseObjectFiles() { 658#if !defined(OFFICIAL_BUILD) 659 std::map<std::string, int>::iterator it; 660 for (it = modules_.begin(); it != modules_.end(); ++it) { 661 int ret = IGNORE_EINTR(close(it->second)); 662 DCHECK(!ret); 663 it->second = -1; 664 } 665 modules_.clear(); 666#endif // !defined(OFFICIAL_BUILD) 667 } 668 669 // Set to true upon successful initialization. 670 bool is_initialized_; 671 672#if !defined(OFFICIAL_BUILD) 673 // Mapping from file name to file descriptor. Includes file descriptors 674 // for all successfully opened object files and the file descriptor for 675 // /proc/self/maps. This code is not safe for production builds. 676 std::map<std::string, int> modules_; 677#endif // !defined(OFFICIAL_BUILD) 678 679 // Cache for the process memory regions. Produced by parsing the contents 680 // of /proc/self/maps cache. 681 std::vector<MappedMemoryRegion> regions_; 682 683 DISALLOW_COPY_AND_ASSIGN(SandboxSymbolizeHelper); 684}; 685#endif // USE_SYMBOLIZE 686 687bool EnableInProcessStackDumping() { 688#if defined(USE_SYMBOLIZE) 689 SandboxSymbolizeHelper::GetInstance(); 690#endif // USE_SYMBOLIZE 691 692 // When running in an application, our code typically expects SIGPIPE 693 // to be ignored. Therefore, when testing that same code, it should run 694 // with SIGPIPE ignored as well. 695 struct sigaction sigpipe_action; 696 memset(&sigpipe_action, 0, sizeof(sigpipe_action)); 697 sigpipe_action.sa_handler = SIG_IGN; 698 sigemptyset(&sigpipe_action.sa_mask); 699 bool success = (sigaction(SIGPIPE, &sigpipe_action, NULL) == 0); 700 701 // Avoid hangs during backtrace initialization, see above. 702 WarmUpBacktrace(); 703 704 struct sigaction action; 705 memset(&action, 0, sizeof(action)); 706 action.sa_flags = SA_RESETHAND | SA_SIGINFO; 707 action.sa_sigaction = &StackDumpSignalHandler; 708 sigemptyset(&action.sa_mask); 709 710 success &= (sigaction(SIGILL, &action, NULL) == 0); 711 success &= (sigaction(SIGABRT, &action, NULL) == 0); 712 success &= (sigaction(SIGFPE, &action, NULL) == 0); 713 success &= (sigaction(SIGBUS, &action, NULL) == 0); 714 success &= (sigaction(SIGSEGV, &action, NULL) == 0); 715// On Linux, SIGSYS is reserved by the kernel for seccomp-bpf sandboxing. 716#if !defined(OS_LINUX) 717 success &= (sigaction(SIGSYS, &action, NULL) == 0); 718#endif // !defined(OS_LINUX) 719 720 return success; 721} 722 723StackTrace::StackTrace() { 724 // NOTE: This code MUST be async-signal safe (it's used by in-process 725 // stack dumping signal handler). NO malloc or stdio is allowed here. 726 727#if !defined(__UCLIBC__) 728 // Though the backtrace API man page does not list any possible negative 729 // return values, we take no chance. 730 count_ = base::saturated_cast<size_t>(backtrace(trace_, arraysize(trace_))); 731#else 732 count_ = 0; 733#endif 734} 735 736void StackTrace::Print() const { 737 // NOTE: This code MUST be async-signal safe (it's used by in-process 738 // stack dumping signal handler). NO malloc or stdio is allowed here. 739 740#if !defined(__UCLIBC__) 741 PrintBacktraceOutputHandler handler; 742 ProcessBacktrace(trace_, count_, &handler); 743#endif 744} 745 746#if !defined(__UCLIBC__) 747void StackTrace::OutputToStream(std::ostream* os) const { 748 StreamBacktraceOutputHandler handler(os); 749 ProcessBacktrace(trace_, count_, &handler); 750} 751#endif 752 753namespace internal { 754 755// NOTE: code from sandbox/linux/seccomp-bpf/demo.cc. 756char* itoa_r(intptr_t i, char* buf, size_t sz, int base, size_t padding) { 757 // Make sure we can write at least one NUL byte. 758 size_t n = 1; 759 if (n > sz) 760 return NULL; 761 762 if (base < 2 || base > 16) { 763 buf[0] = '\000'; 764 return NULL; 765 } 766 767 char* start = buf; 768 769 uintptr_t j = i; 770 771 // Handle negative numbers (only for base 10). 772 if (i < 0 && base == 10) { 773 // This does "j = -i" while avoiding integer overflow. 774 j = static_cast<uintptr_t>(-(i + 1)) + 1; 775 776 // Make sure we can write the '-' character. 777 if (++n > sz) { 778 buf[0] = '\000'; 779 return NULL; 780 } 781 *start++ = '-'; 782 } 783 784 // Loop until we have converted the entire number. Output at least one 785 // character (i.e. '0'). 786 char* ptr = start; 787 do { 788 // Make sure there is still enough space left in our output buffer. 789 if (++n > sz) { 790 buf[0] = '\000'; 791 return NULL; 792 } 793 794 // Output the next digit. 795 *ptr++ = "0123456789abcdef"[j % base]; 796 j /= base; 797 798 if (padding > 0) 799 padding--; 800 } while (j > 0 || padding > 0); 801 802 // Terminate the output with a NUL character. 803 *ptr = '\000'; 804 805 // Conversion to ASCII actually resulted in the digits being in reverse 806 // order. We can't easily generate them in forward order, as we can't tell 807 // the number of characters needed until we are done converting. 808 // So, now, we reverse the string (except for the possible "-" sign). 809 while (--ptr > start) { 810 char ch = *ptr; 811 *ptr = *start; 812 *start++ = ch; 813 } 814 return buf; 815} 816 817} // namespace internal 818 819} // namespace debug 820} // namespace base 821