1use alloc::vec::Vec;
4use core::ops::{Range, RangeFrom, RangeTo};
5
6use crate::common::{
7 DebugAbbrevOffset, DebugAddrBase, DebugAddrIndex, DebugInfoOffset, DebugLineOffset,
8 DebugLineStrOffset, DebugLocListsBase, DebugLocListsIndex, DebugMacinfoOffset,
9 DebugMacroOffset, DebugRngListsBase, DebugRngListsIndex, DebugStrOffset, DebugStrOffsetsBase,
10 DebugStrOffsetsIndex, DebugTypeSignature, DebugTypesOffset, DwoId, Encoding, Format,
11 LocationListsOffset, RawRangeListsOffset, SectionId, UnitSectionOffset,
12};
13use crate::constants;
14use crate::endianity::Endianity;
15use crate::read::abbrev::get_attribute_size;
16use crate::read::{
17 Abbreviation, Abbreviations, AttributeSpecification, DebugAbbrev, DebugStr, EndianSlice, Error,
18 Expression, Reader, ReaderAddress, ReaderOffset, Result, Section, UnitOffset,
19};
20
21impl<T: ReaderOffset> DebugInfoOffset<T> {
22 pub fn to_unit_section_offset<R>(&self, unit: &UnitHeader<R>) -> Option<UnitSectionOffset<T>>
27 where
28 R: Reader<Offset = T>,
29 {
30 if unit.section != SectionId::DebugInfo {
31 return None;
32 }
33 Some(UnitSectionOffset(self.0))
34 }
35
36 pub fn to_unit_offset<R>(&self, unit: &UnitHeader<R>) -> Option<UnitOffset<T>>
41 where
42 R: Reader<Offset = T>,
43 {
44 self.to_unit_section_offset(unit)?.to_unit_offset(unit)
45 }
46}
47
48impl<T: ReaderOffset> DebugTypesOffset<T> {
49 pub fn to_unit_section_offset<R>(&self, unit: &UnitHeader<R>) -> Option<UnitSectionOffset<T>>
54 where
55 R: Reader<Offset = T>,
56 {
57 if unit.section != SectionId::DebugTypes {
58 return None;
59 }
60 Some(UnitSectionOffset(self.0))
61 }
62
63 pub fn to_unit_offset<R>(&self, unit: &UnitHeader<R>) -> Option<UnitOffset<T>>
68 where
69 R: Reader<Offset = T>,
70 {
71 self.to_unit_section_offset(unit)?.to_unit_offset(unit)
72 }
73}
74
75impl<T: ReaderOffset> UnitSectionOffset<T> {
76 pub fn to_unit_offset<R>(&self, unit: &UnitHeader<R>) -> Option<UnitOffset<T>>
81 where
82 R: Reader<Offset = T>,
83 {
84 let offset = UnitOffset(self.0.checked_sub(unit.offset().0)?);
85 if !unit.is_in_bounds(offset) {
86 return None;
87 }
88 Some(offset)
89 }
90
91 pub fn to_debug_info_offset<R>(&self, unit: &UnitHeader<R>) -> Option<DebugInfoOffset<T>>
96 where
97 R: Reader<Offset = T>,
98 {
99 if unit.section != SectionId::DebugInfo {
100 return None;
101 }
102 Some(DebugInfoOffset(self.0))
103 }
104
105 pub fn to_debug_types_offset<R>(&self, unit: &UnitHeader<R>) -> Option<DebugTypesOffset<T>>
110 where
111 R: Reader<Offset = T>,
112 {
113 if unit.section != SectionId::DebugTypes {
114 return None;
115 }
116 Some(DebugTypesOffset(self.0))
117 }
118}
119
120impl<T: ReaderOffset> UnitOffset<T> {
121 pub fn is_in_bounds<R>(&self, unit: &UnitHeader<R>) -> bool
126 where
127 R: Reader<Offset = T>,
128 {
129 unit.is_in_bounds(*self)
130 }
131
132 pub fn to_unit_section_offset<R>(&self, unit: &UnitHeader<R>) -> UnitSectionOffset<T>
139 where
140 R: Reader<Offset = T>,
141 {
142 UnitSectionOffset(unit.offset().0 + self.0)
143 }
144
145 pub fn to_debug_info_offset<R>(&self, unit: &UnitHeader<R>) -> Option<DebugInfoOffset<T>>
150 where
151 R: Reader<Offset = T>,
152 {
153 self.to_unit_section_offset(unit).to_debug_info_offset(unit)
154 }
155
156 pub fn to_debug_types_offset<R>(&self, unit: &UnitHeader<R>) -> Option<DebugTypesOffset<T>>
161 where
162 R: Reader<Offset = T>,
163 {
164 self.to_unit_section_offset(unit)
165 .to_debug_types_offset(unit)
166 }
167}
168
169#[derive(Debug, Default, Clone, Copy)]
172pub struct DebugInfo<R> {
173 debug_info_section: R,
174}
175
176impl<'input, Endian> DebugInfo<EndianSlice<'input, Endian>>
177where
178 Endian: Endianity,
179{
180 pub fn new(debug_info_section: &'input [u8], endian: Endian) -> Self {
195 Self::from(EndianSlice::new(debug_info_section, endian))
196 }
197}
198
199impl<R: Reader> DebugInfo<R> {
200 pub fn units(&self) -> DebugInfoUnitHeadersIter<R> {
215 DebugInfoUnitHeadersIter {
216 input: self.debug_info_section.clone(),
217 offset: UnitSectionOffset(R::Offset::from_u8(0)),
218 }
219 }
220
221 pub fn header_from_offset(&self, offset: DebugInfoOffset<R::Offset>) -> Result<UnitHeader<R>> {
225 let input = &mut self.debug_info_section.clone();
226 input.skip(offset.0)?;
227 parse_unit_header(input, SectionId::DebugInfo, UnitSectionOffset(offset.0))
228 }
229}
230
231impl<T> DebugInfo<T> {
232 pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugInfo<R>
238 where
239 F: FnMut(&'a T) -> R,
240 {
241 borrow(&self.debug_info_section).into()
242 }
243}
244
245impl<R> Section<R> for DebugInfo<R> {
246 fn id() -> SectionId {
247 SectionId::DebugInfo
248 }
249
250 fn reader(&self) -> &R {
251 &self.debug_info_section
252 }
253}
254
255impl<R> From<R> for DebugInfo<R> {
256 fn from(debug_info_section: R) -> Self {
257 DebugInfo { debug_info_section }
258 }
259}
260
261#[derive(Clone, Debug)]
266pub struct DebugInfoUnitHeadersIter<R: Reader> {
267 input: R,
268 offset: UnitSectionOffset<R::Offset>,
269}
270
271impl<R: Reader> DebugInfoUnitHeadersIter<R> {
272 pub fn next(&mut self) -> Result<Option<UnitHeader<R>>> {
274 if self.input.is_empty() {
275 Ok(None)
276 } else {
277 let len = self.input.len();
278 match parse_unit_header(&mut self.input, SectionId::DebugInfo, self.offset) {
279 Ok(header) => {
280 self.offset.0 += len - self.input.len();
281 Ok(Some(header))
282 }
283 Err(e) => {
284 self.input.empty();
285 Err(e)
286 }
287 }
288 }
289 }
290}
291
292#[cfg(feature = "fallible-iterator")]
293impl<R: Reader> fallible_iterator::FallibleIterator for DebugInfoUnitHeadersIter<R> {
294 type Item = UnitHeader<R>;
295 type Error = Error;
296
297 fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
298 DebugInfoUnitHeadersIter::next(self)
299 }
300}
301
302impl<R: Reader> Iterator for DebugInfoUnitHeadersIter<R> {
303 type Item = Result<UnitHeader<R>>;
304
305 fn next(&mut self) -> Option<Self::Item> {
306 DebugInfoUnitHeadersIter::next(self).transpose()
307 }
308}
309
310#[derive(Debug, Clone, Copy, PartialEq, Eq)]
314pub enum UnitType<Offset>
315where
316 Offset: ReaderOffset,
317{
318 Compilation,
321 Type {
324 type_signature: DebugTypeSignature,
326 type_offset: UnitOffset<Offset>,
328 },
329 Partial,
332 Skeleton(DwoId),
338 SplitCompilation(DwoId),
344 SplitType {
347 type_signature: DebugTypeSignature,
349 type_offset: UnitOffset<Offset>,
351 },
352}
353
354impl<Offset> UnitType<Offset>
355where
356 Offset: ReaderOffset,
357{
358 #[allow(unused)]
361 pub(crate) fn dw_ut(&self) -> constants::DwUt {
362 match self {
363 UnitType::Compilation => constants::DW_UT_compile,
364 UnitType::Type { .. } => constants::DW_UT_type,
365 UnitType::Partial => constants::DW_UT_partial,
366 UnitType::Skeleton(_) => constants::DW_UT_skeleton,
367 UnitType::SplitCompilation(_) => constants::DW_UT_split_compile,
368 UnitType::SplitType { .. } => constants::DW_UT_split_type,
369 }
370 }
371}
372
373#[derive(Debug, Clone, Copy, PartialEq, Eq)]
376pub struct UnitHeader<R, Offset = <R as Reader>::Offset>
377where
378 R: Reader<Offset = Offset>,
379 Offset: ReaderOffset,
380{
381 encoding: Encoding,
382 unit_length: Offset,
383 unit_type: UnitType<Offset>,
384 debug_abbrev_offset: DebugAbbrevOffset<Offset>,
385 section: SectionId,
386 unit_offset: UnitSectionOffset<Offset>,
387 entries_buf: R,
388}
389
390impl<R, Offset> UnitHeader<R, Offset>
392where
393 R: Reader<Offset = Offset>,
394 Offset: ReaderOffset,
395{
396 pub fn new(
398 encoding: Encoding,
399 unit_length: Offset,
400 unit_type: UnitType<Offset>,
401 debug_abbrev_offset: DebugAbbrevOffset<Offset>,
402 section: SectionId,
403 unit_offset: UnitSectionOffset<Offset>,
404 entries_buf: R,
405 ) -> Self {
406 UnitHeader {
407 encoding,
408 unit_length,
409 unit_type,
410 debug_abbrev_offset,
411 section,
412 unit_offset,
413 entries_buf,
414 }
415 }
416}
417
418impl<R, Offset> UnitHeader<R, Offset>
420where
421 R: Reader<Offset = Offset>,
422 Offset: ReaderOffset,
423{
424 pub fn section(&self) -> SectionId {
426 self.section
427 }
428
429 pub fn offset(&self) -> UnitSectionOffset<Offset> {
431 self.unit_offset
432 }
433
434 pub fn debug_info_offset(&self) -> Option<DebugInfoOffset<Offset>> {
438 self.unit_offset.to_debug_info_offset(self)
439 }
440
441 pub fn debug_types_offset(&self) -> Option<DebugTypesOffset<Offset>> {
445 self.unit_offset.to_debug_types_offset(self)
446 }
447
448 pub fn size_of_header(&self) -> usize {
451 let unit_length_size = self.encoding.format.initial_length_size() as usize;
452 let version_size = 2;
453 let debug_abbrev_offset_size = self.encoding.format.word_size() as usize;
454 let address_size_size = 1;
455 let unit_type_size = if self.encoding.version == 5 { 1 } else { 0 };
456 let type_specific_size = match self.unit_type {
457 UnitType::Compilation | UnitType::Partial => 0,
458 UnitType::Type { .. } | UnitType::SplitType { .. } => {
459 let type_signature_size = 8;
460 let type_offset_size = self.encoding.format.word_size() as usize;
461 type_signature_size + type_offset_size
462 }
463 UnitType::Skeleton(_) | UnitType::SplitCompilation(_) => 8,
464 };
465
466 unit_length_size
467 + version_size
468 + debug_abbrev_offset_size
469 + address_size_size
470 + unit_type_size
471 + type_specific_size
472 }
473
474 pub fn unit_length(&self) -> Offset {
477 self.unit_length
478 }
479
480 pub fn length_including_self(&self) -> Offset {
483 Offset::from_u8(self.format().initial_length_size()) + self.unit_length
484 }
485
486 pub fn encoding(&self) -> Encoding {
488 self.encoding
489 }
490
491 pub fn version(&self) -> u16 {
493 self.encoding.version
494 }
495
496 pub fn type_(&self) -> UnitType<Offset> {
498 self.unit_type
499 }
500
501 pub fn debug_abbrev_offset(&self) -> DebugAbbrevOffset<Offset> {
504 self.debug_abbrev_offset
505 }
506
507 pub fn address_size(&self) -> u8 {
509 self.encoding.address_size
510 }
511
512 pub fn format(&self) -> Format {
514 self.encoding.format
515 }
516
517 pub fn header_size(&self) -> Offset {
519 self.length_including_self() - self.entries_buf.len()
520 }
521
522 pub fn root_offset(&self) -> UnitOffset<Offset> {
524 UnitOffset(self.header_size())
525 }
526
527 pub(crate) fn is_in_bounds(&self, offset: UnitOffset<Offset>) -> bool {
528 let size_of_header = self.header_size();
529 if offset.0 < size_of_header {
530 return false;
531 }
532
533 let relative_to_entries_buf = offset.0 - size_of_header;
534 relative_to_entries_buf < self.entries_buf.len()
535 }
536
537 pub fn range(&self, idx: Range<UnitOffset<Offset>>) -> Result<R> {
539 if !self.is_in_bounds(idx.start) {
540 return Err(Error::OffsetOutOfBounds(idx.start.0.into_u64()));
541 }
542 if !self.is_in_bounds(idx.end) {
543 return Err(Error::OffsetOutOfBounds(idx.end.0.into_u64()));
544 }
545 assert!(idx.start <= idx.end);
546 let size_of_header = self.header_size();
547 let start = idx.start.0 - size_of_header;
548 let end = idx.end.0 - size_of_header;
549 let mut input = self.entries_buf.clone();
550 input.skip(start)?;
551 input.truncate(end - start)?;
552 Ok(input)
553 }
554
555 pub fn range_from(&self, idx: RangeFrom<UnitOffset<Offset>>) -> Result<R> {
557 if !self.is_in_bounds(idx.start) {
558 return Err(Error::OffsetOutOfBounds(idx.start.0.into_u64()));
559 }
560 let start = idx.start.0 - self.header_size();
561 let mut input = self.entries_buf.clone();
562 input.skip(start)?;
563 Ok(input)
564 }
565
566 pub fn range_to(&self, idx: RangeTo<UnitOffset<Offset>>) -> Result<R> {
568 if !self.is_in_bounds(idx.end) {
569 return Err(Error::OffsetOutOfBounds(idx.end.0.into_u64()));
570 }
571 let end = idx.end.0 - self.header_size();
572 let mut input = self.entries_buf.clone();
573 input.truncate(end)?;
574 Ok(input)
575 }
576
577 pub fn entry<'abbrev>(
583 &self,
584 abbreviations: &'abbrev Abbreviations,
585 offset: UnitOffset<Offset>,
586 ) -> Result<DebuggingInformationEntry<R>> {
587 let mut entry = DebuggingInformationEntry::null();
588 let mut input = self.entries_raw(abbreviations, Some(offset))?;
589 input.read_entry(&mut entry)?;
590 if entry.is_null() {
591 Err(Error::NoEntryAtGivenOffset(offset.0.into_u64()))
592 } else {
593 Ok(entry)
594 }
595 }
596
597 pub fn entries<'abbrev>(
599 &self,
600 abbreviations: &'abbrev Abbreviations,
601 ) -> EntriesCursor<'abbrev, R> {
602 EntriesCursor::new(
603 self.entries_buf.clone(),
604 self.encoding,
605 abbreviations,
606 self.root_offset(),
607 )
608 }
609
610 pub fn entries_at_offset<'abbrev>(
613 &self,
614 abbreviations: &'abbrev Abbreviations,
615 offset: UnitOffset<Offset>,
616 ) -> Result<EntriesCursor<'abbrev, R>> {
617 Ok(EntriesCursor::new(
618 self.range_from(offset..)?,
619 self.encoding,
620 abbreviations,
621 offset,
622 ))
623 }
624
625 pub fn entries_tree<'abbrev>(
628 &self,
629 abbreviations: &'abbrev Abbreviations,
630 offset: Option<UnitOffset<Offset>>,
631 ) -> Result<EntriesTree<'abbrev, R>> {
632 let offset = offset.unwrap_or_else(|| self.root_offset());
633 Ok(EntriesTree::new(
634 self.range_from(offset..)?,
635 self.encoding,
636 abbreviations,
637 offset,
638 ))
639 }
640
641 pub fn entries_raw<'abbrev>(
643 &self,
644 abbreviations: &'abbrev Abbreviations,
645 offset: Option<UnitOffset<Offset>>,
646 ) -> Result<EntriesRaw<'abbrev, R>> {
647 let offset = offset.unwrap_or_else(|| self.root_offset());
648 Ok(EntriesRaw::new(
649 self.range_from(offset..)?,
650 self.encoding,
651 abbreviations,
652 offset,
653 ))
654 }
655
656 pub fn abbreviations(&self, debug_abbrev: &DebugAbbrev<R>) -> Result<Abbreviations> {
658 debug_abbrev.abbreviations(self.debug_abbrev_offset())
659 }
660
661 pub fn is_tombstone_address(&self, address: u64) -> bool {
669 address >= u64::min_tombstone(self.encoding.address_size)
670 }
671}
672
673fn parse_unit_header<R, Offset>(
675 input: &mut R,
676 section: SectionId,
677 unit_offset: UnitSectionOffset<Offset>,
678) -> Result<UnitHeader<R>>
679where
680 R: Reader<Offset = Offset>,
681 Offset: ReaderOffset,
682{
683 let (unit_length, format) = input.read_initial_length()?;
684 let mut rest = input.split(unit_length)?;
685
686 let version = rest.read_u16()?;
687 let abbrev_offset;
688 let address_size;
689 let unit_type;
690 if 2 <= version && version <= 4 {
693 abbrev_offset = rest.read_offset(format).map(DebugAbbrevOffset)?;
694 address_size = rest.read_address_size()?;
695 unit_type = match section {
698 SectionId::DebugTypes => constants::DW_UT_type,
699 _ => constants::DW_UT_compile,
700 };
701 } else if version == 5 {
702 unit_type = rest.read_u8().map(constants::DwUt)?;
703 address_size = rest.read_address_size()?;
704 abbrev_offset = rest.read_offset(format).map(DebugAbbrevOffset)?;
705 } else {
706 return Err(Error::UnknownVersion(u64::from(version)));
707 }
708 let encoding = Encoding {
709 format,
710 version,
711 address_size,
712 };
713
714 let unit_type = match unit_type {
716 constants::DW_UT_compile => UnitType::Compilation,
717 constants::DW_UT_type => {
718 let type_signature = rest.read_u64().map(DebugTypeSignature)?;
719 let type_offset = rest.read_offset(format).map(UnitOffset)?;
720 UnitType::Type {
721 type_signature,
722 type_offset,
723 }
724 }
725 constants::DW_UT_partial => UnitType::Partial,
726 constants::DW_UT_skeleton => {
727 let dwo_id = rest.read_u64().map(DwoId)?;
728 UnitType::Skeleton(dwo_id)
729 }
730 constants::DW_UT_split_compile => {
731 let dwo_id = rest.read_u64().map(DwoId)?;
732 UnitType::SplitCompilation(dwo_id)
733 }
734 constants::DW_UT_split_type => {
735 let type_signature = rest.read_u64().map(DebugTypeSignature)?;
736 let type_offset = rest.read_offset(format).map(UnitOffset)?;
737 UnitType::SplitType {
738 type_signature,
739 type_offset,
740 }
741 }
742 _ => return Err(Error::UnknownUnitType(unit_type)),
743 };
744
745 Ok(UnitHeader::new(
746 encoding,
747 unit_length,
748 unit_type,
749 abbrev_offset,
750 section,
751 unit_offset,
752 rest,
753 ))
754}
755
756#[derive(Clone, Debug)]
763pub struct DebuggingInformationEntry<R, Offset = <R as Reader>::Offset>
764where
765 R: Reader<Offset = Offset>,
766 Offset: ReaderOffset,
767{
768 pub tag: constants::DwTag,
770 pub has_children: bool,
774 pub attrs: Vec<Attribute<R>>,
776 pub offset: UnitOffset<Offset>,
778 pub depth: isize,
780}
781
782impl<R, Offset> Default for DebuggingInformationEntry<R, Offset>
783where
784 R: Reader<Offset = Offset>,
785 Offset: ReaderOffset,
786{
787 fn default() -> Self {
788 Self::null()
789 }
790}
791
792impl<R, Offset> DebuggingInformationEntry<R, Offset>
793where
794 R: Reader<Offset = Offset>,
795 Offset: ReaderOffset,
796{
797 pub fn new(
799 tag: constants::DwTag,
800 has_children: bool,
801 attrs: Vec<Attribute<R>>,
802 offset: UnitOffset<Offset>,
803 ) -> Self {
804 DebuggingInformationEntry {
805 tag,
806 has_children,
807 attrs,
808 offset,
809 depth: 0,
810 }
811 }
812
813 pub fn null() -> Self {
815 DebuggingInformationEntry {
816 tag: constants::DW_TAG_null,
817 has_children: false,
818 attrs: Vec::new(),
819 offset: UnitOffset(Offset::from_u8(0)),
820 depth: 0,
821 }
822 }
823
824 pub fn is_null(&self) -> bool {
826 self.tag == constants::DW_TAG_null
827 }
828
829 pub fn set_null(&mut self) {
833 self.tag = constants::DW_TAG_null;
834 self.has_children = false;
835 self.attrs.clear();
836 }
837
838 pub fn depth(&self) -> isize {
840 self.depth
841 }
842
843 pub fn offset(&self) -> UnitOffset<Offset> {
845 self.offset
846 }
847
848 pub fn tag(&self) -> constants::DwTag {
850 self.tag
851 }
852
853 pub fn has_children(&self) -> bool {
855 self.has_children
856 }
857
858 pub fn attrs(&self) -> &[Attribute<R>] {
860 &self.attrs
861 }
862
863 pub fn has_attr(&self, name: constants::DwAt) -> bool {
865 self.attrs.iter().any(|attr| attr.name == name)
866 }
867
868 pub fn attr(&self, name: constants::DwAt) -> Option<&Attribute<R>> {
872 self.attrs.iter().find(|attr| attr.name == name)
873 }
874
875 pub fn attr_value_raw(&self, name: constants::DwAt) -> Option<AttributeValue<R>> {
880 self.attr(name).map(Attribute::raw_value)
881 }
882
883 pub fn attr_value(&self, name: constants::DwAt) -> Option<AttributeValue<R>> {
888 self.attr(name).map(Attribute::value)
889 }
890
891 fn sibling(&self) -> Option<UnitOffset<R::Offset>> {
894 if let Some(AttributeValue::UnitRef(offset)) = self.attr_value(constants::DW_AT_sibling)
895 && offset.0 > self.offset.0
896 {
897 return Some(offset);
898 }
899 None
900 }
901}
902
903#[repr(u64)]
908#[derive(Clone, Copy, Debug, Eq, PartialEq)]
909pub enum AttributeValue<R, Offset = <R as Reader>::Offset>
910where
911 R: Reader<Offset = Offset>,
912 Offset: ReaderOffset,
913{
914 Addr(u64),
916
917 Block(R),
919
920 Data1(u8),
926
927 Data2(u16),
936
937 Data4(u32),
946
947 Data8(u64),
956
957 Data16(u128),
966
967 Sdata(i64),
969
970 Udata(u64),
972
973 Exprloc(Expression<R>),
976
977 Flag(bool),
979
980 SecOffset(Offset),
983
984 DebugAddrBase(DebugAddrBase<Offset>),
986
987 DebugAddrIndex(DebugAddrIndex<Offset>),
989
990 UnitRef(UnitOffset<Offset>),
992
993 DebugInfoRef(DebugInfoOffset<Offset>),
996
997 DebugInfoRefSup(DebugInfoOffset<Offset>),
999
1000 DebugLineRef(DebugLineOffset<Offset>),
1002
1003 LocationListsRef(LocationListsOffset<Offset>),
1005
1006 DebugLocListsBase(DebugLocListsBase<Offset>),
1008
1009 DebugLocListsIndex(DebugLocListsIndex<Offset>),
1011
1012 DebugMacinfoRef(DebugMacinfoOffset<Offset>),
1014
1015 DebugMacroRef(DebugMacroOffset<Offset>),
1017
1018 RangeListsRef(RawRangeListsOffset<Offset>),
1020
1021 DebugRngListsBase(DebugRngListsBase<Offset>),
1023
1024 DebugRngListsIndex(DebugRngListsIndex<Offset>),
1026
1027 DebugTypesRef(DebugTypeSignature),
1029
1030 DebugStrRef(DebugStrOffset<Offset>),
1032
1033 DebugStrRefSup(DebugStrOffset<Offset>),
1035
1036 DebugStrOffsetsBase(DebugStrOffsetsBase<Offset>),
1038
1039 DebugStrOffsetsIndex(DebugStrOffsetsIndex<Offset>),
1041
1042 DebugLineStrRef(DebugLineStrOffset<Offset>),
1044
1045 String(R),
1048
1049 Encoding(constants::DwAte),
1051
1052 DecimalSign(constants::DwDs),
1054
1055 Endianity(constants::DwEnd),
1057
1058 Accessibility(constants::DwAccess),
1060
1061 Visibility(constants::DwVis),
1063
1064 Virtuality(constants::DwVirtuality),
1066
1067 Language(constants::DwLang),
1069
1070 AddressClass(constants::DwAddr),
1072
1073 IdentifierCase(constants::DwId),
1075
1076 CallingConvention(constants::DwCc),
1078
1079 Inline(constants::DwInl),
1081
1082 Ordering(constants::DwOrd),
1084
1085 FileIndex(u64),
1088
1089 DwoId(DwoId),
1092}
1093
1094#[derive(Copy, Clone, Debug, Eq, PartialEq)]
1097pub struct Attribute<R: Reader> {
1098 name: constants::DwAt,
1099 form: constants::DwForm,
1100 value: AttributeValue<R>,
1101}
1102
1103impl<R: Reader> Attribute<R> {
1104 pub fn name(&self) -> constants::DwAt {
1106 self.name
1107 }
1108
1109 pub fn form(&self) -> constants::DwForm {
1111 self.form
1112 }
1113
1114 pub fn raw_value(&self) -> AttributeValue<R> {
1116 self.value.clone()
1117 }
1118
1119 pub fn value(&self) -> AttributeValue<R> {
1128 macro_rules! address {
1151 () => {};
1152 }
1153 macro_rules! addrptr {
1155 () => {
1156 if let Some(offset) = self.offset_value() {
1157 return AttributeValue::DebugAddrBase(DebugAddrBase(offset));
1158 }
1159 };
1160 }
1161 macro_rules! block {
1166 () => {};
1167 }
1168 macro_rules! constant {
1177 ($value:ident, $variant:ident) => {
1178 if let Some(value) = self.$value() {
1179 return AttributeValue::$variant(value);
1180 }
1181 };
1182 ($value:ident, $variant:ident, $constant:ident) => {
1183 if let Some(value) = self.$value() {
1184 return AttributeValue::$variant(constants::$constant(value));
1185 }
1186 };
1187 }
1188 macro_rules! exprloc {
1190 () => {
1191 if let Some(value) = self.exprloc_value() {
1192 return AttributeValue::Exprloc(value);
1193 }
1194 };
1195 }
1196 macro_rules! flag {
1199 () => {};
1200 }
1201 macro_rules! lineptr {
1203 () => {
1204 if let Some(offset) = self.offset_value() {
1205 return AttributeValue::DebugLineRef(DebugLineOffset(offset));
1206 }
1207 };
1208 }
1209 macro_rules! loclistptr {
1213 () => {
1214 if let Some(offset) = self.offset_value() {
1216 return AttributeValue::LocationListsRef(LocationListsOffset(offset));
1217 }
1218 };
1219 }
1220 macro_rules! loclistsptr {
1222 () => {
1223 if let Some(offset) = self.offset_value() {
1224 return AttributeValue::DebugLocListsBase(DebugLocListsBase(offset));
1225 }
1226 };
1227 }
1228 macro_rules! macinfoptr {
1231 () => {
1232 if let Some(offset) = self.offset_value() {
1233 return AttributeValue::DebugMacinfoRef(DebugMacinfoOffset(offset));
1234 }
1235 };
1236 }
1237 macro_rules! macroptr {
1240 () => {
1241 if let Some(offset) = self.offset_value() {
1242 return AttributeValue::DebugMacroRef(DebugMacroOffset(offset));
1243 }
1244 };
1245 }
1246 macro_rules! reference {
1256 () => {};
1257 }
1258 macro_rules! rangelistptr {
1262 () => {
1263 if let Some(offset) = self.offset_value() {
1265 return AttributeValue::RangeListsRef(RawRangeListsOffset(offset));
1266 }
1267 };
1268 }
1269 macro_rules! rnglistsptr {
1271 () => {
1272 if let Some(offset) = self.offset_value() {
1273 return AttributeValue::DebugRngListsBase(DebugRngListsBase(offset));
1274 }
1275 };
1276 }
1277 macro_rules! string {
1287 () => {};
1288 }
1289 macro_rules! stroffsetsptr {
1291 () => {
1292 if let Some(offset) = self.offset_value() {
1293 return AttributeValue::DebugStrOffsetsBase(DebugStrOffsetsBase(offset));
1294 }
1295 };
1296 }
1297 macro_rules! dwoid {
1299 () => {
1300 if let Some(value) = self.udata_value() {
1301 return AttributeValue::DwoId(DwoId(value));
1302 }
1303 };
1304 }
1305
1306 match self.name {
1308 constants::DW_AT_sibling => {
1309 reference!();
1310 }
1311 constants::DW_AT_location => {
1312 exprloc!();
1313 loclistptr!();
1314 }
1315 constants::DW_AT_name => {
1316 string!();
1317 }
1318 constants::DW_AT_ordering => {
1319 constant!(u8_value, Ordering, DwOrd);
1320 }
1321 constants::DW_AT_byte_size
1322 | constants::DW_AT_bit_offset
1323 | constants::DW_AT_bit_size => {
1324 constant!(udata_value, Udata);
1325 exprloc!();
1326 reference!();
1327 }
1328 constants::DW_AT_stmt_list => {
1329 lineptr!();
1330 }
1331 constants::DW_AT_low_pc => {
1332 address!();
1333 }
1334 constants::DW_AT_high_pc => {
1335 address!();
1336 constant!(udata_value, Udata);
1337 }
1338 constants::DW_AT_language => {
1339 constant!(u16_value, Language, DwLang);
1340 }
1341 constants::DW_AT_discr => {
1342 reference!();
1343 }
1344 constants::DW_AT_discr_value => {
1345 }
1348 constants::DW_AT_visibility => {
1349 constant!(u8_value, Visibility, DwVis);
1350 }
1351 constants::DW_AT_import => {
1352 reference!();
1353 }
1354 constants::DW_AT_string_length => {
1355 exprloc!();
1356 loclistptr!();
1357 reference!();
1358 }
1359 constants::DW_AT_common_reference => {
1360 reference!();
1361 }
1362 constants::DW_AT_comp_dir => {
1363 string!();
1364 }
1365 constants::DW_AT_const_value => {
1366 block!();
1368 string!();
1369 }
1370 constants::DW_AT_containing_type => {
1371 reference!();
1372 }
1373 constants::DW_AT_default_value => {
1374 reference!();
1376 flag!();
1377 }
1378 constants::DW_AT_inline => {
1379 constant!(u8_value, Inline, DwInl);
1380 }
1381 constants::DW_AT_is_optional => {
1382 flag!();
1383 }
1384 constants::DW_AT_lower_bound => {
1385 exprloc!();
1387 reference!();
1388 }
1389 constants::DW_AT_producer => {
1390 string!();
1391 }
1392 constants::DW_AT_prototyped => {
1393 flag!();
1394 }
1395 constants::DW_AT_return_addr => {
1396 exprloc!();
1397 loclistptr!();
1398 }
1399 constants::DW_AT_start_scope => {
1400 rangelistptr!();
1402 }
1403 constants::DW_AT_bit_stride => {
1404 constant!(udata_value, Udata);
1405 exprloc!();
1406 reference!();
1407 }
1408 constants::DW_AT_upper_bound => {
1409 exprloc!();
1411 reference!();
1412 }
1413 constants::DW_AT_abstract_origin => {
1414 reference!();
1415 }
1416 constants::DW_AT_accessibility => {
1417 constant!(u8_value, Accessibility, DwAccess);
1418 }
1419 constants::DW_AT_address_class => {
1420 constant!(udata_value, AddressClass, DwAddr);
1421 }
1422 constants::DW_AT_artificial => {
1423 flag!();
1424 }
1425 constants::DW_AT_base_types => {
1426 reference!();
1427 }
1428 constants::DW_AT_calling_convention => {
1429 constant!(u8_value, CallingConvention, DwCc);
1430 }
1431 constants::DW_AT_count => {
1432 exprloc!();
1434 reference!();
1435 }
1436 constants::DW_AT_data_member_location => {
1437 constant!(udata_value, Udata);
1440 exprloc!();
1441 loclistptr!();
1442 }
1443 constants::DW_AT_decl_column => {
1444 constant!(udata_value, Udata);
1445 }
1446 constants::DW_AT_decl_file => {
1447 constant!(udata_value, FileIndex);
1448 }
1449 constants::DW_AT_decl_line => {
1450 constant!(udata_value, Udata);
1451 }
1452 constants::DW_AT_declaration => {
1453 flag!();
1454 }
1455 constants::DW_AT_discr_list => {
1456 block!();
1457 }
1458 constants::DW_AT_encoding => {
1459 constant!(u8_value, Encoding, DwAte);
1460 }
1461 constants::DW_AT_external => {
1462 flag!();
1463 }
1464 constants::DW_AT_frame_base => {
1465 exprloc!();
1466 loclistptr!();
1467 }
1468 constants::DW_AT_friend => {
1469 reference!();
1470 }
1471 constants::DW_AT_identifier_case => {
1472 constant!(u8_value, IdentifierCase, DwId);
1473 }
1474 constants::DW_AT_macro_info => {
1475 macinfoptr!();
1476 }
1477 constants::DW_AT_namelist_item => {
1478 reference!();
1479 }
1480 constants::DW_AT_priority => {
1481 reference!();
1482 }
1483 constants::DW_AT_segment => {
1484 exprloc!();
1485 loclistptr!();
1486 }
1487 constants::DW_AT_specification => {
1488 reference!();
1489 }
1490 constants::DW_AT_static_link => {
1491 exprloc!();
1492 loclistptr!();
1493 }
1494 constants::DW_AT_type => {
1495 reference!();
1496 }
1497 constants::DW_AT_use_location => {
1498 exprloc!();
1499 loclistptr!();
1500 }
1501 constants::DW_AT_variable_parameter => {
1502 flag!();
1503 }
1504 constants::DW_AT_virtuality => {
1505 constant!(u8_value, Virtuality, DwVirtuality);
1506 }
1507 constants::DW_AT_vtable_elem_location => {
1508 exprloc!();
1509 loclistptr!();
1510 }
1511 constants::DW_AT_allocated => {
1512 exprloc!();
1514 reference!();
1515 }
1516 constants::DW_AT_associated => {
1517 exprloc!();
1519 reference!();
1520 }
1521 constants::DW_AT_data_location => {
1522 exprloc!();
1523 }
1524 constants::DW_AT_byte_stride => {
1525 constant!(udata_value, Udata);
1526 exprloc!();
1527 reference!();
1528 }
1529 constants::DW_AT_entry_pc => {
1530 address!();
1532 }
1533 constants::DW_AT_use_UTF8 => {
1534 flag!();
1535 }
1536 constants::DW_AT_extension => {
1537 reference!();
1538 }
1539 constants::DW_AT_ranges => {
1540 rangelistptr!();
1541 }
1542 constants::DW_AT_trampoline => {
1543 address!();
1544 flag!();
1545 reference!();
1546 string!();
1547 }
1548 constants::DW_AT_call_column => {
1549 constant!(udata_value, Udata);
1550 }
1551 constants::DW_AT_call_file => {
1552 constant!(udata_value, FileIndex);
1553 }
1554 constants::DW_AT_call_line => {
1555 constant!(udata_value, Udata);
1556 }
1557 constants::DW_AT_description => {
1558 string!();
1559 }
1560 constants::DW_AT_binary_scale => {
1561 }
1563 constants::DW_AT_decimal_scale => {
1564 }
1566 constants::DW_AT_small => {
1567 reference!();
1568 }
1569 constants::DW_AT_decimal_sign => {
1570 constant!(u8_value, DecimalSign, DwDs);
1571 }
1572 constants::DW_AT_digit_count => {
1573 }
1575 constants::DW_AT_picture_string => {
1576 string!();
1577 }
1578 constants::DW_AT_mutable => {
1579 flag!();
1580 }
1581 constants::DW_AT_threads_scaled => {
1582 flag!();
1583 }
1584 constants::DW_AT_explicit => {
1585 flag!();
1586 }
1587 constants::DW_AT_object_pointer => {
1588 reference!();
1589 }
1590 constants::DW_AT_endianity => {
1591 constant!(u8_value, Endianity, DwEnd);
1592 }
1593 constants::DW_AT_elemental => {
1594 flag!();
1595 }
1596 constants::DW_AT_pure => {
1597 flag!();
1598 }
1599 constants::DW_AT_recursive => {
1600 flag!();
1601 }
1602 constants::DW_AT_signature => {
1603 reference!();
1604 }
1605 constants::DW_AT_main_subprogram => {
1606 flag!();
1607 }
1608 constants::DW_AT_data_bit_offset => {
1609 }
1611 constants::DW_AT_const_expr => {
1612 flag!();
1613 }
1614 constants::DW_AT_enum_class => {
1615 flag!();
1616 }
1617 constants::DW_AT_linkage_name => {
1618 string!();
1619 }
1620 constants::DW_AT_string_length_bit_size => {
1621 }
1623 constants::DW_AT_string_length_byte_size => {
1624 }
1626 constants::DW_AT_rank => {
1627 exprloc!();
1629 }
1630 constants::DW_AT_str_offsets_base => {
1631 stroffsetsptr!();
1632 }
1633 constants::DW_AT_addr_base | constants::DW_AT_GNU_addr_base => {
1634 addrptr!();
1635 }
1636 constants::DW_AT_rnglists_base | constants::DW_AT_GNU_ranges_base => {
1637 rnglistsptr!();
1638 }
1639 constants::DW_AT_dwo_name => {
1640 string!();
1641 }
1642 constants::DW_AT_reference => {
1643 flag!();
1644 }
1645 constants::DW_AT_rvalue_reference => {
1646 flag!();
1647 }
1648 constants::DW_AT_macros => {
1649 macroptr!();
1650 }
1651 constants::DW_AT_call_all_calls => {
1652 flag!();
1653 }
1654 constants::DW_AT_call_all_source_calls => {
1655 flag!();
1656 }
1657 constants::DW_AT_call_all_tail_calls => {
1658 flag!();
1659 }
1660 constants::DW_AT_call_return_pc => {
1661 address!();
1662 }
1663 constants::DW_AT_call_value => {
1664 exprloc!();
1665 }
1666 constants::DW_AT_call_origin => {
1667 exprloc!();
1668 }
1669 constants::DW_AT_call_parameter => {
1670 reference!();
1671 }
1672 constants::DW_AT_call_pc => {
1673 address!();
1674 }
1675 constants::DW_AT_call_tail_call => {
1676 flag!();
1677 }
1678 constants::DW_AT_call_target => {
1679 exprloc!();
1680 }
1681 constants::DW_AT_call_target_clobbered => {
1682 exprloc!();
1683 }
1684 constants::DW_AT_call_data_location => {
1685 exprloc!();
1686 }
1687 constants::DW_AT_call_data_value => {
1688 exprloc!();
1689 }
1690 constants::DW_AT_noreturn => {
1691 flag!();
1692 }
1693 constants::DW_AT_alignment => {
1694 }
1696 constants::DW_AT_export_symbols => {
1697 flag!();
1698 }
1699 constants::DW_AT_deleted => {
1700 flag!();
1701 }
1702 constants::DW_AT_defaulted => {
1703 }
1705 constants::DW_AT_loclists_base => {
1706 loclistsptr!();
1707 }
1708 constants::DW_AT_GNU_dwo_id => {
1709 dwoid!();
1710 }
1711 _ => {}
1712 }
1713 self.value.clone()
1714 }
1715
1716 #[inline]
1718 pub fn u8_value(&self) -> Option<u8> {
1719 self.value.u8_value()
1720 }
1721
1722 #[inline]
1724 pub fn u16_value(&self) -> Option<u16> {
1725 self.value.u16_value()
1726 }
1727
1728 #[inline]
1730 pub fn udata_value(&self) -> Option<u64> {
1731 self.value.udata_value()
1732 }
1733
1734 #[inline]
1736 pub fn sdata_value(&self) -> Option<i64> {
1737 self.value.sdata_value()
1738 }
1739
1740 #[inline]
1742 pub fn offset_value(&self) -> Option<R::Offset> {
1743 self.value.offset_value()
1744 }
1745
1746 #[inline]
1752 pub fn exprloc_value(&self) -> Option<Expression<R>> {
1753 self.value.exprloc_value()
1754 }
1755
1756 #[inline]
1766 pub fn string_value(&self, debug_str: &DebugStr<R>) -> Option<R> {
1767 self.value.string_value(debug_str)
1768 }
1769
1770 #[inline]
1781 pub fn string_value_sup(
1782 &self,
1783 debug_str: &DebugStr<R>,
1784 debug_str_sup: Option<&DebugStr<R>>,
1785 ) -> Option<R> {
1786 self.value.string_value_sup(debug_str, debug_str_sup)
1787 }
1788}
1789
1790impl<R, Offset> AttributeValue<R, Offset>
1791where
1792 R: Reader<Offset = Offset>,
1793 Offset: ReaderOffset,
1794{
1795 pub fn u8_value(&self) -> Option<u8> {
1797 self.udata_value().and_then(|val| u8::try_from(val).ok())
1798 }
1799
1800 pub fn u16_value(&self) -> Option<u16> {
1802 self.udata_value().and_then(|val| u16::try_from(val).ok())
1803 }
1804
1805 pub fn udata_value(&self) -> Option<u64> {
1807 Some(match *self {
1808 AttributeValue::Data1(data) => u64::from(data),
1809 AttributeValue::Data2(data) => u64::from(data),
1810 AttributeValue::Data4(data) => u64::from(data),
1811 AttributeValue::Data8(data) => data,
1812 AttributeValue::Udata(data) => data,
1813 AttributeValue::Sdata(data) => {
1814 if data < 0 {
1815 return None;
1817 }
1818 data as u64
1819 }
1820 _ => return None,
1821 })
1822 }
1823
1824 pub fn sdata_value(&self) -> Option<i64> {
1826 Some(match *self {
1827 AttributeValue::Data1(data) => i64::from(data as i8),
1828 AttributeValue::Data2(data) => i64::from(data as i16),
1829 AttributeValue::Data4(data) => i64::from(data as i32),
1830 AttributeValue::Data8(data) => data as i64,
1831 AttributeValue::Sdata(data) => data,
1832 AttributeValue::Udata(data) => {
1833 if data > i64::MAX as u64 {
1834 return None;
1836 }
1837 data as i64
1838 }
1839 _ => return None,
1840 })
1841 }
1842
1843 pub fn offset_value(&self) -> Option<R::Offset> {
1845 if let AttributeValue::SecOffset(offset) = *self {
1848 Some(offset)
1849 } else {
1850 None
1851 }
1852 }
1853
1854 pub fn exprloc_value(&self) -> Option<Expression<R>> {
1860 Some(match *self {
1861 AttributeValue::Block(ref data) => Expression(data.clone()),
1862 AttributeValue::Exprloc(ref data) => data.clone(),
1863 _ => return None,
1864 })
1865 }
1866
1867 pub fn string_value(&self, debug_str: &DebugStr<R>) -> Option<R> {
1877 match *self {
1878 AttributeValue::String(ref string) => Some(string.clone()),
1879 AttributeValue::DebugStrRef(offset) => debug_str.get_str(offset).ok(),
1880 _ => None,
1881 }
1882 }
1883
1884 pub fn string_value_sup(
1895 &self,
1896 debug_str: &DebugStr<R>,
1897 debug_str_sup: Option<&DebugStr<R>>,
1898 ) -> Option<R> {
1899 match *self {
1900 AttributeValue::String(ref string) => Some(string.clone()),
1901 AttributeValue::DebugStrRef(offset) => debug_str.get_str(offset).ok(),
1902 AttributeValue::DebugStrRefSup(offset) => {
1903 debug_str_sup.and_then(|s| s.get_str(offset).ok())
1904 }
1905 _ => None,
1906 }
1907 }
1908}
1909
1910fn allow_section_offset(name: constants::DwAt, version: u16) -> bool {
1913 match name {
1914 constants::DW_AT_location
1915 | constants::DW_AT_stmt_list
1916 | constants::DW_AT_string_length
1917 | constants::DW_AT_return_addr
1918 | constants::DW_AT_start_scope
1919 | constants::DW_AT_frame_base
1920 | constants::DW_AT_macro_info
1921 | constants::DW_AT_macros
1922 | constants::DW_AT_segment
1923 | constants::DW_AT_static_link
1924 | constants::DW_AT_use_location
1925 | constants::DW_AT_vtable_elem_location
1926 | constants::DW_AT_ranges => true,
1927 constants::DW_AT_data_member_location => version == 2 || version == 3,
1928 _ => false,
1929 }
1930}
1931
1932#[inline(always)]
1935pub(crate) fn parse_attribute<R: Reader>(
1936 input: &mut R,
1937 encoding: Encoding,
1938 spec: AttributeSpecification,
1939) -> Result<Attribute<R>> {
1940 let mut form = spec.form();
1941 loop {
1942 let value = match form {
1943 constants::DW_FORM_indirect => {
1944 let dynamic_form = input.read_uleb128_u16()?;
1945 form = constants::DwForm(dynamic_form);
1946 continue;
1947 }
1948 constants::DW_FORM_addr => {
1949 let addr = input.read_address(encoding.address_size)?;
1950 AttributeValue::Addr(addr)
1951 }
1952 constants::DW_FORM_block1 => {
1953 let len = input.read_u8().map(R::Offset::from_u8)?;
1954 let block = input.split(len)?;
1955 AttributeValue::Block(block)
1956 }
1957 constants::DW_FORM_block2 => {
1958 let len = input.read_u16().map(R::Offset::from_u16)?;
1959 let block = input.split(len)?;
1960 AttributeValue::Block(block)
1961 }
1962 constants::DW_FORM_block4 => {
1963 let len = input.read_u32().map(R::Offset::from_u32)?;
1964 let block = input.split(len)?;
1965 AttributeValue::Block(block)
1966 }
1967 constants::DW_FORM_block => {
1968 let len = input.read_uleb128().and_then(R::Offset::from_u64)?;
1969 let block = input.split(len)?;
1970 AttributeValue::Block(block)
1971 }
1972 constants::DW_FORM_data1 => {
1973 let data = input.read_u8()?;
1974 AttributeValue::Data1(data)
1975 }
1976 constants::DW_FORM_data2 => {
1977 let data = input.read_u16()?;
1978 AttributeValue::Data2(data)
1979 }
1980 constants::DW_FORM_data4 => {
1981 if encoding.format == Format::Dwarf32
1984 && allow_section_offset(spec.name(), encoding.version)
1985 {
1986 let offset = input.read_offset(Format::Dwarf32)?;
1987 AttributeValue::SecOffset(offset)
1988 } else {
1989 let data = input.read_u32()?;
1990 AttributeValue::Data4(data)
1991 }
1992 }
1993 constants::DW_FORM_data8 => {
1994 if encoding.format == Format::Dwarf64
1997 && allow_section_offset(spec.name(), encoding.version)
1998 {
1999 let offset = input.read_offset(Format::Dwarf64)?;
2000 AttributeValue::SecOffset(offset)
2001 } else {
2002 let data = input.read_u64()?;
2003 AttributeValue::Data8(data)
2004 }
2005 }
2006 constants::DW_FORM_data16 => {
2007 let data = input.read_u128()?;
2008 AttributeValue::Data16(data)
2009 }
2010 constants::DW_FORM_udata => {
2011 let data = input.read_uleb128()?;
2012 AttributeValue::Udata(data)
2013 }
2014 constants::DW_FORM_sdata => {
2015 let data = input.read_sleb128()?;
2016 AttributeValue::Sdata(data)
2017 }
2018 constants::DW_FORM_exprloc => {
2019 let len = input.read_uleb128().and_then(R::Offset::from_u64)?;
2020 let block = input.split(len)?;
2021 AttributeValue::Exprloc(Expression(block))
2022 }
2023 constants::DW_FORM_flag => {
2024 let present = input.read_u8()?;
2025 AttributeValue::Flag(present != 0)
2026 }
2027 constants::DW_FORM_flag_present => {
2028 AttributeValue::Flag(true)
2031 }
2032 constants::DW_FORM_sec_offset => {
2033 let offset = input.read_offset(encoding.format)?;
2034 AttributeValue::SecOffset(offset)
2035 }
2036 constants::DW_FORM_ref1 => {
2037 let reference = input.read_u8().map(R::Offset::from_u8)?;
2038 AttributeValue::UnitRef(UnitOffset(reference))
2039 }
2040 constants::DW_FORM_ref2 => {
2041 let reference = input.read_u16().map(R::Offset::from_u16)?;
2042 AttributeValue::UnitRef(UnitOffset(reference))
2043 }
2044 constants::DW_FORM_ref4 => {
2045 let reference = input.read_u32().map(R::Offset::from_u32)?;
2046 AttributeValue::UnitRef(UnitOffset(reference))
2047 }
2048 constants::DW_FORM_ref8 => {
2049 let reference = input.read_u64().and_then(R::Offset::from_u64)?;
2050 AttributeValue::UnitRef(UnitOffset(reference))
2051 }
2052 constants::DW_FORM_ref_udata => {
2053 let reference = input.read_uleb128().and_then(R::Offset::from_u64)?;
2054 AttributeValue::UnitRef(UnitOffset(reference))
2055 }
2056 constants::DW_FORM_ref_addr => {
2057 let offset = if encoding.version == 2 {
2061 input.read_sized_offset(encoding.address_size)?
2062 } else {
2063 input.read_offset(encoding.format)?
2064 };
2065 AttributeValue::DebugInfoRef(DebugInfoOffset(offset))
2066 }
2067 constants::DW_FORM_ref_sig8 => {
2068 let signature = input.read_u64()?;
2069 AttributeValue::DebugTypesRef(DebugTypeSignature(signature))
2070 }
2071 constants::DW_FORM_ref_sup4 => {
2072 let offset = input.read_u32().map(R::Offset::from_u32)?;
2073 AttributeValue::DebugInfoRefSup(DebugInfoOffset(offset))
2074 }
2075 constants::DW_FORM_ref_sup8 => {
2076 let offset = input.read_u64().and_then(R::Offset::from_u64)?;
2077 AttributeValue::DebugInfoRefSup(DebugInfoOffset(offset))
2078 }
2079 constants::DW_FORM_GNU_ref_alt => {
2080 let offset = input.read_offset(encoding.format)?;
2081 AttributeValue::DebugInfoRefSup(DebugInfoOffset(offset))
2082 }
2083 constants::DW_FORM_string => {
2084 let string = input.read_null_terminated_slice()?;
2085 AttributeValue::String(string)
2086 }
2087 constants::DW_FORM_strp => {
2088 let offset = input.read_offset(encoding.format)?;
2089 AttributeValue::DebugStrRef(DebugStrOffset(offset))
2090 }
2091 constants::DW_FORM_strp_sup | constants::DW_FORM_GNU_strp_alt => {
2092 let offset = input.read_offset(encoding.format)?;
2093 AttributeValue::DebugStrRefSup(DebugStrOffset(offset))
2094 }
2095 constants::DW_FORM_line_strp => {
2096 let offset = input.read_offset(encoding.format)?;
2097 AttributeValue::DebugLineStrRef(DebugLineStrOffset(offset))
2098 }
2099 constants::DW_FORM_implicit_const => {
2100 let data = spec
2101 .implicit_const_value()
2102 .ok_or(Error::InvalidImplicitConst)?;
2103 AttributeValue::Sdata(data)
2104 }
2105 constants::DW_FORM_strx | constants::DW_FORM_GNU_str_index => {
2106 let index = input.read_uleb128().and_then(R::Offset::from_u64)?;
2107 AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
2108 }
2109 constants::DW_FORM_strx1 => {
2110 let index = input.read_u8().map(R::Offset::from_u8)?;
2111 AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
2112 }
2113 constants::DW_FORM_strx2 => {
2114 let index = input.read_u16().map(R::Offset::from_u16)?;
2115 AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
2116 }
2117 constants::DW_FORM_strx3 => {
2118 let index = input.read_uint(3).and_then(R::Offset::from_u64)?;
2119 AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
2120 }
2121 constants::DW_FORM_strx4 => {
2122 let index = input.read_u32().map(R::Offset::from_u32)?;
2123 AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
2124 }
2125 constants::DW_FORM_addrx | constants::DW_FORM_GNU_addr_index => {
2126 let index = input.read_uleb128().and_then(R::Offset::from_u64)?;
2127 AttributeValue::DebugAddrIndex(DebugAddrIndex(index))
2128 }
2129 constants::DW_FORM_addrx1 => {
2130 let index = input.read_u8().map(R::Offset::from_u8)?;
2131 AttributeValue::DebugAddrIndex(DebugAddrIndex(index))
2132 }
2133 constants::DW_FORM_addrx2 => {
2134 let index = input.read_u16().map(R::Offset::from_u16)?;
2135 AttributeValue::DebugAddrIndex(DebugAddrIndex(index))
2136 }
2137 constants::DW_FORM_addrx3 => {
2138 let index = input.read_uint(3).and_then(R::Offset::from_u64)?;
2139 AttributeValue::DebugAddrIndex(DebugAddrIndex(index))
2140 }
2141 constants::DW_FORM_addrx4 => {
2142 let index = input.read_u32().map(R::Offset::from_u32)?;
2143 AttributeValue::DebugAddrIndex(DebugAddrIndex(index))
2144 }
2145 constants::DW_FORM_loclistx => {
2146 let index = input.read_uleb128().and_then(R::Offset::from_u64)?;
2147 AttributeValue::DebugLocListsIndex(DebugLocListsIndex(index))
2148 }
2149 constants::DW_FORM_rnglistx => {
2150 let index = input.read_uleb128().and_then(R::Offset::from_u64)?;
2151 AttributeValue::DebugRngListsIndex(DebugRngListsIndex(index))
2152 }
2153 _ => {
2154 return Err(Error::UnknownForm(form));
2155 }
2156 };
2157 let attr = Attribute {
2158 name: spec.name(),
2159 form: spec.form(),
2160 value,
2161 };
2162 return Ok(attr);
2163 }
2164}
2165
2166pub(crate) fn skip_attributes<R: Reader>(
2167 input: &mut R,
2168 encoding: Encoding,
2169 specs: &[AttributeSpecification],
2170) -> Result<()> {
2171 let mut skip_bytes = R::Offset::from_u8(0);
2172 for spec in specs {
2173 let mut form = spec.form();
2174 loop {
2175 if let Some(len) = get_attribute_size(form, encoding) {
2176 skip_bytes += R::Offset::from_u8(len);
2178 break;
2179 }
2180
2181 if skip_bytes != R::Offset::from_u8(0) {
2183 input.skip(skip_bytes)?;
2185 skip_bytes = R::Offset::from_u8(0);
2186 }
2187
2188 match form {
2189 constants::DW_FORM_indirect => {
2190 let dynamic_form = input.read_uleb128_u16()?;
2191 form = constants::DwForm(dynamic_form);
2192 continue;
2193 }
2194 constants::DW_FORM_block1 => {
2195 skip_bytes = input.read_u8().map(R::Offset::from_u8)?;
2196 }
2197 constants::DW_FORM_block2 => {
2198 skip_bytes = input.read_u16().map(R::Offset::from_u16)?;
2199 }
2200 constants::DW_FORM_block4 => {
2201 skip_bytes = input.read_u32().map(R::Offset::from_u32)?;
2202 }
2203 constants::DW_FORM_block | constants::DW_FORM_exprloc => {
2204 skip_bytes = input.read_uleb128().and_then(R::Offset::from_u64)?;
2205 }
2206 constants::DW_FORM_string => {
2207 let _ = input.read_null_terminated_slice()?;
2208 }
2209 constants::DW_FORM_udata
2210 | constants::DW_FORM_sdata
2211 | constants::DW_FORM_ref_udata
2212 | constants::DW_FORM_strx
2213 | constants::DW_FORM_GNU_str_index
2214 | constants::DW_FORM_addrx
2215 | constants::DW_FORM_GNU_addr_index
2216 | constants::DW_FORM_loclistx
2217 | constants::DW_FORM_rnglistx => {
2218 input.skip_leb128()?;
2219 }
2220 _ => {
2221 return Err(Error::UnknownForm(form));
2222 }
2223 };
2224 break;
2225 }
2226 }
2227 if skip_bytes != R::Offset::from_u8(0) {
2228 input.skip(skip_bytes)?;
2230 }
2231 Ok(())
2232}
2233
2234#[derive(Clone, Debug)]
2291pub struct EntriesRaw<'abbrev, R>
2292where
2293 R: Reader,
2294{
2295 input: R,
2296 encoding: Encoding,
2297 abbreviations: &'abbrev Abbreviations,
2298 end_offset: UnitOffset<R::Offset>,
2299 depth: isize,
2300}
2301
2302impl<'abbrev, R: Reader> EntriesRaw<'abbrev, R> {
2303 pub fn new(
2312 input: R,
2313 encoding: Encoding,
2314 abbreviations: &'abbrev Abbreviations,
2315 offset: UnitOffset<R::Offset>,
2316 ) -> Self {
2317 let end_offset = UnitOffset(offset.0 + input.len());
2318 EntriesRaw {
2319 input,
2320 encoding,
2321 abbreviations,
2322 end_offset,
2323 depth: 0,
2324 }
2325 }
2326
2327 #[inline]
2328 fn empty(&mut self) {
2329 self.input.empty()
2330 }
2331
2332 #[inline]
2334 pub fn is_empty(&self) -> bool {
2335 self.input.is_empty()
2336 }
2337
2338 fn seek_forward(&mut self, offset: UnitOffset<R::Offset>, depth: isize) -> bool {
2339 if let Some(skip_len) = offset.0.checked_sub(self.next_offset().0) {
2340 let mut input = self.input.clone();
2342 if input.skip(skip_len).is_ok() {
2343 self.input = input;
2344 self.depth = depth;
2345 return true;
2346 }
2347 }
2348 false
2349 }
2350
2351 pub fn next_offset(&self) -> UnitOffset<R::Offset> {
2356 UnitOffset(self.end_offset.0 - self.input.len())
2357 }
2358
2359 #[inline]
2364 pub fn next_depth(&self) -> isize {
2365 self.depth
2366 }
2367
2368 pub fn read_entry(&mut self, entry: &mut DebuggingInformationEntry<R>) -> Result<bool> {
2379 entry.depth = self.next_depth();
2380 entry.offset = self.next_offset();
2381 let Some(abbrev) = self.read_abbreviation()? else {
2382 entry.set_null();
2383 return Ok(false);
2384 };
2385 entry.tag = abbrev.tag();
2386 entry.has_children = abbrev.has_children();
2387 self.read_attributes(abbrev.attributes(), &mut entry.attrs)?;
2388 Ok(true)
2389 }
2390
2391 #[inline]
2397 pub fn read_abbreviation(&mut self) -> Result<Option<&'abbrev Abbreviation>> {
2398 let code = self.input.read_uleb128()?;
2399 if code == 0 {
2400 self.depth -= 1;
2401 return Ok(None);
2402 };
2403 let abbrev = self
2404 .abbreviations
2405 .get(code)
2406 .ok_or(Error::InvalidAbbreviationCode(code))?;
2407 if abbrev.has_children() {
2408 self.depth += 1;
2409 }
2410 Ok(Some(abbrev))
2411 }
2412
2413 #[inline(never)]
2418 pub fn read_attribute(&mut self, spec: AttributeSpecification) -> Result<Attribute<R>> {
2419 parse_attribute(&mut self.input, self.encoding, spec)
2420 }
2421
2422 #[inline(always)]
2427 pub fn read_attribute_inline(&mut self, spec: AttributeSpecification) -> Result<Attribute<R>> {
2428 parse_attribute(&mut self.input, self.encoding, spec)
2429 }
2430
2431 pub fn read_attributes(
2437 &mut self,
2438 specs: &[AttributeSpecification],
2439 attrs: &mut Vec<Attribute<R>>,
2440 ) -> Result<()> {
2441 attrs.clear();
2442 attrs.reserve(specs.len());
2443 for spec in specs {
2444 attrs.push(parse_attribute(&mut self.input, self.encoding, *spec)?);
2445 }
2446 Ok(())
2447 }
2448
2449 #[inline]
2451 pub fn skip_attributes(&mut self, specs: &[AttributeSpecification]) -> Result<()> {
2452 skip_attributes(&mut self.input, self.encoding, specs)
2453 }
2454}
2455
2456#[derive(Clone, Debug)]
2467pub struct EntriesCursor<'abbrev, R>
2468where
2469 R: Reader,
2470{
2471 input: EntriesRaw<'abbrev, R>,
2472 cached_current: DebuggingInformationEntry<R>,
2473}
2474
2475impl<'abbrev, R: Reader> EntriesCursor<'abbrev, R> {
2476 fn new(
2477 input: R,
2478 encoding: Encoding,
2479 abbreviations: &'abbrev Abbreviations,
2480 offset: UnitOffset<R::Offset>,
2481 ) -> Self {
2482 EntriesCursor {
2483 input: EntriesRaw::new(input, encoding, abbreviations, offset),
2484 cached_current: DebuggingInformationEntry::null(),
2485 }
2486 }
2487
2488 #[inline]
2493 pub fn current(&self) -> Option<&DebuggingInformationEntry<R>> {
2494 if self.cached_current.is_null() {
2495 None
2496 } else {
2497 Some(&self.cached_current)
2498 }
2499 }
2500
2501 pub fn offset(&self) -> UnitOffset<R::Offset> {
2505 self.cached_current.offset
2506 }
2507
2508 pub fn depth(&self) -> isize {
2512 self.cached_current.depth
2513 }
2514
2515 pub fn next_offset(&self) -> UnitOffset<R::Offset> {
2517 self.input.next_offset()
2518 }
2519
2520 pub fn next_depth(&self) -> isize {
2522 self.input.next_depth()
2523 }
2524
2525 pub fn next_entry(&mut self) -> Result<bool> {
2530 if self.input.is_empty() {
2531 self.cached_current.set_null();
2532 return Ok(false);
2533 }
2534
2535 match self.input.read_entry(&mut self.cached_current) {
2536 Ok(_) => Ok(true),
2537 Err(e) => {
2538 self.input.empty();
2539 self.cached_current.set_null();
2540 Err(e)
2541 }
2542 }
2543 }
2544
2545 pub fn next_dfs(&mut self) -> Result<Option<&DebuggingInformationEntry<R>>> {
2646 loop {
2647 if self.next_entry()? {
2649 if !self.cached_current.is_null() {
2650 return Ok(Some(&self.cached_current));
2651 }
2652 } else {
2653 return Ok(None);
2654 }
2655 }
2656 }
2657
2658 pub fn next_sibling(&mut self) -> Result<Option<&DebuggingInformationEntry<R>>> {
2766 if self.current().is_none() {
2767 return Ok(None);
2769 }
2770
2771 let current_depth = self.cached_current.depth;
2773 loop {
2774 if let Some(current) = self.current()
2775 && current.has_children()
2776 && let Some(sibling_offset) = current.sibling()
2777 {
2778 self.input.seek_forward(sibling_offset, current.depth);
2782 }
2783
2784 if !self.next_entry()? {
2785 return Ok(None);
2787 }
2788
2789 if self.cached_current.depth == current_depth {
2790 return Ok(self.current());
2792 }
2793 }
2794 }
2795}
2796
2797#[derive(Clone, Debug)]
2835pub struct EntriesTree<'abbrev, R>
2836where
2837 R: Reader,
2838{
2839 root: R,
2840 input: EntriesRaw<'abbrev, R>,
2841 entry: DebuggingInformationEntry<R>,
2842}
2843
2844impl<'abbrev, R: Reader> EntriesTree<'abbrev, R> {
2845 fn new(
2846 root: R,
2847 encoding: Encoding,
2848 abbreviations: &'abbrev Abbreviations,
2849 offset: UnitOffset<R::Offset>,
2850 ) -> Self {
2851 let input = root.clone();
2852 EntriesTree {
2853 root,
2854 input: EntriesRaw::new(input, encoding, abbreviations, offset),
2855 entry: DebuggingInformationEntry::null(),
2856 }
2857 }
2858
2859 pub fn root<'me>(&'me mut self) -> Result<EntriesTreeNode<'abbrev, 'me, R>> {
2861 self.input.input = self.root.clone();
2862 self.input.depth = 0;
2863 if !self.input.read_entry(&mut self.entry)? {
2864 return Err(Error::NoEntryAtGivenOffset(self.entry.offset.0.into_u64()));
2865 }
2866 Ok(EntriesTreeNode::new(self, 1))
2867 }
2868
2869 fn next(&mut self, depth: isize) -> Result<bool> {
2875 if self.entry.depth < depth {
2876 debug_assert_eq!(self.entry.depth + 1, depth);
2877
2878 if !self.entry.has_children() {
2879 return Ok(false);
2880 }
2881
2882 if self.input.is_empty() {
2883 self.entry.set_null();
2884 return Ok(false);
2885 }
2886
2887 let entry = self.input.read_entry(&mut self.entry);
2888 if entry.is_err() {
2889 self.input.empty();
2890 self.entry.set_null();
2891 }
2892 return entry;
2893 }
2894
2895 loop {
2896 if self.entry.has_children()
2897 && let Some(sibling_offset) = self.entry.sibling()
2898 {
2899 self.input.seek_forward(sibling_offset, self.entry.depth);
2903 }
2904
2905 if self.input.is_empty() {
2906 self.entry.set_null();
2907 return Ok(false);
2908 }
2909
2910 match self.input.read_entry(&mut self.entry) {
2911 Ok(entry) => {
2912 if self.entry.depth == depth {
2913 return Ok(entry);
2914 }
2915 }
2916 Err(e) => {
2917 self.input.empty();
2918 self.entry.set_null();
2919 return Err(e);
2920 }
2921 }
2922 }
2923 }
2924}
2925
2926#[derive(Debug)]
2931pub struct EntriesTreeNode<'abbrev, 'tree, R: Reader> {
2932 tree: &'tree mut EntriesTree<'abbrev, R>,
2933 depth: isize,
2934}
2935
2936impl<'abbrev, 'tree, R: Reader> EntriesTreeNode<'abbrev, 'tree, R> {
2937 fn new(
2938 tree: &'tree mut EntriesTree<'abbrev, R>,
2939 depth: isize,
2940 ) -> EntriesTreeNode<'abbrev, 'tree, R> {
2941 debug_assert!(!tree.entry.is_null());
2942 EntriesTreeNode { tree, depth }
2943 }
2944
2945 pub fn entry(&self) -> &DebuggingInformationEntry<R> {
2947 &self.tree.entry
2949 }
2950
2951 pub fn children(self) -> EntriesTreeIter<'abbrev, 'tree, R> {
2956 EntriesTreeIter::new(self.tree, self.depth)
2957 }
2958}
2959
2960#[derive(Debug)]
2966pub struct EntriesTreeIter<'abbrev, 'tree, R: Reader> {
2967 tree: &'tree mut EntriesTree<'abbrev, R>,
2968 depth: isize,
2969 empty: bool,
2970}
2971
2972impl<'abbrev, 'tree, R: Reader> EntriesTreeIter<'abbrev, 'tree, R> {
2973 fn new(
2974 tree: &'tree mut EntriesTree<'abbrev, R>,
2975 depth: isize,
2976 ) -> EntriesTreeIter<'abbrev, 'tree, R> {
2977 EntriesTreeIter {
2978 tree,
2979 depth,
2980 empty: false,
2981 }
2982 }
2983
2984 pub fn next<'me>(&'me mut self) -> Result<Option<EntriesTreeNode<'abbrev, 'me, R>>> {
2988 if self.empty {
2989 Ok(None)
2990 } else if self.tree.next(self.depth)? {
2991 Ok(Some(EntriesTreeNode::new(self.tree, self.depth + 1)))
2992 } else {
2993 self.empty = true;
2994 Ok(None)
2995 }
2996 }
2997}
2998
2999#[derive(Debug, Default, Clone, Copy)]
3002pub struct DebugTypes<R> {
3003 debug_types_section: R,
3004}
3005
3006impl<'input, Endian> DebugTypes<EndianSlice<'input, Endian>>
3007where
3008 Endian: Endianity,
3009{
3010 pub fn new(debug_types_section: &'input [u8], endian: Endian) -> Self {
3025 Self::from(EndianSlice::new(debug_types_section, endian))
3026 }
3027}
3028
3029impl<T> DebugTypes<T> {
3030 pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugTypes<R>
3036 where
3037 F: FnMut(&'a T) -> R,
3038 {
3039 borrow(&self.debug_types_section).into()
3040 }
3041}
3042
3043impl<R> Section<R> for DebugTypes<R> {
3044 fn id() -> SectionId {
3045 SectionId::DebugTypes
3046 }
3047
3048 fn reader(&self) -> &R {
3049 &self.debug_types_section
3050 }
3051}
3052
3053impl<R> From<R> for DebugTypes<R> {
3054 fn from(debug_types_section: R) -> Self {
3055 DebugTypes {
3056 debug_types_section,
3057 }
3058 }
3059}
3060
3061impl<R: Reader> DebugTypes<R> {
3062 pub fn units(&self) -> DebugTypesUnitHeadersIter<R> {
3077 DebugTypesUnitHeadersIter {
3078 input: self.debug_types_section.clone(),
3079 offset: UnitSectionOffset(R::Offset::from_u8(0)),
3080 }
3081 }
3082}
3083
3084#[derive(Clone, Debug)]
3090pub struct DebugTypesUnitHeadersIter<R: Reader> {
3091 input: R,
3092 offset: UnitSectionOffset<R::Offset>,
3093}
3094
3095impl<R: Reader> DebugTypesUnitHeadersIter<R> {
3096 pub fn next(&mut self) -> Result<Option<UnitHeader<R>>> {
3098 if self.input.is_empty() {
3099 Ok(None)
3100 } else {
3101 let len = self.input.len();
3102 match parse_unit_header(&mut self.input, SectionId::DebugTypes, self.offset) {
3103 Ok(header) => {
3104 self.offset.0 += len - self.input.len();
3105 Ok(Some(header))
3106 }
3107 Err(e) => {
3108 self.input.empty();
3109 Err(e)
3110 }
3111 }
3112 }
3113 }
3114}
3115
3116#[cfg(feature = "fallible-iterator")]
3117impl<R: Reader> fallible_iterator::FallibleIterator for DebugTypesUnitHeadersIter<R> {
3118 type Item = UnitHeader<R>;
3119 type Error = Error;
3120
3121 fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
3122 DebugTypesUnitHeadersIter::next(self)
3123 }
3124}
3125
3126impl<R: Reader> Iterator for DebugTypesUnitHeadersIter<R> {
3127 type Item = Result<UnitHeader<R>>;
3128
3129 fn next(&mut self) -> Option<Self::Item> {
3130 DebugTypesUnitHeadersIter::next(self).transpose()
3131 }
3132}
3133
3134#[cfg(test)]
3135#[cfg(feature = "write")]
3137mod tests {
3138 use super::*;
3139 use crate::constants;
3140 use crate::constants::*;
3141 use crate::endianity::{Endianity, LittleEndian};
3142 use crate::leb128::write::Leb128;
3143 use crate::read::abbrev::tests::AbbrevSectionMethods;
3144 use crate::read::{
3145 Abbreviation, AttributeSpecification, DebugAbbrev, EndianSlice, Error, Result,
3146 };
3147 use crate::test_util::GimliSectionMethods;
3148 use alloc::vec::Vec;
3149 use test_assembler::{Endian, Label, LabelMaker, Section};
3150
3151 trait UnitSectionMethods {
3154 fn unit<E>(self, unit: &mut UnitHeader<EndianSlice<'_, E>>) -> Self
3155 where
3156 E: Endianity;
3157 fn die<F>(self, code: u64, attr: F) -> Self
3158 where
3159 F: Fn(Section) -> Section;
3160 fn die_null(self) -> Self;
3161 fn attr_string(self, s: &str) -> Self;
3162 fn attr_ref1(self, o: u8) -> Self;
3163 fn offset(self, offset: usize, format: Format) -> Self;
3164 }
3165
3166 impl UnitSectionMethods for Section {
3167 fn unit<E>(self, unit: &mut UnitHeader<EndianSlice<'_, E>>) -> Self
3168 where
3169 E: Endianity,
3170 {
3171 unit.unit_offset.0 = self.size() as usize;
3172 let length = Label::new();
3173 let start = Label::new();
3174 let end = Label::new();
3175
3176 let section = match unit.format() {
3177 Format::Dwarf32 => self.L32(&length),
3178 Format::Dwarf64 => self.L32(0xffff_ffff).L64(&length),
3179 };
3180
3181 let section = match unit.version() {
3182 2..=4 => section
3183 .mark(&start)
3184 .L16(unit.version())
3185 .offset(unit.debug_abbrev_offset.0, unit.format())
3186 .D8(unit.address_size()),
3187 5 => section
3188 .mark(&start)
3189 .L16(unit.version())
3190 .D8(unit.type_().dw_ut().0)
3191 .D8(unit.address_size())
3192 .offset(unit.debug_abbrev_offset.0, unit.format()),
3193 _ => unreachable!(),
3194 };
3195
3196 let section = match unit.type_() {
3197 UnitType::Compilation | UnitType::Partial => section,
3198 UnitType::Type {
3199 type_signature,
3200 type_offset,
3201 }
3202 | UnitType::SplitType {
3203 type_signature,
3204 type_offset,
3205 } => section
3206 .L64(type_signature.0)
3207 .offset(type_offset.0, unit.format()),
3208 UnitType::Skeleton(dwo_id) | UnitType::SplitCompilation(dwo_id) => {
3209 section.L64(dwo_id.0)
3210 }
3211 };
3212
3213 let section = section.append_bytes(unit.entries_buf.slice()).mark(&end);
3214
3215 unit.unit_length = (&end - &start) as usize;
3216 length.set_const(unit.unit_length as u64);
3217
3218 section
3219 }
3220
3221 fn die<F>(self, code: u64, attr: F) -> Self
3222 where
3223 F: Fn(Section) -> Section,
3224 {
3225 let section = self.uleb(code);
3226 attr(section)
3227 }
3228
3229 fn die_null(self) -> Self {
3230 self.D8(0)
3231 }
3232
3233 fn attr_string(self, attr: &str) -> Self {
3234 self.append_bytes(attr.as_bytes()).D8(0)
3235 }
3236
3237 fn attr_ref1(self, attr: u8) -> Self {
3238 self.D8(attr)
3239 }
3240
3241 fn offset(self, offset: usize, format: Format) -> Self {
3242 match format {
3243 Format::Dwarf32 => self.L32(offset as u32),
3244 Format::Dwarf64 => self.L64(offset as u64),
3245 }
3246 }
3247 }
3248
3249 #[test]
3251 fn test_unit_header_variance() {
3252 fn _f<'a: 'b, 'b, E: Endianity>(
3254 x: UnitHeader<EndianSlice<'a, E>>,
3255 ) -> UnitHeader<EndianSlice<'b, E>> {
3256 x
3257 }
3258 }
3259
3260 #[test]
3261 #[cfg(target_pointer_width = "64")]
3262 fn test_units() {
3263 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3264 let mut unit64 = UnitHeader {
3265 encoding: Encoding {
3266 format: Format::Dwarf64,
3267 version: 4,
3268 address_size: 8,
3269 },
3270 unit_length: 0,
3271 unit_type: UnitType::Compilation,
3272 debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
3273 section: SectionId::DebugInfo,
3274 unit_offset: UnitSectionOffset(0),
3275 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3276 };
3277 let mut unit32 = UnitHeader {
3278 encoding: Encoding {
3279 format: Format::Dwarf32,
3280 version: 4,
3281 address_size: 4,
3282 },
3283 unit_length: 0,
3284 unit_type: UnitType::Compilation,
3285 debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3286 section: SectionId::DebugInfo,
3287 unit_offset: UnitSectionOffset(0),
3288 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3289 };
3290 let section = Section::with_endian(Endian::Little)
3291 .unit(&mut unit64)
3292 .unit(&mut unit32);
3293 let buf = section.get_contents().unwrap();
3294
3295 let debug_info = DebugInfo::new(&buf, LittleEndian);
3296 let mut units = debug_info.units();
3297
3298 assert_eq!(units.next(), Ok(Some(unit64)));
3299 assert_eq!(units.next(), Ok(Some(unit32)));
3300 assert_eq!(units.next(), Ok(None));
3301 }
3302
3303 #[test]
3304 fn test_unit_version_unknown_version() {
3305 let buf = [0x02, 0x00, 0x00, 0x00, 0xab, 0xcd];
3306 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3307
3308 match parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)) {
3309 Err(Error::UnknownVersion(0xcdab)) => {}
3310 otherwise => panic!("Unexpected result: {:?}", otherwise),
3311 };
3312
3313 let buf = [0x02, 0x00, 0x00, 0x00, 0x1, 0x0];
3314 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3315
3316 match parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)) {
3317 Err(Error::UnknownVersion(1)) => {}
3318 otherwise => panic!("Unexpected result: {:?}", otherwise),
3319 };
3320 }
3321
3322 #[test]
3323 fn test_unit_version_incomplete() {
3324 let buf = [0x01, 0x00, 0x00, 0x00, 0x04];
3325 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3326
3327 match parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)) {
3328 Err(Error::UnexpectedEof(_)) => {}
3329 otherwise => panic!("Unexpected result: {:?}", otherwise),
3330 };
3331 }
3332
3333 #[test]
3334 fn test_parse_unit_header_32_ok() {
3335 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3336 let encoding = Encoding {
3337 format: Format::Dwarf32,
3338 version: 4,
3339 address_size: 4,
3340 };
3341 let mut expected_unit = UnitHeader {
3342 encoding,
3343 unit_length: 0,
3344 unit_type: UnitType::Compilation,
3345 debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3346 section: SectionId::DebugInfo,
3347 unit_offset: UnitSectionOffset(0),
3348 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3349 };
3350 let section = Section::with_endian(Endian::Little)
3351 .unit(&mut expected_unit)
3352 .append_bytes(expected_rest);
3353 let buf = section.get_contents().unwrap();
3354 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3355
3356 assert_eq!(
3357 parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)),
3358 Ok(expected_unit)
3359 );
3360 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3361 }
3362
3363 #[test]
3364 #[cfg(target_pointer_width = "64")]
3365 fn test_parse_unit_header_64_ok() {
3366 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3367 let encoding = Encoding {
3368 format: Format::Dwarf64,
3369 version: 4,
3370 address_size: 8,
3371 };
3372 let mut expected_unit = UnitHeader {
3373 encoding,
3374 unit_length: 0,
3375 unit_type: UnitType::Compilation,
3376 debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
3377 section: SectionId::DebugInfo,
3378 unit_offset: UnitSectionOffset(0),
3379 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3380 };
3381 let section = Section::with_endian(Endian::Little)
3382 .unit(&mut expected_unit)
3383 .append_bytes(expected_rest);
3384 let buf = section.get_contents().unwrap();
3385 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3386
3387 assert_eq!(
3388 parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)),
3389 Ok(expected_unit)
3390 );
3391 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3392 }
3393
3394 #[test]
3395 fn test_parse_v5_unit_header_32_ok() {
3396 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3397 let encoding = Encoding {
3398 format: Format::Dwarf32,
3399 version: 5,
3400 address_size: 4,
3401 };
3402 let mut expected_unit = UnitHeader {
3403 encoding,
3404 unit_length: 0,
3405 unit_type: UnitType::Compilation,
3406 debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3407 section: SectionId::DebugInfo,
3408 unit_offset: UnitSectionOffset(0),
3409 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3410 };
3411 let section = Section::with_endian(Endian::Little)
3412 .unit(&mut expected_unit)
3413 .append_bytes(expected_rest);
3414 let buf = section.get_contents().unwrap();
3415 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3416
3417 assert_eq!(
3418 parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)),
3419 Ok(expected_unit)
3420 );
3421 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3422 }
3423
3424 #[test]
3425 #[cfg(target_pointer_width = "64")]
3426 fn test_parse_v5_unit_header_64_ok() {
3427 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3428 let encoding = Encoding {
3429 format: Format::Dwarf64,
3430 version: 5,
3431 address_size: 8,
3432 };
3433 let mut expected_unit = UnitHeader {
3434 encoding,
3435 unit_length: 0,
3436 unit_type: UnitType::Compilation,
3437 debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
3438 section: SectionId::DebugInfo,
3439 unit_offset: UnitSectionOffset(0),
3440 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3441 };
3442 let section = Section::with_endian(Endian::Little)
3443 .unit(&mut expected_unit)
3444 .append_bytes(expected_rest);
3445 let buf = section.get_contents().unwrap();
3446 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3447
3448 assert_eq!(
3449 parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)),
3450 Ok(expected_unit)
3451 );
3452 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3453 }
3454
3455 #[test]
3456 fn test_parse_v5_partial_unit_header_32_ok() {
3457 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3458 let encoding = Encoding {
3459 format: Format::Dwarf32,
3460 version: 5,
3461 address_size: 4,
3462 };
3463 let mut expected_unit = UnitHeader {
3464 encoding,
3465 unit_length: 0,
3466 unit_type: UnitType::Partial,
3467 debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3468 section: SectionId::DebugInfo,
3469 unit_offset: UnitSectionOffset(0),
3470 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3471 };
3472 let section = Section::with_endian(Endian::Little)
3473 .unit(&mut expected_unit)
3474 .append_bytes(expected_rest);
3475 let buf = section.get_contents().unwrap();
3476 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3477
3478 assert_eq!(
3479 parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)),
3480 Ok(expected_unit)
3481 );
3482 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3483 }
3484
3485 #[test]
3486 #[cfg(target_pointer_width = "64")]
3487 fn test_parse_v5_partial_unit_header_64_ok() {
3488 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3489 let encoding = Encoding {
3490 format: Format::Dwarf64,
3491 version: 5,
3492 address_size: 8,
3493 };
3494 let mut expected_unit = UnitHeader {
3495 encoding,
3496 unit_length: 0,
3497 unit_type: UnitType::Partial,
3498 debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
3499 section: SectionId::DebugInfo,
3500 unit_offset: UnitSectionOffset(0),
3501 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3502 };
3503 let section = Section::with_endian(Endian::Little)
3504 .unit(&mut expected_unit)
3505 .append_bytes(expected_rest);
3506 let buf = section.get_contents().unwrap();
3507 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3508
3509 assert_eq!(
3510 parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)),
3511 Ok(expected_unit)
3512 );
3513 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3514 }
3515
3516 #[test]
3517 fn test_parse_v5_skeleton_unit_header_32_ok() {
3518 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3519 let encoding = Encoding {
3520 format: Format::Dwarf32,
3521 version: 5,
3522 address_size: 4,
3523 };
3524 let mut expected_unit = UnitHeader {
3525 encoding,
3526 unit_length: 0,
3527 unit_type: UnitType::Skeleton(DwoId(0x0706_5040_0302_1000)),
3528 debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3529 section: SectionId::DebugInfo,
3530 unit_offset: UnitSectionOffset(0),
3531 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3532 };
3533 let section = Section::with_endian(Endian::Little)
3534 .unit(&mut expected_unit)
3535 .append_bytes(expected_rest);
3536 let buf = section.get_contents().unwrap();
3537 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3538
3539 assert_eq!(
3540 parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)),
3541 Ok(expected_unit)
3542 );
3543 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3544 }
3545
3546 #[test]
3547 #[cfg(target_pointer_width = "64")]
3548 fn test_parse_v5_skeleton_unit_header_64_ok() {
3549 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3550 let encoding = Encoding {
3551 format: Format::Dwarf64,
3552 version: 5,
3553 address_size: 8,
3554 };
3555 let mut expected_unit = UnitHeader {
3556 encoding,
3557 unit_length: 0,
3558 unit_type: UnitType::Skeleton(DwoId(0x0706_5040_0302_1000)),
3559 debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
3560 section: SectionId::DebugInfo,
3561 unit_offset: UnitSectionOffset(0),
3562 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3563 };
3564 let section = Section::with_endian(Endian::Little)
3565 .unit(&mut expected_unit)
3566 .append_bytes(expected_rest);
3567 let buf = section.get_contents().unwrap();
3568 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3569
3570 assert_eq!(
3571 parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)),
3572 Ok(expected_unit)
3573 );
3574 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3575 }
3576
3577 #[test]
3578 fn test_parse_v5_split_compilation_unit_header_32_ok() {
3579 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3580 let encoding = Encoding {
3581 format: Format::Dwarf32,
3582 version: 5,
3583 address_size: 4,
3584 };
3585 let mut expected_unit = UnitHeader {
3586 encoding,
3587 unit_length: 0,
3588 unit_type: UnitType::SplitCompilation(DwoId(0x0706_5040_0302_1000)),
3589 debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3590 section: SectionId::DebugInfo,
3591 unit_offset: UnitSectionOffset(0),
3592 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3593 };
3594 let section = Section::with_endian(Endian::Little)
3595 .unit(&mut expected_unit)
3596 .append_bytes(expected_rest);
3597 let buf = section.get_contents().unwrap();
3598 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3599
3600 assert_eq!(
3601 parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)),
3602 Ok(expected_unit)
3603 );
3604 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3605 }
3606
3607 #[test]
3608 #[cfg(target_pointer_width = "64")]
3609 fn test_parse_v5_split_compilation_unit_header_64_ok() {
3610 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3611 let encoding = Encoding {
3612 format: Format::Dwarf64,
3613 version: 5,
3614 address_size: 8,
3615 };
3616 let mut expected_unit = UnitHeader {
3617 encoding,
3618 unit_length: 0,
3619 unit_type: UnitType::SplitCompilation(DwoId(0x0706_5040_0302_1000)),
3620 debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
3621 section: SectionId::DebugInfo,
3622 unit_offset: UnitSectionOffset(0),
3623 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3624 };
3625 let section = Section::with_endian(Endian::Little)
3626 .unit(&mut expected_unit)
3627 .append_bytes(expected_rest);
3628 let buf = section.get_contents().unwrap();
3629 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3630
3631 assert_eq!(
3632 parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)),
3633 Ok(expected_unit)
3634 );
3635 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3636 }
3637
3638 #[test]
3639 fn test_parse_type_unit_header_32_ok() {
3640 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3641 let encoding = Encoding {
3642 format: Format::Dwarf32,
3643 version: 4,
3644 address_size: 8,
3645 };
3646 let mut expected_unit = UnitHeader {
3647 encoding,
3648 unit_length: 0,
3649 unit_type: UnitType::Type {
3650 type_signature: DebugTypeSignature(0xdead_beef_dead_beef),
3651 type_offset: UnitOffset(0x7856_3412),
3652 },
3653 debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3654 section: SectionId::DebugTypes,
3655 unit_offset: UnitSectionOffset(0),
3656 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3657 };
3658 let section = Section::with_endian(Endian::Little)
3659 .unit(&mut expected_unit)
3660 .append_bytes(expected_rest);
3661 let buf = section.get_contents().unwrap();
3662 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3663
3664 assert_eq!(
3665 parse_unit_header(rest, SectionId::DebugTypes, UnitSectionOffset(0)),
3666 Ok(expected_unit)
3667 );
3668 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3669 }
3670
3671 #[test]
3672 #[cfg(target_pointer_width = "64")]
3673 fn test_parse_type_unit_header_64_ok() {
3674 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3675 let encoding = Encoding {
3676 format: Format::Dwarf64,
3677 version: 4,
3678 address_size: 8,
3679 };
3680 let mut expected_unit = UnitHeader {
3681 encoding,
3682 unit_length: 0,
3683 unit_type: UnitType::Type {
3684 type_signature: DebugTypeSignature(0xdead_beef_dead_beef),
3685 type_offset: UnitOffset(0x7856_3412_7856_3412),
3686 },
3687 debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3688 section: SectionId::DebugTypes,
3689 unit_offset: UnitSectionOffset(0),
3690 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3691 };
3692 let section = Section::with_endian(Endian::Little)
3693 .unit(&mut expected_unit)
3694 .append_bytes(expected_rest);
3695 let buf = section.get_contents().unwrap();
3696 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3697
3698 assert_eq!(
3699 parse_unit_header(rest, SectionId::DebugTypes, UnitSectionOffset(0)),
3700 Ok(expected_unit)
3701 );
3702 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3703 }
3704
3705 #[test]
3706 fn test_parse_v5_type_unit_header_32_ok() {
3707 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3708 let encoding = Encoding {
3709 format: Format::Dwarf32,
3710 version: 5,
3711 address_size: 8,
3712 };
3713 let mut expected_unit = UnitHeader {
3714 encoding,
3715 unit_length: 0,
3716 unit_type: UnitType::Type {
3717 type_signature: DebugTypeSignature(0xdead_beef_dead_beef),
3718 type_offset: UnitOffset(0x7856_3412),
3719 },
3720 debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3721 section: SectionId::DebugInfo,
3722 unit_offset: UnitSectionOffset(0),
3723 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3724 };
3725 let section = Section::with_endian(Endian::Little)
3726 .unit(&mut expected_unit)
3727 .append_bytes(expected_rest);
3728 let buf = section.get_contents().unwrap();
3729 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3730
3731 assert_eq!(
3732 parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)),
3733 Ok(expected_unit)
3734 );
3735 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3736 }
3737
3738 #[test]
3739 #[cfg(target_pointer_width = "64")]
3740 fn test_parse_v5_type_unit_header_64_ok() {
3741 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3742 let encoding = Encoding {
3743 format: Format::Dwarf64,
3744 version: 5,
3745 address_size: 8,
3746 };
3747 let mut expected_unit = UnitHeader {
3748 encoding,
3749 unit_length: 0,
3750 unit_type: UnitType::Type {
3751 type_signature: DebugTypeSignature(0xdead_beef_dead_beef),
3752 type_offset: UnitOffset(0x7856_3412_7856_3412),
3753 },
3754 debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3755 section: SectionId::DebugInfo,
3756 unit_offset: UnitSectionOffset(0),
3757 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3758 };
3759 let section = Section::with_endian(Endian::Little)
3760 .unit(&mut expected_unit)
3761 .append_bytes(expected_rest);
3762 let buf = section.get_contents().unwrap();
3763 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3764
3765 assert_eq!(
3766 parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)),
3767 Ok(expected_unit)
3768 );
3769 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3770 }
3771
3772 #[test]
3773 fn test_parse_v5_split_type_unit_header_32_ok() {
3774 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3775 let encoding = Encoding {
3776 format: Format::Dwarf32,
3777 version: 5,
3778 address_size: 8,
3779 };
3780 let mut expected_unit = UnitHeader {
3781 encoding,
3782 unit_length: 0,
3783 unit_type: UnitType::SplitType {
3784 type_signature: DebugTypeSignature(0xdead_beef_dead_beef),
3785 type_offset: UnitOffset(0x7856_3412),
3786 },
3787 debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3788 section: SectionId::DebugInfo,
3789 unit_offset: UnitSectionOffset(0),
3790 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3791 };
3792 let section = Section::with_endian(Endian::Little)
3793 .unit(&mut expected_unit)
3794 .append_bytes(expected_rest);
3795 let buf = section.get_contents().unwrap();
3796 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3797
3798 assert_eq!(
3799 parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)),
3800 Ok(expected_unit)
3801 );
3802 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3803 }
3804
3805 #[test]
3806 #[cfg(target_pointer_width = "64")]
3807 fn test_parse_v5_split_type_unit_header_64_ok() {
3808 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3809 let encoding = Encoding {
3810 format: Format::Dwarf64,
3811 version: 5,
3812 address_size: 8,
3813 };
3814 let mut expected_unit = UnitHeader {
3815 encoding,
3816 unit_length: 0,
3817 unit_type: UnitType::SplitType {
3818 type_signature: DebugTypeSignature(0xdead_beef_dead_beef),
3819 type_offset: UnitOffset(0x7856_3412_7856_3412),
3820 },
3821 debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3822 section: SectionId::DebugInfo,
3823 unit_offset: UnitSectionOffset(0),
3824 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3825 };
3826 let section = Section::with_endian(Endian::Little)
3827 .unit(&mut expected_unit)
3828 .append_bytes(expected_rest);
3829 let buf = section.get_contents().unwrap();
3830 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3831
3832 assert_eq!(
3833 parse_unit_header(rest, SectionId::DebugInfo, UnitSectionOffset(0)),
3834 Ok(expected_unit)
3835 );
3836 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3837 }
3838
3839 fn section_contents<F>(f: F) -> Vec<u8>
3840 where
3841 F: Fn(Section) -> Section,
3842 {
3843 f(Section::with_endian(Endian::Little))
3844 .get_contents()
3845 .unwrap()
3846 }
3847
3848 #[test]
3849 fn test_attribute_value() {
3850 let mut unit = test_parse_attribute_unit_default();
3851 let endian = unit.entries_buf.endian();
3852
3853 let block_data = &[1, 2, 3, 4];
3854 let buf = section_contents(|s| s.uleb(block_data.len() as u64).append_bytes(block_data));
3855 let block = EndianSlice::new(&buf, endian);
3856
3857 let buf = section_contents(|s| s.L32(0x0102_0304));
3858 let data4 = EndianSlice::new(&buf, endian);
3859
3860 let buf = section_contents(|s| s.L64(0x0102_0304_0506_0708));
3861 let data8 = EndianSlice::new(&buf, endian);
3862
3863 let tests = [
3864 (
3865 Format::Dwarf32,
3866 2,
3867 constants::DW_AT_data_member_location,
3868 constants::DW_FORM_block,
3869 block,
3870 AttributeValue::Block(EndianSlice::new(block_data, endian)),
3871 AttributeValue::Exprloc(Expression(EndianSlice::new(block_data, endian))),
3872 ),
3873 (
3874 Format::Dwarf32,
3875 2,
3876 constants::DW_AT_data_member_location,
3877 constants::DW_FORM_data4,
3878 data4,
3879 AttributeValue::SecOffset(0x0102_0304),
3880 AttributeValue::LocationListsRef(LocationListsOffset(0x0102_0304)),
3881 ),
3882 (
3883 Format::Dwarf64,
3884 2,
3885 constants::DW_AT_data_member_location,
3886 constants::DW_FORM_data4,
3887 data4,
3888 AttributeValue::Data4(0x0102_0304),
3889 AttributeValue::Udata(0x0102_0304),
3890 ),
3891 (
3892 Format::Dwarf32,
3893 4,
3894 constants::DW_AT_data_member_location,
3895 constants::DW_FORM_data4,
3896 data4,
3897 AttributeValue::Data4(0x0102_0304),
3898 AttributeValue::Udata(0x0102_0304),
3899 ),
3900 (
3901 Format::Dwarf32,
3902 2,
3903 constants::DW_AT_data_member_location,
3904 constants::DW_FORM_data8,
3905 data8,
3906 AttributeValue::Data8(0x0102_0304_0506_0708),
3907 AttributeValue::Udata(0x0102_0304_0506_0708),
3908 ),
3909 #[cfg(target_pointer_width = "64")]
3910 (
3911 Format::Dwarf64,
3912 2,
3913 constants::DW_AT_data_member_location,
3914 constants::DW_FORM_data8,
3915 data8,
3916 AttributeValue::SecOffset(0x0102_0304_0506_0708),
3917 AttributeValue::LocationListsRef(LocationListsOffset(0x0102_0304_0506_0708)),
3918 ),
3919 (
3920 Format::Dwarf64,
3921 4,
3922 constants::DW_AT_data_member_location,
3923 constants::DW_FORM_data8,
3924 data8,
3925 AttributeValue::Data8(0x0102_0304_0506_0708),
3926 AttributeValue::Udata(0x0102_0304_0506_0708),
3927 ),
3928 (
3929 Format::Dwarf32,
3930 4,
3931 constants::DW_AT_location,
3932 constants::DW_FORM_data4,
3933 data4,
3934 AttributeValue::SecOffset(0x0102_0304),
3935 AttributeValue::LocationListsRef(LocationListsOffset(0x0102_0304)),
3936 ),
3937 #[cfg(target_pointer_width = "64")]
3938 (
3939 Format::Dwarf64,
3940 4,
3941 constants::DW_AT_location,
3942 constants::DW_FORM_data8,
3943 data8,
3944 AttributeValue::SecOffset(0x0102_0304_0506_0708),
3945 AttributeValue::LocationListsRef(LocationListsOffset(0x0102_0304_0506_0708)),
3946 ),
3947 (
3948 Format::Dwarf32,
3949 4,
3950 constants::DW_AT_str_offsets_base,
3951 constants::DW_FORM_sec_offset,
3952 data4,
3953 AttributeValue::SecOffset(0x0102_0304),
3954 AttributeValue::DebugStrOffsetsBase(DebugStrOffsetsBase(0x0102_0304)),
3955 ),
3956 (
3957 Format::Dwarf32,
3958 4,
3959 constants::DW_AT_stmt_list,
3960 constants::DW_FORM_sec_offset,
3961 data4,
3962 AttributeValue::SecOffset(0x0102_0304),
3963 AttributeValue::DebugLineRef(DebugLineOffset(0x0102_0304)),
3964 ),
3965 (
3966 Format::Dwarf32,
3967 4,
3968 constants::DW_AT_addr_base,
3969 constants::DW_FORM_sec_offset,
3970 data4,
3971 AttributeValue::SecOffset(0x0102_0304),
3972 AttributeValue::DebugAddrBase(DebugAddrBase(0x0102_0304)),
3973 ),
3974 (
3975 Format::Dwarf32,
3976 4,
3977 constants::DW_AT_rnglists_base,
3978 constants::DW_FORM_sec_offset,
3979 data4,
3980 AttributeValue::SecOffset(0x0102_0304),
3981 AttributeValue::DebugRngListsBase(DebugRngListsBase(0x0102_0304)),
3982 ),
3983 (
3984 Format::Dwarf32,
3985 4,
3986 constants::DW_AT_loclists_base,
3987 constants::DW_FORM_sec_offset,
3988 data4,
3989 AttributeValue::SecOffset(0x0102_0304),
3990 AttributeValue::DebugLocListsBase(DebugLocListsBase(0x0102_0304)),
3991 ),
3992 ];
3993
3994 for test in tests.iter() {
3995 let (format, version, name, form, mut input, expect_raw, expect_value) = *test;
3996 unit.encoding.format = format;
3997 unit.encoding.version = version;
3998 let spec = AttributeSpecification::new(name, form, None);
3999 let attribute =
4000 parse_attribute(&mut input, unit.encoding(), spec).expect("Should parse attribute");
4001 assert_eq!(attribute.raw_value(), expect_raw);
4002 assert_eq!(attribute.value(), expect_value);
4003 }
4004 }
4005
4006 #[test]
4007 fn test_attribute_udata_sdata_value() {
4008 #[allow(clippy::type_complexity)]
4009 let tests: &[(
4010 AttributeValue<EndianSlice<'_, LittleEndian>>,
4011 Option<u64>,
4012 Option<i64>,
4013 )] = &[
4014 (AttributeValue::Data1(1), Some(1), Some(1)),
4015 (
4016 AttributeValue::Data1(u8::MAX),
4017 Some(u64::from(u8::MAX)),
4018 Some(-1),
4019 ),
4020 (AttributeValue::Data2(1), Some(1), Some(1)),
4021 (
4022 AttributeValue::Data2(u16::MAX),
4023 Some(u64::from(u16::MAX)),
4024 Some(-1),
4025 ),
4026 (AttributeValue::Data4(1), Some(1), Some(1)),
4027 (
4028 AttributeValue::Data4(u32::MAX),
4029 Some(u64::from(u32::MAX)),
4030 Some(-1),
4031 ),
4032 (AttributeValue::Data8(1), Some(1), Some(1)),
4033 (AttributeValue::Data8(u64::MAX), Some(u64::MAX), Some(-1)),
4034 (AttributeValue::Sdata(1), Some(1), Some(1)),
4035 (AttributeValue::Sdata(-1), None, Some(-1)),
4036 (AttributeValue::Udata(1), Some(1), Some(1)),
4037 (AttributeValue::Udata(1u64 << 63), Some(1u64 << 63), None),
4038 ];
4039 for test in tests.iter() {
4040 let (value, expect_udata, expect_sdata) = *test;
4041 let attribute = Attribute {
4042 name: DW_AT_data_member_location,
4043 form: constants::DW_FORM_null, value,
4045 };
4046 assert_eq!(attribute.udata_value(), expect_udata);
4047 assert_eq!(attribute.sdata_value(), expect_sdata);
4048 }
4049 }
4050
4051 fn test_parse_attribute_unit<Endian>(
4052 address_size: u8,
4053 format: Format,
4054 endian: Endian,
4055 ) -> UnitHeader<EndianSlice<'static, Endian>>
4056 where
4057 Endian: Endianity,
4058 {
4059 let encoding = Encoding {
4060 format,
4061 version: 4,
4062 address_size,
4063 };
4064 UnitHeader::new(
4065 encoding,
4066 7,
4067 UnitType::Compilation,
4068 DebugAbbrevOffset(0x0807_0605),
4069 SectionId::DebugInfo,
4070 UnitSectionOffset(0),
4071 EndianSlice::new(&[], endian),
4072 )
4073 }
4074
4075 fn test_parse_attribute_unit_default() -> UnitHeader<EndianSlice<'static, LittleEndian>> {
4076 test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian)
4077 }
4078
4079 fn test_parse_attribute<'input, Endian>(
4080 buf: &'input [u8],
4081 len: usize,
4082 unit: &UnitHeader<EndianSlice<'input, Endian>>,
4083 form: constants::DwForm,
4084 value: AttributeValue<EndianSlice<'input, Endian>>,
4085 ) where
4086 Endian: Endianity,
4087 {
4088 let spec = AttributeSpecification::new(constants::DW_AT_low_pc, form, None);
4089
4090 let expect = Attribute {
4091 name: constants::DW_AT_low_pc,
4092 form,
4093 value,
4094 };
4095
4096 let rest = &mut EndianSlice::new(buf, Endian::default());
4097 match parse_attribute(rest, unit.encoding(), spec) {
4098 Ok(attr) => {
4099 assert_eq!(attr, expect);
4100 assert_eq!(*rest, EndianSlice::new(&buf[len..], Endian::default()));
4101 if let Some(size) = spec.size(unit) {
4102 assert_eq!(rest.len() + size, buf.len());
4103 }
4104 }
4105 otherwise => {
4106 panic!("Unexpected parse result = {:#?}", otherwise);
4107 }
4108 };
4109 }
4110
4111 #[test]
4112 fn test_parse_attribute_addr() {
4113 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
4114 let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4115 let form = constants::DW_FORM_addr;
4116 let value = AttributeValue::Addr(0x0403_0201);
4117 test_parse_attribute(&buf, 4, &unit, form, value);
4118 }
4119
4120 #[test]
4121 fn test_parse_attribute_addr8() {
4122 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
4123 let unit = test_parse_attribute_unit(8, Format::Dwarf32, LittleEndian);
4124 let form = constants::DW_FORM_addr;
4125 let value = AttributeValue::Addr(0x0807_0605_0403_0201);
4126 test_parse_attribute(&buf, 8, &unit, form, value);
4127 }
4128
4129 #[test]
4130 fn test_parse_attribute_block1() {
4131 let buf = [0x03, 0x09, 0x09, 0x09, 0x00, 0x00];
4133 let unit = test_parse_attribute_unit_default();
4134 let form = constants::DW_FORM_block1;
4135 let value = AttributeValue::Block(EndianSlice::new(&buf[1..4], LittleEndian));
4136 test_parse_attribute(&buf, 4, &unit, form, value);
4137 }
4138
4139 #[test]
4140 fn test_parse_attribute_block2() {
4141 let buf = [0x02, 0x00, 0x09, 0x09, 0x00, 0x00];
4143 let unit = test_parse_attribute_unit_default();
4144 let form = constants::DW_FORM_block2;
4145 let value = AttributeValue::Block(EndianSlice::new(&buf[2..4], LittleEndian));
4146 test_parse_attribute(&buf, 4, &unit, form, value);
4147 }
4148
4149 #[test]
4150 fn test_parse_attribute_block4() {
4151 let buf = [0x02, 0x00, 0x00, 0x00, 0x99, 0x99];
4153 let unit = test_parse_attribute_unit_default();
4154 let form = constants::DW_FORM_block4;
4155 let value = AttributeValue::Block(EndianSlice::new(&buf[4..], LittleEndian));
4156 test_parse_attribute(&buf, 6, &unit, form, value);
4157 }
4158
4159 #[test]
4160 fn test_parse_attribute_block() {
4161 let buf = [0x02, 0x99, 0x99];
4163 let unit = test_parse_attribute_unit_default();
4164 let form = constants::DW_FORM_block;
4165 let value = AttributeValue::Block(EndianSlice::new(&buf[1..], LittleEndian));
4166 test_parse_attribute(&buf, 3, &unit, form, value);
4167 }
4168
4169 #[test]
4170 fn test_parse_attribute_data1() {
4171 let buf = [0x03];
4172 let unit = test_parse_attribute_unit_default();
4173 let form = constants::DW_FORM_data1;
4174 let value = AttributeValue::Data1(0x03);
4175 test_parse_attribute(&buf, 1, &unit, form, value);
4176 }
4177
4178 #[test]
4179 fn test_parse_attribute_data2() {
4180 let buf = [0x02, 0x01, 0x0];
4181 let unit = test_parse_attribute_unit_default();
4182 let form = constants::DW_FORM_data2;
4183 let value = AttributeValue::Data2(0x0102);
4184 test_parse_attribute(&buf, 2, &unit, form, value);
4185 }
4186
4187 #[test]
4188 fn test_parse_attribute_data4() {
4189 let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99];
4190 let unit = test_parse_attribute_unit_default();
4191 let form = constants::DW_FORM_data4;
4192 let value = AttributeValue::Data4(0x0403_0201);
4193 test_parse_attribute(&buf, 4, &unit, form, value);
4194 }
4195
4196 #[test]
4197 fn test_parse_attribute_data8() {
4198 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4199 let unit = test_parse_attribute_unit_default();
4200 let form = constants::DW_FORM_data8;
4201 let value = AttributeValue::Data8(0x0807_0605_0403_0201);
4202 test_parse_attribute(&buf, 8, &unit, form, value);
4203 }
4204
4205 #[test]
4206 fn test_parse_attribute_data16() {
4207 let buf = [
4208 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
4209 0x0f, 0x10, 0x99, 0x99,
4210 ];
4211 let unit = test_parse_attribute_unit_default();
4212 let form = constants::DW_FORM_data16;
4213 let value = AttributeValue::Data16(0x100f_0e0d_0c0b_0a09_0807_0605_0403_0201);
4214 test_parse_attribute(&buf, 16, &unit, form, value);
4215 }
4216
4217 #[test]
4218 fn test_parse_attribute_udata() {
4219 let mut buf = Vec::new();
4220 buf.extend_from_slice(Leb128::unsigned(4097).bytes());
4221 let bytes_written = buf.len();
4222 buf.extend_from_slice(&[0; 10]);
4223
4224 let unit = test_parse_attribute_unit_default();
4225 let form = constants::DW_FORM_udata;
4226 let value = AttributeValue::Udata(4097);
4227 test_parse_attribute(&buf, bytes_written, &unit, form, value);
4228 }
4229
4230 #[test]
4231 fn test_parse_attribute_sdata() {
4232 let mut buf = Vec::new();
4233 buf.extend_from_slice(Leb128::signed(-4097).bytes());
4234 let bytes_written = buf.len();
4235 buf.extend_from_slice(&[0; 10]);
4236
4237 let unit = test_parse_attribute_unit_default();
4238 let form = constants::DW_FORM_sdata;
4239 let value = AttributeValue::Sdata(-4097);
4240 test_parse_attribute(&buf, bytes_written, &unit, form, value);
4241 }
4242
4243 #[test]
4244 fn test_parse_attribute_exprloc() {
4245 let buf = [0x02, 0x99, 0x99, 0x11];
4247 let unit = test_parse_attribute_unit_default();
4248 let form = constants::DW_FORM_exprloc;
4249 let value = AttributeValue::Exprloc(Expression(EndianSlice::new(&buf[1..3], LittleEndian)));
4250 test_parse_attribute(&buf, 3, &unit, form, value);
4251 }
4252
4253 #[test]
4254 fn test_parse_attribute_flag_true() {
4255 let buf = [0x42];
4256 let unit = test_parse_attribute_unit_default();
4257 let form = constants::DW_FORM_flag;
4258 let value = AttributeValue::Flag(true);
4259 test_parse_attribute(&buf, 1, &unit, form, value);
4260 }
4261
4262 #[test]
4263 fn test_parse_attribute_flag_false() {
4264 let buf = [0x00];
4265 let unit = test_parse_attribute_unit_default();
4266 let form = constants::DW_FORM_flag;
4267 let value = AttributeValue::Flag(false);
4268 test_parse_attribute(&buf, 1, &unit, form, value);
4269 }
4270
4271 #[test]
4272 fn test_parse_attribute_flag_present() {
4273 let buf = [0x01, 0x02, 0x03, 0x04];
4274 let unit = test_parse_attribute_unit_default();
4275 let form = constants::DW_FORM_flag_present;
4276 let value = AttributeValue::Flag(true);
4277 test_parse_attribute(&buf, 0, &unit, form, value);
4279 }
4280
4281 #[test]
4282 fn test_parse_attribute_sec_offset_32() {
4283 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10];
4284 let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4285 let form = constants::DW_FORM_sec_offset;
4286 let value = AttributeValue::SecOffset(0x0403_0201);
4287 test_parse_attribute(&buf, 4, &unit, form, value);
4288 }
4289
4290 #[test]
4291 #[cfg(target_pointer_width = "64")]
4292 fn test_parse_attribute_sec_offset_64() {
4293 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10];
4294 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4295 let form = constants::DW_FORM_sec_offset;
4296 let value = AttributeValue::SecOffset(0x0807_0605_0403_0201);
4297 test_parse_attribute(&buf, 8, &unit, form, value);
4298 }
4299
4300 #[test]
4301 fn test_parse_attribute_ref1() {
4302 let buf = [0x03];
4303 let unit = test_parse_attribute_unit_default();
4304 let form = constants::DW_FORM_ref1;
4305 let value = AttributeValue::UnitRef(UnitOffset(3));
4306 test_parse_attribute(&buf, 1, &unit, form, value);
4307 }
4308
4309 #[test]
4310 fn test_parse_attribute_ref2() {
4311 let buf = [0x02, 0x01, 0x0];
4312 let unit = test_parse_attribute_unit_default();
4313 let form = constants::DW_FORM_ref2;
4314 let value = AttributeValue::UnitRef(UnitOffset(258));
4315 test_parse_attribute(&buf, 2, &unit, form, value);
4316 }
4317
4318 #[test]
4319 fn test_parse_attribute_ref4() {
4320 let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99];
4321 let unit = test_parse_attribute_unit_default();
4322 let form = constants::DW_FORM_ref4;
4323 let value = AttributeValue::UnitRef(UnitOffset(0x0403_0201));
4324 test_parse_attribute(&buf, 4, &unit, form, value);
4325 }
4326
4327 #[test]
4328 #[cfg(target_pointer_width = "64")]
4329 fn test_parse_attribute_ref8() {
4330 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4331 let unit = test_parse_attribute_unit_default();
4332 let form = constants::DW_FORM_ref8;
4333 let value = AttributeValue::UnitRef(UnitOffset(0x0807_0605_0403_0201));
4334 test_parse_attribute(&buf, 8, &unit, form, value);
4335 }
4336
4337 #[test]
4338 fn test_parse_attribute_ref_sup4() {
4339 let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99];
4340 let unit = test_parse_attribute_unit_default();
4341 let form = constants::DW_FORM_ref_sup4;
4342 let value = AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x0403_0201));
4343 test_parse_attribute(&buf, 4, &unit, form, value);
4344 }
4345
4346 #[test]
4347 #[cfg(target_pointer_width = "64")]
4348 fn test_parse_attribute_ref_sup8() {
4349 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4350 let unit = test_parse_attribute_unit_default();
4351 let form = constants::DW_FORM_ref_sup8;
4352 let value = AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x0807_0605_0403_0201));
4353 test_parse_attribute(&buf, 8, &unit, form, value);
4354 }
4355
4356 #[test]
4357 fn test_parse_attribute_refudata() {
4358 let mut buf = Vec::new();
4359 buf.extend_from_slice(Leb128::unsigned(4097).bytes());
4360 let bytes_written = buf.len();
4361 buf.extend_from_slice(&[0; 10]);
4362
4363 let unit = test_parse_attribute_unit_default();
4364 let form = constants::DW_FORM_ref_udata;
4365 let value = AttributeValue::UnitRef(UnitOffset(4097));
4366 test_parse_attribute(&buf, bytes_written, &unit, form, value);
4367 }
4368
4369 #[test]
4370 fn test_parse_attribute_refaddr_32() {
4371 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4372 let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4373 let form = constants::DW_FORM_ref_addr;
4374 let value = AttributeValue::DebugInfoRef(DebugInfoOffset(0x0403_0201));
4375 test_parse_attribute(&buf, 4, &unit, form, value);
4376 }
4377
4378 #[test]
4379 #[cfg(target_pointer_width = "64")]
4380 fn test_parse_attribute_refaddr_64() {
4381 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4382 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4383 let form = constants::DW_FORM_ref_addr;
4384 let value = AttributeValue::DebugInfoRef(DebugInfoOffset(0x0807_0605_0403_0201));
4385 test_parse_attribute(&buf, 8, &unit, form, value);
4386 }
4387
4388 #[test]
4389 fn test_parse_attribute_refaddr_version2() {
4390 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4391 let mut unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4392 unit.encoding.version = 2;
4393 let form = constants::DW_FORM_ref_addr;
4394 let value = AttributeValue::DebugInfoRef(DebugInfoOffset(0x0403_0201));
4395 test_parse_attribute(&buf, 4, &unit, form, value);
4396 }
4397
4398 #[test]
4399 #[cfg(target_pointer_width = "64")]
4400 fn test_parse_attribute_refaddr8_version2() {
4401 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4402 let mut unit = test_parse_attribute_unit(8, Format::Dwarf32, LittleEndian);
4403 unit.encoding.version = 2;
4404 let form = constants::DW_FORM_ref_addr;
4405 let value = AttributeValue::DebugInfoRef(DebugInfoOffset(0x0807_0605_0403_0201));
4406 test_parse_attribute(&buf, 8, &unit, form, value);
4407 }
4408
4409 #[test]
4410 fn test_parse_attribute_gnu_ref_alt_32() {
4411 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4412 let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4413 let form = constants::DW_FORM_GNU_ref_alt;
4414 let value = AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x0403_0201));
4415 test_parse_attribute(&buf, 4, &unit, form, value);
4416 }
4417
4418 #[test]
4419 #[cfg(target_pointer_width = "64")]
4420 fn test_parse_attribute_gnu_ref_alt_64() {
4421 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4422 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4423 let form = constants::DW_FORM_GNU_ref_alt;
4424 let value = AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x0807_0605_0403_0201));
4425 test_parse_attribute(&buf, 8, &unit, form, value);
4426 }
4427
4428 #[test]
4429 fn test_parse_attribute_refsig8() {
4430 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4431 let unit = test_parse_attribute_unit_default();
4432 let form = constants::DW_FORM_ref_sig8;
4433 let value = AttributeValue::DebugTypesRef(DebugTypeSignature(0x0807_0605_0403_0201));
4434 test_parse_attribute(&buf, 8, &unit, form, value);
4435 }
4436
4437 #[test]
4438 fn test_parse_attribute_string() {
4439 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x0, 0x99, 0x99];
4440 let unit = test_parse_attribute_unit_default();
4441 let form = constants::DW_FORM_string;
4442 let value = AttributeValue::String(EndianSlice::new(&buf[..5], LittleEndian));
4443 test_parse_attribute(&buf, 6, &unit, form, value);
4444 }
4445
4446 #[test]
4447 fn test_parse_attribute_strp_32() {
4448 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4449 let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4450 let form = constants::DW_FORM_strp;
4451 let value = AttributeValue::DebugStrRef(DebugStrOffset(0x0403_0201));
4452 test_parse_attribute(&buf, 4, &unit, form, value);
4453 }
4454
4455 #[test]
4456 #[cfg(target_pointer_width = "64")]
4457 fn test_parse_attribute_strp_64() {
4458 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4459 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4460 let form = constants::DW_FORM_strp;
4461 let value = AttributeValue::DebugStrRef(DebugStrOffset(0x0807_0605_0403_0201));
4462 test_parse_attribute(&buf, 8, &unit, form, value);
4463 }
4464
4465 #[test]
4466 fn test_parse_attribute_strp_sup_32() {
4467 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4468 let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4469 let form = constants::DW_FORM_strp_sup;
4470 let value = AttributeValue::DebugStrRefSup(DebugStrOffset(0x0403_0201));
4471 test_parse_attribute(&buf, 4, &unit, form, value);
4472 }
4473
4474 #[test]
4475 #[cfg(target_pointer_width = "64")]
4476 fn test_parse_attribute_strp_sup_64() {
4477 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4478 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4479 let form = constants::DW_FORM_strp_sup;
4480 let value = AttributeValue::DebugStrRefSup(DebugStrOffset(0x0807_0605_0403_0201));
4481 test_parse_attribute(&buf, 8, &unit, form, value);
4482 }
4483
4484 #[test]
4485 fn test_parse_attribute_gnu_strp_alt_32() {
4486 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4487 let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4488 let form = constants::DW_FORM_GNU_strp_alt;
4489 let value = AttributeValue::DebugStrRefSup(DebugStrOffset(0x0403_0201));
4490 test_parse_attribute(&buf, 4, &unit, form, value);
4491 }
4492
4493 #[test]
4494 #[cfg(target_pointer_width = "64")]
4495 fn test_parse_attribute_gnu_strp_alt_64() {
4496 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4497 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4498 let form = constants::DW_FORM_GNU_strp_alt;
4499 let value = AttributeValue::DebugStrRefSup(DebugStrOffset(0x0807_0605_0403_0201));
4500 test_parse_attribute(&buf, 8, &unit, form, value);
4501 }
4502
4503 #[test]
4504 fn test_parse_attribute_strx() {
4505 let mut buf = Vec::new();
4506 buf.extend_from_slice(Leb128::unsigned(4097).bytes());
4507 let bytes_written = buf.len();
4508 buf.extend_from_slice(&[0; 10]);
4509
4510 let unit = test_parse_attribute_unit_default();
4511 let form = constants::DW_FORM_strx;
4512 let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(4097));
4513 test_parse_attribute(&buf, bytes_written, &unit, form, value);
4514 }
4515
4516 #[test]
4517 fn test_parse_attribute_strx1() {
4518 let buf = [0x01, 0x99, 0x99];
4519 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4520 let form = constants::DW_FORM_strx1;
4521 let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(0x01));
4522 test_parse_attribute(&buf, 1, &unit, form, value);
4523 }
4524
4525 #[test]
4526 fn test_parse_attribute_strx2() {
4527 let buf = [0x01, 0x02, 0x99, 0x99];
4528 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4529 let form = constants::DW_FORM_strx2;
4530 let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(0x0201));
4531 test_parse_attribute(&buf, 2, &unit, form, value);
4532 }
4533
4534 #[test]
4535 fn test_parse_attribute_strx3() {
4536 let buf = [0x01, 0x02, 0x03, 0x99, 0x99];
4537 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4538 let form = constants::DW_FORM_strx3;
4539 let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(0x03_0201));
4540 test_parse_attribute(&buf, 3, &unit, form, value);
4541 }
4542
4543 #[test]
4544 fn test_parse_attribute_strx4() {
4545 let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99];
4546 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4547 let form = constants::DW_FORM_strx4;
4548 let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(0x0403_0201));
4549 test_parse_attribute(&buf, 4, &unit, form, value);
4550 }
4551
4552 #[test]
4553 fn test_parse_attribute_addrx() {
4554 let mut buf = Vec::new();
4555 buf.extend_from_slice(Leb128::unsigned(4097).bytes());
4556 let bytes_written = buf.len();
4557 buf.extend_from_slice(&[0; 10]);
4558
4559 let unit = test_parse_attribute_unit_default();
4560 let form = constants::DW_FORM_addrx;
4561 let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(4097));
4562 test_parse_attribute(&buf, bytes_written, &unit, form, value);
4563 }
4564
4565 #[test]
4566 fn test_parse_attribute_addrx1() {
4567 let buf = [0x01, 0x99, 0x99];
4568 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4569 let form = constants::DW_FORM_addrx1;
4570 let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(0x01));
4571 test_parse_attribute(&buf, 1, &unit, form, value);
4572 }
4573
4574 #[test]
4575 fn test_parse_attribute_addrx2() {
4576 let buf = [0x01, 0x02, 0x99, 0x99];
4577 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4578 let form = constants::DW_FORM_addrx2;
4579 let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(0x0201));
4580 test_parse_attribute(&buf, 2, &unit, form, value);
4581 }
4582
4583 #[test]
4584 fn test_parse_attribute_addrx3() {
4585 let buf = [0x01, 0x02, 0x03, 0x99, 0x99];
4586 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4587 let form = constants::DW_FORM_addrx3;
4588 let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(0x03_0201));
4589 test_parse_attribute(&buf, 3, &unit, form, value);
4590 }
4591
4592 #[test]
4593 fn test_parse_attribute_addrx4() {
4594 let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99];
4595 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4596 let form = constants::DW_FORM_addrx4;
4597 let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(0x0403_0201));
4598 test_parse_attribute(&buf, 4, &unit, form, value);
4599 }
4600
4601 #[test]
4602 fn test_parse_attribute_loclistx() {
4603 let mut buf = Vec::new();
4604 buf.extend_from_slice(Leb128::unsigned(4097).bytes());
4605 let bytes_written = buf.len();
4606 buf.extend_from_slice(&[0; 10]);
4607
4608 let unit = test_parse_attribute_unit_default();
4609 let form = constants::DW_FORM_loclistx;
4610 let value = AttributeValue::DebugLocListsIndex(DebugLocListsIndex(4097));
4611 test_parse_attribute(&buf, bytes_written, &unit, form, value);
4612 }
4613
4614 #[test]
4615 fn test_parse_attribute_rnglistx() {
4616 let mut buf = Vec::new();
4617 buf.extend_from_slice(Leb128::unsigned(4097).bytes());
4618 let bytes_written = buf.len();
4619 buf.extend_from_slice(&[0; 10]);
4620
4621 let unit = test_parse_attribute_unit_default();
4622 let form = constants::DW_FORM_rnglistx;
4623 let value = AttributeValue::DebugRngListsIndex(DebugRngListsIndex(4097));
4624 test_parse_attribute(&buf, bytes_written, &unit, form, value);
4625 }
4626
4627 #[test]
4628 fn test_parse_attribute_indirect() {
4629 let mut buf = Vec::new();
4630 buf.extend_from_slice(Leb128::unsigned(constants::DW_FORM_udata.0.into()).bytes());
4631 buf.extend_from_slice(Leb128::unsigned(9_999_999).bytes());
4632 let bytes_written = buf.len();
4633 buf.extend_from_slice(&[0; 10]);
4634
4635 let unit = test_parse_attribute_unit_default();
4636 let form = constants::DW_FORM_indirect;
4637 let value = AttributeValue::Udata(9_999_999);
4638 test_parse_attribute(&buf, bytes_written, &unit, form, value);
4639 }
4640
4641 #[test]
4642 fn test_parse_attribute_indirect_implicit_const() {
4643 let encoding = Encoding {
4644 format: Format::Dwarf32,
4645 version: 4,
4646 address_size: 4,
4647 };
4648 let mut buf = Vec::new();
4649 buf.extend_from_slice(Leb128::unsigned(constants::DW_FORM_implicit_const.0.into()).bytes());
4650 buf.extend_from_slice(&[0; 10]);
4651
4652 let input = &mut EndianSlice::new(&buf, LittleEndian);
4653 let spec =
4654 AttributeSpecification::new(constants::DW_AT_low_pc, constants::DW_FORM_indirect, None);
4655 assert_eq!(
4656 parse_attribute(input, encoding, spec),
4657 Err(Error::InvalidImplicitConst)
4658 );
4659 }
4660
4661 fn assert_entry_name<Endian>(
4662 entry: &DebuggingInformationEntry<EndianSlice<'_, Endian>>,
4663 name: &str,
4664 ) where
4665 Endian: Endianity,
4666 {
4667 let value = entry
4668 .attr_value(constants::DW_AT_name)
4669 .expect("Should have found the name attribute");
4670
4671 assert_eq!(
4672 value,
4673 AttributeValue::String(EndianSlice::new(name.as_bytes(), Endian::default()))
4674 );
4675 }
4676
4677 fn assert_current_name<Endian>(cursor: &EntriesCursor<'_, EndianSlice<'_, Endian>>, name: &str)
4678 where
4679 Endian: Endianity,
4680 {
4681 let entry = cursor.current().expect("Should have an entry result");
4682 assert_entry_name(entry, name);
4683 }
4684
4685 fn assert_next_entry<Endian>(
4686 cursor: &mut EntriesCursor<'_, EndianSlice<'_, Endian>>,
4687 name: &str,
4688 ) where
4689 Endian: Endianity,
4690 {
4691 assert!(cursor.next_entry().expect("Should parse next entry"));
4692 assert_current_name(cursor, name);
4693 }
4694
4695 fn assert_next_entry_null<Endian>(cursor: &mut EntriesCursor<'_, EndianSlice<'_, Endian>>)
4696 where
4697 Endian: Endianity,
4698 {
4699 assert!(cursor.next_entry().expect("Should parse next entry"));
4700 assert!(cursor.current().is_none());
4701 }
4702
4703 fn assert_next_dfs<Endian>(
4704 cursor: &mut EntriesCursor<'_, EndianSlice<'_, Endian>>,
4705 name: &str,
4706 depth: isize,
4707 ) where
4708 Endian: Endianity,
4709 {
4710 {
4711 let entry = cursor
4712 .next_dfs()
4713 .expect("Should parse next dfs")
4714 .expect("Should not be done with traversal");
4715 assert_eq!(entry.depth(), depth);
4716 assert_entry_name(entry, name);
4717 }
4718 assert_current_name(cursor, name);
4719 }
4720
4721 fn assert_next_sibling<Endian>(
4722 cursor: &mut EntriesCursor<'_, EndianSlice<'_, Endian>>,
4723 name: &str,
4724 depth: isize,
4725 ) where
4726 Endian: Endianity,
4727 {
4728 {
4729 let entry = cursor
4730 .next_sibling()
4731 .expect("Should parse next sibling")
4732 .expect("Should not be done with traversal");
4733 assert_eq!(entry.depth(), depth);
4734 assert_entry_name(entry, name);
4735 }
4736 assert_current_name(cursor, name);
4737 }
4738
4739 fn entries_cursor_tests_abbrev_buf() -> Vec<u8> {
4740 #[rustfmt::skip]
4741 let section = Section::with_endian(Endian::Little)
4742 .abbrev(1, DW_TAG_subprogram, DW_CHILDREN_yes)
4743 .abbrev_attr(DW_AT_name, DW_FORM_string)
4744 .abbrev_attr_null()
4745 .abbrev_null();
4746 section.get_contents().unwrap()
4747 }
4748
4749 fn entries_cursor_tests_debug_info_buf() -> Vec<u8> {
4750 #[rustfmt::skip]
4751 let section = Section::with_endian(Endian::Little)
4752 .die(1, |s| s.attr_string("001"))
4753 .die(1, |s| s.attr_string("002"))
4754 .die(1, |s| s.attr_string("003"))
4755 .die_null()
4756 .die_null()
4757 .die(1, |s| s.attr_string("004"))
4758 .die(1, |s| s.attr_string("005"))
4759 .die_null()
4760 .die(1, |s| s.attr_string("006"))
4761 .die_null()
4762 .die_null()
4763 .die(1, |s| s.attr_string("007"))
4764 .die(1, |s| s.attr_string("008"))
4765 .die(1, |s| s.attr_string("009"))
4766 .die_null()
4767 .die_null()
4768 .die_null()
4769 .die(1, |s| s.attr_string("010"))
4770 .die_null()
4771 .die_null();
4772 let entries_buf = section.get_contents().unwrap();
4773
4774 let encoding = Encoding {
4775 format: Format::Dwarf32,
4776 version: 4,
4777 address_size: 4,
4778 };
4779 let mut unit = UnitHeader {
4780 encoding,
4781 unit_length: 0,
4782 unit_type: UnitType::Compilation,
4783 debug_abbrev_offset: DebugAbbrevOffset(0),
4784 section: SectionId::DebugInfo,
4785 unit_offset: UnitSectionOffset(0),
4786 entries_buf: EndianSlice::new(&entries_buf, LittleEndian),
4787 };
4788 let section = Section::with_endian(Endian::Little).unit(&mut unit);
4789 section.get_contents().unwrap()
4790 }
4791
4792 #[test]
4793 fn test_cursor_next_entry_incomplete() {
4794 #[rustfmt::skip]
4795 let section = Section::with_endian(Endian::Little)
4796 .die(1, |s| s.attr_string("001"))
4797 .die(1, |s| s.attr_string("002"))
4798 .die(1, |s| s);
4799 let entries_buf = section.get_contents().unwrap();
4800
4801 let encoding = Encoding {
4802 format: Format::Dwarf32,
4803 version: 4,
4804 address_size: 4,
4805 };
4806 let mut unit = UnitHeader {
4807 encoding,
4808 unit_length: 0,
4809 unit_type: UnitType::Compilation,
4810 debug_abbrev_offset: DebugAbbrevOffset(0),
4811 section: SectionId::DebugInfo,
4812 unit_offset: UnitSectionOffset(0),
4813 entries_buf: EndianSlice::new(&entries_buf, LittleEndian),
4814 };
4815 let section = Section::with_endian(Endian::Little).unit(&mut unit);
4816 let info_buf = §ion.get_contents().unwrap();
4817 let debug_info = DebugInfo::new(info_buf, LittleEndian);
4818
4819 let unit = debug_info
4820 .units()
4821 .next()
4822 .expect("should have a unit result")
4823 .expect("and it should be ok");
4824
4825 let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
4826 let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
4827
4828 let abbrevs = unit
4829 .abbreviations(&debug_abbrev)
4830 .expect("Should parse abbreviations");
4831
4832 let mut cursor = unit.entries(&abbrevs);
4833
4834 assert_next_entry(&mut cursor, "001");
4835 assert_next_entry(&mut cursor, "002");
4836
4837 assert!(cursor.next_entry().is_err());
4839
4840 assert!(!cursor.next_entry().expect("Should parse next entry"));
4842 }
4843
4844 #[test]
4845 fn test_cursor_next_entry() {
4846 let info_buf = &entries_cursor_tests_debug_info_buf();
4847 let debug_info = DebugInfo::new(info_buf, LittleEndian);
4848
4849 let unit = debug_info
4850 .units()
4851 .next()
4852 .expect("should have a unit result")
4853 .expect("and it should be ok");
4854
4855 let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
4856 let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
4857
4858 let abbrevs = unit
4859 .abbreviations(&debug_abbrev)
4860 .expect("Should parse abbreviations");
4861
4862 let mut cursor = unit.entries(&abbrevs);
4863
4864 assert_next_entry(&mut cursor, "001");
4865 assert_next_entry(&mut cursor, "002");
4866 assert_next_entry(&mut cursor, "003");
4867 assert_next_entry_null(&mut cursor);
4868 assert_next_entry_null(&mut cursor);
4869 assert_next_entry(&mut cursor, "004");
4870 assert_next_entry(&mut cursor, "005");
4871 assert_next_entry_null(&mut cursor);
4872 assert_next_entry(&mut cursor, "006");
4873 assert_next_entry_null(&mut cursor);
4874 assert_next_entry_null(&mut cursor);
4875 assert_next_entry(&mut cursor, "007");
4876 assert_next_entry(&mut cursor, "008");
4877 assert_next_entry(&mut cursor, "009");
4878 assert_next_entry_null(&mut cursor);
4879 assert_next_entry_null(&mut cursor);
4880 assert_next_entry_null(&mut cursor);
4881 assert_next_entry(&mut cursor, "010");
4882 assert_next_entry_null(&mut cursor);
4883 assert_next_entry_null(&mut cursor);
4884
4885 assert!(!cursor.next_entry().expect("Should parse next entry"));
4886 assert!(cursor.current().is_none());
4887 }
4888
4889 #[test]
4890 fn test_cursor_next_dfs() {
4891 let info_buf = &entries_cursor_tests_debug_info_buf();
4892 let debug_info = DebugInfo::new(info_buf, LittleEndian);
4893
4894 let unit = debug_info
4895 .units()
4896 .next()
4897 .expect("should have a unit result")
4898 .expect("and it should be ok");
4899
4900 let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
4901 let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
4902
4903 let abbrevs = unit
4904 .abbreviations(&debug_abbrev)
4905 .expect("Should parse abbreviations");
4906
4907 let mut cursor = unit.entries(&abbrevs);
4908
4909 assert_next_dfs(&mut cursor, "001", 0);
4910 assert_next_dfs(&mut cursor, "002", 1);
4911 assert_next_dfs(&mut cursor, "003", 2);
4912 assert_next_dfs(&mut cursor, "004", 1);
4913 assert_next_dfs(&mut cursor, "005", 2);
4914 assert_next_dfs(&mut cursor, "006", 2);
4915 assert_next_dfs(&mut cursor, "007", 1);
4916 assert_next_dfs(&mut cursor, "008", 2);
4917 assert_next_dfs(&mut cursor, "009", 3);
4918 assert_next_dfs(&mut cursor, "010", 1);
4919
4920 assert!(cursor.next_dfs().expect("Should parse next dfs").is_none());
4921 assert!(cursor.current().is_none());
4922 }
4923
4924 #[test]
4925 fn test_cursor_next_sibling_no_sibling_ptr() {
4926 let info_buf = &entries_cursor_tests_debug_info_buf();
4927 let debug_info = DebugInfo::new(info_buf, LittleEndian);
4928
4929 let unit = debug_info
4930 .units()
4931 .next()
4932 .expect("should have a unit result")
4933 .expect("and it should be ok");
4934
4935 let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
4936 let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
4937
4938 let abbrevs = unit
4939 .abbreviations(&debug_abbrev)
4940 .expect("Should parse abbreviations");
4941
4942 let mut cursor = unit.entries(&abbrevs);
4943
4944 assert_next_dfs(&mut cursor, "001", 0);
4945
4946 assert_next_dfs(&mut cursor, "002", 1);
4949
4950 assert_next_sibling(&mut cursor, "004", 1);
4953 assert_next_sibling(&mut cursor, "007", 1);
4954 assert_next_sibling(&mut cursor, "010", 1);
4955
4956 assert!(
4959 cursor
4960 .next_sibling()
4961 .expect("Should parse next sibling")
4962 .is_none()
4963 );
4964 assert!(cursor.current().is_none());
4965 }
4966
4967 #[test]
4968 fn test_cursor_next_sibling_continuation() {
4969 let info_buf = &entries_cursor_tests_debug_info_buf();
4970 let debug_info = DebugInfo::new(info_buf, LittleEndian);
4971
4972 let unit = debug_info
4973 .units()
4974 .next()
4975 .expect("should have a unit result")
4976 .expect("and it should be ok");
4977
4978 let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
4979 let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
4980
4981 let abbrevs = unit
4982 .abbreviations(&debug_abbrev)
4983 .expect("Should parse abbreviations");
4984
4985 let mut cursor = unit.entries(&abbrevs);
4986
4987 assert_next_dfs(&mut cursor, "001", 0);
4988
4989 assert_next_dfs(&mut cursor, "002", 1);
4992
4993 assert_next_sibling(&mut cursor, "004", 1);
4996 assert_next_dfs(&mut cursor, "005", 2);
4997 assert_next_sibling(&mut cursor, "006", 2);
4998 assert!(
4999 cursor
5000 .next_sibling()
5001 .expect("Should parse next sibling")
5002 .is_none()
5003 );
5004 assert!(
5005 cursor
5006 .next_sibling()
5007 .expect("Should parse next sibling")
5008 .is_none()
5009 );
5010 assert!(
5011 cursor
5012 .next_sibling()
5013 .expect("Should parse next sibling")
5014 .is_none()
5015 );
5016 assert!(
5017 cursor
5018 .next_sibling()
5019 .expect("Should parse next sibling")
5020 .is_none()
5021 );
5022
5023 assert_next_dfs(&mut cursor, "007", 1);
5026 assert_next_sibling(&mut cursor, "010", 1);
5027
5028 assert!(
5031 cursor
5032 .next_sibling()
5033 .expect("Should parse next sibling")
5034 .is_none()
5035 );
5036 assert!(cursor.current().is_none());
5037 }
5038
5039 fn entries_cursor_sibling_abbrev_buf() -> Vec<u8> {
5040 #[rustfmt::skip]
5041 let section = Section::with_endian(Endian::Little)
5042 .abbrev(1, DW_TAG_subprogram, DW_CHILDREN_yes)
5043 .abbrev_attr(DW_AT_name, DW_FORM_string)
5044 .abbrev_attr(DW_AT_sibling, DW_FORM_ref1)
5045 .abbrev_attr_null()
5046 .abbrev(2, DW_TAG_subprogram, DW_CHILDREN_yes)
5047 .abbrev_attr(DW_AT_name, DW_FORM_string)
5048 .abbrev_attr_null()
5049 .abbrev_null();
5050 section.get_contents().unwrap()
5051 }
5052
5053 fn entries_cursor_sibling_entries_buf(header_size: usize) -> Vec<u8> {
5054 let start = Label::new();
5055 let sibling004_ref = Label::new();
5056 let sibling004 = Label::new();
5057 let sibling009_ref = Label::new();
5058 let sibling009 = Label::new();
5059
5060 #[rustfmt::skip]
5061 let section = Section::with_endian(Endian::Little)
5062 .mark(&start)
5063 .die(2, |s| s.attr_string("001"))
5064 .die(1, |s| s.attr_string("002").D8(&sibling004_ref))
5066 .die(10, |s| s.attr_string("003"))
5068 .die_null()
5069 .die_null()
5070 .mark(&sibling004)
5071 .die(1, |s| s.attr_string("004").attr_ref1(255))
5073 .die(2, |s| s.attr_string("005"))
5074 .die_null()
5075 .die_null()
5076 .die(2, |s| s.attr_string("006"))
5078 .die(1, |s| s.attr_string("007").D8(&sibling009_ref))
5080 .die(10, |s| s.attr_string("008"))
5082 .die_null()
5083 .die_null()
5084 .mark(&sibling009)
5085 .die(2, |s| s.attr_string("009"))
5086 .die_null()
5087 .die_null()
5088 .die(2, |s| s.attr_string("010"))
5090 .die(2, |s| s.attr_string("011"))
5091 .die_null()
5092 .die_null()
5093 .die_null();
5094
5095 let offset = header_size as u64 + (&sibling004 - &start) as u64;
5096 sibling004_ref.set_const(offset);
5097
5098 let offset = header_size as u64 + (&sibling009 - &start) as u64;
5099 sibling009_ref.set_const(offset);
5100
5101 section.get_contents().unwrap()
5102 }
5103
5104 fn test_cursor_next_sibling_with_ptr(
5105 cursor: &mut EntriesCursor<'_, EndianSlice<'_, LittleEndian>>,
5106 ) {
5107 assert_next_dfs(cursor, "001", 0);
5108
5109 assert_next_dfs(cursor, "002", 1);
5112
5113 assert_next_sibling(cursor, "004", 1);
5116 assert_next_sibling(cursor, "006", 1);
5117 assert_next_sibling(cursor, "010", 1);
5118
5119 assert!(
5122 cursor
5123 .next_sibling()
5124 .expect("Should parse next sibling")
5125 .is_none()
5126 );
5127 assert!(cursor.current().is_none());
5128 }
5129
5130 #[test]
5131 fn test_debug_info_next_sibling_with_ptr() {
5132 let encoding = Encoding {
5133 format: Format::Dwarf32,
5134 version: 4,
5135 address_size: 4,
5136 };
5137
5138 let mut unit = UnitHeader {
5139 encoding,
5140 unit_length: 0,
5141 unit_type: UnitType::Compilation,
5142 debug_abbrev_offset: DebugAbbrevOffset(0),
5143 section: SectionId::DebugInfo,
5144 unit_offset: UnitSectionOffset(0),
5145 entries_buf: EndianSlice::new(&[], LittleEndian),
5146 };
5147 let header_size = unit.size_of_header();
5148 let entries_buf = entries_cursor_sibling_entries_buf(header_size);
5149 unit.entries_buf = EndianSlice::new(&entries_buf, LittleEndian);
5150 let section = Section::with_endian(Endian::Little).unit(&mut unit);
5151 let info_buf = section.get_contents().unwrap();
5152 let debug_info = DebugInfo::new(&info_buf, LittleEndian);
5153
5154 let unit = debug_info
5155 .units()
5156 .next()
5157 .expect("should have a unit result")
5158 .expect("and it should be ok");
5159
5160 let abbrev_buf = entries_cursor_sibling_abbrev_buf();
5161 let debug_abbrev = DebugAbbrev::new(&abbrev_buf, LittleEndian);
5162
5163 let abbrevs = unit
5164 .abbreviations(&debug_abbrev)
5165 .expect("Should parse abbreviations");
5166
5167 let mut cursor = unit.entries(&abbrevs);
5168 test_cursor_next_sibling_with_ptr(&mut cursor);
5169 }
5170
5171 #[test]
5172 fn test_debug_types_next_sibling_with_ptr() {
5173 let encoding = Encoding {
5174 format: Format::Dwarf32,
5175 version: 4,
5176 address_size: 4,
5177 };
5178 let mut unit = UnitHeader {
5179 encoding,
5180 unit_length: 0,
5181 unit_type: UnitType::Type {
5182 type_signature: DebugTypeSignature(0),
5183 type_offset: UnitOffset(0),
5184 },
5185 debug_abbrev_offset: DebugAbbrevOffset(0),
5186 section: SectionId::DebugTypes,
5187 unit_offset: UnitSectionOffset(0),
5188 entries_buf: EndianSlice::new(&[], LittleEndian),
5189 };
5190 let header_size = unit.size_of_header();
5191 let entries_buf = entries_cursor_sibling_entries_buf(header_size);
5192 unit.entries_buf = EndianSlice::new(&entries_buf, LittleEndian);
5193 let section = Section::with_endian(Endian::Little).unit(&mut unit);
5194 let info_buf = section.get_contents().unwrap();
5195 let debug_types = DebugTypes::new(&info_buf, LittleEndian);
5196
5197 let unit = debug_types
5198 .units()
5199 .next()
5200 .expect("should have a unit result")
5201 .expect("and it should be ok");
5202
5203 let abbrev_buf = entries_cursor_sibling_abbrev_buf();
5204 let debug_abbrev = DebugAbbrev::new(&abbrev_buf, LittleEndian);
5205
5206 let abbrevs = unit
5207 .abbreviations(&debug_abbrev)
5208 .expect("Should parse abbreviations");
5209
5210 let mut cursor = unit.entries(&abbrevs);
5211 test_cursor_next_sibling_with_ptr(&mut cursor);
5212 }
5213
5214 #[test]
5215 fn test_entries_at_offset() {
5216 let info_buf = &entries_cursor_tests_debug_info_buf();
5217 let debug_info = DebugInfo::new(info_buf, LittleEndian);
5218
5219 let unit = debug_info
5220 .units()
5221 .next()
5222 .expect("should have a unit result")
5223 .expect("and it should be ok");
5224
5225 let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
5226 let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
5227
5228 let abbrevs = unit
5229 .abbreviations(&debug_abbrev)
5230 .expect("Should parse abbreviations");
5231
5232 let mut cursor = unit
5233 .entries_at_offset(&abbrevs, UnitOffset(unit.header_size()))
5234 .unwrap();
5235 assert_next_entry(&mut cursor, "001");
5236
5237 let cursor = unit.entries_at_offset(&abbrevs, UnitOffset(0));
5238 match cursor {
5239 Err(Error::OffsetOutOfBounds(0)) => {}
5240 otherwise => {
5241 panic!("Unexpected parse result = {:#?}", otherwise);
5242 }
5243 }
5244 }
5245
5246 fn entries_tree_tests_debug_abbrevs_buf() -> Vec<u8> {
5247 #[rustfmt::skip]
5248 let section = Section::with_endian(Endian::Little)
5249 .abbrev(1, DW_TAG_subprogram, DW_CHILDREN_yes)
5250 .abbrev_attr(DW_AT_name, DW_FORM_string)
5251 .abbrev_attr_null()
5252 .abbrev(2, DW_TAG_subprogram, DW_CHILDREN_no)
5253 .abbrev_attr(DW_AT_name, DW_FORM_string)
5254 .abbrev_attr_null()
5255 .abbrev_null()
5256 .get_contents()
5257 .unwrap();
5258 section
5259 }
5260
5261 fn entries_tree_tests_debug_info_buf(header_size: usize) -> (Vec<u8>, UnitOffset) {
5262 let start = Label::new();
5263 let entry2 = Label::new();
5264 #[rustfmt::skip]
5265 let section = Section::with_endian(Endian::Little)
5266 .mark(&start)
5267 .die(1, |s| s.attr_string("root"))
5268 .die(1, |s| s.attr_string("1"))
5269 .die(1, |s| s.attr_string("1a"))
5270 .die_null()
5271 .die(2, |s| s.attr_string("1b"))
5272 .die_null()
5273 .mark(&entry2)
5274 .die(1, |s| s.attr_string("2"))
5275 .die(1, |s| s.attr_string("2a"))
5276 .die(1, |s| s.attr_string("2a1"))
5277 .die_null()
5278 .die_null()
5279 .die(1, |s| s.attr_string("2b"))
5280 .die(2, |s| s.attr_string("2b1"))
5281 .die_null()
5282 .die_null()
5283 .die(1, |s| s.attr_string("3"))
5284 .die(1, |s| s.attr_string("3a"))
5285 .die(2, |s| s.attr_string("3a1"))
5286 .die(2, |s| s.attr_string("3a2"))
5287 .die_null()
5288 .die(2, |s| s.attr_string("3b"))
5289 .die_null()
5290 .die(2, |s| s.attr_string("final"))
5291 .die_null()
5292 .get_contents()
5293 .unwrap();
5294 let entry2 = UnitOffset(header_size + (&entry2 - &start) as usize);
5295 (section, entry2)
5296 }
5297
5298 #[test]
5299 fn test_entries_tree() {
5300 fn assert_entry<'input, 'abbrev, 'tree, Endian>(
5301 node: Result<Option<EntriesTreeNode<'abbrev, 'tree, EndianSlice<'input, Endian>>>>,
5302 name: &str,
5303 ) -> EntriesTreeIter<'abbrev, 'tree, EndianSlice<'input, Endian>>
5304 where
5305 Endian: Endianity,
5306 {
5307 let node = node
5308 .expect("Should parse entry")
5309 .expect("Should have entry");
5310 assert_entry_name(node.entry(), name);
5311 node.children()
5312 }
5313
5314 fn assert_null<E: Endianity>(
5315 node: Result<Option<EntriesTreeNode<'_, '_, EndianSlice<'_, E>>>>,
5316 ) {
5317 match node {
5318 Ok(None) => {}
5319 otherwise => {
5320 panic!("Unexpected parse result = {:#?}", otherwise);
5321 }
5322 }
5323 }
5324
5325 let abbrevs_buf = entries_tree_tests_debug_abbrevs_buf();
5326 let debug_abbrev = DebugAbbrev::new(&abbrevs_buf, LittleEndian);
5327
5328 let encoding = Encoding {
5329 format: Format::Dwarf32,
5330 version: 4,
5331 address_size: 4,
5332 };
5333 let mut unit = UnitHeader {
5334 encoding,
5335 unit_length: 0,
5336 unit_type: UnitType::Compilation,
5337 debug_abbrev_offset: DebugAbbrevOffset(0),
5338 section: SectionId::DebugInfo,
5339 unit_offset: UnitSectionOffset(0),
5340 entries_buf: EndianSlice::new(&[], LittleEndian),
5341 };
5342 let header_size = unit.size_of_header();
5343 let (entries_buf, entry2) = entries_tree_tests_debug_info_buf(header_size);
5344 unit.entries_buf = EndianSlice::new(&entries_buf, LittleEndian);
5345 let info_buf = Section::with_endian(Endian::Little)
5346 .unit(&mut unit)
5347 .get_contents()
5348 .unwrap();
5349 let debug_info = DebugInfo::new(&info_buf, LittleEndian);
5350
5351 let unit = debug_info
5352 .units()
5353 .next()
5354 .expect("Should parse unit")
5355 .expect("and it should be some");
5356 let abbrevs = unit
5357 .abbreviations(&debug_abbrev)
5358 .expect("Should parse abbreviations");
5359 let mut tree = unit
5360 .entries_tree(&abbrevs, None)
5361 .expect("Should have entries tree");
5362
5363 {
5365 let mut iter = assert_entry(tree.root().map(Some), "root");
5366 assert_entry(iter.next(), "1");
5367 }
5368 {
5369 let mut iter = assert_entry(tree.root().map(Some), "root");
5370 assert_entry(iter.next(), "1");
5371 }
5372
5373 let mut iter = assert_entry(tree.root().map(Some), "root");
5374 {
5375 let mut iter = assert_entry(iter.next(), "1");
5377 {
5378 let mut iter = assert_entry(iter.next(), "1a");
5380 assert_null(iter.next());
5381 assert_null(iter.next());
5382 }
5383 {
5384 let mut iter = assert_entry(iter.next(), "1b");
5386 assert_null(iter.next());
5387 assert_null(iter.next());
5388 }
5389 assert_null(iter.next());
5390 assert_null(iter.next());
5391 }
5392 {
5393 let mut iter = assert_entry(iter.next(), "2");
5395 assert_entry(iter.next(), "2a");
5396 assert_entry(iter.next(), "2b");
5397 assert_null(iter.next());
5398 }
5399 {
5400 let mut iter = assert_entry(iter.next(), "3");
5402 {
5403 let mut iter = assert_entry(iter.next(), "3a");
5404 assert_entry(iter.next(), "3a1");
5405 }
5407 assert_entry(iter.next(), "3b");
5408 assert_null(iter.next());
5409 }
5410 assert_entry(iter.next(), "final");
5411 assert_null(iter.next());
5412
5413 let mut tree = unit
5415 .entries_tree(&abbrevs, Some(entry2))
5416 .expect("Should have entries tree");
5417 let mut iter = assert_entry(tree.root().map(Some), "2");
5418 assert_entry(iter.next(), "2a");
5419 assert_entry(iter.next(), "2b");
5420 assert_null(iter.next());
5421 }
5422
5423 #[test]
5424 fn test_entries_raw() {
5425 fn assert_abbrev<'abbrev, Endian>(
5426 entries: &mut EntriesRaw<'abbrev, EndianSlice<'_, Endian>>,
5427 tag: DwTag,
5428 ) -> &'abbrev Abbreviation
5429 where
5430 Endian: Endianity,
5431 {
5432 let abbrev = entries
5433 .read_abbreviation()
5434 .expect("Should parse abbrev")
5435 .expect("Should have abbrev");
5436 assert_eq!(abbrev.tag(), tag);
5437 abbrev
5438 }
5439
5440 fn assert_null<Endian>(entries: &mut EntriesRaw<'_, EndianSlice<'_, Endian>>)
5441 where
5442 Endian: Endianity,
5443 {
5444 match entries.read_abbreviation() {
5445 Ok(None) => {}
5446 otherwise => {
5447 panic!("Unexpected parse result = {:#?}", otherwise);
5448 }
5449 }
5450 }
5451
5452 fn assert_attr<Endian>(
5453 entries: &mut EntriesRaw<'_, EndianSlice<'_, Endian>>,
5454 spec: Option<AttributeSpecification>,
5455 name: DwAt,
5456 value: &str,
5457 ) where
5458 Endian: Endianity,
5459 {
5460 let spec = spec.expect("Should have attribute specification");
5461 let attr = entries
5462 .read_attribute(spec)
5463 .expect("Should parse attribute");
5464 assert_eq!(attr.name(), name);
5465 assert_eq!(
5466 attr.value(),
5467 AttributeValue::String(EndianSlice::new(value.as_bytes(), Endian::default()))
5468 );
5469 }
5470
5471 #[rustfmt::skip]
5472 let section = Section::with_endian(Endian::Little)
5473 .abbrev(1, DW_TAG_subprogram, DW_CHILDREN_yes)
5474 .abbrev_attr(DW_AT_name, DW_FORM_string)
5475 .abbrev_attr(DW_AT_linkage_name, DW_FORM_string)
5476 .abbrev_attr_null()
5477 .abbrev(2, DW_TAG_variable, DW_CHILDREN_no)
5478 .abbrev_attr(DW_AT_name, DW_FORM_string)
5479 .abbrev_attr_null()
5480 .abbrev_null();
5481 let abbrevs_buf = section.get_contents().unwrap();
5482 let debug_abbrev = DebugAbbrev::new(&abbrevs_buf, LittleEndian);
5483
5484 #[rustfmt::skip]
5485 let section = Section::with_endian(Endian::Little)
5486 .die(1, |s| s.attr_string("f1").attr_string("l1"))
5487 .die(2, |s| s.attr_string("v1"))
5488 .die(2, |s| s.attr_string("v2"))
5489 .die(1, |s| s.attr_string("f2").attr_string("l2"))
5490 .die_null()
5491 .die_null();
5492 let entries_buf = section.get_contents().unwrap();
5493
5494 let encoding = Encoding {
5495 format: Format::Dwarf32,
5496 version: 4,
5497 address_size: 4,
5498 };
5499 let mut unit = UnitHeader {
5500 encoding,
5501 unit_length: 0,
5502 unit_type: UnitType::Compilation,
5503 debug_abbrev_offset: DebugAbbrevOffset(0),
5504 section: SectionId::DebugInfo,
5505 unit_offset: UnitSectionOffset(0),
5506 entries_buf: EndianSlice::new(&entries_buf, LittleEndian),
5507 };
5508 let section = Section::with_endian(Endian::Little).unit(&mut unit);
5509 let info_buf = section.get_contents().unwrap();
5510 let debug_info = DebugInfo::new(&info_buf, LittleEndian);
5511
5512 let unit = debug_info
5513 .units()
5514 .next()
5515 .expect("should have a unit result")
5516 .expect("and it should be ok");
5517
5518 let abbrevs = unit
5519 .abbreviations(&debug_abbrev)
5520 .expect("Should parse abbreviations");
5521
5522 let mut entries = unit
5523 .entries_raw(&abbrevs, None)
5524 .expect("Should have entries");
5525
5526 assert_eq!(entries.next_depth(), 0);
5527 let abbrev = assert_abbrev(&mut entries, DW_TAG_subprogram);
5528 let mut attrs = abbrev.attributes().iter().copied();
5529 assert_attr(&mut entries, attrs.next(), DW_AT_name, "f1");
5530 assert_attr(&mut entries, attrs.next(), DW_AT_linkage_name, "l1");
5531 assert!(attrs.next().is_none());
5532
5533 assert_eq!(entries.next_depth(), 1);
5534 let abbrev = assert_abbrev(&mut entries, DW_TAG_variable);
5535 let mut attrs = abbrev.attributes().iter().copied();
5536 assert_attr(&mut entries, attrs.next(), DW_AT_name, "v1");
5537 assert!(attrs.next().is_none());
5538
5539 assert_eq!(entries.next_depth(), 1);
5540 let abbrev = assert_abbrev(&mut entries, DW_TAG_variable);
5541 let mut attrs = abbrev.attributes().iter().copied();
5542 assert_attr(&mut entries, attrs.next(), DW_AT_name, "v2");
5543 assert!(attrs.next().is_none());
5544
5545 assert_eq!(entries.next_depth(), 1);
5546 let abbrev = assert_abbrev(&mut entries, DW_TAG_subprogram);
5547 let mut attrs = abbrev.attributes().iter().copied();
5548 assert_attr(&mut entries, attrs.next(), DW_AT_name, "f2");
5549 assert_attr(&mut entries, attrs.next(), DW_AT_linkage_name, "l2");
5550 assert!(attrs.next().is_none());
5551
5552 assert_eq!(entries.next_depth(), 2);
5553 assert_null(&mut entries);
5554
5555 assert_eq!(entries.next_depth(), 1);
5556 assert_null(&mut entries);
5557
5558 assert_eq!(entries.next_depth(), 0);
5559 assert!(entries.is_empty());
5560 }
5561
5562 #[test]
5563 fn test_debug_info_offset() {
5564 let padding = &[0; 10];
5565 let entries = &[0; 20];
5566 let encoding = Encoding {
5567 format: Format::Dwarf32,
5568 version: 4,
5569 address_size: 4,
5570 };
5571 let mut unit = UnitHeader {
5572 encoding,
5573 unit_length: 0,
5574 unit_type: UnitType::Compilation,
5575 debug_abbrev_offset: DebugAbbrevOffset(0),
5576 section: SectionId::DebugInfo,
5577 unit_offset: UnitSectionOffset(0),
5578 entries_buf: EndianSlice::new(entries, LittleEndian),
5579 };
5580 Section::with_endian(Endian::Little)
5581 .append_bytes(padding)
5582 .unit(&mut unit);
5583 let offset = padding.len();
5584 let header_length = unit.size_of_header();
5585 let length = unit.length_including_self();
5586 assert_eq!(DebugInfoOffset(0).to_unit_offset(&unit), None);
5587 assert_eq!(DebugInfoOffset(offset - 1).to_unit_offset(&unit), None);
5588 assert_eq!(DebugInfoOffset(offset).to_unit_offset(&unit), None);
5589 assert_eq!(
5590 DebugInfoOffset(offset + header_length - 1).to_unit_offset(&unit),
5591 None
5592 );
5593 assert_eq!(
5594 DebugInfoOffset(offset + header_length).to_unit_offset(&unit),
5595 Some(UnitOffset(header_length))
5596 );
5597 assert_eq!(
5598 DebugInfoOffset(offset + length - 1).to_unit_offset(&unit),
5599 Some(UnitOffset(length - 1))
5600 );
5601 assert_eq!(DebugInfoOffset(offset + length).to_unit_offset(&unit), None);
5602 assert_eq!(
5603 UnitOffset(header_length).to_debug_info_offset(&unit),
5604 Some(DebugInfoOffset(offset + header_length))
5605 );
5606 assert_eq!(
5607 UnitOffset(length - 1).to_debug_info_offset(&unit),
5608 Some(DebugInfoOffset(offset + length - 1))
5609 );
5610 }
5611
5612 #[test]
5613 fn test_debug_types_offset() {
5614 let padding = &[0; 10];
5615 let entries = &[0; 20];
5616 let encoding = Encoding {
5617 format: Format::Dwarf32,
5618 version: 4,
5619 address_size: 4,
5620 };
5621 let mut unit = UnitHeader {
5622 encoding,
5623 unit_length: 0,
5624 unit_type: UnitType::Type {
5625 type_signature: DebugTypeSignature(0),
5626 type_offset: UnitOffset(0),
5627 },
5628 debug_abbrev_offset: DebugAbbrevOffset(0),
5629 section: SectionId::DebugTypes,
5630 unit_offset: UnitSectionOffset(0),
5631 entries_buf: EndianSlice::new(entries, LittleEndian),
5632 };
5633 Section::with_endian(Endian::Little)
5634 .append_bytes(padding)
5635 .unit(&mut unit);
5636 let offset = padding.len();
5637 let header_length = unit.size_of_header();
5638 let length = unit.length_including_self();
5639 assert_eq!(DebugTypesOffset(0).to_unit_offset(&unit), None);
5640 assert_eq!(DebugTypesOffset(offset - 1).to_unit_offset(&unit), None);
5641 assert_eq!(DebugTypesOffset(offset).to_unit_offset(&unit), None);
5642 assert_eq!(
5643 DebugTypesOffset(offset + header_length - 1).to_unit_offset(&unit),
5644 None
5645 );
5646 assert_eq!(
5647 DebugTypesOffset(offset + header_length).to_unit_offset(&unit),
5648 Some(UnitOffset(header_length))
5649 );
5650 assert_eq!(
5651 DebugTypesOffset(offset + length - 1).to_unit_offset(&unit),
5652 Some(UnitOffset(length - 1))
5653 );
5654 assert_eq!(
5655 DebugTypesOffset(offset + length).to_unit_offset(&unit),
5656 None
5657 );
5658 assert_eq!(
5659 UnitOffset(header_length).to_debug_types_offset(&unit),
5660 Some(DebugTypesOffset(offset + header_length))
5661 );
5662 assert_eq!(
5663 UnitOffset(length - 1).to_debug_types_offset(&unit),
5664 Some(DebugTypesOffset(offset + length - 1))
5665 );
5666 }
5667
5668 #[test]
5669 fn test_length_including_self() {
5670 let encoding = Encoding {
5671 format: Format::Dwarf32,
5672 version: 4,
5673 address_size: 4,
5674 };
5675 let mut unit = UnitHeader {
5676 encoding,
5677 unit_length: 0,
5678 unit_type: UnitType::Compilation,
5679 debug_abbrev_offset: DebugAbbrevOffset(0),
5680 section: SectionId::DebugInfo,
5681 unit_offset: UnitSectionOffset(0),
5682 entries_buf: EndianSlice::new(&[], LittleEndian),
5683 };
5684 unit.encoding.format = Format::Dwarf32;
5685 assert_eq!(unit.length_including_self(), 4);
5686 unit.encoding.format = Format::Dwarf64;
5687 assert_eq!(unit.length_including_self(), 12);
5688 unit.unit_length = 10;
5689 assert_eq!(unit.length_including_self(), 22);
5690 }
5691
5692 #[test]
5693 fn test_parse_type_unit_abbrevs() {
5694 let types_buf = [
5695 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, ];
5716 let debug_types = DebugTypes::new(&types_buf, LittleEndian);
5717
5718 let abbrev_buf = [
5719 0x01, 0x2e, 0x01, 0x03, 0x08, 0x00, 0x00, 0x00, ];
5728
5729 let get_some_type_unit = || debug_types.units().next().unwrap().unwrap();
5730
5731 let unit = get_some_type_unit();
5732
5733 let read_debug_abbrev_section_somehow = || &abbrev_buf;
5734 let debug_abbrev = DebugAbbrev::new(read_debug_abbrev_section_somehow(), LittleEndian);
5735 let _abbrevs_for_unit = unit.abbreviations(&debug_abbrev).unwrap();
5736 }
5737}