From b3d939902a287fc1354da101349ffdd6830cb0a7 Mon Sep 17 00:00:00 2001 From: Alexey Samsonov Date: Thu, 7 Nov 2013 07:28:33 +0000 Subject: [PATCH] [Sanitizer] Make StackTrace::Unwind the only public way to unwind a stack trace. llvm-svn: 194196 --- compiler-rt/lib/msan/msan.cc | 9 ++++---- compiler-rt/lib/msan/msan.h | 2 +- .../sanitizer_common/sanitizer_stacktrace.h | 23 +++++++++++++------ .../sanitizer_stacktrace_libcdep.cc | 10 ++------ .../tests/sanitizer_stacktrace_test.cc | 23 ++++++++++++------- compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc | 4 ++-- 6 files changed, 40 insertions(+), 31 deletions(-) diff --git a/compiler-rt/lib/msan/msan.cc b/compiler-rt/lib/msan/msan.cc index 2530fb116738..26498a9b1f36 100644 --- a/compiler-rt/lib/msan/msan.cc +++ b/compiler-rt/lib/msan/msan.cc @@ -180,16 +180,15 @@ static void GetCurrentStackBounds(uptr *stack_top, uptr *stack_bottom) { } void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp, - bool fast) { - if (!fast) { + bool request_fast_unwind) { + if (!StackTrace::WillUseFastUnwind(request_fast_unwind)) { // Block reports from our interceptors during _Unwind_Backtrace. SymbolizerScope sym_scope; - return stack->SlowUnwindStack(pc, max_s); + return stack->Unwind(max_s, pc, bp, 0, 0, request_fast_unwind); } - uptr stack_top, stack_bottom; GetCurrentStackBounds(&stack_top, &stack_bottom); - stack->FastUnwindStack(pc, bp, stack_top, stack_bottom, max_s); + stack->Unwind(max_s, pc, bp, stack_top, stack_bottom, request_fast_unwind); } void PrintWarning(uptr pc, uptr bp) { diff --git a/compiler-rt/lib/msan/msan.h b/compiler-rt/lib/msan/msan.h index 51fa2ebbcf34..4e6c6194505e 100644 --- a/compiler-rt/lib/msan/msan.h +++ b/compiler-rt/lib/msan/msan.h @@ -72,7 +72,7 @@ void PrintWarning(uptr pc, uptr bp); void PrintWarningWithOrigin(uptr pc, uptr bp, u32 origin); void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp, - bool fast); + bool request_fast_unwind); void ReportUMR(StackTrace *stack, u32 origin); void ReportExpectedUMRNotFound(StackTrace *stack); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h index b03f579195c2..035f39f81f1e 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h @@ -47,17 +47,26 @@ struct StackTrace { trace[i] = src[i]; } - void Unwind(uptr max_depth, uptr pc, uptr bp, uptr stack_top, - uptr stack_bottom, bool fast); - // FIXME: Make FastUnwindStack and SlowUnwindStack private methods. - void FastUnwindStack(uptr pc, uptr bp, uptr stack_top, uptr stack_bottom, - uptr max_depth); - void SlowUnwindStack(uptr pc, uptr max_depth); + static bool WillUseFastUnwind(bool request_fast_unwind) { + // Check if fast unwind is available. Fast unwind is the only option on Mac. + if (!SANITIZER_CAN_FAST_UNWIND) + return false; + else if (SANITIZER_MAC) + return true; + return request_fast_unwind; + } - void PopStackFrames(uptr count); + void Unwind(uptr max_depth, uptr pc, uptr bp, uptr stack_top, + uptr stack_bottom, bool request_fast_unwind); static uptr GetCurrentPc(); static uptr GetPreviousInstructionPc(uptr pc); + + private: + void FastUnwindStack(uptr pc, uptr bp, uptr stack_top, uptr stack_bottom, + uptr max_depth); + void SlowUnwindStack(uptr pc, uptr max_depth); + void PopStackFrames(uptr count); }; } // namespace __sanitizer diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc index 8ce0918ded95..a8e70c965645 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc @@ -16,14 +16,8 @@ namespace __sanitizer { void StackTrace::Unwind(uptr max_depth, uptr pc, uptr bp, uptr stack_top, - uptr stack_bottom, bool fast) { - // Check if fast unwind is available. Fast unwind is the only option on Mac. - if (!SANITIZER_CAN_FAST_UNWIND) - fast = false; - else if (SANITIZER_MAC) - fast = true; - - if (!fast) + uptr stack_bottom, bool request_fast_unwind) { + if (!WillUseFastUnwind(request_fast_unwind)) SlowUnwindStack(pc, max_depth); else FastUnwindStack(pc, bp, stack_top, stack_bottom, max_depth); diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc b/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc index 8d2ac2bd5437..5e6d3fdbdb5c 100644 --- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc +++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc @@ -20,6 +20,13 @@ namespace __sanitizer { class FastUnwindTest : public ::testing::Test { protected: virtual void SetUp(); + bool TryFastUnwind(uptr max_depth) { + if (!StackTrace::WillUseFastUnwind(true)) + return false; + trace.Unwind(max_depth, start_pc, (uptr)&fake_stack[0], fake_top, + fake_bottom, true); + return true; + } uptr fake_stack[10]; uptr start_pc; @@ -50,8 +57,8 @@ void FastUnwindTest::SetUp() { } TEST_F(FastUnwindTest, Basic) { - trace.FastUnwindStack(start_pc, (uptr)&fake_stack[0], - fake_top, fake_bottom, kStackTraceMax); + if (!TryFastUnwind(kStackTraceMax)) + return; // Should get all on-stack retaddrs and start_pc. EXPECT_EQ(6U, trace.size); EXPECT_EQ(start_pc, trace.trace[0]); @@ -64,8 +71,8 @@ TEST_F(FastUnwindTest, Basic) { TEST_F(FastUnwindTest, FramePointerLoop) { // Make one fp point to itself. fake_stack[4] = (uptr)&fake_stack[4]; - trace.FastUnwindStack(start_pc, (uptr)&fake_stack[0], - fake_top, fake_bottom, kStackTraceMax); + if (!TryFastUnwind(kStackTraceMax)) + return; // Should get all on-stack retaddrs up to the 4th slot and start_pc. EXPECT_EQ(4U, trace.size); EXPECT_EQ(start_pc, trace.trace[0]); @@ -77,8 +84,8 @@ TEST_F(FastUnwindTest, FramePointerLoop) { TEST_F(FastUnwindTest, MisalignedFramePointer) { // Make one fp misaligned. fake_stack[4] += 3; - trace.FastUnwindStack(start_pc, (uptr)&fake_stack[0], - fake_top, fake_bottom, kStackTraceMax); + if (!TryFastUnwind(kStackTraceMax)) + return; // Should get all on-stack retaddrs up to the 4th slot and start_pc. EXPECT_EQ(4U, trace.size); EXPECT_EQ(start_pc, trace.trace[0]); @@ -88,8 +95,8 @@ TEST_F(FastUnwindTest, MisalignedFramePointer) { } TEST_F(FastUnwindTest, OneFrameStackTrace) { - trace.FastUnwindStack(start_pc, (uptr)&fake_stack[0], - fake_top, fake_bottom, 1); + if (!TryFastUnwind(1)) + return; EXPECT_EQ(1U, trace.size); EXPECT_EQ(start_pc, trace.trace[0]); } diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc index c353cea879c1..4fed43faf25f 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc @@ -726,8 +726,8 @@ void PrintCurrentStackSlow() { #ifndef TSAN_GO __sanitizer::StackTrace *ptrace = new(internal_alloc(MBlockStackTrace, sizeof(__sanitizer::StackTrace))) __sanitizer::StackTrace; - ptrace->SlowUnwindStack(__sanitizer::StackTrace::GetCurrentPc(), - kStackTraceMax); + ptrace->Unwind(kStackTraceMax, __sanitizer::StackTrace::GetCurrentPc(), + 0, 0, 0, false); for (uptr i = 0; i < ptrace->size / 2; i++) { uptr tmp = ptrace->trace[i]; ptrace->trace[i] = ptrace->trace[ptrace->size - i - 1];