summaryrefslogtreecommitdiff
path: root/contrib/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc')
-rw-r--r--contrib/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc13
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 84ff9d9d9e3b..7862575b37bb 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;