diff options
-rw-r--r-- | lib/asan/asan_allocator2.cc | 1 | ||||
-rw-r--r-- | lib/asan/asan_linux.cc | 1 | ||||
-rw-r--r-- | lib/asan/asan_stack.h | 70 | ||||
-rw-r--r-- | lib/asan/asan_thread.h | 1 | ||||
-rw-r--r-- | test/asan/TestCases/malloc_context_size.cc | 6 |
5 files changed, 51 insertions, 28 deletions
diff --git a/lib/asan/asan_allocator2.cc b/lib/asan/asan_allocator2.cc index 773d33bd3..a759b8e35 100644 --- a/lib/asan/asan_allocator2.cc +++ b/lib/asan/asan_allocator2.cc @@ -19,6 +19,7 @@ #include "asan_mapping.h" #include "asan_poisoning.h" #include "asan_report.h" +#include "asan_stack.h" #include "asan_thread.h" #include "sanitizer_common/sanitizer_allocator.h" #include "sanitizer_common/sanitizer_flags.h" diff --git a/lib/asan/asan_linux.cc b/lib/asan/asan_linux.cc index 4e7ca7e77..f2aa690ad 100644 --- a/lib/asan/asan_linux.cc +++ b/lib/asan/asan_linux.cc @@ -18,6 +18,7 @@ #include "asan_interceptors.h" #include "asan_internal.h" #include "asan_thread.h" +#include "sanitizer_common/sanitizer_flags.h" #include "sanitizer_common/sanitizer_libc.h" #include "sanitizer_common/sanitizer_procmaps.h" diff --git a/lib/asan/asan_stack.h b/lib/asan/asan_stack.h index f7abb9335..3cbd2dad4 100644 --- a/lib/asan/asan_stack.h +++ b/lib/asan/asan_stack.h @@ -19,48 +19,64 @@ #include "sanitizer_common/sanitizer_flags.h" #include "sanitizer_common/sanitizer_stacktrace.h" +namespace __asan { + // Get the stack trace with the given pc and bp. // The pc will be in the position 0 of the resulting stack trace. // The bp may refer to the current frame or to the caller's frame. +ALWAYS_INLINE +void GetStackTraceWithPcBpAndContext(StackTrace *stack, uptr max_depth, uptr pc, + uptr bp, void *context, bool fast) { #if SANITIZER_WINDOWS -#define GET_STACK_TRACE_WITH_PC_BP_AND_CONTEXT(max_s, pc, bp, context, fast) \ - StackTrace stack; \ - stack.Unwind(max_s, pc, bp, context, 0, 0, fast) + stack->Unwind(max_depth, pc, bp, context, 0, 0, fast); #else -#define GET_STACK_TRACE_WITH_PC_BP_AND_CONTEXT(max_s, pc, bp, context, fast) \ - StackTrace stack; \ - { \ - AsanThread *t; \ - stack.size = 0; \ - if (asan_inited) { \ - if ((t = GetCurrentThread()) && !t->isUnwinding()) { \ - uptr stack_top = t->stack_top(); \ - uptr stack_bottom = t->stack_bottom(); \ - ScopedUnwinding unwind_scope(t); \ - stack.Unwind(max_s, pc, bp, context, stack_top, stack_bottom, fast); \ - } else if (t == 0 && !fast) { \ - /* If GetCurrentThread() has failed, try to do slow unwind anyways. */ \ - stack.Unwind(max_s, pc, bp, context, 0, 0, false); \ - } \ - } \ + AsanThread *t; + stack->size = 0; + if (asan_inited) { + if ((t = GetCurrentThread()) && !t->isUnwinding()) { + uptr stack_top = t->stack_top(); + uptr stack_bottom = t->stack_bottom(); + ScopedUnwinding unwind_scope(t); + stack->Unwind(max_depth, pc, bp, context, stack_top, stack_bottom, fast); + } else if (t == 0 && !fast) { + /* If GetCurrentThread() has failed, try to do slow unwind anyways. */ + stack->Unwind(max_depth, pc, bp, context, 0, 0, false); + } } #endif // SANITIZER_WINDOWS +} + +} // namespace __asan // NOTE: A Rule of thumb is to retrieve stack trace in the interceptors // as early as possible (in functions exposed to the user), as we generally // don't want stack trace to contain functions from ASan internals. #define GET_STACK_TRACE(max_size, fast) \ - GET_STACK_TRACE_WITH_PC_BP_AND_CONTEXT(max_size, StackTrace::GetCurrentPc(), \ - GET_CURRENT_FRAME(), 0, fast) + StackTrace stack; \ + if (max_size <= 2) { \ + stack.size = max_size; \ + if (max_size > 0) { \ + stack.top_frame_bp = GET_CURRENT_FRAME(); \ + stack.trace[0] = StackTrace::GetCurrentPc(); \ + } \ + if (max_size > 1) \ + stack.trace[1] = GET_CALLER_PC(); \ + } else { \ + GetStackTraceWithPcBpAndContext(&stack, max_size, \ + StackTrace::GetCurrentPc(), \ + GET_CURRENT_FRAME(), 0, fast); \ + } -#define GET_STACK_TRACE_FATAL(pc, bp) \ - GET_STACK_TRACE_WITH_PC_BP_AND_CONTEXT(kStackTraceMax, pc, bp, 0, \ - common_flags()->fast_unwind_on_fatal) +#define GET_STACK_TRACE_FATAL(pc, bp) \ + StackTrace stack; \ + GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, pc, bp, 0, \ + common_flags()->fast_unwind_on_fatal) -#define GET_STACK_TRACE_SIGNAL(pc, bp, context) \ - GET_STACK_TRACE_WITH_PC_BP_AND_CONTEXT(kStackTraceMax, pc, bp, context, \ - common_flags()->fast_unwind_on_fatal) +#define GET_STACK_TRACE_SIGNAL(pc, bp, context) \ + StackTrace stack; \ + GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, pc, bp, context, \ + common_flags()->fast_unwind_on_fatal) #define GET_STACK_TRACE_FATAL_HERE \ GET_STACK_TRACE(kStackTraceMax, common_flags()->fast_unwind_on_fatal) diff --git a/lib/asan/asan_thread.h b/lib/asan/asan_thread.h index 6bcb01ba3..1bce25c28 100644 --- a/lib/asan/asan_thread.h +++ b/lib/asan/asan_thread.h @@ -17,7 +17,6 @@ #include "asan_allocator.h" #include "asan_internal.h" #include "asan_fake_stack.h" -#include "asan_stack.h" #include "asan_stats.h" #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_libc.h" diff --git a/test/asan/TestCases/malloc_context_size.cc b/test/asan/TestCases/malloc_context_size.cc index 266ce66f5..8831de22f 100644 --- a/test/asan/TestCases/malloc_context_size.cc +++ b/test/asan/TestCases/malloc_context_size.cc @@ -3,6 +3,7 @@ // RUN: ASAN_OPTIONS=malloc_context_size=0:fast_unwind_on_malloc=1 not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os // RUN: ASAN_OPTIONS=malloc_context_size=1:fast_unwind_on_malloc=0 not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os // RUN: ASAN_OPTIONS=malloc_context_size=1:fast_unwind_on_malloc=1 not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os +// RUN: ASAN_OPTIONS=malloc_context_size=2 not %t 2>&1 | FileCheck %s --check-prefix=TWO int main() { char *x = new char[20]; @@ -24,4 +25,9 @@ int main() { // CHECK-NOT: #1 0x{{.*}} // CHECK: SUMMARY: AddressSanitizer: heap-use-after-free + + // TWO: previously allocated by thread T{{.*}} here: + // TWO-NEXT: #0 0x{{.*}} + // TWO-NEXT: #1 0x{{.*}} in main {{.*}}malloc_context_size.cc + // TWO: SUMMARY: AddressSanitizer: heap-use-after-free } |