Skip to content

Commit 579b324

Browse files
committed
add gdb debug tread creation method
Signed-off-by: Doru Blânzeanu <[email protected]>
1 parent c5aeada commit 579b324

File tree

7 files changed

+97
-2
lines changed

7 files changed

+97
-2
lines changed

Cargo.lock

Lines changed: 32 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/hyperlight_host/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ sha256 = "1.4.0"
7171
windows-version = "0.1"
7272

7373
[target.'cfg(unix)'.dependencies]
74+
gdbstub = "0.7.3"
75+
gdbstub_arch = "0.3.1"
7476
seccompiler = { version = "0.4.0", optional = true }
7577
kvm-bindings = { version = "0.11", features = ["fam-wrappers"], optional = true }
7678
kvm-ioctls = { version = "0.20", optional = true }
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
use std::io::{self, ErrorKind};
2+
use std::net::TcpListener;
3+
use std::thread;
4+
use thiserror::Error;
5+
#[derive(Debug, Error)]
6+
pub enum GdbTargetError {
7+
#[error("Error encountered while binding to address and port")]
8+
CannotBind,
9+
#[error("Error encountered while listening for connections")]
10+
ListenerError,
11+
#[error("Unexpected error encountered")]
12+
UnexpectedError,
13+
}
14+
15+
impl From<io::Error> for GdbTargetError {
16+
fn from(err: io::Error) -> Self {
17+
match err.kind() {
18+
ErrorKind::AddrInUse => Self::CannotBind,
19+
ErrorKind::AddrNotAvailable => Self::CannotBind,
20+
ErrorKind::ConnectionReset
21+
| ErrorKind::ConnectionAborted
22+
| ErrorKind::ConnectionRefused => Self::ListenerError,
23+
_ => Self::UnexpectedError,
24+
}
25+
}
26+
}
27+
/// Creates a thread that handles gdb protocol
28+
pub fn create_gdb_thread(
29+
port: u16,
30+
) -> Result<(), GdbTargetError> {
31+
let socket = format!("localhost:{}", port);
32+
33+
log::info!("Listening on {:?}", socket);
34+
let listener = TcpListener::bind(socket)?;
35+
36+
log::info!("Starting GDB thread");
37+
let _handle = thread::Builder::new()
38+
.name("GDB handler".to_string())
39+
.spawn(move || -> Result<(), GdbTargetError> {
40+
log::info!("Waiting for GDB connection ... ");
41+
let (_, _) = listener.accept()?;
42+
Ok(())
43+
});
44+
45+
Ok(())
46+
}

src/hyperlight_host/src/hypervisor/hypervisor_handler.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -832,7 +832,7 @@ fn set_up_hypervisor_partition(
832832
mgr: &mut SandboxMemoryManager<GuestSharedMemory>,
833833
#[allow(unused_variables)] // parameter only used for in-process mode
834834
outb_handler: OutBHandlerWrapper,
835-
#[cfg(gdb)] _debug_info: &Option<DebugInfo>,
835+
#[cfg(gdb)] debug_info: &Option<DebugInfo>,
836836
) -> Result<Box<dyn Hypervisor>> {
837837
let mem_size = u64::try_from(mgr.shared_mem.mem_size())?;
838838
let mut regions = mgr.layout.get_memory_regions(&mgr.shared_mem)?;
@@ -911,6 +911,8 @@ fn set_up_hypervisor_partition(
911911
pml4_ptr.absolute()?,
912912
entrypoint_ptr.absolute()?,
913913
rsp_ptr.absolute()?,
914+
#[cfg(gdb)]
915+
debug_info,
914916
)?;
915917
Ok(Box::new(hv))
916918
}

src/hyperlight_host/src/hypervisor/kvm.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ use kvm_ioctls::{Kvm, VcpuExit, VcpuFd, VmFd};
2323
use tracing::{instrument, Span};
2424

2525
use super::fpu::{FP_CONTROL_WORD_DEFAULT, FP_TAG_WORD_DEFAULT, MXCSR_DEFAULT};
26+
#[cfg(gdb)]
27+
use super::gdb::create_gdb_thread;
2628
use super::handlers::{MemAccessHandlerWrapper, OutBHandlerWrapper};
2729
use super::{
2830
HyperlightExit, Hypervisor, VirtualCPU, CR0_AM, CR0_ET, CR0_MP, CR0_NE, CR0_PE, CR0_PG, CR0_WP,
@@ -31,6 +33,8 @@ use super::{
3133
use crate::hypervisor::hypervisor_handler::HypervisorHandler;
3234
use crate::mem::memory_region::{MemoryRegion, MemoryRegionFlags};
3335
use crate::mem::ptr::{GuestPtr, RawPtr};
36+
#[cfg(gdb)]
37+
use crate::sandbox::uninitialized::DebugInfo;
3438
use crate::{log_then_return, new_error, Result};
3539

3640
/// Return `true` if the KVM API is available, version 12, and has UserMemory capability, or `false` otherwise
@@ -75,6 +79,7 @@ impl KVMDriver {
7579
pml4_addr: u64,
7680
entrypoint: u64,
7781
rsp: u64,
82+
#[cfg(gdb)] debug_info: &Option<DebugInfo>,
7883
) -> Result<Self> {
7984
let kvm = Kvm::new()?;
8085

@@ -101,6 +106,11 @@ impl KVMDriver {
101106
let mut vcpu_fd = vm_fd.create_vcpu(0)?;
102107
Self::setup_initial_sregs(&mut vcpu_fd, pml4_addr)?;
103108

109+
#[cfg(gdb)]
110+
if let Some(DebugInfo { port }) = debug_info {
111+
create_gdb_thread(*port).map_err(|_| new_error!("Cannot create GDB thread"))?;
112+
}
113+
104114
let rsp_gp = GuestPtr::try_from(RawPtr::from(rsp))?;
105115
Ok(Self {
106116
_kvm: kvm,

src/hyperlight_host/src/hypervisor/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ pub mod hyperv_linux;
3434
pub(crate) mod hyperv_windows;
3535
pub(crate) mod hypervisor_handler;
3636

37+
/// GDB debugging support
38+
#[cfg(gdb)]
39+
mod gdb;
40+
3741
/// Driver for running in process instead of using hypervisor
3842
#[cfg(inprocess)]
3943
pub mod inprocess;

src/hyperlight_host/src/sandbox/uninitialized.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ use crate::sandbox_state::sandbox::EvolvableSandbox;
3636
use crate::sandbox_state::transition::Noop;
3737
use crate::{log_build_details, log_then_return, new_error, MultiUseSandbox, Result};
3838

39-
#[allow(dead_code)]
4039
#[cfg(gdb)]
4140
/// Used for passing debug configuration to a sandbox
4241
pub struct DebugInfo {

0 commit comments

Comments
 (0)