From 3e8467b8b985efcd11c667d50efa69920cd3b108 Mon Sep 17 00:00:00 2001 From: Alexey Samsonov Date: Tue, 4 Mar 2014 12:21:28 +0000 Subject: [PATCH] Avoid doing any work when unwinding stack traces with 0 or 1 frame llvm-svn: 202837 --- .../lib/sanitizer_common/sanitizer_linux_libcdep.cc | 10 ++++------ .../lib/sanitizer_common/sanitizer_stacktrace.cc | 5 +---- .../sanitizer_stacktrace_libcdep.cc | 13 +++++++++++-- compiler-rt/lib/sanitizer_common/sanitizer_win.cc | 1 + 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc index af6eb06a122b..7f810ed0b67d 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc @@ -223,9 +223,8 @@ _Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) { } void StackTrace::SlowUnwindStack(uptr pc, uptr max_depth) { + CHECK_GE(max_depth, 2); size = 0; - if (max_depth == 0) - return; 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. @@ -239,14 +238,12 @@ void StackTrace::SlowUnwindStack(uptr pc, uptr max_depth) { void StackTrace::SlowUnwindStackWithContext(uptr pc, void *context, uptr max_depth) { + CHECK_GE(max_depth, 2); if (!unwind_backtrace_signal_arch) { SlowUnwindStack(pc, max_depth); return; } - size = 0; - if (max_depth == 0) return; - void *map = acquire_my_map_info_list(); CHECK(map); InternalScopedBuffer frames(kStackTraceMax); @@ -256,8 +253,9 @@ void StackTrace::SlowUnwindStackWithContext(uptr pc, void *context, /* ignore_depth */ 0, max_depth); release_my_map_info_list(map); if (res < 0) return; - CHECK((uptr)res <= kStackTraceMax); + CHECK_LE((uptr)res, kStackTraceMax); + size = 0; // +2 compensate for libcorkscrew unwinder returning addresses of call // instructions instead of raw return addresses. for (sptr i = 0; i < res; ++i) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc index dbacedc14c12..df1475737479 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc @@ -36,10 +36,7 @@ uptr StackTrace::GetCurrentPc() { void StackTrace::FastUnwindStack(uptr pc, uptr bp, uptr stack_top, uptr stack_bottom, uptr max_depth) { - if (max_depth == 0) { - size = 0; - return; - } + CHECK_GE(max_depth, 2); trace[0] = pc; size = 1; uptr *frame = (uptr *)bp; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc index 4784c200f032..d7d5e9e4a2c5 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc @@ -66,6 +66,17 @@ void StackTrace::PrintStack(const uptr *addr, uptr size) { void StackTrace::Unwind(uptr max_depth, uptr 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) { + size = 0; + return; + } + if (max_depth == 1) { + size = 1; + trace[0] = pc; + return; + } if (!WillUseFastUnwind(request_fast_unwind)) { if (context) SlowUnwindStackWithContext(pc, context, max_depth); @@ -74,8 +85,6 @@ void StackTrace::Unwind(uptr max_depth, uptr pc, uptr bp, void *context, } else { FastUnwindStack(pc, bp, stack_top, stack_bottom, max_depth); } - - top_frame_bp = size ? bp : 0; } } // namespace __sanitizer diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win.cc b/compiler-rt/lib/sanitizer_common/sanitizer_win.cc index 162f37ddce2e..21f92b3b6130 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_win.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_win.cc @@ -417,6 +417,7 @@ void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size, } void StackTrace::SlowUnwindStack(uptr pc, uptr max_depth) { + CHECK_GE(max_depth, 2); // FIXME: CaptureStackBackTrace might be too slow for us. // FIXME: Compare with StackWalk64. // FIXME: Look at LLVMUnhandledExceptionFilter in Signals.inc