diff options
Diffstat (limited to 'vendor/gimli/src/read/index.rs')
-rw-r--r-- | vendor/gimli/src/read/index.rs | 535 |
1 files changed, 0 insertions, 535 deletions
diff --git a/vendor/gimli/src/read/index.rs b/vendor/gimli/src/read/index.rs deleted file mode 100644 index 129eb2f..0000000 --- a/vendor/gimli/src/read/index.rs +++ /dev/null @@ -1,535 +0,0 @@ -use core::slice; - -use crate::common::SectionId; -use crate::constants; -use crate::endianity::Endianity; -use crate::read::{EndianSlice, Error, Reader, ReaderOffset, Result, Section}; - -/// The data in the `.debug_cu_index` section of a `.dwp` file. -/// -/// This section contains the compilation unit index. -#[derive(Debug, Default, Clone, Copy)] -pub struct DebugCuIndex<R> { - section: R, -} - -impl<'input, Endian> DebugCuIndex<EndianSlice<'input, Endian>> -where - Endian: Endianity, -{ - /// Construct a new `DebugCuIndex` instance from the data in the `.debug_cu_index` - /// section. - pub fn new(section: &'input [u8], endian: Endian) -> Self { - Self::from(EndianSlice::new(section, endian)) - } -} - -impl<R> Section<R> for DebugCuIndex<R> { - fn id() -> SectionId { - SectionId::DebugCuIndex - } - - fn reader(&self) -> &R { - &self.section - } -} - -impl<R> From<R> for DebugCuIndex<R> { - fn from(section: R) -> Self { - DebugCuIndex { section } - } -} - -impl<R: Reader> DebugCuIndex<R> { - /// Parse the index header. - pub fn index(self) -> Result<UnitIndex<R>> { - UnitIndex::parse(self.section) - } -} - -/// The data in the `.debug_tu_index` section of a `.dwp` file. -/// -/// This section contains the type unit index. -#[derive(Debug, Default, Clone, Copy)] -pub struct DebugTuIndex<R> { - section: R, -} - -impl<'input, Endian> DebugTuIndex<EndianSlice<'input, Endian>> -where - Endian: Endianity, -{ - /// Construct a new `DebugTuIndex` instance from the data in the `.debug_tu_index` - /// section. - pub fn new(section: &'input [u8], endian: Endian) -> Self { - Self::from(EndianSlice::new(section, endian)) - } -} - -impl<R> Section<R> for DebugTuIndex<R> { - fn id() -> SectionId { - SectionId::DebugTuIndex - } - - fn reader(&self) -> &R { - &self.section - } -} - -impl<R> From<R> for DebugTuIndex<R> { - fn from(section: R) -> Self { - DebugTuIndex { section } - } -} - -impl<R: Reader> DebugTuIndex<R> { - /// Parse the index header. - pub fn index(self) -> Result<UnitIndex<R>> { - UnitIndex::parse(self.section) - } -} - -const SECTION_COUNT_MAX: u8 = 8; - -/// The partially parsed index from a `DebugCuIndex` or `DebugTuIndex`. -#[derive(Debug, Clone)] -pub struct UnitIndex<R: Reader> { - version: u16, - section_count: u32, - unit_count: u32, - slot_count: u32, - hash_ids: R, - hash_rows: R, - // Only `section_count` values are valid. - sections: [SectionId; SECTION_COUNT_MAX as usize], - offsets: R, - sizes: R, -} - -impl<R: Reader> UnitIndex<R> { - fn parse(mut input: R) -> Result<UnitIndex<R>> { - if input.is_empty() { - return Ok(UnitIndex { - version: 5, - section_count: 0, - unit_count: 0, - slot_count: 0, - hash_ids: input.clone(), - hash_rows: input.clone(), - sections: [SectionId::DebugAbbrev; SECTION_COUNT_MAX as usize], - offsets: input.clone(), - sizes: input.clone(), - }); - } - - // GNU split-dwarf extension to DWARF 4 uses a 32-bit version, - // but DWARF 5 uses a 16-bit version followed by 16-bit padding. - let mut original_input = input.clone(); - let version; - if input.read_u32()? == 2 { - version = 2 - } else { - version = original_input.read_u16()?; - if version != 5 { - return Err(Error::UnknownVersion(version.into())); - } - } - - let section_count = input.read_u32()?; - let unit_count = input.read_u32()?; - let slot_count = input.read_u32()?; - if slot_count == 0 || slot_count & (slot_count - 1) != 0 || slot_count <= unit_count { - return Err(Error::InvalidIndexSlotCount); - } - - let hash_ids = input.split(R::Offset::from_u64(u64::from(slot_count) * 8)?)?; - let hash_rows = input.split(R::Offset::from_u64(u64::from(slot_count) * 4)?)?; - - let mut sections = [SectionId::DebugAbbrev; SECTION_COUNT_MAX as usize]; - if section_count > SECTION_COUNT_MAX.into() { - return Err(Error::InvalidIndexSectionCount); - } - for i in 0..section_count { - let section = input.read_u32()?; - sections[i as usize] = if version == 2 { - match constants::DwSectV2(section) { - constants::DW_SECT_V2_INFO => SectionId::DebugInfo, - constants::DW_SECT_V2_TYPES => SectionId::DebugTypes, - constants::DW_SECT_V2_ABBREV => SectionId::DebugAbbrev, - constants::DW_SECT_V2_LINE => SectionId::DebugLine, - constants::DW_SECT_V2_LOC => SectionId::DebugLoc, - constants::DW_SECT_V2_STR_OFFSETS => SectionId::DebugStrOffsets, - constants::DW_SECT_V2_MACINFO => SectionId::DebugMacinfo, - constants::DW_SECT_V2_MACRO => SectionId::DebugMacro, - _ => return Err(Error::UnknownIndexSection), - } - } else { - match constants::DwSect(section) { - constants::DW_SECT_INFO => SectionId::DebugInfo, - constants::DW_SECT_ABBREV => SectionId::DebugAbbrev, - constants::DW_SECT_LINE => SectionId::DebugLine, - constants::DW_SECT_LOCLISTS => SectionId::DebugLocLists, - constants::DW_SECT_STR_OFFSETS => SectionId::DebugStrOffsets, - constants::DW_SECT_MACRO => SectionId::DebugMacro, - constants::DW_SECT_RNGLISTS => SectionId::DebugRngLists, - _ => return Err(Error::UnknownIndexSection), - } - }; - } - - let offsets = input.split(R::Offset::from_u64( - u64::from(unit_count) * u64::from(section_count) * 4, - )?)?; - let sizes = input.split(R::Offset::from_u64( - u64::from(unit_count) * u64::from(section_count) * 4, - )?)?; - - Ok(UnitIndex { - version, - section_count, - unit_count, - slot_count, - hash_ids, - hash_rows, - sections, - offsets, - sizes, - }) - } - - /// Find `id` in the index hash table, and return the row index. - /// - /// `id` may be a compilation unit ID if this index is from `.debug_cu_index`, - /// or a type signature if this index is from `.debug_tu_index`. - pub fn find(&self, id: u64) -> Option<u32> { - if self.slot_count == 0 { - return None; - } - let mask = u64::from(self.slot_count - 1); - let mut hash1 = id & mask; - let hash2 = ((id >> 32) & mask) | 1; - for _ in 0..self.slot_count { - // The length of these arrays was validated in `UnitIndex::parse`. - let mut hash_ids = self.hash_ids.clone(); - hash_ids.skip(R::Offset::from_u64(hash1 * 8).ok()?).ok()?; - let hash_id = hash_ids.read_u64().ok()?; - if hash_id == id { - let mut hash_rows = self.hash_rows.clone(); - hash_rows.skip(R::Offset::from_u64(hash1 * 4).ok()?).ok()?; - let hash_row = hash_rows.read_u32().ok()?; - return Some(hash_row); - } - if hash_id == 0 { - return None; - } - hash1 = (hash1 + hash2) & mask; - } - None - } - - /// Return the section offsets and sizes for the given row index. - pub fn sections(&self, mut row: u32) -> Result<UnitIndexSectionIterator<R>> { - if row == 0 { - return Err(Error::InvalidIndexRow); - } - row -= 1; - if row >= self.unit_count { - return Err(Error::InvalidIndexRow); - } - let mut offsets = self.offsets.clone(); - offsets.skip(R::Offset::from_u64( - u64::from(row) * u64::from(self.section_count) * 4, - )?)?; - let mut sizes = self.sizes.clone(); - sizes.skip(R::Offset::from_u64( - u64::from(row) * u64::from(self.section_count) * 4, - )?)?; - Ok(UnitIndexSectionIterator { - sections: self.sections[..self.section_count as usize].iter(), - offsets, - sizes, - }) - } - - /// Return the version. - pub fn version(&self) -> u16 { - self.version - } - - /// Return the number of sections. - pub fn section_count(&self) -> u32 { - self.section_count - } - - /// Return the number of units. - pub fn unit_count(&self) -> u32 { - self.unit_count - } - - /// Return the number of slots. - pub fn slot_count(&self) -> u32 { - self.slot_count - } -} - -/// An iterator over the section offsets and sizes for a row in a `UnitIndex`. -#[derive(Debug, Clone)] -pub struct UnitIndexSectionIterator<'index, R: Reader> { - sections: slice::Iter<'index, SectionId>, - offsets: R, - sizes: R, -} - -impl<'index, R: Reader> Iterator for UnitIndexSectionIterator<'index, R> { - type Item = UnitIndexSection; - - fn next(&mut self) -> Option<UnitIndexSection> { - let section = *self.sections.next()?; - // The length of these arrays was validated in `UnitIndex::parse`. - let offset = self.offsets.read_u32().ok()?; - let size = self.sizes.read_u32().ok()?; - Some(UnitIndexSection { - section, - offset, - size, - }) - } -} - -/// Information about a unit's contribution to a section in a `.dwp` file. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct UnitIndexSection { - /// The section kind. - pub section: SectionId, - /// The base offset of the unit's contribution to the section. - pub offset: u32, - /// The size of the unit's contribution to the section. - pub size: u32, -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::endianity::BigEndian; - use test_assembler::{Endian, Section}; - - #[test] - fn test_empty() { - let buf = EndianSlice::new(&[], BigEndian); - let index = UnitIndex::parse(buf).unwrap(); - assert!(index.find(0).is_none()); - } - - #[test] - fn test_version_2() { - #[rustfmt::skip] - let section = Section::with_endian(Endian::Big) - // Header. - .D32(2).D32(0).D32(0).D32(1) - // Slots. - .D64(0).D32(0); - let buf = section.get_contents().unwrap(); - let buf = EndianSlice::new(&buf, BigEndian); - let index = UnitIndex::parse(buf).unwrap(); - assert_eq!(index.version, 2); - } - - #[test] - fn test_version_5() { - #[rustfmt::skip] - let section = Section::with_endian(Endian::Big) - // Header. - .D16(5).D16(0).D32(0).D32(0).D32(1) - // Slots. - .D64(0).D32(0); - let buf = section.get_contents().unwrap(); - let buf = EndianSlice::new(&buf, BigEndian); - let index = UnitIndex::parse(buf).unwrap(); - assert_eq!(index.version, 5); - } - - #[test] - fn test_version_5_invalid() { - #[rustfmt::skip] - let section = Section::with_endian(Endian::Big) - // Header. - .D32(5).D32(0).D32(0).D32(1) - // Slots. - .D64(0).D32(0); - let buf = section.get_contents().unwrap(); - let buf = EndianSlice::new(&buf, BigEndian); - assert!(UnitIndex::parse(buf).is_err()); - } - - #[test] - fn test_version_2_sections() { - #[rustfmt::skip] - let section = Section::with_endian(Endian::Big) - // Header. - .D32(2).D32(8).D32(1).D32(2) - // Slots. - .D64(0).D64(0).D32(0).D32(0) - // Sections. - .D32(constants::DW_SECT_V2_INFO.0) - .D32(constants::DW_SECT_V2_TYPES.0) - .D32(constants::DW_SECT_V2_ABBREV.0) - .D32(constants::DW_SECT_V2_LINE.0) - .D32(constants::DW_SECT_V2_LOC.0) - .D32(constants::DW_SECT_V2_STR_OFFSETS.0) - .D32(constants::DW_SECT_V2_MACINFO.0) - .D32(constants::DW_SECT_V2_MACRO.0) - // Offsets. - .D32(11).D32(12).D32(13).D32(14).D32(15).D32(16).D32(17).D32(18) - // Sizes. - .D32(21).D32(22).D32(23).D32(24).D32(25).D32(26).D32(27).D32(28); - let buf = section.get_contents().unwrap(); - let buf = EndianSlice::new(&buf, BigEndian); - let index = UnitIndex::parse(buf).unwrap(); - assert_eq!(index.section_count, 8); - assert_eq!( - index.sections, - [ - SectionId::DebugInfo, - SectionId::DebugTypes, - SectionId::DebugAbbrev, - SectionId::DebugLine, - SectionId::DebugLoc, - SectionId::DebugStrOffsets, - SectionId::DebugMacinfo, - SectionId::DebugMacro, - ] - ); - #[rustfmt::skip] - let expect = [ - UnitIndexSection { section: SectionId::DebugInfo, offset: 11, size: 21 }, - UnitIndexSection { section: SectionId::DebugTypes, offset: 12, size: 22 }, - UnitIndexSection { section: SectionId::DebugAbbrev, offset: 13, size: 23 }, - UnitIndexSection { section: SectionId::DebugLine, offset: 14, size: 24 }, - UnitIndexSection { section: SectionId::DebugLoc, offset: 15, size: 25 }, - UnitIndexSection { section: SectionId::DebugStrOffsets, offset: 16, size: 26 }, - UnitIndexSection { section: SectionId::DebugMacinfo, offset: 17, size: 27 }, - UnitIndexSection { section: SectionId::DebugMacro, offset: 18, size: 28 }, - ]; - let mut sections = index.sections(1).unwrap(); - for section in &expect { - assert_eq!(*section, sections.next().unwrap()); - } - assert!(sections.next().is_none()); - } - - #[test] - fn test_version_5_sections() { - #[rustfmt::skip] - let section = Section::with_endian(Endian::Big) - // Header. - .D16(5).D16(0).D32(7).D32(1).D32(2) - // Slots. - .D64(0).D64(0).D32(0).D32(0) - // Sections. - .D32(constants::DW_SECT_INFO.0) - .D32(constants::DW_SECT_ABBREV.0) - .D32(constants::DW_SECT_LINE.0) - .D32(constants::DW_SECT_LOCLISTS.0) - .D32(constants::DW_SECT_STR_OFFSETS.0) - .D32(constants::DW_SECT_MACRO.0) - .D32(constants::DW_SECT_RNGLISTS.0) - // Offsets. - .D32(11).D32(12).D32(13).D32(14).D32(15).D32(16).D32(17) - // Sizes. - .D32(21).D32(22).D32(23).D32(24).D32(25).D32(26).D32(27); - let buf = section.get_contents().unwrap(); - let buf = EndianSlice::new(&buf, BigEndian); - let index = UnitIndex::parse(buf).unwrap(); - assert_eq!(index.section_count, 7); - assert_eq!( - index.sections[..7], - [ - SectionId::DebugInfo, - SectionId::DebugAbbrev, - SectionId::DebugLine, - SectionId::DebugLocLists, - SectionId::DebugStrOffsets, - SectionId::DebugMacro, - SectionId::DebugRngLists, - ] - ); - #[rustfmt::skip] - let expect = [ - UnitIndexSection { section: SectionId::DebugInfo, offset: 11, size: 21 }, - UnitIndexSection { section: SectionId::DebugAbbrev, offset: 12, size: 22 }, - UnitIndexSection { section: SectionId::DebugLine, offset: 13, size: 23 }, - UnitIndexSection { section: SectionId::DebugLocLists, offset: 14, size: 24 }, - UnitIndexSection { section: SectionId::DebugStrOffsets, offset: 15, size: 25 }, - UnitIndexSection { section: SectionId::DebugMacro, offset: 16, size: 26 }, - UnitIndexSection { section: SectionId::DebugRngLists, offset: 17, size: 27 }, - ]; - let mut sections = index.sections(1).unwrap(); - for section in &expect { - assert_eq!(*section, sections.next().unwrap()); - } - assert!(sections.next().is_none()); - - assert!(index.sections(0).is_err()); - assert!(index.sections(2).is_err()); - } - - #[test] - fn test_hash() { - #[rustfmt::skip] - let section = Section::with_endian(Endian::Big) - // Header. - .D16(5).D16(0).D32(2).D32(3).D32(4) - // Slots. - .D64(0xffff_fff2_ffff_fff1) - .D64(0xffff_fff0_ffff_fff1) - .D64(0xffff_fff1_ffff_fff1) - .D64(0) - .D32(3).D32(1).D32(2).D32(0) - // Sections. - .D32(constants::DW_SECT_INFO.0) - .D32(constants::DW_SECT_ABBREV.0) - // Offsets. - .D32(0).D32(0).D32(0).D32(0).D32(0).D32(0) - // Sizes. - .D32(0).D32(0).D32(0).D32(0).D32(0).D32(0); - let buf = section.get_contents().unwrap(); - let buf = EndianSlice::new(&buf, BigEndian); - let index = UnitIndex::parse(buf).unwrap(); - assert_eq!(index.version(), 5); - assert_eq!(index.slot_count(), 4); - assert_eq!(index.unit_count(), 3); - assert_eq!(index.section_count(), 2); - assert_eq!(index.find(0xffff_fff0_ffff_fff1), Some(1)); - assert_eq!(index.find(0xffff_fff1_ffff_fff1), Some(2)); - assert_eq!(index.find(0xffff_fff2_ffff_fff1), Some(3)); - assert_eq!(index.find(0xffff_fff3_ffff_fff1), None); - } - - #[test] - fn test_cu_index() { - #[rustfmt::skip] - let section = Section::with_endian(Endian::Big) - // Header. - .D16(5).D16(0).D32(0).D32(0).D32(1) - // Slots. - .D64(0).D32(0); - let buf = section.get_contents().unwrap(); - let cu_index = DebugCuIndex::new(&buf, BigEndian); - let index = cu_index.index().unwrap(); - assert_eq!(index.version, 5); - } - - #[test] - fn test_tu_index() { - #[rustfmt::skip] - let section = Section::with_endian(Endian::Big) - // Header. - .D16(5).D16(0).D32(0).D32(0).D32(1) - // Slots. - .D64(0).D32(0); - let buf = section.get_contents().unwrap(); - let tu_index = DebugTuIndex::new(&buf, BigEndian); - let index = tu_index.index().unwrap(); - assert_eq!(index.version, 5); - } -} |