Skip to content

Commit fc26f99

Browse files
committed
add hw breakpoint support
- gdb debugger now stops at entrypoint and is able to read addresses, read registers and add or remove breakpoints Signed-off-by: Doru Blânzeanu <[email protected]>
1 parent 9a622a9 commit fc26f99

File tree

1 file changed

+84
-1
lines changed
  • src/hyperlight_host/src/hypervisor/gdb

1 file changed

+84
-1
lines changed

src/hyperlight_host/src/hypervisor/gdb/target.rs

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ use gdbstub::target::ext::base::singlethread::{
77
SingleThreadBase,
88
};
99
use gdbstub::target::ext::base::BaseOps;
10+
use gdbstub::target::ext::breakpoints::{
11+
Breakpoints, BreakpointsOps, HwBreakpoint, HwBreakpointOps,
12+
};
1013
use gdbstub::target::ext::section_offsets::{Offsets, SectionOffsets};
1114
use gdbstub::target::{Target, TargetError, TargetResult};
1215
use gdbstub_arch::x86::reg::X86_64CoreRegs;
@@ -82,7 +85,6 @@ impl KvmDebug {
8285
}
8386
}
8487

85-
#[allow(dead_code)]
8688
/// Gdbstub target used by the gdbstub crate to provide GDB protocol implementation
8789
pub struct HyperlightKvmSandboxTarget {
8890
/// Memory manager that grants access to guest's memory
@@ -98,6 +100,9 @@ pub struct HyperlightKvmSandboxTarget {
98100
/// vCPU paused state
99101
paused: bool,
100102

103+
/// Array of addresses for HW breakpoints
104+
hw_breakpoints: Vec<u64>,
105+
101106
/// Hypervisor communication channels
102107
hyp_conn: GdbConnection,
103108
}
@@ -118,6 +123,9 @@ impl HyperlightKvmSandboxTarget {
118123
entrypoint,
119124

120125
paused: false,
126+
127+
hw_breakpoints: vec![],
128+
121129
hyp_conn,
122130
}
123131
}
@@ -138,6 +146,10 @@ impl HyperlightKvmSandboxTarget {
138146
pub fn get_stop_reason(&self) -> Result<Option<BaseStopReason<(), u64>>, GdbTargetError> {
139147
let ip = self.get_instruction_pointer()?;
140148

149+
if self.hw_breakpoints.contains(&ip) {
150+
return Ok(Some(SingleThreadStopReason::HwBreak(())));
151+
}
152+
141153
if ip == self.entrypoint {
142154
return Ok(Some(SingleThreadStopReason::HwBreak(())));
143155
}
@@ -173,6 +185,44 @@ impl HyperlightKvmSandboxTarget {
173185
self.paused = true;
174186
}
175187

188+
/// Add new breakpoint at provided address if there is enough space
189+
fn add_breakpoint(&mut self, addr: u64) -> Result<bool, GdbTargetError> {
190+
log::debug!("Add breakpoint at address {:X}", addr);
191+
if self.hw_breakpoints.contains(&addr)
192+
|| self.hw_breakpoints.len() >= KvmDebug::MAX_NO_OF_HW_BP
193+
{
194+
Ok(false)
195+
} else {
196+
self.hw_breakpoints.push(addr);
197+
self.debug.set_breakpoints(
198+
&self.vcpu_fd.lock().unwrap(),
199+
&self.hw_breakpoints,
200+
false,
201+
)?;
202+
203+
Ok(true)
204+
}
205+
}
206+
207+
/// Removes breakpoint at the provided address if exists
208+
fn remove_breakpoint(&mut self, addr: u64) -> Result<bool, GdbTargetError> {
209+
log::debug!("Remove breakpoint at address {:X}", addr);
210+
if self.hw_breakpoints.contains(&addr) {
211+
let index = self.hw_breakpoints.iter().position(|a| *a == addr).unwrap();
212+
self.hw_breakpoints.copy_within(index + 1.., index);
213+
self.hw_breakpoints.pop();
214+
self.debug.set_breakpoints(
215+
&self.vcpu_fd.lock().unwrap(),
216+
&self.hw_breakpoints,
217+
false,
218+
)?;
219+
220+
Ok(true)
221+
} else {
222+
Ok(false)
223+
}
224+
}
225+
176226
fn read_regs(&self, regs: &mut X86_64CoreRegs) -> Result<(), GdbTargetError> {
177227
log::debug!("Read registers");
178228
let vcpu_regs = self
@@ -257,6 +307,15 @@ impl Target for HyperlightKvmSandboxTarget {
257307
type Arch = GdbTargetArch;
258308
type Error = GdbTargetError;
259309

310+
#[inline(always)]
311+
fn guard_rail_implicit_sw_breakpoints(&self) -> bool {
312+
true
313+
}
314+
315+
fn support_breakpoints(&mut self) -> Option<BreakpointsOps<Self>> {
316+
Some(self)
317+
}
318+
260319
#[inline(always)]
261320
fn base_ops(&mut self) -> BaseOps<Self::Arch, Self::Error> {
262321
BaseOps::SingleThread(self)
@@ -353,4 +412,28 @@ impl SectionOffsets for HyperlightKvmSandboxTarget {
353412
data_seg: None,
354413
})
355414
}
415+
}
416+
417+
impl Breakpoints for HyperlightKvmSandboxTarget {
418+
fn support_hw_breakpoint(&mut self) -> Option<HwBreakpointOps<Self>> {
419+
Some(self)
420+
}
421+
}
422+
423+
impl HwBreakpoint for HyperlightKvmSandboxTarget {
424+
fn add_hw_breakpoint(
425+
&mut self,
426+
addr: <Self::Arch as Arch>::Usize,
427+
_kind: <Self::Arch as Arch>::BreakpointKind,
428+
) -> TargetResult<bool, Self> {
429+
self.add_breakpoint(addr).map_err(TargetError::Fatal)
430+
}
431+
432+
fn remove_hw_breakpoint(
433+
&mut self,
434+
addr: <Self::Arch as Arch>::Usize,
435+
_kind: <Self::Arch as Arch>::BreakpointKind,
436+
) -> TargetResult<bool, Self> {
437+
self.remove_breakpoint(addr).map_err(TargetError::Fatal)
438+
}
356439
}

0 commit comments

Comments
 (0)