vmi_utils/hexdump.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
use vmi_core::{AccessContext, VmiCore, VmiDriver, VmiError};
/// Representation of memory for hexdump.
pub enum Representation {
/// Display memory as 8-bit values.
U8,
/// Display memory as 32-bit values.
U32,
/// Display memory as 64-bit values.
U64,
}
/// Print a hexdump of memory at the given address.
pub fn hexdump<Driver>(
vmi: &VmiCore<Driver>,
ctx: impl Into<AccessContext>,
count: usize,
representation: Representation,
) -> Result<(), VmiError>
where
Driver: VmiDriver,
{
let ctx = ctx.into();
let mut buf = vec![0u8; count];
vmi.read(ctx, &mut buf)?;
println!(
"--------------------| 0 1 2 3 4 5 6 7 8 9 A B C D E F | 0123456789ABCDEF"
);
for (index, chunk) in buf.chunks(16).enumerate() {
print!(" 0x{:016X} |", ctx.address + (index * 16) as u64);
match representation {
Representation::U8 => {
for &byte in chunk {
print!(" {:02X}", byte);
}
if chunk.len() < 16 {
for _ in 0..(16 - chunk.len()) {
print!(" ");
}
}
}
Representation::U32 => {
for dword in chunk.chunks(4) {
print!(
" 0x{:08X}",
u32::from_le_bytes([dword[0], dword[1], dword[2], dword[3]])
);
}
if (chunk.len() % 4) != 0 {
for _ in 0..(4 - (chunk.len() % 4)) {
print!(" ");
}
}
}
Representation::U64 => {
for qword in chunk.chunks(8) {
print!(
" 0x{:016X}",
u64::from_le_bytes([
qword[0], qword[1], qword[2], qword[3], qword[4], qword[5], qword[6],
qword[7],
])
);
}
if (chunk.len() % 8) != 0 {
for _ in 0..(8 - (chunk.len() % 8)) {
print!(" ");
}
}
}
}
print!(" | ");
for &byte in chunk {
print!(
"{}",
if byte.is_ascii_graphic() {
byte as char
}
else {
'.'
}
);
}
if chunk.len() < 16 {
for _ in 0..(16 - chunk.len()) {
print!(" ");
}
}
println!();
}
Ok(())
}