use super::format::ElfFormat;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct ProgramHeader {
pub p_type: u32,
pub p_flags: u32,
pub p_offset: u64,
pub p_vaddr: u64,
pub p_paddr: u64,
pub p_filesz: u64,
pub p_memsz: u64,
pub p_align: u64,
}
impl ProgramHeader {
#[must_use]
pub fn file_offset_of(&self, vaddr: u64) -> Option<u64> {
let delta = vaddr.checked_sub(self.p_vaddr)?;
if delta >= self.p_filesz {
return None;
}
self.p_offset.checked_add(delta)
}
}
#[derive(Debug)]
pub struct ProgramHeaderTable<'a, F: ElfFormat> {
raw: &'a [F::Phdr],
}
impl<F: ElfFormat> Clone for ProgramHeaderTable<'_, F> {
fn clone(&self) -> Self {
*self
}
}
impl<F: ElfFormat> Copy for ProgramHeaderTable<'_, F> {}
impl<F: ElfFormat> Default for ProgramHeaderTable<'_, F> {
fn default() -> Self {
Self { raw: &[] }
}
}
impl<'a, F: ElfFormat> ProgramHeaderTable<'a, F> {
#[must_use]
pub fn new(raw: &'a [F::Phdr]) -> Self {
Self { raw }
}
#[must_use]
pub fn len(&self) -> usize {
self.raw.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.raw.is_empty()
}
#[must_use]
pub fn get(&self, index: usize) -> Option<ProgramHeader> {
self.raw.get(index).map(F::decode_phdr)
}
pub fn iter(&self) -> impl ExactSizeIterator<Item = ProgramHeader> + use<'a, F> {
self.raw.iter().map(F::decode_phdr)
}
#[must_use]
pub fn vaddr_to_offset(&self, vaddr: u64) -> Option<u64> {
self.iter()
.filter(|p| p.p_type == super::consts::PT_LOAD)
.find_map(|p| p.file_offset_of(vaddr))
}
}