Skip to content

Commit 69de9b3

Browse files
committed
Fix cargo feature 'crashdump'
Signed-off-by: Ludvig Liljenberg <[email protected]>
1 parent 6d4c3a8 commit 69de9b3

File tree

12 files changed

+138
-132
lines changed

12 files changed

+138
-132
lines changed

.github/workflows/dep_rust.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ jobs:
7474
# with only one driver enabled (driver mshv/kvm feature is ignored on windows) + seccomp + inprocess
7575
just test-rust ${{ matrix.config }} inprocess,seccomp,${{ matrix.hypervisor == 'mshv' && 'mshv' || 'kvm' }}
7676
77+
# make sure certain cargo features compile
78+
cargo check -p hyperlight-host --features crashdump
79+
7780
# without any driver (shouldn't compile)
7881
just test-rust-feature-compilation-fail ${{ matrix.config }}
7982

docs/debugging-hyperlight.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,6 @@ cargo test --package hyperlight-host --test integration_test --features print_de
3939

4040
## Dumping the memory configuration, virtual processor register state and memory contents on a crash or unexpected VM Exit
4141

42-
To dump the details of the memory configuration, the virtual processors register state and the contents of the VM memory set the feature `dump_on_crash` and run a debug build. This will result in a dump file being created in the temporary directory. The name and location of the dump file will be printed to the console and logged as an error message.
42+
To dump the details of the memory configuration, the virtual processors register state and the contents of the VM memory set the feature `crashdump` and run a debug build. This will result in a dump file being created in the temporary directory. The name and location of the dump file will be printed to the console and logged as an error message.
4343

4444
There are no tools at this time to analyze the dump file, but it can be useful for debugging.

src/hyperlight_host/Cargo.toml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,7 @@ function_call_metrics = []
118118
executable_heap = []
119119
# This feature enables printing of debug information to stdout in debug builds
120120
print_debug = []
121-
# This feature enables dunping of the VMs details to a file when an unexpected or error exit occurs in a VM in debug mode
122-
# the name of the file is output to stdout and logged.
123-
dump_on_crash = ["dep:tempfile"]
121+
crashdump = ["dep:tempfile"] # Dumps the VM state to a file on unexpected errors or crashes. The path of the file will be printed on stdout and logged. This feature can only be used in debug builds.
124122
kvm = ["dep:kvm-bindings", "dep:kvm-ioctls"]
125123
mshv = ["dep:mshv-bindings", "dep:mshv-ioctls"]
126124
inprocess = []

src/hyperlight_host/build.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ fn main() -> Result<()> {
9494
// inprocess feature is aliased with debug_assertions to make it only available in debug-builds.
9595
// You should never use #[cfg(feature = "inprocess")] in the codebase. Use #[cfg(inprocess)] instead.
9696
inprocess: { all(feature = "inprocess", debug_assertions) },
97+
// crashdump feature is aliased with debug_assertions to make it only available in debug-builds.
98+
crashdump: { all(feature = "crashdump", debug_assertions) },
9799
}
98100

99101
write_built_file()?;
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
use std::io::Write;
2+
3+
use tempfile::NamedTempFile;
4+
5+
use super::Hypervisor;
6+
use crate::{new_error, Result};
7+
8+
/// Dump registers + memory regions + raw memory to a tempfile
9+
#[cfg(crashdump)]
10+
pub(crate) fn crashdump_to_tempfile(hv: &dyn Hypervisor) -> Result<()> {
11+
let mem_regions = hv.get_memory_regions();
12+
let mem_size = mem_regions
13+
.iter()
14+
.map(|region| region.host_region.len())
15+
.sum();
16+
let mem_start_addr = mem_regions[0].host_region.start as *const u8;
17+
18+
if mem_start_addr.is_null() || mem_size == 0 {
19+
return Err(new_error!(
20+
"Invalid address or size while creating crashdump"
21+
));
22+
}
23+
24+
let mut temp_file = NamedTempFile::with_prefix("mem")?;
25+
26+
let hv_details = format!("{:#x?}", hv);
27+
28+
// write hypervisor details such as registers, memory regions, etc.
29+
temp_file.write_all(hv_details.as_bytes())?;
30+
// write memory dump
31+
temp_file.write_all(b"================ MEMORY DUMP =================\n")?;
32+
// SAFETY: Address and size non-null and non-zero
33+
unsafe {
34+
let slice = std::slice::from_raw_parts(mem_start_addr, mem_size);
35+
temp_file.write_all(slice)?;
36+
temp_file.flush()?;
37+
}
38+
let persist_path = temp_file.path().with_extension("dmp");
39+
temp_file
40+
.persist(&persist_path)
41+
.map_err(|e| new_error!("Failed to persist crashdump file: {:?}", e))?;
42+
43+
println!("Memory dumped to file: {:?}", persist_path);
44+
log::error!("Memory dumped to file: {:?}", persist_path);
45+
46+
Ok(())
47+
}

src/hyperlight_host/src/hypervisor/hyperv_linux.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -311,8 +311,6 @@ impl Hypervisor for HypervLinuxDriver {
311311
"mshv MMIO unmapped GPA -Details: Address: {} \n {:#?}",
312312
addr, &self
313313
);
314-
#[cfg(all(debug_assertions, feature = "dump_on_crash"))]
315-
self.dump_on_crash(self.mem_regions.clone());
316314
HyperlightExit::Mmio(addr)
317315
}
318316
INVALID_GPA_ACCESS_MESSAGE => {
@@ -323,8 +321,6 @@ impl Hypervisor for HypervLinuxDriver {
323321
"mshv MMIO invalid GPA access -Details: Address: {} \n {:#?}",
324322
gpa, &self
325323
);
326-
#[cfg(all(debug_assertions, feature = "dump_on_crash"))]
327-
self.dump_on_crash(self.mem_regions.clone());
328324
match self.get_memory_access_violation(
329325
gpa as usize,
330326
&self.mem_regions,
@@ -336,8 +332,6 @@ impl Hypervisor for HypervLinuxDriver {
336332
}
337333
other => {
338334
debug!("mshv Other Exit: Exit: {:#?} \n {:#?}", other, &self);
339-
#[cfg(all(debug_assertions, feature = "dump_on_crash"))]
340-
self.dump_on_crash(self.mem_regions.clone());
341335
log_then_return!("unknown Hyper-V run message type {:?}", other);
342336
}
343337
},
@@ -347,8 +341,6 @@ impl Hypervisor for HypervLinuxDriver {
347341
libc::EAGAIN => HyperlightExit::Retry(),
348342
_ => {
349343
debug!("mshv Error - Details: Error: {} \n {:#?}", e, &self);
350-
#[cfg(all(debug_assertions, feature = "dump_on_crash"))]
351-
self.dump_on_crash(self.mem_regions.clone());
352344
log_then_return!("Error running VCPU {:?}", e);
353345
}
354346
},
@@ -360,6 +352,11 @@ impl Hypervisor for HypervLinuxDriver {
360352
fn as_mut_hypervisor(&mut self) -> &mut dyn Hypervisor {
361353
self as &mut dyn Hypervisor
362354
}
355+
356+
#[cfg(crashdump)]
357+
fn get_memory_regions(&self) -> &[MemoryRegion] {
358+
&self.mem_regions
359+
}
363360
}
364361

365362
impl Drop for HypervLinuxDriver {

src/hyperlight_host/src/hypervisor/hyperv_windows.rs

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -508,18 +508,6 @@ impl Hypervisor for HypervWindowsDriver {
508508
"HyperV Memory Access Details :\n GPA: {:#?}\n Access Info :{:#?}\n {:#?} ",
509509
gpa, access_info, &self
510510
);
511-
#[cfg(all(debug_assertions, feature = "dump_on_crash"))]
512-
{
513-
if let Err(e) = unsafe {
514-
self.write_dump_file(
515-
self.mem_regions.clone(),
516-
self.source_address.add(PAGE_SIZE_USIZE) as *const u8,
517-
self.size,
518-
)
519-
} {
520-
println!("Error dumping memory: {}", e);
521-
}
522-
}
523511

524512
match self.get_memory_access_violation(gpa as usize, &self.mem_regions, access_info)
525513
{
@@ -539,18 +527,6 @@ impl Hypervisor for HypervWindowsDriver {
539527
"HyperV Unexpected Exit Details :#nReason {:#?}\n {:#?}",
540528
exit_context.ExitReason, &self
541529
);
542-
#[cfg(all(debug_assertions, feature = "dump_on_crash"))]
543-
{
544-
if let Err(e) = unsafe {
545-
self.write_dump_file(
546-
self.mem_regions.clone(),
547-
self.source_address.add(PAGE_SIZE_USIZE) as *const u8,
548-
self.size,
549-
)
550-
} {
551-
println!("Error dumping memory: {}", e);
552-
}
553-
}
554530
match self.get_exit_details(exit_context.ExitReason) {
555531
Ok(error) => HyperlightExit::Unknown(error),
556532
Err(e) => HyperlightExit::Unknown(format!("Error getting exit details: {}", e)),
@@ -569,6 +545,11 @@ impl Hypervisor for HypervWindowsDriver {
569545
fn as_mut_hypervisor(&mut self) -> &mut dyn Hypervisor {
570546
self as &mut dyn Hypervisor
571547
}
548+
549+
#[cfg(crashdump)]
550+
fn get_memory_regions(&self) -> &[MemoryRegion] {
551+
&self.mem_regions
552+
}
572553
}
573554

574555
#[cfg(test)]

src/hyperlight_host/src/hypervisor/inprocess.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ use std::fmt::Debug;
1818
use std::os::raw::c_void;
1919

2020
use super::{HyperlightExit, Hypervisor};
21+
#[cfg(crashdump)]
22+
use crate::mem::memory_region::MemoryRegion;
2123
use crate::sandbox::leaked_outb::LeakedOutBWrapper;
2224
use crate::Result;
2325

@@ -123,4 +125,9 @@ impl<'a> Hypervisor for InprocessDriver<'a> {
123125
fn get_partition_handle(&self) -> windows::Win32::System::Hypervisor::WHV_PARTITION_HANDLE {
124126
unimplemented!("get_partition_handle should not be needed since we are in in-process mode")
125127
}
128+
129+
#[cfg(crashdump)]
130+
fn get_memory_regions(&self) -> &[MemoryRegion] {
131+
unimplemented!("get_memory_regions is not supported since we are in in-process mode")
132+
}
126133
}

src/hyperlight_host/src/hypervisor/kvm.rs

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ limitations under the License.
1717
use std::convert::TryFrom;
1818
use std::fmt::Debug;
1919

20-
use cfg_if::cfg_if;
2120
use kvm_bindings::{kvm_fpu, kvm_regs, kvm_userspace_memory_region, KVM_MEM_READONLY};
2221
use kvm_ioctls::Cap::UserMemory;
2322
use kvm_ioctls::{Kvm, VcpuExit, VcpuFd, VmFd};
@@ -283,11 +282,9 @@ impl Hypervisor for KVMDriver {
283282
}
284283
Ok(VcpuExit::MmioRead(addr, _)) => {
285284
debug!("KVM MMIO Read -Details: Address: {} \n {:#?}", addr, &self);
286-
#[cfg(all(debug_assertions, feature = "dump_on_crash"))]
287-
self.dump_on_crash(self.mem_regions.clone());
288-
let gpa = addr as usize;
285+
289286
match self.get_memory_access_violation(
290-
gpa,
287+
addr as usize,
291288
&self.mem_regions,
292289
MemoryRegionFlags::READ,
293290
) {
@@ -297,11 +294,9 @@ impl Hypervisor for KVMDriver {
297294
}
298295
Ok(VcpuExit::MmioWrite(addr, _)) => {
299296
debug!("KVM MMIO Write -Details: Address: {} \n {:#?}", addr, &self);
300-
#[cfg(all(debug_assertions, feature = "dump_on_crash"))]
301-
self.dump_on_crash(self.mem_regions.clone());
302-
let gpa = addr as usize;
297+
303298
match self.get_memory_access_violation(
304-
gpa,
299+
addr as usize,
305300
&self.mem_regions,
306301
MemoryRegionFlags::WRITE,
307302
) {
@@ -315,25 +310,12 @@ impl Hypervisor for KVMDriver {
315310
libc::EAGAIN => HyperlightExit::Retry(),
316311
_ => {
317312
debug!("KVM Error -Details: Address: {} \n {:#?}", e, &self);
318-
#[cfg(all(debug_assertions, feature = "dump_on_crash"))]
319-
self.dump_on_crash(self.mem_regions.clone());
320313
log_then_return!("Error running VCPU {:?}", e);
321314
}
322315
},
323316
Ok(other) => {
324-
cfg_if! {
325-
if #[cfg(all(feature = "print_debug", debug_assertions))] {
326-
let _ = other;
327-
debug!("KVM Other Exit: \n {:#?}", &self);
328-
HyperlightExit::Unknown("Unexpected KVM Exit".to_string())
329-
} else if #[cfg(all(feature = "dump_on_crash", debug_assertions))] {
330-
self.dump_on_crash(self.mem_regions.clone());
331-
HyperlightExit::Unknown(format!("Unexpected KVM Exit {:?}", other))
332-
} else{
333-
debug!("KVM Other Exit {:?}", other);
334-
HyperlightExit::Unknown(format!("Unexpected KVM Exit {:?}", other))
335-
}
336-
}
317+
debug!("KVM Other Exit {:?}", other);
318+
HyperlightExit::Unknown(format!("Unexpected KVM Exit {:?}", other))
337319
}
338320
};
339321
Ok(result)
@@ -343,6 +325,11 @@ impl Hypervisor for KVMDriver {
343325
fn as_mut_hypervisor(&mut self) -> &mut dyn Hypervisor {
344326
self as &mut dyn Hypervisor
345327
}
328+
329+
#[cfg(crashdump)]
330+
fn get_memory_regions(&self) -> &[MemoryRegion] {
331+
&self.mem_regions
332+
}
346333
}
347334

348335
#[cfg(test)]

0 commit comments

Comments
 (0)