use super::ElfParser;
use crate::program_header;
impl ElfParser {
pub(super) fn parse_raw_elf64_program_header_table<'a>(
&'a self,
b: &'a [u8],
encoding: u8,
phoff: usize,
phnum: usize,
) -> nom::IResult<&'a [u8], program_header::RawElf64ProgramHeaderTable> {
let mut phdrs = vec![program_header::RawElf64ProgramHeader::default(); phnum];
for (i, phdr) in phdrs.iter_mut().enumerate().take(phnum) {
log::debug!("trying to parse PHT[{}]", i);
let start = phoff + (std::mem::size_of::<program_header::RawElf64ProgramHeader>() * i);
let (_b, v) = self.parse_raw_elf64_program_header(&b[start..], encoding)?;
*phdr = v;
}
let end = phoff + (std::mem::size_of::<program_header::RawElf64ProgramHeader>() * phnum);
Ok((
&b[end..],
program_header::RawElf64ProgramHeaderTable::new(phdrs),
))
}
fn parse_raw_elf64_program_header<'a>(
&'a self,
b: &'a [u8],
encoding: u8,
) -> nom::IResult<&'a [u8], program_header::RawElf64ProgramHeader> {
let (b, p_type) = self.parse_elf64_word(encoding, b)?;
let (b, p_flags) = self.parse_elf64_word(encoding, b)?;
let (b, p_offset) = self.parse_elf64_offset(encoding, b)?;
let (b, p_vaddr) = self.parse_elf64_address(encoding, b)?;
let (b, p_paddr) = self.parse_elf64_address(encoding, b)?;
let (b, p_filesz) = self.parse_elf64_xword(encoding, b)?;
let (b, p_memsz) = self.parse_elf64_xword(encoding, b)?;
let (b, p_align) = self.parse_elf64_xword(encoding, b)?;
let phdr = program_header::RawElf64ProgramHeaderBuilder::default()
.header_type(p_type)
.flags(p_flags)
.offset(p_offset)
.vaddr(p_vaddr)
.paddr(p_paddr)
.filesz(p_filesz)
.memsz(p_memsz)
.align(p_align)
.build();
Ok((b, phdr))
}
}
#[cfg(test)]
mod tests {
use crate::{header, parser::ElfParserConfig, program_header};
#[test]
fn test_parse_raw_elf64_program_header_table() {
let input = vec![
0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x18, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
let p = ElfParserConfig::new().build();
let result =
p.parse_raw_elf64_program_header_table(&input, header::ELF_IDENT_DATA_2LSB, 0, 2);
assert!(result.is_ok());
let (b, phdrs) = result.unwrap();
assert!(b.is_empty());
let mut it = phdrs.iter();
let phdr0 = it.next();
assert!(phdr0.is_some());
let phdr0 = phdr0.unwrap();
assert_eq!(0x6, phdr0.p_type);
assert_eq!(0x40, phdr0.p_offset);
assert_eq!(0x40, phdr0.p_vaddr);
assert_eq!(0x40, phdr0.p_paddr);
assert_eq!(0x2d8, phdr0.p_filesz);
assert_eq!(0x2d8, phdr0.p_memsz);
assert_eq!(0b100, phdr0.p_flags);
assert_eq!(0x8, phdr0.p_align);
let phdr1 = it.next();
assert!(phdr1.is_some());
let phdr1 = phdr1.unwrap();
assert_eq!(0x3, phdr1.p_type);
assert_eq!(0x318, phdr1.p_offset);
assert_eq!(0x318, phdr1.p_vaddr);
assert_eq!(0x318, phdr1.p_paddr);
assert_eq!(0x1c, phdr1.p_filesz);
assert_eq!(0x1c, phdr1.p_memsz);
assert_eq!(0b100, phdr1.p_flags);
assert_eq!(0x1, phdr1.p_align);
}
#[test]
fn test_parse_raw_elf64_program_header() {
let input = vec![
0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
let p = ElfParserConfig::new().build();
let result = p.parse_raw_elf64_program_header(&input, header::ELF_IDENT_DATA_2LSB);
assert!(result.is_ok());
let (b, phdr) = result.unwrap();
assert!(b.is_empty());
assert_eq!(0x6, phdr.p_type);
assert_eq!(0x40, phdr.p_offset);
assert_eq!(0x40, phdr.p_vaddr);
assert_eq!(0x40, phdr.p_paddr);
assert_eq!(0x2d8, phdr.p_filesz);
assert_eq!(0x2d8, phdr.p_memsz);
assert_eq!(
program_header::ELF_PROGRAM_HEADER_FLAG_READABLE,
phdr.p_flags
);
assert_eq!(0x8, phdr.p_align);
}
}