diff options
Diffstat (limited to 'vendor/object/src/read/elf/section.rs')
-rw-r--r-- | vendor/object/src/read/elf/section.rs | 112 |
1 files changed, 84 insertions, 28 deletions
diff --git a/vendor/object/src/read/elf/section.rs b/vendor/object/src/read/elf/section.rs index 3f8a08216..df08f9e3e 100644 --- a/vendor/object/src/read/elf/section.rs +++ b/vendor/object/src/read/elf/section.rs @@ -10,8 +10,9 @@ use crate::read::{ }; use super::{ - CompressionHeader, ElfFile, ElfSectionRelocationIterator, FileHeader, GnuHashTable, HashTable, - NoteIterator, RelocationSections, SymbolTable, VerdefIterator, VerneedIterator, VersionTable, + AttributesSection, CompressionHeader, ElfFile, ElfSectionRelocationIterator, FileHeader, + GnuHashTable, HashTable, NoteIterator, RelocationSections, SymbolTable, VerdefIterator, + VerneedIterator, VersionTable, }; /// The table of section headers in an ELF file. @@ -362,7 +363,6 @@ pub type ElfSection64<'data, 'file, Endian = Endianness, R = &'data [u8]> = #[derive(Debug)] pub struct ElfSection<'data, 'file, Elf, R = &'data [u8]> where - 'data: 'file, Elf: FileHeader, R: ReadRef<'data>, { @@ -380,32 +380,24 @@ impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> ElfSection<'data, 'file, fn maybe_compressed(&self) -> read::Result<Option<CompressedFileRange>> { let endian = self.file.endian; - if (self.section.sh_flags(endian).into() & u64::from(elf::SHF_COMPRESSED)) == 0 { - return Ok(None); - } - let (section_offset, section_size) = self - .section - .file_range(endian) - .read_error("Invalid ELF compressed section type")?; - let mut offset = section_offset; - let header = self - .file - .data - .read::<Elf::CompressionHeader>(&mut offset) - .read_error("Invalid ELF compressed section offset")?; - if header.ch_type(endian) != elf::ELFCOMPRESS_ZLIB { - return Err(Error("Unsupported ELF compression type")); + 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) } - let uncompressed_size = header.ch_size(endian).into(); - let compressed_size = section_size - .checked_sub(offset - section_offset) - .read_error("Invalid ELF compressed section size")?; - Ok(Some(CompressedFileRange { - format: CompressionFormat::Zlib, - offset, - compressed_size, - uncompressed_size, - })) } /// Try GNU-style "ZLIB" header decompression. @@ -975,6 +967,70 @@ pub trait SectionHeader: Debug + Pod { 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> { |