use super::defs::{ElfLayout, ElfPhdrRaw, ElfProgramFlags, ElfProgramType, NativeElfLayout};
use alloc::vec::Vec;
#[derive(Debug)]
#[repr(transparent)]
pub struct ElfPhdr<L: ElfLayout = NativeElfLayout> {
phdr: L::Phdr,
}
impl<L: ElfLayout> ElfPhdr<L> {
#[inline]
pub fn new(
program_type: ElfProgramType,
flags: ElfProgramFlags,
p_offset: usize,
p_vaddr: usize,
p_paddr: usize,
p_filesz: usize,
p_memsz: usize,
p_align: usize,
) -> Self {
let mut phdr: L::Phdr = unsafe { core::mem::zeroed() };
phdr.set_p_type(program_type.raw());
phdr.set_p_flags(flags.bits());
phdr.set_p_offset(p_offset);
phdr.set_p_vaddr(p_vaddr);
phdr.set_p_paddr(p_paddr);
phdr.set_p_filesz(p_filesz);
phdr.set_p_memsz(p_memsz);
phdr.set_p_align(p_align);
Self { phdr }
}
#[inline]
pub fn program_type(&self) -> ElfProgramType {
ElfProgramType::new(self.phdr.p_type())
}
#[inline]
pub fn flags(&self) -> ElfProgramFlags {
ElfProgramFlags::from_bits_retain(self.phdr.p_flags())
}
#[inline]
pub fn p_offset(&self) -> usize {
self.phdr.p_offset()
}
#[inline]
pub fn p_vaddr(&self) -> usize {
self.phdr.p_vaddr()
}
#[inline]
pub fn p_paddr(&self) -> usize {
self.phdr.p_paddr()
}
#[inline]
pub fn p_filesz(&self) -> usize {
self.phdr.p_filesz()
}
#[inline]
pub fn p_memsz(&self) -> usize {
self.phdr.p_memsz()
}
#[inline]
pub fn p_align(&self) -> usize {
self.phdr.p_align()
}
#[inline]
pub fn set_program_type(&mut self, program_type: ElfProgramType) {
self.phdr.set_p_type(program_type.raw());
}
#[inline]
pub fn set_flags(&mut self, flags: ElfProgramFlags) {
self.phdr.set_p_flags(flags.bits());
}
#[inline]
pub fn set_p_offset(&mut self, p_offset: usize) {
self.phdr.set_p_offset(p_offset);
}
#[inline]
pub fn set_p_vaddr(&mut self, p_vaddr: usize) {
self.phdr.set_p_vaddr(p_vaddr);
}
#[inline]
pub fn set_p_paddr(&mut self, p_paddr: usize) {
self.phdr.set_p_paddr(p_paddr);
}
#[inline]
pub fn set_p_filesz(&mut self, p_filesz: usize) {
self.phdr.set_p_filesz(p_filesz);
}
#[inline]
pub fn set_p_memsz(&mut self, p_memsz: usize) {
self.phdr.set_p_memsz(p_memsz);
}
#[inline]
pub fn set_p_align(&mut self, p_align: usize) {
self.phdr.set_p_align(p_align);
}
}
impl<L: ElfLayout> Clone for ElfPhdr<L> {
#[inline]
fn clone(&self) -> Self {
Self::new(
self.program_type(),
self.flags(),
self.p_offset(),
self.p_vaddr(),
self.p_paddr(),
self.p_filesz(),
self.p_memsz(),
self.p_align(),
)
}
}
#[derive(Clone)]
pub(crate) enum ElfPhdrs<L: ElfLayout = NativeElfLayout> {
Mmap(&'static [ElfPhdr<L>]),
Vec(Vec<ElfPhdr<L>>),
}
impl<L: ElfLayout> ElfPhdrs<L> {
pub(crate) fn as_slice(&self) -> &[ElfPhdr<L>] {
match self {
ElfPhdrs::Mmap(phdrs) => phdrs,
ElfPhdrs::Vec(phdrs) => phdrs,
}
}
}
#[cfg(test)]
mod tests {
use super::{ElfPhdr, ElfProgramFlags, ElfProgramType};
#[test]
fn owned_phdr_round_trips_and_mutates() {
let mut phdr: ElfPhdr = ElfPhdr::new(
ElfProgramType::LOAD,
ElfProgramFlags::READ | ElfProgramFlags::WRITE,
1,
2,
3,
4,
5,
6,
);
assert_eq!(phdr.program_type(), ElfProgramType::LOAD);
assert_eq!(phdr.flags(), ElfProgramFlags::READ | ElfProgramFlags::WRITE);
assert_eq!(phdr.p_offset(), 1);
assert_eq!(phdr.p_vaddr(), 2);
assert_eq!(phdr.p_paddr(), 3);
assert_eq!(phdr.p_filesz(), 4);
assert_eq!(phdr.p_memsz(), 5);
assert_eq!(phdr.p_align(), 6);
phdr.set_program_type(ElfProgramType::DYNAMIC);
phdr.set_flags(ElfProgramFlags::READ);
phdr.set_p_offset(7);
phdr.set_p_vaddr(8);
phdr.set_p_paddr(9);
phdr.set_p_filesz(10);
phdr.set_p_memsz(11);
phdr.set_p_align(12);
assert_eq!(phdr.program_type(), ElfProgramType::DYNAMIC);
assert_eq!(phdr.flags(), ElfProgramFlags::READ);
assert_eq!(phdr.p_offset(), 7);
assert_eq!(phdr.p_vaddr(), 8);
assert_eq!(phdr.p_paddr(), 9);
assert_eq!(phdr.p_filesz(), 10);
assert_eq!(phdr.p_memsz(), 11);
assert_eq!(phdr.p_align(), 12);
}
}