diff --git a/src/read/any.rs b/src/read/any.rs index 80526e99..cb7cd925 100644 --- a/src/read/any.rs +++ b/src/read/any.rs @@ -293,9 +293,9 @@ where } } - fn section_by_name(&'file self, section_name: &str) -> Option> { + fn section_by_name_bytes(&'file self, section_name: &[u8]) -> Option> { map_inner_option!(self.inner, FileInternal, SectionInternal, |x| x - .section_by_name(section_name)) + .section_by_name_bytes(section_name)) .map(|inner| Section { inner }) } @@ -554,6 +554,10 @@ impl<'data, 'file, R: ReadRef<'data>> ObjectSegment<'data> for Segment<'data, 'f with_inner!(self.inner, SegmentInternal, |x| x.data_range(address, size)) } + fn name_bytes(&self) -> Result> { + with_inner!(self.inner, SegmentInternal, |x| x.name_bytes()) + } + fn name(&self) -> Result> { with_inner!(self.inner, SegmentInternal, |x| x.name()) } @@ -695,10 +699,18 @@ impl<'data, 'file, R: ReadRef<'data>> ObjectSection<'data> for Section<'data, 'f with_inner!(self.inner, SectionInternal, |x| x.compressed_data()) } + fn name_bytes(&self) -> Result<&[u8]> { + with_inner!(self.inner, SectionInternal, |x| x.name_bytes()) + } + fn name(&self) -> Result<&str> { with_inner!(self.inner, SectionInternal, |x| x.name()) } + fn segment_name_bytes(&self) -> Result> { + with_inner!(self.inner, SectionInternal, |x| x.segment_name_bytes()) + } + fn segment_name(&self) -> Result> { with_inner!(self.inner, SectionInternal, |x| x.segment_name()) } @@ -817,6 +829,10 @@ impl<'data, 'file, R: ReadRef<'data>> ObjectComdat<'data> for Comdat<'data, 'fil with_inner!(self.inner, ComdatInternal, |x| x.symbol()) } + fn name_bytes(&self) -> Result<&[u8]> { + with_inner!(self.inner, ComdatInternal, |x| x.name_bytes()) + } + fn name(&self) -> Result<&str> { with_inner!(self.inner, ComdatInternal, |x| x.name()) } @@ -1092,6 +1108,10 @@ impl<'data, 'file, R: ReadRef<'data>> ObjectSymbol<'data> for Symbol<'data, 'fil with_inner!(self.inner, SymbolInternal, |x| x.0.index()) } + fn name_bytes(&self) -> Result<&'data [u8]> { + with_inner!(self.inner, SymbolInternal, |x| x.0.name_bytes()) + } + fn name(&self) -> Result<&'data str> { with_inner!(self.inner, SymbolInternal, |x| x.0.name()) } diff --git a/src/read/coff/comdat.rs b/src/read/coff/comdat.rs index 2d87a6d9..3be69ecc 100644 --- a/src/read/coff/comdat.rs +++ b/src/read/coff/comdat.rs @@ -102,10 +102,15 @@ impl<'data, 'file, R: ReadRef<'data>> ObjectComdat<'data> for CoffComdat<'data, } #[inline] - fn name(&self) -> Result<&str> { + fn name_bytes(&self) -> Result<&[u8]> { // Find the name of first symbol referring to the section. - let name = self.symbol.name(self.file.common.symbols.strings())?; - str::from_utf8(name) + self.symbol.name(self.file.common.symbols.strings()) + } + + #[inline] + fn name(&self) -> Result<&str> { + let bytes = self.name_bytes()?; + str::from_utf8(bytes) .ok() .read_error("Non UTF-8 COFF COMDAT name") } diff --git a/src/read/coff/file.rs b/src/read/coff/file.rs index fad2efd9..84ed8191 100644 --- a/src/read/coff/file.rs +++ b/src/read/coff/file.rs @@ -1,5 +1,4 @@ use alloc::vec::Vec; -use core::str; use crate::read::{ self, Architecture, Export, FileFlags, Import, NoDynamicRelocationIterator, Object, @@ -96,9 +95,12 @@ where } } - fn section_by_name(&'file self, section_name: &str) -> Option> { + fn section_by_name_bytes( + &'file self, + section_name: &[u8], + ) -> Option> { self.sections() - .find(|section| section.name() == Ok(section_name)) + .find(|section| section.name_bytes() == Ok(section_name)) } fn section_by_index(&'file self, index: SectionIndex) -> Result> { diff --git a/src/read/coff/section.rs b/src/read/coff/section.rs index 7999246a..e499054d 100644 --- a/src/read/coff/section.rs +++ b/src/read/coff/section.rs @@ -173,14 +173,20 @@ impl<'data, 'file, R: ReadRef<'data>> ObjectSegment<'data> for CoffSegment<'data )) } + #[inline] + fn name_bytes(&self) -> Result> { + self.section + .name(self.file.common.symbols.strings()) + .map(Some) + } + #[inline] fn name(&self) -> Result> { let name = self.section.name(self.file.common.symbols.strings())?; - Ok(Some( - str::from_utf8(name) - .ok() - .read_error("Non UTF-8 COFF section name")?, - )) + str::from_utf8(name) + .ok() + .read_error("Non UTF-8 COFF section name") + .map(Some) } } @@ -274,14 +280,24 @@ impl<'data, 'file, R: ReadRef<'data>> ObjectSection<'data> for CoffSection<'data self.data().map(CompressedData::none) } + #[inline] + fn name_bytes(&self) -> Result<&[u8]> { + self.section.name(self.file.common.symbols.strings()) + } + #[inline] fn name(&self) -> Result<&str> { - let name = self.section.name(self.file.common.symbols.strings())?; + let name = self.name_bytes()?; str::from_utf8(name) .ok() .read_error("Non UTF-8 COFF section name") } + #[inline] + fn segment_name_bytes(&self) -> Result> { + Ok(None) + } + #[inline] fn segment_name(&self) -> Result> { Ok(None) diff --git a/src/read/coff/symbol.rs b/src/read/coff/symbol.rs index 5af801f1..7aa6913a 100644 --- a/src/read/coff/symbol.rs +++ b/src/read/coff/symbol.rs @@ -324,14 +324,18 @@ impl<'data, 'file, R: ReadRef<'data>> ObjectSymbol<'data> for CoffSymbol<'data, self.index } - fn name(&self) -> read::Result<&'data str> { - let name = if self.symbol.has_aux_file_name() { + fn name_bytes(&self) -> read::Result<&'data [u8]> { + if self.symbol.has_aux_file_name() { self.file .symbols - .aux_file_name(self.index.0, self.symbol.number_of_aux_symbols)? + .aux_file_name(self.index.0, self.symbol.number_of_aux_symbols) } else { - self.symbol.name(self.file.symbols.strings())? - }; + self.symbol.name(self.file.symbols.strings()) + } + } + + fn name(&self) -> read::Result<&'data str> { + let name = self.name_bytes()?; str::from_utf8(name) .ok() .read_error("Non UTF-8 COFF symbol name") diff --git a/src/read/elf/comdat.rs b/src/read/elf/comdat.rs index 5feb55b1..964c3746 100644 --- a/src/read/elf/comdat.rs +++ b/src/read/elf/comdat.rs @@ -110,11 +110,15 @@ where SymbolIndex(self.section.sh_info(self.file.endian) as usize) } - fn name(&self) -> read::Result<&str> { + 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)?; - let name = symbol.name(self.file.endian, self.file.symbols.strings())?; + 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") diff --git a/src/read/elf/file.rs b/src/read/elf/file.rs index 68094ba1..a26737cd 100644 --- a/src/read/elf/file.rs +++ b/src/read/elf/file.rs @@ -1,7 +1,7 @@ use alloc::vec::Vec; use core::convert::TryInto; use core::fmt::Debug; -use core::{mem, str}; +use core::mem; use crate::read::{ self, util, Architecture, ByteString, Bytes, Error, Export, FileFlags, Import, Object, @@ -93,10 +93,10 @@ where fn raw_section_by_name<'file>( &'file self, - section_name: &str, + section_name: &[u8], ) -> Option> { self.sections - .section_by_name(self.endian, section_name.as_bytes()) + .section_by_name(self.endian, section_name) .map(|(index, section)| ElfSection { file: self, index: SectionIndex(index), @@ -107,18 +107,21 @@ where #[cfg(feature = "compression")] fn zdebug_section_by_name<'file>( &'file self, - section_name: &str, + section_name: &[u8], ) -> Option> { - if !section_name.starts_with(".debug_") { + if !section_name.starts_with(b".debug_") { return None; } - self.raw_section_by_name(&format!(".zdebug_{}", §ion_name[7..])) + let mut name = Vec::with_capacity(section_name.len() + 1); + name.extend_from_slice(b".zdebug_"); + name.extend_from_slice(§ion_name[7..]); + self.raw_section_by_name(&name) } #[cfg(not(feature = "compression"))] fn zdebug_section_by_name<'file>( &'file self, - _section_name: &str, + _section_name: &[u8], ) -> Option> { None } @@ -193,9 +196,9 @@ where } } - fn section_by_name( + fn section_by_name_bytes( &'file self, - section_name: &str, + section_name: &[u8], ) -> Option> { self.raw_section_by_name(section_name) .or_else(|| self.zdebug_section_by_name(section_name)) @@ -357,7 +360,7 @@ where } fn gnu_debuglink(&self) -> read::Result> { - let section = match self.raw_section_by_name(".gnu_debuglink") { + let section = match self.raw_section_by_name(b".gnu_debuglink") { Some(section) => section, None => return Ok(None), }; @@ -378,7 +381,7 @@ where } fn gnu_debugaltlink(&self) -> read::Result> { - let section = match self.raw_section_by_name(".gnu_debugaltlink") { + let section = match self.raw_section_by_name(b".gnu_debugaltlink") { Some(section) => section, None => return Ok(None), }; diff --git a/src/read/elf/section.rs b/src/read/elf/section.rs index fa99581d..c9045a75 100644 --- a/src/read/elf/section.rs +++ b/src/read/elf/section.rs @@ -514,16 +514,24 @@ where self.compressed_file_range()?.data(self.file.data) } - fn name(&self) -> read::Result<&str> { - let name = self - .file + fn name_bytes(&self) -> read::Result<&[u8]> { + self.file .sections - .section_name(self.file.endian, self.section)?; + .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> { + Ok(None) + } + #[inline] fn segment_name(&self) -> read::Result> { Ok(None) diff --git a/src/read/elf/segment.rs b/src/read/elf/segment.rs index 70528b59..a64a4ba5 100644 --- a/src/read/elf/segment.rs +++ b/src/read/elf/segment.rs @@ -119,6 +119,11 @@ where )) } + #[inline] + fn name_bytes(&self) -> read::Result> { + Ok(None) + } + #[inline] fn name(&self) -> read::Result> { Ok(None) diff --git a/src/read/elf/symbol.rs b/src/read/elf/symbol.rs index f5465eed..8630346f 100644 --- a/src/read/elf/symbol.rs +++ b/src/read/elf/symbol.rs @@ -317,8 +317,12 @@ impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> ObjectSymbol<'data> 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.symbol.name(self.endian, self.symbols.strings())?; + let name = self.name_bytes()?; str::from_utf8(name) .ok() .read_error("Non UTF-8 ELF symbol name") diff --git a/src/read/macho/file.rs b/src/read/macho/file.rs index 54ae2d83..85936588 100644 --- a/src/read/macho/file.rs +++ b/src/read/macho/file.rs @@ -153,13 +153,13 @@ where } } - fn section_by_name( + fn section_by_name_bytes( &'file self, - section_name: &str, + section_name: &[u8], ) -> Option> { // Translate the "." prefix to the "__" prefix used by OSX/Mach-O, eg // ".debug_info" to "__debug_info", and limit to 16 bytes total. - let system_name = if section_name.starts_with('.') { + let system_name = if section_name.starts_with(b".") { if section_name.len() > 15 { Some(§ion_name[1..15]) } else { @@ -170,12 +170,12 @@ where }; let cmp_section_name = |section: &MachOSection<'data, 'file, Mach, R>| { section - .name() + .name_bytes() .map(|name| { section_name == name || system_name .filter(|system_name| { - name.starts_with("__") && name[2..] == **system_name + name.starts_with(b"__") && name[2..] == **system_name }) .is_some() }) @@ -427,6 +427,11 @@ where unreachable!(); } + #[inline] + fn name_bytes(&self) -> Result<&[u8]> { + unreachable!(); + } + #[inline] fn name(&self) -> Result<&str> { unreachable!(); diff --git a/src/read/macho/section.rs b/src/read/macho/section.rs index 7b467da2..3a5a22eb 100644 --- a/src/read/macho/section.rs +++ b/src/read/macho/section.rs @@ -150,6 +150,11 @@ where self.data().map(CompressedData::none) } + #[inline] + fn name_bytes(&self) -> Result<&[u8]> { + Ok(self.internal.section.name()) + } + #[inline] fn name(&self) -> Result<&str> { str::from_utf8(self.internal.section.name()) @@ -157,6 +162,11 @@ where .read_error("Non UTF-8 Mach-O section name") } + #[inline] + fn segment_name_bytes(&self) -> Result> { + Ok(Some(self.internal.section.segment_name())) + } + #[inline] fn segment_name(&self) -> Result> { Ok(Some( diff --git a/src/read/macho/segment.rs b/src/read/macho/segment.rs index d0e90b02..3c2d9649 100644 --- a/src/read/macho/segment.rs +++ b/src/read/macho/segment.rs @@ -124,6 +124,11 @@ where )) } + #[inline] + fn name_bytes(&self) -> Result> { + Ok(Some(self.segment.name())) + } + #[inline] fn name(&self) -> Result> { Ok(Some( diff --git a/src/read/macho/symbol.rs b/src/read/macho/symbol.rs index 1528d52e..e102c5d0 100644 --- a/src/read/macho/symbol.rs +++ b/src/read/macho/symbol.rs @@ -287,10 +287,12 @@ where self.index } + fn name_bytes(&self) -> Result<&'data [u8]> { + self.nlist.name(self.file.endian, self.file.symbols.strings) + } + fn name(&self) -> Result<&'data str> { - let name = self - .nlist - .name(self.file.endian, self.file.symbols.strings)?; + let name = self.name_bytes()?; str::from_utf8(name) .ok() .read_error("Non UTF-8 Mach-O symbol name") diff --git a/src/read/pe/file.rs b/src/read/pe/file.rs index a154d656..cfee7162 100644 --- a/src/read/pe/file.rs +++ b/src/read/pe/file.rs @@ -149,10 +149,13 @@ where } } - fn section_by_name(&'file self, section_name: &str) -> Option> { + fn section_by_name_bytes( + &'file self, + section_name: &[u8], + ) -> Option> { self.common .sections - .section_by_name(self.common.symbols.strings(), section_name.as_bytes()) + .section_by_name(self.common.symbols.strings(), section_name) .map(|(index, section)| PeSection { file: self, index: SectionIndex(index), @@ -495,6 +498,11 @@ where unreachable!(); } + #[inline] + fn name_bytes(&self) -> Result<&[u8]> { + unreachable!(); + } + #[inline] fn name(&self) -> Result<&str> { unreachable!(); diff --git a/src/read/pe/section.rs b/src/read/pe/section.rs index 32e0a825..a91dbdb9 100644 --- a/src/read/pe/section.rs +++ b/src/read/pe/section.rs @@ -119,6 +119,13 @@ where )) } + #[inline] + fn name_bytes(&self) -> Result> { + self.section + .name(self.file.common.symbols.strings()) + .map(Some) + } + #[inline] fn name(&self) -> Result> { let name = self.section.name(self.file.common.symbols.strings())?; @@ -264,14 +271,24 @@ where self.data().map(CompressedData::none) } + #[inline] + fn name_bytes(&self) -> Result<&[u8]> { + self.section.name(self.file.common.symbols.strings()) + } + #[inline] fn name(&self) -> Result<&str> { - let name = self.section.name(self.file.common.symbols.strings())?; + let name = self.name_bytes()?; str::from_utf8(name) .ok() .read_error("Non UTF-8 PE section name") } + #[inline] + fn segment_name_bytes(&self) -> Result> { + Ok(None) + } + #[inline] fn segment_name(&self) -> Result> { Ok(None) diff --git a/src/read/traits.rs b/src/read/traits.rs index 4cc497b9..1aa06309 100644 --- a/src/read/traits.rs +++ b/src/read/traits.rs @@ -83,7 +83,12 @@ pub trait Object<'data: 'file, 'file>: read::private::Sealed { /// name. In this case, the first matching section will be used. /// /// This method skips over sections with invalid names. - fn section_by_name(&'file self, section_name: &str) -> Option; + fn section_by_name(&'file self, section_name: &str) -> Option { + self.section_by_name_bytes(section_name.as_bytes()) + } + + /// Like [`Self::section_by_name`], but allows names that are not UTF-8. + fn section_by_name_bytes(&'file self, section_name: &[u8]) -> Option; /// Get the section at the given index. /// @@ -243,6 +248,11 @@ pub trait ObjectSegment<'data>: read::private::Sealed { fn data_range(&self, address: u64, size: u64) -> Result>; /// Returns the name of the segment. + fn name_bytes(&self) -> Result>; + + /// Returns the name of the segment. + /// + /// Returns an error if the name is not UTF-8. fn name(&self) -> Result>; } @@ -304,9 +314,19 @@ pub trait ObjectSection<'data>: read::private::Sealed { } /// Returns the name of the section. + fn name_bytes(&self) -> Result<&[u8]>; + + /// Returns the name of the section. + /// + /// Returns an error if the name is not UTF-8. fn name(&self) -> Result<&str>; /// Returns the name of the segment for this section. + fn segment_name_bytes(&self) -> Result>; + + /// Returns the name of the segment for this section. + /// + /// Returns an error if the name is not UTF-8. fn segment_name(&self) -> Result>; /// Return the kind of this section. @@ -331,6 +351,11 @@ pub trait ObjectComdat<'data>: read::private::Sealed { fn symbol(&self) -> SymbolIndex; /// Returns the name of the COMDAT section group. + fn name_bytes(&self) -> Result<&[u8]>; + + /// Returns the name of the COMDAT section group. + /// + /// Returns an error if the name is not UTF-8. fn name(&self) -> Result<&str>; /// Get the sections in this section group. @@ -364,6 +389,11 @@ pub trait ObjectSymbol<'data>: read::private::Sealed { fn index(&self) -> SymbolIndex; /// The name of the symbol. + fn name_bytes(&self) -> Result<&'data [u8]>; + + /// The name of the symbol. + /// + /// Returns an error if the name is not UTF-8. fn name(&self) -> Result<&'data str>; /// The address of the symbol. May be zero if the address is unknown. diff --git a/src/read/wasm.rs b/src/read/wasm.rs index 93e9184b..b62da615 100644 --- a/src/read/wasm.rs +++ b/src/read/wasm.rs @@ -330,9 +330,12 @@ where WasmSegmentIterator { file: self } } - fn section_by_name(&'file self, section_name: &str) -> Option> { + fn section_by_name_bytes( + &'file self, + section_name: &[u8], + ) -> Option> { self.sections() - .find(|section| section.name() == Ok(section_name)) + .find(|section| section.name_bytes() == Ok(section_name)) } fn section_by_index(&'file self, index: SectionIndex) -> Result> { @@ -478,6 +481,11 @@ impl<'data, 'file, R> ObjectSegment<'data> for WasmSegment<'data, 'file, R> { unreachable!() } + #[inline] + fn name_bytes(&self) -> Result> { + unreachable!() + } + #[inline] fn name(&self) -> Result> { unreachable!() @@ -566,6 +574,11 @@ impl<'data, 'file, R> ObjectSection<'data> for WasmSection<'data, 'file, R> { self.data().map(CompressedData::none) } + #[inline] + fn name_bytes(&self) -> Result<&[u8]> { + self.name().map(str::as_bytes) + } + #[inline] fn name(&self) -> Result<&str> { Ok(match self.section.code { @@ -585,6 +598,11 @@ impl<'data, 'file, R> ObjectSection<'data> for WasmSection<'data, 'file, R> { }) } + #[inline] + fn segment_name_bytes(&self) -> Result> { + Ok(None) + } + #[inline] fn segment_name(&self) -> Result> { Ok(None) @@ -661,6 +679,11 @@ impl<'data, 'file, R> ObjectComdat<'data> for WasmComdat<'data, 'file, R> { unreachable!(); } + #[inline] + fn name_bytes(&self) -> Result<&[u8]> { + unreachable!(); + } + #[inline] fn name(&self) -> Result<&str> { unreachable!(); @@ -759,6 +782,11 @@ impl<'data, 'file> ObjectSymbol<'data> for WasmSymbol<'data, 'file> { self.index } + #[inline] + fn name_bytes(&self) -> read::Result<&'data [u8]> { + Ok(self.symbol.name.as_bytes()) + } + #[inline] fn name(&self) -> read::Result<&'data str> { Ok(self.symbol.name)