forked from OSchip/llvm-project
[Sanitizer] Make StackTrace::Unwind the only public way to unwind a stack trace.
llvm-svn: 194196
This commit is contained in:
parent
5d350b2ab6
commit
b3d939902a
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
|
Loading…
Reference in New Issue