use super::{ElfParser, ElfParserError};
use crate::{file, header, program_header, section};
impl ElfParser {
pub fn parse_elf_file<'a>(
&'a self,
b: &'a [u8],
) -> Result<file::ElfFile, ElfParserError<&'a [u8]>> {
log::debug!("the entire byte-length of elf file = {}", b.len());
let (b, elf_identification) = self
.peek_raw_elf_identification(b)
.map_err(|e| ElfParserError::FailedToParse("failed to peek e_ident".to_string(), e))?;
match elf_identification.e_class {
header::ELF_IDENT_CLASS_64 => self.parse_elf64_file(b).map(file::ElfFile::Elf64),
_ => Err(ElfParserError::Unsupported(format!(
"invalid e_ident.e_class {}",
elf_identification.e_class
))),
}
}
pub fn parse_raw_elf_file<'a>(
&'a self,
b: &'a [u8],
) -> Result<file::RawElfFile, ElfParserError<&'a [u8]>> {
let (b, elf_identification) = self
.peek_raw_elf_identification(b)
.map_err(|e| ElfParserError::FailedToParse("failed to peek e_ident".to_string(), e))?;
match elf_identification.e_class {
header::ELF_IDENT_CLASS_64 => self.parse_raw_elf64_file(b).map(file::RawElfFile::Elf64),
_ => Err(ElfParserError::Unsupported(format!(
"invalid e_ident.e_class {}",
elf_identification.e_class
))),
}
}
pub(super) fn parse_elf64_file<'a>(
&'a self,
b: &'a [u8],
) -> Result<file::Elf64File, ElfParserError<&'a [u8]>> {
let (_b, ehdr) = if self.parse_config._parse_header {
self.parse_raw_elf64_header(b)
.map(|(b, raw)| (b, header::Elf64Header::from(raw)))
.map_err(|e| {
ElfParserError::FailedToParse("failed to parse e_ident".to_string(), e)
})?
} else {
(b, header::Elf64Header::default())
};
log::debug!("parser goes {} mode", ehdr.ident.class);
log::debug!("ehdr.e_shnum = {}", ehdr.shnum);
log::debug!("ehdr.e_phnum = {}", ehdr.phnum);
let (_b, phdrs) = if self.parse_config._parse_pht {
self.parse_raw_elf64_program_header_table(
b,
ehdr.ident.data.into(),
ehdr.phoff as usize,
ehdr.phnum as usize,
)
.map(|(b, raw)| (b, program_header::Elf64ProgramHeaderTable::from(raw)))
.map_err(|e| {
ElfParserError::FailedToParse("failed ot parse prgoram header table".to_string(), e)
})?
} else {
log::debug!("skip parsing program header table");
(b, program_header::Elf64ProgramHeaderTable::default())
};
let (_b, sections) = if self.parse_config._parse_sections {
let (_b, raw_shdrs) = self
.parse_raw_elf64_section_header_table(
b,
ehdr.ident.data.into(),
ehdr.shoff as usize,
ehdr.shnum as usize,
)
.map_err(|e| {
ElfParserError::FailedToParse(
"failed to parse section header table".to_string(),
e,
)
})?;
let (_b, section_datas) =
self.parse_raw_elf64_sections(b, &raw_shdrs).map_err(|e| {
ElfParserError::FailedToParse("failed to parse sections".to_string(), e)
})?;
let section_name_string_table =
section::ElfStringTable::from(section_datas[ehdr.shstrndx as usize].clone());
let shdr_vec: Vec<section::Elf64SectionHeader> = raw_shdrs
.into_iter()
.map(section::Elf64SectionHeader::from)
.collect();
let shdrs = section::Elf64SectionHeaderTable::new(shdr_vec);
self.parse_elf64_sections(b, shdrs, §ion_name_string_table, ehdr.ident.data.into())
.map_err(|e| {
ElfParserError::FailedToParse("failed to parse sections".to_string(), e)
})?
} else {
log::debug!("skip parsing sections/section header table");
(b, section::Elf64Sections::default())
};
Ok(file::Elf64File {
header: ehdr,
program_headers: phdrs,
sections,
})
}
pub(super) fn parse_raw_elf64_file<'a>(
&'a self,
b: &'a [u8],
) -> Result<file::RawElf64File, ElfParserError<&'a [u8]>> {
let (_b, ehdr) = if self.parse_config._parse_header {
self.parse_raw_elf64_header(b).map_err(|e| {
ElfParserError::FailedToParse("failed to parse elf header".to_string(), e)
})?
} else {
(b, header::RawElf64Header::default())
};
let (_b, shdrs) = if self.parse_config._parse_sections {
self.parse_raw_elf64_section_header_table(
b,
ehdr.e_ident.e_data,
ehdr.e_shoff as usize,
ehdr.e_shnum as usize,
)
.map_err(|e| {
ElfParserError::FailedToParse("failed to parse section header table".to_string(), e)
})?
} else {
(b, section::RawElf64SectionHeaderTable::default())
};
let (_b, section_data_set) = if self.parse_config._parse_sections {
self.parse_raw_elf64_sections(b, &shdrs).map_err(|e| {
ElfParserError::FailedToParse("failed to parse sections".to_string(), e)
})?
} else {
(b, vec![section::RawElf64Section::default(); shdrs.len()])
};
let (_b, phdrs) = if self.parse_config._parse_pht {
self.parse_raw_elf64_program_header_table(
b,
ehdr.e_ident.e_data,
ehdr.e_phoff as usize,
ehdr.e_phnum as usize,
)
.map_err(|e| {
ElfParserError::FailedToParse("failed to parse program header table".to_string(), e)
})?
} else {
(b, program_header::RawElf64ProgramHeaderTable::default())
};
Ok(file::RawElf64File {
header: ehdr,
program_headers: phdrs,
section_headers: shdrs,
sections: section_data_set,
})
}
}