Skip to content

Commit e550a84

Browse files
committed
add read/write address and text section offset support
Signed-off-by: Doru Blânzeanu <[email protected]>
1 parent d9a364b commit e550a84

File tree

4 files changed

+139
-5
lines changed

4 files changed

+139
-5
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ pub fn event_loop_thread(
8181
) {
8282
match debugger.run_blocking::<GdbBlockingEventLoop>(target) {
8383
Ok(disconnect_reason) => match disconnect_reason {
84-
DisconnectReason::Disconnect => {
84+
DisconnectReason::Disconnect => {
8585
log::info!("Gdb client disconnected");
8686
if let Err(e) = target.disable_debug() {
8787
log::error!("Cannot disable debugging: {:?}", e);

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,12 @@ pub enum DebugMsg {
8686
AddHwBreakpoint(u64),
8787
Continue,
8888
DisableDebug,
89+
GetCodeSectionOffset,
90+
ReadAddr(u64, usize),
8991
ReadRegisters,
9092
RemoveHwBreakpoint(u64),
9193
Step,
94+
WriteAddr(u64, Vec<u8>),
9295
WriteRegisters(X86_64Regs),
9396
}
9497

@@ -98,10 +101,13 @@ pub enum DebugResponse {
98101
AddHwBreakpoint(bool),
99102
Continue,
100103
DisableDebug,
104+
GetCodeSectionOffset(u64),
105+
ReadAddr(Vec<u8>),
101106
ReadRegisters(X86_64Regs),
102107
RemoveHwBreakpoint(bool),
103108
Step,
104109
VcpuStopped(VcpuStopReason),
110+
WriteAddr,
105111
WriteRegisters,
106112
}
107113

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

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ use gdbstub::target::ext::base::BaseOps;
99
use gdbstub::target::ext::breakpoints::{
1010
Breakpoints, BreakpointsOps, HwBreakpoint, HwBreakpointOps,
1111
};
12+
use gdbstub::target::ext::section_offsets::{Offsets, SectionOffsets};
1213
use gdbstub::target::{Target, TargetError, TargetResult};
1314
use gdbstub_arch::x86::X86_64_SSE as GdbTargetArch;
1415

15-
use super::{DebugMsg, DebugResponse, DebugCommChannel, GdbTargetError, X86_64Regs};
16+
use super::{DebugCommChannel, DebugMsg, DebugResponse, GdbTargetError, X86_64Regs};
1617

1718
/// Gdbstub target used by the gdbstub crate to provide GDB protocol implementation
1819
pub struct HyperlightSandboxTarget {
@@ -90,6 +91,12 @@ impl Target for HyperlightSandboxTarget {
9091
fn base_ops(&mut self) -> BaseOps<Self::Arch, Self::Error> {
9192
BaseOps::SingleThread(self)
9293
}
94+
95+
fn support_section_offsets(
96+
&mut self,
97+
) -> Option<gdbstub::target::ext::section_offsets::SectionOffsetsOps<Self>> {
98+
Some(self)
99+
}
93100
}
94101

95102
impl SingleThreadBase for HyperlightSandboxTarget {
@@ -100,7 +107,17 @@ impl SingleThreadBase for HyperlightSandboxTarget {
100107
) -> TargetResult<usize, Self> {
101108
log::debug!("Read addr: {:X} len: {:X}", gva, data.len());
102109

103-
unimplemented!()
110+
match self.send_command(DebugMsg::ReadAddr(gva, data.len()))? {
111+
DebugResponse::ReadAddr(v) => {
112+
data.copy_from_slice(&v);
113+
114+
Ok(v.len())
115+
}
116+
msg => {
117+
log::error!("Unexpected message received: {:?}", msg);
118+
Err(TargetError::Fatal(GdbTargetError::UnexpectedMessage))
119+
}
120+
}
104121
}
105122

106123
fn write_addrs(
@@ -109,8 +126,15 @@ impl SingleThreadBase for HyperlightSandboxTarget {
109126
data: &[u8],
110127
) -> TargetResult<(), Self> {
111128
log::debug!("Write addr: {:X} len: {:X}", gva, data.len());
129+
let v = Vec::from(data);
112130

113-
unimplemented!()
131+
match self.send_command(DebugMsg::WriteAddr(gva, v))? {
132+
DebugResponse::WriteAddr => Ok(()),
133+
msg => {
134+
log::error!("Unexpected message received: {:?}", msg);
135+
Err(TargetError::Fatal(GdbTargetError::UnexpectedMessage))
136+
}
137+
}
114138
}
115139

116140
fn read_registers(
@@ -191,6 +215,22 @@ impl SingleThreadBase for HyperlightSandboxTarget {
191215
Some(self)
192216
}
193217
}
218+
impl SectionOffsets for HyperlightSandboxTarget {
219+
fn get_section_offsets(&mut self) -> Result<Offsets<<Self::Arch as Arch>::Usize>, Self::Error> {
220+
log::debug!("Get section offsets");
221+
222+
match self.send_command(DebugMsg::GetCodeSectionOffset)? {
223+
DebugResponse::GetCodeSectionOffset(text) => Ok(Offsets::Segments {
224+
text_seg: text,
225+
data_seg: None,
226+
}),
227+
msg => {
228+
log::error!("Unexpected message received: {:?}", msg);
229+
Err(GdbTargetError::UnexpectedMessage)
230+
}
231+
}
232+
}
233+
}
194234

195235
impl Breakpoints for HyperlightSandboxTarget {
196236
fn support_hw_breakpoint(&mut self) -> Option<HwBreakpointOps<Self>> {

src/hyperlight_host/src/hypervisor/kvm.rs

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ pub(crate) fn is_hypervisor_present() -> bool {
6666
#[cfg(gdb)]
6767
mod debug {
6868
use std::sync::{Arc, Mutex};
69+
70+
use hyperlight_common::mem::PAGE_SIZE;
6971
use kvm_bindings::{
7072
kvm_guest_debug, kvm_regs, KVM_GUESTDBG_ENABLE, KVM_GUESTDBG_SINGLESTEP,
7173
KVM_GUESTDBG_USE_HW_BP, KVM_GUESTDBG_USE_SW_BP,
@@ -75,6 +77,7 @@ mod debug {
7577
use super::KVMDriver;
7678
use crate::hypervisor::gdb::{DebugMsg, DebugResponse, VcpuStopReason, X86_64Regs};
7779
use crate::hypervisor::handlers::DbgMemAccessHandlerCaller;
80+
use crate::mem::layout::SandboxMemoryLayout;
7881
use crate::{new_error, Result};
7982

8083
/// KVM Debug struct
@@ -212,6 +215,70 @@ mod debug {
212215
}
213216
}
214217

218+
pub fn read_addrs(
219+
&mut self,
220+
mut gva: u64,
221+
mut data: &mut [u8],
222+
dbg_mem_access_fn: Arc<Mutex<dyn DbgMemAccessHandlerCaller>>,
223+
) -> Result<()> {
224+
let data_len = data.len();
225+
log::debug!("Read addr: {:X} len: {:X}", gva, data_len);
226+
227+
while !data.is_empty() {
228+
let gpa = self.translate_gva(gva)?;
229+
230+
let read_len = std::cmp::min(
231+
data.len(),
232+
(PAGE_SIZE - (gpa & (PAGE_SIZE - 1))).try_into().unwrap(),
233+
);
234+
let offset = gpa as usize - SandboxMemoryLayout::BASE_ADDRESS;
235+
236+
dbg_mem_access_fn
237+
.clone()
238+
.try_lock()
239+
.map_err(|e| new_error!("Error locking at {}:{}: {}", file!(), line!(), e))?
240+
.read(offset, &mut data[..read_len])?;
241+
242+
data = &mut data[read_len..];
243+
gva += read_len as u64;
244+
}
245+
246+
log::debug!("data before after {:?}", data);
247+
248+
Ok(())
249+
}
250+
251+
pub fn write_addrs(
252+
&mut self,
253+
mut gva: u64,
254+
mut data: &[u8],
255+
dbg_mem_access_fn: Arc<Mutex<dyn DbgMemAccessHandlerCaller>>,
256+
) -> Result<()> {
257+
let data_len = data.len();
258+
log::debug!("Write addr: {:X} len: {:X}", gva, data_len);
259+
260+
while !data.is_empty() {
261+
let gpa = self.translate_gva(gva)?;
262+
263+
let write_len = std::cmp::min(
264+
data.len(),
265+
(PAGE_SIZE - (gpa & (PAGE_SIZE - 1))).try_into().unwrap(),
266+
);
267+
let offset = gpa as usize - SandboxMemoryLayout::BASE_ADDRESS;
268+
269+
dbg_mem_access_fn
270+
.clone()
271+
.try_lock()
272+
.map_err(|e| new_error!("Error locking at {}:{}: {}", file!(), line!(), e))?
273+
.write(offset, data)?;
274+
275+
data = &data[write_len..];
276+
gva += write_len as u64;
277+
}
278+
279+
Ok(())
280+
}
281+
215282
pub fn read_regs(&self, regs: &mut X86_64Regs) -> Result<()> {
216283
log::debug!("Read registers");
217284
let vcpu_regs = self
@@ -342,7 +409,7 @@ mod debug {
342409
pub fn process_dbg_request(
343410
&mut self,
344411
req: DebugMsg,
345-
_dbg_mem_access_fn: Arc<Mutex<dyn DbgMemAccessHandlerCaller>>,
412+
dbg_mem_access_fn: Arc<Mutex<dyn DbgMemAccessHandlerCaller>>,
346413
) -> Result<DebugResponse> {
347414
match req {
348415
DebugMsg::AddHwBreakpoint(addr) => {
@@ -360,6 +427,22 @@ mod debug {
360427

361428
Ok(DebugResponse::DisableDebug)
362429
}
430+
DebugMsg::GetCodeSectionOffset => {
431+
let offset = dbg_mem_access_fn
432+
.clone()
433+
.try_lock()
434+
.map_err(|e| new_error!("Error locking at {}:{}: {}", file!(), line!(), e))?
435+
.get_code_offset()?;
436+
437+
Ok(DebugResponse::GetCodeSectionOffset(offset as u64))
438+
}
439+
DebugMsg::ReadAddr(addr, len) => {
440+
let mut data = vec![0u8; len];
441+
442+
self.read_addrs(addr, &mut data, dbg_mem_access_fn.clone())?;
443+
444+
Ok(DebugResponse::ReadAddr(data))
445+
}
363446
DebugMsg::ReadRegisters => {
364447
let mut regs = X86_64Regs::default();
365448
self.read_regs(&mut regs).expect("Read Regs error");
@@ -375,6 +458,11 @@ mod debug {
375458
self.set_single_step(true)?;
376459
Ok(DebugResponse::Step)
377460
}
461+
DebugMsg::WriteAddr(addr, data) => {
462+
self.write_addrs(addr, &data, dbg_mem_access_fn.clone())?;
463+
464+
Ok(DebugResponse::WriteAddr)
465+
}
378466
DebugMsg::WriteRegisters(regs) => {
379467
self.write_regs(&regs).expect("Write Regs error");
380468
Ok(DebugResponse::WriteRegisters)

0 commit comments

Comments
 (0)