Index: lib/asan/asan_allocator.h =================================================================== --- lib/asan/asan_allocator.h +++ lib/asan/asan_allocator.h @@ -196,7 +196,7 @@ int asan_posix_memalign(void **memptr, uptr alignment, uptr size, BufferedStackTrace *stack); -uptr asan_malloc_usable_size(const void *ptr, uptr pc, uptr bp); +uptr asan_malloc_usable_size(const void *ptr, uptr pc, uptr caller_pc, uptr bp); uptr asan_mz_size(const void *ptr); void asan_mz_force_lock(); Index: lib/asan/asan_allocator.cc =================================================================== --- lib/asan/asan_allocator.cc +++ lib/asan/asan_allocator.cc @@ -814,11 +814,12 @@ return 0; } -uptr asan_malloc_usable_size(const void *ptr, uptr pc, uptr bp) { +uptr asan_malloc_usable_size(const void *ptr, uptr pc, uptr caller_pc, + uptr bp) { if (!ptr) return 0; uptr usable_size = instance.AllocationSize(reinterpret_cast(ptr)); if (flags()->check_malloc_usable_size && (usable_size == 0)) { - GET_STACK_TRACE_FATAL(pc, bp); + GET_STACK_TRACE_FATAL(pc, caller_pc, bp); ReportMallocUsableSizeNotOwned((uptr)ptr, &stack); } return usable_size; Index: lib/asan/asan_errors.cc =================================================================== --- lib/asan/asan_errors.cc +++ lib/asan/asan_errors.cc @@ -32,7 +32,7 @@ Printf("%s", d.EndWarning()); scariness.Print(); BufferedStackTrace stack; - GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, pc, bp, context, + GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, pc, 0, bp, context, common_flags()->fast_unwind_on_fatal); stack.Print(); ReportErrorSummary(scariness.GetDescription(), &stack); @@ -79,7 +79,7 @@ } scariness.Print(); BufferedStackTrace stack; - GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, pc, bp, context, + GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, pc, 0, bp, context, common_flags()->fast_unwind_on_fatal); stack.Print(); MaybeDumpInstructionBytes(pc); @@ -99,8 +99,10 @@ ThreadNameWithParenthesis(tid, tname, sizeof(tname))); Printf("%s", d.EndWarning()); scariness.Print(); - GET_STACK_TRACE_FATAL(second_free_stack->trace[0], - second_free_stack->top_frame_bp); + GET_STACK_TRACE_FATAL( + second_free_stack->trace[0], + second_free_stack->size > 1 ? second_free_stack->trace[1] : 0, + second_free_stack->top_frame_bp); stack.Print(); addr_description.Print(); ReportErrorSummary(scariness.GetDescription(), &stack); @@ -122,7 +124,9 @@ addr_description.chunk_access.chunk_size, delete_size); CHECK_GT(free_stack->size, 0); scariness.Print(); - GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp); + GET_STACK_TRACE_FATAL(free_stack->trace[0], + free_stack->size > 1 ? free_stack->trace[1] : 0, + free_stack->top_frame_bp); stack.Print(); addr_description.Print(); ReportErrorSummary(scariness.GetDescription(), &stack); @@ -143,7 +147,9 @@ Printf("%s", d.EndWarning()); CHECK_GT(free_stack->size, 0); scariness.Print(); - GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp); + GET_STACK_TRACE_FATAL(free_stack->trace[0], + free_stack->size > 1 ? free_stack->trace[1] : 0, + free_stack->top_frame_bp); stack.Print(); addr_description.Print(); ReportErrorSummary(scariness.GetDescription(), &stack); @@ -164,7 +170,9 @@ Printf("%s", d.EndWarning()); CHECK_GT(dealloc_stack->size, 0); scariness.Print(); - GET_STACK_TRACE_FATAL(dealloc_stack->trace[0], dealloc_stack->top_frame_bp); + GET_STACK_TRACE_FATAL(dealloc_stack->trace[0], + dealloc_stack->size > 1 ? dealloc_stack->trace[1] : 0, + dealloc_stack->top_frame_bp); stack.Print(); addr_description.Print(); ReportErrorSummary(scariness.GetDescription(), &stack); @@ -281,7 +289,7 @@ Report("ERROR: AddressSanitizer: %s: %p %p\n", scariness.GetDescription(), addr1_description.Address(), addr2_description.Address()); Printf("%s", d.EndWarning()); - GET_STACK_TRACE_FATAL(pc, bp); + GET_STACK_TRACE_FATAL(pc, 0, bp); stack.Print(); addr1_description.Print(); addr2_description.Print(); @@ -488,7 +496,7 @@ ThreadNameWithParenthesis(tid, tname, sizeof(tname)), d.EndAccess()); scariness.Print(); - GET_STACK_TRACE_FATAL(pc, bp); + GET_STACK_TRACE_FATAL(pc, 0, bp); stack.Print(); // Pass bug_descr because we have a special case for Index: lib/asan/asan_interceptors.cc =================================================================== --- lib/asan/asan_interceptors.cc +++ lib/asan/asan_interceptors.cc @@ -50,35 +50,45 @@ const char *interceptor_name; }; +NOINLINE +static void ReportGenericErrorInCaller(uptr bp, uptr sp, uptr addr, + bool is_write, uptr access_size) { + uptr pc = GET_CALLER_PC(); + ReportGenericError(pc, bp, sp, addr, is_write, access_size, 0, false); +} + // We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE, // and ASAN_WRITE_RANGE as macro instead of function so // that no extra frames are created, and stack trace contains // relevant information only. // We check all shadow bytes. -#define ACCESS_MEMORY_RANGE(ctx, offset, size, isWrite) do { \ - uptr __offset = (uptr)(offset); \ - uptr __size = (uptr)(size); \ - uptr __bad = 0; \ - if (__offset > __offset + __size) { \ - GET_STACK_TRACE_FATAL_HERE; \ - ReportStringFunctionSizeOverflow(__offset, __size, &stack); \ - } \ - if (!QuickCheckForUnpoisonedRegion(__offset, __size) && \ - (__bad = __asan_region_is_poisoned(__offset, __size))) { \ - AsanInterceptorContext *_ctx = (AsanInterceptorContext *)ctx; \ - bool suppressed = false; \ - if (_ctx) { \ - suppressed = IsInterceptorSuppressed(_ctx->interceptor_name); \ - if (!suppressed && HaveStackTraceBasedSuppressions()) { \ - GET_STACK_TRACE_FATAL_HERE; \ - suppressed = IsStackTraceSuppressed(&stack); \ - } \ - } \ - if (!suppressed) { \ - GET_CURRENT_PC_BP_SP; \ - ReportGenericError(pc, bp, sp, __bad, isWrite, __size, 0, false);\ - } \ - } \ +#define ACCESS_MEMORY_RANGE(ctx, offset, size, isWrite) \ + do { \ + uptr __offset = (uptr)(offset); \ + uptr __size = (uptr)(size); \ + uptr __bad = 0; \ + if (__offset > __offset + __size) { \ + GET_STACK_TRACE_FATAL_HERE; \ + ReportStringFunctionSizeOverflow(__offset, __size, &stack); \ + } \ + if (!QuickCheckForUnpoisonedRegion(__offset, __size) && \ + (__bad = __asan_region_is_poisoned(__offset, __size))) { \ + AsanInterceptorContext *_ctx = (AsanInterceptorContext *)ctx; \ + bool suppressed = false; \ + if (_ctx) { \ + suppressed = IsInterceptorSuppressed(_ctx->interceptor_name); \ + if (!suppressed && HaveStackTraceBasedSuppressions()) { \ + GET_STACK_TRACE_FATAL_HERE; \ + suppressed = IsStackTraceSuppressed(&stack); \ + } \ + } \ + if (!suppressed) { \ + uptr local_stack; \ + uptr sp = (uptr)&local_stack; \ + uptr bp = GET_CURRENT_FRAME(); \ + ReportGenericErrorInCaller(bp, sp, __bad, isWrite, __size); \ + } \ + } \ } while (0) // memcpy is called during __asan_init() from the internals of printf(...). Index: lib/asan/asan_malloc_linux.cc =================================================================== --- lib/asan/asan_malloc_linux.cc +++ lib/asan/asan_malloc_linux.cc @@ -109,9 +109,8 @@ } INTERCEPTOR(uptr, malloc_usable_size, void *ptr) { - GET_CURRENT_PC_BP_SP; - (void)sp; - return asan_malloc_usable_size(ptr, pc, bp); + return asan_malloc_usable_size(ptr, StackTrace::GetCurrentPc(), + GET_CALLER_PC(), GET_CURRENT_FRAME()); } // We avoid including malloc.h for portability reasons. Index: lib/asan/asan_malloc_win.cc =================================================================== --- lib/asan/asan_malloc_win.cc +++ lib/asan/asan_malloc_win.cc @@ -131,9 +131,8 @@ ALLOCATION_FUNCTION_ATTRIBUTE size_t _msize(const void *ptr) { - GET_CURRENT_PC_BP_SP; - (void)sp; - return asan_malloc_usable_size(ptr, pc, bp); + return asan_malloc_usable_size(ptr, StackTrace::GetCurrentPc(), + GET_CALLER_PC(), GET_CURRENT_FRAME()); } ALLOCATION_FUNCTION_ATTRIBUTE @@ -200,9 +199,8 @@ INTERCEPTOR_WINAPI(SIZE_T, HeapSize, HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem) { CHECK(dwFlags == 0 && "unsupported heap flags"); - GET_CURRENT_PC_BP_SP; - (void)sp; - return asan_malloc_usable_size(lpMem, pc, bp); + return asan_malloc_usable_size(lpMem, StackTrace::GetCurrentPc(), + GET_CALLER_PC(), GET_CURRENT_FRAME()); } namespace __asan { Index: lib/asan/asan_poisoning.cc =================================================================== --- lib/asan/asan_poisoning.cc +++ lib/asan/asan_poisoning.cc @@ -207,18 +207,26 @@ return 0; } -#define CHECK_SMALL_REGION(p, size, isWrite) \ - do { \ - uptr __p = reinterpret_cast(p); \ - uptr __size = size; \ - if (UNLIKELY(__asan::AddressIsPoisoned(__p) || \ - __asan::AddressIsPoisoned(__p + __size - 1))) { \ - GET_CURRENT_PC_BP_SP; \ - uptr __bad = __asan_region_is_poisoned(__p, __size); \ - __asan_report_error(pc, bp, sp, __bad, isWrite, __size, 0);\ - } \ - } while (false); \ - +NOINLINE +static void report_error(uptr bp, uptr sp, uptr addr, bool is_write, + uptr size) { + uptr pc = GET_CALLER_PC(); + __asan_report_error(pc, bp, sp, addr, is_write, size, 0); +} + +#define CHECK_SMALL_REGION(p, size, isWrite) \ + do { \ + uptr __p = reinterpret_cast(p); \ + uptr __size = size; \ + if (UNLIKELY(__asan::AddressIsPoisoned(__p) || \ + __asan::AddressIsPoisoned(__p + __size - 1))) { \ + uptr local_stack; \ + uptr sp = (uptr)&local_stack; \ + uptr bp = GET_CURRENT_FRAME(); \ + uptr __bad = __asan_region_is_poisoned(__p, __size); \ + report_error(bp, sp, __bad, isWrite, __size); \ + } \ + } while (false); extern "C" SANITIZER_INTERFACE_ATTRIBUTE u16 __sanitizer_unaligned_load16(const uu16 *p) { Index: lib/asan/asan_stack.h =================================================================== --- lib/asan/asan_stack.h +++ lib/asan/asan_stack.h @@ -32,8 +32,8 @@ // The bp may refer to the current frame or to the caller's frame. ALWAYS_INLINE void GetStackTraceWithPcBpAndContext(BufferedStackTrace *stack, uptr max_depth, - uptr pc, uptr bp, void *context, - bool fast) { + uptr pc, uptr caller_pc, uptr bp, + void *context, bool fast) { #if SANITIZER_WINDOWS stack->Unwind(max_depth, pc, bp, context, 0, 0, fast); #else @@ -49,12 +49,12 @@ uptr stack_bottom = t->stack_bottom(); ScopedUnwinding unwind_scope(t); if (!SANITIZER_MIPS || IsValidFrame(bp, stack_top, stack_bottom)) { - stack->Unwind(max_depth, pc, bp, context, stack_top, stack_bottom, - fast); + stack->Unwind(max_depth, pc, caller_pc, bp, context, stack_top, + stack_bottom, fast); } } else if (!t && !fast) { /* If GetCurrentThread() has failed, try to do slow unwind anyways. */ - stack->Unwind(max_depth, pc, bp, context, 0, 0, false); + stack->Unwind(max_depth, pc, caller_pc, bp, context, 0, 0, false); } } #endif // SANITIZER_WINDOWS @@ -66,31 +66,30 @@ // 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) \ - BufferedStackTrace stack; \ - if (max_size <= 2) { \ - stack.size = max_size; \ - if (max_size > 0) { \ - stack.top_frame_bp = GET_CURRENT_FRAME(); \ - stack.trace_buffer[0] = StackTrace::GetCurrentPc(); \ - if (max_size > 1) \ - stack.trace_buffer[1] = GET_CALLER_PC(); \ - } \ - } else { \ - GetStackTraceWithPcBpAndContext(&stack, max_size, \ - StackTrace::GetCurrentPc(), \ - GET_CURRENT_FRAME(), 0, fast); \ +#define GET_STACK_TRACE(max_size, fast) \ + BufferedStackTrace stack; \ + if (max_size <= 2) { \ + stack.size = max_size; \ + if (max_size > 0) { \ + stack.top_frame_bp = GET_CURRENT_FRAME(); \ + stack.trace_buffer[0] = StackTrace::GetCurrentPc(); \ + if (max_size > 1) stack.trace_buffer[1] = GET_CALLER_PC(); \ + } \ + } else { \ + GetStackTraceWithPcBpAndContext( \ + &stack, max_size, StackTrace::GetCurrentPc(), GET_CALLER_PC(), \ + GET_CURRENT_FRAME(), 0, fast); \ } -#define GET_STACK_TRACE_FATAL(pc, bp) \ - BufferedStackTrace stack; \ - GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, pc, bp, 0, \ - common_flags()->fast_unwind_on_fatal) +#define GET_STACK_TRACE_FATAL(pc, caller_pc, bp) \ + BufferedStackTrace stack; \ + GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, pc, caller_pc, bp, \ + 0, common_flags()->fast_unwind_on_fatal) -#define GET_STACK_TRACE_SIGNAL(sig) \ - BufferedStackTrace stack; \ - GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, \ - (sig).pc, (sig).bp, (sig).context, \ +#define GET_STACK_TRACE_SIGNAL(sig) \ + BufferedStackTrace stack; \ + GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, (sig).pc, 0, \ + (sig).bp, (sig).context, \ common_flags()->fast_unwind_on_fatal) #define GET_STACK_TRACE_FATAL_HERE \ Index: lib/asan/tests/asan_interface_test.cc =================================================================== --- lib/asan/tests/asan_interface_test.cc +++ lib/asan/tests/asan_interface_test.cc @@ -10,9 +10,10 @@ // This file is a part of AddressSanitizer, an address sanity checker. // //===----------------------------------------------------------------------===// -#include "asan_test_utils.h" #include #include +#include +#include "asan_test_utils.h" TEST(AddressSanitizerInterface, GetEstimatedAllocatedSize) { EXPECT_EQ(0U, __sanitizer_get_estimated_allocated_size(0)); @@ -399,7 +400,7 @@ TEST(AddressSanitizerInterface, SetErrorReportCallbackTest) { __asan_set_error_report_callback(ErrorReportCallbackOneToZ); - EXPECT_DEATH(__asan_report_error(0, 0, 0, 0, true, 1), + EXPECT_DEATH(__asan_report_error((void *)GET_CALLER_PC(), 0, 0, 0, true, 1), ASAN_PCRE_DOTALL "ABCDEF.*AddressSanitizer.*WRITE.*ABCDEF"); __asan_set_error_report_callback(NULL); } Index: lib/asan/tests/asan_noinst_test.cc =================================================================== --- lib/asan/tests/asan_noinst_test.cc +++ lib/asan/tests/asan_noinst_test.cc @@ -81,7 +81,7 @@ size_t alignment = 1 << (my_rand_r(&seed) % 10 + 1); char *ptr = (char*)__asan::asan_memalign(alignment, size, &stack2, __asan::FROM_MALLOC); - EXPECT_EQ(size, __asan::asan_malloc_usable_size(ptr, 0, 0)); + EXPECT_EQ(size, __asan::asan_malloc_usable_size(ptr, 0, 0, 0)); vec.push_back(ptr); ptr[0] = 0; ptr[size-1] = 0; Index: lib/lsan/lsan.h =================================================================== --- lib/lsan/lsan.h +++ lib/lsan/lsan.h @@ -15,20 +15,21 @@ #include "sanitizer_common/sanitizer_flags.h" #include "sanitizer_common/sanitizer_stacktrace.h" -#define GET_STACK_TRACE(max_size, fast) \ - BufferedStackTrace stack; \ - { \ - uptr stack_top = 0, stack_bottom = 0; \ - ThreadContext *t; \ - if (fast && (t = CurrentThreadContext())) { \ - stack_top = t->stack_end(); \ - stack_bottom = t->stack_begin(); \ - } \ - if (!SANITIZER_MIPS || \ - IsValidFrame(GET_CURRENT_FRAME(), stack_top, stack_bottom)) { \ - stack.Unwind(max_size, StackTrace::GetCurrentPc(), GET_CURRENT_FRAME(), \ - /* context */ 0, stack_top, stack_bottom, fast); \ - } \ +#define GET_STACK_TRACE(max_size, fast) \ + BufferedStackTrace stack; \ + { \ + uptr stack_top = 0, stack_bottom = 0; \ + ThreadContext *t; \ + if (fast && (t = CurrentThreadContext())) { \ + stack_top = t->stack_end(); \ + stack_bottom = t->stack_begin(); \ + } \ + if (!SANITIZER_MIPS || \ + IsValidFrame(GET_CURRENT_FRAME(), stack_top, stack_bottom)) { \ + stack.Unwind(max_size, StackTrace::GetCurrentPc(), GET_CALLER_PC(), \ + GET_CURRENT_FRAME(), /* context */ 0, stack_top, \ + stack_bottom, fast); \ + } \ } #define GET_STACK_TRACE_FATAL \ Index: lib/msan/msan.cc =================================================================== --- lib/msan/msan.cc +++ lib/msan/msan.cc @@ -223,9 +223,9 @@ if (!t || !StackTrace::WillUseFastUnwind(request_fast_unwind)) { // Block reports from our interceptors during _Unwind_Backtrace. SymbolizerScope sym_scope; - return stack->Unwind(max_s, pc, bp, nullptr, 0, 0, request_fast_unwind); + return stack->Unwind(max_s, pc, 0, bp, nullptr, 0, 0, request_fast_unwind); } - stack->Unwind(max_s, pc, bp, nullptr, t->stack_top(), t->stack_bottom(), + stack->Unwind(max_s, pc, 0, bp, nullptr, t->stack_top(), t->stack_bottom(), request_fast_unwind); } Index: lib/sanitizer_common/sanitizer_internal_defs.h =================================================================== --- lib/sanitizer_common/sanitizer_internal_defs.h +++ lib/sanitizer_common/sanitizer_internal_defs.h @@ -289,8 +289,8 @@ enum LinkerInitialized { LINKER_INITIALIZED = 0 }; #if !defined(_MSC_VER) || defined(__clang__) -# define GET_CALLER_PC() (uptr)__builtin_return_address(0) -# define GET_CURRENT_FRAME() (uptr)__builtin_frame_address(0) +#define GET_CALLER_PC() (__sanitizer::uptr) __builtin_return_address(0) +#define GET_CURRENT_FRAME() (__sanitizer::uptr) __builtin_frame_address(0) inline void Trap() { __builtin_trap(); } @@ -299,9 +299,10 @@ extern "C" void* _AddressOfReturnAddress(void); # pragma intrinsic(_ReturnAddress) # pragma intrinsic(_AddressOfReturnAddress) -# define GET_CALLER_PC() (uptr)_ReturnAddress() +#define GET_CALLER_PC() (__sanitizer::uptr) _ReturnAddress() // CaptureStackBackTrace doesn't need to know BP on Windows. -# define GET_CURRENT_FRAME() (((uptr)_AddressOfReturnAddress()) + sizeof(uptr)) +#define GET_CURRENT_FRAME() \ + (((__sanitizer::uptr)_AddressOfReturnAddress()) + sizeof(__sanitizer::uptr)) extern "C" void __ud2(void); # pragma intrinsic(__ud2) Index: lib/sanitizer_common/sanitizer_stacktrace.h =================================================================== --- lib/sanitizer_common/sanitizer_stacktrace.h +++ lib/sanitizer_common/sanitizer_stacktrace.h @@ -94,17 +94,17 @@ BufferedStackTrace() : StackTrace(trace_buffer, 0), top_frame_bp(0) {} void Init(const uptr *pcs, uptr cnt, uptr extra_top_pc = 0); - void Unwind(u32 max_depth, uptr pc, uptr bp, void *context, uptr stack_top, - uptr stack_bottom, bool request_fast_unwind); + void Unwind(u32 max_depth, uptr pc, uptr caller_pc, uptr bp, void *context, + uptr stack_top, uptr stack_bottom, bool request_fast_unwind); private: void FastUnwindStack(uptr pc, uptr bp, uptr stack_top, uptr stack_bottom, u32 max_depth); - void SlowUnwindStack(uptr pc, u32 max_depth); - void SlowUnwindStackWithContext(uptr pc, void *context, + void SlowUnwindStack(uptr pc, uptr caller_pc, u32 max_depth); + void SlowUnwindStackWithContext(uptr pc, uptr caller_pc, void *context, u32 max_depth); void PopStackFrames(uptr count); - uptr LocatePcInTrace(uptr pc); + uptr LocatePcInTrace(uptr pc, uptr caller_pc); BufferedStackTrace(const BufferedStackTrace &); void operator=(const BufferedStackTrace &); @@ -129,13 +129,4 @@ uptr bp = GET_CURRENT_FRAME(); \ uptr pc = GET_CALLER_PC(); -// Use this macro if you want to print stack trace with the current -// function in the top frame. -#define GET_CURRENT_PC_BP_SP \ - uptr bp = GET_CURRENT_FRAME(); \ - uptr pc = StackTrace::GetCurrentPc(); \ - uptr local_stack; \ - uptr sp = (uptr)&local_stack - - #endif // SANITIZER_STACKTRACE_H Index: lib/sanitizer_common/sanitizer_stacktrace.cc =================================================================== --- lib/sanitizer_common/sanitizer_stacktrace.cc +++ lib/sanitizer_common/sanitizer_stacktrace.cc @@ -106,10 +106,6 @@ } } -static bool MatchPc(uptr cur_pc, uptr trace_pc, uptr threshold) { - return cur_pc - trace_pc <= threshold || trace_pc - cur_pc <= threshold; -} - void BufferedStackTrace::PopStackFrames(uptr count) { CHECK_LT(count, size); size -= count; @@ -118,13 +114,13 @@ } } -uptr BufferedStackTrace::LocatePcInTrace(uptr pc) { - // Use threshold to find PC in stack trace, as PC we want to unwind from may - // slightly differ from return address in the actual unwinded stack trace. - const int kPcThreshold = 350; +uptr BufferedStackTrace::LocatePcInTrace(uptr pc, uptr caller_pc) { + uptr min_diff = -1; for (uptr i = 0; i < size; ++i) { - if (MatchPc(pc, trace[i], kPcThreshold)) - return i; + if (trace[i] == pc) return i; + if (i && trace[i] == caller_pc) return i - 1; + uptr diff = trace[i] < pc ? trace[i] - pc : pc - trace[i]; + min_diff = min_diff > diff ? diff : min_diff; } return 0; } Index: lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc =================================================================== --- lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc +++ lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc @@ -54,9 +54,9 @@ Printf("DEDUP_TOKEN: %s\n", dedup_token.data()); } -void BufferedStackTrace::Unwind(u32 max_depth, uptr pc, uptr bp, void *context, - uptr stack_top, uptr stack_bottom, - bool request_fast_unwind) { +void BufferedStackTrace::Unwind(u32 max_depth, uptr pc, uptr caller_pc, uptr bp, + void *context, uptr stack_top, + uptr stack_bottom, bool request_fast_unwind) { top_frame_bp = (max_depth > 0) ? bp : 0; // Avoid doing any work for small max_depth. if (max_depth == 0) { @@ -71,9 +71,9 @@ if (!WillUseFastUnwind(request_fast_unwind)) { #if SANITIZER_CAN_SLOW_UNWIND if (context) - SlowUnwindStackWithContext(pc, context, max_depth); + SlowUnwindStackWithContext(pc, caller_pc, context, max_depth); else - SlowUnwindStack(pc, max_depth); + SlowUnwindStack(pc, caller_pc, max_depth); #else UNREACHABLE("slow unwind requested but not available"); #endif Index: lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cc =================================================================== --- lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cc +++ lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cc @@ -118,13 +118,14 @@ return UNWIND_CONTINUE; } -void BufferedStackTrace::SlowUnwindStack(uptr pc, u32 max_depth) { +void BufferedStackTrace::SlowUnwindStack(uptr pc, uptr caller_pc, + u32 max_depth) { CHECK_GE(max_depth, 2); size = 0; UnwindTraceArg arg = {this, Min(max_depth + 1, kStackTraceMax)}; _Unwind_Backtrace(Unwind_Trace, &arg); // We need to pop a few frames so that pc is on top. - uptr to_pop = LocatePcInTrace(pc); + uptr to_pop = LocatePcInTrace(pc, caller_pc); // trace_buffer[0] belongs to the current function so we always pop it, // unless there is only 1 frame in the stack trace (1 frame is always better // than 0!). @@ -137,11 +138,12 @@ trace_buffer[0] = pc; } -void BufferedStackTrace::SlowUnwindStackWithContext(uptr pc, void *context, +void BufferedStackTrace::SlowUnwindStackWithContext(uptr pc, uptr caller_pc, + void *context, u32 max_depth) { CHECK_GE(max_depth, 2); if (!unwind_backtrace_signal_arch) { - SlowUnwindStack(pc, max_depth); + SlowUnwindStack(pc, caller_pc, max_depth); return; } Index: lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc =================================================================== --- lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc +++ lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc @@ -24,7 +24,7 @@ bool TryFastUnwind(uptr max_depth) { if (!StackTrace::WillUseFastUnwind(true)) return false; - trace.Unwind(max_depth, start_pc, (uptr)&fake_stack[0], 0, fake_top, + trace.Unwind(max_depth, start_pc, 0, (uptr)&fake_stack[0], 0, fake_top, fake_bottom, true); return true; } @@ -155,10 +155,10 @@ BufferedStackTrace stack; uptr pc = StackTrace::GetCurrentPc(); uptr bp = GET_CURRENT_FRAME(); - stack.Unwind(0, pc, bp, 0, 0, 0, false); + stack.Unwind(0, pc, 0, bp, 0, 0, 0, false); EXPECT_EQ(0U, stack.size); EXPECT_EQ(0U, stack.top_frame_bp); - stack.Unwind(1, pc, bp, 0, 0, 0, false); + stack.Unwind(1, pc, 0, bp, 0, 0, 0, false); EXPECT_EQ(1U, stack.size); EXPECT_EQ(pc, stack.trace[0]); EXPECT_EQ(bp, stack.top_frame_bp); Index: lib/tsan/rtl/tsan_rtl_report.cc =================================================================== --- lib/tsan/rtl/tsan_rtl_report.cc +++ lib/tsan/rtl/tsan_rtl_report.cc @@ -697,7 +697,7 @@ BufferedStackTrace *ptrace = new(internal_alloc(MBlockStackTrace, sizeof(BufferedStackTrace))) BufferedStackTrace(); - ptrace->Unwind(kStackTraceMax, pc, 0, 0, 0, 0, false); + ptrace->Unwind(kStackTraceMax, pc, 0, 0, 0, 0, 0, false); for (uptr i = 0; i < ptrace->size / 2; i++) { uptr tmp = ptrace->trace_buffer[i]; ptrace->trace_buffer[i] = ptrace->trace_buffer[ptrace->size - i - 1]; Index: lib/ubsan/ubsan_diag.cc =================================================================== --- lib/ubsan/ubsan_diag.cc +++ lib/ubsan/ubsan_diag.cc @@ -39,7 +39,7 @@ if (StackTrace::WillUseFastUnwind(false)) return; BufferedStackTrace stack; - stack.Unwind(kStackTraceMax, pc, bp, 0, 0, 0, false); + stack.Unwind(kStackTraceMax, pc, 0, bp, 0, 0, 0, false); stack.Print(); }