Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  index.rs

  Sprache: Rust
 

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<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(cratefn borrow<'a, F, R>(&'selfmut borrow: F) -> DebugCuIndex<R>
    where
        F: FnMut(&'a T) -> R,
    {
        borrow(&self.section).into()
    }
}

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<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(cratefn borrow<'a, F, R>(&'selfmut borrow: F) -> DebugTuIndex<R>
    where
        F: FnMut(&'a T) -> R,
    {
        borrow(&self.section).into()
    }
}

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: [IndexSectionId; 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: 0,
                section_count: 0,
                unit_count: 0,
                slot_count: 0,
                hash_ids: input.clone(),
                hash_rows: input.clone(),
                sections: [IndexSectionId::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 = [IndexSectionId::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 => 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,
        )?)?;

        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(&selfmut 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.
    ///
    /// Defaults to 0 for empty sections.
    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, IndexSectionId>,
    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: 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)]
pub enum 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.
    pub fn dwo_name(self) -> &'static str {
        let section_id = match self {
            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 {
    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_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());
    }

    #[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,
            [
                IndexSectionId::DebugInfo,
                IndexSectionId::DebugTypes,
                IndexSectionId::DebugAbbrev,
                IndexSectionId::DebugLine,
                IndexSectionId::DebugLoc,
                IndexSectionId::DebugStrOffsets,
                IndexSectionId::DebugMacinfo,
                IndexSectionId::DebugMacro,
            ]
        );
        #[rustfmt::skip]
        let expect = [
            UnitIndexSection { section: IndexSectionId::DebugInfo, offset: 11, size: 21 },
            UnitIndexSection { section: IndexSectionId::DebugTypes, offset: 12, size: 22 },
            UnitIndexSection { section: IndexSectionId::DebugAbbrev, offset: 13, size: 23 },
            UnitIndexSection { section: IndexSectionId::DebugLine, offset: 14, size: 24 },
            UnitIndexSection { section: IndexSectionId::DebugLoc, offset: 15, size: 25 },
            UnitIndexSection { section: IndexSectionId::DebugStrOffsets, offset: 16, size: 26 },
            UnitIndexSection { section: IndexSectionId::DebugMacinfo, offset: 17, size: 27 },
            UnitIndexSection { section: IndexSectionId::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],
            [
                IndexSectionId::DebugInfo,
                IndexSectionId::DebugAbbrev,
                IndexSectionId::DebugLine,
                IndexSectionId::DebugLocLists,
                IndexSectionId::DebugStrOffsets,
                IndexSectionId::DebugMacro,
                IndexSectionId::DebugRngLists,
            ]
        );
        #[rustfmt::skip]
        let expect = [
            UnitIndexSection { section: IndexSectionId::DebugInfo, offset: 11, size: 21 },
            UnitIndexSection { section: IndexSectionId::DebugAbbrev, offset: 12, size: 22 },
            UnitIndexSection { section: IndexSectionId::DebugLine, offset: 13, size: 23 },
            UnitIndexSection { section: IndexSectionId::DebugLocLists, offset: 14, size: 24 },
            UnitIndexSection { section: IndexSectionId::DebugStrOffsets, offset: 15, size: 25 },
            UnitIndexSection { section: IndexSectionId::DebugMacro, offset: 16, size: 26 },
            UnitIndexSection { section: IndexSectionId::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);
    }
}

Messung V0.5 in Prozent
C=87 H=100 G=93

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet am  2026-06-19) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

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.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik