v8-unwinder.h 4.6 KB

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