pub trait DataLookup {
fn section_at(&self, vaddr: u64) -> Option<(&str, &[u8], usize)>;
fn image_base(&self) -> u64 {
0
}
}
impl DataLookup for crate::format::elf::Elf64File {
fn section_at(&self, vaddr: u64) -> Option<(&str, &[u8], usize)> {
for (idx, sh, data) in self.sections() {
if sh.sh_size == 0 {
continue;
}
let end = sh.sh_addr.checked_add(sh.sh_size)?;
if vaddr >= sh.sh_addr && vaddr < end {
let offset = (vaddr - sh.sh_addr) as usize;
let name = self.section_name(idx)?;
return Some((name, data, offset));
}
}
None
}
}
impl DataLookup for crate::format::pe::PeFile {
fn image_base(&self) -> u64 {
self.image_base
}
fn section_at(&self, vaddr: u64) -> Option<(&str, &[u8], usize)> {
if let Some(hit) = self.section_at_rva(vaddr) {
return Some(hit);
}
if vaddr >= self.image_base {
return self.section_at_rva(vaddr - self.image_base);
}
None
}
}
trait PeFileExt {
fn section_at_rva(&self, rva: u64) -> Option<(&str, &[u8], usize)>;
}
impl PeFileExt for crate::format::pe::PeFile {
fn section_at_rva(&self, rva: u64) -> Option<(&str, &[u8], usize)> {
for (idx, sh) in self.sections.iter().enumerate() {
let start = u64::from(sh.virtual_address);
let size = u64::from(sh.virtual_size.max(sh.size_of_raw_data));
if size == 0 {
continue;
}
let end = start.checked_add(size)?;
if rva < start || rva >= end {
continue;
}
let data = self.section_data(idx)?;
let offset = (rva - start) as usize;
if offset >= data.len() {
return None;
}
let name = self.section_name(idx).unwrap_or("");
return Some((name, data, offset));
}
None
}
}