v8  10.1.124 (node 18.2.0)
V8 is Google's open source JavaScript engine
v8-unwinder.h
Go to the documentation of this file.
1 // Copyright 2021 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef INCLUDE_V8_UNWINDER_H_
6 #define INCLUDE_V8_UNWINDER_H_
7 
8 #include <memory>
9 
10 #include "v8-embedder-state-scope.h" // NOLINT(build/include_directory)
11 #include "v8config.h" // NOLINT(build/include_directory)
12 
13 namespace v8 {
14 // Holds the callee saved registers needed for the stack unwinder. It is the
15 // empty struct if no registers are required. Implemented in
16 // include/v8-unwinder-state.h.
17 struct CalleeSavedRegisters;
18 
19 // A RegisterState represents the current state of registers used
20 // by the sampling profiler API.
26 
27  void* pc; // Instruction pointer.
28  void* sp; // Stack pointer.
29  void* fp; // Frame pointer.
30  void* lr; // Link register (or nullptr on platforms without a link register).
31  // Callee saved registers (or null if no callee saved registers were stored)
32  std::unique_ptr<CalleeSavedRegisters> callee_saved;
33 };
34 
35 // A StateTag represents a possible state of the VM.
36 enum StateTag : int {
37  JS,
38  GC,
45  IDLE
46 };
47 
48 // The output structure filled up by GetStackSample API function.
49 struct SampleInfo {
50  size_t frames_count; // Number of frames collected.
51  void* external_callback_entry; // External callback address if VM is
52  // executing an external callback.
53  void* context; // Incumbent native context address.
54  void* embedder_context; // Native context address for embedder state
55  StateTag vm_state; // Current VM state.
56  EmbedderStateTag embedder_state; // Current Embedder state
57 };
58 
59 struct MemoryRange {
60  const void* start = nullptr;
61  size_t length_in_bytes = 0;
62 };
63 
64 struct JSEntryStub {
66 };
67 
68 struct JSEntryStubs {
72 };
73 
74 /**
75  * Various helpers for skipping over V8 frames in a given stack.
76  *
77  * The unwinder API is only supported on the x64, ARM64 and ARM32 architectures.
78  */
80  public:
81  /**
82  * Attempt to unwind the stack to the most recent C++ frame. This function is
83  * signal-safe and does not access any V8 state and thus doesn't require an
84  * Isolate.
85  *
86  * The unwinder needs to know the location of the JS Entry Stub (a piece of
87  * code that is run when C++ code calls into generated JS code). This is used
88  * for edge cases where the current frame is being constructed or torn down
89  * when the stack sample occurs.
90  *
91  * The unwinder also needs the virtual memory range of all possible V8 code
92  * objects. There are two ranges required - the heap code range and the range
93  * for code embedded in the binary.
94  *
95  * Available on x64, ARM64 and ARM32.
96  *
97  * \param code_pages A list of all of the ranges in which V8 has allocated
98  * executable code. The caller should obtain this list by calling
99  * Isolate::CopyCodePages() during the same interrupt/thread suspension that
100  * captures the stack.
101  * \param register_state The current registers. This is an in-out param that
102  * will be overwritten with the register values after unwinding, on success.
103  * \param stack_base The resulting stack pointer and frame pointer values are
104  * bounds-checked against the stack_base and the original stack pointer value
105  * to ensure that they are valid locations in the given stack. If these values
106  * or any intermediate frame pointer values used during unwinding are ever out
107  * of these bounds, unwinding will fail.
108  *
109  * \return True on success.
110  */
111  static bool TryUnwindV8Frames(const JSEntryStubs& entry_stubs,
112  size_t code_pages_length,
113  const MemoryRange* code_pages,
114  RegisterState* register_state,
115  const void* stack_base);
116 
117  /**
118  * Whether the PC is within the V8 code range represented by code_pages.
119  *
120  * If this returns false, then calling UnwindV8Frames() with the same PC
121  * and unwind_state will always fail. If it returns true, then unwinding may
122  * (but not necessarily) be successful.
123  *
124  * Available on x64, ARM64 and ARM32
125  */
126  static bool PCIsInV8(size_t code_pages_length, const MemoryRange* code_pages,
127  void* pc);
128 };
129 
130 } // namespace v8
131 
132 #endif // INCLUDE_V8_UNWINDER_H_