• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
50 namespace base {
51 namespace debug {
52 
53 namespace {
54 
55 volatile 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
60 const 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
64 const 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__)
DemangleSymbols(std::string * text)75 void 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__)
DemangleSymbols(std::string *)114 void DemangleSymbols(std::string* /* text */) {}
115 #endif  // defined(__GLIBCXX__) && !defined(__UCLIBC__)
116 
117 #endif  // !defined(USE_SYMBOLIZE)
118 
119 class BacktraceOutputHandler {
120  public:
121   virtual void HandleOutput(const char* output) = 0;
122 
123  protected:
~BacktraceOutputHandler()124   virtual ~BacktraceOutputHandler() {}
125 };
126 
127 #if defined(USE_SYMBOLIZE) || !defined(__UCLIBC__)
OutputPointer(void * pointer,BacktraceOutputHandler * handler)128 void 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)
OutputFrameId(intptr_t frame_id,BacktraceOutputHandler * handler)140 void 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__)
ProcessBacktrace(void * const * trace,size_t size,BacktraceOutputHandler * handler)152 void 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 
PrintToStderr(const char * output)211 void 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 
StackDumpSignalHandler(int signal,siginfo_t * info,void * void_context)217 void 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 
394 class PrintBacktraceOutputHandler : public BacktraceOutputHandler {
395  public:
PrintBacktraceOutputHandler()396   PrintBacktraceOutputHandler() {}
397 
HandleOutput(const char * output)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 
408 class StreamBacktraceOutputHandler : public BacktraceOutputHandler {
409  public:
StreamBacktraceOutputHandler(std::ostream * os)410   explicit StreamBacktraceOutputHandler(std::ostream* os) : os_(os) {
411   }
412 
HandleOutput(const char * output)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 
WarmUpBacktrace()421 void 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.
467 class SandboxSymbolizeHelper {
468  public:
469   // Returns the singleton instance.
GetInstance()470   static SandboxSymbolizeHelper* GetInstance() {
471     return Singleton<SandboxSymbolizeHelper>::get();
472   }
473 
474  private:
475   friend struct DefaultSingletonTraits<SandboxSymbolizeHelper>;
476 
SandboxSymbolizeHelper()477   SandboxSymbolizeHelper()
478       : is_initialized_(false) {
479     Init();
480   }
481 
~SandboxSymbolizeHelper()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).
GetFileDescriptor(const char * file_path)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).
OpenObjectFileContainingPc(uint64_t pc,uint64_t & start_address,uint64_t & base_address,char * file_path,int file_path_size)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.
CacheMemoryRegions()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, &regions_)) {
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.
OpenSymbolFiles()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.
Init()640   void Init() {
641     if (CacheMemoryRegions()) {
642       OpenSymbolFiles();
643       google::InstallSymbolizeOpenObjectFileCallback(
644           &OpenObjectFileContainingPc);
645     }
646   }
647 
648   // Unregister symbolization callback.
UnregisterCallback()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.
CloseObjectFiles()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 
EnableInProcessStackDumping()687 bool 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 
StackTrace()723 StackTrace::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 
Print() const736 void 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__)
OutputToStream(std::ostream * os) const747 void StackTrace::OutputToStream(std::ostream* os) const {
748   StreamBacktraceOutputHandler handler(os);
749   ProcessBacktrace(trace_, count_, &handler);
750 }
751 #endif
752 
753 namespace internal {
754 
755 // NOTE: code from sandbox/linux/seccomp-bpf/demo.cc.
itoa_r(intptr_t i,char * buf,size_t sz,int base,size_t padding)756 char* 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