File: v8-unwinder.h

package info (click to toggle)
chromium 139.0.7258.127-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,122,156 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (133 lines) | stat: -rw-r--r-- 4,763 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef INCLUDE_V8_UNWINDER_H_
#define INCLUDE_V8_UNWINDER_H_

#include <memory>

#include "v8-embedder-state-scope.h"  // NOLINT(build/include_directory)
#include "v8config.h"                 // NOLINT(build/include_directory)

namespace v8 {
// Holds the callee saved registers needed for the stack unwinder. It is the
// empty struct if no registers are required. Implemented in
// include/v8-unwinder-state.h.
struct CalleeSavedRegisters;

// A RegisterState represents the current state of registers used
// by the sampling profiler API.
struct V8_EXPORT RegisterState {
  RegisterState();
  ~RegisterState();
  RegisterState(const RegisterState& other);
  RegisterState& operator=(const RegisterState& other);

  void* pc;  // Instruction pointer.
  void* sp;  // Stack pointer.
  void* fp;  // Frame pointer.
  void* lr;  // Link register (or nullptr on platforms without a link register).
  // Callee saved registers (or null if no callee saved registers were stored)
  std::unique_ptr<CalleeSavedRegisters> callee_saved;
};

// A StateTag represents a possible state of the VM.
enum StateTag : uint16_t {
  JS,
  GC,
  PARSER,
  BYTECODE_COMPILER,
  COMPILER,
  OTHER,
  EXTERNAL,
  ATOMICS_WAIT,
  IDLE,
  LOGGING,
};

// The output structure filled up by GetStackSample API function.
struct SampleInfo {
  size_t frames_count;              // Number of frames collected.
  void* external_callback_entry;    // External callback address if VM is
                                    // executing an external callback.
  void* context;                    // Incumbent native context address.
  void* embedder_context;           // Native context address for embedder state
  StateTag vm_state;                // Current VM state.
  EmbedderStateTag embedder_state;  // Current Embedder state
};

struct MemoryRange {
  const void* start = nullptr;
  size_t length_in_bytes = 0;
};

struct JSEntryStub {
  MemoryRange code;
};

struct JSEntryStubs {
  JSEntryStub js_entry_stub;
  JSEntryStub js_construct_entry_stub;
  JSEntryStub js_run_microtasks_entry_stub;
};

/**
 * Various helpers for skipping over V8 frames in a given stack.
 *
 * The unwinder API is only supported on the x64, ARM64 and ARM32 architectures.
 */
class V8_EXPORT Unwinder {
 public:
  /**
   * Attempt to unwind the stack to the most recent C++ frame. This function is
   * signal-safe and does not access any V8 state and thus doesn't require an
   * Isolate.
   *
   * The unwinder needs to know the location of the JS Entry Stub (a piece of
   * code that is run when C++ code calls into generated JS code). This is used
   * for edge cases where the current frame is being constructed or torn down
   * when the stack sample occurs.
   *
   * The unwinder also needs the virtual memory range of all possible V8 code
   * objects. There are two ranges required - the heap code range and the range
   * for code embedded in the binary.
   *
   * Available on x64, ARM64 and ARM32.
   *
   * \param code_pages A list of all of the ranges in which V8 has allocated
   * executable code. The caller should obtain this list by calling
   * Isolate::CopyCodePages() during the same interrupt/thread suspension that
   * captures the stack.
   * \param register_state The current registers. This is an in-out param that
   * will be overwritten with the register values after unwinding, on success.
   * \param stack_base The resulting stack pointer and frame pointer values are
   * bounds-checked against the stack_base and the original stack pointer value
   * to ensure that they are valid locations in the given stack. If these values
   * or any intermediate frame pointer values used during unwinding are ever out
   * of these bounds, unwinding will fail.
   *
   * \return True on success.
   */
  static bool TryUnwindV8Frames(const JSEntryStubs& entry_stubs,
                                size_t code_pages_length,
                                const MemoryRange* code_pages,
                                RegisterState* register_state,
                                const void* stack_base);

  /**
   * Whether the PC is within the V8 code range represented by code_pages.
   *
   * If this returns false, then calling UnwindV8Frames() with the same PC
   * and unwind_state will always fail. If it returns true, then unwinding may
   * (but not necessarily) be successful.
   *
   * Available on x64, ARM64 and ARM32
   */
  static bool PCIsInV8(size_t code_pages_length, const MemoryRange* code_pages,
                       void* pc);
};

}  // namespace v8

#endif  // INCLUDE_V8_UNWINDER_H_