diff --git a/compiler-rt/lib/asan/asan_stack.cc b/compiler-rt/lib/asan/asan_stack.cc --- a/compiler-rt/lib/asan/asan_stack.cc +++ b/compiler-rt/lib/asan/asan_stack.cc @@ -29,31 +29,34 @@ } // namespace __asan void __sanitizer::GetStackTrace(BufferedStackTrace *stack, uptr max_depth, - uptr pc, uptr bp, void *context, bool fast) { + uptr pc, uptr bp, void *context, + bool request_fast_unwind) { using namespace __asan; -#if SANITIZER_WINDOWS - stack->Unwind(max_depth, pc, 0, context, 0, 0, false); -#else - AsanThread *t; - stack->size = 0; - if (LIKELY(asan_inited)) { - if ((t = GetCurrentThread()) && !t->isUnwinding()) { - uptr stack_top = t->stack_top(); - uptr stack_bottom = t->stack_bottom(); - ScopedUnwinding unwind_scope(t); - if (!SANITIZER_MIPS || IsValidFrame(bp, stack_top, stack_bottom)) { - if (StackTrace::WillUseFastUnwind(fast)) - stack->Unwind(max_depth, pc, bp, nullptr, stack_top, stack_bottom, - true); - else - stack->Unwind(max_depth, pc, 0, context, 0, 0, false); - } - } else if (!t && !fast) { - /* If GetCurrentThread() has failed, try to do slow unwind anyways. */ - stack->Unwind(max_depth, pc, bp, context, 0, 0, false); - } + stack->size = 0; // TODO(yln): investigate why this is needed + + if (UNLIKELY(!asan_inited)) return; + + AsanThread *t = GetCurrentThread(); + if (t && t->isUnwinding()) return; + + // TODO(yln): no scope during "best effort" slow unwind without thread + // TODO(yln): use SymbolizerScope sym_scope; here instead of unwind_scope? + if (!t) { + MAYBE_UNWIND_SLOW(stack, pc, context, max_depth); + return; + } + + ScopedUnwinding unwind_scope(t); + if (StackTrace::WillUseFastUnwind(request_fast_unwind)) { + uptr top = t->stack_top(); + uptr bottom = t->stack_bottom(); + if (IsValidFrame(bp, top, bottom)) + UNWIND_FAST(stack, pc, bp, top, bottom, max_depth); + else + MAYBE_UNWIND_SLOW(stack, pc, context, max_depth); + } else { + UNWIND_SLOW(stack, pc, context, max_depth); } -#endif // SANITIZER_WINDOWS } // ------------------ Interface -------------- {{{1 diff --git a/compiler-rt/lib/hwasan/hwasan.cc b/compiler-rt/lib/hwasan/hwasan.cc --- a/compiler-rt/lib/hwasan/hwasan.cc +++ b/compiler-rt/lib/hwasan/hwasan.cc @@ -244,26 +244,25 @@ } // namespace __hwasan -void __sanitizer::GetStackTrace(BufferedStackTrace *stack, uptr max_s, uptr pc, - uptr bp, void *context, +void __sanitizer::GetStackTrace(BufferedStackTrace *stack, uptr max_depth, + uptr pc, uptr bp, void *context, bool request_fast_unwind) { using namespace __hwasan; + stack->size = 0; // TODO(yln): investigate why this is needed + Thread *t = GetCurrentThread(); - if (!t) { - // the thread is still being created. - stack->size = 0; - return; - } - if (!StackTrace::WillUseFastUnwind(request_fast_unwind)) { - // Block reports from our interceptors during _Unwind_Backtrace. - SymbolizerScope sym_scope; - return stack->Unwind(max_s, pc, bp, context, 0, 0, request_fast_unwind); + if (!t) return; + // TODO(yln): no attempt to slow unwind if we can't get current thread? + + SymbolizerScope sym_scope; + if (StackTrace::WillUseFastUnwind(request_fast_unwind)) { + uptr top = t->stack_top(); + uptr bottom = t->stack_bottom(); + // TODO(yln): no check for IsValidFrame ??? + UNWIND_FAST(stack, pc, bp, top, bottom, max_depth); + } else { + UNWIND_SLOW(stack, pc, context, max_depth); } - if (StackTrace::WillUseFastUnwind(request_fast_unwind)) - stack->Unwind(max_s, pc, bp, nullptr, t->stack_top(), t->stack_bottom(), - true); - else - stack->Unwind(max_s, pc, 0, context, 0, 0, false); } // Interface. diff --git a/compiler-rt/lib/lsan/lsan.cc b/compiler-rt/lib/lsan/lsan.cc --- a/compiler-rt/lib/lsan/lsan.cc +++ b/compiler-rt/lib/lsan/lsan.cc @@ -33,20 +33,26 @@ } // namespace __lsan void __sanitizer::GetStackTrace(BufferedStackTrace *stack, uptr max_depth, - uptr pc, uptr bp, void *context, bool fast) { + uptr pc, uptr bp, void *context, + bool request_fast_unwind) { using namespace __lsan; - uptr stack_top = 0, stack_bottom = 0; - ThreadContext *t; - if (StackTrace::WillUseFastUnwind(fast) && - (t = CurrentThreadContext())) { - stack_top = t->stack_end(); - stack_bottom = t->stack_begin(); + + ThreadContext *t = CurrentThreadContext(); + if (!t) { + MAYBE_UNWIND_SLOW(stack, pc, context, max_depth); + return; } - if (!SANITIZER_MIPS || IsValidFrame(bp, stack_top, stack_bottom)) { - if (StackTrace::WillUseFastUnwind(fast)) - stack->Unwind(max_depth, pc, bp, nullptr, stack_top, stack_bottom, true); + + // TODO(yln): No unwinding scope? + if (StackTrace::WillUseFastUnwind(request_fast_unwind)) { + uptr top = t->stack_end(); // TODO(yln): naming is end/begin + uptr bottom = t->stack_begin(); // instead of top/bottom + if (IsValidFrame(bp, top, bottom)) + UNWIND_FAST(stack, pc, bp, top, bottom, max_depth); else - stack->Unwind(max_depth, pc, 0, context, 0, 0, false); + MAYBE_UNWIND_SLOW(stack, pc, context, max_depth); + } else { + UNWIND_SLOW(stack, pc, context, max_depth); } } diff --git a/compiler-rt/lib/msan/msan.cc b/compiler-rt/lib/msan/msan.cc --- a/compiler-rt/lib/msan/msan.cc +++ b/compiler-rt/lib/msan/msan.cc @@ -301,21 +301,26 @@ } // namespace __msan -void __sanitizer::GetStackTrace(BufferedStackTrace *stack, uptr max_s, uptr pc, - uptr bp, void *context, +void __sanitizer::GetStackTrace(BufferedStackTrace *stack, uptr max_depth, + uptr pc, uptr bp, void *context, bool request_fast_unwind) { using namespace __msan; + SymbolizerScope sym_scope; + MsanThread *t = GetCurrentThread(); - if (!t || !StackTrace::WillUseFastUnwind(request_fast_unwind)) { - // Block reports from our interceptors during _Unwind_Backtrace. - SymbolizerScope sym_scope; - return stack->Unwind(max_s, pc, bp, context, 0, 0, false); + if (!t) { + MAYBE_UNWIND_SLOW(stack, pc, context, max_depth); + return; + } + + if (StackTrace::WillUseFastUnwind(request_fast_unwind)) { + uptr top = t->stack_top(); + uptr bottom = t->stack_bottom(); + // TODO(yln): no check for IsValidFrame ??? + UNWIND_FAST(stack, pc, bp, top, bottom, max_depth); + } else { + UNWIND_SLOW(stack, pc, context, max_depth); } - if (StackTrace::WillUseFastUnwind(request_fast_unwind)) - stack->Unwind(max_s, pc, bp, nullptr, t->stack_top(), t->stack_bottom(), - true); - else - stack->Unwind(max_s, pc, 0, context, 0, 0, false); } // Interface. diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h --- a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h @@ -100,6 +100,15 @@ void Init(const uptr *pcs, uptr cnt, uptr extra_top_pc = 0); void Unwind(u32 max_depth, uptr pc, uptr bp, void *context, uptr stack_top, uptr stack_bottom, bool request_fast_unwind); + void UnwindFast(uptr pc, uptr bp, uptr stack_top, uptr stack_bottom, + u32 max_depth); + + void UnwindSlowWithOptionalContext(uptr pc, void *context, u32 max_depth) { + if (context) + UnwindSlow(pc, max_depth); + else + UnwindSlow(pc, context, max_depth); + } void Reset() { *static_cast(this) = StackTrace(trace_buffer, 0); @@ -107,8 +116,6 @@ } private: - void UnwindFast(uptr pc, uptr bp, uptr stack_top, uptr stack_bottom, - u32 max_depth); void UnwindSlow(uptr pc, u32 max_depth); void UnwindSlow(uptr pc, void *context, u32 max_depth); void PopStackFrames(uptr count); @@ -156,4 +163,26 @@ uptr pc = StackTrace::GetCurrentPc(); +#if SANITIZER_CAN_FAST_UNWIND + #define UNWIND_FAST(stack, pc, bp, top, bottom, max_depth) \ + (stack)->UnwindFast((pc), (bp), (top), (bottom), (max_depth)) + #define MAYBE_UNWIND_FAST(stack, pc, bp, top, bottom, max_depth) \ + UNWIND_FAST(stack, pc, bp, top, bottom, max_depth) +#else + #define UNWIND_FAST(stack, pc, bp, top, bottom, max_depth) \ + UNREACHABLE("Fast unwinder is unsupported") + #define MAYBE_UNWIND_FAST(stack, pc, bp, top, bottom, max_depth) +#endif + +#if SANITIZER_CAN_SLOW_UNWIND + #define UNWIND_SLOW(stack, pc, context, max_depth) \ + (stack)->UnwindSlowWithOptionalContext((pc), (context), (max_depth)); + #define MAYBE_UNWIND_SLOW(stack, pc, context, max_depth) \ + UNWIND_SLOW(stack, pc, context, max_depth) +#else + #define UNWIND_SLOW(stack, pc, context, max_depth) \ + UNREACHABLE("Slow unwinder is unsupported") + #define MAYBE_UNWIND_SLOW(stack, pc, context, max_depth) +#endif + #endif // SANITIZER_STACKTRACE_H