1use 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    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    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    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    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#[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    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    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    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    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#[derive(Clone, Debug)]
179pub struct DebugInfoUnitHeadersIter<R: Reader> {
180    input: R,
181    offset: DebugInfoOffset<R::Offset>,
182}
183
184impl<R: Reader> DebugInfoUnitHeadersIter<R> {
185    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
215fn parse_unit_type<R: Reader>(input: &mut R) -> Result<constants::DwUt> {
217    let val = input.read_u8()?;
218    Ok(constants::DwUt(val))
219}
220
221fn 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
229pub(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#[derive(Debug, Clone, Copy, PartialEq, Eq)]
241pub enum UnitType<Offset>
242where
243    Offset: ReaderOffset,
244{
245    Compilation,
248    Type {
251        type_signature: DebugTypeSignature,
253        type_offset: UnitOffset<Offset>,
255    },
256    Partial,
259    Skeleton(DwoId),
265    SplitCompilation(DwoId),
271    SplitType {
274        type_signature: DebugTypeSignature,
276        type_offset: UnitOffset<Offset>,
278    },
279}
280
281impl<Offset> UnitType<Offset>
282where
283    Offset: ReaderOffset,
284{
285    #[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#[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
316impl<R, Offset> UnitHeader<R, Offset>
318where
319    R: Reader<Offset = Offset>,
320    Offset: ReaderOffset,
321{
322    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
342impl<R, Offset> UnitHeader<R, Offset>
344where
345    R: Reader<Offset = Offset>,
346    Offset: ReaderOffset,
347{
348    pub fn offset(&self) -> UnitSectionOffset<Offset> {
350        self.unit_offset
351    }
352
353    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    pub fn unit_length(&self) -> Offset {
382        self.unit_length
383    }
384
385    pub fn length_including_self(&self) -> Offset {
388        Offset::from_u8(self.format().initial_length_size()) + self.unit_length
389    }
390
391    pub fn encoding(&self) -> Encoding {
393        self.encoding
394    }
395
396    pub fn version(&self) -> u16 {
398        self.encoding.version
399    }
400
401    pub fn type_(&self) -> UnitType<Offset> {
403        self.unit_type
404    }
405
406    pub fn debug_abbrev_offset(&self) -> DebugAbbrevOffset<Offset> {
409        self.debug_abbrev_offset
410    }
411
412    pub fn address_size(&self) -> u8 {
414        self.encoding.address_size
415    }
416
417    pub fn format(&self) -> Format {
419        self.encoding.format
420    }
421
422    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    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    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    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    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    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    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    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    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    pub fn abbreviations(&self, debug_abbrev: &DebugAbbrev<R>) -> Result<Abbreviations> {
553        debug_abbrev.abbreviations(self.debug_abbrev_offset())
554    }
555}
556
557fn 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    if 2 <= version && version <= 4 {
576        abbrev_offset = parse_debug_abbrev_offset(&mut rest, format)?;
577        address_size = rest.read_address_size()?;
578        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    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
638fn parse_dwo_id<R: Reader>(input: &mut R) -> Result<DwoId> {
640    Ok(DwoId(input.read_u64()?))
641}
642
643#[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    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    pub fn code(&self) -> u64 {
682        self.abbrev.code()
683    }
684
685    pub fn offset(&self) -> UnitOffset<Offset> {
687        self.offset
688    }
689
690    pub fn tag(&self) -> constants::DwTag {
754        self.abbrev.tag()
755    }
756
757    pub fn has_children(&self) -> bool {
759        self.abbrev.has_children()
760    }
761
762    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    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    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    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    #[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    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    #[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#[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    Addr(u64),
940
941    Block(R),
943
944    Data1(u8),
950
951    Data2(u16),
960
961    Data4(u32),
970
971    Data8(u64),
980
981    Sdata(i64),
983
984    Udata(u64),
986
987    Exprloc(Expression<R>),
990
991    Flag(bool),
993
994    SecOffset(Offset),
997
998    DebugAddrBase(DebugAddrBase<Offset>),
1000
1001    DebugAddrIndex(DebugAddrIndex<Offset>),
1003
1004    UnitRef(UnitOffset<Offset>),
1006
1007    DebugInfoRef(DebugInfoOffset<Offset>),
1010
1011    DebugInfoRefSup(DebugInfoOffset<Offset>),
1013
1014    DebugLineRef(DebugLineOffset<Offset>),
1016
1017    LocationListsRef(LocationListsOffset<Offset>),
1019
1020    DebugLocListsBase(DebugLocListsBase<Offset>),
1022
1023    DebugLocListsIndex(DebugLocListsIndex<Offset>),
1025
1026    DebugMacinfoRef(DebugMacinfoOffset<Offset>),
1028
1029    DebugMacroRef(DebugMacroOffset<Offset>),
1031
1032    RangeListsRef(RawRangeListsOffset<Offset>),
1034
1035    DebugRngListsBase(DebugRngListsBase<Offset>),
1037
1038    DebugRngListsIndex(DebugRngListsIndex<Offset>),
1040
1041    DebugTypesRef(DebugTypeSignature),
1043
1044    DebugStrRef(DebugStrOffset<Offset>),
1046
1047    DebugStrRefSup(DebugStrOffset<Offset>),
1049
1050    DebugStrOffsetsBase(DebugStrOffsetsBase<Offset>),
1052
1053    DebugStrOffsetsIndex(DebugStrOffsetsIndex<Offset>),
1055
1056    DebugLineStrRef(DebugLineStrOffset<Offset>),
1058
1059    String(R),
1062
1063    Encoding(constants::DwAte),
1065
1066    DecimalSign(constants::DwDs),
1068
1069    Endianity(constants::DwEnd),
1071
1072    Accessibility(constants::DwAccess),
1074
1075    Visibility(constants::DwVis),
1077
1078    Virtuality(constants::DwVirtuality),
1080
1081    Language(constants::DwLang),
1083
1084    AddressClass(constants::DwAddr),
1086
1087    IdentifierCase(constants::DwId),
1089
1090    CallingConvention(constants::DwCc),
1092
1093    Inline(constants::DwInl),
1095
1096    Ordering(constants::DwOrd),
1098
1099    FileIndex(u64),
1102
1103    DwoId(DwoId),
1106}
1107
1108#[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    pub fn name(&self) -> constants::DwAt {
1119        self.name
1120    }
1121
1122    pub fn raw_value(&self) -> AttributeValue<R> {
1124        self.value.clone()
1125    }
1126
1127    pub fn value(&self) -> AttributeValue<R> {
1136        macro_rules! address {
1159            () => {};
1160        }
1161        macro_rules! addrptr {
1163            () => {
1164                if let Some(offset) = self.offset_value() {
1165                    return AttributeValue::DebugAddrBase(DebugAddrBase(offset));
1166                }
1167            };
1168        }
1169        macro_rules! block {
1174            () => {};
1175        }
1176        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        macro_rules! exprloc {
1198            () => {
1199                if let Some(value) = self.exprloc_value() {
1200                    return AttributeValue::Exprloc(value);
1201                }
1202            };
1203        }
1204        macro_rules! flag {
1207            () => {};
1208        }
1209        macro_rules! lineptr {
1211            () => {
1212                if let Some(offset) = self.offset_value() {
1213                    return AttributeValue::DebugLineRef(DebugLineOffset(offset));
1214                }
1215            };
1216        }
1217        macro_rules! loclistptr {
1221            () => {
1222                if let Some(offset) = self.offset_value() {
1224                    return AttributeValue::LocationListsRef(LocationListsOffset(offset));
1225                }
1226            };
1227        }
1228        macro_rules! loclistsptr {
1230            () => {
1231                if let Some(offset) = self.offset_value() {
1232                    return AttributeValue::DebugLocListsBase(DebugLocListsBase(offset));
1233                }
1234            };
1235        }
1236        macro_rules! macinfoptr {
1239            () => {
1240                if let Some(offset) = self.offset_value() {
1241                    return AttributeValue::DebugMacinfoRef(DebugMacinfoOffset(offset));
1242                }
1243            };
1244        }
1245        macro_rules! macroptr {
1248            () => {
1249                if let Some(offset) = self.offset_value() {
1250                    return AttributeValue::DebugMacroRef(DebugMacroOffset(offset));
1251                }
1252            };
1253        }
1254        macro_rules! reference {
1264            () => {};
1265        }
1266        macro_rules! rangelistptr {
1270            () => {
1271                if let Some(offset) = self.offset_value() {
1273                    return AttributeValue::RangeListsRef(RawRangeListsOffset(offset));
1274                }
1275            };
1276        }
1277        macro_rules! rnglistsptr {
1279            () => {
1280                if let Some(offset) = self.offset_value() {
1281                    return AttributeValue::DebugRngListsBase(DebugRngListsBase(offset));
1282                }
1283            };
1284        }
1285        macro_rules! string {
1295            () => {};
1296        }
1297        macro_rules! stroffsetsptr {
1299            () => {
1300                if let Some(offset) = self.offset_value() {
1301                    return AttributeValue::DebugStrOffsetsBase(DebugStrOffsetsBase(offset));
1302                }
1303            };
1304        }
1305        macro_rules! dwoid {
1307            () => {
1308                if let Some(value) = self.udata_value() {
1309                    return AttributeValue::DwoId(DwoId(value));
1310                }
1311            };
1312        }
1313
1314        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                }
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                block!();
1376                string!();
1377            }
1378            constants::DW_AT_containing_type => {
1379                reference!();
1380            }
1381            constants::DW_AT_default_value => {
1382                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                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                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                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                exprloc!();
1442                reference!();
1443            }
1444            constants::DW_AT_data_member_location => {
1445                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                exprloc!();
1522                reference!();
1523            }
1524            constants::DW_AT_associated => {
1525                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                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                }
1571            constants::DW_AT_decimal_scale => {
1572                }
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                }
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                }
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                }
1631            constants::DW_AT_string_length_byte_size => {
1632                }
1634            constants::DW_AT_rank => {
1635                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                }
1704            constants::DW_AT_export_symbols => {
1705                flag!();
1706            }
1707            constants::DW_AT_deleted => {
1708                flag!();
1709            }
1710            constants::DW_AT_defaulted => {
1711                }
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    #[inline]
1726    pub fn u8_value(&self) -> Option<u8> {
1727        self.value.u8_value()
1728    }
1729
1730    #[inline]
1732    pub fn u16_value(&self) -> Option<u16> {
1733        self.value.u16_value()
1734    }
1735
1736    #[inline]
1738    pub fn udata_value(&self) -> Option<u64> {
1739        self.value.udata_value()
1740    }
1741
1742    #[inline]
1744    pub fn sdata_value(&self) -> Option<i64> {
1745        self.value.sdata_value()
1746    }
1747
1748    #[inline]
1750    pub fn offset_value(&self) -> Option<R::Offset> {
1751        self.value.offset_value()
1752    }
1753
1754    #[inline]
1760    pub fn exprloc_value(&self) -> Option<Expression<R>> {
1761        self.value.exprloc_value()
1762    }
1763
1764    #[inline]
1774    pub fn string_value(&self, debug_str: &DebugStr<R>) -> Option<R> {
1775        self.value.string_value(debug_str)
1776    }
1777
1778    #[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    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    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    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                    return None;
1835                }
1836                data as u64
1837            }
1838            _ => return None,
1839        })
1840    }
1841
1842    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                    return None;
1854                }
1855                data as i64
1856            }
1857            _ => return None,
1858        })
1859    }
1860
1861    pub fn offset_value(&self) -> Option<R::Offset> {
1863        if let AttributeValue::SecOffset(offset) = *self {
1866            Some(offset)
1867        } else {
1868            None
1869        }
1870    }
1871
1872    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    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    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
1948fn 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                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                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                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                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                skip_bytes += R::Offset::from_u8(len);
2207                break;
2208            }
2209
2210            if skip_bytes != R::Offset::from_u8(0) {
2212                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        input.skip(skip_bytes)?;
2259    }
2260    Ok(())
2261}
2262
2263#[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    #[inline(always)]
2285    pub fn next(&mut self) -> Result<Option<Attribute<R>>> {
2286        if self.attributes.is_empty() {
2287            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#[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    #[inline]
2395    pub fn is_empty(&self) -> bool {
2396        self.input.is_empty()
2397    }
2398
2399    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    #[inline]
2412    pub fn next_depth(&self) -> isize {
2413        self.depth
2414    }
2415
2416    #[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    #[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    #[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#[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    #[inline]
2480    pub fn current(&self) -> Option<&DebuggingInformationEntry<'abbrev, 'unit, R>> {
2481        self.cached_current.as_ref()
2482    }
2483
2484    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    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            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                delta_depth += self.delta_depth;
2649            } else {
2650                return Ok(None);
2651            }
2652        }
2653    }
2654
2655    pub fn next_sibling(
2762        &mut self,
2763    ) -> Result<Option<&DebuggingInformationEntry<'abbrev, 'unit, R>>> {
2764        if self.current().is_none() {
2765            return Ok(None);
2767        }
2768
2769        let mut depth = 0;
2771        loop {
2772            if self.current().is_some() && self.current().unwrap().has_children() {
2774                if let Some(sibling_input) = self.current().unwrap().sibling() {
2775                    self.input = sibling_input;
2779                    self.cached_current = None;
2780                } else {
2781                    depth += 1;
2784                }
2785            }
2786
2787            if self.next_entry()?.is_none() {
2788                return Ok(None);
2790            }
2791
2792            if depth == 0 {
2793                return Ok(self.current());
2795            }
2796
2797            if self.current().is_none() {
2798                depth -= 1;
2801            }
2802        }
2803    }
2804}
2805
2806#[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    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    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                            self.input = sibling_input;
2935                        } else {
2936                            self.depth += 1;
2939                            self.input = entry.after_attrs()?;
2940                        }
2941                    } else {
2942                        self.input = entry.after_attrs()?;
2944                    }
2945                }
2946                None => {
2947                    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#[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    pub fn entry(&self) -> &DebuggingInformationEntry<'abbrev, 'unit, R> {
2995        self.tree.entry.as_ref().unwrap()
2997    }
2998
2999    pub fn children(self) -> EntriesTreeIter<'abbrev, 'unit, 'tree, R> {
3004        EntriesTreeIter::new(self.tree, self.depth)
3005    }
3006}
3007
3008#[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    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
3047fn parse_type_signature<R: Reader>(input: &mut R) -> Result<DebugTypeSignature> {
3050    input.read_u64().map(DebugTypeSignature)
3051}
3052
3053fn parse_type_offset<R: Reader>(input: &mut R, format: Format) -> Result<UnitOffset<R::Offset>> {
3055    input.read_offset(format).map(UnitOffset)
3056}
3057
3058#[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    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    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    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#[derive(Clone, Debug)]
3152pub struct DebugTypesUnitHeadersIter<R: Reader> {
3153    input: R,
3154    offset: DebugTypesOffset<R::Offset>,
3155}
3156
3157impl<R: Reader> DebugTypesUnitHeadersIter<R> {
3158    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#[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    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    #[test]
3317    fn test_unit_header_variance() {
3318        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        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        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        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        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        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        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        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        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        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        assert!(attrs.next().is_err());
5026        assert!(entry.attrs_len.get().is_none());
5027
5028        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 = §ion.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            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        assert_next_dfs(&mut cursor, "002", 1);
5358
5359        assert_next_sibling(&mut cursor, "004");
5362        assert_next_sibling(&mut cursor, "007");
5363        assert_next_sibling(&mut cursor, "010");
5364
5365        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        assert_next_dfs(&mut cursor, "002", 1);
5399
5400        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        assert_next_dfs(&mut cursor, "007", -1);
5425        assert_next_sibling(&mut cursor, "010");
5426
5427        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                .die(1, |s| s.attr_string("002").D8(&sibling004_ref))
5463                    .die(10, |s| s.attr_string("003"))
5465                        .die_null()
5466                    .die_null()
5467                .mark(&sibling004)
5468                .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                .die(2, |s| s.attr_string("006"))
5475                    .die(1, |s| s.attr_string("007").D8(&sibling009_ref))
5477                        .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                .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        assert_next_dfs(cursor, "002", 1);
5509
5510        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        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        {
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            let mut iter = assert_entry(iter.next(), "1");
5772            {
5773                let mut iter = assert_entry(iter.next(), "1a");
5775                assert_null(iter.next());
5776                assert_null(iter.next());
5777            }
5778            {
5779                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            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            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                }
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        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            0x25, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04, 0x01, 0x66, 0x6f, 0x6f, 0x00, 0x01, 0x66, 0x6f, 0x6f, 0x00, 0x01, 0x66, 0x6f, 0x6f, 0x00, 0x00, 0x00, 0x00, ];
6107        let debug_types = DebugTypes::new(&types_buf, LittleEndian);
6108
6109        let abbrev_buf = [
6110            0x01, 0x2e, 0x01, 0x03, 0x08, 0x00, 0x00, 0x00, ];
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}