Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  file.rs   Sprache: unbekannt

 
use alloc::vec::Vec;
use core::convert::TryInto;
use core::fmt::Debug;
use core::mem;

use crate::elf;
use crate::endian::{self, Endian, Endianness, U32};
use crate::pod::Pod;
use crate::read::{
    self, util, Architecture, ByteString, Bytes, Error, Export, FileFlags, Import, Object,
    ObjectKind, ReadError, ReadRef, SectionIndex, StringTable, SymbolIndex,
};

use super::{
    CompressionHeader, Dyn, ElfComdat, ElfComdatIterator, ElfDynamicRelocationIterator, ElfSection,
    ElfSectionIterator, ElfSegment, ElfSegmentIterator, ElfSymbol, ElfSymbolIterator,
    ElfSymbolTable, NoteHeader, ProgramHeader, Rel, Rela, RelocationSections, SectionHeader,
    SectionTable, Sym, SymbolTable,
};

/// A 32-bit ELF object file.
///
/// This is a file that starts with [`elf::FileHeader32`], and corresponds
/// to [`crate::FileKind::Elf32`].
pub type ElfFile32<'data, Endian = Endianness, R = &'data [u8]> =
    ElfFile<'data, elf::FileHeader32<Endian>, R>;
/// A 64-bit ELF object file.
///
/// This is a file that starts with [`elf::FileHeader64`], and corresponds
/// to [`crate::FileKind::Elf64`].
pub type ElfFile64<'data, Endian = Endianness, R = &'data [u8]> =
    ElfFile<'data, elf::FileHeader64<Endian>, R>;

/// A partially parsed ELF file.
///
/// Most functionality is provided by the [`Object`] trait implementation.
#[derive(Debug)]
pub struct ElfFile<'data, Elf, R = &'data [u8]>
where
    Elf: FileHeader,
    R: ReadRef<'data>,
{
    pub(super) endian: Elf::Endian,
    pub(super) data: R,
    pub(super) header: &'data Elf,
    pub(super) segments: &'data [Elf::ProgramHeader],
    pub(super) sections: SectionTable<'data, Elf, R>,
    pub(super) relocations: RelocationSections,
    pub(super) symbols: SymbolTable<'data, Elf, R>,
    pub(super) dynamic_symbols: SymbolTable<'data, Elf, R>,
}

impl<'data, Elf, R> ElfFile<'data, Elf, R>
where
    Elf: FileHeader,
    R: ReadRef<'data>,
{
    /// Parse the raw ELF file data.
    pub fn parse(data: R) -> read::Result<Self> {
        let header = Elf::parse(data)?;
        let endian = header.endian()?;
        let segments = header.program_headers(endian, data)?;
        let sections = header.sections(endian, data)?;
        let symbols = sections.symbols(endian, data, elf::SHT_SYMTAB)?;
        // TODO: get dynamic symbols from DT_SYMTAB if there are no sections
        let dynamic_symbols = sections.symbols(endian, data, elf::SHT_DYNSYM)?;
        // The API we provide requires a mapping from section to relocations, so build it now.
        let relocations = sections.relocation_sections(endian, symbols.section())?;

        Ok(ElfFile {
            endian,
            data,
            header,
            segments,
            sections,
            relocations,
            symbols,
            dynamic_symbols,
        })
    }

    /// Returns the endianness.
    pub fn endian(&self) -> Elf::Endian {
        self.endian
    }

    /// Returns the raw data.
    pub fn data(&self) -> R {
        self.data
    }

    /// Returns the raw ELF file header.
    #[deprecated(note = "Use `elf_header` instead")]
    pub fn raw_header(&self) -> &'data Elf {
        self.header
    }

    /// Returns the raw ELF segments.
    #[deprecated(note = "Use `elf_program_headers` instead")]
    pub fn raw_segments(&self) -> &'data [Elf::ProgramHeader] {
        self.segments
    }

    /// Get the raw ELF file header.
    pub fn elf_header(&self) -> &'data Elf {
        self.header
    }

    /// Get the raw ELF program headers.
    ///
    /// Returns an empty slice if the file has no program headers.
    pub fn elf_program_headers(&self) -> &'data [Elf::ProgramHeader] {
        self.segments
    }

    /// Get the ELF section table.
    ///
    /// Returns an empty section table if the file has no section headers.
    pub fn elf_section_table(&self) -> &SectionTable<'data, Elf, R> {
        &self.sections
    }

    /// Get the ELF symbol table.
    ///
    /// Returns an empty symbol table if the file has no symbol table.
    pub fn elf_symbol_table(&self) -> &SymbolTable<'data, Elf, R> {
        &self.symbols
    }

    /// Get the ELF dynamic symbol table.
    ///
    /// Returns an empty symbol table if the file has no dynamic symbol table.
    pub fn elf_dynamic_symbol_table(&self) -> &SymbolTable<'data, Elf, R> {
        &self.dynamic_symbols
    }

    /// Get a mapping for linked relocation sections.
    pub fn elf_relocation_sections(&self) -> &RelocationSections {
        &self.relocations
    }

    fn raw_section_by_name<'file>(
        &'file self,
        section_name: &[u8],
    ) -> Option<ElfSection<'data, 'file, Elf, R>> {
        self.sections
            .section_by_name(self.endian, section_name)
            .map(|(index, section)| ElfSection {
                file: self,
                index,
                section,
            })
    }

    #[cfg(feature = "compression")]
    fn zdebug_section_by_name<'file>(
        &'file self,
        section_name: &[u8],
    ) -> Option<ElfSection<'data, 'file, Elf, R>> {
        if !section_name.starts_with(b".debug_") {
            return None;
        }
        let mut name = Vec::with_capacity(section_name.len() + 1);
        name.extend_from_slice(b".zdebug_");
        name.extend_from_slice(§ion_name[7..]);
        self.raw_section_by_name(&name)
    }

    #[cfg(not(feature = "compression"))]
    fn zdebug_section_by_name<'file>(
        &'file self,
        _section_name: &[u8],
    ) -> Option<ElfSection<'data, 'file, Elf, R>> {
        None
    }
}

impl<'data, Elf, R> read::private::Sealed for ElfFile<'data, Elf, R>
where
    Elf: FileHeader,
    R: ReadRef<'data>,
{
}

impl<'data, Elf, R> Object<'data> for ElfFile<'data, Elf, R>
where
    Elf: FileHeader,
    R: ReadRef<'data>,
{
    type Segment<'file> = ElfSegment<'data, 'file, Elf, R> where Self: 'file, 'data: 'file;
    type SegmentIterator<'file> = ElfSegmentIterator<'data, 'file, Elf, R> where Self: 'file, 'data: 'file;
    type Section<'file> = ElfSection<'data, 'file, Elf, R> where Self: 'file, 'data: 'file;
    type SectionIterator<'file> = ElfSectionIterator<'data, 'file, Elf, R> where Self: 'file, 'data: 'file;
    type Comdat<'file> = ElfComdat<'data, 'file, Elf, R> where Self: 'file, 'data: 'file;
    type ComdatIterator<'file> = ElfComdatIterator<'data, 'file, Elf, R> where Self: 'file, 'data: 'file;
    type Symbol<'file> = ElfSymbol<'data, 'file, Elf, R> where Self: 'file, 'data: 'file;
    type SymbolIterator<'file> = ElfSymbolIterator<'data, 'file, Elf, R> where Self: 'file, 'data: 'file;
    type SymbolTable<'file> = ElfSymbolTable<'data, 'file, Elf, R> where Self: 'file, 'data: 'file;
    type DynamicRelocationIterator<'file> = ElfDynamicRelocationIterator<'data, 'file, Elf, R> where Self: 'file, 'data: 'file;

    fn architecture(&self) -> Architecture {
        match (
            self.header.e_machine(self.endian),
            self.header.is_class_64(),
        ) {
            (elf::EM_AARCH64, true) => Architecture::Aarch64,
            (elf::EM_AARCH64, false) => Architecture::Aarch64_Ilp32,
            (elf::EM_ARM, _) => Architecture::Arm,
            (elf::EM_AVR, _) => Architecture::Avr,
            (elf::EM_BPF, _) => Architecture::Bpf,
            (elf::EM_CSKY, _) => Architecture::Csky,
            (elf::EM_386, _) => Architecture::I386,
            (elf::EM_X86_64, false) => Architecture::X86_64_X32,
            (elf::EM_X86_64, true) => Architecture::X86_64,
            (elf::EM_HEXAGON, _) => Architecture::Hexagon,
            (elf::EM_LOONGARCH, true) => Architecture::LoongArch64,
            (elf::EM_MIPS, false) => Architecture::Mips,
            (elf::EM_MIPS, true) => Architecture::Mips64,
            (elf::EM_MSP430, _) => Architecture::Msp430,
            (elf::EM_PPC, _) => Architecture::PowerPc,
            (elf::EM_PPC64, _) => Architecture::PowerPc64,
            (elf::EM_RISCV, false) => Architecture::Riscv32,
            (elf::EM_RISCV, true) => Architecture::Riscv64,
            // This is either s390 or s390x, depending on the ELF class.
            // We only support the 64-bit variant s390x here.
            (elf::EM_S390, true) => Architecture::S390x,
            (elf::EM_SBF, _) => Architecture::Sbf,
            (elf::EM_SHARC, false) => Architecture::Sharc,
            (elf::EM_SPARC, false) => Architecture::Sparc,
            (elf::EM_SPARC32PLUS, false) => Architecture::Sparc32Plus,
            (elf::EM_SPARCV9, true) => Architecture::Sparc64,
            (elf::EM_XTENSA, false) => Architecture::Xtensa,
            _ => Architecture::Unknown,
        }
    }

    #[inline]
    fn is_little_endian(&self) -> bool {
        self.header.is_little_endian()
    }

    #[inline]
    fn is_64(&self) -> bool {
        self.header.is_class_64()
    }

    fn kind(&self) -> ObjectKind {
        match self.header.e_type(self.endian) {
            elf::ET_REL => ObjectKind::Relocatable,
            elf::ET_EXEC => ObjectKind::Executable,
            // TODO: check for `DF_1_PIE`?
            elf::ET_DYN => ObjectKind::Dynamic,
            elf::ET_CORE => ObjectKind::Core,
            _ => ObjectKind::Unknown,
        }
    }

    fn segments(&self) -> ElfSegmentIterator<'data, '_, Elf, R> {
        ElfSegmentIterator {
            file: self,
            iter: self.segments.iter(),
        }
    }

    fn section_by_name_bytes<'file>(
        &'file self,
        section_name: &[u8],
    ) -> Option<ElfSection<'data, 'file, Elf, R>> {
        self.raw_section_by_name(section_name)
            .or_else(|| self.zdebug_section_by_name(section_name))
    }

    fn section_by_index(&self, index: SectionIndex) -> read::Result<ElfSection<'data, '_, Elf, R>> {
        let section = self.sections.section(index)?;
        Ok(ElfSection {
            file: self,
            index,
            section,
        })
    }

    fn sections(&self) -> ElfSectionIterator<'data, '_, Elf, R> {
        ElfSectionIterator::new(self)
    }

    fn comdats(&self) -> ElfComdatIterator<'data, '_, Elf, R> {
        ElfComdatIterator::new(self)
    }

    fn symbol_by_index(&self, index: SymbolIndex) -> read::Result<ElfSymbol<'data, '_, Elf, R>> {
        let symbol = self.symbols.symbol(index)?;
        Ok(ElfSymbol {
            endian: self.endian,
            symbols: &self.symbols,
            index,
            symbol,
        })
    }

    fn symbols(&self) -> ElfSymbolIterator<'data, '_, Elf, R> {
        ElfSymbolIterator::new(self.endian, &self.symbols)
    }

    fn symbol_table(&self) -> Option<ElfSymbolTable<'data, '_, Elf, R>> {
        if self.symbols.is_empty() {
            return None;
        }
        Some(ElfSymbolTable {
            endian: self.endian,
            symbols: &self.symbols,
        })
    }

    fn dynamic_symbols(&self) -> ElfSymbolIterator<'data, '_, Elf, R> {
        ElfSymbolIterator::new(self.endian, &self.dynamic_symbols)
    }

    fn dynamic_symbol_table(&self) -> Option<ElfSymbolTable<'data, '_, Elf, R>> {
        if self.dynamic_symbols.is_empty() {
            return None;
        }
        Some(ElfSymbolTable {
            endian: self.endian,
            symbols: &self.dynamic_symbols,
        })
    }

    fn dynamic_relocations<'file>(
        &'file self,
    ) -> Option<ElfDynamicRelocationIterator<'data, 'file, Elf, R>> {
        Some(ElfDynamicRelocationIterator {
            section_index: SectionIndex(1),
            file: self,
            relocations: None,
        })
    }

    fn imports(&self) -> read::Result<Vec<Import<'data>>> {
        let versions = self.sections.versions(self.endian, self.data)?;

        let mut imports = Vec::new();
        for (index, symbol) in self.dynamic_symbols.enumerate() {
            if symbol.is_undefined(self.endian) {
                let name = symbol.name(self.endian, self.dynamic_symbols.strings())?;
                if !name.is_empty() {
                    let library = if let Some(svt) = versions.as_ref() {
                        let vi = svt.version_index(self.endian, index);
                        svt.version(vi)?.and_then(|v| v.file())
                    } else {
                        None
                    }
                    .unwrap_or(&[]);
                    imports.push(Import {
                        name: ByteString(name),
                        library: ByteString(library),
                    });
                }
            }
        }
        Ok(imports)
    }

    fn exports(&self) -> read::Result<Vec<Export<'data>>> {
        let mut exports = Vec::new();
        for symbol in self.dynamic_symbols.iter() {
            if symbol.is_definition(self.endian) {
                let name = symbol.name(self.endian, self.dynamic_symbols.strings())?;
                let address = symbol.st_value(self.endian).into();
                exports.push(Export {
                    name: ByteString(name),
                    address,
                });
            }
        }
        Ok(exports)
    }

    fn has_debug_symbols(&self) -> bool {
        for section in self.sections.iter() {
            if let Ok(name) = self.sections.section_name(self.endian, section) {
                if name == b".debug_info" || name == b".zdebug_info" {
                    return true;
                }
            }
        }
        false
    }

    fn build_id(&self) -> read::Result<Option<&'data [u8]>> {
        let endian = self.endian;
        // Use section headers if present, otherwise use program headers.
        if !self.sections.is_empty() {
            for section in self.sections.iter() {
                if let Some(mut notes) = section.notes(endian, self.data)? {
                    while let Some(note) = notes.next()? {
                        if note.name() == elf::ELF_NOTE_GNU
                            && note.n_type(endian) == elf::NT_GNU_BUILD_ID
                        {
                            return Ok(Some(note.desc()));
                        }
                    }
                }
            }
        } else {
            for segment in self.segments {
                if let Some(mut notes) = segment.notes(endian, self.data)? {
                    while let Some(note) = notes.next()? {
                        if note.name() == elf::ELF_NOTE_GNU
                            && note.n_type(endian) == elf::NT_GNU_BUILD_ID
                        {
                            return Ok(Some(note.desc()));
                        }
                    }
                }
            }
        }
        Ok(None)
    }

    fn gnu_debuglink(&self) -> read::Result<Option<(&'data [u8], u32)>> {
        let section = match self.raw_section_by_name(b".gnu_debuglink") {
            Some(section) => section,
            None => return Ok(None),
        };
        let data = section
            .section
            .data(self.endian, self.data)
            .read_error("Invalid ELF .gnu_debuglink section offset or size")
            .map(Bytes)?;
        let filename = data
            .read_string_at(0)
            .read_error("Missing ELF .gnu_debuglink filename")?;
        let crc_offset = util::align(filename.len() + 1, 4);
        let crc = data
            .read_at::<U32<_>>(crc_offset)
            .read_error("Missing ELF .gnu_debuglink crc")?
            .get(self.endian);
        Ok(Some((filename, crc)))
    }

    fn gnu_debugaltlink(&self) -> read::Result<Option<(&'data [u8], &'data [u8])>> {
        let section = match self.raw_section_by_name(b".gnu_debugaltlink") {
            Some(section) => section,
            None => return Ok(None),
        };
        let mut data = section
            .section
            .data(self.endian, self.data)
            .read_error("Invalid ELF .gnu_debugaltlink section offset or size")
            .map(Bytes)?;
        let filename = data
            .read_string()
            .read_error("Missing ELF .gnu_debugaltlink filename")?;
        let build_id = data.0;
        Ok(Some((filename, build_id)))
    }

    fn relative_address_base(&self) -> u64 {
        0
    }

    fn entry(&self) -> u64 {
        self.header.e_entry(self.endian).into()
    }

    fn flags(&self) -> FileFlags {
        FileFlags::Elf {
            os_abi: self.header.e_ident().os_abi,
            abi_version: self.header.e_ident().abi_version,
            e_flags: self.header.e_flags(self.endian),
        }
    }
}

/// A trait for generic access to [`elf::FileHeader32`] and [`elf::FileHeader64`].
#[allow(missing_docs)]
pub trait FileHeader: Debug + Pod {
    // Ideally this would be a `u64: From<Word>`, but can't express that.
    type Word: Into<u64>;
    type Sword: Into<i64>;
    type Endian: endian::Endian;
    type ProgramHeader: ProgramHeader<Elf = Self, Endian = Self::Endian, Word = Self::Word>;
    type SectionHeader: SectionHeader<Elf = Self, Endian = Self::Endian, Word = Self::Word>;
    type CompressionHeader: CompressionHeader<Endian = Self::Endian, Word = Self::Word>;
    type NoteHeader: NoteHeader<Endian = Self::Endian>;
    type Dyn: Dyn<Endian = Self::Endian, Word = Self::Word>;
    type Sym: Sym<Endian = Self::Endian, Word = Self::Word>;
    type Rel: Rel<Endian = Self::Endian, Word = Self::Word>;
    type Rela: Rela<Endian = Self::Endian, Word = Self::Word> + From<Self::Rel>;

    /// Return true if this type is a 64-bit header.
    ///
    /// This is a property of the type, not a value in the header data.
    fn is_type_64(&self) -> bool;

    /// Return true if this type is a 64-bit header.
    ///
    /// This is a property of the type, not a value in the header data.
    ///
    /// This is the same as [`Self::is_type_64`], but is non-dispatchable.
    fn is_type_64_sized() -> bool
    where
        Self: Sized;

    fn e_ident(&self) -> &elf::Ident;
    fn e_type(&self, endian: Self::Endian) -> u16;
    fn e_machine(&self, endian: Self::Endian) -> u16;
    fn e_version(&self, endian: Self::Endian) -> u32;
    fn e_entry(&self, endian: Self::Endian) -> Self::Word;
    fn e_phoff(&self, endian: Self::Endian) -> Self::Word;
    fn e_shoff(&self, endian: Self::Endian) -> Self::Word;
    fn e_flags(&self, endian: Self::Endian) -> u32;
    fn e_ehsize(&self, endian: Self::Endian) -> u16;
    fn e_phentsize(&self, endian: Self::Endian) -> u16;
    fn e_phnum(&self, endian: Self::Endian) -> u16;
    fn e_shentsize(&self, endian: Self::Endian) -> u16;
    fn e_shnum(&self, endian: Self::Endian) -> u16;
    fn e_shstrndx(&self, endian: Self::Endian) -> u16;

    // Provided methods.

    /// Read the file header.
    ///
    /// Also checks that the ident field in the file header is a supported format.
    fn parse<'data, R: ReadRef<'data>>(data: R) -> read::Result<&'data Self> {
        let header = data
            .read_at::<Self>(0)
            .read_error("Invalid ELF header size or alignment")?;
        if !header.is_supported() {
            return Err(Error("Unsupported ELF header"));
        }
        // TODO: Check self.e_ehsize?
        Ok(header)
    }

    /// Check that the ident field in the file header is a supported format.
    ///
    /// This checks the magic number, version, class, and endianness.
    fn is_supported(&self) -> bool {
        let ident = self.e_ident();
        // TODO: Check self.e_version too? Requires endian though.
        ident.magic == elf::ELFMAG
            && (self.is_type_64() || self.is_class_32())
            && (!self.is_type_64() || self.is_class_64())
            && (self.is_little_endian() || self.is_big_endian())
            && ident.version == elf::EV_CURRENT
    }

    fn is_class_32(&self) -> bool {
        self.e_ident().class == elf::ELFCLASS32
    }

    fn is_class_64(&self) -> bool {
        self.e_ident().class == elf::ELFCLASS64
    }

    fn is_little_endian(&self) -> bool {
        self.e_ident().data == elf::ELFDATA2LSB
    }

    fn is_big_endian(&self) -> bool {
        self.e_ident().data == elf::ELFDATA2MSB
    }

    fn endian(&self) -> read::Result<Self::Endian> {
        Self::Endian::from_big_endian(self.is_big_endian()).read_error("Unsupported ELF endian")
    }

    /// Return the first section header, if present.
    ///
    /// Section 0 is a special case because getting the section headers normally
    /// requires `shnum`, but `shnum` may be in the first section header.
    fn section_0<'data, R: ReadRef<'data>>(
        &self,
        endian: Self::Endian,
        data: R,
    ) -> read::Result<Option<&'data Self::SectionHeader>> {
        let shoff: u64 = self.e_shoff(endian).into();
        if shoff == 0 {
            // No section headers is ok.
            return Ok(None);
        }
        let shentsize = usize::from(self.e_shentsize(endian));
        if shentsize != mem::size_of::<Self::SectionHeader>() {
            // Section header size must match.
            return Err(Error("Invalid ELF section header entry size"));
        }
        data.read_at(shoff)
            .map(Some)
            .read_error("Invalid ELF section header offset or size")
    }

    /// Return the `e_phnum` field of the header. Handles extended values.
    ///
    /// Returns `Err` for invalid values.
    fn phnum<'data, R: ReadRef<'data>>(
        &self,
        endian: Self::Endian,
        data: R,
    ) -> read::Result<usize> {
        let e_phnum = self.e_phnum(endian);
        if e_phnum < elf::PN_XNUM {
            Ok(e_phnum as usize)
        } else if let Some(section_0) = self.section_0(endian, data)? {
            Ok(section_0.sh_info(endian) as usize)
        } else {
            // Section 0 must exist if e_phnum overflows.
            Err(Error("Missing ELF section headers for e_phnum overflow"))
        }
    }

    /// Return the `e_shnum` field of the header. Handles extended values.
    ///
    /// Returns `Err` for invalid values.
    fn shnum<'data, R: ReadRef<'data>>(
        &self,
        endian: Self::Endian,
        data: R,
    ) -> read::Result<usize> {
        let e_shnum = self.e_shnum(endian);
        if e_shnum > 0 {
            Ok(e_shnum as usize)
        } else if let Some(section_0) = self.section_0(endian, data)? {
            section_0
                .sh_size(endian)
                .into()
                .try_into()
                .ok()
                .read_error("Invalid ELF extended e_shnum")
        } else {
            // No section headers is ok.
            Ok(0)
        }
    }

    /// Return the `e_shstrndx` field of the header. Handles extended values.
    ///
    /// Returns `Err` for invalid values (including if the index is 0).
    fn shstrndx<'data, R: ReadRef<'data>>(
        &self,
        endian: Self::Endian,
        data: R,
    ) -> read::Result<u32> {
        let e_shstrndx = self.e_shstrndx(endian);
        let index = if e_shstrndx != elf::SHN_XINDEX {
            e_shstrndx.into()
        } else if let Some(section_0) = self.section_0(endian, data)? {
            section_0.sh_link(endian)
        } else {
            // Section 0 must exist if we're trying to read e_shstrndx.
            return Err(Error("Missing ELF section headers for e_shstrndx overflow"));
        };
        if index == 0 {
            return Err(Error("Missing ELF e_shstrndx"));
        }
        Ok(index)
    }

    /// Return the slice of program headers.
    ///
    /// Returns `Ok(&[])` if there are no program headers.
    /// Returns `Err` for invalid values.
    fn program_headers<'data, R: ReadRef<'data>>(
        &self,
        endian: Self::Endian,
        data: R,
    ) -> read::Result<&'data [Self::ProgramHeader]> {
        let phoff: u64 = self.e_phoff(endian).into();
        if phoff == 0 {
            // No program headers is ok.
            return Ok(&[]);
        }
        let phnum = self.phnum(endian, data)?;
        if phnum == 0 {
            // No program headers is ok.
            return Ok(&[]);
        }
        let phentsize = self.e_phentsize(endian) as usize;
        if phentsize != mem::size_of::<Self::ProgramHeader>() {
            // Program header size must match.
            return Err(Error("Invalid ELF program header entry size"));
        }
        data.read_slice_at(phoff, phnum)
            .read_error("Invalid ELF program header size or alignment")
    }

    /// Return the slice of section headers.
    ///
    /// Returns `Ok(&[])` if there are no section headers.
    /// Returns `Err` for invalid values.
    fn section_headers<'data, R: ReadRef<'data>>(
        &self,
        endian: Self::Endian,
        data: R,
    ) -> read::Result<&'data [Self::SectionHeader]> {
        let shoff: u64 = self.e_shoff(endian).into();
        if shoff == 0 {
            // No section headers is ok.
            return Ok(&[]);
        }
        let shnum = self.shnum(endian, data)?;
        if shnum == 0 {
            // No section headers is ok.
            return Ok(&[]);
        }
        let shentsize = usize::from(self.e_shentsize(endian));
        if shentsize != mem::size_of::<Self::SectionHeader>() {
            // Section header size must match.
            return Err(Error("Invalid ELF section header entry size"));
        }
        data.read_slice_at(shoff, shnum)
            .read_error("Invalid ELF section header offset/size/alignment")
    }

    /// Get the section index of the section header string table.
    ///
    /// Returns `Err` for invalid values (including if the index is 0).
    fn section_strings_index<'data, R: ReadRef<'data>>(
        &self,
        endian: Self::Endian,
        data: R,
    ) -> read::Result<SectionIndex> {
        self.shstrndx(endian, data)
            .map(|index| SectionIndex(index as usize))
    }

    /// Return the string table for the section headers.
    fn section_strings<'data, R: ReadRef<'data>>(
        &self,
        endian: Self::Endian,
        data: R,
        sections: &[Self::SectionHeader],
    ) -> read::Result<StringTable<'data, R>> {
        if sections.is_empty() {
            return Ok(StringTable::default());
        }
        let index = self.section_strings_index(endian, data)?;
        let shstrtab = sections.get(index.0).read_error("Invalid ELF e_shstrndx")?;
        let strings = if let Some((shstrtab_offset, shstrtab_size)) = shstrtab.file_range(endian) {
            let shstrtab_end = shstrtab_offset
                .checked_add(shstrtab_size)
                .read_error("Invalid ELF shstrtab size")?;
            StringTable::new(data, shstrtab_offset, shstrtab_end)
        } else {
            StringTable::default()
        };
        Ok(strings)
    }

    /// Return the section table.
    fn sections<'data, R: ReadRef<'data>>(
        &self,
        endian: Self::Endian,
        data: R,
    ) -> read::Result<SectionTable<'data, Self, R>> {
        let sections = self.section_headers(endian, data)?;
        let strings = self.section_strings(endian, data, sections)?;
        Ok(SectionTable::new(sections, strings))
    }

    /// Returns whether this is a mips64el elf file.
    fn is_mips64el(&self, endian: Self::Endian) -> bool {
        self.is_class_64() && self.is_little_endian() && self.e_machine(endian) == elf::EM_MIPS
    }
}

impl<Endian: endian::Endian> FileHeader for elf::FileHeader32<Endian> {
    type Word = u32;
    type Sword = i32;
    type Endian = Endian;
    type ProgramHeader = elf::ProgramHeader32<Endian>;
    type SectionHeader = elf::SectionHeader32<Endian>;
    type CompressionHeader = elf::CompressionHeader32<Endian>;
    type NoteHeader = elf::NoteHeader32<Endian>;
    type Dyn = elf::Dyn32<Endian>;
    type Sym = elf::Sym32<Endian>;
    type Rel = elf::Rel32<Endian>;
    type Rela = elf::Rela32<Endian>;

    #[inline]
    fn is_type_64(&self) -> bool {
        false
    }

    #[inline]
    fn is_type_64_sized() -> bool
    where
        Self: Sized,
    {
        false
    }

    #[inline]
    fn e_ident(&self) -> &elf::Ident {
        &self.e_ident
    }

    #[inline]
    fn e_type(&self, endian: Self::Endian) -> u16 {
        self.e_type.get(endian)
    }

    #[inline]
    fn e_machine(&self, endian: Self::Endian) -> u16 {
        self.e_machine.get(endian)
    }

    #[inline]
    fn e_version(&self, endian: Self::Endian) -> u32 {
        self.e_version.get(endian)
    }

    #[inline]
    fn e_entry(&self, endian: Self::Endian) -> Self::Word {
        self.e_entry.get(endian)
    }

    #[inline]
    fn e_phoff(&self, endian: Self::Endian) -> Self::Word {
        self.e_phoff.get(endian)
    }

    #[inline]
    fn e_shoff(&self, endian: Self::Endian) -> Self::Word {
        self.e_shoff.get(endian)
    }

    #[inline]
    fn e_flags(&self, endian: Self::Endian) -> u32 {
        self.e_flags.get(endian)
    }

    #[inline]
    fn e_ehsize(&self, endian: Self::Endian) -> u16 {
        self.e_ehsize.get(endian)
    }

    #[inline]
    fn e_phentsize(&self, endian: Self::Endian) -> u16 {
        self.e_phentsize.get(endian)
    }

    #[inline]
    fn e_phnum(&self, endian: Self::Endian) -> u16 {
        self.e_phnum.get(endian)
    }

    #[inline]
    fn e_shentsize(&self, endian: Self::Endian) -> u16 {
        self.e_shentsize.get(endian)
    }

    #[inline]
    fn e_shnum(&self, endian: Self::Endian) -> u16 {
        self.e_shnum.get(endian)
    }

    #[inline]
    fn e_shstrndx(&self, endian: Self::Endian) -> u16 {
        self.e_shstrndx.get(endian)
    }
}

impl<Endian: endian::Endian> FileHeader for elf::FileHeader64<Endian> {
    type Word = u64;
    type Sword = i64;
    type Endian = Endian;
    type ProgramHeader = elf::ProgramHeader64<Endian>;
    type SectionHeader = elf::SectionHeader64<Endian>;
    type CompressionHeader = elf::CompressionHeader64<Endian>;
    type NoteHeader = elf::NoteHeader32<Endian>;
    type Dyn = elf::Dyn64<Endian>;
    type Sym = elf::Sym64<Endian>;
    type Rel = elf::Rel64<Endian>;
    type Rela = elf::Rela64<Endian>;

    #[inline]
    fn is_type_64(&self) -> bool {
        true
    }

    #[inline]
    fn is_type_64_sized() -> bool
    where
        Self: Sized,
    {
        true
    }

    #[inline]
    fn e_ident(&self) -> &elf::Ident {
        &self.e_ident
    }

    #[inline]
    fn e_type(&self, endian: Self::Endian) -> u16 {
        self.e_type.get(endian)
    }

    #[inline]
    fn e_machine(&self, endian: Self::Endian) -> u16 {
        self.e_machine.get(endian)
    }

    #[inline]
    fn e_version(&self, endian: Self::Endian) -> u32 {
        self.e_version.get(endian)
    }

    #[inline]
    fn e_entry(&self, endian: Self::Endian) -> Self::Word {
        self.e_entry.get(endian)
    }

    #[inline]
    fn e_phoff(&self, endian: Self::Endian) -> Self::Word {
        self.e_phoff.get(endian)
    }

    #[inline]
    fn e_shoff(&self, endian: Self::Endian) -> Self::Word {
        self.e_shoff.get(endian)
    }

    #[inline]
    fn e_flags(&self, endian: Self::Endian) -> u32 {
        self.e_flags.get(endian)
    }

    #[inline]
    fn e_ehsize(&self, endian: Self::Endian) -> u16 {
        self.e_ehsize.get(endian)
    }

    #[inline]
    fn e_phentsize(&self, endian: Self::Endian) -> u16 {
        self.e_phentsize.get(endian)
    }

    #[inline]
    fn e_phnum(&self, endian: Self::Endian) -> u16 {
        self.e_phnum.get(endian)
    }

    #[inline]
    fn e_shentsize(&self, endian: Self::Endian) -> u16 {
        self.e_shentsize.get(endian)
    }

    #[inline]
    fn e_shnum(&self, endian: Self::Endian) -> u16 {
        self.e_shnum.get(endian)
    }

    #[inline]
    fn e_shstrndx(&self, endian: Self::Endian) -> u16 {
        self.e_shstrndx.get(endian)
    }
}

[ Dauer der Verarbeitung: 0.30 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge