Skip to content

Commit a1b0a5d

Browse files
committed
add stepping support
- also adds handling of gdb client disconnect by resuming execution Signed-off-by: Doru Blânzeanu <[email protected]>
1 parent 5c22657 commit a1b0a5d

File tree

4 files changed

+59
-2
lines changed

4 files changed

+59
-2
lines changed

src/hyperlight_host/src/hypervisor/gdb/event_loop.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ pub fn event_loop_thread(
8383
Ok(disconnect_reason) => match disconnect_reason {
8484
DisconnectReason::Disconnect => {
8585
log::info!("Gdb client disconnected");
86+
if let Err(e) = target.disable_debug() {
87+
log::error!("Cannot disable debugging: {:?}", e);
88+
}
8689
}
8790
DisconnectReason::TargetExited(_) => {
8891
log::info!("Guest finalized execution and disconnected");

src/hyperlight_host/src/hypervisor/gdb/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,10 @@ pub enum VcpuStopReason {
8585
pub enum DebugMsg {
8686
AddHwBreakpoint(u64),
8787
Continue,
88+
DisableDebug,
8889
ReadRegisters,
8990
RemoveHwBreakpoint(u64),
91+
Step,
9092
WriteRegisters(X86_64Regs),
9193
}
9294

@@ -95,8 +97,10 @@ pub enum DebugMsg {
9597
pub enum DebugResponse {
9698
AddHwBreakpoint(bool),
9799
Continue,
100+
DisableDebug,
98101
ReadRegisters(X86_64Regs),
99102
RemoveHwBreakpoint(bool),
103+
Step,
100104
VcpuStopped(VcpuStopReason),
101105
WriteRegisters,
102106
}

src/hyperlight_host/src/hypervisor/gdb/x86_64_target.rs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ use crossbeam_channel::TryRecvError;
22
use gdbstub::arch::Arch;
33
use gdbstub::common::Signal;
44
use gdbstub::target::ext::base::singlethread::{
5-
SingleThreadBase, SingleThreadResume, SingleThreadResumeOps,
5+
SingleThreadBase, SingleThreadResume, SingleThreadResumeOps, SingleThreadSingleStep,
6+
SingleThreadSingleStepOps,
67
};
78
use gdbstub::target::ext::base::BaseOps;
89
use gdbstub::target::ext::breakpoints::{
@@ -61,6 +62,20 @@ impl HyperlightSandboxTarget {
6162
}
6263
}
6364

65+
/// Sends an event to the Hypervisor that tells it to disable debugging
66+
/// and continue executing until end
67+
/// Note: The method waits for a confirmation message
68+
pub fn disable_debug(&mut self) -> Result<(), GdbTargetError> {
69+
log::info!("Disable debugging and continue until end");
70+
71+
match self.send_command(DebugMsg::DisableDebug)? {
72+
DebugResponse::DisableDebug => Ok(()),
73+
msg => {
74+
log::error!("Unexpected message received: {:?}", msg);
75+
Err(GdbTargetError::UnexpectedMessage)
76+
}
77+
}
78+
}
6479
}
6580

6681
impl Target for HyperlightSandboxTarget {
@@ -222,4 +237,23 @@ impl SingleThreadResume for HyperlightSandboxTarget {
222237
log::debug!("Resume");
223238
self.resume_vcpu()
224239
}
240+
fn support_single_step(&mut self) -> Option<SingleThreadSingleStepOps<Self>> {
241+
Some(self)
242+
}
243+
}
244+
245+
impl SingleThreadSingleStep for HyperlightSandboxTarget {
246+
fn step(&mut self, signal: Option<Signal>) -> Result<(), Self::Error> {
247+
assert!(signal.is_none());
248+
249+
log::debug!("Step");
250+
match self.send_command(DebugMsg::Step)? {
251+
DebugResponse::Step => Ok(()),
252+
msg => {
253+
log::error!("Unexpected message received: {:?}", msg);
254+
255+
Err(GdbTargetError::UnexpectedMessage)
256+
}
257+
}
258+
}
225259
}

src/hyperlight_host/src/hypervisor/kvm.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ mod debug {
7474
/// KVM Debug struct
7575
/// This struct is used to abstract the internal details of the kvm
7676
/// guest debugging settings
77+
#[derive(Default)]
7778
pub struct KvmDebug {
7879
/// vCPU stepping state
7980
single_step: bool,
@@ -144,6 +145,12 @@ mod debug {
144145
}
145146

146147
impl KVMDriver {
148+
/// Resets the debug information to disable debugging
149+
fn disable_debug(&mut self) -> Result<()> {
150+
self.debug = Some(KvmDebug::default());
151+
152+
self.set_single_step(false)
153+
}
147154

148155
/// Returns the instruction pointer from the stopped vCPU
149156
pub fn get_instruction_pointer(&self) -> Result<u64> {
@@ -341,6 +348,11 @@ mod debug {
341348
self.set_single_step(false)?;
342349
Ok(DebugResponse::Continue)
343350
}
351+
DebugMsg::DisableDebug => {
352+
self.disable_debug()?;
353+
354+
Ok(DebugResponse::DisableDebug)
355+
}
344356
DebugMsg::ReadRegisters => {
345357
let mut regs = X86_64Regs::default();
346358
self.read_regs(&mut regs).expect("Read Regs error");
@@ -352,6 +364,10 @@ mod debug {
352364
.expect("Remove hw breakpoint error");
353365
Ok(DebugResponse::RemoveHwBreakpoint(res))
354366
}
367+
DebugMsg::Step => {
368+
self.set_single_step(true)?;
369+
Ok(DebugResponse::Step)
370+
}
355371
DebugMsg::WriteRegisters(regs) => {
356372
self.write_regs(&regs).expect("Write Regs error");
357373
Ok(DebugResponse::WriteRegisters)
@@ -713,7 +729,7 @@ impl Hypervisor for KVMDriver {
713729
// If the command was either step or continue, we need to run the vcpu
714730
let cont = matches!(
715731
response,
716-
DebugResponse::Continue
732+
DebugResponse::Step | DebugResponse::Continue | DebugResponse::DisableDebug
717733
);
718734

719735
self.send_dbg_msg(response)

0 commit comments

Comments
 (0)