diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc index d415279dd5d6..eba6eb9682fe 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc @@ -154,10 +154,6 @@ _Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) { return UNWIND_CONTINUE; } -static bool MatchPc(uptr cur_pc, uptr trace_pc) { - return cur_pc - trace_pc <= 64 || trace_pc - cur_pc <= 64; -} - void StackTrace::SlowUnwindStack(uptr pc, uptr max_depth) { size = 0; if (max_depth == 0) @@ -165,13 +161,10 @@ void StackTrace::SlowUnwindStack(uptr pc, uptr max_depth) { 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, 64, 6); // trace[0] belongs to the current function so we always pop it. - int to_pop = 1; - /**/ if (size > 1 && MatchPc(pc, trace[1])) to_pop = 1; - else if (size > 2 && MatchPc(pc, trace[2])) to_pop = 2; - else if (size > 3 && MatchPc(pc, trace[3])) to_pop = 3; - else if (size > 4 && MatchPc(pc, trace[4])) to_pop = 4; - else if (size > 5 && MatchPc(pc, trace[5])) to_pop = 5; + if (to_pop == 0) + to_pop = 1; PopStackFrames(to_pop); trace[0] = pc; } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc index a110774eec6c..f03490b8c4eb 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc @@ -147,4 +147,17 @@ void StackTrace::PopStackFrames(uptr count) { } } +static bool MatchPc(uptr cur_pc, uptr trace_pc, uptr threshold) { + return cur_pc - trace_pc <= threshold || trace_pc - cur_pc <= threshold; +} + +uptr +StackTrace::LocatePcInTrace(uptr pc, uptr pc_threshold, uptr max_pc_depth) { + for (uptr i = 0; i < max_pc_depth && i < size; ++i) { + if (MatchPc(pc, trace[i], pc_threshold)) + return i; + } + return 0; +} + } // namespace __sanitizer diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h index 035f39f81f1e..408063c187fd 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h @@ -67,6 +67,7 @@ struct StackTrace { uptr max_depth); void SlowUnwindStack(uptr pc, uptr max_depth); void PopStackFrames(uptr count); + uptr LocatePcInTrace(uptr pc, uptr pc_threshold = 0, uptr max_pc_depth = -1); }; } // namespace __sanitizer diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win.cc b/compiler-rt/lib/sanitizer_common/sanitizer_win.cc index d8a57d539f5f..7d07a173496b 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_win.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_win.cc @@ -377,23 +377,16 @@ void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size, } void StackTrace::SlowUnwindStack(uptr pc, uptr max_depth) { - void *tmp[kStackTraceMax]; - // FIXME: CaptureStackBackTrace might be too slow for us. // FIXME: Compare with StackWalk64. // FIXME: Look at LLVMUnhandledExceptionFilter in Signals.inc - uptr cs_ret = CaptureStackBackTrace(2, max_depth, tmp, 0); - uptr offset = 0; + size = CaptureStackBackTrace(2, Min(max_depth, kStackTraceMax), + (void**)trace, 0); // Skip the RTL frames by searching for the PC in the stacktrace. - // FIXME: this doesn't work well for the malloc/free stacks yet. - for (uptr i = 0; i < cs_ret; i++) { - if (pc != (uptr)tmp[i]) - continue; - offset = i; - break; - } - - CopyFrom((uptr*)&tmp[offset], cs_ret - offset); + // FIXME: this doesn't work well for the malloc/free stacks yet - consider + // adjusting the pc_threshold. + uptr pc_location = LocatePcInTrace(pc); + PopStackFrames(pc_location); } void MaybeOpenReportFile() {