Skip to main content

gimli/read/
unit.rs

1//! Functions for parsing DWARF `.debug_info` and `.debug_types` sections.
2
3use alloc::vec::Vec;
4use core::ops::{Range, RangeFrom, RangeTo};
5
6use crate::common::{
7    DebugAbbrevOffset, DebugAddrBase, DebugAddrIndex, DebugInfoOffset, DebugLineOffset,
8    DebugLineStrOffset, DebugLocListsBase, DebugLocListsIndex, DebugMacinfoOffset,
9    DebugMacroOffset, DebugRngListsBase, DebugRngListsIndex, DebugStrOffset, DebugStrOffsetsBase,
10    DebugStrOffsetsIndex, DebugTypeSignature, DebugTypesOffset, DwoId, Encoding, Format,
11    LocationListsOffset, RawRangeListsOffset, SectionId, UnitSectionOffset,
12};
13use crate::constants;
14use crate::endianity::Endianity;
15use crate::read::abbrev::get_attribute_size;
16use crate::read::{
17    Abbreviation, Abbreviations, AttributeSpecification, DebugAbbrev, DebugStr, EndianSlice, Error,
18    Expression, Reader, ReaderAddress, ReaderOffset, Result, Section, UnitOffset,
19};
20
21impl<T: ReaderOffset> DebugInfoOffset<T> {
22    /// Convert a `.debug_info` offset to be an offset within the section containing the
23    /// given unit.
24    ///
25    /// Returns `None` if the unit is not within the `.debug_info` section.
26    pub fn to_unit_section_offset<R>(&self, unit: &UnitHeader<R>) -> Option<UnitSectionOffset<T>>
27    where
28        R: Reader<Offset = T>,
29    {
30        if unit.section != SectionId::DebugInfo {
31            return None;
32        }
33        Some(UnitSectionOffset(self.0))
34    }
35
36    /// Convert an offset to be relative to the start of the given unit,
37    /// instead of relative to the start of the `.debug_info` section.
38    ///
39    /// Returns `None` if the offset is not in bounds for the unit's entries.
40    pub fn to_unit_offset<R>(&self, unit: &UnitHeader<R>) -> Option<UnitOffset<T>>
41    where
42        R: Reader<Offset = T>,
43    {
44        self.to_unit_section_offset(unit)?.to_unit_offset(unit)
45    }
46}
47
48impl<T: ReaderOffset> DebugTypesOffset<T> {
49    /// Convert a `.debug_types` offset to be an offset within the section containing the
50    /// given unit.
51    ///
52    /// Returns `None` if the unit is not within the `.debug_types` section.
53    pub fn to_unit_section_offset<R>(&self, unit: &UnitHeader<R>) -> Option<UnitSectionOffset<T>>
54    where
55        R: Reader<Offset = T>,
56    {
57        if unit.section != SectionId::DebugTypes {
58            return None;
59        }
60        Some(UnitSectionOffset(self.0))
61    }
62
63    /// Convert an offset to be relative to the start of the given unit,
64    /// instead of relative to the start of the `.debug_types` section.
65    ///
66    /// Returns `None` if the offset is not in bounds for the unit's entries.
67    pub fn to_unit_offset<R>(&self, unit: &UnitHeader<R>) -> Option<UnitOffset<T>>
68    where
69        R: Reader<Offset = T>,
70    {
71        self.to_unit_section_offset(unit)?.to_unit_offset(unit)
72    }
73}
74
75impl<T: ReaderOffset> UnitSectionOffset<T> {
76    /// Convert an offset to be relative to the start of the given unit,
77    /// instead of relative to the start of the section.
78    ///
79    /// Returns `None` if the offset is not in bounds for the unit's entries.
80    pub fn to_unit_offset<R>(&self, unit: &UnitHeader<R>) -> Option<UnitOffset<T>>
81    where
82        R: Reader<Offset = T>,
83    {
84        let offset = UnitOffset(self.0.checked_sub(unit.offset().0)?);
85        if !unit.is_in_bounds(offset) {
86            return None;
87        }
88        Some(offset)
89    }
90
91    /// Convert an offset to be relative to the start of the `.debug_info` section,
92    /// instead of relative to the start of the section for the given unit.
93    ///
94    /// Returns `None` if the unit is not within the `.debug_info` section.
95    pub fn to_debug_info_offset<R>(&self, unit: &UnitHeader<R>) -> Option<DebugInfoOffset<T>>
96    where
97        R: Reader<Offset = T>,
98    {
99        if unit.section != SectionId::DebugInfo {
100            return None;
101        }
102        Some(DebugInfoOffset(self.0))
103    }
104
105    /// Convert an offset to be relative to the start of the `.debug_types` section,
106    /// instead of relative to the start of the section for the given unit.
107    ///
108    /// Returns `None` if the unit is not within the `.debug_types` section.
109    pub fn to_debug_types_offset<R>(&self, unit: &UnitHeader<R>) -> Option<DebugTypesOffset<T>>
110    where
111        R: Reader<Offset = T>,
112    {
113        if unit.section != SectionId::DebugTypes {
114            return None;
115        }
116        Some(DebugTypesOffset(self.0))
117    }
118}
119
120impl<T: ReaderOffset> UnitOffset<T> {
121    /// Return true if this offset is within the entries of the given unit.
122    ///
123    /// This only checks that the offset is within the range of the data for unit entries,
124    /// not that there is a valid DIE at this offset.
125    pub fn is_in_bounds<R>(&self, unit: &UnitHeader<R>) -> bool
126    where
127        R: Reader<Offset = T>,
128    {
129        unit.is_in_bounds(*self)
130    }
131
132    /// Convert an offset to be relative to the start of the section containing the unit,
133    /// instead of relative to the start of the given unit.
134    ///
135    /// Does not check that the offset is in bounds or valid. This is because often you
136    /// will know that the offset came from this unit so it must be valid.
137    /// For offsets of uncertain origin, use [`UnitOffset::is_in_bounds`] first.
138    pub fn to_unit_section_offset<R>(&self, unit: &UnitHeader<R>) -> UnitSectionOffset<T>
139    where
140        R: Reader<Offset = T>,
141    {
142        UnitSectionOffset(unit.offset().0 + self.0)
143    }
144
145    /// Convert an offset to be relative to the start of the `.debug_info` section,
146    /// instead of relative to the start of the given unit.
147    ///
148    /// Returns `None` if the unit is not within the `.debug_info` section.
149    pub fn to_debug_info_offset<R>(&self, unit: &UnitHeader<R>) -> Option<DebugInfoOffset<T>>
150    where
151        R: Reader<Offset = T>,
152    {
153        self.to_unit_section_offset(unit).to_debug_info_offset(unit)
154    }
155
156    /// Convert an offset to be relative to the start of the `.debug_types` section,
157    /// instead of relative to the start of the given unit.
158    ///
159    /// Returns `None` if the unit is not within the `.debug_types` section.
160    pub fn to_debug_types_offset<R>(&self, unit: &UnitHeader<R>) -> Option<DebugTypesOffset<T>>
161    where
162        R: Reader<Offset = T>,
163    {
164        self.to_unit_section_offset(unit)
165            .to_debug_types_offset(unit)
166    }
167}
168
169/// The `DebugInfo` struct represents the DWARF debugging information found in
170/// the `.debug_info` section.
171#[derive(Debug, Default, Clone, Copy)]
172pub struct DebugInfo<R> {
173    debug_info_section: R,
174}
175
176impl<'input, Endian> DebugInfo<EndianSlice<'input, Endian>>
177where
178    Endian: Endianity,
179{
180    /// Construct a new `DebugInfo` instance from the data in the `.debug_info`
181    /// section.
182    ///
183    /// It is the caller's responsibility to read the `.debug_info` section and
184    /// present it as a `&[u8]` slice. That means using some ELF loader on
185    /// Linux, a Mach-O loader on macOS, etc.
186    ///
187    /// ```
188    /// use gimli::{DebugInfo, LittleEndian};
189    ///
190    /// # let buf = [0x00, 0x01, 0x02, 0x03];
191    /// # let read_debug_info_section_somehow = || &buf;
192    /// let debug_info = DebugInfo::new(read_debug_info_section_somehow(), LittleEndian);
193    /// ```
194    pub fn new(debug_info_section: &'input [u8], endian: Endian) -> Self {
195        Self::from(EndianSlice::new(debug_info_section, endian))
196    }
197}
198
199impl<R: Reader> DebugInfo<R> {
200    /// Iterate the units in this `.debug_info` section.
201    ///
202    /// ```
203    /// use gimli::{DebugInfo, LittleEndian};
204    ///
205    /// # let buf = [];
206    /// # let read_debug_info_section_somehow = || &buf;
207    /// let debug_info = DebugInfo::new(read_debug_info_section_somehow(), LittleEndian);
208    ///
209    /// let mut iter = debug_info.units();
210    /// while let Some(unit) = iter.next().unwrap() {
211    ///     println!("unit's length is {}", unit.unit_length());
212    /// }
213    /// ```
214    pub fn units(&self) -> DebugInfoUnitHeadersIter<R> {
215        DebugInfoUnitHeadersIter {
216            input: self.debug_info_section.clone(),
217            offset: UnitSectionOffset(R::Offset::from_u8(0)),
218        }
219    }
220
221    /// Get the UnitHeader located at offset from this .debug_info section.
222    ///
223    ///
224    pub fn header_from_offset(&self, offset: DebugInfoOffset<R::Offset>) -> Result<UnitHeader<R>> {
225        let input = &mut self.debug_info_section.clone();
226        input.skip(offset.0)?;
227        parse_unit_header(input, SectionId::DebugInfo, UnitSectionOffset(offset.0))
228    }
229}
230
231impl<T> DebugInfo<T> {
232    /// Create a `DebugInfo` section that references the data in `self`.
233    ///
234    /// This is useful when `R` implements `Reader` but `T` does not.
235    ///
236    /// Used by `DwarfSections::borrow`.
237    pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugInfo<R>
238    where
239        F: FnMut(&'a T) -> R,
240    {
241        borrow(&self.debug_info_section).into()
242    }
243}
244
245impl<R> Section<R> for DebugInfo<R> {
246    fn id() -> SectionId {
247        SectionId::DebugInfo
248    }
249
250    fn reader(&self) -> &R {
251        &self.debug_info_section
252    }
253}
254
255impl<R> From<R> for DebugInfo<R> {
256    fn from(debug_info_section: R) -> Self {
257        DebugInfo { debug_info_section }
258    }
259}
260
261/// An iterator over the units of a .debug_info section.
262///
263/// See the [documentation on
264/// `DebugInfo::units`](./struct.DebugInfo.html#method.units) for more detail.
265#[derive(Clone, Debug)]
266pub struct DebugInfoUnitHeadersIter<R: Reader> {
267    input: R,
268    offset: UnitSectionOffset<R::Offset>,
269}
270
271impl<R: Reader> DebugInfoUnitHeadersIter<R> {
272    /// Advance the iterator to the next unit header.
273    pub fn next(&mut self) -> Result<Option<UnitHeader<R>>> {
274        if self.input.is_empty() {
275            Ok(None)
276        } else {
277            let len = self.input.len();
278            match parse_unit_header(&mut self.input, SectionId::DebugInfo, self.offset) {
279                Ok(header) => {
280                    self.offset.0 += len - self.input.len();
281                    Ok(Some(header))
282                }
283                Err(e) => {
284                    self.input.empty();
285                    Err(e)
286                }
287            }
288        }
289    }
290}
291
292#[cfg(feature = "fallible-iterator")]
293impl<R: Reader> fallible_iterator::FallibleIterator for DebugInfoUnitHeadersIter<R> {
294    type Item = UnitHeader<R>;
295    type Error = Error;
296
297    fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
298        DebugInfoUnitHeadersIter::next(self)
299    }
300}
301
302impl<R: Reader> Iterator for DebugInfoUnitHeadersIter<R> {
303    type Item = Result<UnitHeader<R>>;
304
305    fn next(&mut self) -> Option<Self::Item> {
306        DebugInfoUnitHeadersIter::next(self).transpose()
307    }
308}
309
310/// This enum specifies the type of the unit and any type
311/// specific data carried in the header (e.g. the type
312/// signature/type offset of a type unit).
313#[derive(Debug, Clone, Copy, PartialEq, Eq)]
314pub enum UnitType<Offset>
315where
316    Offset: ReaderOffset,
317{
318    /// In DWARF5, a unit with type `DW_UT_compile`. In previous DWARF versions,
319    /// any unit appearing in the .debug_info section.
320    Compilation,
321    /// In DWARF5, a unit with type `DW_UT_type`. In DWARF4, any unit appearing
322    /// in the .debug_types section.
323    Type {
324        /// The unique type signature for this type unit.
325        type_signature: DebugTypeSignature,
326        /// The offset within this type unit where the type is defined.
327        type_offset: UnitOffset<Offset>,
328    },
329    /// A unit with type `DW_UT_partial`. The root DIE of this unit should be a
330    /// `DW_TAG_partial_unit`.
331    Partial,
332    /// A unit with type `DW_UT_skeleton`. The enclosed dwo_id can be used to
333    /// link this with the corresponding `SplitCompilation` unit in a dwo file.
334    /// NB: The non-standard GNU split DWARF extension to DWARF 4 will instead
335    /// be a `Compilation` unit with the dwo_id present as an attribute on the
336    /// root DIE.
337    Skeleton(DwoId),
338    /// A unit with type `DW_UT_split_compile`. The enclosed dwo_id can be used to
339    /// link this with the corresponding `Skeleton` unit in the original binary.
340    /// NB: The non-standard GNU split DWARF extension to DWARF 4 will instead
341    /// be a `Compilation` unit with the dwo_id present as an attribute on the
342    /// root DIE.
343    SplitCompilation(DwoId),
344    /// A unit with type `DW_UT_split_type`. A split type unit is identical to a
345    /// conventional type unit except for the section in which it appears.
346    SplitType {
347        /// The unique type signature for this type unit.
348        type_signature: DebugTypeSignature,
349        /// The offset within this type unit where the type is defined.
350        type_offset: UnitOffset<Offset>,
351    },
352}
353
354impl<Offset> UnitType<Offset>
355where
356    Offset: ReaderOffset,
357{
358    // TODO: This will be used by the DWARF writing code once it
359    // supports unit types other than simple compilation units.
360    #[allow(unused)]
361    pub(crate) fn dw_ut(&self) -> constants::DwUt {
362        match self {
363            UnitType::Compilation => constants::DW_UT_compile,
364            UnitType::Type { .. } => constants::DW_UT_type,
365            UnitType::Partial => constants::DW_UT_partial,
366            UnitType::Skeleton(_) => constants::DW_UT_skeleton,
367            UnitType::SplitCompilation(_) => constants::DW_UT_split_compile,
368            UnitType::SplitType { .. } => constants::DW_UT_split_type,
369        }
370    }
371}
372
373/// The common fields for the headers of compilation units and
374/// type units.
375#[derive(Debug, Clone, Copy, PartialEq, Eq)]
376pub struct UnitHeader<R, Offset = <R as Reader>::Offset>
377where
378    R: Reader<Offset = Offset>,
379    Offset: ReaderOffset,
380{
381    encoding: Encoding,
382    unit_length: Offset,
383    unit_type: UnitType<Offset>,
384    debug_abbrev_offset: DebugAbbrevOffset<Offset>,
385    section: SectionId,
386    unit_offset: UnitSectionOffset<Offset>,
387    entries_buf: R,
388}
389
390/// Static methods.
391impl<R, Offset> UnitHeader<R, Offset>
392where
393    R: Reader<Offset = Offset>,
394    Offset: ReaderOffset,
395{
396    /// Construct a new `UnitHeader`.
397    pub fn new(
398        encoding: Encoding,
399        unit_length: Offset,
400        unit_type: UnitType<Offset>,
401        debug_abbrev_offset: DebugAbbrevOffset<Offset>,
402        section: SectionId,
403        unit_offset: UnitSectionOffset<Offset>,
404        entries_buf: R,
405    ) -> Self {
406        UnitHeader {
407            encoding,
408            unit_length,
409            unit_type,
410            debug_abbrev_offset,
411            section,
412            unit_offset,
413            entries_buf,
414        }
415    }
416}
417
418/// Instance methods.
419impl<R, Offset> UnitHeader<R, Offset>
420where
421    R: Reader<Offset = Offset>,
422    Offset: ReaderOffset,
423{
424    /// Get the ID of the section containing this unit.
425    pub fn section(&self) -> SectionId {
426        self.section
427    }
428
429    /// Get the offset of this unit within its section.
430    pub fn offset(&self) -> UnitSectionOffset<Offset> {
431        self.unit_offset
432    }
433
434    /// Get the offset of this unit as an offset within the `.debug_info` section.
435    ///
436    /// Returns `None` if this unit is not in the `.debug_info` section.
437    pub fn debug_info_offset(&self) -> Option<DebugInfoOffset<Offset>> {
438        self.unit_offset.to_debug_info_offset(self)
439    }
440
441    /// Get the offset of this unit as an offset within the `.debug_types` section.
442    ///
443    /// Returns `None` if this unit is not in the `.debug_types` section.
444    pub fn debug_types_offset(&self) -> Option<DebugTypesOffset<Offset>> {
445        self.unit_offset.to_debug_types_offset(self)
446    }
447
448    /// Return the serialized size of the common unit header for the given
449    /// DWARF format.
450    pub fn size_of_header(&self) -> usize {
451        let unit_length_size = self.encoding.format.initial_length_size() as usize;
452        let version_size = 2;
453        let debug_abbrev_offset_size = self.encoding.format.word_size() as usize;
454        let address_size_size = 1;
455        let unit_type_size = if self.encoding.version == 5 { 1 } else { 0 };
456        let type_specific_size = match self.unit_type {
457            UnitType::Compilation | UnitType::Partial => 0,
458            UnitType::Type { .. } | UnitType::SplitType { .. } => {
459                let type_signature_size = 8;
460                let type_offset_size = self.encoding.format.word_size() as usize;
461                type_signature_size + type_offset_size
462            }
463            UnitType::Skeleton(_) | UnitType::SplitCompilation(_) => 8,
464        };
465
466        unit_length_size
467            + version_size
468            + debug_abbrev_offset_size
469            + address_size_size
470            + unit_type_size
471            + type_specific_size
472    }
473
474    /// Get the length of the debugging info for this compilation unit, not
475    /// including the byte length of the encoded length itself.
476    pub fn unit_length(&self) -> Offset {
477        self.unit_length
478    }
479
480    /// Get the length of the debugging info for this compilation unit,
481    /// including the byte length of the encoded length itself.
482    pub fn length_including_self(&self) -> Offset {
483        Offset::from_u8(self.format().initial_length_size()) + self.unit_length
484    }
485
486    /// Return the encoding parameters for this unit.
487    pub fn encoding(&self) -> Encoding {
488        self.encoding
489    }
490
491    /// Get the DWARF version of the debugging info for this compilation unit.
492    pub fn version(&self) -> u16 {
493        self.encoding.version
494    }
495
496    /// Get the UnitType of this unit.
497    pub fn type_(&self) -> UnitType<Offset> {
498        self.unit_type
499    }
500
501    /// The offset into the `.debug_abbrev` section for this compilation unit's
502    /// debugging information entries' abbreviations.
503    pub fn debug_abbrev_offset(&self) -> DebugAbbrevOffset<Offset> {
504        self.debug_abbrev_offset
505    }
506
507    /// The size of addresses (in bytes) in this compilation unit.
508    pub fn address_size(&self) -> u8 {
509        self.encoding.address_size
510    }
511
512    /// Whether this compilation unit is encoded in 64- or 32-bit DWARF.
513    pub fn format(&self) -> Format {
514        self.encoding.format
515    }
516
517    /// The serialized size of the header for this compilation unit.
518    pub fn header_size(&self) -> Offset {
519        self.length_including_self() - self.entries_buf.len()
520    }
521
522    /// The unit offset of the root entry.
523    pub fn root_offset(&self) -> UnitOffset<Offset> {
524        UnitOffset(self.header_size())
525    }
526
527    pub(crate) fn is_in_bounds(&self, offset: UnitOffset<Offset>) -> bool {
528        let size_of_header = self.header_size();
529        if offset.0 < size_of_header {
530            return false;
531        }
532
533        let relative_to_entries_buf = offset.0 - size_of_header;
534        relative_to_entries_buf < self.entries_buf.len()
535    }
536
537    /// Get the underlying bytes for the supplied range.
538    pub fn range(&self, idx: Range<UnitOffset<Offset>>) -> Result<R> {
539        if !self.is_in_bounds(idx.start) {
540            return Err(Error::OffsetOutOfBounds(idx.start.0.into_u64()));
541        }
542        if !self.is_in_bounds(idx.end) {
543            return Err(Error::OffsetOutOfBounds(idx.end.0.into_u64()));
544        }
545        assert!(idx.start <= idx.end);
546        let size_of_header = self.header_size();
547        let start = idx.start.0 - size_of_header;
548        let end = idx.end.0 - size_of_header;
549        let mut input = self.entries_buf.clone();
550        input.skip(start)?;
551        input.truncate(end - start)?;
552        Ok(input)
553    }
554
555    /// Get the underlying bytes for the supplied range.
556    pub fn range_from(&self, idx: RangeFrom<UnitOffset<Offset>>) -> Result<R> {
557        if !self.is_in_bounds(idx.start) {
558            return Err(Error::OffsetOutOfBounds(idx.start.0.into_u64()));
559        }
560        let start = idx.start.0 - self.header_size();
561        let mut input = self.entries_buf.clone();
562        input.skip(start)?;
563        Ok(input)
564    }
565
566    /// Get the underlying bytes for the supplied range.
567    pub fn range_to(&self, idx: RangeTo<UnitOffset<Offset>>) -> Result<R> {
568        if !self.is_in_bounds(idx.end) {
569            return Err(Error::OffsetOutOfBounds(idx.end.0.into_u64()));
570        }
571        let end = idx.end.0 - self.header_size();
572        let mut input = self.entries_buf.clone();
573        input.truncate(end)?;
574        Ok(input)
575    }
576
577    /// Read the `DebuggingInformationEntry` at the given offset.
578    ///
579    /// Creating a `DebuggingInformationEntry` requires an allocation, so frequent use of
580    /// this method may be slow. Use methods such as [`Self::entries_at_offset`] to read
581    /// multiple entries where possible, or [`Self::entries_raw`] which does not allocate.
582    pub fn entry<'abbrev>(
583        &self,
584        abbreviations: &'abbrev Abbreviations,
585        offset: UnitOffset<Offset>,
586    ) -> Result<DebuggingInformationEntry<R>> {
587        let mut entry = DebuggingInformationEntry::null();
588        let mut input = self.entries_raw(abbreviations, Some(offset))?;
589        input.read_entry(&mut entry)?;
590        if entry.is_null() {
591            Err(Error::NoEntryAtGivenOffset(offset.0.into_u64()))
592        } else {
593            Ok(entry)
594        }
595    }
596
597    /// Navigate this unit's `DebuggingInformationEntry`s.
598    pub fn entries<'abbrev>(
599        &self,
600        abbreviations: &'abbrev Abbreviations,
601    ) -> EntriesCursor<'abbrev, R> {
602        EntriesCursor::new(
603            self.entries_buf.clone(),
604            self.encoding,
605            abbreviations,
606            self.root_offset(),
607        )
608    }
609
610    /// Navigate this compilation unit's `DebuggingInformationEntry`s
611    /// starting at the given offset.
612    pub fn entries_at_offset<'abbrev>(
613        &self,
614        abbreviations: &'abbrev Abbreviations,
615        offset: UnitOffset<Offset>,
616    ) -> Result<EntriesCursor<'abbrev, R>> {
617        Ok(EntriesCursor::new(
618            self.range_from(offset..)?,
619            self.encoding,
620            abbreviations,
621            offset,
622        ))
623    }
624
625    /// Navigate this unit's `DebuggingInformationEntry`s as a tree
626    /// starting at the given offset.
627    pub fn entries_tree<'abbrev>(
628        &self,
629        abbreviations: &'abbrev Abbreviations,
630        offset: Option<UnitOffset<Offset>>,
631    ) -> Result<EntriesTree<'abbrev, R>> {
632        let offset = offset.unwrap_or_else(|| self.root_offset());
633        Ok(EntriesTree::new(
634            self.range_from(offset..)?,
635            self.encoding,
636            abbreviations,
637            offset,
638        ))
639    }
640
641    /// Read the raw data that defines the Debugging Information Entries.
642    pub fn entries_raw<'abbrev>(
643        &self,
644        abbreviations: &'abbrev Abbreviations,
645        offset: Option<UnitOffset<Offset>>,
646    ) -> Result<EntriesRaw<'abbrev, R>> {
647        let offset = offset.unwrap_or_else(|| self.root_offset());
648        Ok(EntriesRaw::new(
649            self.range_from(offset..)?,
650            self.encoding,
651            abbreviations,
652            offset,
653        ))
654    }
655
656    /// Parse this unit's abbreviations.
657    pub fn abbreviations(&self, debug_abbrev: &DebugAbbrev<R>) -> Result<Abbreviations> {
658        debug_abbrev.abbreviations(self.debug_abbrev_offset())
659    }
660
661    /// Return true if the given address is a tombstone.
662    ///
663    /// This currently checks if the address is -1 or -2 for the address size of the unit.
664    ///
665    /// Note that this cannot detect the use of 0 as a tombstone since that is ambiguous.
666    /// The caller must use their own knowledge of valid address ranges to determine that
667    /// if required.
668    pub fn is_tombstone_address(&self, address: u64) -> bool {
669        address >= u64::min_tombstone(self.encoding.address_size)
670    }
671}
672
673/// Parse a unit header.
674fn parse_unit_header<R, Offset>(
675    input: &mut R,
676    section: SectionId,
677    unit_offset: UnitSectionOffset<Offset>,
678) -> Result<UnitHeader<R>>
679where
680    R: Reader<Offset = Offset>,
681    Offset: ReaderOffset,
682{
683    let (unit_length, format) = input.read_initial_length()?;
684    let mut rest = input.split(unit_length)?;
685
686    let version = rest.read_u16()?;
687    let abbrev_offset;
688    let address_size;
689    let unit_type;
690    // DWARF 1 was very different, and is obsolete, so isn't supported by this
691    // reader.
692    if 2 <= version && version <= 4 {
693        abbrev_offset = rest.read_offset(format).map(DebugAbbrevOffset)?;
694        address_size = rest.read_address_size()?;
695        // Before DWARF5, all units in the .debug_info section are compilation
696        // units, and all units in the .debug_types section are type units.
697        unit_type = match section {
698            SectionId::DebugTypes => constants::DW_UT_type,
699            _ => constants::DW_UT_compile,
700        };
701    } else if version == 5 {
702        unit_type = rest.read_u8().map(constants::DwUt)?;
703        address_size = rest.read_address_size()?;
704        abbrev_offset = rest.read_offset(format).map(DebugAbbrevOffset)?;
705    } else {
706        return Err(Error::UnknownVersion(u64::from(version)));
707    }
708    let encoding = Encoding {
709        format,
710        version,
711        address_size,
712    };
713
714    // Parse any data specific to this type of unit.
715    let unit_type = match unit_type {
716        constants::DW_UT_compile => UnitType::Compilation,
717        constants::DW_UT_type => {
718            let type_signature = rest.read_u64().map(DebugTypeSignature)?;
719            let type_offset = rest.read_offset(format).map(UnitOffset)?;
720            UnitType::Type {
721                type_signature,
722                type_offset,
723            }
724        }
725        constants::DW_UT_partial => UnitType::Partial,
726        constants::DW_UT_skeleton => {
727            let dwo_id = rest.read_u64().map(DwoId)?;
728            UnitType::Skeleton(dwo_id)
729        }
730        constants::DW_UT_split_compile => {
731            let dwo_id = rest.read_u64().map(DwoId)?;
732            UnitType::SplitCompilation(dwo_id)
733        }
734        constants::DW_UT_split_type => {
735            let type_signature = rest.read_u64().map(DebugTypeSignature)?;
736            let type_offset = rest.read_offset(format).map(UnitOffset)?;
737            UnitType::SplitType {
738                type_signature,
739                type_offset,
740            }
741        }
742        _ => return Err(Error::UnknownUnitType(unit_type)),
743    };
744
745    Ok(UnitHeader::new(
746        encoding,
747        unit_length,
748        unit_type,
749        abbrev_offset,
750        section,
751        unit_offset,
752        rest,
753    ))
754}
755
756/// A Debugging Information Entry (DIE).
757///
758/// DIEs have a set of attributes and optionally have children DIEs as well.
759///
760/// Creating a `DebuggingInformationEntry` requires an allocation, so frequent cloning of
761/// this struct may be slow.
762#[derive(Clone, Debug)]
763pub struct DebuggingInformationEntry<R, Offset = <R as Reader>::Offset>
764where
765    R: Reader<Offset = Offset>,
766    Offset: ReaderOffset,
767{
768    /// The DWARF tag for this entry.
769    pub tag: constants::DwTag,
770    /// Whether this entry has a null terminated list of children.
771    ///
772    /// Note that this list may be empty.
773    pub has_children: bool,
774    /// This entry's attributes.
775    pub attrs: Vec<Attribute<R>>,
776    /// The offset within the unit of this entry.
777    pub offset: UnitOffset<Offset>,
778    /// The tree depth of this entry relative to the entry where reading started.
779    pub depth: isize,
780}
781
782impl<R, Offset> Default for DebuggingInformationEntry<R, Offset>
783where
784    R: Reader<Offset = Offset>,
785    Offset: ReaderOffset,
786{
787    fn default() -> Self {
788        Self::null()
789    }
790}
791
792impl<R, Offset> DebuggingInformationEntry<R, Offset>
793where
794    R: Reader<Offset = Offset>,
795    Offset: ReaderOffset,
796{
797    /// Construct a new `DebuggingInformationEntry`.
798    pub fn new(
799        tag: constants::DwTag,
800        has_children: bool,
801        attrs: Vec<Attribute<R>>,
802        offset: UnitOffset<Offset>,
803    ) -> Self {
804        DebuggingInformationEntry {
805            tag,
806            has_children,
807            attrs,
808            offset,
809            depth: 0,
810        }
811    }
812
813    /// Construct a new `DebuggingInformationEntry` with no tag or attributes.
814    pub fn null() -> Self {
815        DebuggingInformationEntry {
816            tag: constants::DW_TAG_null,
817            has_children: false,
818            attrs: Vec::new(),
819            offset: UnitOffset(Offset::from_u8(0)),
820            depth: 0,
821        }
822    }
823
824    /// Return true if the entry tag is `DW_TAG_null`.
825    pub fn is_null(&self) -> bool {
826        self.tag == constants::DW_TAG_null
827    }
828
829    /// Set the entry to a null entry.
830    ///
831    /// This sets the tag to `DW_TAG_null`, and resets the `has_children` and `attrs` fields.
832    pub fn set_null(&mut self) {
833        self.tag = constants::DW_TAG_null;
834        self.has_children = false;
835        self.attrs.clear();
836    }
837
838    /// Get the tree depth of this entry relative to the entry where reading started.
839    pub fn depth(&self) -> isize {
840        self.depth
841    }
842
843    /// Get this entry's offset.
844    pub fn offset(&self) -> UnitOffset<Offset> {
845        self.offset
846    }
847
848    /// Get this entry's tag.
849    pub fn tag(&self) -> constants::DwTag {
850        self.tag
851    }
852
853    /// Return true if this entry's type can have children, false otherwise.
854    pub fn has_children(&self) -> bool {
855        self.has_children
856    }
857
858    /// Return this entry's set of attributes.
859    pub fn attrs(&self) -> &[Attribute<R>] {
860        &self.attrs
861    }
862
863    /// Return true if this entry has an attribute with the given name.
864    pub fn has_attr(&self, name: constants::DwAt) -> bool {
865        self.attrs.iter().any(|attr| attr.name == name)
866    }
867
868    /// Find the first attribute in this entry which has the given name.
869    ///
870    /// Returns `None` if no attribute is found.
871    pub fn attr(&self, name: constants::DwAt) -> Option<&Attribute<R>> {
872        self.attrs.iter().find(|attr| attr.name == name)
873    }
874
875    /// Find the first attribute in this entry which has the given name,
876    /// and return its raw value.
877    ///
878    /// Returns `None` if no attribute is found.
879    pub fn attr_value_raw(&self, name: constants::DwAt) -> Option<AttributeValue<R>> {
880        self.attr(name).map(Attribute::raw_value)
881    }
882
883    /// Find the first attribute in this entry which has the given name,
884    /// and return its normalized value.
885    ///
886    /// Returns `None` if no attribute is found.
887    pub fn attr_value(&self, name: constants::DwAt) -> Option<AttributeValue<R>> {
888        self.attr(name).map(Attribute::value)
889    }
890
891    /// Use the `DW_AT_sibling` attribute to find the offset for the
892    /// next sibling. Returns `None` if the attribute is missing or invalid.
893    fn sibling(&self) -> Option<UnitOffset<R::Offset>> {
894        if let Some(AttributeValue::UnitRef(offset)) = self.attr_value(constants::DW_AT_sibling)
895            && offset.0 > self.offset.0
896        {
897            return Some(offset);
898        }
899        None
900    }
901}
902
903/// The value of an attribute in a `DebuggingInformationEntry`.
904//
905// Set the discriminant size so that all variants use the same alignment
906// for their data.  This gives better code generation in `parse_attribute`.
907#[repr(u64)]
908#[derive(Clone, Copy, Debug, Eq, PartialEq)]
909pub enum AttributeValue<R, Offset = <R as Reader>::Offset>
910where
911    R: Reader<Offset = Offset>,
912    Offset: ReaderOffset,
913{
914    /// "Refers to some location in the address space of the described program."
915    Addr(u64),
916
917    /// A slice of an arbitrary number of bytes.
918    Block(R),
919
920    /// A one byte constant data value. How to interpret the byte depends on context.
921    ///
922    /// From section 7 of the standard: "Depending on context, it may be a
923    /// signed integer, an unsigned integer, a floating-point constant, or
924    /// anything else."
925    Data1(u8),
926
927    /// A two byte constant data value. How to interpret the bytes depends on context.
928    ///
929    /// These bytes have been converted from `R::Endian`. This may need to be reversed
930    /// if this was not required.
931    ///
932    /// From section 7 of the standard: "Depending on context, it may be a
933    /// signed integer, an unsigned integer, a floating-point constant, or
934    /// anything else."
935    Data2(u16),
936
937    /// A four byte constant data value. How to interpret the bytes depends on context.
938    ///
939    /// These bytes have been converted from `R::Endian`. This may need to be reversed
940    /// if this was not required.
941    ///
942    /// From section 7 of the standard: "Depending on context, it may be a
943    /// signed integer, an unsigned integer, a floating-point constant, or
944    /// anything else."
945    Data4(u32),
946
947    /// An eight byte constant data value. How to interpret the bytes depends on context.
948    ///
949    /// These bytes have been converted from `R::Endian`. This may need to be reversed
950    /// if this was not required.
951    ///
952    /// From section 7 of the standard: "Depending on context, it may be a
953    /// signed integer, an unsigned integer, a floating-point constant, or
954    /// anything else."
955    Data8(u64),
956
957    /// An sixteen byte constant data value. How to interpret the bytes depends on context.
958    ///
959    /// These bytes have been converted from `R::Endian`. This may need to be reversed
960    /// if this was not required.
961    ///
962    /// From section 7 of the standard: "Depending on context, it may be a
963    /// signed integer, an unsigned integer, a floating-point constant, or
964    /// anything else."
965    Data16(u128),
966
967    /// A signed integer constant.
968    Sdata(i64),
969
970    /// An unsigned integer constant.
971    Udata(u64),
972
973    /// "The information bytes contain a DWARF expression (see Section 2.5) or
974    /// location description (see Section 2.6)."
975    Exprloc(Expression<R>),
976
977    /// A boolean that indicates presence or absence of the attribute.
978    Flag(bool),
979
980    /// An offset into another section. Which section this is an offset into
981    /// depends on context.
982    SecOffset(Offset),
983
984    /// An offset to a set of addresses in the `.debug_addr` section.
985    DebugAddrBase(DebugAddrBase<Offset>),
986
987    /// An index into a set of addresses in the `.debug_addr` section.
988    DebugAddrIndex(DebugAddrIndex<Offset>),
989
990    /// An offset into the current compilation unit.
991    UnitRef(UnitOffset<Offset>),
992
993    /// An offset into the current `.debug_info` section, but possibly a
994    /// different compilation unit from the current one.
995    DebugInfoRef(DebugInfoOffset<Offset>),
996
997    /// An offset into the `.debug_info` section of the supplementary object file.
998    DebugInfoRefSup(DebugInfoOffset<Offset>),
999
1000    /// An offset into the `.debug_line` section.
1001    DebugLineRef(DebugLineOffset<Offset>),
1002
1003    /// An offset into either the `.debug_loc` section or the `.debug_loclists` section.
1004    LocationListsRef(LocationListsOffset<Offset>),
1005
1006    /// An offset to a set of offsets in the `.debug_loclists` section.
1007    DebugLocListsBase(DebugLocListsBase<Offset>),
1008
1009    /// An index into a set of offsets in the `.debug_loclists` section.
1010    DebugLocListsIndex(DebugLocListsIndex<Offset>),
1011
1012    /// An offset into the `.debug_macinfo` section.
1013    DebugMacinfoRef(DebugMacinfoOffset<Offset>),
1014
1015    /// An offset into the `.debug_macro` section.
1016    DebugMacroRef(DebugMacroOffset<Offset>),
1017
1018    /// An offset into the `.debug_ranges` section.
1019    RangeListsRef(RawRangeListsOffset<Offset>),
1020
1021    /// An offset to a set of offsets in the `.debug_rnglists` section.
1022    DebugRngListsBase(DebugRngListsBase<Offset>),
1023
1024    /// An index into a set of offsets in the `.debug_rnglists` section.
1025    DebugRngListsIndex(DebugRngListsIndex<Offset>),
1026
1027    /// A type signature.
1028    DebugTypesRef(DebugTypeSignature),
1029
1030    /// An offset into the `.debug_str` section.
1031    DebugStrRef(DebugStrOffset<Offset>),
1032
1033    /// An offset into the `.debug_str` section of the supplementary object file.
1034    DebugStrRefSup(DebugStrOffset<Offset>),
1035
1036    /// An offset to a set of entries in the `.debug_str_offsets` section.
1037    DebugStrOffsetsBase(DebugStrOffsetsBase<Offset>),
1038
1039    /// An index into a set of entries in the `.debug_str_offsets` section.
1040    DebugStrOffsetsIndex(DebugStrOffsetsIndex<Offset>),
1041
1042    /// An offset into the `.debug_line_str` section.
1043    DebugLineStrRef(DebugLineStrOffset<Offset>),
1044
1045    /// A slice of bytes representing a string. Does not include a final null byte.
1046    /// Not guaranteed to be UTF-8 or anything like that.
1047    String(R),
1048
1049    /// The value of a `DW_AT_encoding` attribute.
1050    Encoding(constants::DwAte),
1051
1052    /// The value of a `DW_AT_decimal_sign` attribute.
1053    DecimalSign(constants::DwDs),
1054
1055    /// The value of a `DW_AT_endianity` attribute.
1056    Endianity(constants::DwEnd),
1057
1058    /// The value of a `DW_AT_accessibility` attribute.
1059    Accessibility(constants::DwAccess),
1060
1061    /// The value of a `DW_AT_visibility` attribute.
1062    Visibility(constants::DwVis),
1063
1064    /// The value of a `DW_AT_virtuality` attribute.
1065    Virtuality(constants::DwVirtuality),
1066
1067    /// The value of a `DW_AT_language` attribute.
1068    Language(constants::DwLang),
1069
1070    /// The value of a `DW_AT_address_class` attribute.
1071    AddressClass(constants::DwAddr),
1072
1073    /// The value of a `DW_AT_identifier_case` attribute.
1074    IdentifierCase(constants::DwId),
1075
1076    /// The value of a `DW_AT_calling_convention` attribute.
1077    CallingConvention(constants::DwCc),
1078
1079    /// The value of a `DW_AT_inline` attribute.
1080    Inline(constants::DwInl),
1081
1082    /// The value of a `DW_AT_ordering` attribute.
1083    Ordering(constants::DwOrd),
1084
1085    /// An index into the filename entries from the line number information
1086    /// table for the compilation unit containing this value.
1087    FileIndex(u64),
1088
1089    /// An implementation-defined identifier uniquely identifying a compilation
1090    /// unit.
1091    DwoId(DwoId),
1092}
1093
1094/// An attribute in a `DebuggingInformationEntry`, consisting of a name and
1095/// associated value.
1096#[derive(Copy, Clone, Debug, Eq, PartialEq)]
1097pub struct Attribute<R: Reader> {
1098    name: constants::DwAt,
1099    form: constants::DwForm,
1100    value: AttributeValue<R>,
1101}
1102
1103impl<R: Reader> Attribute<R> {
1104    /// Get this attribute's name.
1105    pub fn name(&self) -> constants::DwAt {
1106        self.name
1107    }
1108
1109    /// Get the form that was used to encode this attribute's value.
1110    pub fn form(&self) -> constants::DwForm {
1111        self.form
1112    }
1113
1114    /// Get this attribute's raw value.
1115    pub fn raw_value(&self) -> AttributeValue<R> {
1116        self.value.clone()
1117    }
1118
1119    /// Get this attribute's normalized value.
1120    ///
1121    /// Attribute values can potentially be encoded in multiple equivalent forms,
1122    /// and may have special meaning depending on the attribute name.  This method
1123    /// converts the attribute value to a normalized form based on the attribute
1124    /// name.
1125    ///
1126    /// See "Table 7.5: Attribute encodings" and "Table 7.6: Attribute form encodings".
1127    pub fn value(&self) -> AttributeValue<R> {
1128        // Table 7.5 shows the possible attribute classes for each name.
1129        // Table 7.6 shows the possible attribute classes for each form.
1130        // For each attribute name, we need to match on the form, and
1131        // convert it to one of the classes that is allowed for both
1132        // the name and the form.
1133        //
1134        // The individual class conversions rarely vary for each name,
1135        // so for each class conversion we define a macro that matches
1136        // on the allowed forms for that class.
1137        //
1138        // For some classes, we don't need to do any conversion, so their
1139        // macro is empty.  In the future we may want to fill them in to
1140        // provide strict checking of the forms for each class.  For now,
1141        // they simply provide a way to document the allowed classes for
1142        // each name.
1143
1144        // DW_FORM_addr
1145        // DW_FORM_addrx
1146        // DW_FORM_addrx1
1147        // DW_FORM_addrx2
1148        // DW_FORM_addrx3
1149        // DW_FORM_addrx4
1150        macro_rules! address {
1151            () => {};
1152        }
1153        // DW_FORM_sec_offset
1154        macro_rules! addrptr {
1155            () => {
1156                if let Some(offset) = self.offset_value() {
1157                    return AttributeValue::DebugAddrBase(DebugAddrBase(offset));
1158                }
1159            };
1160        }
1161        // DW_FORM_block
1162        // DW_FORM_block1
1163        // DW_FORM_block2
1164        // DW_FORM_block4
1165        macro_rules! block {
1166            () => {};
1167        }
1168        // DW_FORM_sdata
1169        // DW_FORM_udata
1170        // DW_FORM_data1
1171        // DW_FORM_data2
1172        // DW_FORM_data4
1173        // DW_FORM_data8
1174        // DW_FORM_data16
1175        // DW_FORM_implicit_const
1176        macro_rules! constant {
1177            ($value:ident, $variant:ident) => {
1178                if let Some(value) = self.$value() {
1179                    return AttributeValue::$variant(value);
1180                }
1181            };
1182            ($value:ident, $variant:ident, $constant:ident) => {
1183                if let Some(value) = self.$value() {
1184                    return AttributeValue::$variant(constants::$constant(value));
1185                }
1186            };
1187        }
1188        // DW_FORM_exprloc
1189        macro_rules! exprloc {
1190            () => {
1191                if let Some(value) = self.exprloc_value() {
1192                    return AttributeValue::Exprloc(value);
1193                }
1194            };
1195        }
1196        // DW_FORM_flag
1197        // DW_FORM_flag_present
1198        macro_rules! flag {
1199            () => {};
1200        }
1201        // DW_FORM_sec_offset
1202        macro_rules! lineptr {
1203            () => {
1204                if let Some(offset) = self.offset_value() {
1205                    return AttributeValue::DebugLineRef(DebugLineOffset(offset));
1206                }
1207            };
1208        }
1209        // This also covers `loclist` in DWARF version 5.
1210        // DW_FORM_sec_offset
1211        // DW_FORM_loclistx
1212        macro_rules! loclistptr {
1213            () => {
1214                // DebugLocListsIndex is also an allowed form in DWARF version 5.
1215                if let Some(offset) = self.offset_value() {
1216                    return AttributeValue::LocationListsRef(LocationListsOffset(offset));
1217                }
1218            };
1219        }
1220        // DW_FORM_sec_offset
1221        macro_rules! loclistsptr {
1222            () => {
1223                if let Some(offset) = self.offset_value() {
1224                    return AttributeValue::DebugLocListsBase(DebugLocListsBase(offset));
1225                }
1226            };
1227        }
1228        // DWARF version <= 4.
1229        // DW_FORM_sec_offset
1230        macro_rules! macinfoptr {
1231            () => {
1232                if let Some(offset) = self.offset_value() {
1233                    return AttributeValue::DebugMacinfoRef(DebugMacinfoOffset(offset));
1234                }
1235            };
1236        }
1237        // DWARF version >= 5.
1238        // DW_FORM_sec_offset
1239        macro_rules! macroptr {
1240            () => {
1241                if let Some(offset) = self.offset_value() {
1242                    return AttributeValue::DebugMacroRef(DebugMacroOffset(offset));
1243                }
1244            };
1245        }
1246        // DW_FORM_ref_addr
1247        // DW_FORM_ref1
1248        // DW_FORM_ref2
1249        // DW_FORM_ref4
1250        // DW_FORM_ref8
1251        // DW_FORM_ref_udata
1252        // DW_FORM_ref_sig8
1253        // DW_FORM_ref_sup4
1254        // DW_FORM_ref_sup8
1255        macro_rules! reference {
1256            () => {};
1257        }
1258        // This also covers `rnglist` in DWARF version 5.
1259        // DW_FORM_sec_offset
1260        // DW_FORM_rnglistx
1261        macro_rules! rangelistptr {
1262            () => {
1263                // DebugRngListsIndex is also an allowed form in DWARF version 5.
1264                if let Some(offset) = self.offset_value() {
1265                    return AttributeValue::RangeListsRef(RawRangeListsOffset(offset));
1266                }
1267            };
1268        }
1269        // DW_FORM_sec_offset
1270        macro_rules! rnglistsptr {
1271            () => {
1272                if let Some(offset) = self.offset_value() {
1273                    return AttributeValue::DebugRngListsBase(DebugRngListsBase(offset));
1274                }
1275            };
1276        }
1277        // DW_FORM_string
1278        // DW_FORM_strp
1279        // DW_FORM_strx
1280        // DW_FORM_strx1
1281        // DW_FORM_strx2
1282        // DW_FORM_strx3
1283        // DW_FORM_strx4
1284        // DW_FORM_strp_sup
1285        // DW_FORM_line_strp
1286        macro_rules! string {
1287            () => {};
1288        }
1289        // DW_FORM_sec_offset
1290        macro_rules! stroffsetsptr {
1291            () => {
1292                if let Some(offset) = self.offset_value() {
1293                    return AttributeValue::DebugStrOffsetsBase(DebugStrOffsetsBase(offset));
1294                }
1295            };
1296        }
1297        // This isn't a separate form but it's useful to distinguish it from a generic udata.
1298        macro_rules! dwoid {
1299            () => {
1300                if let Some(value) = self.udata_value() {
1301                    return AttributeValue::DwoId(DwoId(value));
1302                }
1303            };
1304        }
1305
1306        // Perform the allowed class conversions for each attribute name.
1307        match self.name {
1308            constants::DW_AT_sibling => {
1309                reference!();
1310            }
1311            constants::DW_AT_location => {
1312                exprloc!();
1313                loclistptr!();
1314            }
1315            constants::DW_AT_name => {
1316                string!();
1317            }
1318            constants::DW_AT_ordering => {
1319                constant!(u8_value, Ordering, DwOrd);
1320            }
1321            constants::DW_AT_byte_size
1322            | constants::DW_AT_bit_offset
1323            | constants::DW_AT_bit_size => {
1324                constant!(udata_value, Udata);
1325                exprloc!();
1326                reference!();
1327            }
1328            constants::DW_AT_stmt_list => {
1329                lineptr!();
1330            }
1331            constants::DW_AT_low_pc => {
1332                address!();
1333            }
1334            constants::DW_AT_high_pc => {
1335                address!();
1336                constant!(udata_value, Udata);
1337            }
1338            constants::DW_AT_language => {
1339                constant!(u16_value, Language, DwLang);
1340            }
1341            constants::DW_AT_discr => {
1342                reference!();
1343            }
1344            constants::DW_AT_discr_value => {
1345                // constant: depends on type of DW_TAG_variant_part,
1346                // so caller must normalize.
1347            }
1348            constants::DW_AT_visibility => {
1349                constant!(u8_value, Visibility, DwVis);
1350            }
1351            constants::DW_AT_import => {
1352                reference!();
1353            }
1354            constants::DW_AT_string_length => {
1355                exprloc!();
1356                loclistptr!();
1357                reference!();
1358            }
1359            constants::DW_AT_common_reference => {
1360                reference!();
1361            }
1362            constants::DW_AT_comp_dir => {
1363                string!();
1364            }
1365            constants::DW_AT_const_value => {
1366                // TODO: constant: sign depends on DW_AT_type.
1367                block!();
1368                string!();
1369            }
1370            constants::DW_AT_containing_type => {
1371                reference!();
1372            }
1373            constants::DW_AT_default_value => {
1374                // TODO: constant: sign depends on DW_AT_type.
1375                reference!();
1376                flag!();
1377            }
1378            constants::DW_AT_inline => {
1379                constant!(u8_value, Inline, DwInl);
1380            }
1381            constants::DW_AT_is_optional => {
1382                flag!();
1383            }
1384            constants::DW_AT_lower_bound => {
1385                // TODO: constant: sign depends on DW_AT_type.
1386                exprloc!();
1387                reference!();
1388            }
1389            constants::DW_AT_producer => {
1390                string!();
1391            }
1392            constants::DW_AT_prototyped => {
1393                flag!();
1394            }
1395            constants::DW_AT_return_addr => {
1396                exprloc!();
1397                loclistptr!();
1398            }
1399            constants::DW_AT_start_scope => {
1400                // TODO: constant
1401                rangelistptr!();
1402            }
1403            constants::DW_AT_bit_stride => {
1404                constant!(udata_value, Udata);
1405                exprloc!();
1406                reference!();
1407            }
1408            constants::DW_AT_upper_bound => {
1409                // TODO: constant: sign depends on DW_AT_type.
1410                exprloc!();
1411                reference!();
1412            }
1413            constants::DW_AT_abstract_origin => {
1414                reference!();
1415            }
1416            constants::DW_AT_accessibility => {
1417                constant!(u8_value, Accessibility, DwAccess);
1418            }
1419            constants::DW_AT_address_class => {
1420                constant!(udata_value, AddressClass, DwAddr);
1421            }
1422            constants::DW_AT_artificial => {
1423                flag!();
1424            }
1425            constants::DW_AT_base_types => {
1426                reference!();
1427            }
1428            constants::DW_AT_calling_convention => {
1429                constant!(u8_value, CallingConvention, DwCc);
1430            }
1431            constants::DW_AT_count => {
1432                // TODO: constant
1433                exprloc!();
1434                reference!();
1435            }
1436            constants::DW_AT_data_member_location => {
1437                // Constants must be handled before loclistptr so that DW_FORM_data4/8
1438                // are correctly interpreted for DWARF version 4+.
1439                constant!(udata_value, Udata);
1440                exprloc!();
1441                loclistptr!();
1442            }
1443            constants::DW_AT_decl_column => {
1444                constant!(udata_value, Udata);
1445            }
1446            constants::DW_AT_decl_file => {
1447                constant!(udata_value, FileIndex);
1448            }
1449            constants::DW_AT_decl_line => {
1450                constant!(udata_value, Udata);
1451            }
1452            constants::DW_AT_declaration => {
1453                flag!();
1454            }
1455            constants::DW_AT_discr_list => {
1456                block!();
1457            }
1458            constants::DW_AT_encoding => {
1459                constant!(u8_value, Encoding, DwAte);
1460            }
1461            constants::DW_AT_external => {
1462                flag!();
1463            }
1464            constants::DW_AT_frame_base => {
1465                exprloc!();
1466                loclistptr!();
1467            }
1468            constants::DW_AT_friend => {
1469                reference!();
1470            }
1471            constants::DW_AT_identifier_case => {
1472                constant!(u8_value, IdentifierCase, DwId);
1473            }
1474            constants::DW_AT_macro_info => {
1475                macinfoptr!();
1476            }
1477            constants::DW_AT_namelist_item => {
1478                reference!();
1479            }
1480            constants::DW_AT_priority => {
1481                reference!();
1482            }
1483            constants::DW_AT_segment => {
1484                exprloc!();
1485                loclistptr!();
1486            }
1487            constants::DW_AT_specification => {
1488                reference!();
1489            }
1490            constants::DW_AT_static_link => {
1491                exprloc!();
1492                loclistptr!();
1493            }
1494            constants::DW_AT_type => {
1495                reference!();
1496            }
1497            constants::DW_AT_use_location => {
1498                exprloc!();
1499                loclistptr!();
1500            }
1501            constants::DW_AT_variable_parameter => {
1502                flag!();
1503            }
1504            constants::DW_AT_virtuality => {
1505                constant!(u8_value, Virtuality, DwVirtuality);
1506            }
1507            constants::DW_AT_vtable_elem_location => {
1508                exprloc!();
1509                loclistptr!();
1510            }
1511            constants::DW_AT_allocated => {
1512                // TODO: constant
1513                exprloc!();
1514                reference!();
1515            }
1516            constants::DW_AT_associated => {
1517                // TODO: constant
1518                exprloc!();
1519                reference!();
1520            }
1521            constants::DW_AT_data_location => {
1522                exprloc!();
1523            }
1524            constants::DW_AT_byte_stride => {
1525                constant!(udata_value, Udata);
1526                exprloc!();
1527                reference!();
1528            }
1529            constants::DW_AT_entry_pc => {
1530                // TODO: constant
1531                address!();
1532            }
1533            constants::DW_AT_use_UTF8 => {
1534                flag!();
1535            }
1536            constants::DW_AT_extension => {
1537                reference!();
1538            }
1539            constants::DW_AT_ranges => {
1540                rangelistptr!();
1541            }
1542            constants::DW_AT_trampoline => {
1543                address!();
1544                flag!();
1545                reference!();
1546                string!();
1547            }
1548            constants::DW_AT_call_column => {
1549                constant!(udata_value, Udata);
1550            }
1551            constants::DW_AT_call_file => {
1552                constant!(udata_value, FileIndex);
1553            }
1554            constants::DW_AT_call_line => {
1555                constant!(udata_value, Udata);
1556            }
1557            constants::DW_AT_description => {
1558                string!();
1559            }
1560            constants::DW_AT_binary_scale => {
1561                // TODO: constant
1562            }
1563            constants::DW_AT_decimal_scale => {
1564                // TODO: constant
1565            }
1566            constants::DW_AT_small => {
1567                reference!();
1568            }
1569            constants::DW_AT_decimal_sign => {
1570                constant!(u8_value, DecimalSign, DwDs);
1571            }
1572            constants::DW_AT_digit_count => {
1573                // TODO: constant
1574            }
1575            constants::DW_AT_picture_string => {
1576                string!();
1577            }
1578            constants::DW_AT_mutable => {
1579                flag!();
1580            }
1581            constants::DW_AT_threads_scaled => {
1582                flag!();
1583            }
1584            constants::DW_AT_explicit => {
1585                flag!();
1586            }
1587            constants::DW_AT_object_pointer => {
1588                reference!();
1589            }
1590            constants::DW_AT_endianity => {
1591                constant!(u8_value, Endianity, DwEnd);
1592            }
1593            constants::DW_AT_elemental => {
1594                flag!();
1595            }
1596            constants::DW_AT_pure => {
1597                flag!();
1598            }
1599            constants::DW_AT_recursive => {
1600                flag!();
1601            }
1602            constants::DW_AT_signature => {
1603                reference!();
1604            }
1605            constants::DW_AT_main_subprogram => {
1606                flag!();
1607            }
1608            constants::DW_AT_data_bit_offset => {
1609                // TODO: constant
1610            }
1611            constants::DW_AT_const_expr => {
1612                flag!();
1613            }
1614            constants::DW_AT_enum_class => {
1615                flag!();
1616            }
1617            constants::DW_AT_linkage_name => {
1618                string!();
1619            }
1620            constants::DW_AT_string_length_bit_size => {
1621                // TODO: constant
1622            }
1623            constants::DW_AT_string_length_byte_size => {
1624                // TODO: constant
1625            }
1626            constants::DW_AT_rank => {
1627                // TODO: constant
1628                exprloc!();
1629            }
1630            constants::DW_AT_str_offsets_base => {
1631                stroffsetsptr!();
1632            }
1633            constants::DW_AT_addr_base | constants::DW_AT_GNU_addr_base => {
1634                addrptr!();
1635            }
1636            constants::DW_AT_rnglists_base | constants::DW_AT_GNU_ranges_base => {
1637                rnglistsptr!();
1638            }
1639            constants::DW_AT_dwo_name => {
1640                string!();
1641            }
1642            constants::DW_AT_reference => {
1643                flag!();
1644            }
1645            constants::DW_AT_rvalue_reference => {
1646                flag!();
1647            }
1648            constants::DW_AT_macros => {
1649                macroptr!();
1650            }
1651            constants::DW_AT_call_all_calls => {
1652                flag!();
1653            }
1654            constants::DW_AT_call_all_source_calls => {
1655                flag!();
1656            }
1657            constants::DW_AT_call_all_tail_calls => {
1658                flag!();
1659            }
1660            constants::DW_AT_call_return_pc => {
1661                address!();
1662            }
1663            constants::DW_AT_call_value => {
1664                exprloc!();
1665            }
1666            constants::DW_AT_call_origin => {
1667                exprloc!();
1668            }
1669            constants::DW_AT_call_parameter => {
1670                reference!();
1671            }
1672            constants::DW_AT_call_pc => {
1673                address!();
1674            }
1675            constants::DW_AT_call_tail_call => {
1676                flag!();
1677            }
1678            constants::DW_AT_call_target => {
1679                exprloc!();
1680            }
1681            constants::DW_AT_call_target_clobbered => {
1682                exprloc!();
1683            }
1684            constants::DW_AT_call_data_location => {
1685                exprloc!();
1686            }
1687            constants::DW_AT_call_data_value => {
1688                exprloc!();
1689            }
1690            constants::DW_AT_noreturn => {
1691                flag!();
1692            }
1693            constants::DW_AT_alignment => {
1694                // TODO: constant
1695            }
1696            constants::DW_AT_export_symbols => {
1697                flag!();
1698            }
1699            constants::DW_AT_deleted => {
1700                flag!();
1701            }
1702            constants::DW_AT_defaulted => {
1703                // TODO: constant
1704            }
1705            constants::DW_AT_loclists_base => {
1706                loclistsptr!();
1707            }
1708            constants::DW_AT_GNU_dwo_id => {
1709                dwoid!();
1710            }
1711            _ => {}
1712        }
1713        self.value.clone()
1714    }
1715
1716    /// Try to convert this attribute's value to a u8.
1717    #[inline]
1718    pub fn u8_value(&self) -> Option<u8> {
1719        self.value.u8_value()
1720    }
1721
1722    /// Try to convert this attribute's value to a u16.
1723    #[inline]
1724    pub fn u16_value(&self) -> Option<u16> {
1725        self.value.u16_value()
1726    }
1727
1728    /// Try to convert this attribute's value to an unsigned integer.
1729    #[inline]
1730    pub fn udata_value(&self) -> Option<u64> {
1731        self.value.udata_value()
1732    }
1733
1734    /// Try to convert this attribute's value to a signed integer.
1735    #[inline]
1736    pub fn sdata_value(&self) -> Option<i64> {
1737        self.value.sdata_value()
1738    }
1739
1740    /// Try to convert this attribute's value to an offset.
1741    #[inline]
1742    pub fn offset_value(&self) -> Option<R::Offset> {
1743        self.value.offset_value()
1744    }
1745
1746    /// Try to convert this attribute's value to an expression or location buffer.
1747    ///
1748    /// Expressions and locations may be `DW_FORM_block*` or `DW_FORM_exprloc`.
1749    /// The standard doesn't mention `DW_FORM_block*` as a possible form, but
1750    /// it is encountered in practice.
1751    #[inline]
1752    pub fn exprloc_value(&self) -> Option<Expression<R>> {
1753        self.value.exprloc_value()
1754    }
1755
1756    /// Try to return this attribute's value as a string slice.
1757    ///
1758    /// If this attribute's value is either an inline `DW_FORM_string` string,
1759    /// or a `DW_FORM_strp` reference to an offset into the `.debug_str`
1760    /// section, return the attribute's string value as `Some`. Other attribute
1761    /// value forms are returned as `None`.
1762    ///
1763    /// Warning: this function does not handle all possible string forms.
1764    /// Use `Dwarf::attr_string` instead.
1765    #[inline]
1766    pub fn string_value(&self, debug_str: &DebugStr<R>) -> Option<R> {
1767        self.value.string_value(debug_str)
1768    }
1769
1770    /// Try to return this attribute's value as a string slice.
1771    ///
1772    /// If this attribute's value is either an inline `DW_FORM_string` string,
1773    /// or a `DW_FORM_strp` reference to an offset into the `.debug_str`
1774    /// section, or a `DW_FORM_strp_sup` reference to an offset into a supplementary
1775    /// object file, return the attribute's string value as `Some`. Other attribute
1776    /// value forms are returned as `None`.
1777    ///
1778    /// Warning: this function does not handle all possible string forms.
1779    /// Use `Dwarf::attr_string` instead.
1780    #[inline]
1781    pub fn string_value_sup(
1782        &self,
1783        debug_str: &DebugStr<R>,
1784        debug_str_sup: Option<&DebugStr<R>>,
1785    ) -> Option<R> {
1786        self.value.string_value_sup(debug_str, debug_str_sup)
1787    }
1788}
1789
1790impl<R, Offset> AttributeValue<R, Offset>
1791where
1792    R: Reader<Offset = Offset>,
1793    Offset: ReaderOffset,
1794{
1795    /// Try to convert this attribute's value to a u8.
1796    pub fn u8_value(&self) -> Option<u8> {
1797        self.udata_value().and_then(|val| u8::try_from(val).ok())
1798    }
1799
1800    /// Try to convert this attribute's value to a u16.
1801    pub fn u16_value(&self) -> Option<u16> {
1802        self.udata_value().and_then(|val| u16::try_from(val).ok())
1803    }
1804
1805    /// Try to convert this attribute's value to an unsigned integer.
1806    pub fn udata_value(&self) -> Option<u64> {
1807        Some(match *self {
1808            AttributeValue::Data1(data) => u64::from(data),
1809            AttributeValue::Data2(data) => u64::from(data),
1810            AttributeValue::Data4(data) => u64::from(data),
1811            AttributeValue::Data8(data) => data,
1812            AttributeValue::Udata(data) => data,
1813            AttributeValue::Sdata(data) => {
1814                if data < 0 {
1815                    // Maybe we should emit a warning here
1816                    return None;
1817                }
1818                data as u64
1819            }
1820            _ => return None,
1821        })
1822    }
1823
1824    /// Try to convert this attribute's value to a signed integer.
1825    pub fn sdata_value(&self) -> Option<i64> {
1826        Some(match *self {
1827            AttributeValue::Data1(data) => i64::from(data as i8),
1828            AttributeValue::Data2(data) => i64::from(data as i16),
1829            AttributeValue::Data4(data) => i64::from(data as i32),
1830            AttributeValue::Data8(data) => data as i64,
1831            AttributeValue::Sdata(data) => data,
1832            AttributeValue::Udata(data) => {
1833                if data > i64::MAX as u64 {
1834                    // Maybe we should emit a warning here
1835                    return None;
1836                }
1837                data as i64
1838            }
1839            _ => return None,
1840        })
1841    }
1842
1843    /// Try to convert this attribute's value to an offset.
1844    pub fn offset_value(&self) -> Option<R::Offset> {
1845        // While offsets will be DW_FORM_data4/8 in DWARF version 2/3,
1846        // these have already been converted to `SecOffset.
1847        if let AttributeValue::SecOffset(offset) = *self {
1848            Some(offset)
1849        } else {
1850            None
1851        }
1852    }
1853
1854    /// Try to convert this attribute's value to an expression or location buffer.
1855    ///
1856    /// Expressions and locations may be `DW_FORM_block*` or `DW_FORM_exprloc`.
1857    /// The standard doesn't mention `DW_FORM_block*` as a possible form, but
1858    /// it is encountered in practice.
1859    pub fn exprloc_value(&self) -> Option<Expression<R>> {
1860        Some(match *self {
1861            AttributeValue::Block(ref data) => Expression(data.clone()),
1862            AttributeValue::Exprloc(ref data) => data.clone(),
1863            _ => return None,
1864        })
1865    }
1866
1867    /// Try to return this attribute's value as a string slice.
1868    ///
1869    /// If this attribute's value is either an inline `DW_FORM_string` string,
1870    /// or a `DW_FORM_strp` reference to an offset into the `.debug_str`
1871    /// section, return the attribute's string value as `Some`. Other attribute
1872    /// value forms are returned as `None`.
1873    ///
1874    /// Warning: this function does not handle all possible string forms.
1875    /// Use `Dwarf::attr_string` instead.
1876    pub fn string_value(&self, debug_str: &DebugStr<R>) -> Option<R> {
1877        match *self {
1878            AttributeValue::String(ref string) => Some(string.clone()),
1879            AttributeValue::DebugStrRef(offset) => debug_str.get_str(offset).ok(),
1880            _ => None,
1881        }
1882    }
1883
1884    /// Try to return this attribute's value as a string slice.
1885    ///
1886    /// If this attribute's value is either an inline `DW_FORM_string` string,
1887    /// or a `DW_FORM_strp` reference to an offset into the `.debug_str`
1888    /// section, or a `DW_FORM_strp_sup` reference to an offset into a supplementary
1889    /// object file, return the attribute's string value as `Some`. Other attribute
1890    /// value forms are returned as `None`.
1891    ///
1892    /// Warning: this function does not handle all possible string forms.
1893    /// Use `Dwarf::attr_string` instead.
1894    pub fn string_value_sup(
1895        &self,
1896        debug_str: &DebugStr<R>,
1897        debug_str_sup: Option<&DebugStr<R>>,
1898    ) -> Option<R> {
1899        match *self {
1900            AttributeValue::String(ref string) => Some(string.clone()),
1901            AttributeValue::DebugStrRef(offset) => debug_str.get_str(offset).ok(),
1902            AttributeValue::DebugStrRefSup(offset) => {
1903                debug_str_sup.and_then(|s| s.get_str(offset).ok())
1904            }
1905            _ => None,
1906        }
1907    }
1908}
1909
1910// Return true if the given `name` can be a section offset in DWARF version 2/3.
1911// This is required to correctly handle relocations.
1912fn allow_section_offset(name: constants::DwAt, version: u16) -> bool {
1913    match name {
1914        constants::DW_AT_location
1915        | constants::DW_AT_stmt_list
1916        | constants::DW_AT_string_length
1917        | constants::DW_AT_return_addr
1918        | constants::DW_AT_start_scope
1919        | constants::DW_AT_frame_base
1920        | constants::DW_AT_macro_info
1921        | constants::DW_AT_macros
1922        | constants::DW_AT_segment
1923        | constants::DW_AT_static_link
1924        | constants::DW_AT_use_location
1925        | constants::DW_AT_vtable_elem_location
1926        | constants::DW_AT_ranges => true,
1927        constants::DW_AT_data_member_location => version == 2 || version == 3,
1928        _ => false,
1929    }
1930}
1931
1932// This function is performance critical. It is called from a small number of
1933// wrapper functions. We always inline it into the wrapper functions.
1934#[inline(always)]
1935pub(crate) fn parse_attribute<R: Reader>(
1936    input: &mut R,
1937    encoding: Encoding,
1938    spec: AttributeSpecification,
1939) -> Result<Attribute<R>> {
1940    let mut form = spec.form();
1941    loop {
1942        let value = match form {
1943            constants::DW_FORM_indirect => {
1944                let dynamic_form = input.read_uleb128_u16()?;
1945                form = constants::DwForm(dynamic_form);
1946                continue;
1947            }
1948            constants::DW_FORM_addr => {
1949                let addr = input.read_address(encoding.address_size)?;
1950                AttributeValue::Addr(addr)
1951            }
1952            constants::DW_FORM_block1 => {
1953                let len = input.read_u8().map(R::Offset::from_u8)?;
1954                let block = input.split(len)?;
1955                AttributeValue::Block(block)
1956            }
1957            constants::DW_FORM_block2 => {
1958                let len = input.read_u16().map(R::Offset::from_u16)?;
1959                let block = input.split(len)?;
1960                AttributeValue::Block(block)
1961            }
1962            constants::DW_FORM_block4 => {
1963                let len = input.read_u32().map(R::Offset::from_u32)?;
1964                let block = input.split(len)?;
1965                AttributeValue::Block(block)
1966            }
1967            constants::DW_FORM_block => {
1968                let len = input.read_uleb128().and_then(R::Offset::from_u64)?;
1969                let block = input.split(len)?;
1970                AttributeValue::Block(block)
1971            }
1972            constants::DW_FORM_data1 => {
1973                let data = input.read_u8()?;
1974                AttributeValue::Data1(data)
1975            }
1976            constants::DW_FORM_data2 => {
1977                let data = input.read_u16()?;
1978                AttributeValue::Data2(data)
1979            }
1980            constants::DW_FORM_data4 => {
1981                // DWARF version 2/3 may use DW_FORM_data4/8 for section offsets.
1982                // Ensure we handle relocations here.
1983                if encoding.format == Format::Dwarf32
1984                    && allow_section_offset(spec.name(), encoding.version)
1985                {
1986                    let offset = input.read_offset(Format::Dwarf32)?;
1987                    AttributeValue::SecOffset(offset)
1988                } else {
1989                    let data = input.read_u32()?;
1990                    AttributeValue::Data4(data)
1991                }
1992            }
1993            constants::DW_FORM_data8 => {
1994                // DWARF version 2/3 may use DW_FORM_data4/8 for section offsets.
1995                // Ensure we handle relocations here.
1996                if encoding.format == Format::Dwarf64
1997                    && allow_section_offset(spec.name(), encoding.version)
1998                {
1999                    let offset = input.read_offset(Format::Dwarf64)?;
2000                    AttributeValue::SecOffset(offset)
2001                } else {
2002                    let data = input.read_u64()?;
2003                    AttributeValue::Data8(data)
2004                }
2005            }
2006            constants::DW_FORM_data16 => {
2007                let data = input.read_u128()?;
2008                AttributeValue::Data16(data)
2009            }
2010            constants::DW_FORM_udata => {
2011                let data = input.read_uleb128()?;
2012                AttributeValue::Udata(data)
2013            }
2014            constants::DW_FORM_sdata => {
2015                let data = input.read_sleb128()?;
2016                AttributeValue::Sdata(data)
2017            }
2018            constants::DW_FORM_exprloc => {
2019                let len = input.read_uleb128().and_then(R::Offset::from_u64)?;
2020                let block = input.split(len)?;
2021                AttributeValue::Exprloc(Expression(block))
2022            }
2023            constants::DW_FORM_flag => {
2024                let present = input.read_u8()?;
2025                AttributeValue::Flag(present != 0)
2026            }
2027            constants::DW_FORM_flag_present => {
2028                // FlagPresent is this weird compile time always true thing that
2029                // isn't actually present in the serialized DIEs, only in the abbreviation.
2030                AttributeValue::Flag(true)
2031            }
2032            constants::DW_FORM_sec_offset => {
2033                let offset = input.read_offset(encoding.format)?;
2034                AttributeValue::SecOffset(offset)
2035            }
2036            constants::DW_FORM_ref1 => {
2037                let reference = input.read_u8().map(R::Offset::from_u8)?;
2038                AttributeValue::UnitRef(UnitOffset(reference))
2039            }
2040            constants::DW_FORM_ref2 => {
2041                let reference = input.read_u16().map(R::Offset::from_u16)?;
2042                AttributeValue::UnitRef(UnitOffset(reference))
2043            }
2044            constants::DW_FORM_ref4 => {
2045                let reference = input.read_u32().map(R::Offset::from_u32)?;
2046                AttributeValue::UnitRef(UnitOffset(reference))
2047            }
2048            constants::DW_FORM_ref8 => {
2049                let reference = input.read_u64().and_then(R::Offset::from_u64)?;
2050                AttributeValue::UnitRef(UnitOffset(reference))
2051            }
2052            constants::DW_FORM_ref_udata => {
2053                let reference = input.read_uleb128().and_then(R::Offset::from_u64)?;
2054                AttributeValue::UnitRef(UnitOffset(reference))
2055            }
2056            constants::DW_FORM_ref_addr => {
2057                // This is an offset, but DWARF version 2 specifies that DW_FORM_ref_addr
2058                // has the same size as an address on the target system.  This was changed
2059                // in DWARF version 3.
2060                let offset = if encoding.version == 2 {
2061                    input.read_sized_offset(encoding.address_size)?
2062                } else {
2063                    input.read_offset(encoding.format)?
2064                };
2065                AttributeValue::DebugInfoRef(DebugInfoOffset(offset))
2066            }
2067            constants::DW_FORM_ref_sig8 => {
2068                let signature = input.read_u64()?;
2069                AttributeValue::DebugTypesRef(DebugTypeSignature(signature))
2070            }
2071            constants::DW_FORM_ref_sup4 => {
2072                let offset = input.read_u32().map(R::Offset::from_u32)?;
2073                AttributeValue::DebugInfoRefSup(DebugInfoOffset(offset))
2074            }
2075            constants::DW_FORM_ref_sup8 => {
2076                let offset = input.read_u64().and_then(R::Offset::from_u64)?;
2077                AttributeValue::DebugInfoRefSup(DebugInfoOffset(offset))
2078            }
2079            constants::DW_FORM_GNU_ref_alt => {
2080                let offset = input.read_offset(encoding.format)?;
2081                AttributeValue::DebugInfoRefSup(DebugInfoOffset(offset))
2082            }
2083            constants::DW_FORM_string => {
2084                let string = input.read_null_terminated_slice()?;
2085                AttributeValue::String(string)
2086            }
2087            constants::DW_FORM_strp => {
2088                let offset = input.read_offset(encoding.format)?;
2089                AttributeValue::DebugStrRef(DebugStrOffset(offset))
2090            }
2091            constants::DW_FORM_strp_sup | constants::DW_FORM_GNU_strp_alt => {
2092                let offset = input.read_offset(encoding.format)?;
2093                AttributeValue::DebugStrRefSup(DebugStrOffset(offset))
2094            }
2095            constants::DW_FORM_line_strp => {
2096                let offset = input.read_offset(encoding.format)?;
2097                AttributeValue::DebugLineStrRef(DebugLineStrOffset(offset))
2098            }
2099            constants::DW_FORM_implicit_const => {
2100                let data = spec
2101                    .implicit_const_value()
2102                    .ok_or(Error::InvalidImplicitConst)?;
2103                AttributeValue::Sdata(data)
2104            }
2105            constants::DW_FORM_strx | constants::DW_FORM_GNU_str_index => {
2106                let index = input.read_uleb128().and_then(R::Offset::from_u64)?;
2107                AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
2108            }
2109            constants::DW_FORM_strx1 => {
2110                let index = input.read_u8().map(R::Offset::from_u8)?;
2111                AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
2112            }
2113            constants::DW_FORM_strx2 => {
2114                let index = input.read_u16().map(R::Offset::from_u16)?;
2115                AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
2116            }
2117            constants::DW_FORM_strx3 => {
2118                let index = input.read_uint(3).and_then(R::Offset::from_u64)?;
2119                AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
2120            }
2121            constants::DW_FORM_strx4 => {
2122                let index = input.read_u32().map(R::Offset::from_u32)?;
2123                AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
2124            }
2125            constants::DW_FORM_addrx | constants::DW_FORM_GNU_addr_index => {
2126                let index = input.read_uleb128().and_then(R::Offset::from_u64)?;
2127                AttributeValue::DebugAddrIndex(DebugAddrIndex(index))
2128            }
2129            constants::DW_FORM_addrx1 => {
2130                let index = input.read_u8().map(R::Offset::from_u8)?;
2131                AttributeValue::DebugAddrIndex(DebugAddrIndex(index))
2132            }
2133            constants::DW_FORM_addrx2 => {
2134                let index = input.read_u16().map(R::Offset::from_u16)?;
2135                AttributeValue::DebugAddrIndex(DebugAddrIndex(index))
2136            }
2137            constants::DW_FORM_addrx3 => {
2138                let index = input.read_uint(3).and_then(R::Offset::from_u64)?;
2139                AttributeValue::DebugAddrIndex(DebugAddrIndex(index))
2140            }
2141            constants::DW_FORM_addrx4 => {
2142                let index = input.read_u32().map(R::Offset::from_u32)?;
2143                AttributeValue::DebugAddrIndex(DebugAddrIndex(index))
2144            }
2145            constants::DW_FORM_loclistx => {
2146                let index = input.read_uleb128().and_then(R::Offset::from_u64)?;
2147                AttributeValue::DebugLocListsIndex(DebugLocListsIndex(index))
2148            }
2149            constants::DW_FORM_rnglistx => {
2150                let index = input.read_uleb128().and_then(R::Offset::from_u64)?;
2151                AttributeValue::DebugRngListsIndex(DebugRngListsIndex(index))
2152            }
2153            _ => {
2154                return Err(Error::UnknownForm(form));
2155            }
2156        };
2157        let attr = Attribute {
2158            name: spec.name(),
2159            form: spec.form(),
2160            value,
2161        };
2162        return Ok(attr);
2163    }
2164}
2165
2166pub(crate) fn skip_attributes<R: Reader>(
2167    input: &mut R,
2168    encoding: Encoding,
2169    specs: &[AttributeSpecification],
2170) -> Result<()> {
2171    let mut skip_bytes = R::Offset::from_u8(0);
2172    for spec in specs {
2173        let mut form = spec.form();
2174        loop {
2175            if let Some(len) = get_attribute_size(form, encoding) {
2176                // We know the length of this attribute. Accumulate that length.
2177                skip_bytes += R::Offset::from_u8(len);
2178                break;
2179            }
2180
2181            // We have encountered a variable-length attribute.
2182            if skip_bytes != R::Offset::from_u8(0) {
2183                // Skip the accumulated skip bytes and then read the attribute normally.
2184                input.skip(skip_bytes)?;
2185                skip_bytes = R::Offset::from_u8(0);
2186            }
2187
2188            match form {
2189                constants::DW_FORM_indirect => {
2190                    let dynamic_form = input.read_uleb128_u16()?;
2191                    form = constants::DwForm(dynamic_form);
2192                    continue;
2193                }
2194                constants::DW_FORM_block1 => {
2195                    skip_bytes = input.read_u8().map(R::Offset::from_u8)?;
2196                }
2197                constants::DW_FORM_block2 => {
2198                    skip_bytes = input.read_u16().map(R::Offset::from_u16)?;
2199                }
2200                constants::DW_FORM_block4 => {
2201                    skip_bytes = input.read_u32().map(R::Offset::from_u32)?;
2202                }
2203                constants::DW_FORM_block | constants::DW_FORM_exprloc => {
2204                    skip_bytes = input.read_uleb128().and_then(R::Offset::from_u64)?;
2205                }
2206                constants::DW_FORM_string => {
2207                    let _ = input.read_null_terminated_slice()?;
2208                }
2209                constants::DW_FORM_udata
2210                | constants::DW_FORM_sdata
2211                | constants::DW_FORM_ref_udata
2212                | constants::DW_FORM_strx
2213                | constants::DW_FORM_GNU_str_index
2214                | constants::DW_FORM_addrx
2215                | constants::DW_FORM_GNU_addr_index
2216                | constants::DW_FORM_loclistx
2217                | constants::DW_FORM_rnglistx => {
2218                    input.skip_leb128()?;
2219                }
2220                _ => {
2221                    return Err(Error::UnknownForm(form));
2222                }
2223            };
2224            break;
2225        }
2226    }
2227    if skip_bytes != R::Offset::from_u8(0) {
2228        // Skip the remaining accumulated skip bytes.
2229        input.skip(skip_bytes)?;
2230    }
2231    Ok(())
2232}
2233
2234/// A raw reader of the data that defines the Debugging Information Entries.
2235///
2236/// `EntriesRaw` provides primitives to read the components of Debugging Information
2237/// Entries (DIEs). A DIE consists of an abbreviation code (read with `read_abbreviation`)
2238/// followed by a number of attributes (read with `read_attribute`).
2239/// The user must provide the control flow to read these correctly.
2240/// In particular, all attributes must always be read before reading another
2241/// abbreviation code.
2242///
2243/// Alternatively, you may call [`Self::read_entry`] to read the abbreviations and all
2244/// attributes. The attributes are stored in a `Vec` in the DIE, so you should try to
2245/// reuse this allocation for future calls.
2246///
2247/// `EntriesRaw` lacks some features of `EntriesCursor`, such as the ability to skip
2248/// to the next sibling DIE. However, this also allows it to optimize better, since it
2249/// does not need to perform the extra bookkeeping required to support these features,
2250/// and thus it is suitable for cases where performance is important.
2251///
2252/// ## Example Usage
2253/// ```rust,no_run
2254/// # fn example() -> Result<(), gimli::Error> {
2255/// # let debug_info = gimli::DebugInfo::new(&[], gimli::LittleEndian);
2256/// # let get_some_unit = || debug_info.units().next().unwrap().unwrap();
2257/// let unit = get_some_unit();
2258/// # let debug_abbrev = gimli::DebugAbbrev::new(&[], gimli::LittleEndian);
2259/// # let get_abbrevs_for_unit = |_| unit.abbreviations(&debug_abbrev).unwrap();
2260/// let abbrevs = get_abbrevs_for_unit(&unit);
2261///
2262/// let mut entries = unit.entries_raw(&abbrevs, None)?;
2263/// while !entries.is_empty() {
2264///     let abbrev = if let Some(abbrev) = entries.read_abbreviation()? {
2265///         abbrev
2266///     } else {
2267///         // Null entry with no attributes.
2268///         continue
2269///     };
2270///     match abbrev.tag() {
2271///         gimli::DW_TAG_subprogram => {
2272///             // Loop over attributes for DIEs we care about.
2273///             for spec in abbrev.attributes() {
2274///                 let attr = entries.read_attribute(*spec)?;
2275///                 match attr.name() {
2276///                     // Handle attributes.
2277///                     _ => {}
2278///                 }
2279///             }
2280///         }
2281///         _ => {
2282///             // Skip attributes for DIEs we don't care about.
2283///             entries.skip_attributes(abbrev.attributes());
2284///         }
2285///     }
2286/// }
2287/// # unreachable!()
2288/// # }
2289/// ```
2290#[derive(Clone, Debug)]
2291pub struct EntriesRaw<'abbrev, R>
2292where
2293    R: Reader,
2294{
2295    input: R,
2296    encoding: Encoding,
2297    abbreviations: &'abbrev Abbreviations,
2298    end_offset: UnitOffset<R::Offset>,
2299    depth: isize,
2300}
2301
2302impl<'abbrev, R: Reader> EntriesRaw<'abbrev, R> {
2303    /// Construct a new `EntriesRaw`.
2304    ///
2305    /// `input` may be anywhere within the entries for a unit, including partway
2306    /// through an entry. It is up to the caller to know what needs to be parsed
2307    /// next.
2308    ///
2309    /// `offset` may be any value. It is used as the initial value returned by
2310    /// [`Self::next_offset`].
2311    pub fn new(
2312        input: R,
2313        encoding: Encoding,
2314        abbreviations: &'abbrev Abbreviations,
2315        offset: UnitOffset<R::Offset>,
2316    ) -> Self {
2317        let end_offset = UnitOffset(offset.0 + input.len());
2318        EntriesRaw {
2319            input,
2320            encoding,
2321            abbreviations,
2322            end_offset,
2323            depth: 0,
2324        }
2325    }
2326
2327    #[inline]
2328    fn empty(&mut self) {
2329        self.input.empty()
2330    }
2331
2332    /// Return true if there is no more input.
2333    #[inline]
2334    pub fn is_empty(&self) -> bool {
2335        self.input.is_empty()
2336    }
2337
2338    fn seek_forward(&mut self, offset: UnitOffset<R::Offset>, depth: isize) -> bool {
2339        if let Some(skip_len) = offset.0.checked_sub(self.next_offset().0) {
2340            // Ignore invalid offsets. Be careful not to modify self.input on error.
2341            let mut input = self.input.clone();
2342            if input.skip(skip_len).is_ok() {
2343                self.input = input;
2344                self.depth = depth;
2345                return true;
2346            }
2347        }
2348        false
2349    }
2350
2351    /// Return the unit offset at which the reader will read next.
2352    ///
2353    /// If you want the offset of the next entry, then this must be called prior to reading
2354    /// the next entry.
2355    pub fn next_offset(&self) -> UnitOffset<R::Offset> {
2356        UnitOffset(self.end_offset.0 - self.input.len())
2357    }
2358
2359    /// Return the depth of the next entry.
2360    ///
2361    /// This depth is updated when `read_abbreviation` is called, and is updated
2362    /// based on null entries and the `has_children` field in the abbreviation.
2363    #[inline]
2364    pub fn next_depth(&self) -> isize {
2365        self.depth
2366    }
2367
2368    /// Read an entry into a placeholder.
2369    ///
2370    /// This reads the abbreviation code and all attributes. The attributes are stored in
2371    /// a `Vec` in the entry, so you should try to reuse this entry for future calls.
2372    ///
2373    /// Returns `Ok(false)` if a null entry is read. All fields in the entry will be
2374    /// set appropriately for a null entry.
2375    ///
2376    /// Returns `Err` if an error occurred. Some fields in the entry may be modified
2377    /// depending on where the error occurred.
2378    pub fn read_entry(&mut self, entry: &mut DebuggingInformationEntry<R>) -> Result<bool> {
2379        entry.depth = self.next_depth();
2380        entry.offset = self.next_offset();
2381        let Some(abbrev) = self.read_abbreviation()? else {
2382            entry.set_null();
2383            return Ok(false);
2384        };
2385        entry.tag = abbrev.tag();
2386        entry.has_children = abbrev.has_children();
2387        self.read_attributes(abbrev.attributes(), &mut entry.attrs)?;
2388        Ok(true)
2389    }
2390
2391    /// Read an abbreviation code and lookup the corresponding `Abbreviation`.
2392    ///
2393    /// Returns `Ok(None)` for null entries.
2394    ///
2395    /// Returns `Err` if end of input is reached, or the code is invalid.
2396    #[inline]
2397    pub fn read_abbreviation(&mut self) -> Result<Option<&'abbrev Abbreviation>> {
2398        let code = self.input.read_uleb128()?;
2399        if code == 0 {
2400            self.depth -= 1;
2401            return Ok(None);
2402        };
2403        let abbrev = self
2404            .abbreviations
2405            .get(code)
2406            .ok_or(Error::InvalidAbbreviationCode(code))?;
2407        if abbrev.has_children() {
2408            self.depth += 1;
2409        }
2410        Ok(Some(abbrev))
2411    }
2412
2413    /// Read an attribute.
2414    ///
2415    /// This function is never inlined. Consider using `read_attribute_inline` instead
2416    /// if you only call this from a small number of places.
2417    #[inline(never)]
2418    pub fn read_attribute(&mut self, spec: AttributeSpecification) -> Result<Attribute<R>> {
2419        parse_attribute(&mut self.input, self.encoding, spec)
2420    }
2421
2422    /// Read an attribute.
2423    ///
2424    /// Identical to `read_attribute`, but has the `#[inline(always)]` attribute.
2425    /// This allows better optimisation at the cost of code size.
2426    #[inline(always)]
2427    pub fn read_attribute_inline(&mut self, spec: AttributeSpecification) -> Result<Attribute<R>> {
2428        parse_attribute(&mut self.input, self.encoding, spec)
2429    }
2430
2431    /// Read all attributes into a `Vec`.
2432    ///
2433    /// This will clear `attrs` before reading.
2434    ///
2435    /// It is recommended to reuse the same `Vec` for multiple calls to avoid allocations.
2436    pub fn read_attributes(
2437        &mut self,
2438        specs: &[AttributeSpecification],
2439        attrs: &mut Vec<Attribute<R>>,
2440    ) -> Result<()> {
2441        attrs.clear();
2442        attrs.reserve(specs.len());
2443        for spec in specs {
2444            attrs.push(parse_attribute(&mut self.input, self.encoding, *spec)?);
2445        }
2446        Ok(())
2447    }
2448
2449    /// Skip all the attributes of an abbreviation.
2450    #[inline]
2451    pub fn skip_attributes(&mut self, specs: &[AttributeSpecification]) -> Result<()> {
2452        skip_attributes(&mut self.input, self.encoding, specs)
2453    }
2454}
2455
2456/// A cursor into the Debugging Information Entries tree for a compilation unit.
2457///
2458/// The `EntriesCursor` can traverse the DIE tree in DFS order using [`Self::next_dfs`],
2459/// or skip to the next sibling of the entry the cursor is currently pointing to
2460/// using [`Self::next_sibling`].
2461///
2462/// [`Self::next_dfs`] will skip over the null DIEs that delimit lists of children. Use
2463/// [`Self::next_entry`] if you wish to stop at null DIEs. This may be useful if you want
2464/// to read entries at a specific depth, such as moving to the first child prior to using
2465/// [`Self::next_sibling`].
2466#[derive(Clone, Debug)]
2467pub struct EntriesCursor<'abbrev, R>
2468where
2469    R: Reader,
2470{
2471    input: EntriesRaw<'abbrev, R>,
2472    cached_current: DebuggingInformationEntry<R>,
2473}
2474
2475impl<'abbrev, R: Reader> EntriesCursor<'abbrev, R> {
2476    fn new(
2477        input: R,
2478        encoding: Encoding,
2479        abbreviations: &'abbrev Abbreviations,
2480        offset: UnitOffset<R::Offset>,
2481    ) -> Self {
2482        EntriesCursor {
2483            input: EntriesRaw::new(input, encoding, abbreviations, offset),
2484            cached_current: DebuggingInformationEntry::null(),
2485        }
2486    }
2487
2488    /// Get a reference to the entry that the cursor is currently pointing to.
2489    ///
2490    /// If the cursor is not pointing at an entry, or if the current entry is a
2491    /// null entry, then `None` is returned.
2492    #[inline]
2493    pub fn current(&self) -> Option<&DebuggingInformationEntry<R>> {
2494        if self.cached_current.is_null() {
2495            None
2496        } else {
2497            Some(&self.cached_current)
2498        }
2499    }
2500
2501    /// The unit offset of the current DIE.
2502    ///
2503    /// This works even if the cursor is positioned at a null DIE.
2504    pub fn offset(&self) -> UnitOffset<R::Offset> {
2505        self.cached_current.offset
2506    }
2507
2508    /// The tree depth of the current DIE.
2509    ///
2510    /// This works even if the cursor is positioned at a null DIE.
2511    pub fn depth(&self) -> isize {
2512        self.cached_current.depth
2513    }
2514
2515    /// The unit offset of the next DIE that [`Self::next_entry`] will read.
2516    pub fn next_offset(&self) -> UnitOffset<R::Offset> {
2517        self.input.next_offset()
2518    }
2519
2520    /// The tree depth of the next DIE that [`Self::next_entry`] will read.
2521    pub fn next_depth(&self) -> isize {
2522        self.input.next_depth()
2523    }
2524
2525    /// Move the cursor to the next DIE in the tree.
2526    ///
2527    /// Returns `true` if there is a next entry, even if this entry is null.
2528    /// If there is no next entry, then `false` is returned.
2529    pub fn next_entry(&mut self) -> Result<bool> {
2530        if self.input.is_empty() {
2531            self.cached_current.set_null();
2532            return Ok(false);
2533        }
2534
2535        match self.input.read_entry(&mut self.cached_current) {
2536            Ok(_) => Ok(true),
2537            Err(e) => {
2538                self.input.empty();
2539                self.cached_current.set_null();
2540                Err(e)
2541            }
2542        }
2543    }
2544
2545    /// Move the cursor to the next DIE in the tree in DFS order.
2546    ///
2547    /// Upon successful movement of the cursor, returns the entry, which may be:
2548    ///
2549    ///   * The first child of the previous current entry, if any.
2550    ///
2551    ///   * The sibling of the previous current entry, if any.
2552    ///
2553    ///   * The sibling of the previous entry's parent, if any, and so on.
2554    ///
2555    /// If there is no next entry, then `None` is returned.
2556    ///
2557    /// Here is an example that prints the offset and depth of all entries in a
2558    /// compilation unit.
2559    ///
2560    /// ```
2561    /// # use gimli::{DebugAbbrev, DebugInfo, LittleEndian};
2562    /// # let info_buf = [
2563    /// #     // Comilation unit header
2564    /// #
2565    /// #     // 32-bit unit length = 25
2566    /// #     0x19, 0x00, 0x00, 0x00,
2567    /// #     // Version 4
2568    /// #     0x04, 0x00,
2569    /// #     // debug_abbrev_offset
2570    /// #     0x00, 0x00, 0x00, 0x00,
2571    /// #     // Address size
2572    /// #     0x04,
2573    /// #
2574    /// #     // DIEs
2575    /// #
2576    /// #     // Abbreviation code
2577    /// #     0x01,
2578    /// #     // Attribute of form DW_FORM_string = "foo\0"
2579    /// #     0x66, 0x6f, 0x6f, 0x00,
2580    /// #
2581    /// #       // Children
2582    /// #
2583    /// #       // Abbreviation code
2584    /// #       0x01,
2585    /// #       // Attribute of form DW_FORM_string = "foo\0"
2586    /// #       0x66, 0x6f, 0x6f, 0x00,
2587    /// #
2588    /// #         // Children
2589    /// #
2590    /// #         // Abbreviation code
2591    /// #         0x01,
2592    /// #         // Attribute of form DW_FORM_string = "foo\0"
2593    /// #         0x66, 0x6f, 0x6f, 0x00,
2594    /// #
2595    /// #           // Children
2596    /// #
2597    /// #           // End of children
2598    /// #           0x00,
2599    /// #
2600    /// #         // End of children
2601    /// #         0x00,
2602    /// #
2603    /// #       // End of children
2604    /// #       0x00,
2605    /// # ];
2606    /// # let debug_info = DebugInfo::new(&info_buf, LittleEndian);
2607    /// #
2608    /// # let abbrev_buf = [
2609    /// #     // Code
2610    /// #     0x01,
2611    /// #     // DW_TAG_subprogram
2612    /// #     0x2e,
2613    /// #     // DW_CHILDREN_yes
2614    /// #     0x01,
2615    /// #     // Begin attributes
2616    /// #       // Attribute name = DW_AT_name
2617    /// #       0x03,
2618    /// #       // Attribute form = DW_FORM_string
2619    /// #       0x08,
2620    /// #     // End attributes
2621    /// #     0x00,
2622    /// #     0x00,
2623    /// #     // Null terminator
2624    /// #     0x00
2625    /// # ];
2626    /// # let debug_abbrev = DebugAbbrev::new(&abbrev_buf, LittleEndian);
2627    /// #
2628    /// # let get_some_unit = || debug_info.units().next().unwrap().unwrap();
2629    ///
2630    /// let unit = get_some_unit();
2631    /// # let get_abbrevs_for_unit = |_| unit.abbreviations(&debug_abbrev).unwrap();
2632    /// let abbrevs = get_abbrevs_for_unit(&unit);
2633    /// let mut cursor = unit.entries(&abbrevs);
2634    ///
2635    /// // Traverse the DIE tree in depth-first search order.
2636    /// while let Some(current) = cursor.next_dfs().expect("Should parse next dfs") {
2637    ///     println!(
2638    ///         "Offset: {:x} Depth: {} Tag: {}",
2639    ///         current.offset().0,
2640    ///         current.depth(),
2641    ///         current.tag()
2642    ///     );
2643    /// }
2644    /// ```
2645    pub fn next_dfs(&mut self) -> Result<Option<&DebuggingInformationEntry<R>>> {
2646        loop {
2647            // The next entry should be the one we want.
2648            if self.next_entry()? {
2649                if !self.cached_current.is_null() {
2650                    return Ok(Some(&self.cached_current));
2651                }
2652            } else {
2653                return Ok(None);
2654            }
2655        }
2656    }
2657
2658    /// Move the cursor to the next sibling DIE of the current one.
2659    ///
2660    /// Returns `Ok(Some(entry))` when the cursor has been moved to the next sibling,
2661    /// `Ok(None)` when there is no next sibling.
2662    ///
2663    /// The depth of the cursor is never changed if this method returns `Ok`. Once
2664    /// `Ok(None)` is returned, this method will continue to return `Ok(None)` until
2665    /// either [`Self::next_entry`] or [`Self::next_dfs`] is called.
2666    ///
2667    /// This method is useful for reading only the children of a DIE. However, you
2668    /// must first move the cursor to the first child. [`Self::next_entry`] is usually
2669    /// the easiest way to do this. You should also use either [`Self::next_depth`] or
2670    /// [`DebuggingInformationEntry::has_children`] to determine if the DIE can have
2671    /// children.
2672    ///
2673    /// Here is an example that iterates over all of the direct children of the
2674    /// root entry:
2675    ///
2676    /// ```
2677    /// # use gimli::{DebugAbbrev, DebugInfo, LittleEndian};
2678    /// # let info_buf = [
2679    /// #     // Comilation unit header
2680    /// #
2681    /// #     // 32-bit unit length = 25
2682    /// #     0x19, 0x00, 0x00, 0x00,
2683    /// #     // Version 4
2684    /// #     0x04, 0x00,
2685    /// #     // debug_abbrev_offset
2686    /// #     0x00, 0x00, 0x00, 0x00,
2687    /// #     // Address size
2688    /// #     0x04,
2689    /// #
2690    /// #     // DIEs
2691    /// #
2692    /// #     // Abbreviation code
2693    /// #     0x01,
2694    /// #     // Attribute of form DW_FORM_string = "foo\0"
2695    /// #     0x66, 0x6f, 0x6f, 0x00,
2696    /// #
2697    /// #       // Children
2698    /// #
2699    /// #       // Abbreviation code
2700    /// #       0x01,
2701    /// #       // Attribute of form DW_FORM_string = "foo\0"
2702    /// #       0x66, 0x6f, 0x6f, 0x00,
2703    /// #
2704    /// #         // Children
2705    /// #
2706    /// #         // Abbreviation code
2707    /// #         0x01,
2708    /// #         // Attribute of form DW_FORM_string = "foo\0"
2709    /// #         0x66, 0x6f, 0x6f, 0x00,
2710    /// #
2711    /// #           // Children
2712    /// #
2713    /// #           // End of children
2714    /// #           0x00,
2715    /// #
2716    /// #         // End of children
2717    /// #         0x00,
2718    /// #
2719    /// #       // End of children
2720    /// #       0x00,
2721    /// # ];
2722    /// # let debug_info = DebugInfo::new(&info_buf, LittleEndian);
2723    /// #
2724    /// # let get_some_unit = || debug_info.units().next().unwrap().unwrap();
2725    ///
2726    /// # let abbrev_buf = [
2727    /// #     // Code
2728    /// #     0x01,
2729    /// #     // DW_TAG_subprogram
2730    /// #     0x2e,
2731    /// #     // DW_CHILDREN_yes
2732    /// #     0x01,
2733    /// #     // Begin attributes
2734    /// #       // Attribute name = DW_AT_name
2735    /// #       0x03,
2736    /// #       // Attribute form = DW_FORM_string
2737    /// #       0x08,
2738    /// #     // End attributes
2739    /// #     0x00,
2740    /// #     0x00,
2741    /// #     // Null terminator
2742    /// #     0x00
2743    /// # ];
2744    /// # let debug_abbrev = DebugAbbrev::new(&abbrev_buf, LittleEndian);
2745    /// #
2746    /// let unit = get_some_unit();
2747    /// # let get_abbrevs_for_unit = |_| unit.abbreviations(&debug_abbrev).unwrap();
2748    /// let abbrevs = get_abbrevs_for_unit(&unit);
2749    ///
2750    /// let mut cursor = unit.entries(&abbrevs);
2751    ///
2752    /// // Move the cursor to the root.
2753    /// assert!(cursor.next_entry().unwrap());
2754    ///
2755    /// // Move the cursor to the root's first child, if any.
2756    /// assert!(cursor.current().unwrap().has_children());
2757    /// assert!(cursor.next_entry().unwrap());
2758    ///
2759    /// // Iterate the root's children.
2760    /// while let Some(current) = cursor.current() {
2761    ///     println!("{:?} is a child of the root", current);
2762    ///     cursor.next_sibling().expect("Should parse next sibling");
2763    /// }
2764    /// ```
2765    pub fn next_sibling(&mut self) -> Result<Option<&DebuggingInformationEntry<R>>> {
2766        if self.current().is_none() {
2767            // We're already at the null for the end of the sibling list.
2768            return Ok(None);
2769        }
2770
2771        // Loop until we find an entry at the current level.
2772        let current_depth = self.cached_current.depth;
2773        loop {
2774            if let Some(current) = self.current()
2775                && current.has_children()
2776                && let Some(sibling_offset) = current.sibling()
2777            {
2778                // Fast path: this entry has a DW_AT_sibling
2779                // attribute pointing to its sibling, so jump
2780                // to it (which keeps us at the same depth).
2781                self.input.seek_forward(sibling_offset, current.depth);
2782            }
2783
2784            if !self.next_entry()? {
2785                // End of input.
2786                return Ok(None);
2787            }
2788
2789            if self.cached_current.depth == current_depth {
2790                // Found an entry at the current level.
2791                return Ok(self.current());
2792            }
2793        }
2794    }
2795}
2796
2797/// The state information for a tree view of the Debugging Information Entries.
2798///
2799/// The `EntriesTree` can be used to recursively iterate through the DIE
2800/// tree, following the parent/child relationships. The `EntriesTree` contains
2801/// shared state for all nodes in the tree, avoiding any duplicate parsing of
2802/// entries during the traversal.
2803///
2804/// ## Example Usage
2805/// ```rust,no_run
2806/// # fn example() -> Result<(), gimli::Error> {
2807/// # let debug_info = gimli::DebugInfo::new(&[], gimli::LittleEndian);
2808/// # let get_some_unit = || debug_info.units().next().unwrap().unwrap();
2809/// let unit = get_some_unit();
2810/// # let debug_abbrev = gimli::DebugAbbrev::new(&[], gimli::LittleEndian);
2811/// # let get_abbrevs_for_unit = |_| unit.abbreviations(&debug_abbrev).unwrap();
2812/// let abbrevs = get_abbrevs_for_unit(&unit);
2813///
2814/// let mut tree = unit.entries_tree(&abbrevs, None)?;
2815/// let root = tree.root()?;
2816/// process_tree(root)?;
2817/// # unreachable!()
2818/// # }
2819///
2820/// fn process_tree<R>(mut node: gimli::EntriesTreeNode<R>) -> gimli::Result<()>
2821///     where R: gimli::Reader
2822/// {
2823///     // Examine the entry attributes.
2824///     for attr in node.entry().attrs() {
2825///     }
2826///     let mut children = node.children();
2827///     while let Some(child) = children.next()? {
2828///         // Recursively process a child.
2829///         process_tree(child);
2830///     }
2831///     Ok(())
2832/// }
2833/// ```
2834#[derive(Clone, Debug)]
2835pub struct EntriesTree<'abbrev, R>
2836where
2837    R: Reader,
2838{
2839    root: R,
2840    input: EntriesRaw<'abbrev, R>,
2841    entry: DebuggingInformationEntry<R>,
2842}
2843
2844impl<'abbrev, R: Reader> EntriesTree<'abbrev, R> {
2845    fn new(
2846        root: R,
2847        encoding: Encoding,
2848        abbreviations: &'abbrev Abbreviations,
2849        offset: UnitOffset<R::Offset>,
2850    ) -> Self {
2851        let input = root.clone();
2852        EntriesTree {
2853            root,
2854            input: EntriesRaw::new(input, encoding, abbreviations, offset),
2855            entry: DebuggingInformationEntry::null(),
2856        }
2857    }
2858
2859    /// Returns the root node of the tree.
2860    pub fn root<'me>(&'me mut self) -> Result<EntriesTreeNode<'abbrev, 'me, R>> {
2861        self.input.input = self.root.clone();
2862        self.input.depth = 0;
2863        if !self.input.read_entry(&mut self.entry)? {
2864            return Err(Error::NoEntryAtGivenOffset(self.entry.offset.0.into_u64()));
2865        }
2866        Ok(EntriesTreeNode::new(self, 1))
2867    }
2868
2869    /// Move the cursor to the next entry at the specified depth.
2870    ///
2871    /// Requires `depth <= self.depth + 1`.
2872    ///
2873    /// Returns `true` if successful.
2874    fn next(&mut self, depth: isize) -> Result<bool> {
2875        if self.entry.depth < depth {
2876            debug_assert_eq!(self.entry.depth + 1, depth);
2877
2878            if !self.entry.has_children() {
2879                return Ok(false);
2880            }
2881
2882            if self.input.is_empty() {
2883                self.entry.set_null();
2884                return Ok(false);
2885            }
2886
2887            let entry = self.input.read_entry(&mut self.entry);
2888            if entry.is_err() {
2889                self.input.empty();
2890                self.entry.set_null();
2891            }
2892            return entry;
2893        }
2894
2895        loop {
2896            if self.entry.has_children()
2897                && let Some(sibling_offset) = self.entry.sibling()
2898            {
2899                // Fast path: this entry has a DW_AT_sibling
2900                // attribute pointing to its sibling, so jump
2901                // to it (which keeps us at the same depth).
2902                self.input.seek_forward(sibling_offset, self.entry.depth);
2903            }
2904
2905            if self.input.is_empty() {
2906                self.entry.set_null();
2907                return Ok(false);
2908            }
2909
2910            match self.input.read_entry(&mut self.entry) {
2911                Ok(entry) => {
2912                    if self.entry.depth == depth {
2913                        return Ok(entry);
2914                    }
2915                }
2916                Err(e) => {
2917                    self.input.empty();
2918                    self.entry.set_null();
2919                    return Err(e);
2920                }
2921            }
2922        }
2923    }
2924}
2925
2926/// A node in the Debugging Information Entry tree.
2927///
2928/// The root node of a tree can be obtained
2929/// via [`EntriesTree::root`](./struct.EntriesTree.html#method.root).
2930#[derive(Debug)]
2931pub struct EntriesTreeNode<'abbrev, 'tree, R: Reader> {
2932    tree: &'tree mut EntriesTree<'abbrev, R>,
2933    depth: isize,
2934}
2935
2936impl<'abbrev, 'tree, R: Reader> EntriesTreeNode<'abbrev, 'tree, R> {
2937    fn new(
2938        tree: &'tree mut EntriesTree<'abbrev, R>,
2939        depth: isize,
2940    ) -> EntriesTreeNode<'abbrev, 'tree, R> {
2941        debug_assert!(!tree.entry.is_null());
2942        EntriesTreeNode { tree, depth }
2943    }
2944
2945    /// Returns the current entry in the tree.
2946    pub fn entry(&self) -> &DebuggingInformationEntry<R> {
2947        // We never create a node with a null entry.
2948        &self.tree.entry
2949    }
2950
2951    /// Create an iterator for the children of the current entry.
2952    ///
2953    /// The current entry can no longer be accessed after creating the
2954    /// iterator.
2955    pub fn children(self) -> EntriesTreeIter<'abbrev, 'tree, R> {
2956        EntriesTreeIter::new(self.tree, self.depth)
2957    }
2958}
2959
2960/// An iterator that allows traversal of the children of an
2961/// `EntriesTreeNode`.
2962///
2963/// The items returned by this iterator are also `EntriesTreeNode`s,
2964/// which allow recursive traversal of grandchildren, etc.
2965#[derive(Debug)]
2966pub struct EntriesTreeIter<'abbrev, 'tree, R: Reader> {
2967    tree: &'tree mut EntriesTree<'abbrev, R>,
2968    depth: isize,
2969    empty: bool,
2970}
2971
2972impl<'abbrev, 'tree, R: Reader> EntriesTreeIter<'abbrev, 'tree, R> {
2973    fn new(
2974        tree: &'tree mut EntriesTree<'abbrev, R>,
2975        depth: isize,
2976    ) -> EntriesTreeIter<'abbrev, 'tree, R> {
2977        EntriesTreeIter {
2978            tree,
2979            depth,
2980            empty: false,
2981        }
2982    }
2983
2984    /// Returns an `EntriesTreeNode` for the next child entry.
2985    ///
2986    /// Returns `None` if there are no more children.
2987    pub fn next<'me>(&'me mut self) -> Result<Option<EntriesTreeNode<'abbrev, 'me, R>>> {
2988        if self.empty {
2989            Ok(None)
2990        } else if self.tree.next(self.depth)? {
2991            Ok(Some(EntriesTreeNode::new(self.tree, self.depth + 1)))
2992        } else {
2993            self.empty = true;
2994            Ok(None)
2995        }
2996    }
2997}
2998
2999/// The `DebugTypes` struct represents the DWARF type information
3000/// found in the `.debug_types` section.
3001#[derive(Debug, Default, Clone, Copy)]
3002pub struct DebugTypes<R> {
3003    debug_types_section: R,
3004}
3005
3006impl<'input, Endian> DebugTypes<EndianSlice<'input, Endian>>
3007where
3008    Endian: Endianity,
3009{
3010    /// Construct a new `DebugTypes` instance from the data in the `.debug_types`
3011    /// section.
3012    ///
3013    /// It is the caller's responsibility to read the `.debug_types` section and
3014    /// present it as a `&[u8]` slice. That means using some ELF loader on
3015    /// Linux, a Mach-O loader on macOS, etc.
3016    ///
3017    /// ```
3018    /// use gimli::{DebugTypes, LittleEndian};
3019    ///
3020    /// # let buf = [0x00, 0x01, 0x02, 0x03];
3021    /// # let read_debug_types_section_somehow = || &buf;
3022    /// let debug_types = DebugTypes::new(read_debug_types_section_somehow(), LittleEndian);
3023    /// ```
3024    pub fn new(debug_types_section: &'input [u8], endian: Endian) -> Self {
3025        Self::from(EndianSlice::new(debug_types_section, endian))
3026    }
3027}
3028
3029impl<T> DebugTypes<T> {
3030    /// Create a `DebugTypes` section that references the data in `self`.
3031    ///
3032    /// This is useful when `R` implements `Reader` but `T` does not.
3033    ///
3034    /// Used by `DwarfSections::borrow`.
3035    pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugTypes<R>
3036    where
3037        F: FnMut(&'a T) -> R,
3038    {
3039        borrow(&self.debug_types_section).into()
3040    }
3041}
3042
3043impl<R> Section<R> for DebugTypes<R> {
3044    fn id() -> SectionId {
3045        SectionId::DebugTypes
3046    }
3047
3048    fn reader(&self) -> &R {
3049        &self.debug_types_section
3050    }
3051}
3052
3053impl<R> From<R> for DebugTypes<R> {
3054    fn from(debug_types_section: R) -> Self {
3055        DebugTypes {
3056            debug_types_section,
3057        }
3058    }
3059}
3060
3061impl<R: Reader> DebugTypes<R> {
3062    /// Iterate the type-units in this `.debug_types` section.
3063    ///
3064    /// ```
3065    /// use gimli::{DebugTypes, LittleEndian};
3066    ///
3067    /// # let buf = [];
3068    /// # let read_debug_types_section_somehow = || &buf;
3069    /// let debug_types = DebugTypes::new(read_debug_types_section_somehow(), LittleEndian);
3070    ///
3071    /// let mut iter = debug_types.units();
3072    /// while let Some(unit) = iter.next().unwrap() {
3073    ///     println!("unit's length is {}", unit.unit_length());
3074    /// }
3075    /// ```
3076    pub fn units(&self) -> DebugTypesUnitHeadersIter<R> {
3077        DebugTypesUnitHeadersIter {
3078            input: self.debug_types_section.clone(),
3079            offset: UnitSectionOffset(R::Offset::from_u8(0)),
3080        }
3081    }
3082}
3083
3084/// An iterator over the type-units of this `.debug_types` section.
3085///
3086/// See the [documentation on
3087/// `DebugTypes::units`](./struct.DebugTypes.html#method.units) for
3088/// more detail.
3089#[derive(Clone, Debug)]
3090pub struct DebugTypesUnitHeadersIter<R: Reader> {
3091    input: R,
3092    offset: UnitSectionOffset<R::Offset>,
3093}
3094
3095impl<R: Reader> DebugTypesUnitHeadersIter<R> {
3096    /// Advance the iterator to the next type unit header.
3097    pub fn next(&mut self) -> Result<Option<UnitHeader<R>>> {
3098        if self.input.is_empty() {
3099            Ok(None)
3100        } else {
3101            let len = self.input.len();
3102            match parse_unit_header(&mut self.input, SectionId::DebugTypes, self.offset) {
3103                Ok(header) => {
3104                    self.offset.0 += len - self.input.len();
3105                    Ok(Some(header))
3106                }
3107                Err(e) => {
3108                    self.input.empty();
3109                    Err(e)
3110                }
3111            }
3112        }
3113    }
3114}
3115
3116#[cfg(feature = "fallible-iterator")]
3117impl<R: Reader> fallible_iterator::FallibleIterator for DebugTypesUnitHeadersIter<R> {
3118    type Item = UnitHeader<R>;
3119    type Error = Error;
3120
3121    fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
3122        DebugTypesUnitHeadersIter::next(self)
3123    }
3124}
3125
3126impl<R: Reader> Iterator for DebugTypesUnitHeadersIter<R> {
3127    type Item = Result<UnitHeader<R>>;
3128
3129    fn next(&mut self) -> Option<Self::Item> {
3130        DebugTypesUnitHeadersIter::next(self).transpose()
3131    }
3132}
3133
3134#[cfg(test)]
3135// Tests require leb128::write.
3136#[cfg(feature = "write")]
3137mod tests {
3138    use super::*;
3139    use crate::constants;
3140    use crate::constants::*;
3141    use crate::endianity::{Endianity, LittleEndian};
3142    use crate::leb128::write::Leb128;
3143    use crate::read::abbrev::tests::AbbrevSectionMethods;
3144    use crate::read::{
3145        Abbreviation, AttributeSpecification, DebugAbbrev, EndianSlice, Error, Result,
3146    };
3147    use crate::test_util::GimliSectionMethods;
3148    use alloc::vec::Vec;
3149    use test_assembler::{Endian, Label, LabelMaker, Section};
3150
3151    // Mixin methods for `Section` to help define binary test data.
3152
3153    trait UnitSectionMethods {
3154        fn unit<E>(self, unit: &mut UnitHeader<EndianSlice<'_, E>>) -> Self
3155        where
3156            E: Endianity;
3157        fn die<F>(self, code: u64, attr: F) -> Self
3158        where
3159            F: Fn(Section) -> Section;
3160        fn die_null(self) -> Self;
3161        fn attr_string(self, s: &str) -> Self;
3162        fn attr_ref1(self, o: u8) -> Self;
3163        fn offset(self, offset: usize, format: Format) -> Self;
3164    }
3165
3166    impl UnitSectionMethods for Section {
3167        fn unit<E>(self, unit: &mut UnitHeader<EndianSlice<'_, E>>) -> Self
3168        where
3169            E: Endianity,
3170        {
3171            unit.unit_offset.0 = self.size() as usize;
3172            let length = Label::new();
3173            let start = Label::new();
3174            let end = Label::new();
3175
3176            let section = match unit.format() {
3177                Format::Dwarf32 => self.L32(&length),
3178                Format::Dwarf64 => self.L32(0xffff_ffff).L64(&length),
3179            };
3180
3181            let section = match unit.version() {
3182                2..=4 => section
3183                    .mark(&start)
3184                    .L16(unit.version())
3185                    .offset(unit.debug_abbrev_offset.0, unit.format())
3186                    .D8(unit.address_size()),
3187                5 => section
3188                    .mark(&start)
3189                    .L16(unit.version())
3190                    .D8(unit.type_().dw_ut().0)
3191                    .D8(unit.address_size())
3192                    .offset(unit.debug_abbrev_offset.0, unit.format()),
3193                _ => unreachable!(),
3194            };
3195
3196            let section = match unit.type_() {
3197                UnitType::Compilation | UnitType::Partial => section,
3198                UnitType::Type {
3199                    type_signature,
3200                    type_offset,
3201                }
3202                | UnitType::SplitType {
3203                    type_signature,
3204                    type_offset,
3205                } => section
3206                    .L64(type_signature.0)
3207                    .offset(type_offset.0, unit.format()),
3208                UnitType::Skeleton(dwo_id) | UnitType::SplitCompilation(dwo_id) => {
3209                    section.L64(dwo_id.0)
3210                }
3211            };
3212
3213            let section = section.append_bytes(unit.entries_buf.slice()).mark(&end);
3214
3215            unit.unit_length = (&end - &start) as usize;
3216            length.set_const(unit.unit_length as u64);
3217
3218            section
3219        }
3220
3221        fn die<F>(self, code: u64, attr: F) -> Self
3222        where
3223            F: Fn(Section) -> Section,
3224        {
3225            let section = self.uleb(code);
3226            attr(section)
3227        }
3228
3229        fn die_null(self) -> Self {
3230            self.D8(0)
3231        }
3232
3233        fn attr_string(self, attr: &str) -> Self {
3234            self.append_bytes(attr.as_bytes()).D8(0)
3235        }
3236
3237        fn attr_ref1(self, attr: u8) -> Self {
3238            self.D8(attr)
3239        }
3240
3241        fn offset(self, offset: usize, format: Format) -> Self {
3242            match format {
3243                Format::Dwarf32 => self.L32(offset as u32),
3244                Format::Dwarf64 => self.L64(offset as u64),
3245            }
3246        }
3247    }
3248
3249    /// Ensure that `UnitHeader<R>` is covariant wrt R.
3250    #[test]
3251    fn test_unit_header_variance() {
3252        /// This only needs to compile.
3253        fn _f<'a: 'b, 'b, E: Endianity>(
3254            x: UnitHeader<EndianSlice<'a, E>>,
3255        ) -> UnitHeader<EndianSlice<'b, E>> {
3256            x
3257        }
3258    }
3259
3260    #[test]
3261    #[cfg(target_pointer_width = "64")]
3262    fn test_units() {
3263        let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3264        let mut unit64 = UnitHeader {
3265            encoding: Encoding {
3266                format: Format::Dwarf64,
3267                version: 4,
3268                address_size: 8,
3269            },
3270            unit_length: 0,
3271            unit_type: UnitType::Compilation,
3272            debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
3273            section: SectionId::DebugInfo,
3274            unit_offset: UnitSectionOffset(0),
3275            entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3276        };
3277        let mut unit32 = UnitHeader {
3278            encoding: Encoding {
3279                format: Format::Dwarf32,
3280                version: 4,
3281                address_size: 4,
3282            },
3283            unit_length: 0,
3284            unit_type: UnitType::Compilation,
3285            debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3286            section: SectionId::DebugInfo,
3287            unit_offset: UnitSectionOffset(0),
3288            entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3289        };
3290        let section = Section::with_endian(Endian::Little)
3291            .unit(&mut unit64)
3292            .unit(&mut unit32);
3293        let buf = section.get_contents().unwrap();
3294
3295        let debug_info = DebugInfo::new(&buf, LittleEndian);
3296        let mut units = debug_info.units();
3297
3298        assert_eq!(units.next(), Ok(Some(unit64)));
3299        assert_eq!(units.next(), Ok(Some(unit32)));
3300        assert_eq!(units.next(), Ok(None));
3301    }
3302
3303    #[test]
3304    fn test_unit_version_unknown_version() {
3305        let buf = [0x02, 0x00, 0x00, 0x00, 0xab, 0xcd];
3306        let rest = &mut EndianSlice::new(&buf, LittleEndian);
3307
3308        match parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)) {
3309            Err(Error::UnknownVersion(0xcdab)) => {}
3310            otherwise => panic!("Unexpected result: {:?}", otherwise),
3311        };
3312
3313        let buf = [0x02, 0x00, 0x00, 0x00, 0x1, 0x0];
3314        let rest = &mut EndianSlice::new(&buf, LittleEndian);
3315
3316        match parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)) {
3317            Err(Error::UnknownVersion(1)) => {}
3318            otherwise => panic!("Unexpected result: {:?}", otherwise),
3319        };
3320    }
3321
3322    #[test]
3323    fn test_unit_version_incomplete() {
3324        let buf = [0x01, 0x00, 0x00, 0x00, 0x04];
3325        let rest = &mut EndianSlice::new(&buf, LittleEndian);
3326
3327        match parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)) {
3328            Err(Error::UnexpectedEof(_)) => {}
3329            otherwise => panic!("Unexpected result: {:?}", otherwise),
3330        };
3331    }
3332
3333    #[test]
3334    fn test_parse_unit_header_32_ok() {
3335        let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3336        let encoding = Encoding {
3337            format: Format::Dwarf32,
3338            version: 4,
3339            address_size: 4,
3340        };
3341        let mut expected_unit = UnitHeader {
3342            encoding,
3343            unit_length: 0,
3344            unit_type: UnitType::Compilation,
3345            debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3346            section: SectionId::DebugInfo,
3347            unit_offset: UnitSectionOffset(0),
3348            entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3349        };
3350        let section = Section::with_endian(Endian::Little)
3351            .unit(&mut expected_unit)
3352            .append_bytes(expected_rest);
3353        let buf = section.get_contents().unwrap();
3354        let rest = &mut EndianSlice::new(&buf, LittleEndian);
3355
3356        assert_eq!(
3357            parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)),
3358            Ok(expected_unit)
3359        );
3360        assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3361    }
3362
3363    #[test]
3364    #[cfg(target_pointer_width = "64")]
3365    fn test_parse_unit_header_64_ok() {
3366        let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3367        let encoding = Encoding {
3368            format: Format::Dwarf64,
3369            version: 4,
3370            address_size: 8,
3371        };
3372        let mut expected_unit = UnitHeader {
3373            encoding,
3374            unit_length: 0,
3375            unit_type: UnitType::Compilation,
3376            debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
3377            section: SectionId::DebugInfo,
3378            unit_offset: UnitSectionOffset(0),
3379            entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3380        };
3381        let section = Section::with_endian(Endian::Little)
3382            .unit(&mut expected_unit)
3383            .append_bytes(expected_rest);
3384        let buf = section.get_contents().unwrap();
3385        let rest = &mut EndianSlice::new(&buf, LittleEndian);
3386
3387        assert_eq!(
3388            parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)),
3389            Ok(expected_unit)
3390        );
3391        assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3392    }
3393
3394    #[test]
3395    fn test_parse_v5_unit_header_32_ok() {
3396        let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3397        let encoding = Encoding {
3398            format: Format::Dwarf32,
3399            version: 5,
3400            address_size: 4,
3401        };
3402        let mut expected_unit = UnitHeader {
3403            encoding,
3404            unit_length: 0,
3405            unit_type: UnitType::Compilation,
3406            debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3407            section: SectionId::DebugInfo,
3408            unit_offset: UnitSectionOffset(0),
3409            entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3410        };
3411        let section = Section::with_endian(Endian::Little)
3412            .unit(&mut expected_unit)
3413            .append_bytes(expected_rest);
3414        let buf = section.get_contents().unwrap();
3415        let rest = &mut EndianSlice::new(&buf, LittleEndian);
3416
3417        assert_eq!(
3418            parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)),
3419            Ok(expected_unit)
3420        );
3421        assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3422    }
3423
3424    #[test]
3425    #[cfg(target_pointer_width = "64")]
3426    fn test_parse_v5_unit_header_64_ok() {
3427        let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3428        let encoding = Encoding {
3429            format: Format::Dwarf64,
3430            version: 5,
3431            address_size: 8,
3432        };
3433        let mut expected_unit = UnitHeader {
3434            encoding,
3435            unit_length: 0,
3436            unit_type: UnitType::Compilation,
3437            debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
3438            section: SectionId::DebugInfo,
3439            unit_offset: UnitSectionOffset(0),
3440            entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3441        };
3442        let section = Section::with_endian(Endian::Little)
3443            .unit(&mut expected_unit)
3444            .append_bytes(expected_rest);
3445        let buf = section.get_contents().unwrap();
3446        let rest = &mut EndianSlice::new(&buf, LittleEndian);
3447
3448        assert_eq!(
3449            parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)),
3450            Ok(expected_unit)
3451        );
3452        assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3453    }
3454
3455    #[test]
3456    fn test_parse_v5_partial_unit_header_32_ok() {
3457        let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3458        let encoding = Encoding {
3459            format: Format::Dwarf32,
3460            version: 5,
3461            address_size: 4,
3462        };
3463        let mut expected_unit = UnitHeader {
3464            encoding,
3465            unit_length: 0,
3466            unit_type: UnitType::Partial,
3467            debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3468            section: SectionId::DebugInfo,
3469            unit_offset: UnitSectionOffset(0),
3470            entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3471        };
3472        let section = Section::with_endian(Endian::Little)
3473            .unit(&mut expected_unit)
3474            .append_bytes(expected_rest);
3475        let buf = section.get_contents().unwrap();
3476        let rest = &mut EndianSlice::new(&buf, LittleEndian);
3477
3478        assert_eq!(
3479            parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)),
3480            Ok(expected_unit)
3481        );
3482        assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3483    }
3484
3485    #[test]
3486    #[cfg(target_pointer_width = "64")]
3487    fn test_parse_v5_partial_unit_header_64_ok() {
3488        let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3489        let encoding = Encoding {
3490            format: Format::Dwarf64,
3491            version: 5,
3492            address_size: 8,
3493        };
3494        let mut expected_unit = UnitHeader {
3495            encoding,
3496            unit_length: 0,
3497            unit_type: UnitType::Partial,
3498            debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
3499            section: SectionId::DebugInfo,
3500            unit_offset: UnitSectionOffset(0),
3501            entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3502        };
3503        let section = Section::with_endian(Endian::Little)
3504            .unit(&mut expected_unit)
3505            .append_bytes(expected_rest);
3506        let buf = section.get_contents().unwrap();
3507        let rest = &mut EndianSlice::new(&buf, LittleEndian);
3508
3509        assert_eq!(
3510            parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)),
3511            Ok(expected_unit)
3512        );
3513        assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3514    }
3515
3516    #[test]
3517    fn test_parse_v5_skeleton_unit_header_32_ok() {
3518        let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3519        let encoding = Encoding {
3520            format: Format::Dwarf32,
3521            version: 5,
3522            address_size: 4,
3523        };
3524        let mut expected_unit = UnitHeader {
3525            encoding,
3526            unit_length: 0,
3527            unit_type: UnitType::Skeleton(DwoId(0x0706_5040_0302_1000)),
3528            debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3529            section: SectionId::DebugInfo,
3530            unit_offset: UnitSectionOffset(0),
3531            entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3532        };
3533        let section = Section::with_endian(Endian::Little)
3534            .unit(&mut expected_unit)
3535            .append_bytes(expected_rest);
3536        let buf = section.get_contents().unwrap();
3537        let rest = &mut EndianSlice::new(&buf, LittleEndian);
3538
3539        assert_eq!(
3540            parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)),
3541            Ok(expected_unit)
3542        );
3543        assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3544    }
3545
3546    #[test]
3547    #[cfg(target_pointer_width = "64")]
3548    fn test_parse_v5_skeleton_unit_header_64_ok() {
3549        let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3550        let encoding = Encoding {
3551            format: Format::Dwarf64,
3552            version: 5,
3553            address_size: 8,
3554        };
3555        let mut expected_unit = UnitHeader {
3556            encoding,
3557            unit_length: 0,
3558            unit_type: UnitType::Skeleton(DwoId(0x0706_5040_0302_1000)),
3559            debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
3560            section: SectionId::DebugInfo,
3561            unit_offset: UnitSectionOffset(0),
3562            entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3563        };
3564        let section = Section::with_endian(Endian::Little)
3565            .unit(&mut expected_unit)
3566            .append_bytes(expected_rest);
3567        let buf = section.get_contents().unwrap();
3568        let rest = &mut EndianSlice::new(&buf, LittleEndian);
3569
3570        assert_eq!(
3571            parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)),
3572            Ok(expected_unit)
3573        );
3574        assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3575    }
3576
3577    #[test]
3578    fn test_parse_v5_split_compilation_unit_header_32_ok() {
3579        let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3580        let encoding = Encoding {
3581            format: Format::Dwarf32,
3582            version: 5,
3583            address_size: 4,
3584        };
3585        let mut expected_unit = UnitHeader {
3586            encoding,
3587            unit_length: 0,
3588            unit_type: UnitType::SplitCompilation(DwoId(0x0706_5040_0302_1000)),
3589            debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3590            section: SectionId::DebugInfo,
3591            unit_offset: UnitSectionOffset(0),
3592            entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3593        };
3594        let section = Section::with_endian(Endian::Little)
3595            .unit(&mut expected_unit)
3596            .append_bytes(expected_rest);
3597        let buf = section.get_contents().unwrap();
3598        let rest = &mut EndianSlice::new(&buf, LittleEndian);
3599
3600        assert_eq!(
3601            parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)),
3602            Ok(expected_unit)
3603        );
3604        assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3605    }
3606
3607    #[test]
3608    #[cfg(target_pointer_width = "64")]
3609    fn test_parse_v5_split_compilation_unit_header_64_ok() {
3610        let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3611        let encoding = Encoding {
3612            format: Format::Dwarf64,
3613            version: 5,
3614            address_size: 8,
3615        };
3616        let mut expected_unit = UnitHeader {
3617            encoding,
3618            unit_length: 0,
3619            unit_type: UnitType::SplitCompilation(DwoId(0x0706_5040_0302_1000)),
3620            debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
3621            section: SectionId::DebugInfo,
3622            unit_offset: UnitSectionOffset(0),
3623            entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3624        };
3625        let section = Section::with_endian(Endian::Little)
3626            .unit(&mut expected_unit)
3627            .append_bytes(expected_rest);
3628        let buf = section.get_contents().unwrap();
3629        let rest = &mut EndianSlice::new(&buf, LittleEndian);
3630
3631        assert_eq!(
3632            parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)),
3633            Ok(expected_unit)
3634        );
3635        assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3636    }
3637
3638    #[test]
3639    fn test_parse_type_unit_header_32_ok() {
3640        let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3641        let encoding = Encoding {
3642            format: Format::Dwarf32,
3643            version: 4,
3644            address_size: 8,
3645        };
3646        let mut expected_unit = UnitHeader {
3647            encoding,
3648            unit_length: 0,
3649            unit_type: UnitType::Type {
3650                type_signature: DebugTypeSignature(0xdead_beef_dead_beef),
3651                type_offset: UnitOffset(0x7856_3412),
3652            },
3653            debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3654            section: SectionId::DebugTypes,
3655            unit_offset: UnitSectionOffset(0),
3656            entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3657        };
3658        let section = Section::with_endian(Endian::Little)
3659            .unit(&mut expected_unit)
3660            .append_bytes(expected_rest);
3661        let buf = section.get_contents().unwrap();
3662        let rest = &mut EndianSlice::new(&buf, LittleEndian);
3663
3664        assert_eq!(
3665            parse_unit_header(rest, SectionId::DebugTypes, UnitSectionOffset(0)),
3666            Ok(expected_unit)
3667        );
3668        assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3669    }
3670
3671    #[test]
3672    #[cfg(target_pointer_width = "64")]
3673    fn test_parse_type_unit_header_64_ok() {
3674        let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3675        let encoding = Encoding {
3676            format: Format::Dwarf64,
3677            version: 4,
3678            address_size: 8,
3679        };
3680        let mut expected_unit = UnitHeader {
3681            encoding,
3682            unit_length: 0,
3683            unit_type: UnitType::Type {
3684                type_signature: DebugTypeSignature(0xdead_beef_dead_beef),
3685                type_offset: UnitOffset(0x7856_3412_7856_3412),
3686            },
3687            debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3688            section: SectionId::DebugTypes,
3689            unit_offset: UnitSectionOffset(0),
3690            entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3691        };
3692        let section = Section::with_endian(Endian::Little)
3693            .unit(&mut expected_unit)
3694            .append_bytes(expected_rest);
3695        let buf = section.get_contents().unwrap();
3696        let rest = &mut EndianSlice::new(&buf, LittleEndian);
3697
3698        assert_eq!(
3699            parse_unit_header(rest, SectionId::DebugTypes, UnitSectionOffset(0)),
3700            Ok(expected_unit)
3701        );
3702        assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3703    }
3704
3705    #[test]
3706    fn test_parse_v5_type_unit_header_32_ok() {
3707        let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3708        let encoding = Encoding {
3709            format: Format::Dwarf32,
3710            version: 5,
3711            address_size: 8,
3712        };
3713        let mut expected_unit = UnitHeader {
3714            encoding,
3715            unit_length: 0,
3716            unit_type: UnitType::Type {
3717                type_signature: DebugTypeSignature(0xdead_beef_dead_beef),
3718                type_offset: UnitOffset(0x7856_3412),
3719            },
3720            debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3721            section: SectionId::DebugInfo,
3722            unit_offset: UnitSectionOffset(0),
3723            entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3724        };
3725        let section = Section::with_endian(Endian::Little)
3726            .unit(&mut expected_unit)
3727            .append_bytes(expected_rest);
3728        let buf = section.get_contents().unwrap();
3729        let rest = &mut EndianSlice::new(&buf, LittleEndian);
3730
3731        assert_eq!(
3732            parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)),
3733            Ok(expected_unit)
3734        );
3735        assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3736    }
3737
3738    #[test]
3739    #[cfg(target_pointer_width = "64")]
3740    fn test_parse_v5_type_unit_header_64_ok() {
3741        let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3742        let encoding = Encoding {
3743            format: Format::Dwarf64,
3744            version: 5,
3745            address_size: 8,
3746        };
3747        let mut expected_unit = UnitHeader {
3748            encoding,
3749            unit_length: 0,
3750            unit_type: UnitType::Type {
3751                type_signature: DebugTypeSignature(0xdead_beef_dead_beef),
3752                type_offset: UnitOffset(0x7856_3412_7856_3412),
3753            },
3754            debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3755            section: SectionId::DebugInfo,
3756            unit_offset: UnitSectionOffset(0),
3757            entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3758        };
3759        let section = Section::with_endian(Endian::Little)
3760            .unit(&mut expected_unit)
3761            .append_bytes(expected_rest);
3762        let buf = section.get_contents().unwrap();
3763        let rest = &mut EndianSlice::new(&buf, LittleEndian);
3764
3765        assert_eq!(
3766            parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)),
3767            Ok(expected_unit)
3768        );
3769        assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3770    }
3771
3772    #[test]
3773    fn test_parse_v5_split_type_unit_header_32_ok() {
3774        let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3775        let encoding = Encoding {
3776            format: Format::Dwarf32,
3777            version: 5,
3778            address_size: 8,
3779        };
3780        let mut expected_unit = UnitHeader {
3781            encoding,
3782            unit_length: 0,
3783            unit_type: UnitType::SplitType {
3784                type_signature: DebugTypeSignature(0xdead_beef_dead_beef),
3785                type_offset: UnitOffset(0x7856_3412),
3786            },
3787            debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3788            section: SectionId::DebugInfo,
3789            unit_offset: UnitSectionOffset(0),
3790            entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3791        };
3792        let section = Section::with_endian(Endian::Little)
3793            .unit(&mut expected_unit)
3794            .append_bytes(expected_rest);
3795        let buf = section.get_contents().unwrap();
3796        let rest = &mut EndianSlice::new(&buf, LittleEndian);
3797
3798        assert_eq!(
3799            parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)),
3800            Ok(expected_unit)
3801        );
3802        assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3803    }
3804
3805    #[test]
3806    #[cfg(target_pointer_width = "64")]
3807    fn test_parse_v5_split_type_unit_header_64_ok() {
3808        let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3809        let encoding = Encoding {
3810            format: Format::Dwarf64,
3811            version: 5,
3812            address_size: 8,
3813        };
3814        let mut expected_unit = UnitHeader {
3815            encoding,
3816            unit_length: 0,
3817            unit_type: UnitType::SplitType {
3818                type_signature: DebugTypeSignature(0xdead_beef_dead_beef),
3819                type_offset: UnitOffset(0x7856_3412_7856_3412),
3820            },
3821            debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3822            section: SectionId::DebugInfo,
3823            unit_offset: UnitSectionOffset(0),
3824            entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3825        };
3826        let section = Section::with_endian(Endian::Little)
3827            .unit(&mut expected_unit)
3828            .append_bytes(expected_rest);
3829        let buf = section.get_contents().unwrap();
3830        let rest = &mut EndianSlice::new(&buf, LittleEndian);
3831
3832        assert_eq!(
3833            parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)),
3834            Ok(expected_unit)
3835        );
3836        assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3837    }
3838
3839    fn section_contents<F>(f: F) -> Vec<u8>
3840    where
3841        F: Fn(Section) -> Section,
3842    {
3843        f(Section::with_endian(Endian::Little))
3844            .get_contents()
3845            .unwrap()
3846    }
3847
3848    #[test]
3849    fn test_attribute_value() {
3850        let mut unit = test_parse_attribute_unit_default();
3851        let endian = unit.entries_buf.endian();
3852
3853        let block_data = &[1, 2, 3, 4];
3854        let buf = section_contents(|s| s.uleb(block_data.len() as u64).append_bytes(block_data));
3855        let block = EndianSlice::new(&buf, endian);
3856
3857        let buf = section_contents(|s| s.L32(0x0102_0304));
3858        let data4 = EndianSlice::new(&buf, endian);
3859
3860        let buf = section_contents(|s| s.L64(0x0102_0304_0506_0708));
3861        let data8 = EndianSlice::new(&buf, endian);
3862
3863        let tests = [
3864            (
3865                Format::Dwarf32,
3866                2,
3867                constants::DW_AT_data_member_location,
3868                constants::DW_FORM_block,
3869                block,
3870                AttributeValue::Block(EndianSlice::new(block_data, endian)),
3871                AttributeValue::Exprloc(Expression(EndianSlice::new(block_data, endian))),
3872            ),
3873            (
3874                Format::Dwarf32,
3875                2,
3876                constants::DW_AT_data_member_location,
3877                constants::DW_FORM_data4,
3878                data4,
3879                AttributeValue::SecOffset(0x0102_0304),
3880                AttributeValue::LocationListsRef(LocationListsOffset(0x0102_0304)),
3881            ),
3882            (
3883                Format::Dwarf64,
3884                2,
3885                constants::DW_AT_data_member_location,
3886                constants::DW_FORM_data4,
3887                data4,
3888                AttributeValue::Data4(0x0102_0304),
3889                AttributeValue::Udata(0x0102_0304),
3890            ),
3891            (
3892                Format::Dwarf32,
3893                4,
3894                constants::DW_AT_data_member_location,
3895                constants::DW_FORM_data4,
3896                data4,
3897                AttributeValue::Data4(0x0102_0304),
3898                AttributeValue::Udata(0x0102_0304),
3899            ),
3900            (
3901                Format::Dwarf32,
3902                2,
3903                constants::DW_AT_data_member_location,
3904                constants::DW_FORM_data8,
3905                data8,
3906                AttributeValue::Data8(0x0102_0304_0506_0708),
3907                AttributeValue::Udata(0x0102_0304_0506_0708),
3908            ),
3909            #[cfg(target_pointer_width = "64")]
3910            (
3911                Format::Dwarf64,
3912                2,
3913                constants::DW_AT_data_member_location,
3914                constants::DW_FORM_data8,
3915                data8,
3916                AttributeValue::SecOffset(0x0102_0304_0506_0708),
3917                AttributeValue::LocationListsRef(LocationListsOffset(0x0102_0304_0506_0708)),
3918            ),
3919            (
3920                Format::Dwarf64,
3921                4,
3922                constants::DW_AT_data_member_location,
3923                constants::DW_FORM_data8,
3924                data8,
3925                AttributeValue::Data8(0x0102_0304_0506_0708),
3926                AttributeValue::Udata(0x0102_0304_0506_0708),
3927            ),
3928            (
3929                Format::Dwarf32,
3930                4,
3931                constants::DW_AT_location,
3932                constants::DW_FORM_data4,
3933                data4,
3934                AttributeValue::SecOffset(0x0102_0304),
3935                AttributeValue::LocationListsRef(LocationListsOffset(0x0102_0304)),
3936            ),
3937            #[cfg(target_pointer_width = "64")]
3938            (
3939                Format::Dwarf64,
3940                4,
3941                constants::DW_AT_location,
3942                constants::DW_FORM_data8,
3943                data8,
3944                AttributeValue::SecOffset(0x0102_0304_0506_0708),
3945                AttributeValue::LocationListsRef(LocationListsOffset(0x0102_0304_0506_0708)),
3946            ),
3947            (
3948                Format::Dwarf32,
3949                4,
3950                constants::DW_AT_str_offsets_base,
3951                constants::DW_FORM_sec_offset,
3952                data4,
3953                AttributeValue::SecOffset(0x0102_0304),
3954                AttributeValue::DebugStrOffsetsBase(DebugStrOffsetsBase(0x0102_0304)),
3955            ),
3956            (
3957                Format::Dwarf32,
3958                4,
3959                constants::DW_AT_stmt_list,
3960                constants::DW_FORM_sec_offset,
3961                data4,
3962                AttributeValue::SecOffset(0x0102_0304),
3963                AttributeValue::DebugLineRef(DebugLineOffset(0x0102_0304)),
3964            ),
3965            (
3966                Format::Dwarf32,
3967                4,
3968                constants::DW_AT_addr_base,
3969                constants::DW_FORM_sec_offset,
3970                data4,
3971                AttributeValue::SecOffset(0x0102_0304),
3972                AttributeValue::DebugAddrBase(DebugAddrBase(0x0102_0304)),
3973            ),
3974            (
3975                Format::Dwarf32,
3976                4,
3977                constants::DW_AT_rnglists_base,
3978                constants::DW_FORM_sec_offset,
3979                data4,
3980                AttributeValue::SecOffset(0x0102_0304),
3981                AttributeValue::DebugRngListsBase(DebugRngListsBase(0x0102_0304)),
3982            ),
3983            (
3984                Format::Dwarf32,
3985                4,
3986                constants::DW_AT_loclists_base,
3987                constants::DW_FORM_sec_offset,
3988                data4,
3989                AttributeValue::SecOffset(0x0102_0304),
3990                AttributeValue::DebugLocListsBase(DebugLocListsBase(0x0102_0304)),
3991            ),
3992        ];
3993
3994        for test in tests.iter() {
3995            let (format, version, name, form, mut input, expect_raw, expect_value) = *test;
3996            unit.encoding.format = format;
3997            unit.encoding.version = version;
3998            let spec = AttributeSpecification::new(name, form, None);
3999            let attribute =
4000                parse_attribute(&mut input, unit.encoding(), spec).expect("Should parse attribute");
4001            assert_eq!(attribute.raw_value(), expect_raw);
4002            assert_eq!(attribute.value(), expect_value);
4003        }
4004    }
4005
4006    #[test]
4007    fn test_attribute_udata_sdata_value() {
4008        #[allow(clippy::type_complexity)]
4009        let tests: &[(
4010            AttributeValue<EndianSlice<'_, LittleEndian>>,
4011            Option<u64>,
4012            Option<i64>,
4013        )] = &[
4014            (AttributeValue::Data1(1), Some(1), Some(1)),
4015            (
4016                AttributeValue::Data1(u8::MAX),
4017                Some(u64::from(u8::MAX)),
4018                Some(-1),
4019            ),
4020            (AttributeValue::Data2(1), Some(1), Some(1)),
4021            (
4022                AttributeValue::Data2(u16::MAX),
4023                Some(u64::from(u16::MAX)),
4024                Some(-1),
4025            ),
4026            (AttributeValue::Data4(1), Some(1), Some(1)),
4027            (
4028                AttributeValue::Data4(u32::MAX),
4029                Some(u64::from(u32::MAX)),
4030                Some(-1),
4031            ),
4032            (AttributeValue::Data8(1), Some(1), Some(1)),
4033            (AttributeValue::Data8(u64::MAX), Some(u64::MAX), Some(-1)),
4034            (AttributeValue::Sdata(1), Some(1), Some(1)),
4035            (AttributeValue::Sdata(-1), None, Some(-1)),
4036            (AttributeValue::Udata(1), Some(1), Some(1)),
4037            (AttributeValue::Udata(1u64 << 63), Some(1u64 << 63), None),
4038        ];
4039        for test in tests.iter() {
4040            let (value, expect_udata, expect_sdata) = *test;
4041            let attribute = Attribute {
4042                name: DW_AT_data_member_location,
4043                form: constants::DW_FORM_null, // Doesn't matter
4044                value,
4045            };
4046            assert_eq!(attribute.udata_value(), expect_udata);
4047            assert_eq!(attribute.sdata_value(), expect_sdata);
4048        }
4049    }
4050
4051    fn test_parse_attribute_unit<Endian>(
4052        address_size: u8,
4053        format: Format,
4054        endian: Endian,
4055    ) -> UnitHeader<EndianSlice<'static, Endian>>
4056    where
4057        Endian: Endianity,
4058    {
4059        let encoding = Encoding {
4060            format,
4061            version: 4,
4062            address_size,
4063        };
4064        UnitHeader::new(
4065            encoding,
4066            7,
4067            UnitType::Compilation,
4068            DebugAbbrevOffset(0x0807_0605),
4069            SectionId::DebugInfo,
4070            UnitSectionOffset(0),
4071            EndianSlice::new(&[], endian),
4072        )
4073    }
4074
4075    fn test_parse_attribute_unit_default() -> UnitHeader<EndianSlice<'static, LittleEndian>> {
4076        test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian)
4077    }
4078
4079    fn test_parse_attribute<'input, Endian>(
4080        buf: &'input [u8],
4081        len: usize,
4082        unit: &UnitHeader<EndianSlice<'input, Endian>>,
4083        form: constants::DwForm,
4084        value: AttributeValue<EndianSlice<'input, Endian>>,
4085    ) where
4086        Endian: Endianity,
4087    {
4088        let spec = AttributeSpecification::new(constants::DW_AT_low_pc, form, None);
4089
4090        let expect = Attribute {
4091            name: constants::DW_AT_low_pc,
4092            form,
4093            value,
4094        };
4095
4096        let rest = &mut EndianSlice::new(buf, Endian::default());
4097        match parse_attribute(rest, unit.encoding(), spec) {
4098            Ok(attr) => {
4099                assert_eq!(attr, expect);
4100                assert_eq!(*rest, EndianSlice::new(&buf[len..], Endian::default()));
4101                if let Some(size) = spec.size(unit) {
4102                    assert_eq!(rest.len() + size, buf.len());
4103                }
4104            }
4105            otherwise => {
4106                panic!("Unexpected parse result = {:#?}", otherwise);
4107            }
4108        };
4109    }
4110
4111    #[test]
4112    fn test_parse_attribute_addr() {
4113        let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
4114        let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4115        let form = constants::DW_FORM_addr;
4116        let value = AttributeValue::Addr(0x0403_0201);
4117        test_parse_attribute(&buf, 4, &unit, form, value);
4118    }
4119
4120    #[test]
4121    fn test_parse_attribute_addr8() {
4122        let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
4123        let unit = test_parse_attribute_unit(8, Format::Dwarf32, LittleEndian);
4124        let form = constants::DW_FORM_addr;
4125        let value = AttributeValue::Addr(0x0807_0605_0403_0201);
4126        test_parse_attribute(&buf, 8, &unit, form, value);
4127    }
4128
4129    #[test]
4130    fn test_parse_attribute_block1() {
4131        // Length of data (3), three bytes of data, two bytes of left over input.
4132        let buf = [0x03, 0x09, 0x09, 0x09, 0x00, 0x00];
4133        let unit = test_parse_attribute_unit_default();
4134        let form = constants::DW_FORM_block1;
4135        let value = AttributeValue::Block(EndianSlice::new(&buf[1..4], LittleEndian));
4136        test_parse_attribute(&buf, 4, &unit, form, value);
4137    }
4138
4139    #[test]
4140    fn test_parse_attribute_block2() {
4141        // Two byte length of data (2), two bytes of data, two bytes of left over input.
4142        let buf = [0x02, 0x00, 0x09, 0x09, 0x00, 0x00];
4143        let unit = test_parse_attribute_unit_default();
4144        let form = constants::DW_FORM_block2;
4145        let value = AttributeValue::Block(EndianSlice::new(&buf[2..4], LittleEndian));
4146        test_parse_attribute(&buf, 4, &unit, form, value);
4147    }
4148
4149    #[test]
4150    fn test_parse_attribute_block4() {
4151        // Four byte length of data (2), two bytes of data, no left over input.
4152        let buf = [0x02, 0x00, 0x00, 0x00, 0x99, 0x99];
4153        let unit = test_parse_attribute_unit_default();
4154        let form = constants::DW_FORM_block4;
4155        let value = AttributeValue::Block(EndianSlice::new(&buf[4..], LittleEndian));
4156        test_parse_attribute(&buf, 6, &unit, form, value);
4157    }
4158
4159    #[test]
4160    fn test_parse_attribute_block() {
4161        // LEB length of data (2, one byte), two bytes of data, no left over input.
4162        let buf = [0x02, 0x99, 0x99];
4163        let unit = test_parse_attribute_unit_default();
4164        let form = constants::DW_FORM_block;
4165        let value = AttributeValue::Block(EndianSlice::new(&buf[1..], LittleEndian));
4166        test_parse_attribute(&buf, 3, &unit, form, value);
4167    }
4168
4169    #[test]
4170    fn test_parse_attribute_data1() {
4171        let buf = [0x03];
4172        let unit = test_parse_attribute_unit_default();
4173        let form = constants::DW_FORM_data1;
4174        let value = AttributeValue::Data1(0x03);
4175        test_parse_attribute(&buf, 1, &unit, form, value);
4176    }
4177
4178    #[test]
4179    fn test_parse_attribute_data2() {
4180        let buf = [0x02, 0x01, 0x0];
4181        let unit = test_parse_attribute_unit_default();
4182        let form = constants::DW_FORM_data2;
4183        let value = AttributeValue::Data2(0x0102);
4184        test_parse_attribute(&buf, 2, &unit, form, value);
4185    }
4186
4187    #[test]
4188    fn test_parse_attribute_data4() {
4189        let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99];
4190        let unit = test_parse_attribute_unit_default();
4191        let form = constants::DW_FORM_data4;
4192        let value = AttributeValue::Data4(0x0403_0201);
4193        test_parse_attribute(&buf, 4, &unit, form, value);
4194    }
4195
4196    #[test]
4197    fn test_parse_attribute_data8() {
4198        let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4199        let unit = test_parse_attribute_unit_default();
4200        let form = constants::DW_FORM_data8;
4201        let value = AttributeValue::Data8(0x0807_0605_0403_0201);
4202        test_parse_attribute(&buf, 8, &unit, form, value);
4203    }
4204
4205    #[test]
4206    fn test_parse_attribute_data16() {
4207        let buf = [
4208            0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
4209            0x0f, 0x10, 0x99, 0x99,
4210        ];
4211        let unit = test_parse_attribute_unit_default();
4212        let form = constants::DW_FORM_data16;
4213        let value = AttributeValue::Data16(0x100f_0e0d_0c0b_0a09_0807_0605_0403_0201);
4214        test_parse_attribute(&buf, 16, &unit, form, value);
4215    }
4216
4217    #[test]
4218    fn test_parse_attribute_udata() {
4219        let mut buf = Vec::new();
4220        buf.extend_from_slice(Leb128::unsigned(4097).bytes());
4221        let bytes_written = buf.len();
4222        buf.extend_from_slice(&[0; 10]);
4223
4224        let unit = test_parse_attribute_unit_default();
4225        let form = constants::DW_FORM_udata;
4226        let value = AttributeValue::Udata(4097);
4227        test_parse_attribute(&buf, bytes_written, &unit, form, value);
4228    }
4229
4230    #[test]
4231    fn test_parse_attribute_sdata() {
4232        let mut buf = Vec::new();
4233        buf.extend_from_slice(Leb128::signed(-4097).bytes());
4234        let bytes_written = buf.len();
4235        buf.extend_from_slice(&[0; 10]);
4236
4237        let unit = test_parse_attribute_unit_default();
4238        let form = constants::DW_FORM_sdata;
4239        let value = AttributeValue::Sdata(-4097);
4240        test_parse_attribute(&buf, bytes_written, &unit, form, value);
4241    }
4242
4243    #[test]
4244    fn test_parse_attribute_exprloc() {
4245        // LEB length of data (2, one byte), two bytes of data, one byte left over input.
4246        let buf = [0x02, 0x99, 0x99, 0x11];
4247        let unit = test_parse_attribute_unit_default();
4248        let form = constants::DW_FORM_exprloc;
4249        let value = AttributeValue::Exprloc(Expression(EndianSlice::new(&buf[1..3], LittleEndian)));
4250        test_parse_attribute(&buf, 3, &unit, form, value);
4251    }
4252
4253    #[test]
4254    fn test_parse_attribute_flag_true() {
4255        let buf = [0x42];
4256        let unit = test_parse_attribute_unit_default();
4257        let form = constants::DW_FORM_flag;
4258        let value = AttributeValue::Flag(true);
4259        test_parse_attribute(&buf, 1, &unit, form, value);
4260    }
4261
4262    #[test]
4263    fn test_parse_attribute_flag_false() {
4264        let buf = [0x00];
4265        let unit = test_parse_attribute_unit_default();
4266        let form = constants::DW_FORM_flag;
4267        let value = AttributeValue::Flag(false);
4268        test_parse_attribute(&buf, 1, &unit, form, value);
4269    }
4270
4271    #[test]
4272    fn test_parse_attribute_flag_present() {
4273        let buf = [0x01, 0x02, 0x03, 0x04];
4274        let unit = test_parse_attribute_unit_default();
4275        let form = constants::DW_FORM_flag_present;
4276        let value = AttributeValue::Flag(true);
4277        // DW_FORM_flag_present does not consume any bytes of the input stream.
4278        test_parse_attribute(&buf, 0, &unit, form, value);
4279    }
4280
4281    #[test]
4282    fn test_parse_attribute_sec_offset_32() {
4283        let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10];
4284        let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4285        let form = constants::DW_FORM_sec_offset;
4286        let value = AttributeValue::SecOffset(0x0403_0201);
4287        test_parse_attribute(&buf, 4, &unit, form, value);
4288    }
4289
4290    #[test]
4291    #[cfg(target_pointer_width = "64")]
4292    fn test_parse_attribute_sec_offset_64() {
4293        let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10];
4294        let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4295        let form = constants::DW_FORM_sec_offset;
4296        let value = AttributeValue::SecOffset(0x0807_0605_0403_0201);
4297        test_parse_attribute(&buf, 8, &unit, form, value);
4298    }
4299
4300    #[test]
4301    fn test_parse_attribute_ref1() {
4302        let buf = [0x03];
4303        let unit = test_parse_attribute_unit_default();
4304        let form = constants::DW_FORM_ref1;
4305        let value = AttributeValue::UnitRef(UnitOffset(3));
4306        test_parse_attribute(&buf, 1, &unit, form, value);
4307    }
4308
4309    #[test]
4310    fn test_parse_attribute_ref2() {
4311        let buf = [0x02, 0x01, 0x0];
4312        let unit = test_parse_attribute_unit_default();
4313        let form = constants::DW_FORM_ref2;
4314        let value = AttributeValue::UnitRef(UnitOffset(258));
4315        test_parse_attribute(&buf, 2, &unit, form, value);
4316    }
4317
4318    #[test]
4319    fn test_parse_attribute_ref4() {
4320        let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99];
4321        let unit = test_parse_attribute_unit_default();
4322        let form = constants::DW_FORM_ref4;
4323        let value = AttributeValue::UnitRef(UnitOffset(0x0403_0201));
4324        test_parse_attribute(&buf, 4, &unit, form, value);
4325    }
4326
4327    #[test]
4328    #[cfg(target_pointer_width = "64")]
4329    fn test_parse_attribute_ref8() {
4330        let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4331        let unit = test_parse_attribute_unit_default();
4332        let form = constants::DW_FORM_ref8;
4333        let value = AttributeValue::UnitRef(UnitOffset(0x0807_0605_0403_0201));
4334        test_parse_attribute(&buf, 8, &unit, form, value);
4335    }
4336
4337    #[test]
4338    fn test_parse_attribute_ref_sup4() {
4339        let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99];
4340        let unit = test_parse_attribute_unit_default();
4341        let form = constants::DW_FORM_ref_sup4;
4342        let value = AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x0403_0201));
4343        test_parse_attribute(&buf, 4, &unit, form, value);
4344    }
4345
4346    #[test]
4347    #[cfg(target_pointer_width = "64")]
4348    fn test_parse_attribute_ref_sup8() {
4349        let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4350        let unit = test_parse_attribute_unit_default();
4351        let form = constants::DW_FORM_ref_sup8;
4352        let value = AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x0807_0605_0403_0201));
4353        test_parse_attribute(&buf, 8, &unit, form, value);
4354    }
4355
4356    #[test]
4357    fn test_parse_attribute_refudata() {
4358        let mut buf = Vec::new();
4359        buf.extend_from_slice(Leb128::unsigned(4097).bytes());
4360        let bytes_written = buf.len();
4361        buf.extend_from_slice(&[0; 10]);
4362
4363        let unit = test_parse_attribute_unit_default();
4364        let form = constants::DW_FORM_ref_udata;
4365        let value = AttributeValue::UnitRef(UnitOffset(4097));
4366        test_parse_attribute(&buf, bytes_written, &unit, form, value);
4367    }
4368
4369    #[test]
4370    fn test_parse_attribute_refaddr_32() {
4371        let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4372        let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4373        let form = constants::DW_FORM_ref_addr;
4374        let value = AttributeValue::DebugInfoRef(DebugInfoOffset(0x0403_0201));
4375        test_parse_attribute(&buf, 4, &unit, form, value);
4376    }
4377
4378    #[test]
4379    #[cfg(target_pointer_width = "64")]
4380    fn test_parse_attribute_refaddr_64() {
4381        let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4382        let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4383        let form = constants::DW_FORM_ref_addr;
4384        let value = AttributeValue::DebugInfoRef(DebugInfoOffset(0x0807_0605_0403_0201));
4385        test_parse_attribute(&buf, 8, &unit, form, value);
4386    }
4387
4388    #[test]
4389    fn test_parse_attribute_refaddr_version2() {
4390        let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4391        let mut unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4392        unit.encoding.version = 2;
4393        let form = constants::DW_FORM_ref_addr;
4394        let value = AttributeValue::DebugInfoRef(DebugInfoOffset(0x0403_0201));
4395        test_parse_attribute(&buf, 4, &unit, form, value);
4396    }
4397
4398    #[test]
4399    #[cfg(target_pointer_width = "64")]
4400    fn test_parse_attribute_refaddr8_version2() {
4401        let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4402        let mut unit = test_parse_attribute_unit(8, Format::Dwarf32, LittleEndian);
4403        unit.encoding.version = 2;
4404        let form = constants::DW_FORM_ref_addr;
4405        let value = AttributeValue::DebugInfoRef(DebugInfoOffset(0x0807_0605_0403_0201));
4406        test_parse_attribute(&buf, 8, &unit, form, value);
4407    }
4408
4409    #[test]
4410    fn test_parse_attribute_gnu_ref_alt_32() {
4411        let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4412        let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4413        let form = constants::DW_FORM_GNU_ref_alt;
4414        let value = AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x0403_0201));
4415        test_parse_attribute(&buf, 4, &unit, form, value);
4416    }
4417
4418    #[test]
4419    #[cfg(target_pointer_width = "64")]
4420    fn test_parse_attribute_gnu_ref_alt_64() {
4421        let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4422        let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4423        let form = constants::DW_FORM_GNU_ref_alt;
4424        let value = AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x0807_0605_0403_0201));
4425        test_parse_attribute(&buf, 8, &unit, form, value);
4426    }
4427
4428    #[test]
4429    fn test_parse_attribute_refsig8() {
4430        let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4431        let unit = test_parse_attribute_unit_default();
4432        let form = constants::DW_FORM_ref_sig8;
4433        let value = AttributeValue::DebugTypesRef(DebugTypeSignature(0x0807_0605_0403_0201));
4434        test_parse_attribute(&buf, 8, &unit, form, value);
4435    }
4436
4437    #[test]
4438    fn test_parse_attribute_string() {
4439        let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x0, 0x99, 0x99];
4440        let unit = test_parse_attribute_unit_default();
4441        let form = constants::DW_FORM_string;
4442        let value = AttributeValue::String(EndianSlice::new(&buf[..5], LittleEndian));
4443        test_parse_attribute(&buf, 6, &unit, form, value);
4444    }
4445
4446    #[test]
4447    fn test_parse_attribute_strp_32() {
4448        let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4449        let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4450        let form = constants::DW_FORM_strp;
4451        let value = AttributeValue::DebugStrRef(DebugStrOffset(0x0403_0201));
4452        test_parse_attribute(&buf, 4, &unit, form, value);
4453    }
4454
4455    #[test]
4456    #[cfg(target_pointer_width = "64")]
4457    fn test_parse_attribute_strp_64() {
4458        let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4459        let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4460        let form = constants::DW_FORM_strp;
4461        let value = AttributeValue::DebugStrRef(DebugStrOffset(0x0807_0605_0403_0201));
4462        test_parse_attribute(&buf, 8, &unit, form, value);
4463    }
4464
4465    #[test]
4466    fn test_parse_attribute_strp_sup_32() {
4467        let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4468        let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4469        let form = constants::DW_FORM_strp_sup;
4470        let value = AttributeValue::DebugStrRefSup(DebugStrOffset(0x0403_0201));
4471        test_parse_attribute(&buf, 4, &unit, form, value);
4472    }
4473
4474    #[test]
4475    #[cfg(target_pointer_width = "64")]
4476    fn test_parse_attribute_strp_sup_64() {
4477        let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4478        let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4479        let form = constants::DW_FORM_strp_sup;
4480        let value = AttributeValue::DebugStrRefSup(DebugStrOffset(0x0807_0605_0403_0201));
4481        test_parse_attribute(&buf, 8, &unit, form, value);
4482    }
4483
4484    #[test]
4485    fn test_parse_attribute_gnu_strp_alt_32() {
4486        let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4487        let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4488        let form = constants::DW_FORM_GNU_strp_alt;
4489        let value = AttributeValue::DebugStrRefSup(DebugStrOffset(0x0403_0201));
4490        test_parse_attribute(&buf, 4, &unit, form, value);
4491    }
4492
4493    #[test]
4494    #[cfg(target_pointer_width = "64")]
4495    fn test_parse_attribute_gnu_strp_alt_64() {
4496        let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4497        let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4498        let form = constants::DW_FORM_GNU_strp_alt;
4499        let value = AttributeValue::DebugStrRefSup(DebugStrOffset(0x0807_0605_0403_0201));
4500        test_parse_attribute(&buf, 8, &unit, form, value);
4501    }
4502
4503    #[test]
4504    fn test_parse_attribute_strx() {
4505        let mut buf = Vec::new();
4506        buf.extend_from_slice(Leb128::unsigned(4097).bytes());
4507        let bytes_written = buf.len();
4508        buf.extend_from_slice(&[0; 10]);
4509
4510        let unit = test_parse_attribute_unit_default();
4511        let form = constants::DW_FORM_strx;
4512        let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(4097));
4513        test_parse_attribute(&buf, bytes_written, &unit, form, value);
4514    }
4515
4516    #[test]
4517    fn test_parse_attribute_strx1() {
4518        let buf = [0x01, 0x99, 0x99];
4519        let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4520        let form = constants::DW_FORM_strx1;
4521        let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(0x01));
4522        test_parse_attribute(&buf, 1, &unit, form, value);
4523    }
4524
4525    #[test]
4526    fn test_parse_attribute_strx2() {
4527        let buf = [0x01, 0x02, 0x99, 0x99];
4528        let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4529        let form = constants::DW_FORM_strx2;
4530        let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(0x0201));
4531        test_parse_attribute(&buf, 2, &unit, form, value);
4532    }
4533
4534    #[test]
4535    fn test_parse_attribute_strx3() {
4536        let buf = [0x01, 0x02, 0x03, 0x99, 0x99];
4537        let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4538        let form = constants::DW_FORM_strx3;
4539        let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(0x03_0201));
4540        test_parse_attribute(&buf, 3, &unit, form, value);
4541    }
4542
4543    #[test]
4544    fn test_parse_attribute_strx4() {
4545        let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99];
4546        let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4547        let form = constants::DW_FORM_strx4;
4548        let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(0x0403_0201));
4549        test_parse_attribute(&buf, 4, &unit, form, value);
4550    }
4551
4552    #[test]
4553    fn test_parse_attribute_addrx() {
4554        let mut buf = Vec::new();
4555        buf.extend_from_slice(Leb128::unsigned(4097).bytes());
4556        let bytes_written = buf.len();
4557        buf.extend_from_slice(&[0; 10]);
4558
4559        let unit = test_parse_attribute_unit_default();
4560        let form = constants::DW_FORM_addrx;
4561        let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(4097));
4562        test_parse_attribute(&buf, bytes_written, &unit, form, value);
4563    }
4564
4565    #[test]
4566    fn test_parse_attribute_addrx1() {
4567        let buf = [0x01, 0x99, 0x99];
4568        let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4569        let form = constants::DW_FORM_addrx1;
4570        let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(0x01));
4571        test_parse_attribute(&buf, 1, &unit, form, value);
4572    }
4573
4574    #[test]
4575    fn test_parse_attribute_addrx2() {
4576        let buf = [0x01, 0x02, 0x99, 0x99];
4577        let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4578        let form = constants::DW_FORM_addrx2;
4579        let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(0x0201));
4580        test_parse_attribute(&buf, 2, &unit, form, value);
4581    }
4582
4583    #[test]
4584    fn test_parse_attribute_addrx3() {
4585        let buf = [0x01, 0x02, 0x03, 0x99, 0x99];
4586        let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4587        let form = constants::DW_FORM_addrx3;
4588        let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(0x03_0201));
4589        test_parse_attribute(&buf, 3, &unit, form, value);
4590    }
4591
4592    #[test]
4593    fn test_parse_attribute_addrx4() {
4594        let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99];
4595        let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4596        let form = constants::DW_FORM_addrx4;
4597        let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(0x0403_0201));
4598        test_parse_attribute(&buf, 4, &unit, form, value);
4599    }
4600
4601    #[test]
4602    fn test_parse_attribute_loclistx() {
4603        let mut buf = Vec::new();
4604        buf.extend_from_slice(Leb128::unsigned(4097).bytes());
4605        let bytes_written = buf.len();
4606        buf.extend_from_slice(&[0; 10]);
4607
4608        let unit = test_parse_attribute_unit_default();
4609        let form = constants::DW_FORM_loclistx;
4610        let value = AttributeValue::DebugLocListsIndex(DebugLocListsIndex(4097));
4611        test_parse_attribute(&buf, bytes_written, &unit, form, value);
4612    }
4613
4614    #[test]
4615    fn test_parse_attribute_rnglistx() {
4616        let mut buf = Vec::new();
4617        buf.extend_from_slice(Leb128::unsigned(4097).bytes());
4618        let bytes_written = buf.len();
4619        buf.extend_from_slice(&[0; 10]);
4620
4621        let unit = test_parse_attribute_unit_default();
4622        let form = constants::DW_FORM_rnglistx;
4623        let value = AttributeValue::DebugRngListsIndex(DebugRngListsIndex(4097));
4624        test_parse_attribute(&buf, bytes_written, &unit, form, value);
4625    }
4626
4627    #[test]
4628    fn test_parse_attribute_indirect() {
4629        let mut buf = Vec::new();
4630        buf.extend_from_slice(Leb128::unsigned(constants::DW_FORM_udata.0.into()).bytes());
4631        buf.extend_from_slice(Leb128::unsigned(9_999_999).bytes());
4632        let bytes_written = buf.len();
4633        buf.extend_from_slice(&[0; 10]);
4634
4635        let unit = test_parse_attribute_unit_default();
4636        let form = constants::DW_FORM_indirect;
4637        let value = AttributeValue::Udata(9_999_999);
4638        test_parse_attribute(&buf, bytes_written, &unit, form, value);
4639    }
4640
4641    #[test]
4642    fn test_parse_attribute_indirect_implicit_const() {
4643        let encoding = Encoding {
4644            format: Format::Dwarf32,
4645            version: 4,
4646            address_size: 4,
4647        };
4648        let mut buf = Vec::new();
4649        buf.extend_from_slice(Leb128::unsigned(constants::DW_FORM_implicit_const.0.into()).bytes());
4650        buf.extend_from_slice(&[0; 10]);
4651
4652        let input = &mut EndianSlice::new(&buf, LittleEndian);
4653        let spec =
4654            AttributeSpecification::new(constants::DW_AT_low_pc, constants::DW_FORM_indirect, None);
4655        assert_eq!(
4656            parse_attribute(input, encoding, spec),
4657            Err(Error::InvalidImplicitConst)
4658        );
4659    }
4660
4661    fn assert_entry_name<Endian>(
4662        entry: &DebuggingInformationEntry<EndianSlice<'_, Endian>>,
4663        name: &str,
4664    ) where
4665        Endian: Endianity,
4666    {
4667        let value = entry
4668            .attr_value(constants::DW_AT_name)
4669            .expect("Should have found the name attribute");
4670
4671        assert_eq!(
4672            value,
4673            AttributeValue::String(EndianSlice::new(name.as_bytes(), Endian::default()))
4674        );
4675    }
4676
4677    fn assert_current_name<Endian>(cursor: &EntriesCursor<'_, EndianSlice<'_, Endian>>, name: &str)
4678    where
4679        Endian: Endianity,
4680    {
4681        let entry = cursor.current().expect("Should have an entry result");
4682        assert_entry_name(entry, name);
4683    }
4684
4685    fn assert_next_entry<Endian>(
4686        cursor: &mut EntriesCursor<'_, EndianSlice<'_, Endian>>,
4687        name: &str,
4688    ) where
4689        Endian: Endianity,
4690    {
4691        assert!(cursor.next_entry().expect("Should parse next entry"));
4692        assert_current_name(cursor, name);
4693    }
4694
4695    fn assert_next_entry_null<Endian>(cursor: &mut EntriesCursor<'_, EndianSlice<'_, Endian>>)
4696    where
4697        Endian: Endianity,
4698    {
4699        assert!(cursor.next_entry().expect("Should parse next entry"));
4700        assert!(cursor.current().is_none());
4701    }
4702
4703    fn assert_next_dfs<Endian>(
4704        cursor: &mut EntriesCursor<'_, EndianSlice<'_, Endian>>,
4705        name: &str,
4706        depth: isize,
4707    ) where
4708        Endian: Endianity,
4709    {
4710        {
4711            let entry = cursor
4712                .next_dfs()
4713                .expect("Should parse next dfs")
4714                .expect("Should not be done with traversal");
4715            assert_eq!(entry.depth(), depth);
4716            assert_entry_name(entry, name);
4717        }
4718        assert_current_name(cursor, name);
4719    }
4720
4721    fn assert_next_sibling<Endian>(
4722        cursor: &mut EntriesCursor<'_, EndianSlice<'_, Endian>>,
4723        name: &str,
4724        depth: isize,
4725    ) where
4726        Endian: Endianity,
4727    {
4728        {
4729            let entry = cursor
4730                .next_sibling()
4731                .expect("Should parse next sibling")
4732                .expect("Should not be done with traversal");
4733            assert_eq!(entry.depth(), depth);
4734            assert_entry_name(entry, name);
4735        }
4736        assert_current_name(cursor, name);
4737    }
4738
4739    fn entries_cursor_tests_abbrev_buf() -> Vec<u8> {
4740        #[rustfmt::skip]
4741        let section = Section::with_endian(Endian::Little)
4742            .abbrev(1, DW_TAG_subprogram, DW_CHILDREN_yes)
4743                .abbrev_attr(DW_AT_name, DW_FORM_string)
4744                .abbrev_attr_null()
4745            .abbrev_null();
4746        section.get_contents().unwrap()
4747    }
4748
4749    fn entries_cursor_tests_debug_info_buf() -> Vec<u8> {
4750        #[rustfmt::skip]
4751        let section = Section::with_endian(Endian::Little)
4752            .die(1, |s| s.attr_string("001"))
4753                .die(1, |s| s.attr_string("002"))
4754                    .die(1, |s| s.attr_string("003"))
4755                        .die_null()
4756                    .die_null()
4757                .die(1, |s| s.attr_string("004"))
4758                    .die(1, |s| s.attr_string("005"))
4759                        .die_null()
4760                    .die(1, |s| s.attr_string("006"))
4761                        .die_null()
4762                    .die_null()
4763                .die(1, |s| s.attr_string("007"))
4764                    .die(1, |s| s.attr_string("008"))
4765                        .die(1, |s| s.attr_string("009"))
4766                            .die_null()
4767                        .die_null()
4768                    .die_null()
4769                .die(1, |s| s.attr_string("010"))
4770                    .die_null()
4771                .die_null();
4772        let entries_buf = section.get_contents().unwrap();
4773
4774        let encoding = Encoding {
4775            format: Format::Dwarf32,
4776            version: 4,
4777            address_size: 4,
4778        };
4779        let mut unit = UnitHeader {
4780            encoding,
4781            unit_length: 0,
4782            unit_type: UnitType::Compilation,
4783            debug_abbrev_offset: DebugAbbrevOffset(0),
4784            section: SectionId::DebugInfo,
4785            unit_offset: UnitSectionOffset(0),
4786            entries_buf: EndianSlice::new(&entries_buf, LittleEndian),
4787        };
4788        let section = Section::with_endian(Endian::Little).unit(&mut unit);
4789        section.get_contents().unwrap()
4790    }
4791
4792    #[test]
4793    fn test_cursor_next_entry_incomplete() {
4794        #[rustfmt::skip]
4795        let section = Section::with_endian(Endian::Little)
4796            .die(1, |s| s.attr_string("001"))
4797                .die(1, |s| s.attr_string("002"))
4798                    .die(1, |s| s);
4799        let entries_buf = section.get_contents().unwrap();
4800
4801        let encoding = Encoding {
4802            format: Format::Dwarf32,
4803            version: 4,
4804            address_size: 4,
4805        };
4806        let mut unit = UnitHeader {
4807            encoding,
4808            unit_length: 0,
4809            unit_type: UnitType::Compilation,
4810            debug_abbrev_offset: DebugAbbrevOffset(0),
4811            section: SectionId::DebugInfo,
4812            unit_offset: UnitSectionOffset(0),
4813            entries_buf: EndianSlice::new(&entries_buf, LittleEndian),
4814        };
4815        let section = Section::with_endian(Endian::Little).unit(&mut unit);
4816        let info_buf = &section.get_contents().unwrap();
4817        let debug_info = DebugInfo::new(info_buf, LittleEndian);
4818
4819        let unit = debug_info
4820            .units()
4821            .next()
4822            .expect("should have a unit result")
4823            .expect("and it should be ok");
4824
4825        let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
4826        let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
4827
4828        let abbrevs = unit
4829            .abbreviations(&debug_abbrev)
4830            .expect("Should parse abbreviations");
4831
4832        let mut cursor = unit.entries(&abbrevs);
4833
4834        assert_next_entry(&mut cursor, "001");
4835        assert_next_entry(&mut cursor, "002");
4836
4837        // Entry code is present, but none of the attributes.
4838        assert!(cursor.next_entry().is_err());
4839
4840        // Fuse after error.
4841        assert!(!cursor.next_entry().expect("Should parse next entry"));
4842    }
4843
4844    #[test]
4845    fn test_cursor_next_entry() {
4846        let info_buf = &entries_cursor_tests_debug_info_buf();
4847        let debug_info = DebugInfo::new(info_buf, LittleEndian);
4848
4849        let unit = debug_info
4850            .units()
4851            .next()
4852            .expect("should have a unit result")
4853            .expect("and it should be ok");
4854
4855        let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
4856        let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
4857
4858        let abbrevs = unit
4859            .abbreviations(&debug_abbrev)
4860            .expect("Should parse abbreviations");
4861
4862        let mut cursor = unit.entries(&abbrevs);
4863
4864        assert_next_entry(&mut cursor, "001");
4865        assert_next_entry(&mut cursor, "002");
4866        assert_next_entry(&mut cursor, "003");
4867        assert_next_entry_null(&mut cursor);
4868        assert_next_entry_null(&mut cursor);
4869        assert_next_entry(&mut cursor, "004");
4870        assert_next_entry(&mut cursor, "005");
4871        assert_next_entry_null(&mut cursor);
4872        assert_next_entry(&mut cursor, "006");
4873        assert_next_entry_null(&mut cursor);
4874        assert_next_entry_null(&mut cursor);
4875        assert_next_entry(&mut cursor, "007");
4876        assert_next_entry(&mut cursor, "008");
4877        assert_next_entry(&mut cursor, "009");
4878        assert_next_entry_null(&mut cursor);
4879        assert_next_entry_null(&mut cursor);
4880        assert_next_entry_null(&mut cursor);
4881        assert_next_entry(&mut cursor, "010");
4882        assert_next_entry_null(&mut cursor);
4883        assert_next_entry_null(&mut cursor);
4884
4885        assert!(!cursor.next_entry().expect("Should parse next entry"));
4886        assert!(cursor.current().is_none());
4887    }
4888
4889    #[test]
4890    fn test_cursor_next_dfs() {
4891        let info_buf = &entries_cursor_tests_debug_info_buf();
4892        let debug_info = DebugInfo::new(info_buf, LittleEndian);
4893
4894        let unit = debug_info
4895            .units()
4896            .next()
4897            .expect("should have a unit result")
4898            .expect("and it should be ok");
4899
4900        let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
4901        let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
4902
4903        let abbrevs = unit
4904            .abbreviations(&debug_abbrev)
4905            .expect("Should parse abbreviations");
4906
4907        let mut cursor = unit.entries(&abbrevs);
4908
4909        assert_next_dfs(&mut cursor, "001", 0);
4910        assert_next_dfs(&mut cursor, "002", 1);
4911        assert_next_dfs(&mut cursor, "003", 2);
4912        assert_next_dfs(&mut cursor, "004", 1);
4913        assert_next_dfs(&mut cursor, "005", 2);
4914        assert_next_dfs(&mut cursor, "006", 2);
4915        assert_next_dfs(&mut cursor, "007", 1);
4916        assert_next_dfs(&mut cursor, "008", 2);
4917        assert_next_dfs(&mut cursor, "009", 3);
4918        assert_next_dfs(&mut cursor, "010", 1);
4919
4920        assert!(cursor.next_dfs().expect("Should parse next dfs").is_none());
4921        assert!(cursor.current().is_none());
4922    }
4923
4924    #[test]
4925    fn test_cursor_next_sibling_no_sibling_ptr() {
4926        let info_buf = &entries_cursor_tests_debug_info_buf();
4927        let debug_info = DebugInfo::new(info_buf, LittleEndian);
4928
4929        let unit = debug_info
4930            .units()
4931            .next()
4932            .expect("should have a unit result")
4933            .expect("and it should be ok");
4934
4935        let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
4936        let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
4937
4938        let abbrevs = unit
4939            .abbreviations(&debug_abbrev)
4940            .expect("Should parse abbreviations");
4941
4942        let mut cursor = unit.entries(&abbrevs);
4943
4944        assert_next_dfs(&mut cursor, "001", 0);
4945
4946        // Down to the first child of the root entry.
4947
4948        assert_next_dfs(&mut cursor, "002", 1);
4949
4950        // Now iterate all children of the root via `next_sibling`.
4951
4952        assert_next_sibling(&mut cursor, "004", 1);
4953        assert_next_sibling(&mut cursor, "007", 1);
4954        assert_next_sibling(&mut cursor, "010", 1);
4955
4956        // There should be no more siblings.
4957
4958        assert!(
4959            cursor
4960                .next_sibling()
4961                .expect("Should parse next sibling")
4962                .is_none()
4963        );
4964        assert!(cursor.current().is_none());
4965    }
4966
4967    #[test]
4968    fn test_cursor_next_sibling_continuation() {
4969        let info_buf = &entries_cursor_tests_debug_info_buf();
4970        let debug_info = DebugInfo::new(info_buf, LittleEndian);
4971
4972        let unit = debug_info
4973            .units()
4974            .next()
4975            .expect("should have a unit result")
4976            .expect("and it should be ok");
4977
4978        let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
4979        let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
4980
4981        let abbrevs = unit
4982            .abbreviations(&debug_abbrev)
4983            .expect("Should parse abbreviations");
4984
4985        let mut cursor = unit.entries(&abbrevs);
4986
4987        assert_next_dfs(&mut cursor, "001", 0);
4988
4989        // Down to the first child of the root entry.
4990
4991        assert_next_dfs(&mut cursor, "002", 1);
4992
4993        // Get the next sibling, then iterate its children
4994
4995        assert_next_sibling(&mut cursor, "004", 1);
4996        assert_next_dfs(&mut cursor, "005", 2);
4997        assert_next_sibling(&mut cursor, "006", 2);
4998        assert!(
4999            cursor
5000                .next_sibling()
5001                .expect("Should parse next sibling")
5002                .is_none()
5003        );
5004        assert!(
5005            cursor
5006                .next_sibling()
5007                .expect("Should parse next sibling")
5008                .is_none()
5009        );
5010        assert!(
5011            cursor
5012                .next_sibling()
5013                .expect("Should parse next sibling")
5014                .is_none()
5015        );
5016        assert!(
5017            cursor
5018                .next_sibling()
5019                .expect("Should parse next sibling")
5020                .is_none()
5021        );
5022
5023        // And we should be able to continue with the children of the root entry.
5024
5025        assert_next_dfs(&mut cursor, "007", 1);
5026        assert_next_sibling(&mut cursor, "010", 1);
5027
5028        // There should be no more siblings.
5029
5030        assert!(
5031            cursor
5032                .next_sibling()
5033                .expect("Should parse next sibling")
5034                .is_none()
5035        );
5036        assert!(cursor.current().is_none());
5037    }
5038
5039    fn entries_cursor_sibling_abbrev_buf() -> Vec<u8> {
5040        #[rustfmt::skip]
5041        let section = Section::with_endian(Endian::Little)
5042            .abbrev(1, DW_TAG_subprogram, DW_CHILDREN_yes)
5043                .abbrev_attr(DW_AT_name, DW_FORM_string)
5044                .abbrev_attr(DW_AT_sibling, DW_FORM_ref1)
5045                .abbrev_attr_null()
5046            .abbrev(2, DW_TAG_subprogram, DW_CHILDREN_yes)
5047                .abbrev_attr(DW_AT_name, DW_FORM_string)
5048                .abbrev_attr_null()
5049                .abbrev_null();
5050        section.get_contents().unwrap()
5051    }
5052
5053    fn entries_cursor_sibling_entries_buf(header_size: usize) -> Vec<u8> {
5054        let start = Label::new();
5055        let sibling004_ref = Label::new();
5056        let sibling004 = Label::new();
5057        let sibling009_ref = Label::new();
5058        let sibling009 = Label::new();
5059
5060        #[rustfmt::skip]
5061        let section = Section::with_endian(Endian::Little)
5062            .mark(&start)
5063            .die(2, |s| s.attr_string("001"))
5064                // Valid sibling attribute.
5065                .die(1, |s| s.attr_string("002").D8(&sibling004_ref))
5066                    // Invalid code to ensure the sibling attribute was used.
5067                    .die(10, |s| s.attr_string("003"))
5068                        .die_null()
5069                    .die_null()
5070                .mark(&sibling004)
5071                // Invalid sibling attribute.
5072                .die(1, |s| s.attr_string("004").attr_ref1(255))
5073                    .die(2, |s| s.attr_string("005"))
5074                        .die_null()
5075                    .die_null()
5076                // Sibling attribute in child only.
5077                .die(2, |s| s.attr_string("006"))
5078                    // Valid sibling attribute.
5079                    .die(1, |s| s.attr_string("007").D8(&sibling009_ref))
5080                        // Invalid code to ensure the sibling attribute was used.
5081                        .die(10, |s| s.attr_string("008"))
5082                            .die_null()
5083                        .die_null()
5084                    .mark(&sibling009)
5085                    .die(2, |s| s.attr_string("009"))
5086                        .die_null()
5087                    .die_null()
5088                // No sibling attribute.
5089                .die(2, |s| s.attr_string("010"))
5090                    .die(2, |s| s.attr_string("011"))
5091                        .die_null()
5092                    .die_null()
5093                .die_null();
5094
5095        let offset = header_size as u64 + (&sibling004 - &start) as u64;
5096        sibling004_ref.set_const(offset);
5097
5098        let offset = header_size as u64 + (&sibling009 - &start) as u64;
5099        sibling009_ref.set_const(offset);
5100
5101        section.get_contents().unwrap()
5102    }
5103
5104    fn test_cursor_next_sibling_with_ptr(
5105        cursor: &mut EntriesCursor<'_, EndianSlice<'_, LittleEndian>>,
5106    ) {
5107        assert_next_dfs(cursor, "001", 0);
5108
5109        // Down to the first child of the root.
5110
5111        assert_next_dfs(cursor, "002", 1);
5112
5113        // Now iterate all children of the root via `next_sibling`.
5114
5115        assert_next_sibling(cursor, "004", 1);
5116        assert_next_sibling(cursor, "006", 1);
5117        assert_next_sibling(cursor, "010", 1);
5118
5119        // There should be no more siblings.
5120
5121        assert!(
5122            cursor
5123                .next_sibling()
5124                .expect("Should parse next sibling")
5125                .is_none()
5126        );
5127        assert!(cursor.current().is_none());
5128    }
5129
5130    #[test]
5131    fn test_debug_info_next_sibling_with_ptr() {
5132        let encoding = Encoding {
5133            format: Format::Dwarf32,
5134            version: 4,
5135            address_size: 4,
5136        };
5137
5138        let mut unit = UnitHeader {
5139            encoding,
5140            unit_length: 0,
5141            unit_type: UnitType::Compilation,
5142            debug_abbrev_offset: DebugAbbrevOffset(0),
5143            section: SectionId::DebugInfo,
5144            unit_offset: UnitSectionOffset(0),
5145            entries_buf: EndianSlice::new(&[], LittleEndian),
5146        };
5147        let header_size = unit.size_of_header();
5148        let entries_buf = entries_cursor_sibling_entries_buf(header_size);
5149        unit.entries_buf = EndianSlice::new(&entries_buf, LittleEndian);
5150        let section = Section::with_endian(Endian::Little).unit(&mut unit);
5151        let info_buf = section.get_contents().unwrap();
5152        let debug_info = DebugInfo::new(&info_buf, LittleEndian);
5153
5154        let unit = debug_info
5155            .units()
5156            .next()
5157            .expect("should have a unit result")
5158            .expect("and it should be ok");
5159
5160        let abbrev_buf = entries_cursor_sibling_abbrev_buf();
5161        let debug_abbrev = DebugAbbrev::new(&abbrev_buf, LittleEndian);
5162
5163        let abbrevs = unit
5164            .abbreviations(&debug_abbrev)
5165            .expect("Should parse abbreviations");
5166
5167        let mut cursor = unit.entries(&abbrevs);
5168        test_cursor_next_sibling_with_ptr(&mut cursor);
5169    }
5170
5171    #[test]
5172    fn test_debug_types_next_sibling_with_ptr() {
5173        let encoding = Encoding {
5174            format: Format::Dwarf32,
5175            version: 4,
5176            address_size: 4,
5177        };
5178        let mut unit = UnitHeader {
5179            encoding,
5180            unit_length: 0,
5181            unit_type: UnitType::Type {
5182                type_signature: DebugTypeSignature(0),
5183                type_offset: UnitOffset(0),
5184            },
5185            debug_abbrev_offset: DebugAbbrevOffset(0),
5186            section: SectionId::DebugTypes,
5187            unit_offset: UnitSectionOffset(0),
5188            entries_buf: EndianSlice::new(&[], LittleEndian),
5189        };
5190        let header_size = unit.size_of_header();
5191        let entries_buf = entries_cursor_sibling_entries_buf(header_size);
5192        unit.entries_buf = EndianSlice::new(&entries_buf, LittleEndian);
5193        let section = Section::with_endian(Endian::Little).unit(&mut unit);
5194        let info_buf = section.get_contents().unwrap();
5195        let debug_types = DebugTypes::new(&info_buf, LittleEndian);
5196
5197        let unit = debug_types
5198            .units()
5199            .next()
5200            .expect("should have a unit result")
5201            .expect("and it should be ok");
5202
5203        let abbrev_buf = entries_cursor_sibling_abbrev_buf();
5204        let debug_abbrev = DebugAbbrev::new(&abbrev_buf, LittleEndian);
5205
5206        let abbrevs = unit
5207            .abbreviations(&debug_abbrev)
5208            .expect("Should parse abbreviations");
5209
5210        let mut cursor = unit.entries(&abbrevs);
5211        test_cursor_next_sibling_with_ptr(&mut cursor);
5212    }
5213
5214    #[test]
5215    fn test_entries_at_offset() {
5216        let info_buf = &entries_cursor_tests_debug_info_buf();
5217        let debug_info = DebugInfo::new(info_buf, LittleEndian);
5218
5219        let unit = debug_info
5220            .units()
5221            .next()
5222            .expect("should have a unit result")
5223            .expect("and it should be ok");
5224
5225        let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
5226        let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
5227
5228        let abbrevs = unit
5229            .abbreviations(&debug_abbrev)
5230            .expect("Should parse abbreviations");
5231
5232        let mut cursor = unit
5233            .entries_at_offset(&abbrevs, UnitOffset(unit.header_size()))
5234            .unwrap();
5235        assert_next_entry(&mut cursor, "001");
5236
5237        let cursor = unit.entries_at_offset(&abbrevs, UnitOffset(0));
5238        match cursor {
5239            Err(Error::OffsetOutOfBounds(0)) => {}
5240            otherwise => {
5241                panic!("Unexpected parse result = {:#?}", otherwise);
5242            }
5243        }
5244    }
5245
5246    fn entries_tree_tests_debug_abbrevs_buf() -> Vec<u8> {
5247        #[rustfmt::skip]
5248        let section = Section::with_endian(Endian::Little)
5249            .abbrev(1, DW_TAG_subprogram, DW_CHILDREN_yes)
5250                .abbrev_attr(DW_AT_name, DW_FORM_string)
5251                .abbrev_attr_null()
5252            .abbrev(2, DW_TAG_subprogram, DW_CHILDREN_no)
5253                .abbrev_attr(DW_AT_name, DW_FORM_string)
5254                .abbrev_attr_null()
5255            .abbrev_null()
5256            .get_contents()
5257            .unwrap();
5258        section
5259    }
5260
5261    fn entries_tree_tests_debug_info_buf(header_size: usize) -> (Vec<u8>, UnitOffset) {
5262        let start = Label::new();
5263        let entry2 = Label::new();
5264        #[rustfmt::skip]
5265        let section = Section::with_endian(Endian::Little)
5266            .mark(&start)
5267            .die(1, |s| s.attr_string("root"))
5268                .die(1, |s| s.attr_string("1"))
5269                    .die(1, |s| s.attr_string("1a"))
5270                        .die_null()
5271                    .die(2, |s| s.attr_string("1b"))
5272                    .die_null()
5273                .mark(&entry2)
5274                .die(1, |s| s.attr_string("2"))
5275                    .die(1, |s| s.attr_string("2a"))
5276                        .die(1, |s| s.attr_string("2a1"))
5277                            .die_null()
5278                        .die_null()
5279                    .die(1, |s| s.attr_string("2b"))
5280                        .die(2, |s| s.attr_string("2b1"))
5281                        .die_null()
5282                    .die_null()
5283                .die(1, |s| s.attr_string("3"))
5284                    .die(1, |s| s.attr_string("3a"))
5285                        .die(2, |s| s.attr_string("3a1"))
5286                        .die(2, |s| s.attr_string("3a2"))
5287                        .die_null()
5288                    .die(2, |s| s.attr_string("3b"))
5289                    .die_null()
5290                .die(2, |s| s.attr_string("final"))
5291                .die_null()
5292            .get_contents()
5293            .unwrap();
5294        let entry2 = UnitOffset(header_size + (&entry2 - &start) as usize);
5295        (section, entry2)
5296    }
5297
5298    #[test]
5299    fn test_entries_tree() {
5300        fn assert_entry<'input, 'abbrev, 'tree, Endian>(
5301            node: Result<Option<EntriesTreeNode<'abbrev, 'tree, EndianSlice<'input, Endian>>>>,
5302            name: &str,
5303        ) -> EntriesTreeIter<'abbrev, 'tree, EndianSlice<'input, Endian>>
5304        where
5305            Endian: Endianity,
5306        {
5307            let node = node
5308                .expect("Should parse entry")
5309                .expect("Should have entry");
5310            assert_entry_name(node.entry(), name);
5311            node.children()
5312        }
5313
5314        fn assert_null<E: Endianity>(
5315            node: Result<Option<EntriesTreeNode<'_, '_, EndianSlice<'_, E>>>>,
5316        ) {
5317            match node {
5318                Ok(None) => {}
5319                otherwise => {
5320                    panic!("Unexpected parse result = {:#?}", otherwise);
5321                }
5322            }
5323        }
5324
5325        let abbrevs_buf = entries_tree_tests_debug_abbrevs_buf();
5326        let debug_abbrev = DebugAbbrev::new(&abbrevs_buf, LittleEndian);
5327
5328        let encoding = Encoding {
5329            format: Format::Dwarf32,
5330            version: 4,
5331            address_size: 4,
5332        };
5333        let mut unit = UnitHeader {
5334            encoding,
5335            unit_length: 0,
5336            unit_type: UnitType::Compilation,
5337            debug_abbrev_offset: DebugAbbrevOffset(0),
5338            section: SectionId::DebugInfo,
5339            unit_offset: UnitSectionOffset(0),
5340            entries_buf: EndianSlice::new(&[], LittleEndian),
5341        };
5342        let header_size = unit.size_of_header();
5343        let (entries_buf, entry2) = entries_tree_tests_debug_info_buf(header_size);
5344        unit.entries_buf = EndianSlice::new(&entries_buf, LittleEndian);
5345        let info_buf = Section::with_endian(Endian::Little)
5346            .unit(&mut unit)
5347            .get_contents()
5348            .unwrap();
5349        let debug_info = DebugInfo::new(&info_buf, LittleEndian);
5350
5351        let unit = debug_info
5352            .units()
5353            .next()
5354            .expect("Should parse unit")
5355            .expect("and it should be some");
5356        let abbrevs = unit
5357            .abbreviations(&debug_abbrev)
5358            .expect("Should parse abbreviations");
5359        let mut tree = unit
5360            .entries_tree(&abbrevs, None)
5361            .expect("Should have entries tree");
5362
5363        // Test we can restart iteration of the tree.
5364        {
5365            let mut iter = assert_entry(tree.root().map(Some), "root");
5366            assert_entry(iter.next(), "1");
5367        }
5368        {
5369            let mut iter = assert_entry(tree.root().map(Some), "root");
5370            assert_entry(iter.next(), "1");
5371        }
5372
5373        let mut iter = assert_entry(tree.root().map(Some), "root");
5374        {
5375            // Test iteration with children.
5376            let mut iter = assert_entry(iter.next(), "1");
5377            {
5378                // Test iteration with children flag, but no children.
5379                let mut iter = assert_entry(iter.next(), "1a");
5380                assert_null(iter.next());
5381                assert_null(iter.next());
5382            }
5383            {
5384                // Test iteration without children flag.
5385                let mut iter = assert_entry(iter.next(), "1b");
5386                assert_null(iter.next());
5387                assert_null(iter.next());
5388            }
5389            assert_null(iter.next());
5390            assert_null(iter.next());
5391        }
5392        {
5393            // Test skipping over children.
5394            let mut iter = assert_entry(iter.next(), "2");
5395            assert_entry(iter.next(), "2a");
5396            assert_entry(iter.next(), "2b");
5397            assert_null(iter.next());
5398        }
5399        {
5400            // Test skipping after partial iteration.
5401            let mut iter = assert_entry(iter.next(), "3");
5402            {
5403                let mut iter = assert_entry(iter.next(), "3a");
5404                assert_entry(iter.next(), "3a1");
5405                // Parent iter should be able to skip over "3a2".
5406            }
5407            assert_entry(iter.next(), "3b");
5408            assert_null(iter.next());
5409        }
5410        assert_entry(iter.next(), "final");
5411        assert_null(iter.next());
5412
5413        // Test starting at an offset.
5414        let mut tree = unit
5415            .entries_tree(&abbrevs, Some(entry2))
5416            .expect("Should have entries tree");
5417        let mut iter = assert_entry(tree.root().map(Some), "2");
5418        assert_entry(iter.next(), "2a");
5419        assert_entry(iter.next(), "2b");
5420        assert_null(iter.next());
5421    }
5422
5423    #[test]
5424    fn test_entries_raw() {
5425        fn assert_abbrev<'abbrev, Endian>(
5426            entries: &mut EntriesRaw<'abbrev, EndianSlice<'_, Endian>>,
5427            tag: DwTag,
5428        ) -> &'abbrev Abbreviation
5429        where
5430            Endian: Endianity,
5431        {
5432            let abbrev = entries
5433                .read_abbreviation()
5434                .expect("Should parse abbrev")
5435                .expect("Should have abbrev");
5436            assert_eq!(abbrev.tag(), tag);
5437            abbrev
5438        }
5439
5440        fn assert_null<Endian>(entries: &mut EntriesRaw<'_, EndianSlice<'_, Endian>>)
5441        where
5442            Endian: Endianity,
5443        {
5444            match entries.read_abbreviation() {
5445                Ok(None) => {}
5446                otherwise => {
5447                    panic!("Unexpected parse result = {:#?}", otherwise);
5448                }
5449            }
5450        }
5451
5452        fn assert_attr<Endian>(
5453            entries: &mut EntriesRaw<'_, EndianSlice<'_, Endian>>,
5454            spec: Option<AttributeSpecification>,
5455            name: DwAt,
5456            value: &str,
5457        ) where
5458            Endian: Endianity,
5459        {
5460            let spec = spec.expect("Should have attribute specification");
5461            let attr = entries
5462                .read_attribute(spec)
5463                .expect("Should parse attribute");
5464            assert_eq!(attr.name(), name);
5465            assert_eq!(
5466                attr.value(),
5467                AttributeValue::String(EndianSlice::new(value.as_bytes(), Endian::default()))
5468            );
5469        }
5470
5471        #[rustfmt::skip]
5472        let section = Section::with_endian(Endian::Little)
5473            .abbrev(1, DW_TAG_subprogram, DW_CHILDREN_yes)
5474                .abbrev_attr(DW_AT_name, DW_FORM_string)
5475                .abbrev_attr(DW_AT_linkage_name, DW_FORM_string)
5476                .abbrev_attr_null()
5477            .abbrev(2, DW_TAG_variable, DW_CHILDREN_no)
5478                .abbrev_attr(DW_AT_name, DW_FORM_string)
5479                .abbrev_attr_null()
5480            .abbrev_null();
5481        let abbrevs_buf = section.get_contents().unwrap();
5482        let debug_abbrev = DebugAbbrev::new(&abbrevs_buf, LittleEndian);
5483
5484        #[rustfmt::skip]
5485        let section = Section::with_endian(Endian::Little)
5486            .die(1, |s| s.attr_string("f1").attr_string("l1"))
5487                .die(2, |s| s.attr_string("v1"))
5488                .die(2, |s| s.attr_string("v2"))
5489                .die(1, |s| s.attr_string("f2").attr_string("l2"))
5490                    .die_null()
5491                .die_null();
5492        let entries_buf = section.get_contents().unwrap();
5493
5494        let encoding = Encoding {
5495            format: Format::Dwarf32,
5496            version: 4,
5497            address_size: 4,
5498        };
5499        let mut unit = UnitHeader {
5500            encoding,
5501            unit_length: 0,
5502            unit_type: UnitType::Compilation,
5503            debug_abbrev_offset: DebugAbbrevOffset(0),
5504            section: SectionId::DebugInfo,
5505            unit_offset: UnitSectionOffset(0),
5506            entries_buf: EndianSlice::new(&entries_buf, LittleEndian),
5507        };
5508        let section = Section::with_endian(Endian::Little).unit(&mut unit);
5509        let info_buf = section.get_contents().unwrap();
5510        let debug_info = DebugInfo::new(&info_buf, LittleEndian);
5511
5512        let unit = debug_info
5513            .units()
5514            .next()
5515            .expect("should have a unit result")
5516            .expect("and it should be ok");
5517
5518        let abbrevs = unit
5519            .abbreviations(&debug_abbrev)
5520            .expect("Should parse abbreviations");
5521
5522        let mut entries = unit
5523            .entries_raw(&abbrevs, None)
5524            .expect("Should have entries");
5525
5526        assert_eq!(entries.next_depth(), 0);
5527        let abbrev = assert_abbrev(&mut entries, DW_TAG_subprogram);
5528        let mut attrs = abbrev.attributes().iter().copied();
5529        assert_attr(&mut entries, attrs.next(), DW_AT_name, "f1");
5530        assert_attr(&mut entries, attrs.next(), DW_AT_linkage_name, "l1");
5531        assert!(attrs.next().is_none());
5532
5533        assert_eq!(entries.next_depth(), 1);
5534        let abbrev = assert_abbrev(&mut entries, DW_TAG_variable);
5535        let mut attrs = abbrev.attributes().iter().copied();
5536        assert_attr(&mut entries, attrs.next(), DW_AT_name, "v1");
5537        assert!(attrs.next().is_none());
5538
5539        assert_eq!(entries.next_depth(), 1);
5540        let abbrev = assert_abbrev(&mut entries, DW_TAG_variable);
5541        let mut attrs = abbrev.attributes().iter().copied();
5542        assert_attr(&mut entries, attrs.next(), DW_AT_name, "v2");
5543        assert!(attrs.next().is_none());
5544
5545        assert_eq!(entries.next_depth(), 1);
5546        let abbrev = assert_abbrev(&mut entries, DW_TAG_subprogram);
5547        let mut attrs = abbrev.attributes().iter().copied();
5548        assert_attr(&mut entries, attrs.next(), DW_AT_name, "f2");
5549        assert_attr(&mut entries, attrs.next(), DW_AT_linkage_name, "l2");
5550        assert!(attrs.next().is_none());
5551
5552        assert_eq!(entries.next_depth(), 2);
5553        assert_null(&mut entries);
5554
5555        assert_eq!(entries.next_depth(), 1);
5556        assert_null(&mut entries);
5557
5558        assert_eq!(entries.next_depth(), 0);
5559        assert!(entries.is_empty());
5560    }
5561
5562    #[test]
5563    fn test_debug_info_offset() {
5564        let padding = &[0; 10];
5565        let entries = &[0; 20];
5566        let encoding = Encoding {
5567            format: Format::Dwarf32,
5568            version: 4,
5569            address_size: 4,
5570        };
5571        let mut unit = UnitHeader {
5572            encoding,
5573            unit_length: 0,
5574            unit_type: UnitType::Compilation,
5575            debug_abbrev_offset: DebugAbbrevOffset(0),
5576            section: SectionId::DebugInfo,
5577            unit_offset: UnitSectionOffset(0),
5578            entries_buf: EndianSlice::new(entries, LittleEndian),
5579        };
5580        Section::with_endian(Endian::Little)
5581            .append_bytes(padding)
5582            .unit(&mut unit);
5583        let offset = padding.len();
5584        let header_length = unit.size_of_header();
5585        let length = unit.length_including_self();
5586        assert_eq!(DebugInfoOffset(0).to_unit_offset(&unit), None);
5587        assert_eq!(DebugInfoOffset(offset - 1).to_unit_offset(&unit), None);
5588        assert_eq!(DebugInfoOffset(offset).to_unit_offset(&unit), None);
5589        assert_eq!(
5590            DebugInfoOffset(offset + header_length - 1).to_unit_offset(&unit),
5591            None
5592        );
5593        assert_eq!(
5594            DebugInfoOffset(offset + header_length).to_unit_offset(&unit),
5595            Some(UnitOffset(header_length))
5596        );
5597        assert_eq!(
5598            DebugInfoOffset(offset + length - 1).to_unit_offset(&unit),
5599            Some(UnitOffset(length - 1))
5600        );
5601        assert_eq!(DebugInfoOffset(offset + length).to_unit_offset(&unit), None);
5602        assert_eq!(
5603            UnitOffset(header_length).to_debug_info_offset(&unit),
5604            Some(DebugInfoOffset(offset + header_length))
5605        );
5606        assert_eq!(
5607            UnitOffset(length - 1).to_debug_info_offset(&unit),
5608            Some(DebugInfoOffset(offset + length - 1))
5609        );
5610    }
5611
5612    #[test]
5613    fn test_debug_types_offset() {
5614        let padding = &[0; 10];
5615        let entries = &[0; 20];
5616        let encoding = Encoding {
5617            format: Format::Dwarf32,
5618            version: 4,
5619            address_size: 4,
5620        };
5621        let mut unit = UnitHeader {
5622            encoding,
5623            unit_length: 0,
5624            unit_type: UnitType::Type {
5625                type_signature: DebugTypeSignature(0),
5626                type_offset: UnitOffset(0),
5627            },
5628            debug_abbrev_offset: DebugAbbrevOffset(0),
5629            section: SectionId::DebugTypes,
5630            unit_offset: UnitSectionOffset(0),
5631            entries_buf: EndianSlice::new(entries, LittleEndian),
5632        };
5633        Section::with_endian(Endian::Little)
5634            .append_bytes(padding)
5635            .unit(&mut unit);
5636        let offset = padding.len();
5637        let header_length = unit.size_of_header();
5638        let length = unit.length_including_self();
5639        assert_eq!(DebugTypesOffset(0).to_unit_offset(&unit), None);
5640        assert_eq!(DebugTypesOffset(offset - 1).to_unit_offset(&unit), None);
5641        assert_eq!(DebugTypesOffset(offset).to_unit_offset(&unit), None);
5642        assert_eq!(
5643            DebugTypesOffset(offset + header_length - 1).to_unit_offset(&unit),
5644            None
5645        );
5646        assert_eq!(
5647            DebugTypesOffset(offset + header_length).to_unit_offset(&unit),
5648            Some(UnitOffset(header_length))
5649        );
5650        assert_eq!(
5651            DebugTypesOffset(offset + length - 1).to_unit_offset(&unit),
5652            Some(UnitOffset(length - 1))
5653        );
5654        assert_eq!(
5655            DebugTypesOffset(offset + length).to_unit_offset(&unit),
5656            None
5657        );
5658        assert_eq!(
5659            UnitOffset(header_length).to_debug_types_offset(&unit),
5660            Some(DebugTypesOffset(offset + header_length))
5661        );
5662        assert_eq!(
5663            UnitOffset(length - 1).to_debug_types_offset(&unit),
5664            Some(DebugTypesOffset(offset + length - 1))
5665        );
5666    }
5667
5668    #[test]
5669    fn test_length_including_self() {
5670        let encoding = Encoding {
5671            format: Format::Dwarf32,
5672            version: 4,
5673            address_size: 4,
5674        };
5675        let mut unit = UnitHeader {
5676            encoding,
5677            unit_length: 0,
5678            unit_type: UnitType::Compilation,
5679            debug_abbrev_offset: DebugAbbrevOffset(0),
5680            section: SectionId::DebugInfo,
5681            unit_offset: UnitSectionOffset(0),
5682            entries_buf: EndianSlice::new(&[], LittleEndian),
5683        };
5684        unit.encoding.format = Format::Dwarf32;
5685        assert_eq!(unit.length_including_self(), 4);
5686        unit.encoding.format = Format::Dwarf64;
5687        assert_eq!(unit.length_including_self(), 12);
5688        unit.unit_length = 10;
5689        assert_eq!(unit.length_including_self(), 22);
5690    }
5691
5692    #[test]
5693    fn test_parse_type_unit_abbrevs() {
5694        let types_buf = [
5695            // Type unit header
5696            0x25, 0x00, 0x00, 0x00, // 32-bit unit length = 37
5697            0x04, 0x00, // Version 4
5698            0x00, 0x00, 0x00, 0x00, // debug_abbrev_offset
5699            0x04, // Address size
5700            0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // Type signature
5701            0x01, 0x02, 0x03, 0x04, // Type offset
5702            // DIEs
5703            // Abbreviation code
5704            0x01, // Attribute of form DW_FORM_string = "foo\0"
5705            0x66, 0x6f, 0x6f, 0x00, // Children
5706            // Abbreviation code
5707            0x01, // Attribute of form DW_FORM_string = "foo\0"
5708            0x66, 0x6f, 0x6f, 0x00, // Children
5709            // Abbreviation code
5710            0x01, // Attribute of form DW_FORM_string = "foo\0"
5711            0x66, 0x6f, 0x6f, 0x00, // Children
5712            0x00, // End of children
5713            0x00, // End of children
5714            0x00, // End of children
5715        ];
5716        let debug_types = DebugTypes::new(&types_buf, LittleEndian);
5717
5718        let abbrev_buf = [
5719            // Code
5720            0x01, // DW_TAG_subprogram
5721            0x2e, // DW_CHILDREN_yes
5722            0x01, // Begin attributes
5723            0x03, // Attribute name = DW_AT_name
5724            0x08, // Attribute form = DW_FORM_string
5725            0x00, 0x00, // End attributes
5726            0x00, // Null terminator
5727        ];
5728
5729        let get_some_type_unit = || debug_types.units().next().unwrap().unwrap();
5730
5731        let unit = get_some_type_unit();
5732
5733        let read_debug_abbrev_section_somehow = || &abbrev_buf;
5734        let debug_abbrev = DebugAbbrev::new(read_debug_abbrev_section_somehow(), LittleEndian);
5735        let _abbrevs_for_unit = unit.abbreviations(&debug_abbrev).unwrap();
5736    }
5737}