fast = false;
#endif
if (!fast)
- return stack->SlowUnwindStack(pc, max_s, 3);
+ return stack->SlowUnwindStack(pc, max_s);
stack->size = 0;
stack->trace[0] = pc;
if (max_s > 1) {
// FIXME: this test does not properly work with slow unwind yet.
// CHECK-FAST: ERROR: AddressSanitizer: heap-buffer-overflow
+// CHECK-FAST: is located 0 bytes to the right
+// CHECK-FAST: #0{{.*}}operator new
+// CHECK-FAST-NEXT: #1{{.*}}QsortCallback
+// CHECK-FAST-NOT: MyQsort
+//
// CHECK-SLOW: ERROR: AddressSanitizer: heap-buffer-overflow
+// CHECK-SLOW: is located 0 bytes to the right
+// CHECK-SLOW: #0{{.*}}operator new
+// CHECK-SLOW-NEXT: #1{{.*}}QsortCallback
+// CHECK-SLOW: #{{.*}}MyQsort
+// CHECK-SLOW-NEXT: #{{.*}}main
return UNWIND_CONTINUE;
}
-void StackTrace::SlowUnwindStack(uptr pc, uptr max_depth, uptr frames_to_pop) {
+static bool MatchPc(uptr cur_pc, uptr trace_pc) {
+ return cur_pc - trace_pc <= 8;
+}
+
+void StackTrace::SlowUnwindStack(uptr pc, uptr max_depth) {
this->size = 0;
- this->trace[0] = pc;
this->max_size = max_depth;
if (max_depth > 1) {
_Unwind_Backtrace(Unwind_Trace, this);
- this->PopStackFrames(frames_to_pop);
+ // We need to pop a few (up to 3) frames so that pc is on top.
+ // trace[0] belongs to the current function.
+ int to_pop = 1;
+ /**/ if (size >= 2 && MatchPc(pc, trace[1])) to_pop = 2;
+ else if (size >= 3 && MatchPc(pc, trace[2])) to_pop = 3;
+ else if (size >= 4 && MatchPc(pc, trace[3])) to_pop = 4;
+ this->PopStackFrames(to_pop);
}
+ this->trace[0] = pc;
}
} // namespace __sanitizer
}
void FastUnwindStack(uptr pc, uptr bp, uptr stack_top, uptr stack_bottom);
- void SlowUnwindStack(uptr pc, uptr max_depth, uptr frames_to_pop);
+ void SlowUnwindStack(uptr pc, uptr max_depth);
void PopStackFrames(uptr count);