Index: compiler-rt/trunk/lib/asan/asan_errors.cc =================================================================== --- compiler-rt/trunk/lib/asan/asan_errors.cc +++ compiler-rt/trunk/lib/asan/asan_errors.cc @@ -35,7 +35,7 @@ // corresponding code in the sanitizer_common and we use this callback to // print it. static_cast(callback_context)->Print(); - GetStackTrace(stack, kStackTraceMax, sig.pc, sig.bp, sig.context, fast); + stack->Unwind(sig.pc, sig.bp, sig.context, fast); } void ErrorDeadlySignal::Print() { Index: compiler-rt/trunk/lib/asan/asan_stack.h =================================================================== --- compiler-rt/trunk/lib/asan/asan_stack.h +++ compiler-rt/trunk/lib/asan/asan_stack.h @@ -42,19 +42,19 @@ if (max_size > 1) stack.trace_buffer[1] = GET_CALLER_PC(); \ } \ } else { \ - GetStackTrace(&stack, max_size, StackTrace::GetCurrentPc(), \ - GET_CURRENT_FRAME(), 0, fast); \ + stack.Unwind(StackTrace::GetCurrentPc(), \ + GET_CURRENT_FRAME(), nullptr, fast, max_size); \ } #define GET_STACK_TRACE_FATAL(pc, bp) \ BufferedStackTrace stack; \ - GetStackTrace(&stack, kStackTraceMax, pc, bp, 0, \ - common_flags()->fast_unwind_on_fatal) + stack.Unwind(pc, bp, nullptr, \ + common_flags()->fast_unwind_on_fatal) #define GET_STACK_TRACE_SIGNAL(sig) \ BufferedStackTrace stack; \ - GetStackTrace(&stack, kStackTraceMax, (sig).pc, (sig).bp, (sig).context, \ - common_flags()->fast_unwind_on_fatal) + stack.Unwind((sig).pc, (sig).bp, (sig).context, \ + common_flags()->fast_unwind_on_fatal) #define GET_STACK_TRACE_FATAL_HERE \ GET_STACK_TRACE(kStackTraceMax, common_flags()->fast_unwind_on_fatal) Index: compiler-rt/trunk/lib/hwasan/hwasan.h =================================================================== --- compiler-rt/trunk/lib/hwasan/hwasan.h +++ compiler-rt/trunk/lib/hwasan/hwasan.h @@ -112,16 +112,15 @@ #define GET_MALLOC_STACK_TRACE \ BufferedStackTrace stack; \ - if (hwasan_inited) \ - GetStackTrace(&stack, common_flags()->malloc_context_size, \ - StackTrace::GetCurrentPc(), GET_CURRENT_FRAME(), nullptr, \ - common_flags()->fast_unwind_on_malloc) + if (hwasan_inited) \ + stack.Unwind(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME(), \ + nullptr, common_flags()->fast_unwind_on_malloc, \ + common_flags()->malloc_context_size) #define GET_FATAL_STACK_TRACE_PC_BP(pc, bp) \ BufferedStackTrace stack; \ - if (hwasan_inited) \ - GetStackTrace(&stack, kStackTraceMax, pc, bp, nullptr, \ - common_flags()->fast_unwind_on_fatal) + if (hwasan_inited) \ + stack.Unwind(pc, bp, nullptr, common_flags()->fast_unwind_on_fatal) #define GET_FATAL_STACK_TRACE_HERE \ GET_FATAL_STACK_TRACE_PC_BP(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME()) Index: compiler-rt/trunk/lib/hwasan/hwasan_linux.cpp =================================================================== --- compiler-rt/trunk/lib/hwasan/hwasan_linux.cpp +++ compiler-rt/trunk/lib/hwasan/hwasan_linux.cpp @@ -378,8 +378,7 @@ InternalMmapVector stack_buffer(1); BufferedStackTrace *stack = stack_buffer.data(); stack->Reset(); - GetStackTrace(stack, kStackTraceMax, pc, frame, uc, - common_flags()->fast_unwind_on_fatal); + stack->Unwind(pc, frame, uc, common_flags()->fast_unwind_on_fatal); bool fatal = flags()->halt_on_error || !ai.recover; ReportTagMismatch(stack, ai.addr, ai.size, ai.is_store, fatal); @@ -417,8 +416,8 @@ static void OnStackUnwind(const SignalContext &sig, const void *, BufferedStackTrace *stack) { - GetStackTrace(stack, kStackTraceMax, StackTrace::GetNextInstructionPc(sig.pc), - sig.bp, sig.context, common_flags()->fast_unwind_on_fatal); + stack->Unwind(StackTrace::GetNextInstructionPc(sig.pc), sig.bp, sig.context, + common_flags()->fast_unwind_on_fatal); } void HwasanOnDeadlySignal(int signo, void *info, void *context) { Index: compiler-rt/trunk/lib/lsan/lsan.h =================================================================== --- compiler-rt/trunk/lib/lsan/lsan.h +++ compiler-rt/trunk/lib/lsan/lsan.h @@ -17,8 +17,8 @@ #define GET_STACK_TRACE(max_size, fast) \ __sanitizer::BufferedStackTrace stack; \ - GetStackTrace(&stack, max_size, StackTrace::GetCurrentPc(), \ - GET_CURRENT_FRAME(), nullptr, fast); + stack.Unwind(StackTrace::GetCurrentPc(), \ + GET_CURRENT_FRAME(), nullptr, fast, max_size); #define GET_STACK_TRACE_FATAL \ GET_STACK_TRACE(kStackTraceMax, common_flags()->fast_unwind_on_fatal) Index: compiler-rt/trunk/lib/lsan/lsan.cc =================================================================== --- compiler-rt/trunk/lib/lsan/lsan.cc +++ compiler-rt/trunk/lib/lsan/lsan.cc @@ -89,7 +89,7 @@ static void OnStackUnwind(const SignalContext &sig, const void *, BufferedStackTrace *stack) { - GetStackTrace(stack, kStackTraceMax, sig.pc, sig.bp, sig.context, + stack->Unwind(sig.pc, sig.bp, sig.context, common_flags()->fast_unwind_on_fatal); } Index: compiler-rt/trunk/lib/msan/msan.h =================================================================== --- compiler-rt/trunk/lib/msan/msan.h +++ compiler-rt/trunk/lib/msan/msan.h @@ -325,23 +325,21 @@ #define GET_MALLOC_STACK_TRACE \ BufferedStackTrace stack; \ if (__msan_get_track_origins() && msan_inited) \ - GetStackTrace(&stack, common_flags()->malloc_context_size, \ - StackTrace::GetCurrentPc(), GET_CURRENT_FRAME(), nullptr, \ - common_flags()->fast_unwind_on_malloc) + stack.Unwind(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME(), \ + nullptr, common_flags()->fast_unwind_on_malloc, \ + common_flags()->malloc_context_size) // For platforms which support slow unwinder only, we restrict the store context // size to 1, basically only storing the current pc. We do this because the slow // unwinder which is based on libunwind is not async signal safe and causes // random freezes in forking applications as well as in signal handlers. -#define GET_STORE_STACK_TRACE_PC_BP(pc, bp) \ - BufferedStackTrace stack; \ - if (__msan_get_track_origins() > 1 && msan_inited) { \ - if (!SANITIZER_CAN_FAST_UNWIND) \ - GetStackTrace(&stack, Min(1, flags()->store_context_size), pc, bp, \ - nullptr, false); \ - else \ - GetStackTrace(&stack, flags()->store_context_size, pc, bp, nullptr, \ - common_flags()->fast_unwind_on_malloc); \ +#define GET_STORE_STACK_TRACE_PC_BP(pc, bp) \ + BufferedStackTrace stack; \ + if (__msan_get_track_origins() > 1 && msan_inited) { \ + int size = flags()->store_context_size; \ + if (!SANITIZER_CAN_FAST_UNWIND) \ + size = Min(size, 1); \ + stack.Unwind(pc, bp, nullptr, common_flags()->fast_unwind_on_malloc, size);\ } #define GET_STORE_STACK_TRACE \ @@ -350,8 +348,7 @@ #define GET_FATAL_STACK_TRACE_PC_BP(pc, bp) \ BufferedStackTrace stack; \ if (msan_inited) \ - GetStackTrace(&stack, kStackTraceMax, pc, bp, nullptr, \ - common_flags()->fast_unwind_on_fatal) + stack.Unwind(pc, bp, nullptr, common_flags()->fast_unwind_on_fatal) #define GET_FATAL_STACK_TRACE_HERE \ GET_FATAL_STACK_TRACE_PC_BP(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME()) Index: compiler-rt/trunk/lib/msan/msan.cc =================================================================== --- compiler-rt/trunk/lib/msan/msan.cc +++ compiler-rt/trunk/lib/msan/msan.cc @@ -382,7 +382,7 @@ static void OnStackUnwind(const SignalContext &sig, const void *, BufferedStackTrace *stack) { - GetStackTrace(stack, kStackTraceMax, sig.pc, sig.bp, sig.context, + stack->Unwind(sig.pc, sig.bp, sig.context, common_flags()->fast_unwind_on_fatal); } Index: compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace.h =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace.h +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace.h @@ -16,6 +16,13 @@ namespace __sanitizer { +struct BufferedStackTrace; +// Get the stack trace with the given pc and bp. +// The pc will be in the position 0 of the resulting stack trace. +// The bp may refer to the current frame or to the caller's frame. +void GetStackTrace(BufferedStackTrace *stack, uptr max_depth, uptr pc, uptr bp, + void *context, bool request_fast_unwind); + static const u32 kStackTraceMax = 256; #if defined(__sparc__) || (SANITIZER_LINUX && defined(__mips__)) @@ -96,6 +103,20 @@ BufferedStackTrace() : StackTrace(trace_buffer, 0), top_frame_bp(0) {} void Init(const uptr *pcs, uptr cnt, uptr extra_top_pc = 0); + + void Unwind(uptr pc, uptr bp, void *context, bool request_fast, + u32 max_depth = kStackTraceMax) { + top_frame_bp = (max_depth > 0) ? bp : 0; + // Small max_depth optimization + if (max_depth <= 1) { + if (max_depth == 1) + trace_buffer[0] = pc; + size = max_depth; + return; + } + GetStackTrace(this, max_depth, pc, bp, context, request_fast); + } + void Unwind(u32 max_depth, uptr pc, uptr bp, void *context, uptr stack_top, uptr stack_bottom, bool request_fast_unwind); @@ -121,31 +142,27 @@ return frame > stack_bottom && frame < stack_top - 2 * sizeof (uhwptr); } -// Get the stack trace with the given pc and bp. -// The pc will be in the position 0 of the resulting stack trace. -// The bp may refer to the current frame or to the caller's frame. -void GetStackTrace(BufferedStackTrace *stack, uptr max_depth, uptr pc, uptr bp, - void *context, bool request_fast_unwind); - } // namespace __sanitizer // Use this macro if you want to print stack trace with the caller // of the current function in the top frame. -#define GET_CALLER_PC_BP_SP \ - uptr bp = GET_CURRENT_FRAME(); \ - uptr pc = GET_CALLER_PC(); \ - uptr local_stack; \ - uptr sp = (uptr)&local_stack - #define GET_CALLER_PC_BP \ uptr bp = GET_CURRENT_FRAME(); \ uptr pc = GET_CALLER_PC(); +#define GET_CALLER_PC_BP_SP \ + GET_CALLER_PC_BP; \ + uptr local_stack; \ + uptr sp = (uptr)&local_stack + // Use this macro if you want to print stack trace with the current // function in the top frame. -#define GET_CURRENT_PC_BP_SP \ +#define GET_CURRENT_PC_BP \ uptr bp = GET_CURRENT_FRAME(); \ - uptr pc = StackTrace::GetCurrentPc(); \ + uptr pc = StackTrace::GetCurrentPc() + +#define GET_CURRENT_PC_BP_SP \ + GET_CURRENT_PC_BP; \ uptr local_stack; \ uptr sp = (uptr)&local_stack Index: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_report.cc =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_report.cc +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_report.cc @@ -98,16 +98,9 @@ InternalMmapVector stack_buffer(1); BufferedStackTrace *stack = stack_buffer.data(); stack->Reset(); - uptr top = 0; - uptr bottom = 0; - GET_CALLER_PC_BP_SP; - (void)sp; - bool fast = common_flags()->fast_unwind_on_fatal; - if (StackTrace::WillUseFastUnwind(fast)) { - GetThreadStackTopAndBottom(false, &top, &bottom); - stack->Unwind(kStackTraceMax, pc, bp, nullptr, top, bottom, true); - } else - stack->Unwind(kStackTraceMax, pc, 0, nullptr, 0, 0, false); + + GET_CALLER_PC_BP; + stack->Unwind(pc, bp, nullptr, common_flags()->fast_unwind_on_fatal); Printf("%s", d.Warning()); Report("WARNING: %s: writable-executable page usage\n", SanitizerToolName); Index: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.cc =================================================================== --- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.cc +++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.cc @@ -328,14 +328,8 @@ #if !SANITIZER_GO static void OnStackUnwind(const SignalContext &sig, const void *, BufferedStackTrace *stack) { - uptr top = 0; - uptr bottom = 0; - bool fast = common_flags()->fast_unwind_on_fatal; - if (StackTrace::WillUseFastUnwind(fast)) { - GetThreadStackTopAndBottom(false, &top, &bottom); - stack->Unwind(kStackTraceMax, sig.pc, sig.bp, nullptr, top, bottom, true); - } else - stack->Unwind(kStackTraceMax, sig.pc, 0, sig.context, 0, 0, false); + stack->Unwind(sig.pc, sig.bp, sig.context, + common_flags()->fast_unwind_on_fatal); } static void TsanOnDeadlySignal(int signo, void *siginfo, void *context) { Index: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc =================================================================== --- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc +++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc @@ -729,18 +729,12 @@ ALWAYS_INLINE void PrintCurrentStackSlow(uptr pc) { #if !SANITIZER_GO - uptr bp = 0; - uptr top = 0; - uptr bottom = 0; + uptr bp = GET_CURRENT_FRAME(); BufferedStackTrace *ptrace = new(internal_alloc(MBlockStackTrace, sizeof(BufferedStackTrace))) BufferedStackTrace(); - if (__sanitizer::StackTrace::WillUseFastUnwind(false)) { - bp = GET_CURRENT_FRAME(); - __sanitizer::GetThreadStackTopAndBottom(false, &top, &bottom); - ptrace->Unwind(kStackTraceMax, pc, bp, nullptr, top, bottom, true); - } else - ptrace->Unwind(kStackTraceMax, pc, 0, nullptr, 0, 0, false); + ptrace->Unwind(pc, bp, nullptr, false); + for (uptr i = 0; i < ptrace->size / 2; i++) { uptr tmp = ptrace->trace_buffer[i]; ptrace->trace_buffer[i] = ptrace->trace_buffer[ptrace->size - i - 1]; Index: compiler-rt/trunk/lib/ubsan/ubsan_diag_standalone.cc =================================================================== --- compiler-rt/trunk/lib/ubsan/ubsan_diag_standalone.cc +++ compiler-rt/trunk/lib/ubsan/ubsan_diag_standalone.cc @@ -16,21 +16,23 @@ using namespace __ubsan; +void __sanitizer::GetStackTrace(BufferedStackTrace *stack, uptr max_depth, + uptr pc, uptr bp, void *context, bool fast) { + uptr top = 0; + uptr bottom = 0; + if (StackTrace::WillUseFastUnwind(fast)) { + GetThreadStackTopAndBottom(false, &top, &bottom); + stack->Unwind(max_depth, pc, bp, nullptr, top, bottom, true); + } else + stack->Unwind(max_depth, pc, bp, context, 0, 0, false); +} + extern "C" { SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_print_stack_trace() { - uptr top = 0; - uptr bottom = 0; - bool request_fast_unwind = common_flags()->fast_unwind_on_fatal; - GET_CURRENT_PC_BP_SP; - (void)sp; + GET_CURRENT_PC_BP; BufferedStackTrace stack; - if (__sanitizer::StackTrace::WillUseFastUnwind(request_fast_unwind)) { - __sanitizer::GetThreadStackTopAndBottom(false, &top, &bottom); - stack.Unwind(kStackTraceMax, pc, bp, nullptr, top, bottom, true); - } else { - stack.Unwind(kStackTraceMax, pc, 0, nullptr, 0, 0, false); - } + stack.Unwind(pc, bp, nullptr, common_flags()->fast_unwind_on_fatal); stack.Print(); } } // extern "C"