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