Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1926)

Unified Diff: base/debug/stack_trace.h

Issue 2361353002: Link stack frames of JNI stubs to JNI callbacks. (Closed)
Patch Set: Simplify - remove FakeStackFrame, etc. Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 {

Powered by Google App Engine
This is Rietveld 408576698