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_placement_new.h" 16 #include "sanitizer_stacktrace.h" 17 #include "sanitizer_stacktrace_printer.h" 18 #include "sanitizer_symbolizer.h" 19 20 namespace __sanitizer { 21 22 void StackTrace::Print() const { 23 if (trace == nullptr || size == 0) { 24 Printf(" <empty stack>\n\n"); 25 return; 26 } 27 InternalScopedString frame_desc(GetPageSizeCached() * 2); 28 InternalScopedString dedup_token(GetPageSizeCached()); 29 int dedup_frames = common_flags()->dedup_token_length; 30 uptr frame_num = 0; 31 for (uptr i = 0; i < size && trace[i]; i++) { 32 // PCs in stack traces are actually the return addresses, that is, 33 // addresses of the next instructions after the call. 34 uptr pc = GetPreviousInstructionPc(trace[i]); 35 SymbolizedStack *frames = Symbolizer::GetOrInit()->SymbolizePC(pc); 36 CHECK(frames); 37 for (SymbolizedStack *cur = frames; cur; cur = cur->next) { 38 frame_desc.clear(); 39 RenderFrame(&frame_desc, common_flags()->stack_trace_format, frame_num++, 40 cur->info, common_flags()->symbolize_vs_style, 41 common_flags()->strip_path_prefix); 42 Printf("%s\n", frame_desc.data()); 43 if (dedup_frames-- > 0) { 44 if (dedup_token.length()) 45 dedup_token.append("--"); 46 dedup_token.append(cur->info.function); 47 } 48 } 49 frames->ClearAll(); 50 } 51 // Always print a trailing empty line after stack trace. 52 Printf("\n"); 53 if (dedup_token.length()) 54 Printf("DEDUP_TOKEN: %s\n", dedup_token.data()); 55 } 56 57 void BufferedStackTrace::Unwind(u32 max_depth, uptr pc, uptr bp, void *context, 58 uptr stack_top, uptr stack_bottom, 59 bool request_fast_unwind) { 60 top_frame_bp = (max_depth > 0) ? bp : 0; 61 // Avoid doing any work for small max_depth. 62 if (max_depth == 0) { 63 size = 0; 64 return; 65 } 66 if (max_depth == 1) { 67 size = 1; 68 trace_buffer[0] = pc; 69 return; 70 } 71 if (!WillUseFastUnwind(request_fast_unwind)) { 72 #if SANITIZER_CAN_SLOW_UNWIND 73 if (context) 74 SlowUnwindStackWithContext(pc, context, max_depth); 75 else 76 SlowUnwindStack(pc, max_depth); 77 #else 78 UNREACHABLE("slow unwind requested but not available"); 79 #endif 80 } else { 81 FastUnwindStack(pc, bp, stack_top, stack_bottom, max_depth); 82 } 83 } 84 85 } // namespace __sanitizer 86