TL;DR:
In older version of code Debug was implemented for structs in external crates (winapi 0.2 and kernel32-sys 0.2). Updating code with newest version of crates (winapi 0.3, kernel32-sys now just part of that crate), Debug is no longer implemented?
More details:
I'm reading through Rust in Action and chapter 6 gives an example of examining your program's memory (ch6-meminfo-win).
Aside from code not working b/c of an aliasing mistake, it's out of date and I get a depreciation warning for kernel32-sys. So I've tried to bring the code up to date with the current version of winapi (0.3.9 - kernel32-sys is now integrated into that crate) and I think I have everything working, but lines 44 and 56 in the original program ( println!("{:?}", proc_info);
and println!("{:#?}", mem_info);
) give the following errors:
SYSTEM_INFO
cannot be formatted using{:?}
because it doesn't implementDebug
the trait
Debug
is not implemented forMEMORY_BASIC_INFORMATION
I think with my own structs this would be fairly easy, just adding #[derive(Debug)]
above the struct definition, right? But I don't know how to handle it with the struct being defined in winapi
crate.
What I tried:
I used 'Go to SYSTEM_INFO' in my IDE and then added #[derive(Debug)]
above the code it directed me to (line 26 in sysinfoapi.rs
) but it's a STRUCT!
macro and adding derive debug no effect. I also tried adding the line above the struct definition inside of the STRUCT!
and still no effect.
Full code:
use winapi::shared::{
minwindef::DWORD,
minwindef::LPCVOID,
basetsd::SIZE_T,
};
use winapi::um::{
winnt::HANDLE,
winnt::PVOID,
sysinfoapi::SYSTEM_INFO,
winnt::MEMORY_BASIC_INFORMATION,
winnt::PMEMORY_BASIC_INFORMATION,
sysinfoapi::LPSYSTEM_INFO,
processthreadsapi::GetCurrentProcessId,
processthreadsapi::GetCurrentProcess,
sysinfoapi::GetSystemInfo,
memoryapi::VirtualQueryEx,
};
fn main() {
let this_pid: DWORD;
let this_proc: HANDLE;
let min_addr: LPCVOID;
let max_addr: LPCVOID;
let mut base_addr: PVOID;
let mut proc_info: SYSTEM_INFO;
let mut mem_info: MEMORY_BASIC_INFORMATION;
const MEMINFO_SIZE: usize = std::mem::size_of::<MEMORY_BASIC_INFORMATION>();
unsafe {
base_addr = std::mem::zeroed();
proc_info = std::mem::zeroed();
mem_info = std::mem::zeroed();
}
unsafe {
this_pid = GetCurrentProcessId();
this_proc = GetCurrentProcess();
GetSystemInfo(
&mut proc_info as LPSYSTEM_INFO
);
};
min_addr = proc_info.lpMinimumApplicationAddress;
max_addr = proc_info.lpMaximumApplicationAddress;
println!("{:?} @ {:p}", this_pid, this_proc);
println!("{:?}", proc_info);
println!("min: {:p}, max: {:p}", min_addr, max_addr);
loop {
let rc: SIZE_T = unsafe {
VirtualQueryEx(
this_proc, // HANDLE, hProcess
base_addr, // LPCVOID, lpAddress
&mut mem_info, // PMEMORY_BASIC_INFORMATION, lpBuffer
MEMINFO_SIZE as SIZE_T, // SIZE_T, dwLength
)
};
if rc == 0 {
break
}
println!("{:#?}", mem_info);
base_addr = ((base_addr as SIZE_T) mem_info.RegionSize) as PVOID;
}
}
Edit: Fixed const MEMINFO_SIZE
CodePudding user response:
Try using a struct wrapper. When you need to access the wrapped value, use wrapper_name.0
. Here's an example:
struct SystemInfoWrapper(SYSTEM_INFO);
impl std::fmt::Debug for SystemInfoWrapper {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f,
"SYSTEM_INFO {{
lpMinimumApplicationAddress: {:?},
lpMaximumApplicationAddress: {:?},
dwActiveProcessorMask: {:?},
dwNumberOfProcessors: {:?},
dwProcessorType: {:?},
dwAllocationGranularity: {:?},
wProcessorLevel: {:?},
wProcessorRevision: {:?}
}}",
self.0.lpMinimumApplicationAddress,
self.0.lpMaximumApplicationAddress,
self.0.dwActiveProcessorMask,
self.0.dwNumberOfProcessors,
self.0.dwProcessorType,
self.0.dwAllocationGranularity,
self.0.wProcessorLevel,
self.0.wProcessorRevision
)
}
}
struct MemoryBasicInformationWrapper(MEMORY_BASIC_INFORMATION);
impl std::fmt::Debug for MemoryBasicInformationWrapper {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f,
"MEMORY_BASIC_INFORMATION {{
BaseAddress: {:?},
AllocationBase: {:?},
AllocationProtect: {:?},
RegionSize: {:?},
State: {:?},
Protect: {:?},
Type: {:?}
}}",
self.0.BaseAddress,
self.0.AllocationBase,
self.0.AllocationProtect,
self.0.RegionSize,
self.0.State,
self.0.Protect,
self.0.Type
)
}
}