/// The data in the `.debug_cu_index` section of a `.dwp` file. /// /// This section contains the compilation unit index. #[derive(Debug, Default, Clone, Copy)] pubstruct 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. pubfn new(section: &'input [u8], endian: Endian) -> Self { Self::from(EndianSlice::new(section, endian))
}
}
impl<T> DebugCuIndex<T> { /// Create a `DebugCuIndex` section that references the data in `self`. /// /// This is useful when `R` implements `Reader` but `T` does not. /// /// Used by `DwarfPackageSections::borrow`. pub(crate) fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugCuIndex<R> where
F: FnMut(&'a T) -> R,
{
borrow(&self.section).into()
}
}
impl<R: Reader> DebugCuIndex<R> { /// Parse the index header. pubfn 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)] pubstruct 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. pubfn new(section: &'input [u8], endian: Endian) -> Self { Self::from(EndianSlice::new(section, endian))
}
}
impl<T> DebugTuIndex<T> { /// Create a `DebugTuIndex` section that references the data in `self`. /// /// This is useful when `R` implements `Reader` but `T` does not. /// /// Used by `DwarfPackageSections::borrow`. pub(crate) fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugTuIndex<R> where
F: FnMut(&'a T) -> R,
{
borrow(&self.section).into()
}
}
// 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. letmut 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)?)?;
letmut sections = [IndexSectionId::DebugAbbrev; SECTION_COUNT_MAX as usize]; if section_count > SECTION_COUNT_MAX.into() { return Err(Error::InvalidIndexSectionCount);
} for i in0..section_count { let section = input.read_u32()?;
sections[i as usize] = if version == 2 { match constants::DwSectV2(section) {
constants::DW_SECT_V2_INFO => IndexSectionId::DebugInfo,
constants::DW_SECT_V2_TYPES => IndexSectionId::DebugTypes,
constants::DW_SECT_V2_ABBREV => IndexSectionId::DebugAbbrev,
constants::DW_SECT_V2_LINE => IndexSectionId::DebugLine,
constants::DW_SECT_V2_LOC => IndexSectionId::DebugLoc,
constants::DW_SECT_V2_STR_OFFSETS => IndexSectionId::DebugStrOffsets,
constants::DW_SECT_V2_MACINFO => IndexSectionId::DebugMacinfo,
constants::DW_SECT_V2_MACRO => IndexSectionId::DebugMacro,
section => return Err(Error::UnknownIndexSectionV2(section)),
}
} else { match constants::DwSect(section) {
constants::DW_SECT_INFO => IndexSectionId::DebugInfo,
constants::DW_SECT_ABBREV => IndexSectionId::DebugAbbrev,
constants::DW_SECT_LINE => IndexSectionId::DebugLine,
constants::DW_SECT_LOCLISTS => IndexSectionId::DebugLocLists,
constants::DW_SECT_STR_OFFSETS => IndexSectionId::DebugStrOffsets,
constants::DW_SECT_MACRO => IndexSectionId::DebugMacro,
constants::DW_SECT_RNGLISTS => IndexSectionId::DebugRngLists,
section => return Err(Error::UnknownIndexSection(section)),
}
};
}
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,
)?)?;
/// 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`. pubfn find(&self, id: u64) -> Option<u32> { ifself.slot_count == 0 { return None;
} let mask = u64::from(self.slot_count - 1); letmut hash1 = id & mask; let hash2 = ((id >> 32) & mask) | 1; for _ in0..self.slot_count { // The length of these arrays was validated in `UnitIndex::parse`. letmut 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 { letmut 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. pubfn 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);
} letmut offsets = self.offsets.clone();
offsets.skip(R::Offset::from_u64(
u64::from(row) * u64::from(self.section_count) * 4,
)?)?; letmut 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. /// /// Defaults to 0 for empty sections. pubfn version(&self) -> u16 { self.version
}
/// Return the number of sections. pubfn section_count(&self) -> u32 { self.section_count
}
/// Return the number of units. pubfn unit_count(&self) -> u32 { self.unit_count
}
/// Return the number of slots. pubfn slot_count(&self) -> u32 { self.slot_count
}
}
/// An iterator over the section offsets and sizes for a row in a `UnitIndex`. #[derive(Debug, Clone)] pubstruct UnitIndexSectionIterator<'index, R: Reader> {
sections: slice::Iter<'index, IndexSectionId>,
offsets: R,
sizes: R,
}
impl<'index, R: Reader> Iterator for UnitIndexSectionIterator<'index, R> { type Item = UnitIndexSection;
fn next(&mutself) -> 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)] pubstruct UnitIndexSection { /// The section kind. pub section: IndexSectionId, /// 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,
}
/// Section kinds which are permitted in a `.dwp` index. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pubenum IndexSectionId { /// The `.debug_abbrev.dwo` section.
DebugAbbrev, /// The `.debug_info.dwo` section.
DebugInfo, /// The `.debug_line.dwo` section.
DebugLine, /// The `.debug_loc.dwo` section.
DebugLoc, /// The `.debug_loclists.dwo` section.
DebugLocLists, /// The `.debug_macinfo.dwo` section.
DebugMacinfo, /// The `.debug_macro.dwo` section.
DebugMacro, /// The `.debug_rnglists.dwo` section.
DebugRngLists, /// The `.debug_str_offsets.dwo` section.
DebugStrOffsets, /// The `.debug_types.dwo` section.
DebugTypes,
}
impl IndexSectionId { /// Returns the ELF section name for this kind, when found in a .dwo or .dwp file. pubfn dwo_name(self) -> &'static str { let section_id = matchself {
IndexSectionId::DebugAbbrev => SectionId::DebugAbbrev,
IndexSectionId::DebugInfo => SectionId::DebugInfo,
IndexSectionId::DebugLine => SectionId::DebugLine,
IndexSectionId::DebugLoc => SectionId::DebugLoc,
IndexSectionId::DebugLocLists => SectionId::DebugLocLists,
IndexSectionId::DebugMacro => SectionId::DebugMacro,
IndexSectionId::DebugMacinfo => SectionId::DebugMacinfo,
IndexSectionId::DebugRngLists => SectionId::DebugRngLists,
IndexSectionId::DebugStrOffsets => SectionId::DebugStrOffsets,
IndexSectionId::DebugTypes => SectionId::DebugTypes,
};
section_id.dwo_name().unwrap()
}
}
#[cfg(test)] mod tests { usesuper::*; usecrate::endianity::BigEndian; use test_assembler::{Endian, Section};
#[test] fn test_empty() { let buf = EndianSlice::new(&[], BigEndian); let index = UnitIndex::parse(buf).unwrap();
assert_eq!(index.version(), 0);
assert_eq!(index.unit_count(), 0);
assert_eq!(index.slot_count(), 0);
assert!(index.find(0).is_none());
}
#[test] fn test_zero_slots() { #[rustfmt::skip] let section = Section::with_endian(Endian::Big) // Header.
.D32(2).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(), 2);
assert_eq!(index.unit_count(), 0);
assert_eq!(index.slot_count(), 0);
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());
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.