pub struct Session {
pub target: Target,
pub backend: Box<dyn DebugBackend>,
pub breakpoints: BreakpointManager,
pub register_map: RegisterMap,
pub current_thread: String,
pub exception_policies: ExceptionPolicyTable,
pub reload_module_list_pending: bool,
pub last_event: Option<LastEvent>,
/* private fields */
}Expand description
The root owner of a live debugging session: the introspection context, the backend that drives the target, and the session state layered on top.
Fields§
§target: Target§backend: Box<dyn DebugBackend>§breakpoints: BreakpointManager§register_map: RegisterMap§current_thread: String§exception_policies: ExceptionPolicyTablePer-exception-code stop policy (sxe/sxd/sxn/sxi). Session state
so every host shares one table: the REPL loop applies it (including
its -c commands), and the shared Self::wait_for_stop_bounded
auto-continues the command-free Continue policies for the SDK/MCP.
reload_module_list_pending: boolWhether a guest reload is mid-flight with the loaded-module list not yet
available (very early boot). Carried across continue_until_break calls
so the post-reboot KD-reconnect dance runs to completion; when the list
appears, Self::try_complete_pending_reload finishes rediscovery and
stops the backend’s reconnect-assist poking. The single owner of that
state; hosts read it rather than reimplement it.
last_event: Option<LastEvent>Most recently observed backend stop and the disposition used when it was subsequently continued.
Implementations§
Source§impl Session
impl Session
Sourcepub fn open(spec: &TargetSpec) -> Result<Self>
pub fn open(spec: &TargetSpec) -> Result<Self>
Attach per spec: open a dump, or connect the chosen live backend.
The one construction path shared by the CLI, MCP, and Python hosts, so
backend selection, endpoint defaults, and instance locking cannot
drift between them.
kd/kdnet/gdb take a per-target instance lock before building the backend, so a second attach against the same resource fails fast rather than racing on the handshake; dumps and passive memory are read-only and coexist with anything.
Sourcepub fn open_with_progress(
spec: &TargetSpec,
progress: &mut dyn FnMut(&str),
) -> Result<Self>
pub fn open_with_progress( spec: &TargetSpec, progress: &mut dyn FnMut(&str), ) -> Result<Self>
Self::open, reporting connection progress (transport banners, the
KD wait for a target, the memory-source decision) through progress
one line at a time. Only live KD attaches report anything.
Sourcepub fn connect<F>(
phys: Arc<PhysMem>,
target: Option<&str>,
make_backend: F,
) -> Result<Self>
pub fn connect<F>( phys: Arc<PhysMem>, target: Option<&str>, make_backend: F, ) -> Result<Self>
Acquire the single-instance lock for target (None for read-only
backends that are safe to share), then connect a backend via
make_backend and build the owned session.
Sourcepub fn connect_kd<F>(
resource: &str,
memory_source: KdMemorySource,
progress: &mut dyn FnMut(&str),
make_backend: F,
) -> Result<Self>
pub fn connect_kd<F>( resource: &str, memory_source: KdMemorySource, progress: &mut dyn FnMut(&str), make_backend: F, ) -> Result<Self>
Connect KD/KDNET, select a validated memory source, and build the
session. Auto prefers matching host VM memory and safely falls back to
target-mediated KD physical-memory requests. Connection progress and
the memory-source decision are reported through progress.
Sourcepub fn new(phys: Arc<PhysMem>, backend: Box<dyn DebugBackend>) -> Result<Self>
pub fn new(phys: Arc<PhysMem>, backend: Box<dyn DebugBackend>) -> Result<Self>
Build a session around an already-connected backend and physical-memory
source. Hosts normally use Self::connect or Self::connect_kd.
Sourcepub fn step(&mut self) -> Result<()>
pub fn step(&mut self) -> Result<()>
Single-step one instruction on the currently selected thread. If RIP sits
on one of our breakpoints, do the disable/step/enable dance; otherwise
plain step + trap-flag clear. Afterward re-arm enabled breakpoints (the
stub can drop non-hit ones on a stop) and re-select the landed-on thread.
The full “step one instruction”, shared by the REPL (si) and the SDK.
Sourcepub fn set_current_thread(&mut self, id: &str) -> Result<()>
pub fn set_current_thread(&mut self, id: &str) -> Result<()>
Select id as the current inspection thread (e.g. a vCPU id), so
registers/backtrace/step operate on it. Validates the id against the
backend. Shared by the REPL’s thread/vcpu commands and the SDKs.
Sourcepub fn select_parked_windows_thread(&mut self, thread: &ThreadInfo)
pub fn select_parked_windows_thread(&mut self, thread: &ThreadInfo)
Select a non-running Windows thread for metadata and stack inspection without changing the backend vCPU. This deliberately does not attempt to manufacture a register context for the parked thread.
Sourcepub fn select_frame(&mut self, selected: SelectedFrame)
pub fn select_frame(&mut self, selected: SelectedFrame)
Install a debugger-selected frame/context as the inspection context:
its recovered registers shadow the live ones and its address space
becomes the expression/memory scope. Shared by the REPL’s .frame /
.cxr / .trap and the DAP frame selection so the two can’t drift.
pub fn parked_windows_thread(&self) -> Option<&ThreadInfo>
Sourcepub fn windows_thread_candidates(&mut self) -> Result<Vec<ThreadInfo>>
pub fn windows_thread_candidates(&mut self) -> Result<Vec<ThreadInfo>>
Every Windows thread the target knows plus the ones currently on a vCPU (which a mid-creation walk may not list yet). The candidate set for selecting a thread by tid/ETHREAD/KTHREAD.
Sourcepub fn find_windows_thread(&mut self, value: u64) -> Result<ThreadInfo>
pub fn find_windows_thread(&mut self, value: u64) -> Result<ThreadInfo>
The one Windows thread value names: a thread id, an ETHREAD, or a
KTHREAD address. Ambiguity (a tid colliding with an address) is an
error rather than a guess.
Sourcepub fn select_windows_thread(
&mut self,
thread: &ThreadInfo,
) -> Result<Option<String>>
pub fn select_windows_thread( &mut self, thread: &ThreadInfo, ) -> Result<Option<String>>
Make thread the inspection context (.thread): a thread that is on
a vCPU switches the live register context to that vCPU; any other
thread is parked (stack-only, no coherent register file). Returns the
vCPU id when the selection is live.
Sourcepub fn reset_windows_thread(&mut self) -> Result<()>
pub fn reset_windows_thread(&mut self) -> Result<()>
Drop any Windows-thread selection and return to the backend’s current
vCPU context (.thread with no argument).
Sourcepub fn select_frame_index(&mut self, index: usize) -> Result<SelectedFrame>
pub fn select_frame_index(&mut self, index: usize) -> Result<SelectedFrame>
Select stack frame index (.frame N) of the current live thread as
the inspection context, so registers, locals, and expressions see that
frame’s recovered register file. Returns the frame. A parked thread has
no register file to unwind from and is refused.
Sourcepub fn restore_live_register_cache(&mut self)
pub fn restore_live_register_cache(&mut self)
Refill the target’s register cache from the live backend context, or clear it while the VM runs or a parked thread is selected, so expression evaluation follows the current thread’s address space.
Sourcepub fn clear_selected_frame(&mut self)
pub fn clear_selected_frame(&mut self)
Forget a selected frame/context and go back to the live register file
(.frame reset / .cxr with no argument).
Sourcepub fn recovered_live_trace(
&mut self,
limit: usize,
) -> Result<(RecoveredStackTrace, HashMap<String, u64>, bool)>
pub fn recovered_live_trace( &mut self, limit: usize, ) -> Result<(RecoveredStackTrace, HashMap<String, u64>, bool)>
Unwind limit frames from the current context: the selected frame’s
seed registers when one is selected, else the live vCPU file. Returns
the trace, the seed register values, and whether that seed is the
vCPU’s own register file (a .cxr/.trap context is not).
Sourcepub fn record_stop_event(&mut self, event: &StopEvent)
pub fn record_stop_event(&mut self, event: &StopEvent)
Record a raw backend stop for .lastevent and typed hosts. REPL paths
that own their richer wait loop call this at the same boundary as the
session wait helpers.
Sourcepub fn record_continuation_disposition(
&mut self,
disposition: ContinueDisposition,
)
pub fn record_continuation_disposition( &mut self, disposition: ContinueDisposition, )
Attach the acknowledgment chosen for the current stop. A successful continuation calls this after the backend accepts the request.
Sourcepub fn interrupt(&mut self) -> Result<StopEvent>
pub fn interrupt(&mut self) -> Result<StopEvent>
Pause the VM and return the first meaningful stop. Every raw event routes
through Self::classify_stop_event, so an interrupt that races with a
filtered breakpoint or reconnect-assist stop cannot bypass core state.
Bounded: while the guest is rebooting (reconnect assist) or hammering a
wrong-process breakpoint, every break-in can classify as noise and be
resumed; after [INTERRUPT_MAX_RESUMES] of those the last stop is
surfaced as-is rather than spinning forever (the ^D exit path lives on
this).
Sourcepub fn interrupt_outcome(&mut self) -> Result<ContinueOutcome>
pub fn interrupt_outcome(&mut self) -> Result<ContinueOutcome>
Self::interrupt keeping the classification: a breakpoint hit that
races the break-in is reported as that breakpoint (with its action and
condition result) rather than as a bare STATUS_BREAKPOINT stop. A
target that is not running is not broken into (KD would wait out its
break-in timeout): a stop parked by Self::with_target_halted or
Self::service_idle is surfaced, and a plain halt reports its pc.
Sourcepub fn with_target_halted<T>(
&mut self,
edit: impl FnOnce(&mut Session) -> Result<T>,
) -> Result<T>
pub fn with_target_halted<T>( &mut self, edit: impl FnOnce(&mut Session) -> Result<T>, ) -> Result<T>
Run edit with the target halted, restoring the previous run state.
If the target is already halted, edit runs directly and neither
interrupts nor resumes the backend. If it is running, this method breaks
in, runs edit, and resumes afterward unless the interrupt exposed a
genuine pending stop. Such a stop is left halted and parked for the next
Self::wait_for_stop_bounded, while an edit error still resumes an
otherwise ordinary break-in before returning the error. This primitive is
shared by hosts that edit breakpoint state; it emits no notifications.
Sourcepub fn halt_for_exit(&mut self) -> Result<()>
pub fn halt_for_exit(&mut self) -> Result<()>
Bring the target to a real halt before teardown: consume a stop that is already pending if it is meaningful, else break in. The REPL’s ^D path.
Sourcepub fn current_instruction(&mut self) -> Result<CurrentInstruction>
pub fn current_instruction(&mut self) -> Result<CurrentInstruction>
Decode the instruction at the current thread’s program counter, masking any software-breakpoint patch and reading through the thread’s preferred code DTB. Selects the current thread first; the VM must be halted.
Sourcepub fn step_over_target(&mut self) -> Result<StepKind>
pub fn step_over_target(&mut self) -> Result<StepKind>
Compute the step-over plan for the current instruction: run to the
instruction after a call, otherwise a plain single-step. The shared
decision used by the REPL p and Self::step_over.
Sourcepub fn step_out_target(&mut self) -> Result<VirtAddr>
pub fn step_out_target(&mut self) -> Result<VirtAddr>
The current frame’s caller return address (the step-out target). Walks a
few frames of the current thread’s stack and returns the second frame’s
IP. Shared by the REPL gu and Self::step_out.
Sourcepub fn run_to(
&mut self,
address: VirtAddr,
cancel: &AtomicBool,
) -> Result<ContinueOutcome>
pub fn run_to( &mut self, address: VirtAddr, cancel: &AtomicBool, ) -> Result<ContinueOutcome>
Run until address is reached. If a breakpoint is already set there in
the current context this is a plain Self::continue_until_break;
otherwise it installs a temporary breakpoint, runs to it, removes it, and
reports reaching it as ContinueOutcome::Step. A different breakpoint,
bugcheck, or exception en route is surfaced as-is. Blocks until a stop
(checking cancel between polls); on cancel it halts, removes the temp
breakpoint, and returns ContinueOutcome::Running. The run-to-address
primitive behind Self::step_over / Self::step_out.
Sourcepub fn step_over(&mut self, cancel: &AtomicBool) -> Result<ContinueOutcome>
pub fn step_over(&mut self, cancel: &AtomicBool) -> Result<ContinueOutcome>
Step over the current instruction: single-step it, or, if it’s a call,
run to the instruction after it (ContinueOutcome::Step on completion).
Shared by the REPL p (target only) and the SDKs.
Sourcepub fn step_out(&mut self, cancel: &AtomicBool) -> Result<ContinueOutcome>
pub fn step_out(&mut self, cancel: &AtomicBool) -> Result<ContinueOutcome>
Step out of the current function: run to the caller’s return address.
Sourcepub fn read_registers(&mut self) -> Result<Vec<u8>>
pub fn read_registers(&mut self) -> Result<Vec<u8>>
Read the selected live vCPU register file. A parked Windows thread is a stack-only inspection target and must never fall through to the backend’s unrelated live register context.
Sourcepub fn write_register(&mut self, name: &str, value: u64) -> Result<()>
pub fn write_register(&mut self, name: &str, value: u64) -> Result<()>
Set a single register on the current thread by name, as a read-modify- write of the register file (read all, patch the one, write back).
Sourcepub fn capabilities(&self) -> Vec<BackendCapability>
pub fn capabilities(&self) -> Vec<BackendCapability>
The backend’s capability matrix (what the current transport supports), so a host can report unsupported operations up front instead of by failure.
Sourcepub fn read_debug_output(&self, since_seq: u64) -> DebugOutputPage
pub fn read_debug_output(&self, since_seq: u64) -> DebugOutputPage
Read captured guest debug output (DbgPrint) at or after since_seq.
Snapshot+cursor: pass the previous page’s next_seq to poll only new
lines. Empty on backends without a native debug stream (gdb/memory); see
DebugCapability::DebugOutput.
Sourcepub fn kernel_coherent(&self) -> bool
pub fn kernel_coherent(&self) -> bool
Whether kernel structures are safe to read: the loaded-module list is
populated (not early boot / mid-rediscovery) and the kernel base still
reads MZ (no undetected reboot).
Sourcepub fn settle_pending_stop(&mut self) -> Result<()>
pub fn settle_pending_stop(&mut self) -> Result<()>
Drain a stop the background servicer has already caught without advancing
to a later event. This makes a physically halted VM visible even while
is_running() still holds stale running state.
Debugger-generated noise is still absorbed so read/status surfaces match
normal run control. Reload stops keep their deferred TargetReloaded
notification for the next wait surface.
Sourcepub fn service_idle(&mut self)
pub fn service_idle(&mut self)
Service the guest while the host is otherwise idle: absorb a stop the
background servicer caught but no tool call has drained (chiefly a
wrong-process hit on a shared-page breakpoint), so the guest is not left
frozen between tool calls. Noise is resumed; a real stop is parked for
the next wait_for_stop.
Sourcepub fn take_parked_stop(&mut self) -> Option<ContinueOutcome>
pub fn take_parked_stop(&mut self) -> Option<ContinueOutcome>
Hand over a stop Self::service_idle parked while the host was idle,
for hosts that render stops themselves rather than through
Self::wait_for_stop_bounded. The VM is halted at it.
Sourcepub fn stopped_context(&mut self) -> (Option<ProcessInfo>, Option<ThreadInfo>)
pub fn stopped_context(&mut self) -> (Option<ProcessInfo>, Option<ThreadInfo>)
Resolve the stopped vCPU’s process and Windows thread from the target. Select that thread for inspection. The attached process scope is separate and persists across resumes.
Sourcepub fn run_status(&mut self) -> RunStatus
pub fn run_status(&mut self) -> RunStatus
A read-only run-control snapshot for the “where am I” surface (see
RunStatus). When halted, selects the current thread and resolves
rip+symbol (best-effort); while running, leaves those None. Reports
coherent: false while a post-reboot rediscovery is still pending so a
host waits instead of enumerating stale state.
Sourcepub fn add_breakpoint(
&mut self,
addr: VirtAddr,
symbol: Option<String>,
config: BreakpointConfig,
) -> Result<u32>
pub fn add_breakpoint( &mut self, addr: VirtAddr, symbol: Option<String>, config: BreakpointConfig, ) -> Result<u32>
Set a code breakpoint at addr with an optional display symbol and
its configuration (condition, pass count, one-shot, command action;
BreakpointConfig::default() for a plain one). The breakpoint’s scope
is derived from the current inspection context at install time.
Returns the breakpoint id.
Sourcepub fn add_symbol_breakpoint(
&mut self,
symbol: String,
config: BreakpointConfig,
) -> Result<u32>
pub fn add_symbol_breakpoint( &mut self, symbol: String, config: BreakpointConfig, ) -> Result<u32>
Set a symbol-identity breakpoint: it survives module unload/reload and may remain deferred until matching symbols are loaded.
Sourcepub fn add_source_breakpoint(
&mut self,
source: String,
config: BreakpointConfig,
) -> Result<Vec<u32>>
pub fn add_source_breakpoint( &mut self, source: String, config: BreakpointConfig, ) -> Result<Vec<u32>>
Set one source identity for every address matching file:line, or one
deferred identity when no matching module is currently loaded. Returns
one id per matching address (or the single deferred id).
Sourcepub fn add_pattern_breakpoints(
&mut self,
pattern: &str,
config: BreakpointConfig,
limit: usize,
) -> Result<(Vec<u32>, Vec<Error>)>
pub fn add_pattern_breakpoints( &mut self, pattern: &str, config: BreakpointConfig, limit: usize, ) -> Result<(Vec<u32>, Vec<Error>)>
Set one symbol-identity breakpoint per symbol matching pattern
(bm): */? globs, optionally module!-qualified; at most limit
matches. Returns the ids created, and the count of matches that
failed to install (already reported through errors).
Sourcepub fn breakpoint_scope_for_pid(&self, pid: u64) -> Result<BreakpointScope>
pub fn breakpoint_scope_for_pid(&self, pid: u64) -> Result<BreakpointScope>
The /p <pid> breakpoint scope: hits are reported only from that
process’s address space.
Sourcepub fn set_breakpoint_condition(
&mut self,
id: u32,
condition: Option<String>,
) -> Result<()>
pub fn set_breakpoint_condition( &mut self, id: u32, condition: Option<String>, ) -> Result<()>
Replace (or clear) a breakpoint’s condition, compiling it with the default expression grammar.
Sourcepub fn add_watchpoint(
&mut self,
addr: VirtAddr,
access: WatchpointAccess,
len: u8,
symbol: Option<String>,
config: BreakpointConfig,
) -> Result<u32>
pub fn add_watchpoint( &mut self, addr: VirtAddr, access: WatchpointAccess, len: u8, symbol: Option<String>, config: BreakpointConfig, ) -> Result<u32>
Watch data accesses at addr (global across guest address spaces),
with an optional host-resolved display symbol. Hosts choose write or
read/write behavior while the backend implementation remains private.
Returns the stop-point id.
Sourcepub fn remove_breakpoint(&mut self, id: u32) -> Result<()>
pub fn remove_breakpoint(&mut self, id: u32) -> Result<()>
Remove a breakpoint by id.
Sourcepub fn enable_breakpoint(&mut self, id: u32) -> Result<()>
pub fn enable_breakpoint(&mut self, id: u32) -> Result<()>
Re-arm a disabled breakpoint (re-patch its int3).
Sourcepub fn disable_breakpoint(&mut self, id: u32) -> Result<()>
pub fn disable_breakpoint(&mut self, id: u32) -> Result<()>
Disable a breakpoint (restore the original byte) without forgetting it, so it can be re-enabled later.
Sourcepub fn list_breakpoints(&self) -> Vec<&Breakpoint>
pub fn list_breakpoints(&self) -> Vec<&Breakpoint>
List all breakpoints.
Sourcepub fn breakpoint(&self, id: u32) -> Option<&Breakpoint>
pub fn breakpoint(&self, id: u32) -> Option<&Breakpoint>
Return one breakpoint by id.
Sourcepub fn vcpus(&mut self) -> Result<Vec<VcpuInfo>>
pub fn vcpus(&mut self) -> Result<Vec<VcpuInfo>>
Inspect every backend execution context (vCPU): its RIP, the address space it is running in (kernel / a process / unknown), and the nearest symbol. Selects each vCPU in turn to read its register file, then restores the originally-stopped one. The VM must be halted.
Sourcepub fn active_thread_map(&mut self) -> HashMap<u64, (String, ThreadInfo)>
pub fn active_thread_map(&mut self) -> HashMap<u64, (String, ThreadInfo)>
Map each active Windows thread (one currently scheduled on a vCPU) to
the vCPU running it and its ThreadInfo, keyed by ETHREAD address.
Walks every backend vCPU, resolves the Windows thread it is executing,
and restores the originally-stopped vCPU. Best-effort (empty map if the
backend can’t enumerate vCPUs).
Sourcepub fn windows_threads(
&mut self,
) -> Result<(Vec<ThreadInfo>, HashMap<u64, String>)>
pub fn windows_threads( &mut self, ) -> Result<(Vec<ThreadInfo>, HashMap<u64, String>)>
Enumerate all Windows threads, merged with the currently-active threads
(so a thread scheduled on a vCPU but absent from the walk is still
included), sorted by (pid, tid). Returns the threads plus a map of
ETHREAD -> vCPU id for those currently running; hosts apply their own
filtering/rendering.
Sourcepub fn read_masked(&self, addr: VirtAddr, buf: &mut [u8]) -> Result<()>
pub fn read_masked(&self, addr: VirtAddr, buf: &mut [u8]) -> Result<()>
Read guest virtual memory in the current inspection context with our own breakpoint patch bytes masked back to the original code, so every host (REPL, MCP, SDK) sees the same bytes the guest would run.
Sourcepub fn disassemble(
&self,
addr: VirtAddr,
count: usize,
) -> Result<Vec<DisasmRow>>
pub fn disassemble( &self, addr: VirtAddr, count: usize, ) -> Result<Vec<DisasmRow>>
Disassemble count instructions starting at addr in the current
address space. Our own breakpoint int3 bytes are masked back to the
original opcode, and branch / rip-relative targets get symbol comments.
Sourcepub fn recovered_backtrace(
&mut self,
limit: usize,
) -> Result<(RecoveredStackTrace, HashMap<String, u64>)>
pub fn recovered_backtrace( &mut self, limit: usize, ) -> Result<(RecoveredStackTrace, HashMap<String, u64>)>
The current backend context’s call stack with the sparse registers recovered for every frame, plus the seed register file the walk started from. A parked Windows thread is walked from its saved context without touching the backend vCPU.
Sourcepub fn backtrace(&mut self, limit: usize) -> Result<StackTrace>
pub fn backtrace(&mut self, limit: usize) -> Result<StackTrace>
Walk the currently selected backend context’s call stack, returning up to
limit frames. A parked Windows thread uses stack-only recovery without
touching the backend vCPU.
Sourcepub fn backtrace_thread(
&self,
thread: &ThreadInfo,
limit: usize,
) -> Result<ThreadStackTrace>
pub fn backtrace_thread( &self, thread: &ThreadInfo, limit: usize, ) -> Result<ThreadStackTrace>
Unwind a specified non-running Windows thread in its owning process address space without selecting it or mutating the backend vCPU.
Sourcepub fn remove_all_breakpoints(&mut self) -> Result<()>
pub fn remove_all_breakpoints(&mut self) -> Result<()>
Uninstall every breakpoint. Successful removals are forgotten; failed removals remain managed so callers can retry and must not resume the target as if cleanup had succeeded.
Sourcepub fn cleanup_for_exit(&mut self) -> Result<()>
pub fn cleanup_for_exit(&mut self) -> Result<()>
Leave the target in a usable state when a frontend exits: halt first if needed, restore every debugger-owned breakpoint site, and resume only when both operations succeed. Any failure explicitly prepares the backend to leave the target halted.
Sourcepub fn resume(&mut self) -> Result<()>
pub fn resume(&mut self) -> Result<()>
Resume the VM. If sitting on one of our breakpoints, step past it first
(otherwise the int3 at RIP re-fires immediately), re-arm enabled
breakpoints, then continue and drop the now-stale inspection caches.
The canonical resume prologue, shared by the REPL and the SDK.
Does not poll for Ctrl+C or handle KD target-reload/reconnect the way the REPL’s continue loop does; those remain REPL concerns.
Sourcepub fn clear_resume_state(&mut self)
pub fn clear_resume_state(&mut self)
Clear every inspection cache that cannot survive a crash/reboot command before the shared wait loop re-establishes the next stop.
Sourcepub fn resume_with_disposition(
&mut self,
disposition: ContinueDisposition,
) -> Result<()>
pub fn resume_with_disposition( &mut self, disposition: ContinueDisposition, ) -> Result<()>
Resume with an explicit exception acknowledgment while preserving the
same breakpoint step-over and cache invalidation prologue as Self::resume.
Sourcepub fn resolve_breakpoint_stop(
&mut self,
rip: u64,
cr3: u64,
) -> Result<BreakpointStopAction>
pub fn resolve_breakpoint_stop( &mut self, rip: u64, cr3: u64, ) -> Result<BreakpointStopAction>
Classify a freshly observed stop at (rip, cr3) against our breakpoints,
performing the absorb actions the caller shouldn’t have to: a false
conditional breakpoint or a wrong-process hit on a shared-page int3 is
stepped over and resumed, returning BreakpointStopAction::Resumed. A
real hit re-arms enabled breakpoints (the stub can drop non-hit ones on a
stop) and returns its details. The caller must have read registers and
established (rip, cr3) for the stopped thread first.
Shared by Self::continue_until_break and the REPL’s continue loop so
they can’t drift on which int3 hits surface and which are silently resumed.
Sourcepub fn refresh_modules_on_stop(&mut self) -> bool
pub fn refresh_modules_on_stop(&mut self) -> bool
Consult and clear the module-change signals, reconciling symbolic breakpoints when the module set moved. Returns whether it moved. The KD event signal and the per-stop module-list refresh are joined here so all hosts share the same deferred-breakpoint behavior; refresh and reconciliation failures are logged and do not discard the stop.
Sourcepub fn take_module_refresh_report(&mut self) -> Option<ModuleSymbolLoadReport>
pub fn take_module_refresh_report(&mut self) -> Option<ModuleSymbolLoadReport>
Take the latest module-symbol report for the REPL’s existing summary. The report is private to the REPL’s summary path.
Sourcepub fn take_notices(&mut self) -> Vec<String>
pub fn take_notices(&mut self) -> Vec<String>
Drain the diagnostics core and backend raised since the last drain, in the order they happened. Hosts call this at each output boundary.
Sourcepub fn classify_stop_event(
&mut self,
event: StopEvent,
) -> Result<StopResolution>
pub fn classify_stop_event( &mut self, event: StopEvent, ) -> Result<StopResolution>
Classify one raw backend stop and perform every core-owned transition.
This is the only stop-ingestion state machine. REPL, MCP, Python, and
idle servicing may differ in polling and presentation, but must route
raw events here so reload handling, DR acknowledgment, scope checks,
int3 rewind, conditions, and auto-resume behavior cannot drift.
Sourcepub fn continue_until_break(
&mut self,
timeout: Option<Duration>,
cancel: &AtomicBool,
disposition: ContinueDisposition,
) -> Result<ContinueOutcome>
pub fn continue_until_break( &mut self, timeout: Option<Duration>, cancel: &AtomicBool, disposition: ContinueDisposition, ) -> Result<ContinueOutcome>
Resume the VM (unless already running, in which case no exception
acknowledgment is sent) with disposition, then wait up to timeout
for a meaningful stop; wrong-process int3 hits and false conditional
breakpoints are stepped over silently. None waits indefinitely;
cancel or an elapsed timeout returns ContinueOutcome::Running
with the VM left running. Non-resuming observation is
Self::wait_for_stop_bounded.
Sourcepub fn wait_for_stop_bounded(
&mut self,
timeout: Option<Duration>,
cancel: &AtomicBool,
) -> Result<ContinueOutcome>
pub fn wait_for_stop_bounded( &mut self, timeout: Option<Duration>, cancel: &AtomicBool, ) -> Result<ContinueOutcome>
Wait up to timeout for the next meaningful stop without resuming:
drains a held stop, drives the reboot / breakpoint classification, absorbs
debugger noise (assist break-ins, stray single-steps, wrong-process and
false-condition hits), and returns the stop worth surfacing (or
ContinueOutcome::Running on timeout/cancel). Because it never resumes, a
caller already halted at an interesting site (e.g. the early-boot reload)
observes it in place instead of blowing past it; that separation is why
the MCP surface splits resume from wait.
Sourcepub fn wait_for_stop(&mut self) -> Result<StopEvent>
pub fn wait_for_stop(&mut self) -> Result<StopEvent>
Block until the backend produces a meaningful stop, routing every raw
event through Self::classify_stop_event. Filtered breakpoint hits and
debugger noise are resumed internally.
Sourcepub fn reload_with_hint(&mut self, hint: Option<VirtAddr>) -> Result<()>
pub fn reload_with_hint(&mut self, hint: Option<VirtAddr>) -> Result<()>
Rebuild guest state using an optional kernel-base hint through the shared
[perform_target_reload] action.
Sourcepub fn try_complete_pending_reload(&mut self) -> Result<bool>
pub fn try_complete_pending_reload(&mut self) -> Result<bool>
If a module-list reload is pending and the loaded-module list has now appeared, finish rediscovery: reload the kernel module symbols, tell the backend rediscovery completed (stopping its reconnect-assist poking), and clear the pending flag. Returns whether it completed on this call. The REPL layers cache refresh and progress printing on the same condition.
Sourcepub fn try_finish_rediscovery_from_memory(&mut self)
pub fn try_finish_rediscovery_from_memory(&mut self)
Try to finish module-list rediscovery by reading PsLoadedModuleList from
guest memory instead of forcing a stop. Skips while a reload notification
is still owed, so completion cannot silently swallow the one
TargetReloaded event.
Sourcepub fn clear_deferred_reload_surface(&mut self)
pub fn clear_deferred_reload_surface(&mut self)
Clear a deferred reboot notification once the host has already observed or acted on the rebuilt target. Leave it pending if the current kernel mapping still looks stale, so a later wait can surface the real reload.
Sourcepub fn classify_reload_stop(
&mut self,
event: &mut StopEvent,
) -> Result<ReloadDisposition>
pub fn classify_reload_stop( &mut self, event: &mut StopEvent, ) -> Result<ReloadDisposition>
Advance the reboot / KD-reconnect state machine for a freshly observed
event, returning how a host should treat it (see ReloadDisposition).
On a detected reload it drops stale breakpoints, rebuilds guest state, and
records whether the module list is available yet (setting
Self::reload_module_list_pending); on a later stop it tries to complete
a pending rediscovery; otherwise it recognizes transport assist break-ins.
Mutates event.target_reloaded to match. continue_until_break consumes
it; the REPL shares its predicates so they can’t drift.
Source§impl Session
impl Session
Sourcepub fn inspect_pcr(&mut self, processor: u16) -> Result<PcrDetail>
pub fn inspect_pcr(&mut self, processor: u16) -> Result<PcrDetail>
Decode KPCR/KPRCB essentials, using halted backend descriptor registers only when target-memory descriptor fields are unavailable; all other diagnostic values retain their target-memory layout/read errors.
Sourcepub fn inspect_idt(
&mut self,
processor: u16,
vector: Option<u16>,
) -> Result<IdtDetail>
pub fn inspect_idt( &mut self, processor: u16, vector: Option<u16>, ) -> Result<IdtDetail>
Decode one IDT vector or all 256 vectors from the halted processor’s IDTR, falling back to backend register reads when PDB state is absent; each entry field preserves its own memory/symbol diagnostic.
Sourcepub fn inspect_gdt(&mut self, processor: u16) -> Result<GdtDetail>
pub fn inspect_gdt(&mut self, processor: u16) -> Result<GdtDetail>
Decode the halted processor’s bounded GDT, falling back to backend GDTR registers when PDB state is absent; each entry field preserves its own raw/descriptor diagnostic.
Source§impl Session
impl Session
Sourcepub fn target_version(&mut self) -> Result<TargetVersionDetail>
pub fn target_version(&mut self) -> Result<TargetVersionDetail>
Add backend identity and a backend vCPU count fallback to the target metadata. The target-only method remains useful for passive memory and dump consumers that have no execution backend.
Source§impl Session
impl Session
Sourcepub fn inspect_running(
&self,
include_idle: bool,
include_stacks: bool,
) -> Result<RunningDetail>
pub fn inspect_running( &self, include_idle: bool, include_stacks: bool, ) -> Result<RunningDetail>
Decode running processor metadata and, when requested, append a bounded short stack for each current thread using the session’s stack walker. KPRC/KPCR, current/next/idle pointers, thread metadata, and stack reads are independent diagnostics, so one processor’s missing field does not discard its other rows.
Sourcepub fn inspect_apcs(&self, selector: ApcSelector) -> Result<ApcListDetail>
pub fn inspect_apcs(&self, selector: ApcSelector) -> Result<ApcListDetail>
Decode kernel and user APC queues for the selected/current thread, one
thread, one PID/EPROCESS, or all threads. APC list walks are bounded and
preserve their per-list termination; layout failure is retained in
layout_error while thread metadata still remains usable.
Sourcepub fn inspect_stacks(
&mut self,
level: u8,
filter: Option<&str>,
) -> Result<StacksDetail>
pub fn inspect_stacks( &mut self, level: u8, filter: Option<&str>, ) -> Result<StacksDetail>
Enumerate every Windows thread (including active vCPU threads absent from the process walk), resolve its bounded stack, and apply the optional case-insensitive process/symbol filter before returning structured rows. Each top symbol/stack read is independently diagnostic; unreadable thread metadata remains visible with its unavailable field.
Auto Trait Implementations§
impl !Freeze for Session
impl !RefUnwindSafe for Session
impl !Send for Session
impl !Sync for Session
impl !UnwindSafe for Session
impl Unpin for Session
impl UnsafeUnpin for Session
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<D> OwoColorize for D
impl<D> OwoColorize for D
Source§fn fg<C>(&self) -> FgColorDisplay<'_, C, Self>where
C: Color,
fn fg<C>(&self) -> FgColorDisplay<'_, C, Self>where
C: Color,
Source§fn bg<C>(&self) -> BgColorDisplay<'_, C, Self>where
C: Color,
fn bg<C>(&self) -> BgColorDisplay<'_, C, Self>where
C: Color,
Source§fn black(&self) -> FgColorDisplay<'_, Black, Self>
fn black(&self) -> FgColorDisplay<'_, Black, Self>
Source§fn on_black(&self) -> BgColorDisplay<'_, Black, Self>
fn on_black(&self) -> BgColorDisplay<'_, Black, Self>
Source§fn red(&self) -> FgColorDisplay<'_, Red, Self>
fn red(&self) -> FgColorDisplay<'_, Red, Self>
Source§fn on_red(&self) -> BgColorDisplay<'_, Red, Self>
fn on_red(&self) -> BgColorDisplay<'_, Red, Self>
Source§fn green(&self) -> FgColorDisplay<'_, Green, Self>
fn green(&self) -> FgColorDisplay<'_, Green, Self>
Source§fn on_green(&self) -> BgColorDisplay<'_, Green, Self>
fn on_green(&self) -> BgColorDisplay<'_, Green, Self>
Source§fn yellow(&self) -> FgColorDisplay<'_, Yellow, Self>
fn yellow(&self) -> FgColorDisplay<'_, Yellow, Self>
Source§fn on_yellow(&self) -> BgColorDisplay<'_, Yellow, Self>
fn on_yellow(&self) -> BgColorDisplay<'_, Yellow, Self>
Source§fn blue(&self) -> FgColorDisplay<'_, Blue, Self>
fn blue(&self) -> FgColorDisplay<'_, Blue, Self>
Source§fn on_blue(&self) -> BgColorDisplay<'_, Blue, Self>
fn on_blue(&self) -> BgColorDisplay<'_, Blue, Self>
Source§fn magenta(&self) -> FgColorDisplay<'_, Magenta, Self>
fn magenta(&self) -> FgColorDisplay<'_, Magenta, Self>
Source§fn on_magenta(&self) -> BgColorDisplay<'_, Magenta, Self>
fn on_magenta(&self) -> BgColorDisplay<'_, Magenta, Self>
Source§fn purple(&self) -> FgColorDisplay<'_, Magenta, Self>
fn purple(&self) -> FgColorDisplay<'_, Magenta, Self>
Source§fn on_purple(&self) -> BgColorDisplay<'_, Magenta, Self>
fn on_purple(&self) -> BgColorDisplay<'_, Magenta, Self>
Source§fn cyan(&self) -> FgColorDisplay<'_, Cyan, Self>
fn cyan(&self) -> FgColorDisplay<'_, Cyan, Self>
Source§fn on_cyan(&self) -> BgColorDisplay<'_, Cyan, Self>
fn on_cyan(&self) -> BgColorDisplay<'_, Cyan, Self>
Source§fn white(&self) -> FgColorDisplay<'_, White, Self>
fn white(&self) -> FgColorDisplay<'_, White, Self>
Source§fn on_white(&self) -> BgColorDisplay<'_, White, Self>
fn on_white(&self) -> BgColorDisplay<'_, White, Self>
Source§fn default_color(&self) -> FgColorDisplay<'_, Default, Self>
fn default_color(&self) -> FgColorDisplay<'_, Default, Self>
Source§fn on_default_color(&self) -> BgColorDisplay<'_, Default, Self>
fn on_default_color(&self) -> BgColorDisplay<'_, Default, Self>
Source§fn bright_black(&self) -> FgColorDisplay<'_, BrightBlack, Self>
fn bright_black(&self) -> FgColorDisplay<'_, BrightBlack, Self>
Source§fn on_bright_black(&self) -> BgColorDisplay<'_, BrightBlack, Self>
fn on_bright_black(&self) -> BgColorDisplay<'_, BrightBlack, Self>
Source§fn bright_red(&self) -> FgColorDisplay<'_, BrightRed, Self>
fn bright_red(&self) -> FgColorDisplay<'_, BrightRed, Self>
Source§fn on_bright_red(&self) -> BgColorDisplay<'_, BrightRed, Self>
fn on_bright_red(&self) -> BgColorDisplay<'_, BrightRed, Self>
Source§fn bright_green(&self) -> FgColorDisplay<'_, BrightGreen, Self>
fn bright_green(&self) -> FgColorDisplay<'_, BrightGreen, Self>
Source§fn on_bright_green(&self) -> BgColorDisplay<'_, BrightGreen, Self>
fn on_bright_green(&self) -> BgColorDisplay<'_, BrightGreen, Self>
Source§fn bright_yellow(&self) -> FgColorDisplay<'_, BrightYellow, Self>
fn bright_yellow(&self) -> FgColorDisplay<'_, BrightYellow, Self>
Source§fn on_bright_yellow(&self) -> BgColorDisplay<'_, BrightYellow, Self>
fn on_bright_yellow(&self) -> BgColorDisplay<'_, BrightYellow, Self>
Source§fn bright_blue(&self) -> FgColorDisplay<'_, BrightBlue, Self>
fn bright_blue(&self) -> FgColorDisplay<'_, BrightBlue, Self>
Source§fn on_bright_blue(&self) -> BgColorDisplay<'_, BrightBlue, Self>
fn on_bright_blue(&self) -> BgColorDisplay<'_, BrightBlue, Self>
Source§fn bright_magenta(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
fn bright_magenta(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
Source§fn on_bright_magenta(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
fn on_bright_magenta(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
Source§fn bright_purple(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
fn bright_purple(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
Source§fn on_bright_purple(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
fn on_bright_purple(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
Source§fn bright_cyan(&self) -> FgColorDisplay<'_, BrightCyan, Self>
fn bright_cyan(&self) -> FgColorDisplay<'_, BrightCyan, Self>
Source§fn on_bright_cyan(&self) -> BgColorDisplay<'_, BrightCyan, Self>
fn on_bright_cyan(&self) -> BgColorDisplay<'_, BrightCyan, Self>
Source§fn bright_white(&self) -> FgColorDisplay<'_, BrightWhite, Self>
fn bright_white(&self) -> FgColorDisplay<'_, BrightWhite, Self>
Source§fn on_bright_white(&self) -> BgColorDisplay<'_, BrightWhite, Self>
fn on_bright_white(&self) -> BgColorDisplay<'_, BrightWhite, Self>
Source§fn bold(&self) -> BoldDisplay<'_, Self>
fn bold(&self) -> BoldDisplay<'_, Self>
Source§fn dimmed(&self) -> DimDisplay<'_, Self>
fn dimmed(&self) -> DimDisplay<'_, Self>
Source§fn italic(&self) -> ItalicDisplay<'_, Self>
fn italic(&self) -> ItalicDisplay<'_, Self>
Source§fn underline(&self) -> UnderlineDisplay<'_, Self>
fn underline(&self) -> UnderlineDisplay<'_, Self>
Source§fn blink(&self) -> BlinkDisplay<'_, Self>
fn blink(&self) -> BlinkDisplay<'_, Self>
Source§fn blink_fast(&self) -> BlinkFastDisplay<'_, Self>
fn blink_fast(&self) -> BlinkFastDisplay<'_, Self>
Source§fn reversed(&self) -> ReversedDisplay<'_, Self>
fn reversed(&self) -> ReversedDisplay<'_, Self>
Source§fn strikethrough(&self) -> StrikeThroughDisplay<'_, Self>
fn strikethrough(&self) -> StrikeThroughDisplay<'_, Self>
Source§fn color<Color>(&self, color: Color) -> FgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
fn color<Color>(&self, color: Color) -> FgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
OwoColorize::fg or
a color-specific method, such as OwoColorize::green, Read moreSource§fn on_color<Color>(&self, color: Color) -> BgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
fn on_color<Color>(&self, color: Color) -> BgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
OwoColorize::bg or
a color-specific method, such as OwoColorize::on_yellow, Read more