diff options
Diffstat (limited to 'vendor/object/src/read/elf/note.rs')
-rw-r--r-- | vendor/object/src/read/elf/note.rs | 271 |
1 files changed, 0 insertions, 271 deletions
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)) - } -} |