[Sanitizer] Make StackTrace::Unwind the only public way to unwind a stack trace.

llvm-svn: 194196
This commit is contained in:
Alexey Samsonov 2013-11-07 07:28:33 +00:00
parent 5d350b2ab6
commit b3d939902a
6 changed files with 40 additions and 31 deletions

View File

@ -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) {

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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]);
}

View File

@ -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];