Index: /home/seurer/llvm/llvm-test/projects/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h =================================================================== --- /home/seurer/llvm/llvm-test/projects/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h +++ /home/seurer/llvm/llvm-test/projects/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h @@ -19,8 +19,7 @@ static const u32 kStackTraceMax = 256; -#if SANITIZER_LINUX && (defined(__aarch64__) || defined(__powerpc__) || \ - defined(__powerpc64__) || defined(__sparc__) || \ +#if SANITIZER_LINUX && (defined(__aarch64__) || defined(__sparc__) || \ defined(__mips__)) # define SANITIZER_CAN_FAST_UNWIND 0 #elif SANITIZER_WINDOWS @@ -105,7 +104,7 @@ void SlowUnwindStack(uptr pc, u32 max_depth); void SlowUnwindStackWithContext(uptr pc, void *context, u32 max_depth); - void PopStackFrames(uptr count); + void PopStackFramesToPC(uptr pc); uptr LocatePcInTrace(uptr pc); BufferedStackTrace(const BufferedStackTrace &); Index: /home/seurer/llvm/llvm-test/projects/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc =================================================================== --- /home/seurer/llvm/llvm-test/projects/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc +++ /home/seurer/llvm/llvm-test/projects/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc @@ -17,6 +17,16 @@ namespace __sanitizer { + +#if defined(__powerpc__) || defined(__powerpc64__) + static const int kOffsetToPcInFrame = 2; + static const bool kFastUnwindPopFramesToPC = true; +#else + static const int kOffsetToPcInFrame = 1; + static const bool kFastUnwindPopFramesToPC = false; +#endif + + uptr StackTrace::GetNextInstructionPc(uptr pc) { #if defined(__mips__) return pc + 8; @@ -83,25 +93,39 @@ while (IsValidFrame((uptr)frame, stack_top, bottom) && IsAligned((uptr)frame, sizeof(*frame)) && size < max_depth) { - uhwptr pc1 = frame[1]; + uhwptr pc1 = frame[kOffsetToPcInFrame]; if (pc1 != pc) { trace_buffer[size++] = (uptr) pc1; } bottom = (uptr)frame; frame = GetCanonicFrame((uptr)frame[0], stack_top, bottom); } + if (kFastUnwindPopFramesToPC) { + PopStackFramesToPC(pc); + } } 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; +void BufferedStackTrace::PopStackFramesToPC(uptr pc) { + uptr to_pop = LocatePcInTrace(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!). + // 1-frame stacks don't normally happen, but this depends on the actual + // unwinder implementation (libgcc, libunwind, etc) which is outside of our + // control. + if (to_pop == 0 && size > 1) + to_pop = 1; + + CHECK_LT(to_pop, size); + size -= to_pop; for (uptr i = 0; i < size; ++i) { - trace_buffer[i] = trace_buffer[i + count]; + trace_buffer[i] = trace_buffer[i + to_pop]; } + trace_buffer[0] = pc; } uptr BufferedStackTrace::LocatePcInTrace(uptr pc) { Index: /home/seurer/llvm/llvm-test/projects/compiler-rt/lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cc =================================================================== --- /home/seurer/llvm/llvm-test/projects/compiler-rt/lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cc +++ /home/seurer/llvm/llvm-test/projects/compiler-rt/lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cc @@ -114,17 +114,7 @@ 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); - // 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!). - // 1-frame stacks don't normally happen, but this depends on the actual - // unwinder implementation (libgcc, libunwind, etc) which is outside of our - // control. - if (to_pop == 0 && size > 1) - to_pop = 1; - PopStackFrames(to_pop); - trace_buffer[0] = pc; + PopStackFramesToPC(pc); } void BufferedStackTrace::SlowUnwindStackWithContext(uptr pc, void *context, Index: /home/seurer/llvm/llvm-test/projects/compiler-rt/lib/sanitizer_common/sanitizer_unwind_posix_libcdep.cc =================================================================== --- /home/seurer/llvm/llvm-test/projects/compiler-rt/lib/sanitizer_common/sanitizer_unwind_posix_libcdep.cc +++ /home/seurer/llvm/llvm-test/projects/compiler-rt/lib/sanitizer_common/sanitizer_unwind_posix_libcdep.cc @@ -113,18 +113,9 @@ 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); - // 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!). - // 1-frame stacks don't normally happen, but this depends on the actual - // unwinder implementation (libgcc, libunwind, etc) which is outside of our - // control. - if (to_pop == 0 && size > 1) - to_pop = 1; - PopStackFrames(to_pop); - trace_buffer[0] = pc; + PopStackFramesToPC(pc); } void BufferedStackTrace::SlowUnwindStackWithContext(uptr pc, void *context,