Chromium Code Reviews| Index: base/debug/stack_trace.h |
| diff --git a/base/debug/stack_trace.h b/base/debug/stack_trace.h |
| index 23e7b5164b63472409a92e992c5c1095dfa48d26..13287247a2807997bbce1f66e08bef5440bd1dbf 100644 |
| --- a/base/debug/stack_trace.h |
| +++ b/base/debug/stack_trace.h |
| @@ -11,6 +11,7 @@ |
| #include <string> |
| #include "base/base_export.h" |
| +#include "base/macros.h" |
| #include "build/build_config.h" |
| #if defined(OS_POSIX) |
| @@ -113,6 +114,54 @@ class BASE_EXPORT StackTrace { |
| BASE_EXPORT size_t TraceStackFramePointers(const void** out_trace, |
| size_t max_depth, |
| size_t skip_initial); |
| + |
| +// 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(). |
|
Primiano Tucci (use gerrit)
2016/10/13 20:03:21
+0 (i.e. __builtin_frame_address(0))
Dmitry Skiba
2016/10/17 22:09:11
Not necessarily, if __builtin_frame_address(7) wor
|
| +// Destructor restores original linkage of |fp| to avoid corrupting caller's |
| +// frame register on return. |
| +// |
| +// This class can be used to repair broken stack frame chain in cases |
| +// when execution flow goes into code built without frame pointers: |
| +// |
| +// void DoWork() { |
| +// CallJava(); |
| +// } |
| +// static __thread void* g_saved_fp; |
| +// void CallJava() { |
| +// g_saved_fp = __builtin_frame_address(0); |
| +// JNI->Call(...); // indirectly calls JavaCallback() |
| +// } |
| +// void JavaCallback() { |
| +// ScopedStackFrameLinker linker(__builtin_frame_address(0), g_saved_fp); |
| +// ... |
| +// TraceStackFramePointers(...); |
| +// } |
| +// |
| +// This produces the following trace: |
| +// |
| +// #0 JavaCallback() |
| +// #1 <address of the code inside JVM that called JavaCallback> |
| +// #2 DoWork() |
| +// ...rest of the trace... |
| +// |
| +// JVM doesn't use frame pointers, so when JavaCallback() is called back by |
|
Primiano Tucci (use gerrit)
2016/10/13 20:03:21
Honestly I think that these lines of comment (148-
Dmitry Skiba
2016/10/17 22:09:11
The fact that JNI is used in explanation how Scope
|
| +// JVM, stack frame register contains bogus value that becomes JavaCallback's |
| +// parent frame address. Without LinkStackFrames() unwinding would've stopped |
| +// at that bogus frame address yielding just two first frames (#0 and #1). |
| +// LinkStackFrames() overwrites JavaCallback's parent frame address with |
| +// CallJava's frame, so unwinder produces full trace without even noticing |
| +// that stack frame chain was broken. |
| +class BASE_EXPORT ScopedStackFrameLinker { |
| + public: |
| + ScopedStackFrameLinker(void* fp, void* parent_fp); |
| + ~ScopedStackFrameLinker(); |
| + private: |
|
Primiano Tucci (use gerrit)
2016/10/13 20:03:21
nit \n here and below (before disallow)
Dmitry Skiba
2016/10/17 22:09:11
Done.
|
| + void* fp_; |
| + void* original_parent_fp_; |
| + DISALLOW_COPY_AND_ASSIGN(ScopedStackFrameLinker); |
| +}; |
| + |
| #endif // HAVE_TRACE_STACK_FRAME_POINTERS |
| namespace internal { |