gimli/read/
unit.rs

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