| Index: base/debug/stack_trace.cc
|
| diff --git a/base/debug/stack_trace.cc b/base/debug/stack_trace.cc
|
| index f3ffef360f0680a8a36cdabc4fa43c5ee1fc390c..fb2f6b508f2e0e582299e4321c9b5ef117cd8e53 100644
|
| --- a/base/debug/stack_trace.cc
|
| +++ b/base/debug/stack_trace.cc
|
| @@ -9,6 +9,7 @@
|
| #include <algorithm>
|
| #include <sstream>
|
|
|
| +#include "base/logging.h"
|
| #include "base/macros.h"
|
|
|
| #if HAVE_TRACE_STACK_FRAME_POINTERS
|
| @@ -176,6 +177,17 @@ uintptr_t ScanStackForNextFrame(uintptr_t fp, uintptr_t stack_end) {
|
| return 0;
|
| }
|
|
|
| +// Links stack frame |fp| to |parent_fp|, so that during stack unwinding
|
| +// TraceStackFramePointers() visits |parent_fp| after visiting |fp|.
|
| +// Both frame pointers must come from __builtin_frame_address().
|
| +// Returns previous stack frame |fp| was linked to.
|
| +void* LinkStackFrames(void* fpp, void* parent_fp) {
|
| + uintptr_t fp = reinterpret_cast<uintptr_t>(fpp) - kStackFrameAdjustment;
|
| + void* prev_parent_fp = reinterpret_cast<void**>(fp)[0];
|
| + reinterpret_cast<void**>(fp)[0] = parent_fp;
|
| + return prev_parent_fp;
|
| +}
|
| +
|
| #endif // HAVE_TRACE_STACK_FRAME_POINTERS
|
|
|
| } // namespace
|
| @@ -245,6 +257,17 @@ size_t TraceStackFramePointers(const void** out_trace,
|
| return depth;
|
| }
|
|
|
| +ScopedStackFrameLinker::ScopedStackFrameLinker(void* fp, void* parent_fp)
|
| + : fp_(fp),
|
| + parent_fp_(parent_fp),
|
| + original_parent_fp_(LinkStackFrames(fp, parent_fp)) {}
|
| +
|
| +ScopedStackFrameLinker::~ScopedStackFrameLinker() {
|
| + void* previous_parent_fp = LinkStackFrames(fp_, original_parent_fp_);
|
| + CHECK_EQ(parent_fp_, previous_parent_fp)
|
| + << "Stack frame's parent pointer has changed!";
|
| +}
|
| +
|
| #endif // HAVE_TRACE_STACK_FRAME_POINTERS
|
|
|
| } // namespace debug
|
|
|