Skip to content

Commit

Permalink
windows works
Browse files Browse the repository at this point in the history
  • Loading branch information
codyps committed Nov 5, 2021
1 parent 393a85d commit af3d1d3
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 102 deletions.
54 changes: 0 additions & 54 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ tracing = "0.1"
libc = { version = "0.2", features = ["extra_traits"] }

[target.'cfg(windows)'.dependencies]
object = "0.27"
winapi = { version = "0.3", features = ["psapi", "libloaderapi"] }
winapi = { version = "0.3", features = ["libloaderapi", "winnt", "dbghelp"] }
lazy_static = "1"

[dev-dependencies]
Expand Down
77 changes: 31 additions & 46 deletions src/windows.rs
Original file line number Diff line number Diff line change
@@ -1,63 +1,48 @@
use lazy_static::lazy_static;
use object::Object;
use tracing::{event, Level};
use winapi::um::dbghelp::ImageNtHeader;
use winapi::um::libloaderapi::GetModuleHandleA;
use winapi::um::psapi::GetModuleInformation;
use winapi::um::winnt::IMAGE_DEBUG_DIRECTORY;
use winapi::um::winnt::IMAGE_DEBUG_TYPE_CODEVIEW;
use winapi::um::winnt::IMAGE_DIRECTORY_ENTRY_DEBUG;

#[allow(bad_style)]
struct CV_INFO_PDB70 {
cv_signature: u32,
signature: [u8; 16],
_age: u32,
// followed by pdb name
}

lazy_static! {
// This primarily exists as a hack to allow us to return a `&'static [u8]`
static ref BUILD_ID_CACHE: Option<&'static [u8]> = {
let module = unsafe { GetModuleHandleA(core::ptr::null_mut()) };
let mut module_info = core::mem::MaybeUninit::uninit();
event!(Level::TRACE, "module {:#x}", module as usize);

let image_nt_header = unsafe { &*ImageNtHeader(module as _) };

// NOTE: GetModuleInformation is just using the PE header to get it's info. We can probably
// skip using it entirely if we grab the size ourselves or `object` can handle it for us.
let ok = unsafe {
GetModuleInformation(
core::ptr::null_mut(),
module,
module_info.as_mut_ptr(),
core::mem::size_of_val(&module_info) as u32,
)
};
if ok != 0 {
let opt_header = &image_nt_header.OptionalHeader;
let dir = &opt_header.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG as usize];
if dir.Size == 0 {
event!(Level::ERROR, "IMAGE_DIRECTORY_ENTRY_DEBUG is empty");
return None;
}

let module_info = unsafe { module_info.assume_init() };

let module_slice: &'static [u8] = unsafe {
core::slice::from_raw_parts(
module_info.lpBaseOfDll as *const u8,
module_info.SizeOfImage as usize,
)
};
let dbg_dir = unsafe { &*((module as usize + dir.VirtualAddress as usize) as *const IMAGE_DEBUG_DIRECTORY) };

// parse the PE file that starts at handle to locate a gnu build-id section or some windows
// thingy.

// let v = match object::read::File::parse(module_slice) {
let v: object::read::pe::PeFile<'_, object::pe::ImageNtHeaders64> = match object::read::pe::PeFile::parse(module_slice) {
Err(e) => {
event!(Level::ERROR, "module parse failed: {}", e);
return None;
if dbg_dir.Type == IMAGE_DEBUG_TYPE_CODEVIEW {
let pdb_info = unsafe { &*((module as usize + dbg_dir.AddressOfRawData as usize) as *const CV_INFO_PDB70) };
if pdb_info.cv_signature != 0x53445352 {
event!(Level::ERROR, "mismatch sig: {:#x}", pdb_info.cv_signature);
None
} else {
Some(&pdb_info.signature[..])
}
Ok(v) => v,
};

let cv = match v.pdb_info() {
Err(e) => {
event!(Level::ERROR, "error obtaining CodeView: {}", e);
return None;
}
Ok(None) => {
event!(Level::INFO, "no pdb_info present in executable");
return None;
}
Ok(Some(v)) => v,
};

Some(&Box::leak(Box::new(cv.guid()))[..])
} else {
event!(Level::ERROR, "wrong image type {:#x}", dbg_dir.Type);
None
}
};
}

Expand Down

0 comments on commit af3d1d3

Please sign in to comment.