From 1b6a04ca5504955c571d1c97504fb45ea0befee4 Mon Sep 17 00:00:00 2001 From: Valentin Popov Date: Mon, 8 Jan 2024 01:21:28 +0400 Subject: Initial vendor packages Signed-off-by: Valentin Popov --- vendor/object/src/read/elf/comdat.rs | 162 +++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 vendor/object/src/read/elf/comdat.rs (limited to 'vendor/object/src/read/elf/comdat.rs') diff --git a/vendor/object/src/read/elf/comdat.rs b/vendor/object/src/read/elf/comdat.rs new file mode 100644 index 0000000..882d253 --- /dev/null +++ b/vendor/object/src/read/elf/comdat.rs @@ -0,0 +1,162 @@ +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, 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, 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>, +} + +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 { + 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, 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, 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], +} + +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> { + 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, 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, 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>, +} + +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 { + let index = self.sections.next()?; + Some(SectionIndex(index.get(self.file.endian) as usize)) + } +} -- cgit v1.2.3