diff options
| author | hachem <im@hachem.wtf> | 2025-12-13 12:04:35 +0100 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2025-12-13 12:04:35 +0100 |
| commit | 643287696ea9baccc90a26643b6adb9fabcdf433 (patch) | |
| tree | cc614203c39ad7595f96ae4ffa47c8e2ca5ccc29 /src/debugger/debugger.h | |
| parent | 5529924dec7b1947dc50e1aee6156d43a0ea4e8c (diff) | |
feat: tracing, instrumentation and sampling in the debugger
Diffstat (limited to 'src/debugger/debugger.h')
| -rw-r--r-- | src/debugger/debugger.h | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/src/debugger/debugger.h b/src/debugger/debugger.h index 5e154b2..16bfb6b 100644 --- a/src/debugger/debugger.h +++ b/src/debugger/debugger.h @@ -6,12 +6,18 @@ #include <chrono> #include <cstdint> #include <filesystem> +#include <unordered_map> #include <memory> #include <span> #include <string> #include <string_view> #include <vector> +namespace lldb +{ + class SBThread; +} + namespace Hsdbg { class Debugger @@ -55,6 +61,15 @@ namespace Hsdbg auto clear_traces() -> void; auto traces() const -> std::span<const FunctionTrace> { return m_traces; } + auto timeline() const -> std::span<const TimelineSpan> { return m_timeline; } + + auto span_label(uint32_t trace_id) const -> const char*; + + auto instrumentation_active() const -> bool { return m_instr_available; } + + auto set_sampling_enabled(bool enabled) -> void { m_sampling_enabled = enabled; } + auto sampling_enabled() const -> bool { return m_sampling_enabled; } + auto threads() const -> std::span<const Thread> { return m_threads; } auto call_stack() const -> std::span<const StackFrame> { return m_call_stack; } auto locals() const -> std::span<const Variable> { return m_locals; } @@ -114,8 +129,50 @@ namespace Hsdbg auto resolve_trace(FunctionTrace& trace) -> void; auto handle_trace_stop() -> bool; + auto record_trace_entry(FunctionTrace& trace, lldb::SBThread& thread) -> void; + auto record_trace_return(lldb::SBThread& thread) -> void; auto trace_now() const -> double; + struct InstrRecord; + auto resolve_instrumentation() -> void; + auto read_instrumentation() -> void; + auto apply_instr_record(const InstrRecord& record) -> void; + auto intern_instr_function(uint64_t address) -> uint32_t; + auto symbol_load_address(const char* name) -> uint64_t; + + struct InstrOpenCall + { + uint32_t trace_id = 0; + uint64_t start_ns = 0; + size_t span_index = 0; + }; + + auto maybe_request_sample() -> void; + auto take_sample_and_resume() -> bool; + auto take_sample() -> void; + auto fold_sample(uint64_t thread_id, const std::vector<uint32_t>& stack, double now) -> void; + auto intern_named_function(std::string_view name) -> uint32_t; + + struct OpenSample + { + uint32_t trace_id = 0; + size_t span_index = 0; + }; + + auto ensure_return_breakpoint(uint64_t address) -> int32_t; + auto clear_return_breakpoints() -> void; + + struct PendingCall + { + uint32_t trace_id = 0; + uint64_t thread_id = 0; + uint64_t return_pc = 0; + uint64_t frame_sp = 0; + double start = 0.0; + size_t call_index = 0; + size_t span_index = 0; + }; + std::unique_ptr<Session> m_session; TargetState m_state = TargetState::NoTarget; @@ -129,6 +186,10 @@ namespace Hsdbg std::vector<FunctionTrace> m_traces; uint32_t m_next_trace_id = 1; + std::vector<PendingCall> m_pending_calls; + std::vector<TimelineSpan> m_timeline; + + std::unordered_map<uint64_t, int32_t> m_return_breakpoints; std::vector<Thread> m_threads; std::vector<StackFrame> m_call_stack; @@ -147,5 +208,23 @@ namespace Hsdbg uint64_t m_resident_memory = 0; std::chrono::steady_clock::time_point m_trace_epoch = std::chrono::steady_clock::now(); + + bool m_instr_checked = false; + bool m_instr_available = false; + uint64_t m_instr_head_addr = 0; + uint64_t m_instr_records_addr = 0; + uint64_t m_instr_capacity = 0; + uint64_t m_instr_read_count = 0; + uint64_t m_instr_base_ns = 0; + bool m_instr_base_set = false; + std::unordered_map<uint64_t, uint32_t> m_instr_functions; + std::unordered_map<uint32_t, std::string> m_instr_names; + std::unordered_map<uint64_t, std::vector<InstrOpenCall>> m_instr_stacks; + + bool m_sampling_enabled = false; + bool m_sample_pending = false; + std::chrono::steady_clock::time_point m_sample_last{}; + std::unordered_map<std::string, uint32_t> m_sample_functions; + std::unordered_map<uint64_t, std::vector<OpenSample>> m_sample_stacks; }; } |
