pelf 0.1.5

A library for parsing/generating/analyzing ELF
Documentation
use super::{ElfParser, ElfParserError};
use crate::{file, header, program_header, section};

impl ElfParser {
    /// parses the entire of the given ELF file.
    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
            ))),
        }
    }

    /// parses the entire of the given ELF file.
    /// that may return the "raw" representation of the ELF file.
    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
            ))),
        }
    }

    /// parses an 64-bit ELF file.
    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, &section_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,
        })
    }

    /// parses an 64-bit ELF file as the raw representation.
    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,
        })
    }
}