stack_trace_posix.cc revision 116680a4aac90f2aa7413d9095a592090648e557
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
48namespace base {
49namespace debug {
50
51namespace {
52
53volatile 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
58const 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
62const 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]"
72void 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
117class BacktraceOutputHandler {
118 public:
119  virtual void HandleOutput(const char* output) = 0;
120
121 protected:
122  virtual ~BacktraceOutputHandler() {}
123};
124
125void 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)
136void 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
147void 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
202void 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
208void 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
401class 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
415class 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
430void 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.
476class 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
699bool EnableInProcessStackDumpingForSandbox() {
700#if defined(USE_SYMBOLIZE)
701  SandboxSymbolizeHelper::GetInstance();
702#endif  // USE_SYMBOLIZE
703
704  return EnableInProcessStackDumping();
705}
706
707bool 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
739StackTrace::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
752void 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__)
763void StackTrace::OutputToStream(std::ostream* os) const {
764  StreamBacktraceOutputHandler handler(os);
765  ProcessBacktrace(trace_, count_, &handler);
766}
767#endif
768
769namespace internal {
770
771// NOTE: code from sandbox/linux/seccomp-bpf/demo.cc.
772char *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