diff options
Diffstat (limited to 'contrib/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc')
-rw-r--r-- | contrib/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc b/contrib/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc index 84ff9d9..7862575 100644 --- a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc +++ b/contrib/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc @@ -83,7 +83,18 @@ void BufferedStackTrace::FastUnwindStack(uptr pc, uptr bp, uptr stack_top, while (IsValidFrame((uptr)frame, stack_top, bottom) && IsAligned((uptr)frame, sizeof(*frame)) && size < max_depth) { +#ifdef __powerpc__ + // PowerPC ABIs specify that the return address is saved at offset + // 16 of the *caller's* stack frame. Thus we must dereference the + // back chain to find the caller frame before extracting it. + uhwptr *caller_frame = (uhwptr*)frame[0]; + if (!IsValidFrame((uptr)caller_frame, stack_top, bottom) || + !IsAligned((uptr)caller_frame, sizeof(uhwptr))) + break; + uhwptr pc1 = caller_frame[2]; +#else uhwptr pc1 = frame[1]; +#endif if (pc1 != pc) { trace_buffer[size++] = (uptr) pc1; } @@ -107,7 +118,7 @@ void BufferedStackTrace::PopStackFrames(uptr count) { 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 = 304; + const int kPcThreshold = 320; for (uptr i = 0; i < size; ++i) { if (MatchPc(pc, trace[i], kPcThreshold)) return i; |