• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- sanitizer_stacktrace_libcdep.cc -----------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is shared between AddressSanitizer and ThreadSanitizer
11 // run-time libraries.
12 //===----------------------------------------------------------------------===//
13 
14 #include "sanitizer_common.h"
15 #include "sanitizer_stacktrace.h"
16 #include "sanitizer_symbolizer.h"
17 
18 namespace __sanitizer {
19 
PrintStackFramePrefix(InternalScopedString * buffer,uptr frame_num,uptr pc)20 static void PrintStackFramePrefix(InternalScopedString *buffer, uptr frame_num,
21                                   uptr pc) {
22   buffer->append("    #%zu 0x%zx", frame_num, pc);
23 }
24 
PrintStack(const uptr * addr,uptr size)25 void StackTrace::PrintStack(const uptr *addr, uptr size) {
26   if (addr == 0 || size == 0) {
27     Printf("    <empty stack>\n\n");
28     return;
29   }
30   InternalScopedBuffer<char> buff(GetPageSizeCached() * 2);
31   InternalScopedBuffer<AddressInfo> addr_frames(64);
32   InternalScopedString frame_desc(GetPageSizeCached() * 2);
33   uptr frame_num = 0;
34   for (uptr i = 0; i < size && addr[i]; i++) {
35     // PCs in stack traces are actually the return addresses, that is,
36     // addresses of the next instructions after the call.
37     uptr pc = GetPreviousInstructionPc(addr[i]);
38     uptr addr_frames_num = Symbolizer::GetOrInit()->SymbolizePC(
39         pc, addr_frames.data(), addr_frames.size());
40     if (addr_frames_num == 0) {
41       frame_desc.clear();
42       PrintStackFramePrefix(&frame_desc, frame_num, pc);
43       frame_desc.append(" (<unknown module>)");
44       Printf("%s\n", frame_desc.data());
45       frame_num++;
46       continue;
47     }
48     for (uptr j = 0; j < addr_frames_num; j++) {
49       AddressInfo &info = addr_frames[j];
50       frame_desc.clear();
51       PrintStackFramePrefix(&frame_desc, frame_num, pc);
52       if (info.function) {
53         frame_desc.append(" in %s", info.function);
54         // Print offset in function if we don't know the source file.
55         if (!info.file && info.function_offset != AddressInfo::kUnknown)
56           frame_desc.append("+0x%zx", info.function_offset);
57       }
58       if (info.file) {
59         frame_desc.append(" ");
60         PrintSourceLocation(&frame_desc, info.file, info.line, info.column);
61       } else if (info.module) {
62         frame_desc.append(" ");
63         PrintModuleAndOffset(&frame_desc, info.module, info.module_offset);
64       }
65       Printf("%s\n", frame_desc.data());
66       frame_num++;
67       info.Clear();
68     }
69   }
70   // Always print a trailing empty line after stack trace.
71   Printf("\n");
72 }
73 
Unwind(uptr max_depth,uptr pc,uptr bp,void * context,uptr stack_top,uptr stack_bottom,bool request_fast_unwind)74 void StackTrace::Unwind(uptr max_depth, uptr pc, uptr bp, void *context,
75                         uptr stack_top, uptr stack_bottom,
76                         bool request_fast_unwind) {
77   top_frame_bp = (max_depth > 0) ? bp : 0;
78   // Avoid doing any work for small max_depth.
79   if (max_depth == 0) {
80     size = 0;
81     return;
82   }
83   if (max_depth == 1) {
84     size = 1;
85     trace[0] = pc;
86     return;
87   }
88   if (!WillUseFastUnwind(request_fast_unwind)) {
89     if (context)
90       SlowUnwindStackWithContext(pc, context, max_depth);
91     else
92       SlowUnwindStack(pc, max_depth);
93   } else {
94     FastUnwindStack(pc, bp, stack_top, stack_bottom, max_depth);
95   }
96 }
97 
98 }  // namespace __sanitizer
99