diff options
Diffstat (limited to 'vendor/gimli/src/read/str.rs')
-rw-r--r-- | vendor/gimli/src/read/str.rs | 321 |
1 files changed, 0 insertions, 321 deletions
diff --git a/vendor/gimli/src/read/str.rs b/vendor/gimli/src/read/str.rs deleted file mode 100644 index c6b87d8..0000000 --- a/vendor/gimli/src/read/str.rs +++ /dev/null @@ -1,321 +0,0 @@ -use crate::common::{ - DebugLineStrOffset, DebugStrOffset, DebugStrOffsetsBase, DebugStrOffsetsIndex, DwarfFileType, - Encoding, SectionId, -}; -use crate::endianity::Endianity; -use crate::read::{EndianSlice, Reader, ReaderOffset, Result, Section}; -use crate::Format; - -/// The `DebugStr` struct represents the DWARF strings -/// found in the `.debug_str` section. -#[derive(Debug, Default, Clone, Copy)] -pub struct DebugStr<R> { - debug_str_section: R, -} - -impl<'input, Endian> DebugStr<EndianSlice<'input, Endian>> -where - Endian: Endianity, -{ - /// Construct a new `DebugStr` instance from the data in the `.debug_str` - /// section. - /// - /// It is the caller's responsibility to read the `.debug_str` section and - /// present it as a `&[u8]` slice. That means using some ELF loader on - /// Linux, a Mach-O loader on macOS, etc. - /// - /// ``` - /// use gimli::{DebugStr, LittleEndian}; - /// - /// # let buf = [0x00, 0x01, 0x02, 0x03]; - /// # let read_debug_str_section_somehow = || &buf; - /// let debug_str = DebugStr::new(read_debug_str_section_somehow(), LittleEndian); - /// ``` - pub fn new(debug_str_section: &'input [u8], endian: Endian) -> Self { - Self::from(EndianSlice::new(debug_str_section, endian)) - } -} - -impl<R: Reader> DebugStr<R> { - /// Lookup a string from the `.debug_str` section by DebugStrOffset. - /// - /// ``` - /// use gimli::{DebugStr, DebugStrOffset, LittleEndian}; - /// - /// # let buf = [0x01, 0x02, 0x00]; - /// # let offset = DebugStrOffset(0); - /// # let read_debug_str_section_somehow = || &buf; - /// # let debug_str_offset_somehow = || offset; - /// let debug_str = DebugStr::new(read_debug_str_section_somehow(), LittleEndian); - /// println!("Found string {:?}", debug_str.get_str(debug_str_offset_somehow())); - /// ``` - pub fn get_str(&self, offset: DebugStrOffset<R::Offset>) -> Result<R> { - let input = &mut self.debug_str_section.clone(); - input.skip(offset.0)?; - input.read_null_terminated_slice() - } -} - -impl<T> DebugStr<T> { - /// Create a `DebugStr` section that references the data in `self`. - /// - /// This is useful when `R` implements `Reader` but `T` does not. - /// - /// ## Example Usage - /// - /// ```rust,no_run - /// # let load_section = || unimplemented!(); - /// // Read the DWARF section into a `Vec` with whatever object loader you're using. - /// let owned_section: gimli::DebugStr<Vec<u8>> = load_section(); - /// // Create a reference to the DWARF section. - /// let section = owned_section.borrow(|section| { - /// gimli::EndianSlice::new(§ion, gimli::LittleEndian) - /// }); - /// ``` - pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugStr<R> - where - F: FnMut(&'a T) -> R, - { - borrow(&self.debug_str_section).into() - } -} - -impl<R> Section<R> for DebugStr<R> { - fn id() -> SectionId { - SectionId::DebugStr - } - - fn reader(&self) -> &R { - &self.debug_str_section - } -} - -impl<R> From<R> for DebugStr<R> { - fn from(debug_str_section: R) -> Self { - DebugStr { debug_str_section } - } -} - -/// The raw contents of the `.debug_str_offsets` section. -#[derive(Debug, Default, Clone, Copy)] -pub struct DebugStrOffsets<R> { - section: R, -} - -impl<R: Reader> DebugStrOffsets<R> { - // TODO: add an iterator over the sets of entries in the section. - // This is not needed for common usage of the section though. - - /// Returns the `.debug_str` offset at the given `base` and `index`. - /// - /// A set of entries in the `.debug_str_offsets` section consists of a header - /// followed by a series of string table offsets. - /// - /// The `base` must be the `DW_AT_str_offsets_base` value from the compilation unit DIE. - /// This is an offset that points to the first entry following the header. - /// - /// The `index` is the value of a `DW_FORM_strx` attribute. - /// - /// The `format` must be the DWARF format of the compilation unit. This format must - /// match the header. However, note that we do not parse the header to validate this, - /// since locating the header is unreliable, and the GNU extensions do not emit it. - pub fn get_str_offset( - &self, - format: Format, - base: DebugStrOffsetsBase<R::Offset>, - index: DebugStrOffsetsIndex<R::Offset>, - ) -> Result<DebugStrOffset<R::Offset>> { - let input = &mut self.section.clone(); - input.skip(base.0)?; - input.skip(R::Offset::from_u64( - index.0.into_u64() * u64::from(format.word_size()), - )?)?; - input.read_offset(format).map(DebugStrOffset) - } -} - -impl<T> DebugStrOffsets<T> { - /// Create a `DebugStrOffsets` section that references the data in `self`. - /// - /// This is useful when `R` implements `Reader` but `T` does not. - /// - /// ## Example Usage - /// - /// ```rust,no_run - /// # let load_section = || unimplemented!(); - /// // Read the DWARF section into a `Vec` with whatever object loader you're using. - /// let owned_section: gimli::DebugStrOffsets<Vec<u8>> = load_section(); - /// // Create a reference to the DWARF section. - /// let section = owned_section.borrow(|section| { - /// gimli::EndianSlice::new(§ion, gimli::LittleEndian) - /// }); - /// ``` - pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugStrOffsets<R> - where - F: FnMut(&'a T) -> R, - { - borrow(&self.section).into() - } -} - -impl<R> Section<R> for DebugStrOffsets<R> { - fn id() -> SectionId { - SectionId::DebugStrOffsets - } - - fn reader(&self) -> &R { - &self.section - } -} - -impl<R> From<R> for DebugStrOffsets<R> { - fn from(section: R) -> Self { - DebugStrOffsets { section } - } -} - -impl<Offset> DebugStrOffsetsBase<Offset> -where - Offset: ReaderOffset, -{ - /// Returns a `DebugStrOffsetsBase` with the default value of DW_AT_str_offsets_base - /// for the given `Encoding` and `DwarfFileType`. - pub fn default_for_encoding_and_file( - encoding: Encoding, - file_type: DwarfFileType, - ) -> DebugStrOffsetsBase<Offset> { - if encoding.version >= 5 && file_type == DwarfFileType::Dwo { - // In .dwo files, the compiler omits the DW_AT_str_offsets_base attribute (because there is - // only a single unit in the file) but we must skip past the header, which the attribute - // would normally do for us. - // initial_length_size + version + 2 bytes of padding. - DebugStrOffsetsBase(Offset::from_u8( - encoding.format.initial_length_size() + 2 + 2, - )) - } else { - DebugStrOffsetsBase(Offset::from_u8(0)) - } - } -} - -/// The `DebugLineStr` struct represents the DWARF strings -/// found in the `.debug_line_str` section. -#[derive(Debug, Default, Clone, Copy)] -pub struct DebugLineStr<R> { - section: R, -} - -impl<'input, Endian> DebugLineStr<EndianSlice<'input, Endian>> -where - Endian: Endianity, -{ - /// Construct a new `DebugLineStr` instance from the data in the `.debug_line_str` - /// section. - /// - /// It is the caller's responsibility to read the `.debug_line_str` section and - /// present it as a `&[u8]` slice. That means using some ELF loader on - /// Linux, a Mach-O loader on macOS, etc. - /// - /// ``` - /// use gimli::{DebugLineStr, LittleEndian}; - /// - /// # let buf = [0x00, 0x01, 0x02, 0x03]; - /// # let read_debug_line_str_section_somehow = || &buf; - /// let debug_str = DebugLineStr::new(read_debug_line_str_section_somehow(), LittleEndian); - /// ``` - pub fn new(debug_line_str_section: &'input [u8], endian: Endian) -> Self { - Self::from(EndianSlice::new(debug_line_str_section, endian)) - } -} - -impl<R: Reader> DebugLineStr<R> { - /// Lookup a string from the `.debug_line_str` section by DebugLineStrOffset. - pub fn get_str(&self, offset: DebugLineStrOffset<R::Offset>) -> Result<R> { - let input = &mut self.section.clone(); - input.skip(offset.0)?; - input.read_null_terminated_slice() - } -} - -impl<T> DebugLineStr<T> { - /// Create a `DebugLineStr` section that references the data in `self`. - /// - /// This is useful when `R` implements `Reader` but `T` does not. - /// - /// ## Example Usage - /// - /// ```rust,no_run - /// # let load_section = || unimplemented!(); - /// // Read the DWARF section into a `Vec` with whatever object loader you're using. - /// let owned_section: gimli::DebugLineStr<Vec<u8>> = load_section(); - /// // Create a reference to the DWARF section. - /// let section = owned_section.borrow(|section| { - /// gimli::EndianSlice::new(§ion, gimli::LittleEndian) - /// }); - /// ``` - pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugLineStr<R> - where - F: FnMut(&'a T) -> R, - { - borrow(&self.section).into() - } -} - -impl<R> Section<R> for DebugLineStr<R> { - fn id() -> SectionId { - SectionId::DebugLineStr - } - - fn reader(&self) -> &R { - &self.section - } -} - -impl<R> From<R> for DebugLineStr<R> { - fn from(section: R) -> Self { - DebugLineStr { section } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::test_util::GimliSectionMethods; - use crate::LittleEndian; - use test_assembler::{Endian, Label, LabelMaker, Section}; - - #[test] - fn test_get_str_offset() { - for format in vec![Format::Dwarf32, Format::Dwarf64] { - let zero = Label::new(); - let length = Label::new(); - let start = Label::new(); - let first = Label::new(); - let end = Label::new(); - let mut section = Section::with_endian(Endian::Little) - .mark(&zero) - .initial_length(format, &length, &start) - .D16(5) - .D16(0) - .mark(&first); - for i in 0..20 { - section = section.word(format.word_size(), 1000 + i); - } - section = section.mark(&end); - length.set_const((&end - &start) as u64); - - let section = section.get_contents().unwrap(); - let debug_str_offsets = DebugStrOffsets::from(EndianSlice::new(§ion, LittleEndian)); - let base = DebugStrOffsetsBase((&first - &zero) as usize); - - assert_eq!( - debug_str_offsets.get_str_offset(format, base, DebugStrOffsetsIndex(0)), - Ok(DebugStrOffset(1000)) - ); - assert_eq!( - debug_str_offsets.get_str_offset(format, base, DebugStrOffsetsIndex(19)), - Ok(DebugStrOffset(1019)) - ); - } - } -} |