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