Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/arch/x86_64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use x86_64::structures::paging::{
page_table::{FrameError, PageTableEntry},
};

use crate::{linux::x86_64::kvm_cpu::KVM_32BIT_GAP_START, mem::MmapMemory, paging::PagetableError};
use crate::{mem::MmapMemory, os::x86_64::kvm_cpu::KVM_32BIT_GAP_START, paging::PagetableError};

pub(crate) const RAM_START: GuestPhysAddr = GuestPhysAddr::new(0x0);
// Right below 3 GiB, aka. 0xBFFF_FFFF
Expand Down
7 changes: 0 additions & 7 deletions src/bin/uhyve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,6 @@ struct UhyveArgs {
#[clap(short = 's', long, env = "HERMIT_GDB_PORT", num_args(0..=1), default_missing_value("6677"))]
#[serde(default)]
#[merge(strategy = merge::option::overwrite_none)]
#[cfg(target_os = "linux")]
gdb_port: Option<u16>,

/// TOML configuration file
Expand Down Expand Up @@ -434,7 +433,6 @@ impl From<Args> for Params {
file_isolation,
#[cfg(target_os = "linux")]
io_mode,
#[cfg(target_os = "linux")]
gdb_port,
config: _,
#[cfg(feature = "instrument")]
Expand Down Expand Up @@ -477,10 +475,7 @@ impl From<Args> for Params {
#[cfg(target_os = "linux")]
pit: pit.unwrap_or_default(),
file_mapping,
#[cfg(target_os = "linux")]
gdb_port,
#[cfg(target_os = "macos")]
gdb_port: None,
kernel_args,
tempdir,
#[cfg(target_os = "linux")]
Expand Down Expand Up @@ -692,7 +687,6 @@ mod tests {
file_isolation: None,
#[cfg(target_os = "linux")]
io_mode: None,
#[cfg(target_os = "linux")]
gdb_port: None,
config: Some(PathBuf::from("config.txt")),
#[cfg(feature = "instrument")]
Expand Down Expand Up @@ -759,7 +753,6 @@ mod tests {
file_isolation: Some(String::from("strict")),
#[cfg(target_os = "linux")]
io_mode: Some(String::from("direct")),
#[cfg(target_os = "linux")]
gdb_port: Some(1),
config: Some(PathBuf::from("config.txt")),
#[cfg(feature = "instrument")]
Expand Down
155 changes: 155 additions & 0 deletions src/gdb/base.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
use gdbstub::{
arch::Arch as GdbstubArch,
common::Tid,
target::{
self, Target, TargetError, TargetResult,
ext::{
base::multithread as target_multithread,
section_offsets::{Offsets, SectionOffsets},
},
},
};
use uhyve_interface::GuestVirtAddr;

#[cfg(not(target_os = "macos"))]
use crate::os::gdb::regs;
use crate::{
HypervisorError, gdb::GdbVcpuManager, vcpu::VirtualCPU, virt_to_phys, vm::DefaultBackend,
};

impl Target for GdbVcpuManager<DefaultBackend> {
type Error = HypervisorError;

#[cfg(target_arch = "aarch64")]
type Arch = gdbstub_arch::aarch64::AArch64;
#[cfg(target_arch = "x86_64")]
type Arch = gdbstub_arch::x86::X86_64_SSE;

// --------------- IMPORTANT NOTE ---------------
// Always remember to annotate IDET enable methods with `inline(always)`!
// Without this annotation, LLVM might fail to dead-code-eliminate nested IDET
// implementations, resulting in unnecessary binary bloat.

#[inline(always)]
fn base_ops(&mut self) -> target::ext::base::BaseOps<'_, Self::Arch, Self::Error> {
target::ext::base::BaseOps::MultiThread(self)
}

#[inline(always)]
#[cfg(not(target_os = "macos"))]
fn support_breakpoints(
&mut self,
) -> Option<target::ext::breakpoints::BreakpointsOps<'_, Self>> {
Some(self)
}

#[inline(always)]
#[cfg(not(target_os = "macos"))]
fn support_section_offsets(
&mut self,
) -> Option<target::ext::section_offsets::SectionOffsetsOps<'_, Self>> {
Some(self)
}
}

#[cfg_attr(target_os = "macos", allow(unused_variables))]
impl target_multithread::MultiThreadBase for GdbVcpuManager<DefaultBackend> {
fn read_registers(
&mut self,
regs: &mut <Self::Arch as GdbstubArch>::Registers,
tid: Tid,
) -> TargetResult<(), Self> {
#[cfg(not(target_os = "macos"))]
return regs::read(self.get_vm_cpu(tid).read().unwrap().get_vcpu(), regs)
.map_err(|error| TargetError::Errno(error.errno().try_into().unwrap()));
#[cfg(target_os = "macos")]
todo!()
}

fn write_registers(
&mut self,
regs: &<Self::Arch as GdbstubArch>::Registers,
tid: Tid,
) -> TargetResult<(), Self> {
#[cfg(not(target_os = "macos"))]
return regs::write(regs, self.get_vm_cpu(tid).read().unwrap().get_vcpu())
.map_err(|error| TargetError::Errno(error.errno().try_into().unwrap()));
#[cfg(target_os = "macos")]
todo!()
}

fn read_addrs(
&mut self,
start_addr: u64,
data: &mut [u8],
tid: Tid,
) -> TargetResult<usize, Self> {
let guest_addr = GuestVirtAddr::try_new(start_addr).map_err(|_e| TargetError::NonFatal)?;
// Safety: mem is copied to data before mem can be modified.
let src = unsafe {
self.peripherals.mem.slice_at(
virt_to_phys(
guest_addr,
&self.peripherals.mem,
self.get_vm_cpu(tid).read().unwrap().get_root_pagetable(),
)
.map_err(|_| ())?,
data.len(),
)
}
.map_err(|_e| TargetError::NonFatal)?;
data.copy_from_slice(src);
Ok(data.len())
}

fn write_addrs(&mut self, start_addr: u64, data: &[u8], tid: Tid) -> TargetResult<(), Self> {
// Safety: self.vm.mem is not altered during the lifetime of mem.
let mem = unsafe {
self.peripherals.mem.slice_at_mut(
virt_to_phys(
GuestVirtAddr::new(start_addr),
&self.peripherals.mem,
self.get_vm_cpu(tid).read().unwrap().get_root_pagetable(),
)
.map_err(|_err| ())?,
data.len(),
)
}
.unwrap();
mem.copy_from_slice(data);
Ok(())
}

fn list_active_threads(
&mut self,
thread_is_active: &mut dyn FnMut(Tid),
) -> Result<(), Self::Error> {
for i in &self.vcpus {
if i.shared.is_stopped() && !self.is_initializing {
continue;
}
thread_is_active(i.tid.try_into().unwrap());
}
Ok(())
}

fn is_thread_alive(&mut self, tid: Tid) -> Result<bool, Self::Error> {
Ok(self.is_initializing || !self.get_vcpu_wrapper(tid).shared.is_stopped())
}

#[inline(always)]
fn support_resume(&mut self) -> Option<target_multithread::MultiThreadResumeOps<'_, Self>> {
Some(self)
}
}

impl SectionOffsets for crate::gdb::GdbVcpuManager<DefaultBackend> {
fn get_section_offsets(&mut self) -> Result<Offsets<u64>, Self::Error> {
let offset = self.kernel_info.kernel_address.as_u64();
Ok(Offsets::Sections {
text: offset,
data: offset,
bss: Some(offset),
})
}
}
Loading