From bb69879d09a2ca2419c1d90a9bb67fd1c6c983eb Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Thu, 13 Dec 2012 12:31:55 +0000 Subject: [PATCH] [asan] pop the internal stack frames in SlowUnwindStack, extend the test to check this llvm-svn: 170124 --- compiler-rt/lib/asan/asan_linux.cc | 2 +- compiler-rt/lib/asan/lit_tests/Linux/malloc-in-qsort.cc | 10 ++++++++++ compiler-rt/lib/sanitizer_common/sanitizer_linux.cc | 16 +++++++++++++--- compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h | 2 +- 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/compiler-rt/lib/asan/asan_linux.cc b/compiler-rt/lib/asan/asan_linux.cc index 02a3d14..ff91e89 100644 --- a/compiler-rt/lib/asan/asan_linux.cc +++ b/compiler-rt/lib/asan/asan_linux.cc @@ -129,7 +129,7 @@ void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp, bool fast) { fast = false; #endif if (!fast) - return stack->SlowUnwindStack(pc, max_s, 3); + return stack->SlowUnwindStack(pc, max_s); stack->size = 0; stack->trace[0] = pc; if (max_s > 1) { diff --git a/compiler-rt/lib/asan/lit_tests/Linux/malloc-in-qsort.cc b/compiler-rt/lib/asan/lit_tests/Linux/malloc-in-qsort.cc index 5140890..a3fa255 100644 --- a/compiler-rt/lib/asan/lit_tests/Linux/malloc-in-qsort.cc +++ b/compiler-rt/lib/asan/lit_tests/Linux/malloc-in-qsort.cc @@ -37,4 +37,14 @@ int main() { // FIXME: this test does not properly work with slow unwind yet. // CHECK-FAST: ERROR: AddressSanitizer: heap-buffer-overflow +// CHECK-FAST: is located 0 bytes to the right +// CHECK-FAST: #0{{.*}}operator new +// CHECK-FAST-NEXT: #1{{.*}}QsortCallback +// CHECK-FAST-NOT: MyQsort +// // CHECK-SLOW: ERROR: AddressSanitizer: heap-buffer-overflow +// CHECK-SLOW: is located 0 bytes to the right +// CHECK-SLOW: #0{{.*}}operator new +// CHECK-SLOW-NEXT: #1{{.*}}QsortCallback +// CHECK-SLOW: #{{.*}}MyQsort +// CHECK-SLOW-NEXT: #{{.*}}main diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc index 6a0f261..a0f0274 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc @@ -411,14 +411,24 @@ _Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) { return UNWIND_CONTINUE; } -void StackTrace::SlowUnwindStack(uptr pc, uptr max_depth, uptr frames_to_pop) { +static bool MatchPc(uptr cur_pc, uptr trace_pc) { + return cur_pc - trace_pc <= 8; +} + +void StackTrace::SlowUnwindStack(uptr pc, uptr max_depth) { this->size = 0; - this->trace[0] = pc; this->max_size = max_depth; if (max_depth > 1) { _Unwind_Backtrace(Unwind_Trace, this); - this->PopStackFrames(frames_to_pop); + // We need to pop a few (up to 3) frames so that pc is on top. + // trace[0] belongs to the current function. + int to_pop = 1; + /**/ if (size >= 2 && MatchPc(pc, trace[1])) to_pop = 2; + else if (size >= 3 && MatchPc(pc, trace[2])) to_pop = 3; + else if (size >= 4 && MatchPc(pc, trace[3])) to_pop = 4; + this->PopStackFrames(to_pop); } + this->trace[0] = pc; } } // namespace __sanitizer diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h index 64979ec..90ad31f 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h @@ -44,7 +44,7 @@ struct StackTrace { } void FastUnwindStack(uptr pc, uptr bp, uptr stack_top, uptr stack_bottom); - void SlowUnwindStack(uptr pc, uptr max_depth, uptr frames_to_pop); + void SlowUnwindStack(uptr pc, uptr max_depth); void PopStackFrames(uptr count); -- 2.7.4