use object::{
coff::SectionTable, pe, read::pe::DataDirectories, Bytes, LittleEndian as LE, ReadRef,
};
use super::Value;
pub fn pdb_path(data_dirs: &DataDirectories, mem: &[u8], sections: &SectionTable) -> Option<Value> {
let dir = data_dirs.get(pe::IMAGE_DIRECTORY_ENTRY_DEBUG)?;
let mut debug_data = Bytes(dir.data(mem, sections).ok()?);
let nb_directories = debug_data.len() / std::mem::size_of::<pe::ImageDebugDirectory>();
for debug_dir in debug_data
.read_slice::<pe::ImageDebugDirectory>(nb_directories)
.ok()?
{
if debug_dir.typ.get(LE) != pe::IMAGE_DEBUG_TYPE_CODEVIEW {
return None;
}
let mut offset = 0;
let raw_data_addr = debug_dir.address_of_raw_data.get(LE);
let raw_data_ptr = debug_dir.pointer_to_raw_data.get(LE);
if raw_data_addr != 0 {
if let Some(v) = super::va_to_file_offset(sections, raw_data_addr) {
offset = v;
}
}
if offset == 0 && raw_data_ptr != 0 {
offset = raw_data_ptr;
}
if offset == 0 {
continue;
}
let info = mem
.read_slice_at::<u8>(offset.into(), debug_dir.size_of_data.get(LE) as usize)
.ok()?;
let mut info = Bytes(info);
let sig = match info.read_bytes(4) {
Ok(v) => v.0,
Err(_) => continue,
};
let pdb_path_offset = match sig {
b"NB10" => 12,
b"RSDS" => 20,
b"MTOC" => 16,
_ => continue,
};
let path = info.read_string_at(pdb_path_offset).ok()?;
return Some(path.to_vec().into());
}
None
}