1//===-- sanitizer_stacktrace_libcdep.cc -----------------------------------===// 2// 3// This file is distributed under the University of Illinois Open Source 4// License. See LICENSE.TXT for details. 5// 6//===----------------------------------------------------------------------===// 7// 8// This file is shared between AddressSanitizer and ThreadSanitizer 9// run-time libraries. 10//===----------------------------------------------------------------------===// 11 12#include "sanitizer_common.h" 13#include "sanitizer_placement_new.h" 14#include "sanitizer_stacktrace.h" 15#include "sanitizer_stacktrace_printer.h" 16#include "sanitizer_symbolizer.h" 17 18namespace __sanitizer { 19 20void StackTrace::Print() const { 21 if (trace == nullptr || size == 0) { 22 Printf(" <empty stack>\n\n"); 23 return; 24 } 25 const int kMaxAddrFrames = 64; 26 InternalScopedBuffer<AddressInfo> addr_frames(kMaxAddrFrames); 27 for (uptr i = 0; i < kMaxAddrFrames; i++) 28 new(&addr_frames[i]) AddressInfo(); 29 InternalScopedString frame_desc(GetPageSizeCached() * 2); 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 uptr addr_frames_num = Symbolizer::GetOrInit()->SymbolizePC( 36 pc, addr_frames.data(), kMaxAddrFrames); 37 if (addr_frames_num == 0) { 38 addr_frames[0].address = pc; 39 addr_frames_num = 1; 40 } 41 for (uptr j = 0; j < addr_frames_num; j++) { 42 AddressInfo &info = addr_frames[j]; 43 frame_desc.clear(); 44 RenderFrame(&frame_desc, common_flags()->stack_trace_format, frame_num++, 45 info, common_flags()->strip_path_prefix); 46 Printf("%s\n", frame_desc.data()); 47 info.Clear(); 48 } 49 } 50 // Always print a trailing empty line after stack trace. 51 Printf("\n"); 52} 53 54void BufferedStackTrace::Unwind(uptr max_depth, uptr pc, uptr bp, void *context, 55 uptr stack_top, uptr stack_bottom, 56 bool request_fast_unwind) { 57 top_frame_bp = (max_depth > 0) ? bp : 0; 58 // Avoid doing any work for small max_depth. 59 if (max_depth == 0) { 60 size = 0; 61 return; 62 } 63 if (max_depth == 1) { 64 size = 1; 65 trace_buffer[0] = pc; 66 return; 67 } 68 if (!WillUseFastUnwind(request_fast_unwind)) { 69 if (context) 70 SlowUnwindStackWithContext(pc, context, max_depth); 71 else 72 SlowUnwindStack(pc, max_depth); 73 } else { 74 FastUnwindStack(pc, bp, stack_top, stack_bottom, max_depth); 75 } 76} 77 78} // namespace __sanitizer 79