Skip to content

Commit 16492de

Browse files
committed
add sw breakpoint support
Signed-off-by: Doru Blânzeanu <[email protected]>
1 parent 791aaf8 commit 16492de

File tree

1 file changed

+67
-4
lines changed

1 file changed

+67
-4
lines changed

src/hyperlight_host/src/hypervisor/gdb/kvm_target.rs

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::collections::HashMap;
12
use std::sync::{Arc, Mutex};
23

34
use crossbeam_channel::TryRecvError;
@@ -10,7 +11,7 @@ use gdbstub::target::ext::base::singlethread::{
1011
};
1112
use gdbstub::target::ext::base::BaseOps;
1213
use gdbstub::target::ext::breakpoints::{
13-
Breakpoints, BreakpointsOps, HwBreakpoint, HwBreakpointOps,
14+
Breakpoints, BreakpointsOps, HwBreakpoint, HwBreakpointOps, SwBreakpoint, SwBreakpointOps,
1415
};
1516
use gdbstub::target::ext::section_offsets::{Offsets, SectionOffsets};
1617
use gdbstub::target::{Target, TargetError, TargetResult};
@@ -19,7 +20,7 @@ use gdbstub_arch::x86::X86_64_SSE as GdbTargetArch;
1920
use hyperlight_common::mem::PAGE_SIZE;
2021
use kvm_bindings::{
2122
kvm_guest_debug, kvm_regs, KVM_GUESTDBG_ENABLE, KVM_GUESTDBG_SINGLESTEP,
22-
KVM_GUESTDBG_USE_HW_BP,
23+
KVM_GUESTDBG_USE_HW_BP, KVM_GUESTDBG_USE_SW_BP,
2324
};
2425
use kvm_ioctls::VcpuFd;
2526

@@ -29,6 +30,13 @@ use crate::mem::layout::SandboxMemoryLayout;
2930
use crate::mem::mgr::SandboxMemoryManager;
3031
use crate::mem::shared_mem::{GuestSharedMemory, SharedMemory};
3132

33+
/// Software Breakpoint size in memory
34+
const SW_BP_SIZE: usize = 1;
35+
/// Software Breakpoinnt opcode
36+
const SW_BP_OP: u8 = 0xCC;
37+
/// Software Breakpoint written to memory
38+
const SW_BP: [u8; SW_BP_SIZE] = [SW_BP_OP];
39+
3240
/// KVM Debug struct
3341
/// This struct is used to abstract the internal details of the kvm
3442
/// guest debugging settings
@@ -42,7 +50,7 @@ impl KvmDebug {
4250

4351
pub fn new() -> Self {
4452
let dbg = kvm_guest_debug {
45-
control: KVM_GUESTDBG_ENABLE,
53+
control: KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP,
4654
..Default::default()
4755
};
4856

@@ -106,6 +114,8 @@ pub struct HyperlightKvmSandboxTarget {
106114

107115
/// Array of addresses for HW breakpoints
108116
hw_breakpoints: Vec<u64>,
117+
/// Array of addresses for SW breakpoints
118+
sw_breakpoints: HashMap<u64, [u8; SW_BP_SIZE]>,
109119

110120
/// Hypervisor communication channels
111121
hyp_conn: GdbConnection,
@@ -130,6 +140,7 @@ impl HyperlightKvmSandboxTarget {
130140
single_step: false,
131141

132142
hw_breakpoints: vec![],
143+
sw_breakpoints: HashMap::new(),
133144

134145
hyp_conn,
135146
}
@@ -437,6 +448,9 @@ impl Breakpoints for HyperlightKvmSandboxTarget {
437448
fn support_hw_breakpoint(&mut self) -> Option<HwBreakpointOps<Self>> {
438449
Some(self)
439450
}
451+
fn support_sw_breakpoint(&mut self) -> Option<SwBreakpointOps<'_, Self>> {
452+
Some(self)
453+
}
440454
}
441455

442456
impl HwBreakpoint for HyperlightKvmSandboxTarget {
@@ -496,6 +510,55 @@ impl HwBreakpoint for HyperlightKvmSandboxTarget {
496510
}
497511
}
498512

513+
impl SwBreakpoint for HyperlightKvmSandboxTarget {
514+
/// Adds a software breakpoint by setting a specific operation code at the
515+
/// address so when the vCPU hits it, it knows it is a software breakpoint.
516+
///
517+
/// The existing data at the address is saved so it can be restored when
518+
/// removing the breakpoint
519+
fn add_sw_breakpoint(
520+
&mut self,
521+
addr: <Self::Arch as Arch>::Usize,
522+
_kind: <Self::Arch as Arch>::BreakpointKind,
523+
) -> TargetResult<bool, Self> {
524+
log::debug!("Add sw breakpoint at address {:X}", addr);
525+
let addr = self.translate_gva(addr).map_err(TargetError::Fatal)?;
526+
527+
if self.sw_breakpoints.contains_key(&addr) {
528+
return Ok(true);
529+
}
530+
531+
let mut save_data = [0u8; SW_BP_SIZE];
532+
self.read_addrs(addr, &mut save_data)?;
533+
self.write_addrs(addr, &SW_BP)?;
534+
535+
self.sw_breakpoints.insert(addr, save_data);
536+
537+
Ok(true)
538+
}
539+
540+
/// Removes a software breakpoint by restoring the saved data at the corresponding
541+
/// address
542+
fn remove_sw_breakpoint(
543+
&mut self,
544+
addr: <Self::Arch as Arch>::Usize,
545+
_kind: <Self::Arch as Arch>::BreakpointKind,
546+
) -> TargetResult<bool, Self> {
547+
log::debug!("Remove sw breakpoint at address {:X}", addr);
548+
549+
let addr = self.translate_gva(addr).map_err(TargetError::Fatal)?;
550+
551+
if self.sw_breakpoints.contains_key(&addr) {
552+
let save_data = self
553+
.sw_breakpoints
554+
.remove(&addr)
555+
.expect("Expected the hashmap to contain the address");
556+
self.write_addrs(addr, &save_data)?;
557+
558+
Ok(true)
559+
} else {
560+
Ok(false)
561+
}
499562
}
500563
}
501564

@@ -518,4 +581,4 @@ impl SingleThreadSingleStep for HyperlightKvmSandboxTarget {
518581
self.set_single_step(true)?;
519582
self.resume_vcpu()
520583
}
521-
}
584+
}

0 commit comments

Comments
 (0)