aboutsummaryrefslogtreecommitdiff
path: root/vendor/object/src/read/elf
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/object/src/read/elf')
-rw-r--r--vendor/object/src/read/elf/attributes.rs307
-rw-r--r--vendor/object/src/read/elf/comdat.rs162
-rw-r--r--vendor/object/src/read/elf/compression.rs56
-rw-r--r--vendor/object/src/read/elf/dynamic.rs117
-rw-r--r--vendor/object/src/read/elf/file.rs916
-rw-r--r--vendor/object/src/read/elf/hash.rs224
-rw-r--r--vendor/object/src/read/elf/mod.rs78
-rw-r--r--vendor/object/src/read/elf/note.rs271
-rw-r--r--vendor/object/src/read/elf/relocation.rs628
-rw-r--r--vendor/object/src/read/elf/section.rs1150
-rw-r--r--vendor/object/src/read/elf/segment.rs334
-rw-r--r--vendor/object/src/read/elf/symbol.rs595
-rw-r--r--vendor/object/src/read/elf/version.rs424
13 files changed, 0 insertions, 5262 deletions
diff --git a/vendor/object/src/read/elf/attributes.rs b/vendor/object/src/read/elf/attributes.rs
deleted file mode 100644
index bf6f35c..0000000
--- a/vendor/object/src/read/elf/attributes.rs
+++ /dev/null
@@ -1,307 +0,0 @@
-use core::convert::TryInto;
-
-use crate::elf;
-use crate::endian;
-use crate::read::{Bytes, Error, ReadError, Result};
-
-use super::FileHeader;
-
-/// An ELF attributes section.
-///
-/// This may be a GNU attributes section, or an architecture specific attributes section.
-///
-/// An attributes section contains a series of [`AttributesSubsection`].
-///
-/// Returned by [`SectionHeader::attributes`](super::SectionHeader::attributes)
-/// and [`SectionHeader::gnu_attributes`](super::SectionHeader::gnu_attributes).
-#[derive(Debug, Clone)]
-pub struct AttributesSection<'data, Elf: FileHeader> {
- endian: Elf::Endian,
- version: u8,
- data: Bytes<'data>,
-}
-
-impl<'data, Elf: FileHeader> AttributesSection<'data, Elf> {
- /// Parse an ELF attributes section given the section data.
- pub fn new(endian: Elf::Endian, data: &'data [u8]) -> Result<Self> {
- let mut data = Bytes(data);
-
- // Skip the version field that is one byte long.
- let version = *data
- .read::<u8>()
- .read_error("Invalid ELF attributes section offset or size")?;
-
- Ok(AttributesSection {
- endian,
- version,
- data,
- })
- }
-
- /// Return the version of the attributes section.
- pub fn version(&self) -> u8 {
- self.version
- }
-
- /// Return an iterator over the subsections.
- pub fn subsections(&self) -> Result<AttributesSubsectionIterator<'data, Elf>> {
- // There is currently only one format version.
- if self.version != b'A' {
- return Err(Error("Unsupported ELF attributes section version"));
- }
-
- Ok(AttributesSubsectionIterator {
- endian: self.endian,
- data: self.data,
- })
- }
-}
-
-/// An iterator for the subsections in an [`AttributesSection`].
-#[derive(Debug, Clone)]
-pub struct AttributesSubsectionIterator<'data, Elf: FileHeader> {
- endian: Elf::Endian,
- data: Bytes<'data>,
-}
-
-impl<'data, Elf: FileHeader> AttributesSubsectionIterator<'data, Elf> {
- /// Return the next subsection.
- pub fn next(&mut self) -> Result<Option<AttributesSubsection<'data, Elf>>> {
- if self.data.is_empty() {
- return Ok(None);
- }
-
- let result = self.parse();
- if result.is_err() {
- self.data = Bytes(&[]);
- }
- result
- }
-
- fn parse(&mut self) -> Result<Option<AttributesSubsection<'data, Elf>>> {
- // First read the subsection length.
- let mut data = self.data;
- let length = data
- .read::<endian::U32Bytes<Elf::Endian>>()
- .read_error("ELF attributes section is too short")?
- .get(self.endian);
-
- // Now read the entire subsection, updating self.data.
- let mut data = self
- .data
- .read_bytes(length as usize)
- .read_error("Invalid ELF attributes subsection length")?;
- // Skip the subsection length field.
- data.skip(4)
- .read_error("Invalid ELF attributes subsection length")?;
-
- let vendor = data
- .read_string()
- .read_error("Invalid ELF attributes vendor")?;
-
- Ok(Some(AttributesSubsection {
- endian: self.endian,
- length,
- vendor,
- data,
- }))
- }
-}
-
-/// A subsection in an [`AttributesSection`].
-///
-/// A subsection is identified by a vendor name. It contains a series of
-/// [`AttributesSubsubsection`].
-#[derive(Debug, Clone)]
-pub struct AttributesSubsection<'data, Elf: FileHeader> {
- endian: Elf::Endian,
- length: u32,
- vendor: &'data [u8],
- data: Bytes<'data>,
-}
-
-impl<'data, Elf: FileHeader> AttributesSubsection<'data, Elf> {
- /// Return the length of the attributes subsection.
- pub fn length(&self) -> u32 {
- self.length
- }
-
- /// Return the vendor name of the attributes subsection.
- pub fn vendor(&self) -> &'data [u8] {
- self.vendor
- }
-
- /// Return an iterator over the sub-subsections.
- pub fn subsubsections(&self) -> AttributesSubsubsectionIterator<'data, Elf> {
- AttributesSubsubsectionIterator {
- endian: self.endian,
- data: self.data,
- }
- }
-}
-
-/// An iterator for the sub-subsections in an [`AttributesSubsection`].
-#[derive(Debug, Clone)]
-pub struct AttributesSubsubsectionIterator<'data, Elf: FileHeader> {
- endian: Elf::Endian,
- data: Bytes<'data>,
-}
-
-impl<'data, Elf: FileHeader> AttributesSubsubsectionIterator<'data, Elf> {
- /// Return the next sub-subsection.
- pub fn next(&mut self) -> Result<Option<AttributesSubsubsection<'data>>> {
- if self.data.is_empty() {
- return Ok(None);
- }
-
- let result = self.parse();
- if result.is_err() {
- self.data = Bytes(&[]);
- }
- result
- }
-
- fn parse(&mut self) -> Result<Option<AttributesSubsubsection<'data>>> {
- // The format of a sub-section looks like this:
- //
- // <file-tag> <size> <attribute>*
- // | <section-tag> <size> <section-number>* 0 <attribute>*
- // | <symbol-tag> <size> <symbol-number>* 0 <attribute>*
- let mut data = self.data;
- let tag = *data
- .read::<u8>()
- .read_error("ELF attributes subsection is too short")?;
- let length = data
- .read::<endian::U32Bytes<Elf::Endian>>()
- .read_error("ELF attributes subsection is too short")?
- .get(self.endian);
-
- // Now read the entire sub-subsection, updating self.data.
- let mut data = self
- .data
- .read_bytes(length as usize)
- .read_error("Invalid ELF attributes sub-subsection length")?;
- // Skip the tag and sub-subsection size field.
- data.skip(1 + 4)
- .read_error("Invalid ELF attributes sub-subsection length")?;
-
- let indices = if tag == elf::Tag_Section || tag == elf::Tag_Symbol {
- data.read_string()
- .map(Bytes)
- .read_error("Missing ELF attributes sub-subsection indices")?
- } else if tag == elf::Tag_File {
- Bytes(&[])
- } else {
- return Err(Error("Unimplemented ELF attributes sub-subsection tag"));
- };
-
- Ok(Some(AttributesSubsubsection {
- tag,
- length,
- indices,
- data,
- }))
- }
-}
-
-/// A sub-subsection in an [`AttributesSubsection`].
-///
-/// A sub-subsection is identified by a tag. It contains an optional series of indices,
-/// followed by a series of attributes.
-#[derive(Debug, Clone)]
-pub struct AttributesSubsubsection<'data> {
- tag: u8,
- length: u32,
- indices: Bytes<'data>,
- data: Bytes<'data>,
-}
-
-impl<'data> AttributesSubsubsection<'data> {
- /// Return the tag of the attributes sub-subsection.
- pub fn tag(&self) -> u8 {
- self.tag
- }
-
- /// Return the length of the attributes sub-subsection.
- pub fn length(&self) -> u32 {
- self.length
- }
-
- /// Return the data containing the indices.
- pub fn indices_data(&self) -> &'data [u8] {
- self.indices.0
- }
-
- /// Return the indices.
- ///
- /// This will be section indices if the tag is `Tag_Section`,
- /// or symbol indices if the tag is `Tag_Symbol`,
- /// and otherwise it will be empty.
- pub fn indices(&self) -> AttributeIndexIterator<'data> {
- AttributeIndexIterator { data: self.indices }
- }
-
- /// Return the data containing the attributes.
- pub fn attributes_data(&self) -> &'data [u8] {
- self.data.0
- }
-
- /// Return a parser for the data containing the attributes.
- pub fn attributes(&self) -> AttributeReader<'data> {
- AttributeReader { data: self.data }
- }
-}
-
-/// An iterator over the indices in an [`AttributesSubsubsection`].
-#[derive(Debug, Clone)]
-pub struct AttributeIndexIterator<'data> {
- data: Bytes<'data>,
-}
-
-impl<'data> AttributeIndexIterator<'data> {
- /// Parse the next index.
- pub fn next(&mut self) -> Result<Option<u32>> {
- if self.data.is_empty() {
- return Ok(None);
- }
- let err = "Invalid ELF attribute index";
- self.data
- .read_uleb128()
- .read_error(err)?
- .try_into()
- .map_err(|_| ())
- .read_error(err)
- .map(Some)
- }
-}
-
-/// A parser for the attributes in an [`AttributesSubsubsection`].
-///
-/// The parser relies on the caller to know the format of the data for each attribute tag.
-#[derive(Debug, Clone)]
-pub struct AttributeReader<'data> {
- data: Bytes<'data>,
-}
-
-impl<'data> AttributeReader<'data> {
- /// Parse a tag.
- pub fn read_tag(&mut self) -> Result<Option<u64>> {
- if self.data.is_empty() {
- return Ok(None);
- }
- let err = "Invalid ELF attribute tag";
- self.data.read_uleb128().read_error(err).map(Some)
- }
-
- /// Parse an integer value.
- pub fn read_integer(&mut self) -> Result<u64> {
- let err = "Invalid ELF attribute integer value";
- self.data.read_uleb128().read_error(err)
- }
-
- /// Parse a string value.
- pub fn read_string(&mut self) -> Result<&'data [u8]> {
- let err = "Invalid ELF attribute string value";
- self.data.read_string().read_error(err)
- }
-}
diff --git a/vendor/object/src/read/elf/comdat.rs b/vendor/object/src/read/elf/comdat.rs
deleted file mode 100644
index 882d253..0000000
--- a/vendor/object/src/read/elf/comdat.rs
+++ /dev/null
@@ -1,162 +0,0 @@
-use core::fmt::Debug;
-use core::{iter, slice, str};
-
-use crate::elf;
-use crate::endian::{Endianness, U32Bytes};
-use crate::read::{self, ComdatKind, ObjectComdat, ReadError, ReadRef, SectionIndex, SymbolIndex};
-
-use super::{ElfFile, FileHeader, SectionHeader, Sym};
-
-/// An iterator for the COMDAT section groups in an [`ElfFile32`](super::ElfFile32).
-pub type ElfComdatIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
- ElfComdatIterator<'data, 'file, elf::FileHeader32<Endian>, R>;
-/// An iterator for the COMDAT section groups in an [`ElfFile64`](super::ElfFile64).
-pub type ElfComdatIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
- ElfComdatIterator<'data, 'file, elf::FileHeader64<Endian>, R>;
-
-/// An iterator for the COMDAT section groups in an [`ElfFile`].
-#[derive(Debug)]
-pub struct ElfComdatIterator<'data, 'file, Elf, R = &'data [u8]>
-where
- Elf: FileHeader,
- R: ReadRef<'data>,
-{
- pub(super) file: &'file ElfFile<'data, Elf, R>,
- pub(super) iter: iter::Enumerate<slice::Iter<'data, Elf::SectionHeader>>,
-}
-
-impl<'data, 'file, Elf, R> Iterator for ElfComdatIterator<'data, 'file, Elf, R>
-where
- Elf: FileHeader,
- R: ReadRef<'data>,
-{
- type Item = ElfComdat<'data, 'file, Elf, R>;
-
- fn next(&mut self) -> Option<Self::Item> {
- for (_index, section) in self.iter.by_ref() {
- if let Some(comdat) = ElfComdat::parse(self.file, section) {
- return Some(comdat);
- }
- }
- None
- }
-}
-
-/// A COMDAT section group in an [`ElfFile32`](super::ElfFile32).
-pub type ElfComdat32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
- ElfComdat<'data, 'file, elf::FileHeader32<Endian>, R>;
-/// A COMDAT section group in an [`ElfFile64`](super::ElfFile64).
-pub type ElfComdat64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
- ElfComdat<'data, 'file, elf::FileHeader64<Endian>, R>;
-
-/// A COMDAT section group in an [`ElfFile`].
-///
-/// Most functionality is provided by the [`ObjectComdat`] trait implementation.
-#[derive(Debug)]
-pub struct ElfComdat<'data, 'file, Elf, R = &'data [u8]>
-where
- Elf: FileHeader,
- R: ReadRef<'data>,
-{
- file: &'file ElfFile<'data, Elf, R>,
- section: &'data Elf::SectionHeader,
- sections: &'data [U32Bytes<Elf::Endian>],
-}
-
-impl<'data, 'file, Elf, R> ElfComdat<'data, 'file, Elf, R>
-where
- Elf: FileHeader,
- R: ReadRef<'data>,
-{
- fn parse(
- file: &'file ElfFile<'data, Elf, R>,
- section: &'data Elf::SectionHeader,
- ) -> Option<ElfComdat<'data, 'file, Elf, R>> {
- let (flag, sections) = section.group(file.endian, file.data).ok()??;
- if flag != elf::GRP_COMDAT {
- return None;
- }
- Some(ElfComdat {
- file,
- section,
- sections,
- })
- }
-}
-
-impl<'data, 'file, Elf, R> read::private::Sealed for ElfComdat<'data, 'file, Elf, R>
-where
- Elf: FileHeader,
- R: ReadRef<'data>,
-{
-}
-
-impl<'data, 'file, Elf, R> ObjectComdat<'data> for ElfComdat<'data, 'file, Elf, R>
-where
- Elf: FileHeader,
- R: ReadRef<'data>,
-{
- type SectionIterator = ElfComdatSectionIterator<'data, 'file, Elf, R>;
-
- #[inline]
- fn kind(&self) -> ComdatKind {
- ComdatKind::Any
- }
-
- #[inline]
- fn symbol(&self) -> SymbolIndex {
- SymbolIndex(self.section.sh_info(self.file.endian) as usize)
- }
-
- fn name_bytes(&self) -> read::Result<&[u8]> {
- // FIXME: check sh_link
- let index = self.section.sh_info(self.file.endian) as usize;
- let symbol = self.file.symbols.symbol(index)?;
- symbol.name(self.file.endian, self.file.symbols.strings())
- }
-
- fn name(&self) -> read::Result<&str> {
- let name = self.name_bytes()?;
- str::from_utf8(name)
- .ok()
- .read_error("Non UTF-8 ELF COMDAT name")
- }
-
- fn sections(&self) -> Self::SectionIterator {
- ElfComdatSectionIterator {
- file: self.file,
- sections: self.sections.iter(),
- }
- }
-}
-
-/// An iterator for the sections in a COMDAT section group in an [`ElfFile32`](super::ElfFile32).
-pub type ElfComdatSectionIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
- ElfComdatSectionIterator<'data, 'file, elf::FileHeader32<Endian>, R>;
-/// An iterator for the sections in a COMDAT section group in an [`ElfFile64`](super::ElfFile64).
-pub type ElfComdatSectionIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
- ElfComdatSectionIterator<'data, 'file, elf::FileHeader64<Endian>, R>;
-
-/// An iterator for the sections in a COMDAT section group in an [`ElfFile`].
-#[derive(Debug)]
-pub struct ElfComdatSectionIterator<'data, 'file, Elf, R = &'data [u8]>
-where
- Elf: FileHeader,
- R: ReadRef<'data>,
-{
- file: &'file ElfFile<'data, Elf, R>,
- sections: slice::Iter<'data, U32Bytes<Elf::Endian>>,
-}
-
-impl<'data, 'file, Elf, R> Iterator for ElfComdatSectionIterator<'data, 'file, Elf, R>
-where
- Elf: FileHeader,
- R: ReadRef<'data>,
-{
- type Item = SectionIndex;
-
- fn next(&mut self) -> Option<Self::Item> {
- let index = self.sections.next()?;
- Some(SectionIndex(index.get(self.file.endian) as usize))
- }
-}
diff --git a/vendor/object/src/read/elf/compression.rs b/vendor/object/src/read/elf/compression.rs
deleted file mode 100644
index de2533f..0000000
--- a/vendor/object/src/read/elf/compression.rs
+++ /dev/null
@@ -1,56 +0,0 @@
-use core::fmt::Debug;
-
-use crate::elf;
-use crate::endian;
-use crate::pod::Pod;
-
-/// A trait for generic access to [`elf::CompressionHeader32`] and [`elf::CompressionHeader64`].
-#[allow(missing_docs)]
-pub trait CompressionHeader: Debug + Pod {
- type Word: Into<u64>;
- type Endian: endian::Endian;
-
- fn ch_type(&self, endian: Self::Endian) -> u32;
- fn ch_size(&self, endian: Self::Endian) -> Self::Word;
- fn ch_addralign(&self, endian: Self::Endian) -> Self::Word;
-}
-
-impl<Endian: endian::Endian> CompressionHeader for elf::CompressionHeader32<Endian> {
- type Word = u32;
- type Endian = Endian;
-
- #[inline]
- fn ch_type(&self, endian: Self::Endian) -> u32 {
- self.ch_type.get(endian)
- }
-
- #[inline]
- fn ch_size(&self, endian: Self::Endian) -> Self::Word {
- self.ch_size.get(endian)
- }
-
- #[inline]
- fn ch_addralign(&self, endian: Self::Endian) -> Self::Word {
- self.ch_addralign.get(endian)
- }
-}
-
-impl<Endian: endian::Endian> CompressionHeader for elf::CompressionHeader64<Endian> {
- type Word = u64;
- type Endian = Endian;
-
- #[inline]
- fn ch_type(&self, endian: Self::Endian) -> u32 {
- self.ch_type.get(endian)
- }
-
- #[inline]
- fn ch_size(&self, endian: Self::Endian) -> Self::Word {
- self.ch_size.get(endian)
- }
-
- #[inline]
- fn ch_addralign(&self, endian: Self::Endian) -> Self::Word {
- self.ch_addralign.get(endian)
- }
-}
diff --git a/vendor/object/src/read/elf/dynamic.rs b/vendor/object/src/read/elf/dynamic.rs
deleted file mode 100644
index 1661434..0000000
--- a/vendor/object/src/read/elf/dynamic.rs
+++ /dev/null
@@ -1,117 +0,0 @@
-use core::convert::TryInto;
-use core::fmt::Debug;
-
-use crate::elf;
-use crate::endian;
-use crate::pod::Pod;
-use crate::read::{ReadError, Result, StringTable};
-
-/// A trait for generic access to [`elf::Dyn32`] and [`elf::Dyn64`].
-#[allow(missing_docs)]
-pub trait Dyn: Debug + Pod {
- type Word: Into<u64>;
- type Endian: endian::Endian;
-
- fn d_tag(&self, endian: Self::Endian) -> Self::Word;
- fn d_val(&self, endian: Self::Endian) -> Self::Word;
-
- /// Try to convert the tag to a `u32`.
- fn tag32(&self, endian: Self::Endian) -> Option<u32> {
- self.d_tag(endian).into().try_into().ok()
- }
-
- /// Try to convert the value to a `u32`.
- fn val32(&self, endian: Self::Endian) -> Option<u32> {
- self.d_val(endian).into().try_into().ok()
- }
-
- /// Return true if the value is an offset in the dynamic string table.
- fn is_string(&self, endian: Self::Endian) -> bool {
- if let Some(tag) = self.tag32(endian) {
- match tag {
- elf::DT_NEEDED
- | elf::DT_SONAME
- | elf::DT_RPATH
- | elf::DT_RUNPATH
- | elf::DT_AUXILIARY
- | elf::DT_FILTER => true,
- _ => false,
- }
- } else {
- false
- }
- }
-
- /// Use the value to get a string in a string table.
- ///
- /// Does not check for an appropriate tag.
- fn string<'data>(
- &self,
- endian: Self::Endian,
- strings: StringTable<'data>,
- ) -> Result<&'data [u8]> {
- self.val32(endian)
- .and_then(|val| strings.get(val).ok())
- .read_error("Invalid ELF dyn string")
- }
-
- /// Return true if the value is an address.
- fn is_address(&self, endian: Self::Endian) -> bool {
- if let Some(tag) = self.tag32(endian) {
- match tag {
- elf::DT_PLTGOT
- | elf::DT_HASH
- | elf::DT_STRTAB
- | elf::DT_SYMTAB
- | elf::DT_RELA
- | elf::DT_INIT
- | elf::DT_FINI
- | elf::DT_SYMBOLIC
- | elf::DT_REL
- | elf::DT_DEBUG
- | elf::DT_JMPREL
- | elf::DT_FINI_ARRAY
- | elf::DT_INIT_ARRAY
- | elf::DT_PREINIT_ARRAY
- | elf::DT_SYMTAB_SHNDX
- | elf::DT_VERDEF
- | elf::DT_VERNEED
- | elf::DT_VERSYM
- | elf::DT_ADDRRNGLO..=elf::DT_ADDRRNGHI => true,
- _ => false,
- }
- } else {
- false
- }
- }
-}
-
-impl<Endian: endian::Endian> Dyn for elf::Dyn32<Endian> {
- type Word = u32;
- type Endian = Endian;
-
- #[inline]
- fn d_tag(&self, endian: Self::Endian) -> Self::Word {
- self.d_tag.get(endian)
- }
-
- #[inline]
- fn d_val(&self, endian: Self::Endian) -> Self::Word {
- self.d_val.get(endian)
- }
-}
-
-impl<Endian: endian::Endian> Dyn for elf::Dyn64<Endian> {
- type Word = u64;
- type Endian = Endian;
-
- #[inline]
- fn d_tag(&self, endian: Self::Endian) -> Self::Word {
- self.d_tag.get(endian)
- }
-
- #[inline]
- fn d_val(&self, endian: Self::Endian) -> Self::Word {
- self.d_val.get(endian)
- }
-}
diff --git a/vendor/object/src/read/elf/file.rs b/vendor/object/src/read/elf/file.rs
deleted file mode 100644
index 14ba568..0000000
--- a/vendor/object/src/read/elf/file.rs
+++ /dev/null
@@ -1,916 +0,0 @@
-use alloc::vec::Vec;
-use core::convert::TryInto;
-use core::fmt::Debug;
-use core::mem;
-
-use crate::read::{
- self, util, Architecture, ByteString, Bytes, Error, Export, FileFlags, Import, Object,
- ObjectKind, ReadError, ReadRef, SectionIndex, StringTable, SymbolIndex,
-};
-use crate::{elf, endian, Endian, Endianness, Pod, U32};
-
-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.
- pub fn raw_header(&self) -> &'data Elf {
- self.header
- }
-
- /// Returns the raw ELF segments.
- pub fn raw_segments(&self) -> &'data [Elf::ProgramHeader] {
- self.segments
- }
-
- 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: SectionIndex(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(&section_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, 'file, Elf, R> Object<'data, 'file> for ElfFile<'data, Elf, R>
-where
- 'data: 'file,
- Elf: FileHeader,
- R: 'file + ReadRef<'data>,
-{
- type Segment = ElfSegment<'data, 'file, Elf, R>;
- type SegmentIterator = ElfSegmentIterator<'data, 'file, Elf, R>;
- type Section = ElfSection<'data, 'file, Elf, R>;
- type SectionIterator = ElfSectionIterator<'data, 'file, Elf, R>;
- type Comdat = ElfComdat<'data, 'file, Elf, R>;
- type ComdatIterator = ElfComdatIterator<'data, 'file, Elf, R>;
- type Symbol = ElfSymbol<'data, 'file, Elf, R>;
- type SymbolIterator = ElfSymbolIterator<'data, 'file, Elf, R>;
- type SymbolTable = ElfSymbolTable<'data, 'file, Elf, R>;
- type DynamicRelocationIterator = ElfDynamicRelocationIterator<'data, 'file, Elf, R>;
-
- 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_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(&'file self) -> ElfSegmentIterator<'data, 'file, Elf, R> {
- ElfSegmentIterator {
- file: self,
- iter: self.segments.iter(),
- }
- }
-
- fn section_by_name_bytes(
- &'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(
- &'file self,
- index: SectionIndex,
- ) -> read::Result<ElfSection<'data, 'file, Elf, R>> {
- let section = self.sections.section(index)?;
- Ok(ElfSection {
- file: self,
- index,
- section,
- })
- }
-
- fn sections(&'file self) -> ElfSectionIterator<'data, 'file, Elf, R> {
- ElfSectionIterator {
- file: self,
- iter: self.sections.iter().enumerate(),
- }
- }
-
- fn comdats(&'file self) -> ElfComdatIterator<'data, 'file, Elf, R> {
- ElfComdatIterator {
- file: self,
- iter: self.sections.iter().enumerate(),
- }
- }
-
- fn symbol_by_index(
- &'file self,
- index: SymbolIndex,
- ) -> read::Result<ElfSymbol<'data, 'file, Elf, R>> {
- let symbol = self.symbols.symbol(index.0)?;
- Ok(ElfSymbol {
- endian: self.endian,
- symbols: &self.symbols,
- index,
- symbol,
- })
- }
-
- fn symbols(&'file self) -> ElfSymbolIterator<'data, 'file, Elf, R> {
- ElfSymbolIterator {
- endian: self.endian,
- symbols: &self.symbols,
- index: 0,
- }
- }
-
- fn symbol_table(&'file self) -> Option<ElfSymbolTable<'data, 'file, Elf, R>> {
- if self.symbols.is_empty() {
- return None;
- }
- Some(ElfSymbolTable {
- endian: self.endian,
- symbols: &self.symbols,
- })
- }
-
- fn dynamic_symbols(&'file self) -> ElfSymbolIterator<'data, 'file, Elf, R> {
- ElfSymbolIterator {
- endian: self.endian,
- symbols: &self.dynamic_symbols,
- index: 0,
- }
- }
-
- fn dynamic_symbol_table(&'file self) -> Option<ElfSymbolTable<'data, 'file, Elf, R>> {
- if self.dynamic_symbols.is_empty() {
- return None;
- }
- Some(ElfSymbolTable {
- endian: self.endian,
- symbols: &self.dynamic_symbols,
- })
- }
-
- fn dynamic_relocations(
- &'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 mut imports = Vec::new();
- for symbol in self.dynamic_symbols.iter() {
- if symbol.is_undefined(self.endian) {
- let name = symbol.name(self.endian, self.dynamic_symbols.strings())?;
- if !name.is_empty() {
- // TODO: use symbol versioning to determine library
- imports.push(Import {
- name: ByteString(name),
- library: ByteString(&[]),
- });
- }
- }
- }
- 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")
- }
-
- /// 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.shstrndx(endian, data)? as usize;
- let shstrtab = sections.get(index).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)
- }
-}
diff --git a/vendor/object/src/read/elf/hash.rs b/vendor/object/src/read/elf/hash.rs
deleted file mode 100644
index b0130cc..0000000
--- a/vendor/object/src/read/elf/hash.rs
+++ /dev/null
@@ -1,224 +0,0 @@
-use core::mem;
-
-use crate::elf;
-use crate::read::{ReadError, ReadRef, Result};
-use crate::{U32, U64};
-
-use super::{FileHeader, Sym, SymbolTable, Version, VersionTable};
-
-/// A SysV symbol hash table in an ELF file.
-///
-/// Returned by [`SectionHeader::hash`](super::SectionHeader::hash).
-#[derive(Debug)]
-pub struct HashTable<'data, Elf: FileHeader> {
- buckets: &'data [U32<Elf::Endian>],
- chains: &'data [U32<Elf::Endian>],
-}
-
-impl<'data, Elf: FileHeader> HashTable<'data, Elf> {
- /// Parse a SysV hash table.
- ///
- /// `data` should be from an [`elf::SHT_HASH`] section, or from a
- /// segment pointed to via the [`elf::DT_HASH`] entry.
- ///
- /// The header is read at offset 0 in the given `data`.
- pub fn parse(endian: Elf::Endian, data: &'data [u8]) -> Result<Self> {
- let mut offset = 0;
- let header = data
- .read::<elf::HashHeader<Elf::Endian>>(&mut offset)
- .read_error("Invalid hash header")?;
- let buckets = data
- .read_slice(&mut offset, header.bucket_count.get(endian) as usize)
- .read_error("Invalid hash buckets")?;
- let chains = data
- .read_slice(&mut offset, header.chain_count.get(endian) as usize)
- .read_error("Invalid hash chains")?;
- Ok(HashTable { buckets, chains })
- }
-
- /// Return the symbol table length.
- pub fn symbol_table_length(&self) -> u32 {
- self.chains.len() as u32
- }
-
- /// Use the hash table to find the symbol table entry with the given name, hash and version.
- pub fn find<R: ReadRef<'data>>(
- &self,
- endian: Elf::Endian,
- name: &[u8],
- hash: u32,
- version: Option<&Version<'_>>,
- symbols: &SymbolTable<'data, Elf, R>,
- versions: &VersionTable<'data, Elf>,
- ) -> Option<(usize, &'data Elf::Sym)> {
- // Get the chain start from the bucket for this hash.
- let mut index = self.buckets[(hash as usize) % self.buckets.len()].get(endian) as usize;
- // Avoid infinite loop.
- let mut i = 0;
- let strings = symbols.strings();
- while index != 0 && i < self.chains.len() {
- if let Ok(symbol) = symbols.symbol(index) {
- if symbol.name(endian, strings) == Ok(name)
- && versions.matches(endian, index, version)
- {
- return Some((index, symbol));
- }
- }
- index = self.chains.get(index)?.get(endian) as usize;
- i += 1;
- }
- None
- }
-}
-
-/// A GNU symbol hash table in an ELF file.
-///
-/// Returned by [`SectionHeader::gnu_hash`](super::SectionHeader::gnu_hash).
-#[derive(Debug)]
-pub struct GnuHashTable<'data, Elf: FileHeader> {
- symbol_base: u32,
- bloom_shift: u32,
- bloom_filters: &'data [u8],
- buckets: &'data [U32<Elf::Endian>],
- values: &'data [U32<Elf::Endian>],
-}
-
-impl<'data, Elf: FileHeader> GnuHashTable<'data, Elf> {
- /// Parse a GNU hash table.
- ///
- /// `data` should be from an [`elf::SHT_GNU_HASH`] section, or from a
- /// segment pointed to via the [`elf::DT_GNU_HASH`] entry.
- ///
- /// The header is read at offset 0 in the given `data`.
- ///
- /// The header does not contain a length field, and so all of `data`
- /// will be used as the hash table values. It does not matter if this
- /// is longer than needed, and this will often the case when accessing
- /// the hash table via the [`elf::DT_GNU_HASH`] entry.
- pub fn parse(endian: Elf::Endian, data: &'data [u8]) -> Result<Self> {
- let mut offset = 0;
- let header = data
- .read::<elf::GnuHashHeader<Elf::Endian>>(&mut offset)
- .read_error("Invalid GNU hash header")?;
- let bloom_len =
- u64::from(header.bloom_count.get(endian)) * mem::size_of::<Elf::Word>() as u64;
- let bloom_filters = data
- .read_bytes(&mut offset, bloom_len)
- .read_error("Invalid GNU hash bloom filters")?;
- let buckets = data
- .read_slice(&mut offset, header.bucket_count.get(endian) as usize)
- .read_error("Invalid GNU hash buckets")?;
- let chain_count = (data.len() - offset as usize) / 4;
- let values = data
- .read_slice(&mut offset, chain_count)
- .read_error("Invalid GNU hash values")?;
- Ok(GnuHashTable {
- symbol_base: header.symbol_base.get(endian),
- bloom_shift: header.bloom_shift.get(endian),
- bloom_filters,
- buckets,
- values,
- })
- }
-
- /// Return the symbol table index of the first symbol in the hash table.
- pub fn symbol_base(&self) -> u32 {
- self.symbol_base
- }
-
- /// Determine the symbol table length by finding the last entry in the hash table.
- ///
- /// Returns `None` if the hash table is empty or invalid.
- pub fn symbol_table_length(&self, endian: Elf::Endian) -> Option<u32> {
- // Ensure we find a non-empty bucket.
- if self.symbol_base == 0 {
- return None;
- }
-
- // Find the highest chain index in a bucket.
- let mut max_symbol = 0;
- for bucket in self.buckets {
- let bucket = bucket.get(endian);
- if max_symbol < bucket {
- max_symbol = bucket;
- }
- }
-
- // Find the end of the chain.
- for value in self
- .values
- .get(max_symbol.checked_sub(self.symbol_base)? as usize..)?
- {
- max_symbol += 1;
- if value.get(endian) & 1 != 0 {
- return Some(max_symbol);
- }
- }
-
- None
- }
-
- /// Use the hash table to find the symbol table entry with the given name, hash, and version.
- pub fn find<R: ReadRef<'data>>(
- &self,
- endian: Elf::Endian,
- name: &[u8],
- hash: u32,
- version: Option<&Version<'_>>,
- symbols: &SymbolTable<'data, Elf, R>,
- versions: &VersionTable<'data, Elf>,
- ) -> Option<(usize, &'data Elf::Sym)> {
- let word_bits = mem::size_of::<Elf::Word>() as u32 * 8;
-
- // Test against bloom filter.
- let bloom_count = self.bloom_filters.len() / mem::size_of::<Elf::Word>();
- let offset =
- ((hash / word_bits) & (bloom_count as u32 - 1)) * mem::size_of::<Elf::Word>() as u32;
- let filter = if word_bits == 64 {
- self.bloom_filters
- .read_at::<U64<Elf::Endian>>(offset.into())
- .ok()?
- .get(endian)
- } else {
- self.bloom_filters
- .read_at::<U32<Elf::Endian>>(offset.into())
- .ok()?
- .get(endian)
- .into()
- };
- if filter & (1 << (hash % word_bits)) == 0 {
- return None;
- }
- if filter & (1 << ((hash >> self.bloom_shift) % word_bits)) == 0 {
- return None;
- }
-
- // Get the chain start from the bucket for this hash.
- let mut index = self.buckets[(hash as usize) % self.buckets.len()].get(endian) as usize;
- if index == 0 {
- return None;
- }
-
- // Test symbols in the chain.
- let strings = symbols.strings();
- let symbols = symbols.symbols().get(index..)?;
- let values = self
- .values
- .get(index.checked_sub(self.symbol_base as usize)?..)?;
- for (symbol, value) in symbols.iter().zip(values.iter()) {
- let value = value.get(endian);
- if value | 1 == hash | 1 {
- if symbol.name(endian, strings) == Ok(name)
- && versions.matches(endian, index, version)
- {
- return Some((index, symbol));
- }
- }
- if value & 1 != 0 {
- break;
- }
- index += 1;
- }
- None
- }
-}
diff --git a/vendor/object/src/read/elf/mod.rs b/vendor/object/src/read/elf/mod.rs
deleted file mode 100644
index 66931bd..0000000
--- a/vendor/object/src/read/elf/mod.rs
+++ /dev/null
@@ -1,78 +0,0 @@
-//! Support for reading ELF files.
-//!
-//! Traits are used to abstract over the difference between 32-bit and 64-bit ELF.
-//! The primary trait for this is [`FileHeader`].
-//!
-//! ## High level API
-//!
-//! [`ElfFile`] implements the [`Object`](crate::read::Object) trait for ELF files.
-//! [`ElfFile`] is parameterised by [`FileHeader`] to allow reading both 32-bit and
-//! 64-bit ELF. There are type aliases for these parameters ([`ElfFile32`] and
-//! [`ElfFile64`]).
-//!
-//! ## Low level API
-//!
-//! The [`FileHeader`] trait can be directly used to parse both [`elf::FileHeader32`]
-//! and [`elf::FileHeader64`].
-//!
-//! ### Example for low level API
-//! ```no_run
-//! use object::elf;
-//! use object::read::elf::{FileHeader, Sym};
-//! use std::error::Error;
-//! use std::fs;
-//!
-//! /// Reads a file and displays the name of each symbol.
-//! fn main() -> Result<(), Box<dyn Error>> {
-//! # #[cfg(feature = "std")] {
-//! let data = fs::read("path/to/binary")?;
-//! let elf = elf::FileHeader64::<object::Endianness>::parse(&*data)?;
-//! let endian = elf.endian()?;
-//! let sections = elf.sections(endian, &*data)?;
-//! let symbols = sections.symbols(endian, &*data, elf::SHT_SYMTAB)?;
-//! for symbol in symbols.iter() {
-//! let name = symbol.name(endian, symbols.strings())?;
-//! println!("{}", String::from_utf8_lossy(name));
-//! }
-//! # }
-//! Ok(())
-//! }
-//! ```
-#[cfg(doc)]
-use crate::elf;
-
-mod file;
-pub use file::*;
-
-mod segment;
-pub use segment::*;
-
-mod section;
-pub use section::*;
-
-mod symbol;
-pub use symbol::*;
-
-mod relocation;
-pub use relocation::*;
-
-mod comdat;
-pub use comdat::*;
-
-mod dynamic;
-pub use dynamic::*;
-
-mod compression;
-pub use compression::*;
-
-mod note;
-pub use note::*;
-
-mod hash;
-pub use hash::*;
-
-mod version;
-pub use version::*;
-
-mod attributes;
-pub use attributes::*;
diff --git a/vendor/object/src/read/elf/note.rs b/vendor/object/src/read/elf/note.rs
deleted file mode 100644
index e2beef9..0000000
--- a/vendor/object/src/read/elf/note.rs
+++ /dev/null
@@ -1,271 +0,0 @@
-use core::fmt::Debug;
-use core::mem;
-
-use crate::elf;
-use crate::endian::{self, U32};
-use crate::pod::Pod;
-use crate::read::util;
-use crate::read::{self, Bytes, Error, ReadError};
-
-use super::FileHeader;
-
-/// An iterator over the notes in an ELF section or segment.
-///
-/// Returned [`ProgramHeader::notes`](super::ProgramHeader::notes)
-/// and [`SectionHeader::notes`](super::SectionHeader::notes).
-#[derive(Debug)]
-pub struct NoteIterator<'data, Elf>
-where
- Elf: FileHeader,
-{
- endian: Elf::Endian,
- align: usize,
- data: Bytes<'data>,
-}
-
-impl<'data, Elf> NoteIterator<'data, Elf>
-where
- Elf: FileHeader,
-{
- /// An iterator over the notes in an ELF section or segment.
- ///
- /// `align` should be from the `p_align` field of the segment,
- /// or the `sh_addralign` field of the section. Supported values are
- /// either 4 or 8, but values less than 4 are treated as 4.
- /// This matches the behaviour of binutils.
- ///
- /// Returns `Err` if `align` is invalid.
- pub fn new(endian: Elf::Endian, align: Elf::Word, data: &'data [u8]) -> read::Result<Self> {
- let align = match align.into() {
- 0u64..=4 => 4,
- 8 => 8,
- _ => return Err(Error("Invalid ELF note alignment")),
- };
- // TODO: check data alignment?
- Ok(NoteIterator {
- endian,
- align,
- data: Bytes(data),
- })
- }
-
- /// Returns the next note.
- pub fn next(&mut self) -> read::Result<Option<Note<'data, Elf>>> {
- let mut data = self.data;
- if data.is_empty() {
- return Ok(None);
- }
-
- let header = data
- .read_at::<Elf::NoteHeader>(0)
- .read_error("ELF note is too short")?;
-
- // The name has no alignment requirement.
- let offset = mem::size_of::<Elf::NoteHeader>();
- let namesz = header.n_namesz(self.endian) as usize;
- let name = data
- .read_bytes_at(offset, namesz)
- .read_error("Invalid ELF note namesz")?
- .0;
-
- // The descriptor must be aligned.
- let offset = util::align(offset + namesz, self.align);
- let descsz = header.n_descsz(self.endian) as usize;
- let desc = data
- .read_bytes_at(offset, descsz)
- .read_error("Invalid ELF note descsz")?
- .0;
-
- // The next note (if any) must be aligned.
- let offset = util::align(offset + descsz, self.align);
- if data.skip(offset).is_err() {
- data = Bytes(&[]);
- }
- self.data = data;
-
- Ok(Some(Note { header, name, desc }))
- }
-}
-
-/// A parsed [`NoteHeader`].
-#[derive(Debug)]
-pub struct Note<'data, Elf>
-where
- Elf: FileHeader,
-{
- header: &'data Elf::NoteHeader,
- name: &'data [u8],
- desc: &'data [u8],
-}
-
-impl<'data, Elf: FileHeader> Note<'data, Elf> {
- /// Return the `n_type` field of the `NoteHeader`.
- ///
- /// The meaning of this field is determined by `name`.
- pub fn n_type(&self, endian: Elf::Endian) -> u32 {
- self.header.n_type(endian)
- }
-
- /// Return the `n_namesz` field of the `NoteHeader`.
- pub fn n_namesz(&self, endian: Elf::Endian) -> u32 {
- self.header.n_namesz(endian)
- }
-
- /// Return the `n_descsz` field of the `NoteHeader`.
- pub fn n_descsz(&self, endian: Elf::Endian) -> u32 {
- self.header.n_descsz(endian)
- }
-
- /// Return the bytes for the name field following the `NoteHeader`.
- ///
- /// This field is usually a string including one or more trailing null bytes
- /// (but it is not required to be).
- ///
- /// The length of this field is given by `n_namesz`.
- pub fn name_bytes(&self) -> &'data [u8] {
- self.name
- }
-
- /// Return the bytes for the name field following the `NoteHeader`,
- /// excluding all trailing null bytes.
- pub fn name(&self) -> &'data [u8] {
- let mut name = self.name;
- while let [rest @ .., 0] = name {
- name = rest;
- }
- name
- }
-
- /// Return the bytes for the desc field following the `NoteHeader`.
- ///
- /// The length of this field is given by `n_descsz`. The meaning
- /// of this field is determined by `name` and `n_type`.
- pub fn desc(&self) -> &'data [u8] {
- self.desc
- }
-
- /// Return an iterator for properties if this note's type is [`elf::NT_GNU_PROPERTY_TYPE_0`].
- pub fn gnu_properties(
- &self,
- endian: Elf::Endian,
- ) -> Option<GnuPropertyIterator<'data, Elf::Endian>> {
- if self.name() != elf::ELF_NOTE_GNU || self.n_type(endian) != elf::NT_GNU_PROPERTY_TYPE_0 {
- return None;
- }
- // Use the ELF class instead of the section alignment.
- // This matches what other parsers do.
- let align = if Elf::is_type_64_sized() { 8 } else { 4 };
- Some(GnuPropertyIterator {
- endian,
- align,
- data: Bytes(self.desc),
- })
- }
-}
-
-/// A trait for generic access to [`elf::NoteHeader32`] and [`elf::NoteHeader64`].
-#[allow(missing_docs)]
-pub trait NoteHeader: Debug + Pod {
- type Endian: endian::Endian;
-
- fn n_namesz(&self, endian: Self::Endian) -> u32;
- fn n_descsz(&self, endian: Self::Endian) -> u32;
- fn n_type(&self, endian: Self::Endian) -> u32;
-}
-
-impl<Endian: endian::Endian> NoteHeader for elf::NoteHeader32<Endian> {
- type Endian = Endian;
-
- #[inline]
- fn n_namesz(&self, endian: Self::Endian) -> u32 {
- self.n_namesz.get(endian)
- }
-
- #[inline]
- fn n_descsz(&self, endian: Self::Endian) -> u32 {
- self.n_descsz.get(endian)
- }
-
- #[inline]
- fn n_type(&self, endian: Self::Endian) -> u32 {
- self.n_type.get(endian)
- }
-}
-
-impl<Endian: endian::Endian> NoteHeader for elf::NoteHeader64<Endian> {
- type Endian = Endian;
-
- #[inline]
- fn n_namesz(&self, endian: Self::Endian) -> u32 {
- self.n_namesz.get(endian)
- }
-
- #[inline]
- fn n_descsz(&self, endian: Self::Endian) -> u32 {
- self.n_descsz.get(endian)
- }
-
- #[inline]
- fn n_type(&self, endian: Self::Endian) -> u32 {
- self.n_type.get(endian)
- }
-}
-
-/// An iterator for the properties in a [`elf::NT_GNU_PROPERTY_TYPE_0`] note.
-///
-/// Returned by [`Note::gnu_properties`].
-#[derive(Debug)]
-pub struct GnuPropertyIterator<'data, Endian: endian::Endian> {
- endian: Endian,
- align: usize,
- data: Bytes<'data>,
-}
-
-impl<'data, Endian: endian::Endian> GnuPropertyIterator<'data, Endian> {
- /// Returns the next property.
- pub fn next(&mut self) -> read::Result<Option<GnuProperty<'data>>> {
- let mut data = self.data;
- if data.is_empty() {
- return Ok(None);
- }
-
- (|| -> Result<_, ()> {
- let pr_type = data.read_at::<U32<Endian>>(0)?.get(self.endian);
- let pr_datasz = data.read_at::<U32<Endian>>(4)?.get(self.endian) as usize;
- let pr_data = data.read_bytes_at(8, pr_datasz)?.0;
- data.skip(util::align(8 + pr_datasz, self.align))?;
- self.data = data;
- Ok(Some(GnuProperty { pr_type, pr_data }))
- })()
- .read_error("Invalid ELF GNU property")
- }
-}
-
-/// A property in a [`elf::NT_GNU_PROPERTY_TYPE_0`] note.
-#[derive(Debug)]
-pub struct GnuProperty<'data> {
- pr_type: u32,
- pr_data: &'data [u8],
-}
-
-impl<'data> GnuProperty<'data> {
- /// Return the property type.
- ///
- /// This is one of the `GNU_PROPERTY_*` constants.
- pub fn pr_type(&self) -> u32 {
- self.pr_type
- }
-
- /// Return the property data.
- pub fn pr_data(&self) -> &'data [u8] {
- self.pr_data
- }
-
- /// Parse the property data as an unsigned 32-bit integer.
- pub fn data_u32<E: endian::Endian>(&self, endian: E) -> read::Result<u32> {
- Bytes(self.pr_data)
- .read_at::<U32<E>>(0)
- .read_error("Invalid ELF GNU property data")
- .map(|val| val.get(endian))
- }
-}
diff --git a/vendor/object/src/read/elf/relocation.rs b/vendor/object/src/read/elf/relocation.rs
deleted file mode 100644
index aac1574..0000000
--- a/vendor/object/src/read/elf/relocation.rs
+++ /dev/null
@@ -1,628 +0,0 @@
-use alloc::fmt;
-use alloc::vec::Vec;
-use core::fmt::Debug;
-use core::slice;
-
-use crate::elf;
-use crate::endian::{self, Endianness};
-use crate::pod::Pod;
-use crate::read::{
- self, Error, ReadRef, Relocation, RelocationEncoding, RelocationKind, RelocationTarget,
- SectionIndex, SymbolIndex,
-};
-
-use super::{ElfFile, FileHeader, SectionHeader, SectionTable};
-
-/// A mapping from section index to associated relocation sections.
-#[derive(Debug)]
-pub struct RelocationSections {
- relocations: Vec<usize>,
-}
-
-impl RelocationSections {
- /// Create a new mapping using the section table.
- ///
- /// Skips relocation sections that do not use the given symbol table section.
- pub fn parse<'data, Elf: FileHeader, R: ReadRef<'data>>(
- endian: Elf::Endian,
- sections: &SectionTable<'data, Elf, R>,
- symbol_section: SectionIndex,
- ) -> read::Result<Self> {
- let mut relocations = vec![0; sections.len()];
- for (index, section) in sections.iter().enumerate().rev() {
- let sh_type = section.sh_type(endian);
- if sh_type == elf::SHT_REL || sh_type == elf::SHT_RELA {
- // The symbol indices used in relocations must be for the symbol table
- // we are expecting to use.
- let sh_link = SectionIndex(section.sh_link(endian) as usize);
- if sh_link != symbol_section {
- continue;
- }
-
- let sh_info = section.sh_info(endian) as usize;
- if sh_info == 0 {
- // Skip dynamic relocations.
- continue;
- }
- if sh_info >= relocations.len() {
- return Err(Error("Invalid ELF sh_info for relocation section"));
- }
-
- // Handle multiple relocation sections by chaining them.
- let next = relocations[sh_info];
- relocations[sh_info] = index;
- relocations[index] = next;
- }
- }
- Ok(Self { relocations })
- }
-
- /// Given a section index, return the section index of the associated relocation section.
- ///
- /// This may also be called with a relocation section index, and it will return the
- /// next associated relocation section.
- pub fn get(&self, index: usize) -> Option<usize> {
- self.relocations.get(index).cloned().filter(|x| *x != 0)
- }
-}
-
-pub(super) enum ElfRelaIterator<'data, Elf: FileHeader> {
- Rel(slice::Iter<'data, Elf::Rel>),
- Rela(slice::Iter<'data, Elf::Rela>),
-}
-
-impl<'data, Elf: FileHeader> ElfRelaIterator<'data, Elf> {
- fn is_rel(&self) -> bool {
- match self {
- ElfRelaIterator::Rel(_) => true,
- ElfRelaIterator::Rela(_) => false,
- }
- }
-}
-
-impl<'data, Elf: FileHeader> Iterator for ElfRelaIterator<'data, Elf> {
- type Item = Elf::Rela;
-
- fn next(&mut self) -> Option<Self::Item> {
- match self {
- ElfRelaIterator::Rel(ref mut i) => i.next().cloned().map(Self::Item::from),
- ElfRelaIterator::Rela(ref mut i) => i.next().cloned(),
- }
- }
-}
-
-/// An iterator for the dynamic relocations in an [`ElfFile32`](super::ElfFile32).
-pub type ElfDynamicRelocationIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
- ElfDynamicRelocationIterator<'data, 'file, elf::FileHeader32<Endian>, R>;
-/// An iterator for the dynamic relocations in an [`ElfFile64`](super::ElfFile64).
-pub type ElfDynamicRelocationIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
- ElfDynamicRelocationIterator<'data, 'file, elf::FileHeader64<Endian>, R>;
-
-/// An iterator for the dynamic relocations in an [`ElfFile`].
-pub struct ElfDynamicRelocationIterator<'data, 'file, Elf, R = &'data [u8]>
-where
- Elf: FileHeader,
- R: ReadRef<'data>,
-{
- /// The current relocation section index.
- pub(super) section_index: SectionIndex,
- pub(super) file: &'file ElfFile<'data, Elf, R>,
- pub(super) relocations: Option<ElfRelaIterator<'data, Elf>>,
-}
-
-impl<'data, 'file, Elf, R> Iterator for ElfDynamicRelocationIterator<'data, 'file, Elf, R>
-where
- Elf: FileHeader,
- R: ReadRef<'data>,
-{
- type Item = (u64, Relocation);
-
- fn next(&mut self) -> Option<Self::Item> {
- let endian = self.file.endian;
- loop {
- if let Some(ref mut relocations) = self.relocations {
- if let Some(reloc) = relocations.next() {
- let relocation =
- parse_relocation(self.file.header, endian, reloc, relocations.is_rel());
- return Some((reloc.r_offset(endian).into(), relocation));
- }
- self.relocations = None;
- }
-
- let section = self.file.sections.section(self.section_index).ok()?;
- self.section_index.0 += 1;
-
- let sh_link = SectionIndex(section.sh_link(endian) as usize);
- if sh_link != self.file.dynamic_symbols.section() {
- continue;
- }
-
- match section.sh_type(endian) {
- elf::SHT_REL => {
- if let Ok(relocations) = section.data_as_array(endian, self.file.data) {
- self.relocations = Some(ElfRelaIterator::Rel(relocations.iter()));
- }
- }
- elf::SHT_RELA => {
- if let Ok(relocations) = section.data_as_array(endian, self.file.data) {
- self.relocations = Some(ElfRelaIterator::Rela(relocations.iter()));
- }
- }
- _ => {}
- }
- }
- }
-}
-
-impl<'data, 'file, Elf, R> fmt::Debug for ElfDynamicRelocationIterator<'data, 'file, Elf, R>
-where
- Elf: FileHeader,
- R: ReadRef<'data>,
-{
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("ElfDynamicRelocationIterator").finish()
- }
-}
-
-/// An iterator for the relocations for an [`ElfSection32`](super::ElfSection32).
-pub type ElfSectionRelocationIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
- ElfSectionRelocationIterator<'data, 'file, elf::FileHeader32<Endian>, R>;
-/// An iterator for the relocations for an [`ElfSection64`](super::ElfSection64).
-pub type ElfSectionRelocationIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
- ElfSectionRelocationIterator<'data, 'file, elf::FileHeader64<Endian>, R>;
-
-/// An iterator for the relocations for an [`ElfSection`](super::ElfSection).
-pub struct ElfSectionRelocationIterator<'data, 'file, Elf, R = &'data [u8]>
-where
- Elf: FileHeader,
- R: ReadRef<'data>,
-{
- /// The current pointer in the chain of relocation sections.
- pub(super) section_index: SectionIndex,
- pub(super) file: &'file ElfFile<'data, Elf, R>,
- pub(super) relocations: Option<ElfRelaIterator<'data, Elf>>,
-}
-
-impl<'data, 'file, Elf, R> Iterator for ElfSectionRelocationIterator<'data, 'file, Elf, R>
-where
- Elf: FileHeader,
- R: ReadRef<'data>,
-{
- type Item = (u64, Relocation);
-
- fn next(&mut self) -> Option<Self::Item> {
- let endian = self.file.endian;
- loop {
- if let Some(ref mut relocations) = self.relocations {
- if let Some(reloc) = relocations.next() {
- let relocation =
- parse_relocation(self.file.header, endian, reloc, relocations.is_rel());
- return Some((reloc.r_offset(endian).into(), relocation));
- }
- self.relocations = None;
- }
- self.section_index = SectionIndex(self.file.relocations.get(self.section_index.0)?);
- // The construction of RelocationSections ensures section_index is valid.
- let section = self.file.sections.section(self.section_index).unwrap();
- match section.sh_type(endian) {
- elf::SHT_REL => {
- if let Ok(relocations) = section.data_as_array(endian, self.file.data) {
- self.relocations = Some(ElfRelaIterator::Rel(relocations.iter()));
- }
- }
- elf::SHT_RELA => {
- if let Ok(relocations) = section.data_as_array(endian, self.file.data) {
- self.relocations = Some(ElfRelaIterator::Rela(relocations.iter()));
- }
- }
- _ => {}
- }
- }
- }
-}
-
-impl<'data, 'file, Elf, R> fmt::Debug for ElfSectionRelocationIterator<'data, 'file, Elf, R>
-where
- Elf: FileHeader,
- R: ReadRef<'data>,
-{
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("ElfSectionRelocationIterator").finish()
- }
-}
-
-fn parse_relocation<Elf: FileHeader>(
- header: &Elf,
- endian: Elf::Endian,
- reloc: Elf::Rela,
- implicit_addend: bool,
-) -> Relocation {
- let mut encoding = RelocationEncoding::Generic;
- let is_mips64el = header.is_mips64el(endian);
- let (kind, size) = match header.e_machine(endian) {
- elf::EM_AARCH64 => {
- if header.is_type_64() {
- match reloc.r_type(endian, false) {
- elf::R_AARCH64_ABS64 => (RelocationKind::Absolute, 64),
- elf::R_AARCH64_ABS32 => (RelocationKind::Absolute, 32),
- elf::R_AARCH64_ABS16 => (RelocationKind::Absolute, 16),
- elf::R_AARCH64_PREL64 => (RelocationKind::Relative, 64),
- elf::R_AARCH64_PREL32 => (RelocationKind::Relative, 32),
- elf::R_AARCH64_PREL16 => (RelocationKind::Relative, 16),
- elf::R_AARCH64_CALL26 => {
- encoding = RelocationEncoding::AArch64Call;
- (RelocationKind::PltRelative, 26)
- }
- r_type => (RelocationKind::Elf(r_type), 0),
- }
- } else {
- match reloc.r_type(endian, false) {
- elf::R_AARCH64_P32_ABS32 => (RelocationKind::Absolute, 32),
- r_type => (RelocationKind::Elf(r_type), 0),
- }
- }
- }
- elf::EM_ARM => match reloc.r_type(endian, false) {
- elf::R_ARM_ABS32 => (RelocationKind::Absolute, 32),
- r_type => (RelocationKind::Elf(r_type), 0),
- },
- elf::EM_AVR => match reloc.r_type(endian, false) {
- elf::R_AVR_32 => (RelocationKind::Absolute, 32),
- elf::R_AVR_16 => (RelocationKind::Absolute, 16),
- r_type => (RelocationKind::Elf(r_type), 0),
- },
- elf::EM_BPF => match reloc.r_type(endian, false) {
- elf::R_BPF_64_64 => (RelocationKind::Absolute, 64),
- elf::R_BPF_64_32 => (RelocationKind::Absolute, 32),
- r_type => (RelocationKind::Elf(r_type), 0),
- },
- elf::EM_CSKY => match reloc.r_type(endian, false) {
- elf::R_CKCORE_ADDR32 => (RelocationKind::Absolute, 32),
- elf::R_CKCORE_PCREL32 => (RelocationKind::Relative, 32),
- r_type => (RelocationKind::Elf(r_type), 0),
- },
- elf::EM_386 => match reloc.r_type(endian, false) {
- elf::R_386_32 => (RelocationKind::Absolute, 32),
- elf::R_386_PC32 => (RelocationKind::Relative, 32),
- elf::R_386_GOT32 => (RelocationKind::Got, 32),
- elf::R_386_PLT32 => (RelocationKind::PltRelative, 32),
- elf::R_386_GOTOFF => (RelocationKind::GotBaseOffset, 32),
- elf::R_386_GOTPC => (RelocationKind::GotBaseRelative, 32),
- elf::R_386_16 => (RelocationKind::Absolute, 16),
- elf::R_386_PC16 => (RelocationKind::Relative, 16),
- elf::R_386_8 => (RelocationKind::Absolute, 8),
- elf::R_386_PC8 => (RelocationKind::Relative, 8),
- r_type => (RelocationKind::Elf(r_type), 0),
- },
- elf::EM_X86_64 => match reloc.r_type(endian, false) {
- elf::R_X86_64_64 => (RelocationKind::Absolute, 64),
- elf::R_X86_64_PC32 => (RelocationKind::Relative, 32),
- elf::R_X86_64_GOT32 => (RelocationKind::Got, 32),
- elf::R_X86_64_PLT32 => (RelocationKind::PltRelative, 32),
- elf::R_X86_64_GOTPCREL => (RelocationKind::GotRelative, 32),
- elf::R_X86_64_32 => (RelocationKind::Absolute, 32),
- elf::R_X86_64_32S => {
- encoding = RelocationEncoding::X86Signed;
- (RelocationKind::Absolute, 32)
- }
- elf::R_X86_64_16 => (RelocationKind::Absolute, 16),
- elf::R_X86_64_PC16 => (RelocationKind::Relative, 16),
- elf::R_X86_64_8 => (RelocationKind::Absolute, 8),
- elf::R_X86_64_PC8 => (RelocationKind::Relative, 8),
- r_type => (RelocationKind::Elf(r_type), 0),
- },
- elf::EM_HEXAGON => match reloc.r_type(endian, false) {
- elf::R_HEX_32 => (RelocationKind::Absolute, 32),
- r_type => (RelocationKind::Elf(r_type), 0),
- },
- elf::EM_LOONGARCH => match reloc.r_type(endian, false) {
- elf::R_LARCH_32 => (RelocationKind::Absolute, 32),
- elf::R_LARCH_64 => (RelocationKind::Absolute, 64),
- elf::R_LARCH_32_PCREL => (RelocationKind::Relative, 32),
- elf::R_LARCH_64_PCREL => (RelocationKind::Relative, 64),
- elf::R_LARCH_B16 => {
- encoding = RelocationEncoding::LoongArchBranch;
- (RelocationKind::Relative, 16)
- }
- elf::R_LARCH_B21 => {
- encoding = RelocationEncoding::LoongArchBranch;
- (RelocationKind::Relative, 21)
- }
- elf::R_LARCH_B26 => {
- encoding = RelocationEncoding::LoongArchBranch;
- (RelocationKind::Relative, 26)
- }
- r_type => (RelocationKind::Elf(r_type), 0),
- },
- elf::EM_MIPS => match reloc.r_type(endian, is_mips64el) {
- elf::R_MIPS_16 => (RelocationKind::Absolute, 16),
- elf::R_MIPS_32 => (RelocationKind::Absolute, 32),
- elf::R_MIPS_64 => (RelocationKind::Absolute, 64),
- r_type => (RelocationKind::Elf(r_type), 0),
- },
- elf::EM_MSP430 => match reloc.r_type(endian, false) {
- elf::R_MSP430_32 => (RelocationKind::Absolute, 32),
- elf::R_MSP430_16_BYTE => (RelocationKind::Absolute, 16),
- r_type => (RelocationKind::Elf(r_type), 0),
- },
- elf::EM_PPC => match reloc.r_type(endian, false) {
- elf::R_PPC_ADDR32 => (RelocationKind::Absolute, 32),
- r_type => (RelocationKind::Elf(r_type), 0),
- },
- elf::EM_PPC64 => match reloc.r_type(endian, false) {
- elf::R_PPC64_ADDR32 => (RelocationKind::Absolute, 32),
- elf::R_PPC64_ADDR64 => (RelocationKind::Absolute, 64),
- r_type => (RelocationKind::Elf(r_type), 0),
- },
- elf::EM_RISCV => match reloc.r_type(endian, false) {
- elf::R_RISCV_32 => (RelocationKind::Absolute, 32),
- elf::R_RISCV_64 => (RelocationKind::Absolute, 64),
- r_type => (RelocationKind::Elf(r_type), 0),
- },
- elf::EM_S390 => match reloc.r_type(endian, false) {
- elf::R_390_8 => (RelocationKind::Absolute, 8),
- elf::R_390_16 => (RelocationKind::Absolute, 16),
- elf::R_390_32 => (RelocationKind::Absolute, 32),
- elf::R_390_64 => (RelocationKind::Absolute, 64),
- elf::R_390_PC16 => (RelocationKind::Relative, 16),
- elf::R_390_PC32 => (RelocationKind::Relative, 32),
- elf::R_390_PC64 => (RelocationKind::Relative, 64),
- elf::R_390_PC16DBL => {
- encoding = RelocationEncoding::S390xDbl;
- (RelocationKind::Relative, 16)
- }
- elf::R_390_PC32DBL => {
- encoding = RelocationEncoding::S390xDbl;
- (RelocationKind::Relative, 32)
- }
- elf::R_390_PLT16DBL => {
- encoding = RelocationEncoding::S390xDbl;
- (RelocationKind::PltRelative, 16)
- }
- elf::R_390_PLT32DBL => {
- encoding = RelocationEncoding::S390xDbl;
- (RelocationKind::PltRelative, 32)
- }
- elf::R_390_GOT16 => (RelocationKind::Got, 16),
- elf::R_390_GOT32 => (RelocationKind::Got, 32),
- elf::R_390_GOT64 => (RelocationKind::Got, 64),
- elf::R_390_GOTENT => {
- encoding = RelocationEncoding::S390xDbl;
- (RelocationKind::GotRelative, 32)
- }
- elf::R_390_GOTOFF16 => (RelocationKind::GotBaseOffset, 16),
- elf::R_390_GOTOFF32 => (RelocationKind::GotBaseOffset, 32),
- elf::R_390_GOTOFF64 => (RelocationKind::GotBaseOffset, 64),
- elf::R_390_GOTPC => (RelocationKind::GotBaseRelative, 64),
- elf::R_390_GOTPCDBL => {
- encoding = RelocationEncoding::S390xDbl;
- (RelocationKind::GotBaseRelative, 32)
- }
- r_type => (RelocationKind::Elf(r_type), 0),
- },
- elf::EM_SBF => match reloc.r_type(endian, false) {
- elf::R_SBF_64_64 => (RelocationKind::Absolute, 64),
- elf::R_SBF_64_32 => (RelocationKind::Absolute, 32),
- r_type => (RelocationKind::Elf(r_type), 0),
- },
- elf::EM_SHARC => match reloc.r_type(endian, false) {
- elf::R_SHARC_ADDR24_V3 => {
- encoding = RelocationEncoding::SharcTypeA;
- (RelocationKind::Absolute, 24)
- }
- elf::R_SHARC_ADDR32_V3 => {
- encoding = RelocationEncoding::SharcTypeA;
- (RelocationKind::Absolute, 32)
- }
- elf::R_SHARC_ADDR_VAR_V3 => {
- encoding = RelocationEncoding::Generic;
- (RelocationKind::Absolute, 32)
- }
- elf::R_SHARC_PCRSHORT_V3 => {
- encoding = RelocationEncoding::SharcTypeA;
- (RelocationKind::Relative, 6)
- }
- elf::R_SHARC_PCRLONG_V3 => {
- encoding = RelocationEncoding::SharcTypeA;
- (RelocationKind::Relative, 24)
- }
- elf::R_SHARC_DATA6_V3 => {
- encoding = RelocationEncoding::SharcTypeA;
- (RelocationKind::Absolute, 6)
- }
- elf::R_SHARC_DATA16_V3 => {
- encoding = RelocationEncoding::SharcTypeA;
- (RelocationKind::Absolute, 16)
- }
- elf::R_SHARC_DATA6_VISA_V3 => {
- encoding = RelocationEncoding::SharcTypeB;
- (RelocationKind::Absolute, 6)
- }
- elf::R_SHARC_DATA7_VISA_V3 => {
- encoding = RelocationEncoding::SharcTypeB;
- (RelocationKind::Absolute, 7)
- }
- elf::R_SHARC_DATA16_VISA_V3 => {
- encoding = RelocationEncoding::SharcTypeB;
- (RelocationKind::Absolute, 16)
- }
- elf::R_SHARC_PCR6_VISA_V3 => {
- encoding = RelocationEncoding::SharcTypeB;
- (RelocationKind::Relative, 16)
- }
- elf::R_SHARC_ADDR_VAR16_V3 => {
- encoding = RelocationEncoding::Generic;
- (RelocationKind::Absolute, 16)
- }
- r_type => (RelocationKind::Elf(r_type), 0),
- },
- elf::EM_SPARC | elf::EM_SPARC32PLUS | elf::EM_SPARCV9 => {
- match reloc.r_type(endian, false) {
- elf::R_SPARC_32 | elf::R_SPARC_UA32 => (RelocationKind::Absolute, 32),
- elf::R_SPARC_64 | elf::R_SPARC_UA64 => (RelocationKind::Absolute, 64),
- r_type => (RelocationKind::Elf(r_type), 0),
- }
- }
- elf::EM_XTENSA => match reloc.r_type(endian, false) {
- elf::R_XTENSA_32 => (RelocationKind::Absolute, 32),
- elf::R_XTENSA_32_PCREL => (RelocationKind::Relative, 32),
- r_type => (RelocationKind::Elf(r_type), 0),
- },
- _ => (RelocationKind::Elf(reloc.r_type(endian, false)), 0),
- };
- let sym = reloc.r_sym(endian, is_mips64el) as usize;
- let target = if sym == 0 {
- RelocationTarget::Absolute
- } else {
- RelocationTarget::Symbol(SymbolIndex(sym))
- };
- Relocation {
- kind,
- encoding,
- size,
- target,
- addend: reloc.r_addend(endian).into(),
- implicit_addend,
- }
-}
-
-/// A trait for generic access to [`elf::Rel32`] and [`elf::Rel64`].
-#[allow(missing_docs)]
-pub trait Rel: Debug + Pod + Clone {
- type Word: Into<u64>;
- type Sword: Into<i64>;
- type Endian: endian::Endian;
-
- fn r_offset(&self, endian: Self::Endian) -> Self::Word;
- fn r_info(&self, endian: Self::Endian) -> Self::Word;
- fn r_sym(&self, endian: Self::Endian) -> u32;
- fn r_type(&self, endian: Self::Endian) -> u32;
-}
-
-impl<Endian: endian::Endian> Rel for elf::Rel32<Endian> {
- type Word = u32;
- type Sword = i32;
- type Endian = Endian;
-
- #[inline]
- fn r_offset(&self, endian: Self::Endian) -> Self::Word {
- self.r_offset.get(endian)
- }
-
- #[inline]
- fn r_info(&self, endian: Self::Endian) -> Self::Word {
- self.r_info.get(endian)
- }
-
- #[inline]
- fn r_sym(&self, endian: Self::Endian) -> u32 {
- self.r_sym(endian)
- }
-
- #[inline]
- fn r_type(&self, endian: Self::Endian) -> u32 {
- self.r_type(endian)
- }
-}
-
-impl<Endian: endian::Endian> Rel for elf::Rel64<Endian> {
- type Word = u64;
- type Sword = i64;
- type Endian = Endian;
-
- #[inline]
- fn r_offset(&self, endian: Self::Endian) -> Self::Word {
- self.r_offset.get(endian)
- }
-
- #[inline]
- fn r_info(&self, endian: Self::Endian) -> Self::Word {
- self.r_info.get(endian)
- }
-
- #[inline]
- fn r_sym(&self, endian: Self::Endian) -> u32 {
- self.r_sym(endian)
- }
-
- #[inline]
- fn r_type(&self, endian: Self::Endian) -> u32 {
- self.r_type(endian)
- }
-}
-
-/// A trait for generic access to [`elf::Rela32`] and [`elf::Rela64`].
-#[allow(missing_docs)]
-pub trait Rela: Debug + Pod + Clone {
- type Word: Into<u64>;
- type Sword: Into<i64>;
- type Endian: endian::Endian;
-
- fn r_offset(&self, endian: Self::Endian) -> Self::Word;
- fn r_info(&self, endian: Self::Endian, is_mips64el: bool) -> Self::Word;
- fn r_addend(&self, endian: Self::Endian) -> Self::Sword;
- fn r_sym(&self, endian: Self::Endian, is_mips64el: bool) -> u32;
- fn r_type(&self, endian: Self::Endian, is_mips64el: bool) -> u32;
-}
-
-impl<Endian: endian::Endian> Rela for elf::Rela32<Endian> {
- type Word = u32;
- type Sword = i32;
- type Endian = Endian;
-
- #[inline]
- fn r_offset(&self, endian: Self::Endian) -> Self::Word {
- self.r_offset.get(endian)
- }
-
- #[inline]
- fn r_info(&self, endian: Self::Endian, _is_mips64el: bool) -> Self::Word {
- self.r_info.get(endian)
- }
-
- #[inline]
- fn r_addend(&self, endian: Self::Endian) -> Self::Sword {
- self.r_addend.get(endian)
- }
-
- #[inline]
- fn r_sym(&self, endian: Self::Endian, _is_mips64el: bool) -> u32 {
- self.r_sym(endian)
- }
-
- #[inline]
- fn r_type(&self, endian: Self::Endian, _is_mips64el: bool) -> u32 {
- self.r_type(endian)
- }
-}
-
-impl<Endian: endian::Endian> Rela for elf::Rela64<Endian> {
- type Word = u64;
- type Sword = i64;
- type Endian = Endian;
-
- #[inline]
- fn r_offset(&self, endian: Self::Endian) -> Self::Word {
- self.r_offset.get(endian)
- }
-
- #[inline]
- fn r_info(&self, endian: Self::Endian, is_mips64el: bool) -> Self::Word {
- self.get_r_info(endian, is_mips64el)
- }
-
- #[inline]
- fn r_addend(&self, endian: Self::Endian) -> Self::Sword {
- self.r_addend.get(endian)
- }
-
- #[inline]
- fn r_sym(&self, endian: Self::Endian, is_mips64el: bool) -> u32 {
- self.r_sym(endian, is_mips64el)
- }
-
- #[inline]
- fn r_type(&self, endian: Self::Endian, is_mips64el: bool) -> u32 {
- self.r_type(endian, is_mips64el)
- }
-}
diff --git a/vendor/object/src/read/elf/section.rs b/vendor/object/src/read/elf/section.rs
deleted file mode 100644
index 2b5ae01..0000000
--- a/vendor/object/src/read/elf/section.rs
+++ /dev/null
@@ -1,1150 +0,0 @@
-use core::fmt::Debug;
-use core::{iter, mem, slice, str};
-
-use crate::elf;
-use crate::endian::{self, Endianness, U32Bytes};
-use crate::pod::Pod;
-use crate::read::{
- self, Bytes, CompressedData, CompressedFileRange, CompressionFormat, Error, ObjectSection,
- ReadError, ReadRef, SectionFlags, SectionIndex, SectionKind, StringTable,
-};
-
-use super::{
- AttributesSection, CompressionHeader, ElfFile, ElfSectionRelocationIterator, FileHeader,
- GnuHashTable, HashTable, NoteIterator, RelocationSections, SymbolTable, VerdefIterator,
- VerneedIterator, VersionTable,
-};
-
-/// The table of section headers in an ELF file.
-///
-/// Also includes the string table used for the section names.
-///
-/// Returned by [`FileHeader::sections`].
-#[derive(Debug, Default, Clone, Copy)]
-pub struct SectionTable<'data, Elf: FileHeader, R = &'data [u8]>
-where
- R: ReadRef<'data>,
-{
- sections: &'data [Elf::SectionHeader],
- strings: StringTable<'data, R>,
-}
-
-impl<'data, Elf: FileHeader, R: ReadRef<'data>> SectionTable<'data, Elf, R> {
- /// Create a new section table.
- #[inline]
- pub fn new(sections: &'data [Elf::SectionHeader], strings: StringTable<'data, R>) -> Self {
- SectionTable { sections, strings }
- }
-
- /// Iterate over the section headers.
- #[inline]
- pub fn iter(&self) -> slice::Iter<'data, Elf::SectionHeader> {
- self.sections.iter()
- }
-
- /// Return true if the section table is empty.
- #[inline]
- pub fn is_empty(&self) -> bool {
- self.sections.is_empty()
- }
-
- /// The number of section headers.
- #[inline]
- pub fn len(&self) -> usize {
- self.sections.len()
- }
-
- /// Return the section header at the given index.
- pub fn section(&self, index: SectionIndex) -> read::Result<&'data Elf::SectionHeader> {
- self.sections
- .get(index.0)
- .read_error("Invalid ELF section index")
- }
-
- /// Return the section header with the given name.
- ///
- /// Ignores sections with invalid names.
- pub fn section_by_name(
- &self,
- endian: Elf::Endian,
- name: &[u8],
- ) -> Option<(usize, &'data Elf::SectionHeader)> {
- self.sections
- .iter()
- .enumerate()
- .find(|(_, section)| self.section_name(endian, section) == Ok(name))
- }
-
- /// Return the section name for the given section header.
- pub fn section_name(
- &self,
- endian: Elf::Endian,
- section: &'data Elf::SectionHeader,
- ) -> read::Result<&'data [u8]> {
- section.name(endian, self.strings)
- }
-
- /// Return the string table at the given section index.
- ///
- /// Returns an error if the section is not a string table.
- #[inline]
- pub fn strings(
- &self,
- endian: Elf::Endian,
- data: R,
- index: SectionIndex,
- ) -> read::Result<StringTable<'data, R>> {
- self.section(index)?
- .strings(endian, data)?
- .read_error("Invalid ELF string section type")
- }
-
- /// Return the symbol table of the given section type.
- ///
- /// Returns an empty symbol table if the symbol table does not exist.
- #[inline]
- pub fn symbols(
- &self,
- endian: Elf::Endian,
- data: R,
- sh_type: u32,
- ) -> read::Result<SymbolTable<'data, Elf, R>> {
- debug_assert!(sh_type == elf::SHT_DYNSYM || sh_type == elf::SHT_SYMTAB);
-
- let (index, section) = match self
- .iter()
- .enumerate()
- .find(|s| s.1.sh_type(endian) == sh_type)
- {
- Some(s) => s,
- None => return Ok(SymbolTable::default()),
- };
-
- SymbolTable::parse(endian, data, self, SectionIndex(index), section)
- }
-
- /// Return the symbol table at the given section index.
- ///
- /// Returns an error if the section is not a symbol table.
- #[inline]
- pub fn symbol_table_by_index(
- &self,
- endian: Elf::Endian,
- data: R,
- index: SectionIndex,
- ) -> read::Result<SymbolTable<'data, Elf, R>> {
- let section = self.section(index)?;
- match section.sh_type(endian) {
- elf::SHT_DYNSYM | elf::SHT_SYMTAB => {}
- _ => return Err(Error("Invalid ELF symbol table section type")),
- }
- SymbolTable::parse(endian, data, self, index, section)
- }
-
- /// Create a mapping from section index to associated relocation sections.
- #[inline]
- pub fn relocation_sections(
- &self,
- endian: Elf::Endian,
- symbol_section: SectionIndex,
- ) -> read::Result<RelocationSections> {
- RelocationSections::parse(endian, self, symbol_section)
- }
-
- /// Return the contents of a dynamic section.
- ///
- /// Also returns the linked string table index.
- ///
- /// Returns `Ok(None)` if there is no `SHT_DYNAMIC` section.
- /// Returns `Err` for invalid values.
- pub fn dynamic(
- &self,
- endian: Elf::Endian,
- data: R,
- ) -> read::Result<Option<(&'data [Elf::Dyn], SectionIndex)>> {
- for section in self.sections {
- if let Some(dynamic) = section.dynamic(endian, data)? {
- return Ok(Some(dynamic));
- }
- }
- Ok(None)
- }
-
- /// Return the header of a SysV hash section.
- ///
- /// Returns `Ok(None)` if there is no SysV GNU hash section.
- /// Returns `Err` for invalid values.
- pub fn hash_header(
- &self,
- endian: Elf::Endian,
- data: R,
- ) -> read::Result<Option<&'data elf::HashHeader<Elf::Endian>>> {
- for section in self.sections {
- if let Some(hash) = section.hash_header(endian, data)? {
- return Ok(Some(hash));
- }
- }
- Ok(None)
- }
-
- /// Return the contents of a SysV hash section.
- ///
- /// Also returns the linked symbol table index.
- ///
- /// Returns `Ok(None)` if there is no SysV hash section.
- /// Returns `Err` for invalid values.
- pub fn hash(
- &self,
- endian: Elf::Endian,
- data: R,
- ) -> read::Result<Option<(HashTable<'data, Elf>, SectionIndex)>> {
- for section in self.sections {
- if let Some(hash) = section.hash(endian, data)? {
- return Ok(Some(hash));
- }
- }
- Ok(None)
- }
-
- /// Return the header of a GNU hash section.
- ///
- /// Returns `Ok(None)` if there is no GNU hash section.
- /// Returns `Err` for invalid values.
- pub fn gnu_hash_header(
- &self,
- endian: Elf::Endian,
- data: R,
- ) -> read::Result<Option<&'data elf::GnuHashHeader<Elf::Endian>>> {
- for section in self.sections {
- if let Some(hash) = section.gnu_hash_header(endian, data)? {
- return Ok(Some(hash));
- }
- }
- Ok(None)
- }
-
- /// Return the contents of a GNU hash section.
- ///
- /// Also returns the linked symbol table index.
- ///
- /// Returns `Ok(None)` if there is no GNU hash section.
- /// Returns `Err` for invalid values.
- pub fn gnu_hash(
- &self,
- endian: Elf::Endian,
- data: R,
- ) -> read::Result<Option<(GnuHashTable<'data, Elf>, SectionIndex)>> {
- for section in self.sections {
- if let Some(hash) = section.gnu_hash(endian, data)? {
- return Ok(Some(hash));
- }
- }
- Ok(None)
- }
-
- /// Return the contents of a `SHT_GNU_VERSYM` section.
- ///
- /// Also returns the linked symbol table index.
- ///
- /// Returns `Ok(None)` if there is no `SHT_GNU_VERSYM` section.
- /// Returns `Err` for invalid values.
- pub fn gnu_versym(
- &self,
- endian: Elf::Endian,
- data: R,
- ) -> read::Result<Option<(&'data [elf::Versym<Elf::Endian>], SectionIndex)>> {
- for section in self.sections {
- if let Some(syms) = section.gnu_versym(endian, data)? {
- return Ok(Some(syms));
- }
- }
- Ok(None)
- }
-
- /// Return the contents of a `SHT_GNU_VERDEF` section.
- ///
- /// Also returns the linked string table index.
- ///
- /// Returns `Ok(None)` if there is no `SHT_GNU_VERDEF` section.
- /// Returns `Err` for invalid values.
- pub fn gnu_verdef(
- &self,
- endian: Elf::Endian,
- data: R,
- ) -> read::Result<Option<(VerdefIterator<'data, Elf>, SectionIndex)>> {
- for section in self.sections {
- if let Some(defs) = section.gnu_verdef(endian, data)? {
- return Ok(Some(defs));
- }
- }
- Ok(None)
- }
-
- /// Return the contents of a `SHT_GNU_VERNEED` section.
- ///
- /// Also returns the linked string table index.
- ///
- /// Returns `Ok(None)` if there is no `SHT_GNU_VERNEED` section.
- /// Returns `Err` for invalid values.
- pub fn gnu_verneed(
- &self,
- endian: Elf::Endian,
- data: R,
- ) -> read::Result<Option<(VerneedIterator<'data, Elf>, SectionIndex)>> {
- for section in self.sections {
- if let Some(needs) = section.gnu_verneed(endian, data)? {
- return Ok(Some(needs));
- }
- }
- Ok(None)
- }
-
- /// Returns the symbol version table.
- ///
- /// Returns `Ok(None)` if there is no `SHT_GNU_VERSYM` section.
- /// Returns `Err` for invalid values.
- pub fn versions(
- &self,
- endian: Elf::Endian,
- data: R,
- ) -> read::Result<Option<VersionTable<'data, Elf>>> {
- let (versyms, link) = match self.gnu_versym(endian, data)? {
- Some(val) => val,
- None => return Ok(None),
- };
- let strings = self.symbol_table_by_index(endian, data, link)?.strings();
- // TODO: check links?
- let verdefs = self.gnu_verdef(endian, data)?.map(|x| x.0);
- let verneeds = self.gnu_verneed(endian, data)?.map(|x| x.0);
- VersionTable::parse(endian, versyms, verdefs, verneeds, strings).map(Some)
- }
-}
-
-/// An iterator for the sections in an [`ElfFile32`](super::ElfFile32).
-pub type ElfSectionIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
- ElfSectionIterator<'data, 'file, elf::FileHeader32<Endian>, R>;
-/// An iterator for the sections in an [`ElfFile64`](super::ElfFile64).
-pub type ElfSectionIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
- ElfSectionIterator<'data, 'file, elf::FileHeader64<Endian>, R>;
-
-/// An iterator for the sections in an [`ElfFile`].
-#[derive(Debug)]
-pub struct ElfSectionIterator<'data, 'file, Elf, R = &'data [u8]>
-where
- Elf: FileHeader,
- R: ReadRef<'data>,
-{
- pub(super) file: &'file ElfFile<'data, Elf, R>,
- pub(super) iter: iter::Enumerate<slice::Iter<'data, Elf::SectionHeader>>,
-}
-
-impl<'data, 'file, Elf, R> Iterator for ElfSectionIterator<'data, 'file, Elf, R>
-where
- Elf: FileHeader,
- R: ReadRef<'data>,
-{
- type Item = ElfSection<'data, 'file, Elf, R>;
-
- fn next(&mut self) -> Option<Self::Item> {
- self.iter.next().map(|(index, section)| ElfSection {
- index: SectionIndex(index),
- file: self.file,
- section,
- })
- }
-}
-
-/// A section in an [`ElfFile32`](super::ElfFile32).
-pub type ElfSection32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
- ElfSection<'data, 'file, elf::FileHeader32<Endian>, R>;
-/// A section in an [`ElfFile64`](super::ElfFile64).
-pub type ElfSection64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
- ElfSection<'data, 'file, elf::FileHeader64<Endian>, R>;
-
-/// A section in an [`ElfFile`].
-///
-/// Most functionality is provided by the [`ObjectSection`] trait implementation.
-#[derive(Debug)]
-pub struct ElfSection<'data, 'file, Elf, R = &'data [u8]>
-where
- Elf: FileHeader,
- R: ReadRef<'data>,
-{
- pub(super) file: &'file ElfFile<'data, Elf, R>,
- pub(super) index: SectionIndex,
- pub(super) section: &'data Elf::SectionHeader,
-}
-
-impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> ElfSection<'data, 'file, Elf, R> {
- fn bytes(&self) -> read::Result<&'data [u8]> {
- self.section
- .data(self.file.endian, self.file.data)
- .read_error("Invalid ELF section size or offset")
- }
-
- fn maybe_compressed(&self) -> read::Result<Option<CompressedFileRange>> {
- let endian = self.file.endian;
- if let Some((header, offset, compressed_size)) =
- self.section.compression(endian, self.file.data)?
- {
- let format = match header.ch_type(endian) {
- elf::ELFCOMPRESS_ZLIB => CompressionFormat::Zlib,
- elf::ELFCOMPRESS_ZSTD => CompressionFormat::Zstandard,
- _ => return Err(Error("Unsupported ELF compression type")),
- };
- let uncompressed_size = header.ch_size(endian).into();
- Ok(Some(CompressedFileRange {
- format,
- offset,
- compressed_size,
- uncompressed_size,
- }))
- } else {
- Ok(None)
- }
- }
-
- /// Try GNU-style "ZLIB" header decompression.
- fn maybe_compressed_gnu(&self) -> read::Result<Option<CompressedFileRange>> {
- let name = match self.name() {
- Ok(name) => name,
- // I think it's ok to ignore this error?
- Err(_) => return Ok(None),
- };
- if !name.starts_with(".zdebug_") {
- return Ok(None);
- }
- let (section_offset, section_size) = self
- .section
- .file_range(self.file.endian)
- .read_error("Invalid ELF GNU compressed section type")?;
- let mut offset = section_offset;
- let data = self.file.data;
- // Assume ZLIB-style uncompressed data is no more than 4GB to avoid accidentally
- // huge allocations. This also reduces the chance of accidentally matching on a
- // .debug_str that happens to start with "ZLIB".
- if data
- .read_bytes(&mut offset, 8)
- .read_error("ELF GNU compressed section is too short")?
- != b"ZLIB\0\0\0\0"
- {
- return Err(Error("Invalid ELF GNU compressed section header"));
- }
- let uncompressed_size = data
- .read::<U32Bytes<_>>(&mut offset)
- .read_error("ELF GNU compressed section is too short")?
- .get(endian::BigEndian)
- .into();
- let compressed_size = section_size
- .checked_sub(offset - section_offset)
- .read_error("ELF GNU compressed section is too short")?;
- Ok(Some(CompressedFileRange {
- format: CompressionFormat::Zlib,
- offset,
- compressed_size,
- uncompressed_size,
- }))
- }
-}
-
-impl<'data, 'file, Elf, R> read::private::Sealed for ElfSection<'data, 'file, Elf, R>
-where
- Elf: FileHeader,
- R: ReadRef<'data>,
-{
-}
-
-impl<'data, 'file, Elf, R> ObjectSection<'data> for ElfSection<'data, 'file, Elf, R>
-where
- Elf: FileHeader,
- R: ReadRef<'data>,
-{
- type RelocationIterator = ElfSectionRelocationIterator<'data, 'file, Elf, R>;
-
- #[inline]
- fn index(&self) -> SectionIndex {
- self.index
- }
-
- #[inline]
- fn address(&self) -> u64 {
- self.section.sh_addr(self.file.endian).into()
- }
-
- #[inline]
- fn size(&self) -> u64 {
- self.section.sh_size(self.file.endian).into()
- }
-
- #[inline]
- fn align(&self) -> u64 {
- self.section.sh_addralign(self.file.endian).into()
- }
-
- #[inline]
- fn file_range(&self) -> Option<(u64, u64)> {
- self.section.file_range(self.file.endian)
- }
-
- #[inline]
- fn data(&self) -> read::Result<&'data [u8]> {
- self.bytes()
- }
-
- fn data_range(&self, address: u64, size: u64) -> read::Result<Option<&'data [u8]>> {
- Ok(read::util::data_range(
- self.bytes()?,
- self.address(),
- address,
- size,
- ))
- }
-
- fn compressed_file_range(&self) -> read::Result<CompressedFileRange> {
- Ok(if let Some(data) = self.maybe_compressed()? {
- data
- } else if let Some(data) = self.maybe_compressed_gnu()? {
- data
- } else {
- CompressedFileRange::none(self.file_range())
- })
- }
-
- fn compressed_data(&self) -> read::Result<CompressedData<'data>> {
- self.compressed_file_range()?.data(self.file.data)
- }
-
- fn name_bytes(&self) -> read::Result<&[u8]> {
- self.file
- .sections
- .section_name(self.file.endian, self.section)
- }
-
- fn name(&self) -> read::Result<&str> {
- let name = self.name_bytes()?;
- str::from_utf8(name)
- .ok()
- .read_error("Non UTF-8 ELF section name")
- }
-
- #[inline]
- fn segment_name_bytes(&self) -> read::Result<Option<&[u8]>> {
- Ok(None)
- }
-
- #[inline]
- fn segment_name(&self) -> read::Result<Option<&str>> {
- Ok(None)
- }
-
- fn kind(&self) -> SectionKind {
- let flags = self.section.sh_flags(self.file.endian).into();
- let sh_type = self.section.sh_type(self.file.endian);
- match sh_type {
- elf::SHT_PROGBITS => {
- if flags & u64::from(elf::SHF_ALLOC) != 0 {
- if flags & u64::from(elf::SHF_EXECINSTR) != 0 {
- SectionKind::Text
- } else if flags & u64::from(elf::SHF_TLS) != 0 {
- SectionKind::Tls
- } else if flags & u64::from(elf::SHF_WRITE) != 0 {
- SectionKind::Data
- } else if flags & u64::from(elf::SHF_STRINGS) != 0 {
- SectionKind::ReadOnlyString
- } else {
- SectionKind::ReadOnlyData
- }
- } else if flags & u64::from(elf::SHF_STRINGS) != 0 {
- SectionKind::OtherString
- } else {
- SectionKind::Other
- }
- }
- elf::SHT_NOBITS => {
- if flags & u64::from(elf::SHF_TLS) != 0 {
- SectionKind::UninitializedTls
- } else {
- SectionKind::UninitializedData
- }
- }
- elf::SHT_NOTE => SectionKind::Note,
- elf::SHT_NULL
- | elf::SHT_SYMTAB
- | elf::SHT_STRTAB
- | elf::SHT_RELA
- | elf::SHT_HASH
- | elf::SHT_DYNAMIC
- | elf::SHT_REL
- | elf::SHT_DYNSYM
- | elf::SHT_GROUP => SectionKind::Metadata,
- _ => SectionKind::Elf(sh_type),
- }
- }
-
- fn relocations(&self) -> ElfSectionRelocationIterator<'data, 'file, Elf, R> {
- ElfSectionRelocationIterator {
- section_index: self.index,
- file: self.file,
- relocations: None,
- }
- }
-
- fn flags(&self) -> SectionFlags {
- SectionFlags::Elf {
- sh_flags: self.section.sh_flags(self.file.endian).into(),
- }
- }
-}
-
-/// A trait for generic access to [`elf::SectionHeader32`] and [`elf::SectionHeader64`].
-#[allow(missing_docs)]
-pub trait SectionHeader: Debug + Pod {
- type Elf: FileHeader<SectionHeader = Self, Endian = Self::Endian, Word = Self::Word>;
- type Word: Into<u64>;
- type Endian: endian::Endian;
-
- fn sh_name(&self, endian: Self::Endian) -> u32;
- fn sh_type(&self, endian: Self::Endian) -> u32;
- fn sh_flags(&self, endian: Self::Endian) -> Self::Word;
- fn sh_addr(&self, endian: Self::Endian) -> Self::Word;
- fn sh_offset(&self, endian: Self::Endian) -> Self::Word;
- fn sh_size(&self, endian: Self::Endian) -> Self::Word;
- fn sh_link(&self, endian: Self::Endian) -> u32;
- fn sh_info(&self, endian: Self::Endian) -> u32;
- fn sh_addralign(&self, endian: Self::Endian) -> Self::Word;
- fn sh_entsize(&self, endian: Self::Endian) -> Self::Word;
-
- /// Parse the section name from the string table.
- fn name<'data, R: ReadRef<'data>>(
- &self,
- endian: Self::Endian,
- strings: StringTable<'data, R>,
- ) -> read::Result<&'data [u8]> {
- strings
- .get(self.sh_name(endian))
- .read_error("Invalid ELF section name offset")
- }
-
- /// Return the offset and size of the section in the file.
- ///
- /// Returns `None` for sections that have no data in the file.
- fn file_range(&self, endian: Self::Endian) -> Option<(u64, u64)> {
- if self.sh_type(endian) == elf::SHT_NOBITS {
- None
- } else {
- Some((self.sh_offset(endian).into(), self.sh_size(endian).into()))
- }
- }
-
- /// Return the section data.
- ///
- /// Returns `Ok(&[])` if the section has no data.
- /// Returns `Err` for invalid values.
- fn data<'data, R: ReadRef<'data>>(
- &self,
- endian: Self::Endian,
- data: R,
- ) -> read::Result<&'data [u8]> {
- if let Some((offset, size)) = self.file_range(endian) {
- data.read_bytes_at(offset, size)
- .read_error("Invalid ELF section size or offset")
- } else {
- Ok(&[])
- }
- }
-
- /// Return the section data as a slice of the given type.
- ///
- /// Allows padding at the end of the data.
- /// Returns `Ok(&[])` if the section has no data.
- /// Returns `Err` for invalid values, including bad alignment.
- fn data_as_array<'data, T: Pod, R: ReadRef<'data>>(
- &self,
- endian: Self::Endian,
- data: R,
- ) -> read::Result<&'data [T]> {
- let mut data = self.data(endian, data).map(Bytes)?;
- data.read_slice(data.len() / mem::size_of::<T>())
- .read_error("Invalid ELF section size or offset")
- }
-
- /// Return the strings in the section.
- ///
- /// Returns `Ok(None)` if the section does not contain strings.
- /// Returns `Err` for invalid values.
- fn strings<'data, R: ReadRef<'data>>(
- &self,
- endian: Self::Endian,
- data: R,
- ) -> read::Result<Option<StringTable<'data, R>>> {
- if self.sh_type(endian) != elf::SHT_STRTAB {
- return Ok(None);
- }
- let str_offset = self.sh_offset(endian).into();
- let str_size = self.sh_size(endian).into();
- let str_end = str_offset
- .checked_add(str_size)
- .read_error("Invalid ELF string section offset or size")?;
- Ok(Some(StringTable::new(data, str_offset, str_end)))
- }
-
- /// Return the symbols in the section.
- ///
- /// Also finds the linked string table in `sections`.
- ///
- /// `section_index` must be the 0-based index of this section, and is used
- /// to find the corresponding extended section index table in `sections`.
- ///
- /// Returns `Ok(None)` if the section does not contain symbols.
- /// Returns `Err` for invalid values.
- fn symbols<'data, R: ReadRef<'data>>(
- &self,
- endian: Self::Endian,
- data: R,
- sections: &SectionTable<'data, Self::Elf, R>,
- section_index: SectionIndex,
- ) -> read::Result<Option<SymbolTable<'data, Self::Elf, R>>> {
- let sh_type = self.sh_type(endian);
- if sh_type != elf::SHT_SYMTAB && sh_type != elf::SHT_DYNSYM {
- return Ok(None);
- }
- SymbolTable::parse(endian, data, sections, section_index, self).map(Some)
- }
-
- /// Return the `Elf::Rel` entries in the section.
- ///
- /// Also returns the linked symbol table index.
- ///
- /// Returns `Ok(None)` if the section does not contain relocations.
- /// Returns `Err` for invalid values.
- fn rel<'data, R: ReadRef<'data>>(
- &self,
- endian: Self::Endian,
- data: R,
- ) -> read::Result<Option<(&'data [<Self::Elf as FileHeader>::Rel], SectionIndex)>> {
- if self.sh_type(endian) != elf::SHT_REL {
- return Ok(None);
- }
- let rel = self
- .data_as_array(endian, data)
- .read_error("Invalid ELF relocation section offset or size")?;
- let link = SectionIndex(self.sh_link(endian) as usize);
- Ok(Some((rel, link)))
- }
-
- /// Return the `Elf::Rela` entries in the section.
- ///
- /// Also returns the linked symbol table index.
- ///
- /// Returns `Ok(None)` if the section does not contain relocations.
- /// Returns `Err` for invalid values.
- fn rela<'data, R: ReadRef<'data>>(
- &self,
- endian: Self::Endian,
- data: R,
- ) -> read::Result<Option<(&'data [<Self::Elf as FileHeader>::Rela], SectionIndex)>> {
- if self.sh_type(endian) != elf::SHT_RELA {
- return Ok(None);
- }
- let rela = self
- .data_as_array(endian, data)
- .read_error("Invalid ELF relocation section offset or size")?;
- let link = SectionIndex(self.sh_link(endian) as usize);
- Ok(Some((rela, link)))
- }
-
- /// Return entries in a dynamic section.
- ///
- /// Also returns the linked string table index.
- ///
- /// Returns `Ok(None)` if the section type is not `SHT_DYNAMIC`.
- /// Returns `Err` for invalid values.
- fn dynamic<'data, R: ReadRef<'data>>(
- &self,
- endian: Self::Endian,
- data: R,
- ) -> read::Result<Option<(&'data [<Self::Elf as FileHeader>::Dyn], SectionIndex)>> {
- if self.sh_type(endian) != elf::SHT_DYNAMIC {
- return Ok(None);
- }
- let dynamic = self
- .data_as_array(endian, data)
- .read_error("Invalid ELF dynamic section offset or size")?;
- let link = SectionIndex(self.sh_link(endian) as usize);
- Ok(Some((dynamic, link)))
- }
-
- /// Return a note iterator for the section data.
- ///
- /// Returns `Ok(None)` if the section does not contain notes.
- /// Returns `Err` for invalid values.
- fn notes<'data, R: ReadRef<'data>>(
- &self,
- endian: Self::Endian,
- data: R,
- ) -> read::Result<Option<NoteIterator<'data, Self::Elf>>> {
- if self.sh_type(endian) != elf::SHT_NOTE {
- return Ok(None);
- }
- let data = self
- .data(endian, data)
- .read_error("Invalid ELF note section offset or size")?;
- let notes = NoteIterator::new(endian, self.sh_addralign(endian), data)?;
- Ok(Some(notes))
- }
-
- /// Return the contents of a group section.
- ///
- /// The first value is a `GRP_*` value, and the remaining values
- /// are section indices.
- ///
- /// Returns `Ok(None)` if the section does not define a group.
- /// Returns `Err` for invalid values.
- fn group<'data, R: ReadRef<'data>>(
- &self,
- endian: Self::Endian,
- data: R,
- ) -> read::Result<Option<(u32, &'data [U32Bytes<Self::Endian>])>> {
- if self.sh_type(endian) != elf::SHT_GROUP {
- return Ok(None);
- }
- let mut data = self
- .data(endian, data)
- .read_error("Invalid ELF group section offset or size")
- .map(Bytes)?;
- let flag = data
- .read::<U32Bytes<_>>()
- .read_error("Invalid ELF group section offset or size")?
- .get(endian);
- let count = data.len() / mem::size_of::<U32Bytes<Self::Endian>>();
- let sections = data
- .read_slice(count)
- .read_error("Invalid ELF group section offset or size")?;
- Ok(Some((flag, sections)))
- }
-
- /// Return the header of a SysV hash section.
- ///
- /// Returns `Ok(None)` if the section does not contain a SysV hash.
- /// Returns `Err` for invalid values.
- fn hash_header<'data, R: ReadRef<'data>>(
- &self,
- endian: Self::Endian,
- data: R,
- ) -> read::Result<Option<&'data elf::HashHeader<Self::Endian>>> {
- if self.sh_type(endian) != elf::SHT_HASH {
- return Ok(None);
- }
- let data = self
- .data(endian, data)
- .read_error("Invalid ELF hash section offset or size")?;
- let header = data
- .read_at::<elf::HashHeader<Self::Endian>>(0)
- .read_error("Invalid hash header")?;
- Ok(Some(header))
- }
-
- /// Return the contents of a SysV hash section.
- ///
- /// Also returns the linked symbol table index.
- ///
- /// Returns `Ok(None)` if the section does not contain a SysV hash.
- /// Returns `Err` for invalid values.
- fn hash<'data, R: ReadRef<'data>>(
- &self,
- endian: Self::Endian,
- data: R,
- ) -> read::Result<Option<(HashTable<'data, Self::Elf>, SectionIndex)>> {
- if self.sh_type(endian) != elf::SHT_HASH {
- return Ok(None);
- }
- let data = self
- .data(endian, data)
- .read_error("Invalid ELF hash section offset or size")?;
- let hash = HashTable::parse(endian, data)?;
- let link = SectionIndex(self.sh_link(endian) as usize);
- Ok(Some((hash, link)))
- }
-
- /// Return the header of a GNU hash section.
- ///
- /// Returns `Ok(None)` if the section does not contain a GNU hash.
- /// Returns `Err` for invalid values.
- fn gnu_hash_header<'data, R: ReadRef<'data>>(
- &self,
- endian: Self::Endian,
- data: R,
- ) -> read::Result<Option<&'data elf::GnuHashHeader<Self::Endian>>> {
- if self.sh_type(endian) != elf::SHT_GNU_HASH {
- return Ok(None);
- }
- let data = self
- .data(endian, data)
- .read_error("Invalid ELF GNU hash section offset or size")?;
- let header = data
- .read_at::<elf::GnuHashHeader<Self::Endian>>(0)
- .read_error("Invalid GNU hash header")?;
- Ok(Some(header))
- }
-
- /// Return the contents of a GNU hash section.
- ///
- /// Also returns the linked symbol table index.
- ///
- /// Returns `Ok(None)` if the section does not contain a GNU hash.
- /// Returns `Err` for invalid values.
- fn gnu_hash<'data, R: ReadRef<'data>>(
- &self,
- endian: Self::Endian,
- data: R,
- ) -> read::Result<Option<(GnuHashTable<'data, Self::Elf>, SectionIndex)>> {
- if self.sh_type(endian) != elf::SHT_GNU_HASH {
- return Ok(None);
- }
- let data = self
- .data(endian, data)
- .read_error("Invalid ELF GNU hash section offset or size")?;
- let hash = GnuHashTable::parse(endian, data)?;
- let link = SectionIndex(self.sh_link(endian) as usize);
- Ok(Some((hash, link)))
- }
-
- /// Return the contents of a `SHT_GNU_VERSYM` section.
- ///
- /// Also returns the linked symbol table index.
- ///
- /// Returns `Ok(None)` if the section type is not `SHT_GNU_VERSYM`.
- /// Returns `Err` for invalid values.
- fn gnu_versym<'data, R: ReadRef<'data>>(
- &self,
- endian: Self::Endian,
- data: R,
- ) -> read::Result<Option<(&'data [elf::Versym<Self::Endian>], SectionIndex)>> {
- if self.sh_type(endian) != elf::SHT_GNU_VERSYM {
- return Ok(None);
- }
- let versym = self
- .data_as_array(endian, data)
- .read_error("Invalid ELF GNU versym section offset or size")?;
- let link = SectionIndex(self.sh_link(endian) as usize);
- Ok(Some((versym, link)))
- }
-
- /// Return an iterator for the entries of a `SHT_GNU_VERDEF` section.
- ///
- /// Also returns the linked string table index.
- ///
- /// Returns `Ok(None)` if the section type is not `SHT_GNU_VERDEF`.
- /// Returns `Err` for invalid values.
- fn gnu_verdef<'data, R: ReadRef<'data>>(
- &self,
- endian: Self::Endian,
- data: R,
- ) -> read::Result<Option<(VerdefIterator<'data, Self::Elf>, SectionIndex)>> {
- if self.sh_type(endian) != elf::SHT_GNU_VERDEF {
- return Ok(None);
- }
- let verdef = self
- .data(endian, data)
- .read_error("Invalid ELF GNU verdef section offset or size")?;
- let link = SectionIndex(self.sh_link(endian) as usize);
- Ok(Some((VerdefIterator::new(endian, verdef), link)))
- }
-
- /// Return an iterator for the entries of a `SHT_GNU_VERNEED` section.
- ///
- /// Also returns the linked string table index.
- ///
- /// Returns `Ok(None)` if the section type is not `SHT_GNU_VERNEED`.
- /// Returns `Err` for invalid values.
- fn gnu_verneed<'data, R: ReadRef<'data>>(
- &self,
- endian: Self::Endian,
- data: R,
- ) -> read::Result<Option<(VerneedIterator<'data, Self::Elf>, SectionIndex)>> {
- if self.sh_type(endian) != elf::SHT_GNU_VERNEED {
- return Ok(None);
- }
- let verneed = self
- .data(endian, data)
- .read_error("Invalid ELF GNU verneed section offset or size")?;
- let link = SectionIndex(self.sh_link(endian) as usize);
- Ok(Some((VerneedIterator::new(endian, verneed), link)))
- }
-
- /// Return the contents of a `SHT_GNU_ATTRIBUTES` section.
- ///
- /// Returns `Ok(None)` if the section type is not `SHT_GNU_ATTRIBUTES`.
- /// Returns `Err` for invalid values.
- fn gnu_attributes<'data, R: ReadRef<'data>>(
- &self,
- endian: Self::Endian,
- data: R,
- ) -> read::Result<Option<AttributesSection<'data, Self::Elf>>> {
- if self.sh_type(endian) != elf::SHT_GNU_ATTRIBUTES {
- return Ok(None);
- }
- self.attributes(endian, data).map(Some)
- }
-
- /// Parse the contents of the section as attributes.
- ///
- /// This function does not check whether section type corresponds
- /// to a section that contains attributes.
- ///
- /// Returns `Err` for invalid values.
- fn attributes<'data, R: ReadRef<'data>>(
- &self,
- endian: Self::Endian,
- data: R,
- ) -> read::Result<AttributesSection<'data, Self::Elf>> {
- let data = self.data(endian, data)?;
- AttributesSection::new(endian, data)
- }
-
- /// Parse the compression header if present.
- ///
- /// Returns the header, and the offset and size of the compressed section data
- /// in the file.
- ///
- /// Returns `Ok(None)` if the section flags do not have `SHF_COMPRESSED`.
- /// Returns `Err` for invalid values.
- fn compression<'data, R: ReadRef<'data>>(
- &self,
- endian: Self::Endian,
- data: R,
- ) -> read::Result<
- Option<(
- &'data <Self::Elf as FileHeader>::CompressionHeader,
- u64,
- u64,
- )>,
- > {
- if (self.sh_flags(endian).into() & u64::from(elf::SHF_COMPRESSED)) == 0 {
- return Ok(None);
- }
- let (section_offset, section_size) = self
- .file_range(endian)
- .read_error("Invalid ELF compressed section type")?;
- let mut offset = section_offset;
- let header = data
- .read::<<Self::Elf as FileHeader>::CompressionHeader>(&mut offset)
- .read_error("Invalid ELF compressed section offset")?;
- let compressed_size = section_size
- .checked_sub(offset - section_offset)
- .read_error("Invalid ELF compressed section size")?;
- Ok(Some((header, offset, compressed_size)))
- }
-}
-
-impl<Endian: endian::Endian> SectionHeader for elf::SectionHeader32<Endian> {
- type Elf = elf::FileHeader32<Endian>;
- type Word = u32;
- type Endian = Endian;
-
- #[inline]
- fn sh_name(&self, endian: Self::Endian) -> u32 {
- self.sh_name.get(endian)
- }
-
- #[inline]
- fn sh_type(&self, endian: Self::Endian) -> u32 {
- self.sh_type.get(endian)
- }
-
- #[inline]
- fn sh_flags(&self, endian: Self::Endian) -> Self::Word {
- self.sh_flags.get(endian)
- }
-
- #[inline]
- fn sh_addr(&self, endian: Self::Endian) -> Self::Word {
- self.sh_addr.get(endian)
- }
-
- #[inline]
- fn sh_offset(&self, endian: Self::Endian) -> Self::Word {
- self.sh_offset.get(endian)
- }
-
- #[inline]
- fn sh_size(&self, endian: Self::Endian) -> Self::Word {
- self.sh_size.get(endian)
- }
-
- #[inline]
- fn sh_link(&self, endian: Self::Endian) -> u32 {
- self.sh_link.get(endian)
- }
-
- #[inline]
- fn sh_info(&self, endian: Self::Endian) -> u32 {
- self.sh_info.get(endian)
- }
-
- #[inline]
- fn sh_addralign(&self, endian: Self::Endian) -> Self::Word {
- self.sh_addralign.get(endian)
- }
-
- #[inline]
- fn sh_entsize(&self, endian: Self::Endian) -> Self::Word {
- self.sh_entsize.get(endian)
- }
-}
-
-impl<Endian: endian::Endian> SectionHeader for elf::SectionHeader64<Endian> {
- type Word = u64;
- type Endian = Endian;
- type Elf = elf::FileHeader64<Endian>;
-
- #[inline]
- fn sh_name(&self, endian: Self::Endian) -> u32 {
- self.sh_name.get(endian)
- }
-
- #[inline]
- fn sh_type(&self, endian: Self::Endian) -> u32 {
- self.sh_type.get(endian)
- }
-
- #[inline]
- fn sh_flags(&self, endian: Self::Endian) -> Self::Word {
- self.sh_flags.get(endian)
- }
-
- #[inline]
- fn sh_addr(&self, endian: Self::Endian) -> Self::Word {
- self.sh_addr.get(endian)
- }
-
- #[inline]
- fn sh_offset(&self, endian: Self::Endian) -> Self::Word {
- self.sh_offset.get(endian)
- }
-
- #[inline]
- fn sh_size(&self, endian: Self::Endian) -> Self::Word {
- self.sh_size.get(endian)
- }
-
- #[inline]
- fn sh_link(&self, endian: Self::Endian) -> u32 {
- self.sh_link.get(endian)
- }
-
- #[inline]
- fn sh_info(&self, endian: Self::Endian) -> u32 {
- self.sh_info.get(endian)
- }
-
- #[inline]
- fn sh_addralign(&self, endian: Self::Endian) -> Self::Word {
- self.sh_addralign.get(endian)
- }
-
- #[inline]
- fn sh_entsize(&self, endian: Self::Endian) -> Self::Word {
- self.sh_entsize.get(endian)
- }
-}
diff --git a/vendor/object/src/read/elf/segment.rs b/vendor/object/src/read/elf/segment.rs
deleted file mode 100644
index 957117a..0000000
--- a/vendor/object/src/read/elf/segment.rs
+++ /dev/null
@@ -1,334 +0,0 @@
-use core::fmt::Debug;
-use core::{mem, slice, str};
-
-use crate::elf;
-use crate::endian::{self, Endianness};
-use crate::pod::Pod;
-use crate::read::{self, Bytes, ObjectSegment, ReadError, ReadRef, SegmentFlags};
-
-use super::{ElfFile, FileHeader, NoteIterator};
-
-/// An iterator for the segments in an [`ElfFile32`](super::ElfFile32).
-pub type ElfSegmentIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
- ElfSegmentIterator<'data, 'file, elf::FileHeader32<Endian>, R>;
-/// An iterator for the segments in an [`ElfFile64`](super::ElfFile64).
-pub type ElfSegmentIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
- ElfSegmentIterator<'data, 'file, elf::FileHeader64<Endian>, R>;
-
-/// An iterator for the segments in an [`ElfFile`].
-#[derive(Debug)]
-pub struct ElfSegmentIterator<'data, 'file, Elf, R = &'data [u8]>
-where
- Elf: FileHeader,
- R: ReadRef<'data>,
-{
- pub(super) file: &'file ElfFile<'data, Elf, R>,
- pub(super) iter: slice::Iter<'data, Elf::ProgramHeader>,
-}
-
-impl<'data, 'file, Elf, R> Iterator for ElfSegmentIterator<'data, 'file, Elf, R>
-where
- Elf: FileHeader,
- R: ReadRef<'data>,
-{
- type Item = ElfSegment<'data, 'file, Elf, R>;
-
- fn next(&mut self) -> Option<Self::Item> {
- for segment in self.iter.by_ref() {
- if segment.p_type(self.file.endian) == elf::PT_LOAD {
- return Some(ElfSegment {
- file: self.file,
- segment,
- });
- }
- }
- None
- }
-}
-
-/// A segment in an [`ElfFile32`](super::ElfFile32).
-pub type ElfSegment32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
- ElfSegment<'data, 'file, elf::FileHeader32<Endian>, R>;
-/// A segment in an [`ElfFile64`](super::ElfFile64).
-pub type ElfSegment64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
- ElfSegment<'data, 'file, elf::FileHeader64<Endian>, R>;
-
-/// A segment in an [`ElfFile`].
-///
-/// Most functionality is provided by the [`ObjectSegment`] trait implementation.
-#[derive(Debug)]
-pub struct ElfSegment<'data, 'file, Elf, R = &'data [u8]>
-where
- Elf: FileHeader,
- R: ReadRef<'data>,
-{
- pub(super) file: &'file ElfFile<'data, Elf, R>,
- pub(super) segment: &'data Elf::ProgramHeader,
-}
-
-impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> ElfSegment<'data, 'file, Elf, R> {
- fn bytes(&self) -> read::Result<&'data [u8]> {
- self.segment
- .data(self.file.endian, self.file.data)
- .read_error("Invalid ELF segment size or offset")
- }
-}
-
-impl<'data, 'file, Elf, R> read::private::Sealed for ElfSegment<'data, 'file, Elf, R>
-where
- Elf: FileHeader,
- R: ReadRef<'data>,
-{
-}
-
-impl<'data, 'file, Elf, R> ObjectSegment<'data> for ElfSegment<'data, 'file, Elf, R>
-where
- Elf: FileHeader,
- R: ReadRef<'data>,
-{
- #[inline]
- fn address(&self) -> u64 {
- self.segment.p_vaddr(self.file.endian).into()
- }
-
- #[inline]
- fn size(&self) -> u64 {
- self.segment.p_memsz(self.file.endian).into()
- }
-
- #[inline]
- fn align(&self) -> u64 {
- self.segment.p_align(self.file.endian).into()
- }
-
- #[inline]
- fn file_range(&self) -> (u64, u64) {
- self.segment.file_range(self.file.endian)
- }
-
- #[inline]
- fn data(&self) -> read::Result<&'data [u8]> {
- self.bytes()
- }
-
- fn data_range(&self, address: u64, size: u64) -> read::Result<Option<&'data [u8]>> {
- Ok(read::util::data_range(
- self.bytes()?,
- self.address(),
- address,
- size,
- ))
- }
-
- #[inline]
- fn name_bytes(&self) -> read::Result<Option<&[u8]>> {
- Ok(None)
- }
-
- #[inline]
- fn name(&self) -> read::Result<Option<&str>> {
- Ok(None)
- }
-
- #[inline]
- fn flags(&self) -> SegmentFlags {
- let p_flags = self.segment.p_flags(self.file.endian);
- SegmentFlags::Elf { p_flags }
- }
-}
-
-/// A trait for generic access to [`elf::ProgramHeader32`] and [`elf::ProgramHeader64`].
-#[allow(missing_docs)]
-pub trait ProgramHeader: Debug + Pod {
- type Elf: FileHeader<ProgramHeader = Self, Endian = Self::Endian, Word = Self::Word>;
- type Word: Into<u64>;
- type Endian: endian::Endian;
-
- fn p_type(&self, endian: Self::Endian) -> u32;
- fn p_flags(&self, endian: Self::Endian) -> u32;
- fn p_offset(&self, endian: Self::Endian) -> Self::Word;
- fn p_vaddr(&self, endian: Self::Endian) -> Self::Word;
- fn p_paddr(&self, endian: Self::Endian) -> Self::Word;
- fn p_filesz(&self, endian: Self::Endian) -> Self::Word;
- fn p_memsz(&self, endian: Self::Endian) -> Self::Word;
- fn p_align(&self, endian: Self::Endian) -> Self::Word;
-
- /// Return the offset and size of the segment in the file.
- fn file_range(&self, endian: Self::Endian) -> (u64, u64) {
- (self.p_offset(endian).into(), self.p_filesz(endian).into())
- }
-
- /// Return the segment data.
- ///
- /// Returns `Err` for invalid values.
- fn data<'data, R: ReadRef<'data>>(
- &self,
- endian: Self::Endian,
- data: R,
- ) -> Result<&'data [u8], ()> {
- let (offset, size) = self.file_range(endian);
- data.read_bytes_at(offset, size)
- }
-
- /// Return the segment data as a slice of the given type.
- ///
- /// Allows padding at the end of the data.
- /// Returns `Ok(&[])` if the segment has no data.
- /// Returns `Err` for invalid values, including bad alignment.
- fn data_as_array<'data, T: Pod, R: ReadRef<'data>>(
- &self,
- endian: Self::Endian,
- data: R,
- ) -> Result<&'data [T], ()> {
- let mut data = self.data(endian, data).map(Bytes)?;
- data.read_slice(data.len() / mem::size_of::<T>())
- }
-
- /// Return the segment data in the given virtual address range
- ///
- /// Returns `Ok(None)` if the segment does not contain the address.
- /// Returns `Err` for invalid values.
- fn data_range<'data, R: ReadRef<'data>>(
- &self,
- endian: Self::Endian,
- data: R,
- address: u64,
- size: u64,
- ) -> Result<Option<&'data [u8]>, ()> {
- Ok(read::util::data_range(
- self.data(endian, data)?,
- self.p_vaddr(endian).into(),
- address,
- size,
- ))
- }
-
- /// Return entries in a dynamic segment.
- ///
- /// Returns `Ok(None)` if the segment is not `PT_DYNAMIC`.
- /// Returns `Err` for invalid values.
- fn dynamic<'data, R: ReadRef<'data>>(
- &self,
- endian: Self::Endian,
- data: R,
- ) -> read::Result<Option<&'data [<Self::Elf as FileHeader>::Dyn]>> {
- if self.p_type(endian) != elf::PT_DYNAMIC {
- return Ok(None);
- }
- let dynamic = self
- .data_as_array(endian, data)
- .read_error("Invalid ELF dynamic segment offset or size")?;
- Ok(Some(dynamic))
- }
-
- /// Return a note iterator for the segment data.
- ///
- /// Returns `Ok(None)` if the segment does not contain notes.
- /// Returns `Err` for invalid values.
- fn notes<'data, R: ReadRef<'data>>(
- &self,
- endian: Self::Endian,
- data: R,
- ) -> read::Result<Option<NoteIterator<'data, Self::Elf>>> {
- if self.p_type(endian) != elf::PT_NOTE {
- return Ok(None);
- }
- let data = self
- .data(endian, data)
- .read_error("Invalid ELF note segment offset or size")?;
- let notes = NoteIterator::new(endian, self.p_align(endian), data)?;
- Ok(Some(notes))
- }
-}
-
-impl<Endian: endian::Endian> ProgramHeader for elf::ProgramHeader32<Endian> {
- type Word = u32;
- type Endian = Endian;
- type Elf = elf::FileHeader32<Endian>;
-
- #[inline]
- fn p_type(&self, endian: Self::Endian) -> u32 {
- self.p_type.get(endian)
- }
-
- #[inline]
- fn p_flags(&self, endian: Self::Endian) -> u32 {
- self.p_flags.get(endian)
- }
-
- #[inline]
- fn p_offset(&self, endian: Self::Endian) -> Self::Word {
- self.p_offset.get(endian)
- }
-
- #[inline]
- fn p_vaddr(&self, endian: Self::Endian) -> Self::Word {
- self.p_vaddr.get(endian)
- }
-
- #[inline]
- fn p_paddr(&self, endian: Self::Endian) -> Self::Word {
- self.p_paddr.get(endian)
- }
-
- #[inline]
- fn p_filesz(&self, endian: Self::Endian) -> Self::Word {
- self.p_filesz.get(endian)
- }
-
- #[inline]
- fn p_memsz(&self, endian: Self::Endian) -> Self::Word {
- self.p_memsz.get(endian)
- }
-
- #[inline]
- fn p_align(&self, endian: Self::Endian) -> Self::Word {
- self.p_align.get(endian)
- }
-}
-
-impl<Endian: endian::Endian> ProgramHeader for elf::ProgramHeader64<Endian> {
- type Word = u64;
- type Endian = Endian;
- type Elf = elf::FileHeader64<Endian>;
-
- #[inline]
- fn p_type(&self, endian: Self::Endian) -> u32 {
- self.p_type.get(endian)
- }
-
- #[inline]
- fn p_flags(&self, endian: Self::Endian) -> u32 {
- self.p_flags.get(endian)
- }
-
- #[inline]
- fn p_offset(&self, endian: Self::Endian) -> Self::Word {
- self.p_offset.get(endian)
- }
-
- #[inline]
- fn p_vaddr(&self, endian: Self::Endian) -> Self::Word {
- self.p_vaddr.get(endian)
- }
-
- #[inline]
- fn p_paddr(&self, endian: Self::Endian) -> Self::Word {
- self.p_paddr.get(endian)
- }
-
- #[inline]
- fn p_filesz(&self, endian: Self::Endian) -> Self::Word {
- self.p_filesz.get(endian)
- }
-
- #[inline]
- fn p_memsz(&self, endian: Self::Endian) -> Self::Word {
- self.p_memsz.get(endian)
- }
-
- #[inline]
- fn p_align(&self, endian: Self::Endian) -> Self::Word {
- self.p_align.get(endian)
- }
-}
diff --git a/vendor/object/src/read/elf/symbol.rs b/vendor/object/src/read/elf/symbol.rs
deleted file mode 100644
index 8ba707f..0000000
--- a/vendor/object/src/read/elf/symbol.rs
+++ /dev/null
@@ -1,595 +0,0 @@
-use alloc::fmt;
-use alloc::vec::Vec;
-use core::fmt::Debug;
-use core::slice;
-use core::str;
-
-use crate::endian::{self, Endianness};
-use crate::pod::Pod;
-use crate::read::util::StringTable;
-use crate::read::{
- self, ObjectSymbol, ObjectSymbolTable, ReadError, ReadRef, SectionIndex, SymbolFlags,
- SymbolIndex, SymbolKind, SymbolMap, SymbolMapEntry, SymbolScope, SymbolSection,
-};
-use crate::{elf, U32};
-
-use super::{FileHeader, SectionHeader, SectionTable};
-
-/// A table of symbol entries in an ELF file.
-///
-/// Also includes the string table used for the symbol names.
-///
-/// Returned by [`SectionTable::symbols`].
-#[derive(Debug, Clone, Copy)]
-pub struct SymbolTable<'data, Elf: FileHeader, R = &'data [u8]>
-where
- R: ReadRef<'data>,
-{
- section: SectionIndex,
- string_section: SectionIndex,
- shndx_section: SectionIndex,
- symbols: &'data [Elf::Sym],
- strings: StringTable<'data, R>,
- shndx: &'data [U32<Elf::Endian>],
-}
-
-impl<'data, Elf: FileHeader, R: ReadRef<'data>> Default for SymbolTable<'data, Elf, R> {
- fn default() -> Self {
- SymbolTable {
- section: SectionIndex(0),
- string_section: SectionIndex(0),
- shndx_section: SectionIndex(0),
- symbols: &[],
- strings: Default::default(),
- shndx: &[],
- }
- }
-}
-
-impl<'data, Elf: FileHeader, R: ReadRef<'data>> SymbolTable<'data, Elf, R> {
- /// Parse the given symbol table section.
- pub fn parse(
- endian: Elf::Endian,
- data: R,
- sections: &SectionTable<'data, Elf, R>,
- section_index: SectionIndex,
- section: &Elf::SectionHeader,
- ) -> read::Result<SymbolTable<'data, Elf, R>> {
- debug_assert!(
- section.sh_type(endian) == elf::SHT_DYNSYM
- || section.sh_type(endian) == elf::SHT_SYMTAB
- );
-
- let symbols = section
- .data_as_array(endian, data)
- .read_error("Invalid ELF symbol table data")?;
-
- let link = SectionIndex(section.sh_link(endian) as usize);
- let strings = sections.strings(endian, data, link)?;
-
- let mut shndx_section = SectionIndex(0);
- let mut shndx = &[][..];
- for (i, s) in sections.iter().enumerate() {
- if s.sh_type(endian) == elf::SHT_SYMTAB_SHNDX
- && s.sh_link(endian) as usize == section_index.0
- {
- shndx_section = SectionIndex(i);
- shndx = s
- .data_as_array(endian, data)
- .read_error("Invalid ELF symtab_shndx data")?;
- }
- }
-
- Ok(SymbolTable {
- section: section_index,
- string_section: link,
- symbols,
- strings,
- shndx,
- shndx_section,
- })
- }
-
- /// Return the section index of this symbol table.
- #[inline]
- pub fn section(&self) -> SectionIndex {
- self.section
- }
-
- /// Return the section index of the shndx table.
- #[inline]
- pub fn shndx_section(&self) -> SectionIndex {
- self.shndx_section
- }
-
- /// Return the section index of the linked string table.
- #[inline]
- pub fn string_section(&self) -> SectionIndex {
- self.string_section
- }
-
- /// Return the string table used for the symbol names.
- #[inline]
- pub fn strings(&self) -> StringTable<'data, R> {
- self.strings
- }
-
- /// Return the symbol table.
- #[inline]
- pub fn symbols(&self) -> &'data [Elf::Sym] {
- self.symbols
- }
-
- /// Iterate over the symbols.
- #[inline]
- pub fn iter(&self) -> slice::Iter<'data, Elf::Sym> {
- self.symbols.iter()
- }
-
- /// Return true if the symbol table is empty.
- #[inline]
- pub fn is_empty(&self) -> bool {
- self.symbols.is_empty()
- }
-
- /// The number of symbols.
- #[inline]
- pub fn len(&self) -> usize {
- self.symbols.len()
- }
-
- /// Return the symbol at the given index.
- pub fn symbol(&self, index: usize) -> read::Result<&'data Elf::Sym> {
- self.symbols
- .get(index)
- .read_error("Invalid ELF symbol index")
- }
-
- /// Return the extended section index for the given symbol if present.
- #[inline]
- pub fn shndx(&self, endian: Elf::Endian, index: usize) -> Option<u32> {
- self.shndx.get(index).map(|x| x.get(endian))
- }
-
- /// Return the section index for the given symbol.
- ///
- /// This uses the extended section index if present.
- pub fn symbol_section(
- &self,
- endian: Elf::Endian,
- symbol: &'data Elf::Sym,
- index: usize,
- ) -> read::Result<Option<SectionIndex>> {
- match symbol.st_shndx(endian) {
- elf::SHN_UNDEF => Ok(None),
- elf::SHN_XINDEX => self
- .shndx(endian, index)
- .read_error("Missing ELF symbol extended index")
- .map(|index| Some(SectionIndex(index as usize))),
- shndx if shndx < elf::SHN_LORESERVE => Ok(Some(SectionIndex(shndx.into()))),
- _ => Ok(None),
- }
- }
-
- /// Return the symbol name for the given symbol.
- pub fn symbol_name(
- &self,
- endian: Elf::Endian,
- symbol: &'data Elf::Sym,
- ) -> read::Result<&'data [u8]> {
- symbol.name(endian, self.strings)
- }
-
- /// Construct a map from addresses to a user-defined map entry.
- pub fn map<Entry: SymbolMapEntry, F: Fn(&'data Elf::Sym) -> Option<Entry>>(
- &self,
- endian: Elf::Endian,
- f: F,
- ) -> SymbolMap<Entry> {
- let mut symbols = Vec::with_capacity(self.symbols.len());
- for symbol in self.symbols {
- if !symbol.is_definition(endian) {
- continue;
- }
- if let Some(entry) = f(symbol) {
- symbols.push(entry);
- }
- }
- SymbolMap::new(symbols)
- }
-}
-
-/// A symbol table in an [`ElfFile32`](super::ElfFile32).
-pub type ElfSymbolTable32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
- ElfSymbolTable<'data, 'file, elf::FileHeader32<Endian>, R>;
-/// A symbol table in an [`ElfFile32`](super::ElfFile32).
-pub type ElfSymbolTable64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
- ElfSymbolTable<'data, 'file, elf::FileHeader64<Endian>, R>;
-
-/// A symbol table in an [`ElfFile`](super::ElfFile).
-#[derive(Debug, Clone, Copy)]
-pub struct ElfSymbolTable<'data, 'file, Elf, R = &'data [u8]>
-where
- Elf: FileHeader,
- R: ReadRef<'data>,
-{
- pub(super) endian: Elf::Endian,
- pub(super) symbols: &'file SymbolTable<'data, Elf, R>,
-}
-
-impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> read::private::Sealed
- for ElfSymbolTable<'data, 'file, Elf, R>
-{
-}
-
-impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> ObjectSymbolTable<'data>
- for ElfSymbolTable<'data, 'file, Elf, R>
-{
- type Symbol = ElfSymbol<'data, 'file, Elf, R>;
- type SymbolIterator = ElfSymbolIterator<'data, 'file, Elf, R>;
-
- fn symbols(&self) -> Self::SymbolIterator {
- ElfSymbolIterator {
- endian: self.endian,
- symbols: self.symbols,
- index: 0,
- }
- }
-
- fn symbol_by_index(&self, index: SymbolIndex) -> read::Result<Self::Symbol> {
- let symbol = self.symbols.symbol(index.0)?;
- Ok(ElfSymbol {
- endian: self.endian,
- symbols: self.symbols,
- index,
- symbol,
- })
- }
-}
-
-/// An iterator for the symbols in an [`ElfFile32`](super::ElfFile32).
-pub type ElfSymbolIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
- ElfSymbolIterator<'data, 'file, elf::FileHeader32<Endian>, R>;
-/// An iterator for the symbols in an [`ElfFile64`](super::ElfFile64).
-pub type ElfSymbolIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
- ElfSymbolIterator<'data, 'file, elf::FileHeader64<Endian>, R>;
-
-/// An iterator for the symbols in an [`ElfFile`](super::ElfFile).
-pub struct ElfSymbolIterator<'data, 'file, Elf, R = &'data [u8]>
-where
- Elf: FileHeader,
- R: ReadRef<'data>,
-{
- pub(super) endian: Elf::Endian,
- pub(super) symbols: &'file SymbolTable<'data, Elf, R>,
- pub(super) index: usize,
-}
-
-impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> fmt::Debug
- for ElfSymbolIterator<'data, 'file, Elf, R>
-{
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("ElfSymbolIterator").finish()
- }
-}
-
-impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> Iterator
- for ElfSymbolIterator<'data, 'file, Elf, R>
-{
- type Item = ElfSymbol<'data, 'file, Elf, R>;
-
- fn next(&mut self) -> Option<Self::Item> {
- let index = self.index;
- let symbol = self.symbols.symbols.get(index)?;
- self.index += 1;
- Some(ElfSymbol {
- endian: self.endian,
- symbols: self.symbols,
- index: SymbolIndex(index),
- symbol,
- })
- }
-}
-
-/// A symbol in an [`ElfFile32`](super::ElfFile32).
-pub type ElfSymbol32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
- ElfSymbol<'data, 'file, elf::FileHeader32<Endian>, R>;
-/// A symbol in an [`ElfFile64`](super::ElfFile64).
-pub type ElfSymbol64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
- ElfSymbol<'data, 'file, elf::FileHeader64<Endian>, R>;
-
-/// A symbol in an [`ElfFile`](super::ElfFile).
-///
-/// Most functionality is provided by the [`ObjectSymbol`] trait implementation.
-#[derive(Debug, Clone, Copy)]
-pub struct ElfSymbol<'data, 'file, Elf, R = &'data [u8]>
-where
- Elf: FileHeader,
- R: ReadRef<'data>,
-{
- pub(super) endian: Elf::Endian,
- pub(super) symbols: &'file SymbolTable<'data, Elf, R>,
- pub(super) index: SymbolIndex,
- pub(super) symbol: &'data Elf::Sym,
-}
-
-impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> ElfSymbol<'data, 'file, Elf, R> {
- /// Return a reference to the raw symbol structure.
- #[inline]
- pub fn raw_symbol(&self) -> &'data Elf::Sym {
- self.symbol
- }
-}
-
-impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> read::private::Sealed
- for ElfSymbol<'data, 'file, Elf, R>
-{
-}
-
-impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> ObjectSymbol<'data>
- for ElfSymbol<'data, 'file, Elf, R>
-{
- #[inline]
- fn index(&self) -> SymbolIndex {
- self.index
- }
-
- fn name_bytes(&self) -> read::Result<&'data [u8]> {
- self.symbol.name(self.endian, self.symbols.strings())
- }
-
- fn name(&self) -> read::Result<&'data str> {
- let name = self.name_bytes()?;
- str::from_utf8(name)
- .ok()
- .read_error("Non UTF-8 ELF symbol name")
- }
-
- #[inline]
- fn address(&self) -> u64 {
- self.symbol.st_value(self.endian).into()
- }
-
- #[inline]
- fn size(&self) -> u64 {
- self.symbol.st_size(self.endian).into()
- }
-
- fn kind(&self) -> SymbolKind {
- match self.symbol.st_type() {
- elf::STT_NOTYPE if self.index.0 == 0 => SymbolKind::Null,
- elf::STT_NOTYPE => SymbolKind::Unknown,
- elf::STT_OBJECT | elf::STT_COMMON => SymbolKind::Data,
- elf::STT_FUNC | elf::STT_GNU_IFUNC => SymbolKind::Text,
- elf::STT_SECTION => SymbolKind::Section,
- elf::STT_FILE => SymbolKind::File,
- elf::STT_TLS => SymbolKind::Tls,
- _ => SymbolKind::Unknown,
- }
- }
-
- fn section(&self) -> SymbolSection {
- match self.symbol.st_shndx(self.endian) {
- elf::SHN_UNDEF => SymbolSection::Undefined,
- elf::SHN_ABS => {
- if self.symbol.st_type() == elf::STT_FILE {
- SymbolSection::None
- } else {
- SymbolSection::Absolute
- }
- }
- elf::SHN_COMMON => SymbolSection::Common,
- elf::SHN_XINDEX => match self.symbols.shndx(self.endian, self.index.0) {
- Some(index) => SymbolSection::Section(SectionIndex(index as usize)),
- None => SymbolSection::Unknown,
- },
- index if index < elf::SHN_LORESERVE => {
- SymbolSection::Section(SectionIndex(index as usize))
- }
- _ => SymbolSection::Unknown,
- }
- }
-
- #[inline]
- fn is_undefined(&self) -> bool {
- self.symbol.st_shndx(self.endian) == elf::SHN_UNDEF
- }
-
- #[inline]
- fn is_definition(&self) -> bool {
- self.symbol.is_definition(self.endian)
- }
-
- #[inline]
- fn is_common(&self) -> bool {
- self.symbol.st_shndx(self.endian) == elf::SHN_COMMON
- }
-
- #[inline]
- fn is_weak(&self) -> bool {
- self.symbol.st_bind() == elf::STB_WEAK
- }
-
- fn scope(&self) -> SymbolScope {
- if self.symbol.st_shndx(self.endian) == elf::SHN_UNDEF {
- SymbolScope::Unknown
- } else {
- match self.symbol.st_bind() {
- elf::STB_LOCAL => SymbolScope::Compilation,
- elf::STB_GLOBAL | elf::STB_WEAK => {
- if self.symbol.st_visibility() == elf::STV_HIDDEN {
- SymbolScope::Linkage
- } else {
- SymbolScope::Dynamic
- }
- }
- _ => SymbolScope::Unknown,
- }
- }
- }
-
- #[inline]
- fn is_global(&self) -> bool {
- self.symbol.st_bind() != elf::STB_LOCAL
- }
-
- #[inline]
- fn is_local(&self) -> bool {
- self.symbol.st_bind() == elf::STB_LOCAL
- }
-
- #[inline]
- fn flags(&self) -> SymbolFlags<SectionIndex, SymbolIndex> {
- SymbolFlags::Elf {
- st_info: self.symbol.st_info(),
- st_other: self.symbol.st_other(),
- }
- }
-}
-
-/// A trait for generic access to [`elf::Sym32`] and [`elf::Sym64`].
-#[allow(missing_docs)]
-pub trait Sym: Debug + Pod {
- type Word: Into<u64>;
- type Endian: endian::Endian;
-
- fn st_name(&self, endian: Self::Endian) -> u32;
- fn st_info(&self) -> u8;
- fn st_bind(&self) -> u8;
- fn st_type(&self) -> u8;
- fn st_other(&self) -> u8;
- fn st_visibility(&self) -> u8;
- fn st_shndx(&self, endian: Self::Endian) -> u16;
- fn st_value(&self, endian: Self::Endian) -> Self::Word;
- fn st_size(&self, endian: Self::Endian) -> Self::Word;
-
- /// Parse the symbol name from the string table.
- fn name<'data, R: ReadRef<'data>>(
- &self,
- endian: Self::Endian,
- strings: StringTable<'data, R>,
- ) -> read::Result<&'data [u8]> {
- strings
- .get(self.st_name(endian))
- .read_error("Invalid ELF symbol name offset")
- }
-
- /// Return true if the symbol is undefined.
- #[inline]
- fn is_undefined(&self, endian: Self::Endian) -> bool {
- self.st_shndx(endian) == elf::SHN_UNDEF
- }
-
- /// Return true if the symbol is a definition of a function or data object.
- fn is_definition(&self, endian: Self::Endian) -> bool {
- let shndx = self.st_shndx(endian);
- if shndx == elf::SHN_UNDEF || (shndx >= elf::SHN_LORESERVE && shndx != elf::SHN_XINDEX) {
- return false;
- }
- match self.st_type() {
- elf::STT_NOTYPE => self.st_size(endian).into() != 0,
- elf::STT_FUNC | elf::STT_OBJECT => true,
- _ => false,
- }
- }
-}
-
-impl<Endian: endian::Endian> Sym for elf::Sym32<Endian> {
- type Word = u32;
- type Endian = Endian;
-
- #[inline]
- fn st_name(&self, endian: Self::Endian) -> u32 {
- self.st_name.get(endian)
- }
-
- #[inline]
- fn st_info(&self) -> u8 {
- self.st_info
- }
-
- #[inline]
- fn st_bind(&self) -> u8 {
- self.st_bind()
- }
-
- #[inline]
- fn st_type(&self) -> u8 {
- self.st_type()
- }
-
- #[inline]
- fn st_other(&self) -> u8 {
- self.st_other
- }
-
- #[inline]
- fn st_visibility(&self) -> u8 {
- self.st_visibility()
- }
-
- #[inline]
- fn st_shndx(&self, endian: Self::Endian) -> u16 {
- self.st_shndx.get(endian)
- }
-
- #[inline]
- fn st_value(&self, endian: Self::Endian) -> Self::Word {
- self.st_value.get(endian)
- }
-
- #[inline]
- fn st_size(&self, endian: Self::Endian) -> Self::Word {
- self.st_size.get(endian)
- }
-}
-
-impl<Endian: endian::Endian> Sym for elf::Sym64<Endian> {
- type Word = u64;
- type Endian = Endian;
-
- #[inline]
- fn st_name(&self, endian: Self::Endian) -> u32 {
- self.st_name.get(endian)
- }
-
- #[inline]
- fn st_info(&self) -> u8 {
- self.st_info
- }
-
- #[inline]
- fn st_bind(&self) -> u8 {
- self.st_bind()
- }
-
- #[inline]
- fn st_type(&self) -> u8 {
- self.st_type()
- }
-
- #[inline]
- fn st_other(&self) -> u8 {
- self.st_other
- }
-
- #[inline]
- fn st_visibility(&self) -> u8 {
- self.st_visibility()
- }
-
- #[inline]
- fn st_shndx(&self, endian: Self::Endian) -> u16 {
- self.st_shndx.get(endian)
- }
-
- #[inline]
- fn st_value(&self, endian: Self::Endian) -> Self::Word {
- self.st_value.get(endian)
- }
-
- #[inline]
- fn st_size(&self, endian: Self::Endian) -> Self::Word {
- self.st_size.get(endian)
- }
-}
diff --git a/vendor/object/src/read/elf/version.rs b/vendor/object/src/read/elf/version.rs
deleted file mode 100644
index 28eeed0..0000000
--- a/vendor/object/src/read/elf/version.rs
+++ /dev/null
@@ -1,424 +0,0 @@
-use alloc::vec::Vec;
-
-use crate::read::{Bytes, ReadError, ReadRef, Result, StringTable};
-use crate::{elf, endian};
-
-use super::FileHeader;
-
-/// A version index.
-#[derive(Debug, Default, Clone, Copy)]
-pub struct VersionIndex(pub u16);
-
-impl VersionIndex {
- /// Return the version index.
- pub fn index(&self) -> u16 {
- self.0 & elf::VERSYM_VERSION
- }
-
- /// Return true if it is the local index.
- pub fn is_local(&self) -> bool {
- self.index() == elf::VER_NDX_LOCAL
- }
-
- /// Return true if it is the global index.
- pub fn is_global(&self) -> bool {
- self.index() == elf::VER_NDX_GLOBAL
- }
-
- /// Return the hidden flag.
- pub fn is_hidden(&self) -> bool {
- self.0 & elf::VERSYM_HIDDEN != 0
- }
-}
-
-/// A version definition or requirement.
-///
-/// This is derived from entries in the [`elf::SHT_GNU_VERDEF`] and [`elf::SHT_GNU_VERNEED`] sections.
-#[derive(Debug, Default, Clone, Copy)]
-pub struct Version<'data> {
- name: &'data [u8],
- hash: u32,
- // Used to keep track of valid indices in `VersionTable`.
- valid: bool,
-}
-
-impl<'data> Version<'data> {
- /// Return the version name.
- pub fn name(&self) -> &'data [u8] {
- self.name
- }
-
- /// Return hash of the version name.
- pub fn hash(&self) -> u32 {
- self.hash
- }
-}
-
-/// A table of version definitions and requirements.
-///
-/// It allows looking up the version information for a given symbol index.
-///
-/// This is derived from entries in the [`elf::SHT_GNU_VERSYM`], [`elf::SHT_GNU_VERDEF`]
-/// and [`elf::SHT_GNU_VERNEED`] sections.
-///
-/// Returned by [`SectionTable::versions`](super::SectionTable::versions).
-#[derive(Debug, Clone)]
-pub struct VersionTable<'data, Elf: FileHeader> {
- symbols: &'data [elf::Versym<Elf::Endian>],
- versions: Vec<Version<'data>>,
-}
-
-impl<'data, Elf: FileHeader> Default for VersionTable<'data, Elf> {
- fn default() -> Self {
- VersionTable {
- symbols: &[],
- versions: Vec::new(),
- }
- }
-}
-
-impl<'data, Elf: FileHeader> VersionTable<'data, Elf> {
- /// Parse the version sections.
- pub fn parse<R: ReadRef<'data>>(
- endian: Elf::Endian,
- versyms: &'data [elf::Versym<Elf::Endian>],
- verdefs: Option<VerdefIterator<'data, Elf>>,
- verneeds: Option<VerneedIterator<'data, Elf>>,
- strings: StringTable<'data, R>,
- ) -> Result<Self> {
- let mut max_index = 0;
- if let Some(mut verdefs) = verdefs.clone() {
- while let Some((verdef, _)) = verdefs.next()? {
- if verdef.vd_flags.get(endian) & elf::VER_FLG_BASE != 0 {
- continue;
- }
- let index = verdef.vd_ndx.get(endian) & elf::VERSYM_VERSION;
- if max_index < index {
- max_index = index;
- }
- }
- }
- if let Some(mut verneeds) = verneeds.clone() {
- while let Some((_, mut vernauxs)) = verneeds.next()? {
- while let Some(vernaux) = vernauxs.next()? {
- let index = vernaux.vna_other.get(endian) & elf::VERSYM_VERSION;
- if max_index < index {
- max_index = index;
- }
- }
- }
- }
-
- // Indices should be sequential, but this could be up to
- // 32k * size_of::<Version>() if max_index is bad.
- let mut versions = vec![Version::default(); max_index as usize + 1];
-
- if let Some(mut verdefs) = verdefs {
- while let Some((verdef, mut verdauxs)) = verdefs.next()? {
- if verdef.vd_flags.get(endian) & elf::VER_FLG_BASE != 0 {
- continue;
- }
- let index = verdef.vd_ndx.get(endian) & elf::VERSYM_VERSION;
- if index <= elf::VER_NDX_GLOBAL {
- // TODO: return error?
- continue;
- }
- if let Some(verdaux) = verdauxs.next()? {
- versions[usize::from(index)] = Version {
- name: verdaux.name(endian, strings)?,
- hash: verdef.vd_hash.get(endian),
- valid: true,
- };
- }
- }
- }
- if let Some(mut verneeds) = verneeds {
- while let Some((_, mut vernauxs)) = verneeds.next()? {
- while let Some(vernaux) = vernauxs.next()? {
- let index = vernaux.vna_other.get(endian) & elf::VERSYM_VERSION;
- if index <= elf::VER_NDX_GLOBAL {
- // TODO: return error?
- continue;
- }
- versions[usize::from(index)] = Version {
- name: vernaux.name(endian, strings)?,
- hash: vernaux.vna_hash.get(endian),
- valid: true,
- };
- }
- }
- }
-
- Ok(VersionTable {
- symbols: versyms,
- versions,
- })
- }
-
- /// Return true if the version table is empty.
- pub fn is_empty(&self) -> bool {
- self.symbols.is_empty()
- }
-
- /// Return version index for a given symbol index.
- pub fn version_index(&self, endian: Elf::Endian, index: usize) -> VersionIndex {
- let version_index = match self.symbols.get(index) {
- Some(x) => x.0.get(endian),
- // Ideally this would be VER_NDX_LOCAL for undefined symbols,
- // but currently there are no checks that need this distinction.
- None => elf::VER_NDX_GLOBAL,
- };
- VersionIndex(version_index)
- }
-
- /// Return version information for a given symbol version index.
- ///
- /// Returns `Ok(None)` for local and global versions.
- /// Returns `Err(_)` if index is invalid.
- pub fn version(&self, index: VersionIndex) -> Result<Option<&Version<'data>>> {
- if index.index() <= elf::VER_NDX_GLOBAL {
- return Ok(None);
- }
- self.versions
- .get(usize::from(index.index()))
- .filter(|version| version.valid)
- .read_error("Invalid ELF symbol version index")
- .map(Some)
- }
-
- /// Return true if the given symbol index satisfies the requirements of `need`.
- ///
- /// Returns false for any error.
- ///
- /// Note: this function hasn't been fully tested and is likely to be incomplete.
- pub fn matches(&self, endian: Elf::Endian, index: usize, need: Option<&Version<'_>>) -> bool {
- let version_index = self.version_index(endian, index);
- let def = match self.version(version_index) {
- Ok(def) => def,
- Err(_) => return false,
- };
- match (def, need) {
- (Some(def), Some(need)) => need.hash == def.hash && need.name == def.name,
- (None, Some(_need)) => {
- // Version must be present if needed.
- false
- }
- (Some(_def), None) => {
- // For a dlsym call, use the newest version.
- // TODO: if not a dlsym call, then use the oldest version.
- !version_index.is_hidden()
- }
- (None, None) => true,
- }
- }
-}
-
-/// An iterator for the entries in an ELF [`elf::SHT_GNU_VERDEF`] section.
-#[derive(Debug, Clone)]
-pub struct VerdefIterator<'data, Elf: FileHeader> {
- endian: Elf::Endian,
- data: Bytes<'data>,
-}
-
-impl<'data, Elf: FileHeader> VerdefIterator<'data, Elf> {
- pub(super) fn new(endian: Elf::Endian, data: &'data [u8]) -> Self {
- VerdefIterator {
- endian,
- data: Bytes(data),
- }
- }
-
- /// Return the next `Verdef` entry.
- pub fn next(
- &mut self,
- ) -> Result<Option<(&'data elf::Verdef<Elf::Endian>, VerdauxIterator<'data, Elf>)>> {
- if self.data.is_empty() {
- return Ok(None);
- }
-
- let verdef = self
- .data
- .read_at::<elf::Verdef<_>>(0)
- .read_error("ELF verdef is too short")?;
-
- let mut verdaux_data = self.data;
- verdaux_data
- .skip(verdef.vd_aux.get(self.endian) as usize)
- .read_error("Invalid ELF vd_aux")?;
- let verdaux =
- VerdauxIterator::new(self.endian, verdaux_data.0, verdef.vd_cnt.get(self.endian));
-
- let next = verdef.vd_next.get(self.endian);
- if next != 0 {
- self.data
- .skip(next as usize)
- .read_error("Invalid ELF vd_next")?;
- } else {
- self.data = Bytes(&[]);
- }
- Ok(Some((verdef, verdaux)))
- }
-}
-
-/// An iterator for the auxiliary records for an entry in an ELF [`elf::SHT_GNU_VERDEF`] section.
-#[derive(Debug, Clone)]
-pub struct VerdauxIterator<'data, Elf: FileHeader> {
- endian: Elf::Endian,
- data: Bytes<'data>,
- count: u16,
-}
-
-impl<'data, Elf: FileHeader> VerdauxIterator<'data, Elf> {
- pub(super) fn new(endian: Elf::Endian, data: &'data [u8], count: u16) -> Self {
- VerdauxIterator {
- endian,
- data: Bytes(data),
- count,
- }
- }
-
- /// Return the next `Verdaux` entry.
- pub fn next(&mut self) -> Result<Option<&'data elf::Verdaux<Elf::Endian>>> {
- if self.count == 0 {
- return Ok(None);
- }
-
- let verdaux = self
- .data
- .read_at::<elf::Verdaux<_>>(0)
- .read_error("ELF verdaux is too short")?;
-
- self.data
- .skip(verdaux.vda_next.get(self.endian) as usize)
- .read_error("Invalid ELF vda_next")?;
- self.count -= 1;
- Ok(Some(verdaux))
- }
-}
-
-/// An iterator for the entries in an ELF [`elf::SHT_GNU_VERNEED`] section.
-#[derive(Debug, Clone)]
-pub struct VerneedIterator<'data, Elf: FileHeader> {
- endian: Elf::Endian,
- data: Bytes<'data>,
-}
-
-impl<'data, Elf: FileHeader> VerneedIterator<'data, Elf> {
- pub(super) fn new(endian: Elf::Endian, data: &'data [u8]) -> Self {
- VerneedIterator {
- endian,
- data: Bytes(data),
- }
- }
-
- /// Return the next `Verneed` entry.
- pub fn next(
- &mut self,
- ) -> Result<
- Option<(
- &'data elf::Verneed<Elf::Endian>,
- VernauxIterator<'data, Elf>,
- )>,
- > {
- if self.data.is_empty() {
- return Ok(None);
- }
-
- let verneed = self
- .data
- .read_at::<elf::Verneed<_>>(0)
- .read_error("ELF verneed is too short")?;
-
- let mut vernaux_data = self.data;
- vernaux_data
- .skip(verneed.vn_aux.get(self.endian) as usize)
- .read_error("Invalid ELF vn_aux")?;
- let vernaux =
- VernauxIterator::new(self.endian, vernaux_data.0, verneed.vn_cnt.get(self.endian));
-
- let next = verneed.vn_next.get(self.endian);
- if next != 0 {
- self.data
- .skip(next as usize)
- .read_error("Invalid ELF vn_next")?;
- } else {
- self.data = Bytes(&[]);
- }
- Ok(Some((verneed, vernaux)))
- }
-}
-
-/// An iterator for the auxiliary records for an entry in an ELF [`elf::SHT_GNU_VERNEED`] section.
-#[derive(Debug, Clone)]
-pub struct VernauxIterator<'data, Elf: FileHeader> {
- endian: Elf::Endian,
- data: Bytes<'data>,
- count: u16,
-}
-
-impl<'data, Elf: FileHeader> VernauxIterator<'data, Elf> {
- pub(super) fn new(endian: Elf::Endian, data: &'data [u8], count: u16) -> Self {
- VernauxIterator {
- endian,
- data: Bytes(data),
- count,
- }
- }
-
- /// Return the next `Vernaux` entry.
- pub fn next(&mut self) -> Result<Option<&'data elf::Vernaux<Elf::Endian>>> {
- if self.count == 0 {
- return Ok(None);
- }
-
- let vernaux = self
- .data
- .read_at::<elf::Vernaux<_>>(0)
- .read_error("ELF vernaux is too short")?;
-
- self.data
- .skip(vernaux.vna_next.get(self.endian) as usize)
- .read_error("Invalid ELF vna_next")?;
- self.count -= 1;
- Ok(Some(vernaux))
- }
-}
-
-impl<Endian: endian::Endian> elf::Verdaux<Endian> {
- /// Parse the version name from the string table.
- pub fn name<'data, R: ReadRef<'data>>(
- &self,
- endian: Endian,
- strings: StringTable<'data, R>,
- ) -> Result<&'data [u8]> {
- strings
- .get(self.vda_name.get(endian))
- .read_error("Invalid ELF vda_name")
- }
-}
-
-impl<Endian: endian::Endian> elf::Verneed<Endian> {
- /// Parse the file from the string table.
- pub fn file<'data, R: ReadRef<'data>>(
- &self,
- endian: Endian,
- strings: StringTable<'data, R>,
- ) -> Result<&'data [u8]> {
- strings
- .get(self.vn_file.get(endian))
- .read_error("Invalid ELF vn_file")
- }
-}
-
-impl<Endian: endian::Endian> elf::Vernaux<Endian> {
- /// Parse the version name from the string table.
- pub fn name<'data, R: ReadRef<'data>>(
- &self,
- endian: Endian,
- strings: StringTable<'data, R>,
- ) -> Result<&'data [u8]> {
- strings
- .get(self.vna_name.get(endian))
- .read_error("Invalid ELF vna_name")
- }
-}