1use core::cell::Cell;
4use core::ops::{Range, RangeFrom, RangeTo};
5
6use crate::common::{
7 DebugAbbrevOffset, DebugAddrBase, DebugAddrIndex, DebugInfoOffset, DebugLineOffset,
8 DebugLineStrOffset, DebugLocListsBase, DebugLocListsIndex, DebugMacinfoOffset,
9 DebugMacroOffset, DebugRngListsBase, DebugRngListsIndex, DebugStrOffset, DebugStrOffsetsBase,
10 DebugStrOffsetsIndex, DebugTypeSignature, DebugTypesOffset, DwoId, Encoding, Format,
11 LocationListsOffset, RawRangeListsOffset, SectionId, UnitSectionOffset,
12};
13use crate::constants;
14use crate::endianity::Endianity;
15use crate::read::abbrev::get_attribute_size;
16use crate::read::{
17 Abbreviation, Abbreviations, AttributeSpecification, DebugAbbrev, DebugStr, EndianSlice, Error,
18 Expression, Reader, ReaderOffset, Result, Section, UnitOffset,
19};
20
21impl<T: ReaderOffset> DebugTypesOffset<T> {
22 pub fn to_unit_offset<R>(&self, unit: &UnitHeader<R>) -> Option<UnitOffset<T>>
26 where
27 R: Reader<Offset = T>,
28 {
29 let unit_offset = unit.offset().as_debug_types_offset()?;
30 let offset = UnitOffset(self.0.checked_sub(unit_offset.0)?);
31 if !unit.is_valid_offset(offset) {
32 return None;
33 }
34 Some(offset)
35 }
36}
37
38impl<T: ReaderOffset> DebugInfoOffset<T> {
39 pub fn to_unit_offset<R>(&self, unit: &UnitHeader<R>) -> Option<UnitOffset<T>>
43 where
44 R: Reader<Offset = T>,
45 {
46 let unit_offset = unit.offset().as_debug_info_offset()?;
47 let offset = UnitOffset(self.0.checked_sub(unit_offset.0)?);
48 if !unit.is_valid_offset(offset) {
49 return None;
50 }
51 Some(offset)
52 }
53}
54
55impl<T: ReaderOffset> UnitOffset<T> {
56 pub fn to_debug_info_offset<R>(&self, unit: &UnitHeader<R>) -> Option<DebugInfoOffset<T>>
60 where
61 R: Reader<Offset = T>,
62 {
63 let unit_offset = unit.offset().as_debug_info_offset()?;
64 Some(DebugInfoOffset(unit_offset.0 + self.0))
65 }
66
67 pub fn to_debug_types_offset<R>(&self, unit: &UnitHeader<R>) -> Option<DebugTypesOffset<T>>
71 where
72 R: Reader<Offset = T>,
73 {
74 let unit_offset = unit.offset().as_debug_types_offset()?;
75 Some(DebugTypesOffset(unit_offset.0 + self.0))
76 }
77}
78
79#[derive(Debug, Default, Clone, Copy)]
82pub struct DebugInfo<R> {
83 debug_info_section: R,
84}
85
86impl<'input, Endian> DebugInfo<EndianSlice<'input, Endian>>
87where
88 Endian: Endianity,
89{
90 pub fn new(debug_info_section: &'input [u8], endian: Endian) -> Self {
105 Self::from(EndianSlice::new(debug_info_section, endian))
106 }
107}
108
109impl<R: Reader> DebugInfo<R> {
110 pub fn units(&self) -> DebugInfoUnitHeadersIter<R> {
128 DebugInfoUnitHeadersIter {
129 input: self.debug_info_section.clone(),
130 offset: DebugInfoOffset(R::Offset::from_u8(0)),
131 }
132 }
133
134 pub fn header_from_offset(&self, offset: DebugInfoOffset<R::Offset>) -> Result<UnitHeader<R>> {
138 let input = &mut self.debug_info_section.clone();
139 input.skip(offset.0)?;
140 parse_unit_header(input, offset.into())
141 }
142}
143
144impl<T> DebugInfo<T> {
145 pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugInfo<R>
151 where
152 F: FnMut(&'a T) -> R,
153 {
154 borrow(&self.debug_info_section).into()
155 }
156}
157
158impl<R> Section<R> for DebugInfo<R> {
159 fn id() -> SectionId {
160 SectionId::DebugInfo
161 }
162
163 fn reader(&self) -> &R {
164 &self.debug_info_section
165 }
166}
167
168impl<R> From<R> for DebugInfo<R> {
169 fn from(debug_info_section: R) -> Self {
170 DebugInfo { debug_info_section }
171 }
172}
173
174#[derive(Clone, Debug)]
179pub struct DebugInfoUnitHeadersIter<R: Reader> {
180 input: R,
181 offset: DebugInfoOffset<R::Offset>,
182}
183
184impl<R: Reader> DebugInfoUnitHeadersIter<R> {
185 pub fn next(&mut self) -> Result<Option<UnitHeader<R>>> {
187 if self.input.is_empty() {
188 Ok(None)
189 } else {
190 let len = self.input.len();
191 match parse_unit_header(&mut self.input, self.offset.into()) {
192 Ok(header) => {
193 self.offset.0 += len - self.input.len();
194 Ok(Some(header))
195 }
196 Err(e) => {
197 self.input.empty();
198 Err(e)
199 }
200 }
201 }
202 }
203}
204
205#[cfg(feature = "fallible-iterator")]
206impl<R: Reader> fallible_iterator::FallibleIterator for DebugInfoUnitHeadersIter<R> {
207 type Item = UnitHeader<R>;
208 type Error = Error;
209
210 fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
211 DebugInfoUnitHeadersIter::next(self)
212 }
213}
214
215fn parse_unit_type<R: Reader>(input: &mut R) -> Result<constants::DwUt> {
217 let val = input.read_u8()?;
218 Ok(constants::DwUt(val))
219}
220
221fn parse_debug_abbrev_offset<R: Reader>(
223 input: &mut R,
224 format: Format,
225) -> Result<DebugAbbrevOffset<R::Offset>> {
226 input.read_offset(format).map(DebugAbbrevOffset)
227}
228
229pub(crate) fn parse_debug_info_offset<R: Reader>(
231 input: &mut R,
232 format: Format,
233) -> Result<DebugInfoOffset<R::Offset>> {
234 input.read_offset(format).map(DebugInfoOffset)
235}
236
237#[derive(Debug, Clone, Copy, PartialEq, Eq)]
241pub enum UnitType<Offset>
242where
243 Offset: ReaderOffset,
244{
245 Compilation,
248 Type {
251 type_signature: DebugTypeSignature,
253 type_offset: UnitOffset<Offset>,
255 },
256 Partial,
259 Skeleton(DwoId),
265 SplitCompilation(DwoId),
271 SplitType {
274 type_signature: DebugTypeSignature,
276 type_offset: UnitOffset<Offset>,
278 },
279}
280
281impl<Offset> UnitType<Offset>
282where
283 Offset: ReaderOffset,
284{
285 #[allow(unused)]
288 pub(crate) fn dw_ut(&self) -> constants::DwUt {
289 match self {
290 UnitType::Compilation => constants::DW_UT_compile,
291 UnitType::Type { .. } => constants::DW_UT_type,
292 UnitType::Partial => constants::DW_UT_partial,
293 UnitType::Skeleton(_) => constants::DW_UT_skeleton,
294 UnitType::SplitCompilation(_) => constants::DW_UT_split_compile,
295 UnitType::SplitType { .. } => constants::DW_UT_split_type,
296 }
297 }
298}
299
300#[derive(Debug, Clone, Copy, PartialEq, Eq)]
303pub struct UnitHeader<R, Offset = <R as Reader>::Offset>
304where
305 R: Reader<Offset = Offset>,
306 Offset: ReaderOffset,
307{
308 encoding: Encoding,
309 unit_length: Offset,
310 unit_type: UnitType<Offset>,
311 debug_abbrev_offset: DebugAbbrevOffset<Offset>,
312 unit_offset: UnitSectionOffset<Offset>,
313 entries_buf: R,
314}
315
316impl<R, Offset> UnitHeader<R, Offset>
318where
319 R: Reader<Offset = Offset>,
320 Offset: ReaderOffset,
321{
322 pub fn new(
324 encoding: Encoding,
325 unit_length: Offset,
326 unit_type: UnitType<Offset>,
327 debug_abbrev_offset: DebugAbbrevOffset<Offset>,
328 unit_offset: UnitSectionOffset<Offset>,
329 entries_buf: R,
330 ) -> Self {
331 UnitHeader {
332 encoding,
333 unit_length,
334 unit_type,
335 debug_abbrev_offset,
336 unit_offset,
337 entries_buf,
338 }
339 }
340}
341
342impl<R, Offset> UnitHeader<R, Offset>
344where
345 R: Reader<Offset = Offset>,
346 Offset: ReaderOffset,
347{
348 pub fn offset(&self) -> UnitSectionOffset<Offset> {
350 self.unit_offset
351 }
352
353 pub fn size_of_header(&self) -> usize {
356 let unit_length_size = self.encoding.format.initial_length_size() as usize;
357 let version_size = 2;
358 let debug_abbrev_offset_size = self.encoding.format.word_size() as usize;
359 let address_size_size = 1;
360 let unit_type_size = if self.encoding.version == 5 { 1 } else { 0 };
361 let type_specific_size = match self.unit_type {
362 UnitType::Compilation | UnitType::Partial => 0,
363 UnitType::Type { .. } | UnitType::SplitType { .. } => {
364 let type_signature_size = 8;
365 let type_offset_size = self.encoding.format.word_size() as usize;
366 type_signature_size + type_offset_size
367 }
368 UnitType::Skeleton(_) | UnitType::SplitCompilation(_) => 8,
369 };
370
371 unit_length_size
372 + version_size
373 + debug_abbrev_offset_size
374 + address_size_size
375 + unit_type_size
376 + type_specific_size
377 }
378
379 pub fn unit_length(&self) -> Offset {
382 self.unit_length
383 }
384
385 pub fn length_including_self(&self) -> Offset {
388 Offset::from_u8(self.format().initial_length_size()) + self.unit_length
389 }
390
391 pub fn encoding(&self) -> Encoding {
393 self.encoding
394 }
395
396 pub fn version(&self) -> u16 {
398 self.encoding.version
399 }
400
401 pub fn type_(&self) -> UnitType<Offset> {
403 self.unit_type
404 }
405
406 pub fn debug_abbrev_offset(&self) -> DebugAbbrevOffset<Offset> {
409 self.debug_abbrev_offset
410 }
411
412 pub fn address_size(&self) -> u8 {
414 self.encoding.address_size
415 }
416
417 pub fn format(&self) -> Format {
419 self.encoding.format
420 }
421
422 pub fn header_size(&self) -> Offset {
424 self.length_including_self() - self.entries_buf.len()
425 }
426
427 pub(crate) fn is_valid_offset(&self, offset: UnitOffset<Offset>) -> bool {
428 let size_of_header = self.header_size();
429 if offset.0 < size_of_header {
430 return false;
431 }
432
433 let relative_to_entries_buf = offset.0 - size_of_header;
434 relative_to_entries_buf < self.entries_buf.len()
435 }
436
437 pub fn range(&self, idx: Range<UnitOffset<Offset>>) -> Result<R> {
439 if !self.is_valid_offset(idx.start) {
440 return Err(Error::OffsetOutOfBounds);
441 }
442 if !self.is_valid_offset(idx.end) {
443 return Err(Error::OffsetOutOfBounds);
444 }
445 assert!(idx.start <= idx.end);
446 let size_of_header = self.header_size();
447 let start = idx.start.0 - size_of_header;
448 let end = idx.end.0 - size_of_header;
449 let mut input = self.entries_buf.clone();
450 input.skip(start)?;
451 input.truncate(end - start)?;
452 Ok(input)
453 }
454
455 pub fn range_from(&self, idx: RangeFrom<UnitOffset<Offset>>) -> Result<R> {
457 if !self.is_valid_offset(idx.start) {
458 return Err(Error::OffsetOutOfBounds);
459 }
460 let start = idx.start.0 - self.header_size();
461 let mut input = self.entries_buf.clone();
462 input.skip(start)?;
463 Ok(input)
464 }
465
466 pub fn range_to(&self, idx: RangeTo<UnitOffset<Offset>>) -> Result<R> {
468 if !self.is_valid_offset(idx.end) {
469 return Err(Error::OffsetOutOfBounds);
470 }
471 let end = idx.end.0 - self.header_size();
472 let mut input = self.entries_buf.clone();
473 input.truncate(end)?;
474 Ok(input)
475 }
476
477 pub fn entry<'me, 'abbrev>(
479 &'me self,
480 abbreviations: &'abbrev Abbreviations,
481 offset: UnitOffset<Offset>,
482 ) -> Result<DebuggingInformationEntry<'abbrev, 'me, R>> {
483 let mut input = self.range_from(offset..)?;
484 let entry = DebuggingInformationEntry::parse(&mut input, self, abbreviations)?;
485 entry.ok_or(Error::NoEntryAtGivenOffset)
486 }
487
488 pub fn entries<'me, 'abbrev>(
490 &'me self,
491 abbreviations: &'abbrev Abbreviations,
492 ) -> EntriesCursor<'abbrev, 'me, R> {
493 EntriesCursor {
494 unit: self,
495 input: self.entries_buf.clone(),
496 abbreviations,
497 cached_current: None,
498 delta_depth: 0,
499 }
500 }
501
502 pub fn entries_at_offset<'me, 'abbrev>(
505 &'me self,
506 abbreviations: &'abbrev Abbreviations,
507 offset: UnitOffset<Offset>,
508 ) -> Result<EntriesCursor<'abbrev, 'me, R>> {
509 let input = self.range_from(offset..)?;
510 Ok(EntriesCursor {
511 unit: self,
512 input,
513 abbreviations,
514 cached_current: None,
515 delta_depth: 0,
516 })
517 }
518
519 pub fn entries_tree<'me, 'abbrev>(
522 &'me self,
523 abbreviations: &'abbrev Abbreviations,
524 offset: Option<UnitOffset<Offset>>,
525 ) -> Result<EntriesTree<'abbrev, 'me, R>> {
526 let input = match offset {
527 Some(offset) => self.range_from(offset..)?,
528 None => self.entries_buf.clone(),
529 };
530 Ok(EntriesTree::new(input, self, abbreviations))
531 }
532
533 pub fn entries_raw<'me, 'abbrev>(
535 &'me self,
536 abbreviations: &'abbrev Abbreviations,
537 offset: Option<UnitOffset<Offset>>,
538 ) -> Result<EntriesRaw<'abbrev, 'me, R>> {
539 let input = match offset {
540 Some(offset) => self.range_from(offset..)?,
541 None => self.entries_buf.clone(),
542 };
543 Ok(EntriesRaw {
544 input,
545 unit: self,
546 abbreviations,
547 depth: 0,
548 })
549 }
550
551 pub fn abbreviations(&self, debug_abbrev: &DebugAbbrev<R>) -> Result<Abbreviations> {
553 debug_abbrev.abbreviations(self.debug_abbrev_offset())
554 }
555}
556
557fn parse_unit_header<R, Offset>(
559 input: &mut R,
560 unit_offset: UnitSectionOffset<Offset>,
561) -> Result<UnitHeader<R>>
562where
563 R: Reader<Offset = Offset>,
564 Offset: ReaderOffset,
565{
566 let (unit_length, format) = input.read_initial_length()?;
567 let mut rest = input.split(unit_length)?;
568
569 let version = rest.read_u16()?;
570 let abbrev_offset;
571 let address_size;
572 let unit_type;
573 if 2 <= version && version <= 4 {
576 abbrev_offset = parse_debug_abbrev_offset(&mut rest, format)?;
577 address_size = rest.read_address_size()?;
578 unit_type = match unit_offset {
581 UnitSectionOffset::DebugInfoOffset(_) => constants::DW_UT_compile,
582 UnitSectionOffset::DebugTypesOffset(_) => constants::DW_UT_type,
583 };
584 } else if version == 5 {
585 unit_type = parse_unit_type(&mut rest)?;
586 address_size = rest.read_address_size()?;
587 abbrev_offset = parse_debug_abbrev_offset(&mut rest, format)?;
588 } else {
589 return Err(Error::UnknownVersion(u64::from(version)));
590 }
591 let encoding = Encoding {
592 format,
593 version,
594 address_size,
595 };
596
597 let unit_type = match unit_type {
599 constants::DW_UT_compile => UnitType::Compilation,
600 constants::DW_UT_type => {
601 let type_signature = parse_type_signature(&mut rest)?;
602 let type_offset = parse_type_offset(&mut rest, format)?;
603 UnitType::Type {
604 type_signature,
605 type_offset,
606 }
607 }
608 constants::DW_UT_partial => UnitType::Partial,
609 constants::DW_UT_skeleton => {
610 let dwo_id = parse_dwo_id(&mut rest)?;
611 UnitType::Skeleton(dwo_id)
612 }
613 constants::DW_UT_split_compile => {
614 let dwo_id = parse_dwo_id(&mut rest)?;
615 UnitType::SplitCompilation(dwo_id)
616 }
617 constants::DW_UT_split_type => {
618 let type_signature = parse_type_signature(&mut rest)?;
619 let type_offset = parse_type_offset(&mut rest, format)?;
620 UnitType::SplitType {
621 type_signature,
622 type_offset,
623 }
624 }
625 _ => return Err(Error::UnsupportedUnitType),
626 };
627
628 Ok(UnitHeader::new(
629 encoding,
630 unit_length,
631 unit_type,
632 abbrev_offset,
633 unit_offset,
634 rest,
635 ))
636}
637
638fn parse_dwo_id<R: Reader>(input: &mut R) -> Result<DwoId> {
640 Ok(DwoId(input.read_u64()?))
641}
642
643#[derive(Clone, Debug)]
647pub struct DebuggingInformationEntry<'abbrev, 'unit, R, Offset = <R as Reader>::Offset>
648where
649 R: Reader<Offset = Offset>,
650 Offset: ReaderOffset,
651{
652 offset: UnitOffset<Offset>,
653 attrs_slice: R,
654 attrs_len: Cell<Option<Offset>>,
655 abbrev: &'abbrev Abbreviation,
656 unit: &'unit UnitHeader<R, Offset>,
657}
658
659impl<'abbrev, 'unit, R, Offset> DebuggingInformationEntry<'abbrev, 'unit, R, Offset>
660where
661 R: Reader<Offset = Offset>,
662 Offset: ReaderOffset,
663{
664 pub fn new(
666 offset: UnitOffset<Offset>,
667 attrs_slice: R,
668 abbrev: &'abbrev Abbreviation,
669 unit: &'unit UnitHeader<R, Offset>,
670 ) -> Self {
671 DebuggingInformationEntry {
672 offset,
673 attrs_slice,
674 attrs_len: Cell::new(None),
675 abbrev,
676 unit,
677 }
678 }
679
680 pub fn code(&self) -> u64 {
682 self.abbrev.code()
683 }
684
685 pub fn offset(&self) -> UnitOffset<Offset> {
687 self.offset
688 }
689
690 pub fn tag(&self) -> constants::DwTag {
754 self.abbrev.tag()
755 }
756
757 pub fn has_children(&self) -> bool {
759 self.abbrev.has_children()
760 }
761
762 pub fn attrs<'me>(&'me self) -> AttrsIter<'abbrev, 'me, 'unit, R> {
841 AttrsIter {
842 input: self.attrs_slice.clone(),
843 attributes: self.abbrev.attributes(),
844 entry: self,
845 }
846 }
847
848 pub fn attr(&self, name: constants::DwAt) -> Result<Option<Attribute<R>>> {
851 let mut attrs = self.attrs();
852 while let Some(attr) = attrs.next()? {
853 if attr.name() == name {
854 return Ok(Some(attr));
855 }
856 }
857 Ok(None)
858 }
859
860 pub fn attr_value_raw(&self, name: constants::DwAt) -> Result<Option<AttributeValue<R>>> {
863 self.attr(name)
864 .map(|attr| attr.map(|attr| attr.raw_value()))
865 }
866
867 pub fn attr_value(&self, name: constants::DwAt) -> Result<Option<AttributeValue<R>>> {
871 self.attr(name).map(|attr| attr.map(|attr| attr.value()))
872 }
873
874 #[inline(always)]
876 fn after_attrs(&self) -> Result<R> {
877 if let Some(attrs_len) = self.attrs_len.get() {
878 let mut input = self.attrs_slice.clone();
879 input.skip(attrs_len)?;
880 Ok(input)
881 } else {
882 let mut attrs = self.attrs();
883 while attrs.next()?.is_some() {}
884 Ok(attrs.input)
885 }
886 }
887
888 fn sibling(&self) -> Option<R> {
891 let attr = self.attr_value(constants::DW_AT_sibling);
892 if let Ok(Some(AttributeValue::UnitRef(offset))) = attr {
893 if offset.0 > self.offset.0 {
894 if let Ok(input) = self.unit.range_from(offset..) {
895 return Some(input);
896 }
897 }
898 }
899 None
900 }
901
902 #[inline(always)]
904 fn parse(
905 input: &mut R,
906 unit: &'unit UnitHeader<R>,
907 abbreviations: &'abbrev Abbreviations,
908 ) -> Result<Option<Self>> {
909 let offset = unit.header_size() + input.offset_from(&unit.entries_buf);
910 let code = input.read_uleb128()?;
911 if code == 0 {
912 return Ok(None);
913 };
914 let abbrev = abbreviations
915 .get(code)
916 .ok_or(Error::UnknownAbbreviation(code))?;
917 Ok(Some(DebuggingInformationEntry {
918 offset: UnitOffset(offset),
919 attrs_slice: input.clone(),
920 attrs_len: Cell::new(None),
921 abbrev,
922 unit,
923 }))
924 }
925}
926
927#[repr(u64)]
932#[derive(Clone, Copy, Debug, Eq, PartialEq)]
933pub enum AttributeValue<R, Offset = <R as Reader>::Offset>
934where
935 R: Reader<Offset = Offset>,
936 Offset: ReaderOffset,
937{
938 Addr(u64),
940
941 Block(R),
943
944 Data1(u8),
950
951 Data2(u16),
960
961 Data4(u32),
970
971 Data8(u64),
980
981 Sdata(i64),
983
984 Udata(u64),
986
987 Exprloc(Expression<R>),
990
991 Flag(bool),
993
994 SecOffset(Offset),
997
998 DebugAddrBase(DebugAddrBase<Offset>),
1000
1001 DebugAddrIndex(DebugAddrIndex<Offset>),
1003
1004 UnitRef(UnitOffset<Offset>),
1006
1007 DebugInfoRef(DebugInfoOffset<Offset>),
1010
1011 DebugInfoRefSup(DebugInfoOffset<Offset>),
1013
1014 DebugLineRef(DebugLineOffset<Offset>),
1016
1017 LocationListsRef(LocationListsOffset<Offset>),
1019
1020 DebugLocListsBase(DebugLocListsBase<Offset>),
1022
1023 DebugLocListsIndex(DebugLocListsIndex<Offset>),
1025
1026 DebugMacinfoRef(DebugMacinfoOffset<Offset>),
1028
1029 DebugMacroRef(DebugMacroOffset<Offset>),
1031
1032 RangeListsRef(RawRangeListsOffset<Offset>),
1034
1035 DebugRngListsBase(DebugRngListsBase<Offset>),
1037
1038 DebugRngListsIndex(DebugRngListsIndex<Offset>),
1040
1041 DebugTypesRef(DebugTypeSignature),
1043
1044 DebugStrRef(DebugStrOffset<Offset>),
1046
1047 DebugStrRefSup(DebugStrOffset<Offset>),
1049
1050 DebugStrOffsetsBase(DebugStrOffsetsBase<Offset>),
1052
1053 DebugStrOffsetsIndex(DebugStrOffsetsIndex<Offset>),
1055
1056 DebugLineStrRef(DebugLineStrOffset<Offset>),
1058
1059 String(R),
1062
1063 Encoding(constants::DwAte),
1065
1066 DecimalSign(constants::DwDs),
1068
1069 Endianity(constants::DwEnd),
1071
1072 Accessibility(constants::DwAccess),
1074
1075 Visibility(constants::DwVis),
1077
1078 Virtuality(constants::DwVirtuality),
1080
1081 Language(constants::DwLang),
1083
1084 AddressClass(constants::DwAddr),
1086
1087 IdentifierCase(constants::DwId),
1089
1090 CallingConvention(constants::DwCc),
1092
1093 Inline(constants::DwInl),
1095
1096 Ordering(constants::DwOrd),
1098
1099 FileIndex(u64),
1102
1103 DwoId(DwoId),
1106}
1107
1108#[derive(Copy, Clone, Debug, Eq, PartialEq)]
1111pub struct Attribute<R: Reader> {
1112 name: constants::DwAt,
1113 value: AttributeValue<R>,
1114}
1115
1116impl<R: Reader> Attribute<R> {
1117 pub fn name(&self) -> constants::DwAt {
1119 self.name
1120 }
1121
1122 pub fn raw_value(&self) -> AttributeValue<R> {
1124 self.value.clone()
1125 }
1126
1127 pub fn value(&self) -> AttributeValue<R> {
1136 macro_rules! address {
1159 () => {};
1160 }
1161 macro_rules! addrptr {
1163 () => {
1164 if let Some(offset) = self.offset_value() {
1165 return AttributeValue::DebugAddrBase(DebugAddrBase(offset));
1166 }
1167 };
1168 }
1169 macro_rules! block {
1174 () => {};
1175 }
1176 macro_rules! constant {
1185 ($value:ident, $variant:ident) => {
1186 if let Some(value) = self.$value() {
1187 return AttributeValue::$variant(value);
1188 }
1189 };
1190 ($value:ident, $variant:ident, $constant:ident) => {
1191 if let Some(value) = self.$value() {
1192 return AttributeValue::$variant(constants::$constant(value));
1193 }
1194 };
1195 }
1196 macro_rules! exprloc {
1198 () => {
1199 if let Some(value) = self.exprloc_value() {
1200 return AttributeValue::Exprloc(value);
1201 }
1202 };
1203 }
1204 macro_rules! flag {
1207 () => {};
1208 }
1209 macro_rules! lineptr {
1211 () => {
1212 if let Some(offset) = self.offset_value() {
1213 return AttributeValue::DebugLineRef(DebugLineOffset(offset));
1214 }
1215 };
1216 }
1217 macro_rules! loclistptr {
1221 () => {
1222 if let Some(offset) = self.offset_value() {
1224 return AttributeValue::LocationListsRef(LocationListsOffset(offset));
1225 }
1226 };
1227 }
1228 macro_rules! loclistsptr {
1230 () => {
1231 if let Some(offset) = self.offset_value() {
1232 return AttributeValue::DebugLocListsBase(DebugLocListsBase(offset));
1233 }
1234 };
1235 }
1236 macro_rules! macinfoptr {
1239 () => {
1240 if let Some(offset) = self.offset_value() {
1241 return AttributeValue::DebugMacinfoRef(DebugMacinfoOffset(offset));
1242 }
1243 };
1244 }
1245 macro_rules! macroptr {
1248 () => {
1249 if let Some(offset) = self.offset_value() {
1250 return AttributeValue::DebugMacroRef(DebugMacroOffset(offset));
1251 }
1252 };
1253 }
1254 macro_rules! reference {
1264 () => {};
1265 }
1266 macro_rules! rangelistptr {
1270 () => {
1271 if let Some(offset) = self.offset_value() {
1273 return AttributeValue::RangeListsRef(RawRangeListsOffset(offset));
1274 }
1275 };
1276 }
1277 macro_rules! rnglistsptr {
1279 () => {
1280 if let Some(offset) = self.offset_value() {
1281 return AttributeValue::DebugRngListsBase(DebugRngListsBase(offset));
1282 }
1283 };
1284 }
1285 macro_rules! string {
1295 () => {};
1296 }
1297 macro_rules! stroffsetsptr {
1299 () => {
1300 if let Some(offset) = self.offset_value() {
1301 return AttributeValue::DebugStrOffsetsBase(DebugStrOffsetsBase(offset));
1302 }
1303 };
1304 }
1305 macro_rules! dwoid {
1307 () => {
1308 if let Some(value) = self.udata_value() {
1309 return AttributeValue::DwoId(DwoId(value));
1310 }
1311 };
1312 }
1313
1314 match self.name {
1316 constants::DW_AT_sibling => {
1317 reference!();
1318 }
1319 constants::DW_AT_location => {
1320 exprloc!();
1321 loclistptr!();
1322 }
1323 constants::DW_AT_name => {
1324 string!();
1325 }
1326 constants::DW_AT_ordering => {
1327 constant!(u8_value, Ordering, DwOrd);
1328 }
1329 constants::DW_AT_byte_size
1330 | constants::DW_AT_bit_offset
1331 | constants::DW_AT_bit_size => {
1332 constant!(udata_value, Udata);
1333 exprloc!();
1334 reference!();
1335 }
1336 constants::DW_AT_stmt_list => {
1337 lineptr!();
1338 }
1339 constants::DW_AT_low_pc => {
1340 address!();
1341 }
1342 constants::DW_AT_high_pc => {
1343 address!();
1344 constant!(udata_value, Udata);
1345 }
1346 constants::DW_AT_language => {
1347 constant!(u16_value, Language, DwLang);
1348 }
1349 constants::DW_AT_discr => {
1350 reference!();
1351 }
1352 constants::DW_AT_discr_value => {
1353 }
1356 constants::DW_AT_visibility => {
1357 constant!(u8_value, Visibility, DwVis);
1358 }
1359 constants::DW_AT_import => {
1360 reference!();
1361 }
1362 constants::DW_AT_string_length => {
1363 exprloc!();
1364 loclistptr!();
1365 reference!();
1366 }
1367 constants::DW_AT_common_reference => {
1368 reference!();
1369 }
1370 constants::DW_AT_comp_dir => {
1371 string!();
1372 }
1373 constants::DW_AT_const_value => {
1374 block!();
1376 string!();
1377 }
1378 constants::DW_AT_containing_type => {
1379 reference!();
1380 }
1381 constants::DW_AT_default_value => {
1382 reference!();
1384 flag!();
1385 }
1386 constants::DW_AT_inline => {
1387 constant!(u8_value, Inline, DwInl);
1388 }
1389 constants::DW_AT_is_optional => {
1390 flag!();
1391 }
1392 constants::DW_AT_lower_bound => {
1393 exprloc!();
1395 reference!();
1396 }
1397 constants::DW_AT_producer => {
1398 string!();
1399 }
1400 constants::DW_AT_prototyped => {
1401 flag!();
1402 }
1403 constants::DW_AT_return_addr => {
1404 exprloc!();
1405 loclistptr!();
1406 }
1407 constants::DW_AT_start_scope => {
1408 rangelistptr!();
1410 }
1411 constants::DW_AT_bit_stride => {
1412 constant!(udata_value, Udata);
1413 exprloc!();
1414 reference!();
1415 }
1416 constants::DW_AT_upper_bound => {
1417 exprloc!();
1419 reference!();
1420 }
1421 constants::DW_AT_abstract_origin => {
1422 reference!();
1423 }
1424 constants::DW_AT_accessibility => {
1425 constant!(u8_value, Accessibility, DwAccess);
1426 }
1427 constants::DW_AT_address_class => {
1428 constant!(udata_value, AddressClass, DwAddr);
1429 }
1430 constants::DW_AT_artificial => {
1431 flag!();
1432 }
1433 constants::DW_AT_base_types => {
1434 reference!();
1435 }
1436 constants::DW_AT_calling_convention => {
1437 constant!(u8_value, CallingConvention, DwCc);
1438 }
1439 constants::DW_AT_count => {
1440 exprloc!();
1442 reference!();
1443 }
1444 constants::DW_AT_data_member_location => {
1445 constant!(udata_value, Udata);
1448 exprloc!();
1449 loclistptr!();
1450 }
1451 constants::DW_AT_decl_column => {
1452 constant!(udata_value, Udata);
1453 }
1454 constants::DW_AT_decl_file => {
1455 constant!(udata_value, FileIndex);
1456 }
1457 constants::DW_AT_decl_line => {
1458 constant!(udata_value, Udata);
1459 }
1460 constants::DW_AT_declaration => {
1461 flag!();
1462 }
1463 constants::DW_AT_discr_list => {
1464 block!();
1465 }
1466 constants::DW_AT_encoding => {
1467 constant!(u8_value, Encoding, DwAte);
1468 }
1469 constants::DW_AT_external => {
1470 flag!();
1471 }
1472 constants::DW_AT_frame_base => {
1473 exprloc!();
1474 loclistptr!();
1475 }
1476 constants::DW_AT_friend => {
1477 reference!();
1478 }
1479 constants::DW_AT_identifier_case => {
1480 constant!(u8_value, IdentifierCase, DwId);
1481 }
1482 constants::DW_AT_macro_info => {
1483 macinfoptr!();
1484 }
1485 constants::DW_AT_namelist_item => {
1486 reference!();
1487 }
1488 constants::DW_AT_priority => {
1489 reference!();
1490 }
1491 constants::DW_AT_segment => {
1492 exprloc!();
1493 loclistptr!();
1494 }
1495 constants::DW_AT_specification => {
1496 reference!();
1497 }
1498 constants::DW_AT_static_link => {
1499 exprloc!();
1500 loclistptr!();
1501 }
1502 constants::DW_AT_type => {
1503 reference!();
1504 }
1505 constants::DW_AT_use_location => {
1506 exprloc!();
1507 loclistptr!();
1508 }
1509 constants::DW_AT_variable_parameter => {
1510 flag!();
1511 }
1512 constants::DW_AT_virtuality => {
1513 constant!(u8_value, Virtuality, DwVirtuality);
1514 }
1515 constants::DW_AT_vtable_elem_location => {
1516 exprloc!();
1517 loclistptr!();
1518 }
1519 constants::DW_AT_allocated => {
1520 exprloc!();
1522 reference!();
1523 }
1524 constants::DW_AT_associated => {
1525 exprloc!();
1527 reference!();
1528 }
1529 constants::DW_AT_data_location => {
1530 exprloc!();
1531 }
1532 constants::DW_AT_byte_stride => {
1533 constant!(udata_value, Udata);
1534 exprloc!();
1535 reference!();
1536 }
1537 constants::DW_AT_entry_pc => {
1538 address!();
1540 }
1541 constants::DW_AT_use_UTF8 => {
1542 flag!();
1543 }
1544 constants::DW_AT_extension => {
1545 reference!();
1546 }
1547 constants::DW_AT_ranges => {
1548 rangelistptr!();
1549 }
1550 constants::DW_AT_trampoline => {
1551 address!();
1552 flag!();
1553 reference!();
1554 string!();
1555 }
1556 constants::DW_AT_call_column => {
1557 constant!(udata_value, Udata);
1558 }
1559 constants::DW_AT_call_file => {
1560 constant!(udata_value, FileIndex);
1561 }
1562 constants::DW_AT_call_line => {
1563 constant!(udata_value, Udata);
1564 }
1565 constants::DW_AT_description => {
1566 string!();
1567 }
1568 constants::DW_AT_binary_scale => {
1569 }
1571 constants::DW_AT_decimal_scale => {
1572 }
1574 constants::DW_AT_small => {
1575 reference!();
1576 }
1577 constants::DW_AT_decimal_sign => {
1578 constant!(u8_value, DecimalSign, DwDs);
1579 }
1580 constants::DW_AT_digit_count => {
1581 }
1583 constants::DW_AT_picture_string => {
1584 string!();
1585 }
1586 constants::DW_AT_mutable => {
1587 flag!();
1588 }
1589 constants::DW_AT_threads_scaled => {
1590 flag!();
1591 }
1592 constants::DW_AT_explicit => {
1593 flag!();
1594 }
1595 constants::DW_AT_object_pointer => {
1596 reference!();
1597 }
1598 constants::DW_AT_endianity => {
1599 constant!(u8_value, Endianity, DwEnd);
1600 }
1601 constants::DW_AT_elemental => {
1602 flag!();
1603 }
1604 constants::DW_AT_pure => {
1605 flag!();
1606 }
1607 constants::DW_AT_recursive => {
1608 flag!();
1609 }
1610 constants::DW_AT_signature => {
1611 reference!();
1612 }
1613 constants::DW_AT_main_subprogram => {
1614 flag!();
1615 }
1616 constants::DW_AT_data_bit_offset => {
1617 }
1619 constants::DW_AT_const_expr => {
1620 flag!();
1621 }
1622 constants::DW_AT_enum_class => {
1623 flag!();
1624 }
1625 constants::DW_AT_linkage_name => {
1626 string!();
1627 }
1628 constants::DW_AT_string_length_bit_size => {
1629 }
1631 constants::DW_AT_string_length_byte_size => {
1632 }
1634 constants::DW_AT_rank => {
1635 exprloc!();
1637 }
1638 constants::DW_AT_str_offsets_base => {
1639 stroffsetsptr!();
1640 }
1641 constants::DW_AT_addr_base | constants::DW_AT_GNU_addr_base => {
1642 addrptr!();
1643 }
1644 constants::DW_AT_rnglists_base | constants::DW_AT_GNU_ranges_base => {
1645 rnglistsptr!();
1646 }
1647 constants::DW_AT_dwo_name => {
1648 string!();
1649 }
1650 constants::DW_AT_reference => {
1651 flag!();
1652 }
1653 constants::DW_AT_rvalue_reference => {
1654 flag!();
1655 }
1656 constants::DW_AT_macros => {
1657 macroptr!();
1658 }
1659 constants::DW_AT_call_all_calls => {
1660 flag!();
1661 }
1662 constants::DW_AT_call_all_source_calls => {
1663 flag!();
1664 }
1665 constants::DW_AT_call_all_tail_calls => {
1666 flag!();
1667 }
1668 constants::DW_AT_call_return_pc => {
1669 address!();
1670 }
1671 constants::DW_AT_call_value => {
1672 exprloc!();
1673 }
1674 constants::DW_AT_call_origin => {
1675 exprloc!();
1676 }
1677 constants::DW_AT_call_parameter => {
1678 reference!();
1679 }
1680 constants::DW_AT_call_pc => {
1681 address!();
1682 }
1683 constants::DW_AT_call_tail_call => {
1684 flag!();
1685 }
1686 constants::DW_AT_call_target => {
1687 exprloc!();
1688 }
1689 constants::DW_AT_call_target_clobbered => {
1690 exprloc!();
1691 }
1692 constants::DW_AT_call_data_location => {
1693 exprloc!();
1694 }
1695 constants::DW_AT_call_data_value => {
1696 exprloc!();
1697 }
1698 constants::DW_AT_noreturn => {
1699 flag!();
1700 }
1701 constants::DW_AT_alignment => {
1702 }
1704 constants::DW_AT_export_symbols => {
1705 flag!();
1706 }
1707 constants::DW_AT_deleted => {
1708 flag!();
1709 }
1710 constants::DW_AT_defaulted => {
1711 }
1713 constants::DW_AT_loclists_base => {
1714 loclistsptr!();
1715 }
1716 constants::DW_AT_GNU_dwo_id => {
1717 dwoid!();
1718 }
1719 _ => {}
1720 }
1721 self.value.clone()
1722 }
1723
1724 #[inline]
1726 pub fn u8_value(&self) -> Option<u8> {
1727 self.value.u8_value()
1728 }
1729
1730 #[inline]
1732 pub fn u16_value(&self) -> Option<u16> {
1733 self.value.u16_value()
1734 }
1735
1736 #[inline]
1738 pub fn udata_value(&self) -> Option<u64> {
1739 self.value.udata_value()
1740 }
1741
1742 #[inline]
1744 pub fn sdata_value(&self) -> Option<i64> {
1745 self.value.sdata_value()
1746 }
1747
1748 #[inline]
1750 pub fn offset_value(&self) -> Option<R::Offset> {
1751 self.value.offset_value()
1752 }
1753
1754 #[inline]
1760 pub fn exprloc_value(&self) -> Option<Expression<R>> {
1761 self.value.exprloc_value()
1762 }
1763
1764 #[inline]
1774 pub fn string_value(&self, debug_str: &DebugStr<R>) -> Option<R> {
1775 self.value.string_value(debug_str)
1776 }
1777
1778 #[inline]
1789 pub fn string_value_sup(
1790 &self,
1791 debug_str: &DebugStr<R>,
1792 debug_str_sup: Option<&DebugStr<R>>,
1793 ) -> Option<R> {
1794 self.value.string_value_sup(debug_str, debug_str_sup)
1795 }
1796}
1797
1798impl<R, Offset> AttributeValue<R, Offset>
1799where
1800 R: Reader<Offset = Offset>,
1801 Offset: ReaderOffset,
1802{
1803 pub fn u8_value(&self) -> Option<u8> {
1805 if let Some(value) = self.udata_value() {
1806 if value <= u64::from(u8::MAX) {
1807 return Some(value as u8);
1808 }
1809 }
1810 None
1811 }
1812
1813 pub fn u16_value(&self) -> Option<u16> {
1815 if let Some(value) = self.udata_value() {
1816 if value <= u64::from(u16::MAX) {
1817 return Some(value as u16);
1818 }
1819 }
1820 None
1821 }
1822
1823 pub fn udata_value(&self) -> Option<u64> {
1825 Some(match *self {
1826 AttributeValue::Data1(data) => u64::from(data),
1827 AttributeValue::Data2(data) => u64::from(data),
1828 AttributeValue::Data4(data) => u64::from(data),
1829 AttributeValue::Data8(data) => data,
1830 AttributeValue::Udata(data) => data,
1831 AttributeValue::Sdata(data) => {
1832 if data < 0 {
1833 return None;
1835 }
1836 data as u64
1837 }
1838 _ => return None,
1839 })
1840 }
1841
1842 pub fn sdata_value(&self) -> Option<i64> {
1844 Some(match *self {
1845 AttributeValue::Data1(data) => i64::from(data as i8),
1846 AttributeValue::Data2(data) => i64::from(data as i16),
1847 AttributeValue::Data4(data) => i64::from(data as i32),
1848 AttributeValue::Data8(data) => data as i64,
1849 AttributeValue::Sdata(data) => data,
1850 AttributeValue::Udata(data) => {
1851 if data > i64::MAX as u64 {
1852 return None;
1854 }
1855 data as i64
1856 }
1857 _ => return None,
1858 })
1859 }
1860
1861 pub fn offset_value(&self) -> Option<R::Offset> {
1863 if let AttributeValue::SecOffset(offset) = *self {
1866 Some(offset)
1867 } else {
1868 None
1869 }
1870 }
1871
1872 pub fn exprloc_value(&self) -> Option<Expression<R>> {
1878 Some(match *self {
1879 AttributeValue::Block(ref data) => Expression(data.clone()),
1880 AttributeValue::Exprloc(ref data) => data.clone(),
1881 _ => return None,
1882 })
1883 }
1884
1885 pub fn string_value(&self, debug_str: &DebugStr<R>) -> Option<R> {
1895 match *self {
1896 AttributeValue::String(ref string) => Some(string.clone()),
1897 AttributeValue::DebugStrRef(offset) => debug_str.get_str(offset).ok(),
1898 _ => None,
1899 }
1900 }
1901
1902 pub fn string_value_sup(
1913 &self,
1914 debug_str: &DebugStr<R>,
1915 debug_str_sup: Option<&DebugStr<R>>,
1916 ) -> Option<R> {
1917 match *self {
1918 AttributeValue::String(ref string) => Some(string.clone()),
1919 AttributeValue::DebugStrRef(offset) => debug_str.get_str(offset).ok(),
1920 AttributeValue::DebugStrRefSup(offset) => {
1921 debug_str_sup.and_then(|s| s.get_str(offset).ok())
1922 }
1923 _ => None,
1924 }
1925 }
1926}
1927
1928fn length_u8_value<R: Reader>(input: &mut R) -> Result<R> {
1929 let len = input.read_u8().map(R::Offset::from_u8)?;
1930 input.split(len)
1931}
1932
1933fn length_u16_value<R: Reader>(input: &mut R) -> Result<R> {
1934 let len = input.read_u16().map(R::Offset::from_u16)?;
1935 input.split(len)
1936}
1937
1938fn length_u32_value<R: Reader>(input: &mut R) -> Result<R> {
1939 let len = input.read_u32().map(R::Offset::from_u32)?;
1940 input.split(len)
1941}
1942
1943fn length_uleb128_value<R: Reader>(input: &mut R) -> Result<R> {
1944 let len = input.read_uleb128().and_then(R::Offset::from_u64)?;
1945 input.split(len)
1946}
1947
1948fn allow_section_offset(name: constants::DwAt, version: u16) -> bool {
1951 match name {
1952 constants::DW_AT_location
1953 | constants::DW_AT_stmt_list
1954 | constants::DW_AT_string_length
1955 | constants::DW_AT_return_addr
1956 | constants::DW_AT_start_scope
1957 | constants::DW_AT_frame_base
1958 | constants::DW_AT_macro_info
1959 | constants::DW_AT_macros
1960 | constants::DW_AT_segment
1961 | constants::DW_AT_static_link
1962 | constants::DW_AT_use_location
1963 | constants::DW_AT_vtable_elem_location
1964 | constants::DW_AT_ranges => true,
1965 constants::DW_AT_data_member_location => version == 2 || version == 3,
1966 _ => false,
1967 }
1968}
1969
1970pub(crate) fn parse_attribute<R: Reader>(
1971 input: &mut R,
1972 encoding: Encoding,
1973 spec: AttributeSpecification,
1974) -> Result<Attribute<R>> {
1975 let mut form = spec.form();
1976 loop {
1977 let value = match form {
1978 constants::DW_FORM_indirect => {
1979 let dynamic_form = input.read_uleb128_u16()?;
1980 form = constants::DwForm(dynamic_form);
1981 continue;
1982 }
1983 constants::DW_FORM_addr => {
1984 let addr = input.read_address(encoding.address_size)?;
1985 AttributeValue::Addr(addr)
1986 }
1987 constants::DW_FORM_block1 => {
1988 let block = length_u8_value(input)?;
1989 AttributeValue::Block(block)
1990 }
1991 constants::DW_FORM_block2 => {
1992 let block = length_u16_value(input)?;
1993 AttributeValue::Block(block)
1994 }
1995 constants::DW_FORM_block4 => {
1996 let block = length_u32_value(input)?;
1997 AttributeValue::Block(block)
1998 }
1999 constants::DW_FORM_block => {
2000 let block = length_uleb128_value(input)?;
2001 AttributeValue::Block(block)
2002 }
2003 constants::DW_FORM_data1 => {
2004 let data = input.read_u8()?;
2005 AttributeValue::Data1(data)
2006 }
2007 constants::DW_FORM_data2 => {
2008 let data = input.read_u16()?;
2009 AttributeValue::Data2(data)
2010 }
2011 constants::DW_FORM_data4 => {
2012 if encoding.format == Format::Dwarf32
2015 && allow_section_offset(spec.name(), encoding.version)
2016 {
2017 let offset = input.read_offset(Format::Dwarf32)?;
2018 AttributeValue::SecOffset(offset)
2019 } else {
2020 let data = input.read_u32()?;
2021 AttributeValue::Data4(data)
2022 }
2023 }
2024 constants::DW_FORM_data8 => {
2025 if encoding.format == Format::Dwarf64
2028 && allow_section_offset(spec.name(), encoding.version)
2029 {
2030 let offset = input.read_offset(Format::Dwarf64)?;
2031 AttributeValue::SecOffset(offset)
2032 } else {
2033 let data = input.read_u64()?;
2034 AttributeValue::Data8(data)
2035 }
2036 }
2037 constants::DW_FORM_data16 => {
2038 let block = input.split(R::Offset::from_u8(16))?;
2039 AttributeValue::Block(block)
2040 }
2041 constants::DW_FORM_udata => {
2042 let data = input.read_uleb128()?;
2043 AttributeValue::Udata(data)
2044 }
2045 constants::DW_FORM_sdata => {
2046 let data = input.read_sleb128()?;
2047 AttributeValue::Sdata(data)
2048 }
2049 constants::DW_FORM_exprloc => {
2050 let block = length_uleb128_value(input)?;
2051 AttributeValue::Exprloc(Expression(block))
2052 }
2053 constants::DW_FORM_flag => {
2054 let present = input.read_u8()?;
2055 AttributeValue::Flag(present != 0)
2056 }
2057 constants::DW_FORM_flag_present => {
2058 AttributeValue::Flag(true)
2061 }
2062 constants::DW_FORM_sec_offset => {
2063 let offset = input.read_offset(encoding.format)?;
2064 AttributeValue::SecOffset(offset)
2065 }
2066 constants::DW_FORM_ref1 => {
2067 let reference = input.read_u8().map(R::Offset::from_u8)?;
2068 AttributeValue::UnitRef(UnitOffset(reference))
2069 }
2070 constants::DW_FORM_ref2 => {
2071 let reference = input.read_u16().map(R::Offset::from_u16)?;
2072 AttributeValue::UnitRef(UnitOffset(reference))
2073 }
2074 constants::DW_FORM_ref4 => {
2075 let reference = input.read_u32().map(R::Offset::from_u32)?;
2076 AttributeValue::UnitRef(UnitOffset(reference))
2077 }
2078 constants::DW_FORM_ref8 => {
2079 let reference = input.read_u64().and_then(R::Offset::from_u64)?;
2080 AttributeValue::UnitRef(UnitOffset(reference))
2081 }
2082 constants::DW_FORM_ref_udata => {
2083 let reference = input.read_uleb128().and_then(R::Offset::from_u64)?;
2084 AttributeValue::UnitRef(UnitOffset(reference))
2085 }
2086 constants::DW_FORM_ref_addr => {
2087 let offset = if encoding.version == 2 {
2091 input.read_sized_offset(encoding.address_size)?
2092 } else {
2093 input.read_offset(encoding.format)?
2094 };
2095 AttributeValue::DebugInfoRef(DebugInfoOffset(offset))
2096 }
2097 constants::DW_FORM_ref_sig8 => {
2098 let signature = input.read_u64()?;
2099 AttributeValue::DebugTypesRef(DebugTypeSignature(signature))
2100 }
2101 constants::DW_FORM_ref_sup4 => {
2102 let offset = input.read_u32().map(R::Offset::from_u32)?;
2103 AttributeValue::DebugInfoRefSup(DebugInfoOffset(offset))
2104 }
2105 constants::DW_FORM_ref_sup8 => {
2106 let offset = input.read_u64().and_then(R::Offset::from_u64)?;
2107 AttributeValue::DebugInfoRefSup(DebugInfoOffset(offset))
2108 }
2109 constants::DW_FORM_GNU_ref_alt => {
2110 let offset = input.read_offset(encoding.format)?;
2111 AttributeValue::DebugInfoRefSup(DebugInfoOffset(offset))
2112 }
2113 constants::DW_FORM_string => {
2114 let string = input.read_null_terminated_slice()?;
2115 AttributeValue::String(string)
2116 }
2117 constants::DW_FORM_strp => {
2118 let offset = input.read_offset(encoding.format)?;
2119 AttributeValue::DebugStrRef(DebugStrOffset(offset))
2120 }
2121 constants::DW_FORM_strp_sup | constants::DW_FORM_GNU_strp_alt => {
2122 let offset = input.read_offset(encoding.format)?;
2123 AttributeValue::DebugStrRefSup(DebugStrOffset(offset))
2124 }
2125 constants::DW_FORM_line_strp => {
2126 let offset = input.read_offset(encoding.format)?;
2127 AttributeValue::DebugLineStrRef(DebugLineStrOffset(offset))
2128 }
2129 constants::DW_FORM_implicit_const => {
2130 let data = spec
2131 .implicit_const_value()
2132 .ok_or(Error::InvalidImplicitConst)?;
2133 AttributeValue::Sdata(data)
2134 }
2135 constants::DW_FORM_strx | constants::DW_FORM_GNU_str_index => {
2136 let index = input.read_uleb128().and_then(R::Offset::from_u64)?;
2137 AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
2138 }
2139 constants::DW_FORM_strx1 => {
2140 let index = input.read_u8().map(R::Offset::from_u8)?;
2141 AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
2142 }
2143 constants::DW_FORM_strx2 => {
2144 let index = input.read_u16().map(R::Offset::from_u16)?;
2145 AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
2146 }
2147 constants::DW_FORM_strx3 => {
2148 let index = input.read_uint(3).and_then(R::Offset::from_u64)?;
2149 AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
2150 }
2151 constants::DW_FORM_strx4 => {
2152 let index = input.read_u32().map(R::Offset::from_u32)?;
2153 AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
2154 }
2155 constants::DW_FORM_addrx | constants::DW_FORM_GNU_addr_index => {
2156 let index = input.read_uleb128().and_then(R::Offset::from_u64)?;
2157 AttributeValue::DebugAddrIndex(DebugAddrIndex(index))
2158 }
2159 constants::DW_FORM_addrx1 => {
2160 let index = input.read_u8().map(R::Offset::from_u8)?;
2161 AttributeValue::DebugAddrIndex(DebugAddrIndex(index))
2162 }
2163 constants::DW_FORM_addrx2 => {
2164 let index = input.read_u16().map(R::Offset::from_u16)?;
2165 AttributeValue::DebugAddrIndex(DebugAddrIndex(index))
2166 }
2167 constants::DW_FORM_addrx3 => {
2168 let index = input.read_uint(3).and_then(R::Offset::from_u64)?;
2169 AttributeValue::DebugAddrIndex(DebugAddrIndex(index))
2170 }
2171 constants::DW_FORM_addrx4 => {
2172 let index = input.read_u32().map(R::Offset::from_u32)?;
2173 AttributeValue::DebugAddrIndex(DebugAddrIndex(index))
2174 }
2175 constants::DW_FORM_loclistx => {
2176 let index = input.read_uleb128().and_then(R::Offset::from_u64)?;
2177 AttributeValue::DebugLocListsIndex(DebugLocListsIndex(index))
2178 }
2179 constants::DW_FORM_rnglistx => {
2180 let index = input.read_uleb128().and_then(R::Offset::from_u64)?;
2181 AttributeValue::DebugRngListsIndex(DebugRngListsIndex(index))
2182 }
2183 _ => {
2184 return Err(Error::UnknownForm(form));
2185 }
2186 };
2187 let attr = Attribute {
2188 name: spec.name(),
2189 value,
2190 };
2191 return Ok(attr);
2192 }
2193}
2194
2195pub(crate) fn skip_attributes<R: Reader>(
2196 input: &mut R,
2197 encoding: Encoding,
2198 specs: &[AttributeSpecification],
2199) -> Result<()> {
2200 let mut skip_bytes = R::Offset::from_u8(0);
2201 for spec in specs {
2202 let mut form = spec.form();
2203 loop {
2204 if let Some(len) = get_attribute_size(form, encoding) {
2205 skip_bytes += R::Offset::from_u8(len);
2207 break;
2208 }
2209
2210 if skip_bytes != R::Offset::from_u8(0) {
2212 input.skip(skip_bytes)?;
2214 skip_bytes = R::Offset::from_u8(0);
2215 }
2216
2217 match form {
2218 constants::DW_FORM_indirect => {
2219 let dynamic_form = input.read_uleb128_u16()?;
2220 form = constants::DwForm(dynamic_form);
2221 continue;
2222 }
2223 constants::DW_FORM_block1 => {
2224 skip_bytes = input.read_u8().map(R::Offset::from_u8)?;
2225 }
2226 constants::DW_FORM_block2 => {
2227 skip_bytes = input.read_u16().map(R::Offset::from_u16)?;
2228 }
2229 constants::DW_FORM_block4 => {
2230 skip_bytes = input.read_u32().map(R::Offset::from_u32)?;
2231 }
2232 constants::DW_FORM_block | constants::DW_FORM_exprloc => {
2233 skip_bytes = input.read_uleb128().and_then(R::Offset::from_u64)?;
2234 }
2235 constants::DW_FORM_string => {
2236 let _ = input.read_null_terminated_slice()?;
2237 }
2238 constants::DW_FORM_udata
2239 | constants::DW_FORM_sdata
2240 | constants::DW_FORM_ref_udata
2241 | constants::DW_FORM_strx
2242 | constants::DW_FORM_GNU_str_index
2243 | constants::DW_FORM_addrx
2244 | constants::DW_FORM_GNU_addr_index
2245 | constants::DW_FORM_loclistx
2246 | constants::DW_FORM_rnglistx => {
2247 input.skip_leb128()?;
2248 }
2249 _ => {
2250 return Err(Error::UnknownForm(form));
2251 }
2252 };
2253 break;
2254 }
2255 }
2256 if skip_bytes != R::Offset::from_u8(0) {
2257 input.skip(skip_bytes)?;
2259 }
2260 Ok(())
2261}
2262
2263#[derive(Clone, Copy, Debug)]
2272pub struct AttrsIter<'abbrev, 'entry, 'unit, R: Reader> {
2273 input: R,
2274 attributes: &'abbrev [AttributeSpecification],
2275 entry: &'entry DebuggingInformationEntry<'abbrev, 'unit, R>,
2276}
2277
2278impl<'abbrev, 'entry, 'unit, R: Reader> AttrsIter<'abbrev, 'entry, 'unit, R> {
2279 #[inline(always)]
2285 pub fn next(&mut self) -> Result<Option<Attribute<R>>> {
2286 if self.attributes.is_empty() {
2287 if let Some(end) = self.entry.attrs_len.get() {
2292 debug_assert_eq!(end, self.input.offset_from(&self.entry.attrs_slice));
2293 } else {
2294 self.entry
2295 .attrs_len
2296 .set(Some(self.input.offset_from(&self.entry.attrs_slice)));
2297 }
2298
2299 return Ok(None);
2300 }
2301
2302 let spec = self.attributes[0];
2303 let rest_spec = &self.attributes[1..];
2304 match parse_attribute(&mut self.input, self.entry.unit.encoding(), spec) {
2305 Ok(attr) => {
2306 self.attributes = rest_spec;
2307 Ok(Some(attr))
2308 }
2309 Err(e) => {
2310 self.input.empty();
2311 Err(e)
2312 }
2313 }
2314 }
2315}
2316
2317#[cfg(feature = "fallible-iterator")]
2318impl<'abbrev, 'entry, 'unit, R: Reader> fallible_iterator::FallibleIterator
2319 for AttrsIter<'abbrev, 'entry, 'unit, R>
2320{
2321 type Item = Attribute<R>;
2322 type Error = Error;
2323
2324 fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
2325 AttrsIter::next(self)
2326 }
2327}
2328
2329#[derive(Clone, Debug)]
2382pub struct EntriesRaw<'abbrev, 'unit, R>
2383where
2384 R: Reader,
2385{
2386 input: R,
2387 unit: &'unit UnitHeader<R>,
2388 abbreviations: &'abbrev Abbreviations,
2389 depth: isize,
2390}
2391
2392impl<'abbrev, 'unit, R: Reader> EntriesRaw<'abbrev, 'unit, R> {
2393 #[inline]
2395 pub fn is_empty(&self) -> bool {
2396 self.input.is_empty()
2397 }
2398
2399 pub fn next_offset(&self) -> UnitOffset<R::Offset> {
2404 UnitOffset(self.unit.header_size() + self.input.offset_from(&self.unit.entries_buf))
2405 }
2406
2407 #[inline]
2412 pub fn next_depth(&self) -> isize {
2413 self.depth
2414 }
2415
2416 #[inline]
2420 pub fn read_abbreviation(&mut self) -> Result<Option<&'abbrev Abbreviation>> {
2421 let code = self.input.read_uleb128()?;
2422 if code == 0 {
2423 self.depth -= 1;
2424 return Ok(None);
2425 };
2426 let abbrev = self
2427 .abbreviations
2428 .get(code)
2429 .ok_or(Error::UnknownAbbreviation(code))?;
2430 if abbrev.has_children() {
2431 self.depth += 1;
2432 }
2433 Ok(Some(abbrev))
2434 }
2435
2436 #[inline]
2438 pub fn read_attribute(&mut self, spec: AttributeSpecification) -> Result<Attribute<R>> {
2439 parse_attribute(&mut self.input, self.unit.encoding(), spec)
2440 }
2441
2442 #[inline]
2444 pub fn skip_attributes(&mut self, specs: &[AttributeSpecification]) -> Result<()> {
2445 skip_attributes(&mut self.input, self.unit.encoding(), specs)
2446 }
2447}
2448
2449#[derive(Clone, Debug)]
2463pub struct EntriesCursor<'abbrev, 'unit, R>
2464where
2465 R: Reader,
2466{
2467 input: R,
2468 unit: &'unit UnitHeader<R>,
2469 abbreviations: &'abbrev Abbreviations,
2470 cached_current: Option<DebuggingInformationEntry<'abbrev, 'unit, R>>,
2471 delta_depth: isize,
2472}
2473
2474impl<'abbrev, 'unit, R: Reader> EntriesCursor<'abbrev, 'unit, R> {
2475 #[inline]
2480 pub fn current(&self) -> Option<&DebuggingInformationEntry<'abbrev, 'unit, R>> {
2481 self.cached_current.as_ref()
2482 }
2483
2484 pub fn next_entry(&mut self) -> Result<Option<()>> {
2489 if let Some(ref current) = self.cached_current {
2490 self.input = current.after_attrs()?;
2491 }
2492
2493 if self.input.is_empty() {
2494 self.cached_current = None;
2495 self.delta_depth = 0;
2496 return Ok(None);
2497 }
2498
2499 match DebuggingInformationEntry::parse(&mut self.input, self.unit, self.abbreviations) {
2500 Ok(Some(entry)) => {
2501 self.delta_depth = entry.has_children() as isize;
2502 self.cached_current = Some(entry);
2503 Ok(Some(()))
2504 }
2505 Ok(None) => {
2506 self.delta_depth = -1;
2507 self.cached_current = None;
2508 Ok(Some(()))
2509 }
2510 Err(e) => {
2511 self.input.empty();
2512 self.delta_depth = 0;
2513 self.cached_current = None;
2514 Err(e)
2515 }
2516 }
2517 }
2518
2519 pub fn next_dfs(
2637 &mut self,
2638 ) -> Result<Option<(isize, &DebuggingInformationEntry<'abbrev, 'unit, R>)>> {
2639 let mut delta_depth = self.delta_depth;
2640 loop {
2641 if self.next_entry()?.is_some() {
2643 if let Some(ref entry) = self.cached_current {
2644 return Ok(Some((delta_depth, entry)));
2645 }
2646
2647 delta_depth += self.delta_depth;
2649 } else {
2650 return Ok(None);
2651 }
2652 }
2653 }
2654
2655 pub fn next_sibling(
2762 &mut self,
2763 ) -> Result<Option<&DebuggingInformationEntry<'abbrev, 'unit, R>>> {
2764 if self.current().is_none() {
2765 return Ok(None);
2767 }
2768
2769 let mut depth = 0;
2771 loop {
2772 if self.current().is_some() && self.current().unwrap().has_children() {
2774 if let Some(sibling_input) = self.current().unwrap().sibling() {
2775 self.input = sibling_input;
2779 self.cached_current = None;
2780 } else {
2781 depth += 1;
2784 }
2785 }
2786
2787 if self.next_entry()?.is_none() {
2788 return Ok(None);
2790 }
2791
2792 if depth == 0 {
2793 return Ok(self.current());
2795 }
2796
2797 if self.current().is_none() {
2798 depth -= 1;
2801 }
2802 }
2803 }
2804}
2805
2806#[derive(Clone, Debug)]
2847pub struct EntriesTree<'abbrev, 'unit, R>
2848where
2849 R: Reader,
2850{
2851 root: R,
2852 unit: &'unit UnitHeader<R>,
2853 abbreviations: &'abbrev Abbreviations,
2854 input: R,
2855 entry: Option<DebuggingInformationEntry<'abbrev, 'unit, R>>,
2856 depth: isize,
2857}
2858
2859impl<'abbrev, 'unit, R: Reader> EntriesTree<'abbrev, 'unit, R> {
2860 fn new(root: R, unit: &'unit UnitHeader<R>, abbreviations: &'abbrev Abbreviations) -> Self {
2861 let input = root.clone();
2862 EntriesTree {
2863 root,
2864 unit,
2865 abbreviations,
2866 input,
2867 entry: None,
2868 depth: 0,
2869 }
2870 }
2871
2872 pub fn root<'me>(&'me mut self) -> Result<EntriesTreeNode<'abbrev, 'unit, 'me, R>> {
2874 self.input = self.root.clone();
2875 self.entry =
2876 DebuggingInformationEntry::parse(&mut self.input, self.unit, self.abbreviations)?;
2877 if self.entry.is_none() {
2878 return Err(Error::UnexpectedNull);
2879 }
2880 self.depth = 0;
2881 Ok(EntriesTreeNode::new(self, 1))
2882 }
2883
2884 fn next(&mut self, depth: isize) -> Result<bool> {
2890 if self.depth < depth {
2891 debug_assert_eq!(self.depth + 1, depth);
2892
2893 match self.entry {
2894 Some(ref entry) => {
2895 if !entry.has_children() {
2896 return Ok(false);
2897 }
2898 self.depth += 1;
2899 self.input = entry.after_attrs()?;
2900 }
2901 None => return Ok(false),
2902 }
2903
2904 if self.input.is_empty() {
2905 self.entry = None;
2906 return Ok(false);
2907 }
2908
2909 return match DebuggingInformationEntry::parse(
2910 &mut self.input,
2911 self.unit,
2912 self.abbreviations,
2913 ) {
2914 Ok(entry) => {
2915 self.entry = entry;
2916 Ok(self.entry.is_some())
2917 }
2918 Err(e) => {
2919 self.input.empty();
2920 self.entry = None;
2921 Err(e)
2922 }
2923 };
2924 }
2925
2926 loop {
2927 match self.entry {
2928 Some(ref entry) => {
2929 if entry.has_children() {
2930 if let Some(sibling_input) = entry.sibling() {
2931 self.input = sibling_input;
2935 } else {
2936 self.depth += 1;
2939 self.input = entry.after_attrs()?;
2940 }
2941 } else {
2942 self.input = entry.after_attrs()?;
2944 }
2945 }
2946 None => {
2947 self.depth -= 1;
2949 }
2950 }
2951
2952 if self.input.is_empty() {
2953 self.entry = None;
2954 return Ok(false);
2955 }
2956
2957 match DebuggingInformationEntry::parse(&mut self.input, self.unit, self.abbreviations) {
2958 Ok(entry) => {
2959 self.entry = entry;
2960 if self.depth == depth {
2961 return Ok(self.entry.is_some());
2962 }
2963 }
2964 Err(e) => {
2965 self.input.empty();
2966 self.entry = None;
2967 return Err(e);
2968 }
2969 }
2970 }
2971 }
2972}
2973
2974#[derive(Debug)]
2979pub struct EntriesTreeNode<'abbrev, 'unit, 'tree, R: Reader> {
2980 tree: &'tree mut EntriesTree<'abbrev, 'unit, R>,
2981 depth: isize,
2982}
2983
2984impl<'abbrev, 'unit, 'tree, R: Reader> EntriesTreeNode<'abbrev, 'unit, 'tree, R> {
2985 fn new(
2986 tree: &'tree mut EntriesTree<'abbrev, 'unit, R>,
2987 depth: isize,
2988 ) -> EntriesTreeNode<'abbrev, 'unit, 'tree, R> {
2989 debug_assert!(tree.entry.is_some());
2990 EntriesTreeNode { tree, depth }
2991 }
2992
2993 pub fn entry(&self) -> &DebuggingInformationEntry<'abbrev, 'unit, R> {
2995 self.tree.entry.as_ref().unwrap()
2997 }
2998
2999 pub fn children(self) -> EntriesTreeIter<'abbrev, 'unit, 'tree, R> {
3004 EntriesTreeIter::new(self.tree, self.depth)
3005 }
3006}
3007
3008#[derive(Debug)]
3014pub struct EntriesTreeIter<'abbrev, 'unit, 'tree, R: Reader> {
3015 tree: &'tree mut EntriesTree<'abbrev, 'unit, R>,
3016 depth: isize,
3017 empty: bool,
3018}
3019
3020impl<'abbrev, 'unit, 'tree, R: Reader> EntriesTreeIter<'abbrev, 'unit, 'tree, R> {
3021 fn new(
3022 tree: &'tree mut EntriesTree<'abbrev, 'unit, R>,
3023 depth: isize,
3024 ) -> EntriesTreeIter<'abbrev, 'unit, 'tree, R> {
3025 EntriesTreeIter {
3026 tree,
3027 depth,
3028 empty: false,
3029 }
3030 }
3031
3032 pub fn next<'me>(&'me mut self) -> Result<Option<EntriesTreeNode<'abbrev, 'unit, 'me, R>>> {
3036 if self.empty {
3037 Ok(None)
3038 } else if self.tree.next(self.depth)? {
3039 Ok(Some(EntriesTreeNode::new(self.tree, self.depth + 1)))
3040 } else {
3041 self.empty = true;
3042 Ok(None)
3043 }
3044 }
3045}
3046
3047fn parse_type_signature<R: Reader>(input: &mut R) -> Result<DebugTypeSignature> {
3050 input.read_u64().map(DebugTypeSignature)
3051}
3052
3053fn parse_type_offset<R: Reader>(input: &mut R, format: Format) -> Result<UnitOffset<R::Offset>> {
3055 input.read_offset(format).map(UnitOffset)
3056}
3057
3058#[derive(Debug, Default, Clone, Copy)]
3061pub struct DebugTypes<R> {
3062 debug_types_section: R,
3063}
3064
3065impl<'input, Endian> DebugTypes<EndianSlice<'input, Endian>>
3066where
3067 Endian: Endianity,
3068{
3069 pub fn new(debug_types_section: &'input [u8], endian: Endian) -> Self {
3084 Self::from(EndianSlice::new(debug_types_section, endian))
3085 }
3086}
3087
3088impl<T> DebugTypes<T> {
3089 pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugTypes<R>
3095 where
3096 F: FnMut(&'a T) -> R,
3097 {
3098 borrow(&self.debug_types_section).into()
3099 }
3100}
3101
3102impl<R> Section<R> for DebugTypes<R> {
3103 fn id() -> SectionId {
3104 SectionId::DebugTypes
3105 }
3106
3107 fn reader(&self) -> &R {
3108 &self.debug_types_section
3109 }
3110}
3111
3112impl<R> From<R> for DebugTypes<R> {
3113 fn from(debug_types_section: R) -> Self {
3114 DebugTypes {
3115 debug_types_section,
3116 }
3117 }
3118}
3119
3120impl<R: Reader> DebugTypes<R> {
3121 pub fn units(&self) -> DebugTypesUnitHeadersIter<R> {
3139 DebugTypesUnitHeadersIter {
3140 input: self.debug_types_section.clone(),
3141 offset: DebugTypesOffset(R::Offset::from_u8(0)),
3142 }
3143 }
3144}
3145
3146#[derive(Clone, Debug)]
3152pub struct DebugTypesUnitHeadersIter<R: Reader> {
3153 input: R,
3154 offset: DebugTypesOffset<R::Offset>,
3155}
3156
3157impl<R: Reader> DebugTypesUnitHeadersIter<R> {
3158 pub fn next(&mut self) -> Result<Option<UnitHeader<R>>> {
3160 if self.input.is_empty() {
3161 Ok(None)
3162 } else {
3163 let len = self.input.len();
3164 match parse_unit_header(&mut self.input, self.offset.into()) {
3165 Ok(header) => {
3166 self.offset.0 += len - self.input.len();
3167 Ok(Some(header))
3168 }
3169 Err(e) => {
3170 self.input.empty();
3171 Err(e)
3172 }
3173 }
3174 }
3175 }
3176}
3177
3178#[cfg(feature = "fallible-iterator")]
3179impl<R: Reader> fallible_iterator::FallibleIterator for DebugTypesUnitHeadersIter<R> {
3180 type Item = UnitHeader<R>;
3181 type Error = Error;
3182
3183 fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
3184 DebugTypesUnitHeadersIter::next(self)
3185 }
3186}
3187
3188#[cfg(test)]
3189#[cfg(feature = "write")]
3191mod tests {
3192 use super::*;
3193 use crate::constants;
3194 use crate::constants::*;
3195 use crate::endianity::{Endianity, LittleEndian};
3196 use crate::leb128;
3197 use crate::read::abbrev::tests::AbbrevSectionMethods;
3198 use crate::read::{
3199 Abbreviation, AttributeSpecification, DebugAbbrev, EndianSlice, Error, Result,
3200 };
3201 use crate::test_util::GimliSectionMethods;
3202 use alloc::vec::Vec;
3203 use core::cell::Cell;
3204 use test_assembler::{Endian, Label, LabelMaker, Section};
3205
3206 trait UnitSectionMethods {
3209 fn unit<E>(self, unit: &mut UnitHeader<EndianSlice<'_, E>>) -> Self
3210 where
3211 E: Endianity;
3212 fn die<F>(self, code: u64, attr: F) -> Self
3213 where
3214 F: Fn(Section) -> Section;
3215 fn die_null(self) -> Self;
3216 fn attr_string(self, s: &str) -> Self;
3217 fn attr_ref1(self, o: u8) -> Self;
3218 fn offset(self, offset: usize, format: Format) -> Self;
3219 }
3220
3221 impl UnitSectionMethods for Section {
3222 fn unit<E>(self, unit: &mut UnitHeader<EndianSlice<'_, E>>) -> Self
3223 where
3224 E: Endianity,
3225 {
3226 let size = self.size();
3227 let length = Label::new();
3228 let start = Label::new();
3229 let end = Label::new();
3230
3231 let section = match unit.format() {
3232 Format::Dwarf32 => self.L32(&length),
3233 Format::Dwarf64 => self.L32(0xffff_ffff).L64(&length),
3234 };
3235
3236 let section = match unit.version() {
3237 2..=4 => section
3238 .mark(&start)
3239 .L16(unit.version())
3240 .offset(unit.debug_abbrev_offset.0, unit.format())
3241 .D8(unit.address_size()),
3242 5 => section
3243 .mark(&start)
3244 .L16(unit.version())
3245 .D8(unit.type_().dw_ut().0)
3246 .D8(unit.address_size())
3247 .offset(unit.debug_abbrev_offset.0, unit.format()),
3248 _ => unreachable!(),
3249 };
3250
3251 let section = match unit.type_() {
3252 UnitType::Compilation | UnitType::Partial => {
3253 unit.unit_offset = DebugInfoOffset(size as usize).into();
3254 section
3255 }
3256 UnitType::Type {
3257 type_signature,
3258 type_offset,
3259 }
3260 | UnitType::SplitType {
3261 type_signature,
3262 type_offset,
3263 } => {
3264 if unit.version() == 5 {
3265 unit.unit_offset = DebugInfoOffset(size as usize).into();
3266 } else {
3267 unit.unit_offset = DebugTypesOffset(size as usize).into();
3268 }
3269 section
3270 .L64(type_signature.0)
3271 .offset(type_offset.0, unit.format())
3272 }
3273 UnitType::Skeleton(dwo_id) | UnitType::SplitCompilation(dwo_id) => {
3274 unit.unit_offset = DebugInfoOffset(size as usize).into();
3275 section.L64(dwo_id.0)
3276 }
3277 };
3278
3279 let section = section.append_bytes(unit.entries_buf.slice()).mark(&end);
3280
3281 unit.unit_length = (&end - &start) as usize;
3282 length.set_const(unit.unit_length as u64);
3283
3284 section
3285 }
3286
3287 fn die<F>(self, code: u64, attr: F) -> Self
3288 where
3289 F: Fn(Section) -> Section,
3290 {
3291 let section = self.uleb(code);
3292 attr(section)
3293 }
3294
3295 fn die_null(self) -> Self {
3296 self.D8(0)
3297 }
3298
3299 fn attr_string(self, attr: &str) -> Self {
3300 self.append_bytes(attr.as_bytes()).D8(0)
3301 }
3302
3303 fn attr_ref1(self, attr: u8) -> Self {
3304 self.D8(attr)
3305 }
3306
3307 fn offset(self, offset: usize, format: Format) -> Self {
3308 match format {
3309 Format::Dwarf32 => self.L32(offset as u32),
3310 Format::Dwarf64 => self.L64(offset as u64),
3311 }
3312 }
3313 }
3314
3315 #[test]
3317 fn test_unit_header_variance() {
3318 fn _f<'a: 'b, 'b, E: Endianity>(
3320 x: UnitHeader<EndianSlice<'a, E>>,
3321 ) -> UnitHeader<EndianSlice<'b, E>> {
3322 x
3323 }
3324 }
3325
3326 #[test]
3327 fn test_parse_debug_abbrev_offset_32() {
3328 let section = Section::with_endian(Endian::Little).L32(0x0403_0201);
3329 let buf = section.get_contents().unwrap();
3330 let buf = &mut EndianSlice::new(&buf, LittleEndian);
3331
3332 match parse_debug_abbrev_offset(buf, Format::Dwarf32) {
3333 Ok(val) => assert_eq!(val, DebugAbbrevOffset(0x0403_0201)),
3334 otherwise => panic!("Unexpected result: {:?}", otherwise),
3335 };
3336 }
3337
3338 #[test]
3339 fn test_parse_debug_abbrev_offset_32_incomplete() {
3340 let buf = [0x01, 0x02];
3341 let buf = &mut EndianSlice::new(&buf, LittleEndian);
3342
3343 match parse_debug_abbrev_offset(buf, Format::Dwarf32) {
3344 Err(Error::UnexpectedEof(_)) => {}
3345 otherwise => panic!("Unexpected result: {:?}", otherwise),
3346 };
3347 }
3348
3349 #[test]
3350 #[cfg(target_pointer_width = "64")]
3351 fn test_parse_debug_abbrev_offset_64() {
3352 let section = Section::with_endian(Endian::Little).L64(0x0807_0605_0403_0201);
3353 let buf = section.get_contents().unwrap();
3354 let buf = &mut EndianSlice::new(&buf, LittleEndian);
3355
3356 match parse_debug_abbrev_offset(buf, Format::Dwarf64) {
3357 Ok(val) => assert_eq!(val, DebugAbbrevOffset(0x0807_0605_0403_0201)),
3358 otherwise => panic!("Unexpected result: {:?}", otherwise),
3359 };
3360 }
3361
3362 #[test]
3363 fn test_parse_debug_abbrev_offset_64_incomplete() {
3364 let buf = [0x01, 0x02];
3365 let buf = &mut EndianSlice::new(&buf, LittleEndian);
3366
3367 match parse_debug_abbrev_offset(buf, Format::Dwarf64) {
3368 Err(Error::UnexpectedEof(_)) => {}
3369 otherwise => panic!("Unexpected result: {:?}", otherwise),
3370 };
3371 }
3372
3373 #[test]
3374 fn test_parse_debug_info_offset_32() {
3375 let section = Section::with_endian(Endian::Little).L32(0x0403_0201);
3376 let buf = section.get_contents().unwrap();
3377 let buf = &mut EndianSlice::new(&buf, LittleEndian);
3378
3379 match parse_debug_info_offset(buf, Format::Dwarf32) {
3380 Ok(val) => assert_eq!(val, DebugInfoOffset(0x0403_0201)),
3381 otherwise => panic!("Unexpected result: {:?}", otherwise),
3382 };
3383 }
3384
3385 #[test]
3386 fn test_parse_debug_info_offset_32_incomplete() {
3387 let buf = [0x01, 0x02];
3388 let buf = &mut EndianSlice::new(&buf, LittleEndian);
3389
3390 match parse_debug_info_offset(buf, Format::Dwarf32) {
3391 Err(Error::UnexpectedEof(_)) => {}
3392 otherwise => panic!("Unexpected result: {:?}", otherwise),
3393 };
3394 }
3395
3396 #[test]
3397 #[cfg(target_pointer_width = "64")]
3398 fn test_parse_debug_info_offset_64() {
3399 let section = Section::with_endian(Endian::Little).L64(0x0807_0605_0403_0201);
3400 let buf = section.get_contents().unwrap();
3401 let buf = &mut EndianSlice::new(&buf, LittleEndian);
3402
3403 match parse_debug_info_offset(buf, Format::Dwarf64) {
3404 Ok(val) => assert_eq!(val, DebugInfoOffset(0x0807_0605_0403_0201)),
3405 otherwise => panic!("Unexpected result: {:?}", otherwise),
3406 };
3407 }
3408
3409 #[test]
3410 fn test_parse_debug_info_offset_64_incomplete() {
3411 let buf = [0x01, 0x02];
3412 let buf = &mut EndianSlice::new(&buf, LittleEndian);
3413
3414 match parse_debug_info_offset(buf, Format::Dwarf64) {
3415 Err(Error::UnexpectedEof(_)) => {}
3416 otherwise => panic!("Unexpected result: {:?}", otherwise),
3417 };
3418 }
3419
3420 #[test]
3421 #[cfg(target_pointer_width = "64")]
3422 fn test_units() {
3423 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3424 let mut unit64 = UnitHeader {
3425 encoding: Encoding {
3426 format: Format::Dwarf64,
3427 version: 4,
3428 address_size: 8,
3429 },
3430 unit_length: 0,
3431 unit_type: UnitType::Compilation,
3432 debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
3433 unit_offset: DebugInfoOffset(0).into(),
3434 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3435 };
3436 let mut unit32 = UnitHeader {
3437 encoding: Encoding {
3438 format: Format::Dwarf32,
3439 version: 4,
3440 address_size: 4,
3441 },
3442 unit_length: 0,
3443 unit_type: UnitType::Compilation,
3444 debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3445 unit_offset: DebugInfoOffset(0).into(),
3446 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3447 };
3448 let section = Section::with_endian(Endian::Little)
3449 .unit(&mut unit64)
3450 .unit(&mut unit32);
3451 let buf = section.get_contents().unwrap();
3452
3453 let debug_info = DebugInfo::new(&buf, LittleEndian);
3454 let mut units = debug_info.units();
3455
3456 assert_eq!(units.next(), Ok(Some(unit64)));
3457 assert_eq!(units.next(), Ok(Some(unit32)));
3458 assert_eq!(units.next(), Ok(None));
3459 }
3460
3461 #[test]
3462 fn test_unit_version_unknown_version() {
3463 let buf = [0x02, 0x00, 0x00, 0x00, 0xab, 0xcd];
3464 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3465
3466 match parse_unit_header(rest, DebugInfoOffset(0).into()) {
3467 Err(Error::UnknownVersion(0xcdab)) => {}
3468 otherwise => panic!("Unexpected result: {:?}", otherwise),
3469 };
3470
3471 let buf = [0x02, 0x00, 0x00, 0x00, 0x1, 0x0];
3472 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3473
3474 match parse_unit_header(rest, DebugInfoOffset(0).into()) {
3475 Err(Error::UnknownVersion(1)) => {}
3476 otherwise => panic!("Unexpected result: {:?}", otherwise),
3477 };
3478 }
3479
3480 #[test]
3481 fn test_unit_version_incomplete() {
3482 let buf = [0x01, 0x00, 0x00, 0x00, 0x04];
3483 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3484
3485 match parse_unit_header(rest, DebugInfoOffset(0).into()) {
3486 Err(Error::UnexpectedEof(_)) => {}
3487 otherwise => panic!("Unexpected result: {:?}", otherwise),
3488 };
3489 }
3490
3491 #[test]
3492 fn test_parse_unit_header_32_ok() {
3493 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3494 let encoding = Encoding {
3495 format: Format::Dwarf32,
3496 version: 4,
3497 address_size: 4,
3498 };
3499 let mut expected_unit = UnitHeader {
3500 encoding,
3501 unit_length: 0,
3502 unit_type: UnitType::Compilation,
3503 debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3504 unit_offset: DebugInfoOffset(0).into(),
3505 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3506 };
3507 let section = Section::with_endian(Endian::Little)
3508 .unit(&mut expected_unit)
3509 .append_bytes(expected_rest);
3510 let buf = section.get_contents().unwrap();
3511 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3512
3513 assert_eq!(
3514 parse_unit_header(rest, DebugInfoOffset(0).into()),
3515 Ok(expected_unit)
3516 );
3517 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3518 }
3519
3520 #[test]
3521 #[cfg(target_pointer_width = "64")]
3522 fn test_parse_unit_header_64_ok() {
3523 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3524 let encoding = Encoding {
3525 format: Format::Dwarf64,
3526 version: 4,
3527 address_size: 8,
3528 };
3529 let mut expected_unit = UnitHeader {
3530 encoding,
3531 unit_length: 0,
3532 unit_type: UnitType::Compilation,
3533 debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
3534 unit_offset: DebugInfoOffset(0).into(),
3535 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3536 };
3537 let section = Section::with_endian(Endian::Little)
3538 .unit(&mut expected_unit)
3539 .append_bytes(expected_rest);
3540 let buf = section.get_contents().unwrap();
3541 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3542
3543 assert_eq!(
3544 parse_unit_header(rest, DebugInfoOffset(0).into()),
3545 Ok(expected_unit)
3546 );
3547 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3548 }
3549
3550 #[test]
3551 fn test_parse_v5_unit_header_32_ok() {
3552 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3553 let encoding = Encoding {
3554 format: Format::Dwarf32,
3555 version: 5,
3556 address_size: 4,
3557 };
3558 let mut expected_unit = UnitHeader {
3559 encoding,
3560 unit_length: 0,
3561 unit_type: UnitType::Compilation,
3562 debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3563 unit_offset: DebugInfoOffset(0).into(),
3564 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3565 };
3566 let section = Section::with_endian(Endian::Little)
3567 .unit(&mut expected_unit)
3568 .append_bytes(expected_rest);
3569 let buf = section.get_contents().unwrap();
3570 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3571
3572 assert_eq!(
3573 parse_unit_header(rest, DebugInfoOffset(0).into()),
3574 Ok(expected_unit)
3575 );
3576 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3577 }
3578
3579 #[test]
3580 #[cfg(target_pointer_width = "64")]
3581 fn test_parse_v5_unit_header_64_ok() {
3582 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3583 let encoding = Encoding {
3584 format: Format::Dwarf64,
3585 version: 5,
3586 address_size: 8,
3587 };
3588 let mut expected_unit = UnitHeader {
3589 encoding,
3590 unit_length: 0,
3591 unit_type: UnitType::Compilation,
3592 debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
3593 unit_offset: DebugInfoOffset(0).into(),
3594 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3595 };
3596 let section = Section::with_endian(Endian::Little)
3597 .unit(&mut expected_unit)
3598 .append_bytes(expected_rest);
3599 let buf = section.get_contents().unwrap();
3600 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3601
3602 assert_eq!(
3603 parse_unit_header(rest, DebugInfoOffset(0).into()),
3604 Ok(expected_unit)
3605 );
3606 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3607 }
3608
3609 #[test]
3610 fn test_parse_v5_partial_unit_header_32_ok() {
3611 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3612 let encoding = Encoding {
3613 format: Format::Dwarf32,
3614 version: 5,
3615 address_size: 4,
3616 };
3617 let mut expected_unit = UnitHeader {
3618 encoding,
3619 unit_length: 0,
3620 unit_type: UnitType::Partial,
3621 debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3622 unit_offset: DebugInfoOffset(0).into(),
3623 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3624 };
3625 let section = Section::with_endian(Endian::Little)
3626 .unit(&mut expected_unit)
3627 .append_bytes(expected_rest);
3628 let buf = section.get_contents().unwrap();
3629 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3630
3631 assert_eq!(
3632 parse_unit_header(rest, DebugInfoOffset(0).into()),
3633 Ok(expected_unit)
3634 );
3635 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3636 }
3637
3638 #[test]
3639 #[cfg(target_pointer_width = "64")]
3640 fn test_parse_v5_partial_unit_header_64_ok() {
3641 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3642 let encoding = Encoding {
3643 format: Format::Dwarf64,
3644 version: 5,
3645 address_size: 8,
3646 };
3647 let mut expected_unit = UnitHeader {
3648 encoding,
3649 unit_length: 0,
3650 unit_type: UnitType::Partial,
3651 debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
3652 unit_offset: DebugInfoOffset(0).into(),
3653 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3654 };
3655 let section = Section::with_endian(Endian::Little)
3656 .unit(&mut expected_unit)
3657 .append_bytes(expected_rest);
3658 let buf = section.get_contents().unwrap();
3659 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3660
3661 assert_eq!(
3662 parse_unit_header(rest, DebugInfoOffset(0).into()),
3663 Ok(expected_unit)
3664 );
3665 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3666 }
3667
3668 #[test]
3669 fn test_parse_v5_skeleton_unit_header_32_ok() {
3670 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3671 let encoding = Encoding {
3672 format: Format::Dwarf32,
3673 version: 5,
3674 address_size: 4,
3675 };
3676 let mut expected_unit = UnitHeader {
3677 encoding,
3678 unit_length: 0,
3679 unit_type: UnitType::Skeleton(DwoId(0x0706_5040_0302_1000)),
3680 debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3681 unit_offset: DebugInfoOffset(0).into(),
3682 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3683 };
3684 let section = Section::with_endian(Endian::Little)
3685 .unit(&mut expected_unit)
3686 .append_bytes(expected_rest);
3687 let buf = section.get_contents().unwrap();
3688 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3689
3690 assert_eq!(
3691 parse_unit_header(rest, DebugInfoOffset(0).into()),
3692 Ok(expected_unit)
3693 );
3694 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3695 }
3696
3697 #[test]
3698 #[cfg(target_pointer_width = "64")]
3699 fn test_parse_v5_skeleton_unit_header_64_ok() {
3700 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3701 let encoding = Encoding {
3702 format: Format::Dwarf64,
3703 version: 5,
3704 address_size: 8,
3705 };
3706 let mut expected_unit = UnitHeader {
3707 encoding,
3708 unit_length: 0,
3709 unit_type: UnitType::Skeleton(DwoId(0x0706_5040_0302_1000)),
3710 debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
3711 unit_offset: DebugInfoOffset(0).into(),
3712 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3713 };
3714 let section = Section::with_endian(Endian::Little)
3715 .unit(&mut expected_unit)
3716 .append_bytes(expected_rest);
3717 let buf = section.get_contents().unwrap();
3718 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3719
3720 assert_eq!(
3721 parse_unit_header(rest, DebugInfoOffset(0).into()),
3722 Ok(expected_unit)
3723 );
3724 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3725 }
3726
3727 #[test]
3728 fn test_parse_v5_split_compilation_unit_header_32_ok() {
3729 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3730 let encoding = Encoding {
3731 format: Format::Dwarf32,
3732 version: 5,
3733 address_size: 4,
3734 };
3735 let mut expected_unit = UnitHeader {
3736 encoding,
3737 unit_length: 0,
3738 unit_type: UnitType::SplitCompilation(DwoId(0x0706_5040_0302_1000)),
3739 debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3740 unit_offset: DebugInfoOffset(0).into(),
3741 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3742 };
3743 let section = Section::with_endian(Endian::Little)
3744 .unit(&mut expected_unit)
3745 .append_bytes(expected_rest);
3746 let buf = section.get_contents().unwrap();
3747 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3748
3749 assert_eq!(
3750 parse_unit_header(rest, DebugInfoOffset(0).into()),
3751 Ok(expected_unit)
3752 );
3753 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3754 }
3755
3756 #[test]
3757 #[cfg(target_pointer_width = "64")]
3758 fn test_parse_v5_split_compilation_unit_header_64_ok() {
3759 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3760 let encoding = Encoding {
3761 format: Format::Dwarf64,
3762 version: 5,
3763 address_size: 8,
3764 };
3765 let mut expected_unit = UnitHeader {
3766 encoding,
3767 unit_length: 0,
3768 unit_type: UnitType::SplitCompilation(DwoId(0x0706_5040_0302_1000)),
3769 debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
3770 unit_offset: DebugInfoOffset(0).into(),
3771 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3772 };
3773 let section = Section::with_endian(Endian::Little)
3774 .unit(&mut expected_unit)
3775 .append_bytes(expected_rest);
3776 let buf = section.get_contents().unwrap();
3777 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3778
3779 assert_eq!(
3780 parse_unit_header(rest, DebugInfoOffset(0).into()),
3781 Ok(expected_unit)
3782 );
3783 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3784 }
3785
3786 #[test]
3787 fn test_parse_type_offset_32_ok() {
3788 let buf = [0x12, 0x34, 0x56, 0x78, 0x00];
3789 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3790
3791 match parse_type_offset(rest, Format::Dwarf32) {
3792 Ok(offset) => {
3793 assert_eq!(rest.len(), 1);
3794 assert_eq!(UnitOffset(0x7856_3412), offset);
3795 }
3796 otherwise => panic!("Unexpected result: {:?}", otherwise),
3797 }
3798 }
3799
3800 #[test]
3801 #[cfg(target_pointer_width = "64")]
3802 fn test_parse_type_offset_64_ok() {
3803 let buf = [0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xff, 0x00];
3804 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3805
3806 match parse_type_offset(rest, Format::Dwarf64) {
3807 Ok(offset) => {
3808 assert_eq!(rest.len(), 1);
3809 assert_eq!(UnitOffset(0xffde_bc9a_7856_3412), offset);
3810 }
3811 otherwise => panic!("Unexpected result: {:?}", otherwise),
3812 }
3813 }
3814
3815 #[test]
3816 fn test_parse_type_offset_incomplete() {
3817 let buf = [0xff, 0xff, 0xff];
3819 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3820
3821 match parse_type_offset(rest, Format::Dwarf32) {
3822 Err(Error::UnexpectedEof(_)) => {}
3823 otherwise => panic!("Unexpected result: {:?}", otherwise),
3824 };
3825 }
3826
3827 #[test]
3828 fn test_parse_type_unit_header_32_ok() {
3829 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3830 let encoding = Encoding {
3831 format: Format::Dwarf32,
3832 version: 4,
3833 address_size: 8,
3834 };
3835 let mut expected_unit = UnitHeader {
3836 encoding,
3837 unit_length: 0,
3838 unit_type: UnitType::Type {
3839 type_signature: DebugTypeSignature(0xdead_beef_dead_beef),
3840 type_offset: UnitOffset(0x7856_3412),
3841 },
3842 debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3843 unit_offset: DebugTypesOffset(0).into(),
3844 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3845 };
3846 let section = Section::with_endian(Endian::Little)
3847 .unit(&mut expected_unit)
3848 .append_bytes(expected_rest);
3849 let buf = section.get_contents().unwrap();
3850 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3851
3852 assert_eq!(
3853 parse_unit_header(rest, DebugTypesOffset(0).into()),
3854 Ok(expected_unit)
3855 );
3856 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3857 }
3858
3859 #[test]
3860 #[cfg(target_pointer_width = "64")]
3861 fn test_parse_type_unit_header_64_ok() {
3862 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3863 let encoding = Encoding {
3864 format: Format::Dwarf64,
3865 version: 4,
3866 address_size: 8,
3867 };
3868 let mut expected_unit = UnitHeader {
3869 encoding,
3870 unit_length: 0,
3871 unit_type: UnitType::Type {
3872 type_signature: DebugTypeSignature(0xdead_beef_dead_beef),
3873 type_offset: UnitOffset(0x7856_3412_7856_3412),
3874 },
3875 debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3876 unit_offset: DebugTypesOffset(0).into(),
3877 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3878 };
3879 let section = Section::with_endian(Endian::Little)
3880 .unit(&mut expected_unit)
3881 .append_bytes(expected_rest);
3882 let buf = section.get_contents().unwrap();
3883 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3884
3885 assert_eq!(
3886 parse_unit_header(rest, DebugTypesOffset(0).into()),
3887 Ok(expected_unit)
3888 );
3889 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3890 }
3891
3892 #[test]
3893 fn test_parse_v5_type_unit_header_32_ok() {
3894 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3895 let encoding = Encoding {
3896 format: Format::Dwarf32,
3897 version: 5,
3898 address_size: 8,
3899 };
3900 let mut expected_unit = UnitHeader {
3901 encoding,
3902 unit_length: 0,
3903 unit_type: UnitType::Type {
3904 type_signature: DebugTypeSignature(0xdead_beef_dead_beef),
3905 type_offset: UnitOffset(0x7856_3412),
3906 },
3907 debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3908 unit_offset: DebugInfoOffset(0).into(),
3909 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3910 };
3911 let section = Section::with_endian(Endian::Little)
3912 .unit(&mut expected_unit)
3913 .append_bytes(expected_rest);
3914 let buf = section.get_contents().unwrap();
3915 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3916
3917 assert_eq!(
3918 parse_unit_header(rest, DebugInfoOffset(0).into()),
3919 Ok(expected_unit)
3920 );
3921 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3922 }
3923
3924 #[test]
3925 #[cfg(target_pointer_width = "64")]
3926 fn test_parse_v5_type_unit_header_64_ok() {
3927 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3928 let encoding = Encoding {
3929 format: Format::Dwarf64,
3930 version: 5,
3931 address_size: 8,
3932 };
3933 let mut expected_unit = UnitHeader {
3934 encoding,
3935 unit_length: 0,
3936 unit_type: UnitType::Type {
3937 type_signature: DebugTypeSignature(0xdead_beef_dead_beef),
3938 type_offset: UnitOffset(0x7856_3412_7856_3412),
3939 },
3940 debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3941 unit_offset: DebugInfoOffset(0).into(),
3942 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3943 };
3944 let section = Section::with_endian(Endian::Little)
3945 .unit(&mut expected_unit)
3946 .append_bytes(expected_rest);
3947 let buf = section.get_contents().unwrap();
3948 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3949
3950 assert_eq!(
3951 parse_unit_header(rest, DebugInfoOffset(0).into()),
3952 Ok(expected_unit)
3953 );
3954 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3955 }
3956
3957 #[test]
3958 fn test_parse_v5_split_type_unit_header_32_ok() {
3959 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3960 let encoding = Encoding {
3961 format: Format::Dwarf32,
3962 version: 5,
3963 address_size: 8,
3964 };
3965 let mut expected_unit = UnitHeader {
3966 encoding,
3967 unit_length: 0,
3968 unit_type: UnitType::SplitType {
3969 type_signature: DebugTypeSignature(0xdead_beef_dead_beef),
3970 type_offset: UnitOffset(0x7856_3412),
3971 },
3972 debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3973 unit_offset: DebugInfoOffset(0).into(),
3974 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3975 };
3976 let section = Section::with_endian(Endian::Little)
3977 .unit(&mut expected_unit)
3978 .append_bytes(expected_rest);
3979 let buf = section.get_contents().unwrap();
3980 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3981
3982 assert_eq!(
3983 parse_unit_header(rest, DebugInfoOffset(0).into()),
3984 Ok(expected_unit)
3985 );
3986 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3987 }
3988
3989 #[test]
3990 #[cfg(target_pointer_width = "64")]
3991 fn test_parse_v5_split_type_unit_header_64_ok() {
3992 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3993 let encoding = Encoding {
3994 format: Format::Dwarf64,
3995 version: 5,
3996 address_size: 8,
3997 };
3998 let mut expected_unit = UnitHeader {
3999 encoding,
4000 unit_length: 0,
4001 unit_type: UnitType::SplitType {
4002 type_signature: DebugTypeSignature(0xdead_beef_dead_beef),
4003 type_offset: UnitOffset(0x7856_3412_7856_3412),
4004 },
4005 debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
4006 unit_offset: DebugInfoOffset(0).into(),
4007 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
4008 };
4009 let section = Section::with_endian(Endian::Little)
4010 .unit(&mut expected_unit)
4011 .append_bytes(expected_rest);
4012 let buf = section.get_contents().unwrap();
4013 let rest = &mut EndianSlice::new(&buf, LittleEndian);
4014
4015 assert_eq!(
4016 parse_unit_header(rest, DebugInfoOffset(0).into()),
4017 Ok(expected_unit)
4018 );
4019 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
4020 }
4021
4022 fn section_contents<F>(f: F) -> Vec<u8>
4023 where
4024 F: Fn(Section) -> Section,
4025 {
4026 f(Section::with_endian(Endian::Little))
4027 .get_contents()
4028 .unwrap()
4029 }
4030
4031 #[test]
4032 fn test_attribute_value() {
4033 let mut unit = test_parse_attribute_unit_default();
4034 let endian = unit.entries_buf.endian();
4035
4036 let block_data = &[1, 2, 3, 4];
4037 let buf = section_contents(|s| s.uleb(block_data.len() as u64).append_bytes(block_data));
4038 let block = EndianSlice::new(&buf, endian);
4039
4040 let buf = section_contents(|s| s.L32(0x0102_0304));
4041 let data4 = EndianSlice::new(&buf, endian);
4042
4043 let buf = section_contents(|s| s.L64(0x0102_0304_0506_0708));
4044 let data8 = EndianSlice::new(&buf, endian);
4045
4046 let tests = [
4047 (
4048 Format::Dwarf32,
4049 2,
4050 constants::DW_AT_data_member_location,
4051 constants::DW_FORM_block,
4052 block,
4053 AttributeValue::Block(EndianSlice::new(block_data, endian)),
4054 AttributeValue::Exprloc(Expression(EndianSlice::new(block_data, endian))),
4055 ),
4056 (
4057 Format::Dwarf32,
4058 2,
4059 constants::DW_AT_data_member_location,
4060 constants::DW_FORM_data4,
4061 data4,
4062 AttributeValue::SecOffset(0x0102_0304),
4063 AttributeValue::LocationListsRef(LocationListsOffset(0x0102_0304)),
4064 ),
4065 (
4066 Format::Dwarf64,
4067 2,
4068 constants::DW_AT_data_member_location,
4069 constants::DW_FORM_data4,
4070 data4,
4071 AttributeValue::Data4(0x0102_0304),
4072 AttributeValue::Udata(0x0102_0304),
4073 ),
4074 (
4075 Format::Dwarf32,
4076 4,
4077 constants::DW_AT_data_member_location,
4078 constants::DW_FORM_data4,
4079 data4,
4080 AttributeValue::Data4(0x0102_0304),
4081 AttributeValue::Udata(0x0102_0304),
4082 ),
4083 (
4084 Format::Dwarf32,
4085 2,
4086 constants::DW_AT_data_member_location,
4087 constants::DW_FORM_data8,
4088 data8,
4089 AttributeValue::Data8(0x0102_0304_0506_0708),
4090 AttributeValue::Udata(0x0102_0304_0506_0708),
4091 ),
4092 #[cfg(target_pointer_width = "64")]
4093 (
4094 Format::Dwarf64,
4095 2,
4096 constants::DW_AT_data_member_location,
4097 constants::DW_FORM_data8,
4098 data8,
4099 AttributeValue::SecOffset(0x0102_0304_0506_0708),
4100 AttributeValue::LocationListsRef(LocationListsOffset(0x0102_0304_0506_0708)),
4101 ),
4102 (
4103 Format::Dwarf64,
4104 4,
4105 constants::DW_AT_data_member_location,
4106 constants::DW_FORM_data8,
4107 data8,
4108 AttributeValue::Data8(0x0102_0304_0506_0708),
4109 AttributeValue::Udata(0x0102_0304_0506_0708),
4110 ),
4111 (
4112 Format::Dwarf32,
4113 4,
4114 constants::DW_AT_location,
4115 constants::DW_FORM_data4,
4116 data4,
4117 AttributeValue::SecOffset(0x0102_0304),
4118 AttributeValue::LocationListsRef(LocationListsOffset(0x0102_0304)),
4119 ),
4120 #[cfg(target_pointer_width = "64")]
4121 (
4122 Format::Dwarf64,
4123 4,
4124 constants::DW_AT_location,
4125 constants::DW_FORM_data8,
4126 data8,
4127 AttributeValue::SecOffset(0x0102_0304_0506_0708),
4128 AttributeValue::LocationListsRef(LocationListsOffset(0x0102_0304_0506_0708)),
4129 ),
4130 (
4131 Format::Dwarf32,
4132 4,
4133 constants::DW_AT_str_offsets_base,
4134 constants::DW_FORM_sec_offset,
4135 data4,
4136 AttributeValue::SecOffset(0x0102_0304),
4137 AttributeValue::DebugStrOffsetsBase(DebugStrOffsetsBase(0x0102_0304)),
4138 ),
4139 (
4140 Format::Dwarf32,
4141 4,
4142 constants::DW_AT_stmt_list,
4143 constants::DW_FORM_sec_offset,
4144 data4,
4145 AttributeValue::SecOffset(0x0102_0304),
4146 AttributeValue::DebugLineRef(DebugLineOffset(0x0102_0304)),
4147 ),
4148 (
4149 Format::Dwarf32,
4150 4,
4151 constants::DW_AT_addr_base,
4152 constants::DW_FORM_sec_offset,
4153 data4,
4154 AttributeValue::SecOffset(0x0102_0304),
4155 AttributeValue::DebugAddrBase(DebugAddrBase(0x0102_0304)),
4156 ),
4157 (
4158 Format::Dwarf32,
4159 4,
4160 constants::DW_AT_rnglists_base,
4161 constants::DW_FORM_sec_offset,
4162 data4,
4163 AttributeValue::SecOffset(0x0102_0304),
4164 AttributeValue::DebugRngListsBase(DebugRngListsBase(0x0102_0304)),
4165 ),
4166 (
4167 Format::Dwarf32,
4168 4,
4169 constants::DW_AT_loclists_base,
4170 constants::DW_FORM_sec_offset,
4171 data4,
4172 AttributeValue::SecOffset(0x0102_0304),
4173 AttributeValue::DebugLocListsBase(DebugLocListsBase(0x0102_0304)),
4174 ),
4175 ];
4176
4177 for test in tests.iter() {
4178 let (format, version, name, form, mut input, expect_raw, expect_value) = *test;
4179 unit.encoding.format = format;
4180 unit.encoding.version = version;
4181 let spec = AttributeSpecification::new(name, form, None);
4182 let attribute =
4183 parse_attribute(&mut input, unit.encoding(), spec).expect("Should parse attribute");
4184 assert_eq!(attribute.raw_value(), expect_raw);
4185 assert_eq!(attribute.value(), expect_value);
4186 }
4187 }
4188
4189 #[test]
4190 fn test_attribute_udata_sdata_value() {
4191 #[allow(clippy::type_complexity)]
4192 let tests: &[(
4193 AttributeValue<EndianSlice<'_, LittleEndian>>,
4194 Option<u64>,
4195 Option<i64>,
4196 )] = &[
4197 (AttributeValue::Data1(1), Some(1), Some(1)),
4198 (
4199 AttributeValue::Data1(u8::MAX),
4200 Some(u64::from(u8::MAX)),
4201 Some(-1),
4202 ),
4203 (AttributeValue::Data2(1), Some(1), Some(1)),
4204 (
4205 AttributeValue::Data2(u16::MAX),
4206 Some(u64::from(u16::MAX)),
4207 Some(-1),
4208 ),
4209 (AttributeValue::Data4(1), Some(1), Some(1)),
4210 (
4211 AttributeValue::Data4(u32::MAX),
4212 Some(u64::from(u32::MAX)),
4213 Some(-1),
4214 ),
4215 (AttributeValue::Data8(1), Some(1), Some(1)),
4216 (AttributeValue::Data8(u64::MAX), Some(u64::MAX), Some(-1)),
4217 (AttributeValue::Sdata(1), Some(1), Some(1)),
4218 (AttributeValue::Sdata(-1), None, Some(-1)),
4219 (AttributeValue::Udata(1), Some(1), Some(1)),
4220 (AttributeValue::Udata(1u64 << 63), Some(1u64 << 63), None),
4221 ];
4222 for test in tests.iter() {
4223 let (value, expect_udata, expect_sdata) = *test;
4224 let attribute = Attribute {
4225 name: DW_AT_data_member_location,
4226 value,
4227 };
4228 assert_eq!(attribute.udata_value(), expect_udata);
4229 assert_eq!(attribute.sdata_value(), expect_sdata);
4230 }
4231 }
4232
4233 fn test_parse_attribute_unit<Endian>(
4234 address_size: u8,
4235 format: Format,
4236 endian: Endian,
4237 ) -> UnitHeader<EndianSlice<'static, Endian>>
4238 where
4239 Endian: Endianity,
4240 {
4241 let encoding = Encoding {
4242 format,
4243 version: 4,
4244 address_size,
4245 };
4246 UnitHeader::new(
4247 encoding,
4248 7,
4249 UnitType::Compilation,
4250 DebugAbbrevOffset(0x0807_0605),
4251 DebugInfoOffset(0).into(),
4252 EndianSlice::new(&[], endian),
4253 )
4254 }
4255
4256 fn test_parse_attribute_unit_default() -> UnitHeader<EndianSlice<'static, LittleEndian>> {
4257 test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian)
4258 }
4259
4260 fn test_parse_attribute<'input, Endian>(
4261 buf: &'input [u8],
4262 len: usize,
4263 unit: &UnitHeader<EndianSlice<'input, Endian>>,
4264 form: constants::DwForm,
4265 value: AttributeValue<EndianSlice<'input, Endian>>,
4266 ) where
4267 Endian: Endianity,
4268 {
4269 let spec = AttributeSpecification::new(constants::DW_AT_low_pc, form, None);
4270
4271 let expect = Attribute {
4272 name: constants::DW_AT_low_pc,
4273 value,
4274 };
4275
4276 let rest = &mut EndianSlice::new(buf, Endian::default());
4277 match parse_attribute(rest, unit.encoding(), spec) {
4278 Ok(attr) => {
4279 assert_eq!(attr, expect);
4280 assert_eq!(*rest, EndianSlice::new(&buf[len..], Endian::default()));
4281 if let Some(size) = spec.size(unit) {
4282 assert_eq!(rest.len() + size, buf.len());
4283 }
4284 }
4285 otherwise => {
4286 panic!("Unexpected parse result = {:#?}", otherwise);
4287 }
4288 };
4289 }
4290
4291 #[test]
4292 fn test_parse_attribute_addr() {
4293 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
4294 let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4295 let form = constants::DW_FORM_addr;
4296 let value = AttributeValue::Addr(0x0403_0201);
4297 test_parse_attribute(&buf, 4, &unit, form, value);
4298 }
4299
4300 #[test]
4301 fn test_parse_attribute_addr8() {
4302 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
4303 let unit = test_parse_attribute_unit(8, Format::Dwarf32, LittleEndian);
4304 let form = constants::DW_FORM_addr;
4305 let value = AttributeValue::Addr(0x0807_0605_0403_0201);
4306 test_parse_attribute(&buf, 8, &unit, form, value);
4307 }
4308
4309 #[test]
4310 fn test_parse_attribute_block1() {
4311 let buf = [0x03, 0x09, 0x09, 0x09, 0x00, 0x00];
4313 let unit = test_parse_attribute_unit_default();
4314 let form = constants::DW_FORM_block1;
4315 let value = AttributeValue::Block(EndianSlice::new(&buf[1..4], LittleEndian));
4316 test_parse_attribute(&buf, 4, &unit, form, value);
4317 }
4318
4319 #[test]
4320 fn test_parse_attribute_block2() {
4321 let buf = [0x02, 0x00, 0x09, 0x09, 0x00, 0x00];
4323 let unit = test_parse_attribute_unit_default();
4324 let form = constants::DW_FORM_block2;
4325 let value = AttributeValue::Block(EndianSlice::new(&buf[2..4], LittleEndian));
4326 test_parse_attribute(&buf, 4, &unit, form, value);
4327 }
4328
4329 #[test]
4330 fn test_parse_attribute_block4() {
4331 let buf = [0x02, 0x00, 0x00, 0x00, 0x99, 0x99];
4333 let unit = test_parse_attribute_unit_default();
4334 let form = constants::DW_FORM_block4;
4335 let value = AttributeValue::Block(EndianSlice::new(&buf[4..], LittleEndian));
4336 test_parse_attribute(&buf, 6, &unit, form, value);
4337 }
4338
4339 #[test]
4340 fn test_parse_attribute_block() {
4341 let buf = [0x02, 0x99, 0x99];
4343 let unit = test_parse_attribute_unit_default();
4344 let form = constants::DW_FORM_block;
4345 let value = AttributeValue::Block(EndianSlice::new(&buf[1..], LittleEndian));
4346 test_parse_attribute(&buf, 3, &unit, form, value);
4347 }
4348
4349 #[test]
4350 fn test_parse_attribute_data1() {
4351 let buf = [0x03];
4352 let unit = test_parse_attribute_unit_default();
4353 let form = constants::DW_FORM_data1;
4354 let value = AttributeValue::Data1(0x03);
4355 test_parse_attribute(&buf, 1, &unit, form, value);
4356 }
4357
4358 #[test]
4359 fn test_parse_attribute_data2() {
4360 let buf = [0x02, 0x01, 0x0];
4361 let unit = test_parse_attribute_unit_default();
4362 let form = constants::DW_FORM_data2;
4363 let value = AttributeValue::Data2(0x0102);
4364 test_parse_attribute(&buf, 2, &unit, form, value);
4365 }
4366
4367 #[test]
4368 fn test_parse_attribute_data4() {
4369 let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99];
4370 let unit = test_parse_attribute_unit_default();
4371 let form = constants::DW_FORM_data4;
4372 let value = AttributeValue::Data4(0x0403_0201);
4373 test_parse_attribute(&buf, 4, &unit, form, value);
4374 }
4375
4376 #[test]
4377 fn test_parse_attribute_data8() {
4378 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4379 let unit = test_parse_attribute_unit_default();
4380 let form = constants::DW_FORM_data8;
4381 let value = AttributeValue::Data8(0x0807_0605_0403_0201);
4382 test_parse_attribute(&buf, 8, &unit, form, value);
4383 }
4384
4385 #[test]
4386 fn test_parse_attribute_udata() {
4387 let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4388
4389 let bytes_written = {
4390 let mut writable = &mut buf[..];
4391 leb128::write::unsigned(&mut writable, 4097).expect("should write ok")
4392 };
4393
4394 let unit = test_parse_attribute_unit_default();
4395 let form = constants::DW_FORM_udata;
4396 let value = AttributeValue::Udata(4097);
4397 test_parse_attribute(&buf, bytes_written, &unit, form, value);
4398 }
4399
4400 #[test]
4401 fn test_parse_attribute_sdata() {
4402 let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4403
4404 let bytes_written = {
4405 let mut writable = &mut buf[..];
4406 leb128::write::signed(&mut writable, -4097).expect("should write ok")
4407 };
4408
4409 let unit = test_parse_attribute_unit_default();
4410 let form = constants::DW_FORM_sdata;
4411 let value = AttributeValue::Sdata(-4097);
4412 test_parse_attribute(&buf, bytes_written, &unit, form, value);
4413 }
4414
4415 #[test]
4416 fn test_parse_attribute_exprloc() {
4417 let buf = [0x02, 0x99, 0x99, 0x11];
4419 let unit = test_parse_attribute_unit_default();
4420 let form = constants::DW_FORM_exprloc;
4421 let value = AttributeValue::Exprloc(Expression(EndianSlice::new(&buf[1..3], LittleEndian)));
4422 test_parse_attribute(&buf, 3, &unit, form, value);
4423 }
4424
4425 #[test]
4426 fn test_parse_attribute_flag_true() {
4427 let buf = [0x42];
4428 let unit = test_parse_attribute_unit_default();
4429 let form = constants::DW_FORM_flag;
4430 let value = AttributeValue::Flag(true);
4431 test_parse_attribute(&buf, 1, &unit, form, value);
4432 }
4433
4434 #[test]
4435 fn test_parse_attribute_flag_false() {
4436 let buf = [0x00];
4437 let unit = test_parse_attribute_unit_default();
4438 let form = constants::DW_FORM_flag;
4439 let value = AttributeValue::Flag(false);
4440 test_parse_attribute(&buf, 1, &unit, form, value);
4441 }
4442
4443 #[test]
4444 fn test_parse_attribute_flag_present() {
4445 let buf = [0x01, 0x02, 0x03, 0x04];
4446 let unit = test_parse_attribute_unit_default();
4447 let form = constants::DW_FORM_flag_present;
4448 let value = AttributeValue::Flag(true);
4449 test_parse_attribute(&buf, 0, &unit, form, value);
4451 }
4452
4453 #[test]
4454 fn test_parse_attribute_sec_offset_32() {
4455 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10];
4456 let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4457 let form = constants::DW_FORM_sec_offset;
4458 let value = AttributeValue::SecOffset(0x0403_0201);
4459 test_parse_attribute(&buf, 4, &unit, form, value);
4460 }
4461
4462 #[test]
4463 #[cfg(target_pointer_width = "64")]
4464 fn test_parse_attribute_sec_offset_64() {
4465 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10];
4466 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4467 let form = constants::DW_FORM_sec_offset;
4468 let value = AttributeValue::SecOffset(0x0807_0605_0403_0201);
4469 test_parse_attribute(&buf, 8, &unit, form, value);
4470 }
4471
4472 #[test]
4473 fn test_parse_attribute_ref1() {
4474 let buf = [0x03];
4475 let unit = test_parse_attribute_unit_default();
4476 let form = constants::DW_FORM_ref1;
4477 let value = AttributeValue::UnitRef(UnitOffset(3));
4478 test_parse_attribute(&buf, 1, &unit, form, value);
4479 }
4480
4481 #[test]
4482 fn test_parse_attribute_ref2() {
4483 let buf = [0x02, 0x01, 0x0];
4484 let unit = test_parse_attribute_unit_default();
4485 let form = constants::DW_FORM_ref2;
4486 let value = AttributeValue::UnitRef(UnitOffset(258));
4487 test_parse_attribute(&buf, 2, &unit, form, value);
4488 }
4489
4490 #[test]
4491 fn test_parse_attribute_ref4() {
4492 let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99];
4493 let unit = test_parse_attribute_unit_default();
4494 let form = constants::DW_FORM_ref4;
4495 let value = AttributeValue::UnitRef(UnitOffset(0x0403_0201));
4496 test_parse_attribute(&buf, 4, &unit, form, value);
4497 }
4498
4499 #[test]
4500 #[cfg(target_pointer_width = "64")]
4501 fn test_parse_attribute_ref8() {
4502 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4503 let unit = test_parse_attribute_unit_default();
4504 let form = constants::DW_FORM_ref8;
4505 let value = AttributeValue::UnitRef(UnitOffset(0x0807_0605_0403_0201));
4506 test_parse_attribute(&buf, 8, &unit, form, value);
4507 }
4508
4509 #[test]
4510 fn test_parse_attribute_ref_sup4() {
4511 let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99];
4512 let unit = test_parse_attribute_unit_default();
4513 let form = constants::DW_FORM_ref_sup4;
4514 let value = AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x0403_0201));
4515 test_parse_attribute(&buf, 4, &unit, form, value);
4516 }
4517
4518 #[test]
4519 #[cfg(target_pointer_width = "64")]
4520 fn test_parse_attribute_ref_sup8() {
4521 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4522 let unit = test_parse_attribute_unit_default();
4523 let form = constants::DW_FORM_ref_sup8;
4524 let value = AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x0807_0605_0403_0201));
4525 test_parse_attribute(&buf, 8, &unit, form, value);
4526 }
4527
4528 #[test]
4529 fn test_parse_attribute_refudata() {
4530 let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4531
4532 let bytes_written = {
4533 let mut writable = &mut buf[..];
4534 leb128::write::unsigned(&mut writable, 4097).expect("should write ok")
4535 };
4536
4537 let unit = test_parse_attribute_unit_default();
4538 let form = constants::DW_FORM_ref_udata;
4539 let value = AttributeValue::UnitRef(UnitOffset(4097));
4540 test_parse_attribute(&buf, bytes_written, &unit, form, value);
4541 }
4542
4543 #[test]
4544 fn test_parse_attribute_refaddr_32() {
4545 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4546 let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4547 let form = constants::DW_FORM_ref_addr;
4548 let value = AttributeValue::DebugInfoRef(DebugInfoOffset(0x0403_0201));
4549 test_parse_attribute(&buf, 4, &unit, form, value);
4550 }
4551
4552 #[test]
4553 #[cfg(target_pointer_width = "64")]
4554 fn test_parse_attribute_refaddr_64() {
4555 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4556 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4557 let form = constants::DW_FORM_ref_addr;
4558 let value = AttributeValue::DebugInfoRef(DebugInfoOffset(0x0807_0605_0403_0201));
4559 test_parse_attribute(&buf, 8, &unit, form, value);
4560 }
4561
4562 #[test]
4563 fn test_parse_attribute_refaddr_version2() {
4564 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4565 let mut unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4566 unit.encoding.version = 2;
4567 let form = constants::DW_FORM_ref_addr;
4568 let value = AttributeValue::DebugInfoRef(DebugInfoOffset(0x0403_0201));
4569 test_parse_attribute(&buf, 4, &unit, form, value);
4570 }
4571
4572 #[test]
4573 #[cfg(target_pointer_width = "64")]
4574 fn test_parse_attribute_refaddr8_version2() {
4575 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4576 let mut unit = test_parse_attribute_unit(8, Format::Dwarf32, LittleEndian);
4577 unit.encoding.version = 2;
4578 let form = constants::DW_FORM_ref_addr;
4579 let value = AttributeValue::DebugInfoRef(DebugInfoOffset(0x0807_0605_0403_0201));
4580 test_parse_attribute(&buf, 8, &unit, form, value);
4581 }
4582
4583 #[test]
4584 fn test_parse_attribute_gnu_ref_alt_32() {
4585 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4586 let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4587 let form = constants::DW_FORM_GNU_ref_alt;
4588 let value = AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x0403_0201));
4589 test_parse_attribute(&buf, 4, &unit, form, value);
4590 }
4591
4592 #[test]
4593 #[cfg(target_pointer_width = "64")]
4594 fn test_parse_attribute_gnu_ref_alt_64() {
4595 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4596 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4597 let form = constants::DW_FORM_GNU_ref_alt;
4598 let value = AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x0807_0605_0403_0201));
4599 test_parse_attribute(&buf, 8, &unit, form, value);
4600 }
4601
4602 #[test]
4603 fn test_parse_attribute_refsig8() {
4604 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4605 let unit = test_parse_attribute_unit_default();
4606 let form = constants::DW_FORM_ref_sig8;
4607 let value = AttributeValue::DebugTypesRef(DebugTypeSignature(0x0807_0605_0403_0201));
4608 test_parse_attribute(&buf, 8, &unit, form, value);
4609 }
4610
4611 #[test]
4612 fn test_parse_attribute_string() {
4613 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x0, 0x99, 0x99];
4614 let unit = test_parse_attribute_unit_default();
4615 let form = constants::DW_FORM_string;
4616 let value = AttributeValue::String(EndianSlice::new(&buf[..5], LittleEndian));
4617 test_parse_attribute(&buf, 6, &unit, form, value);
4618 }
4619
4620 #[test]
4621 fn test_parse_attribute_strp_32() {
4622 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4623 let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4624 let form = constants::DW_FORM_strp;
4625 let value = AttributeValue::DebugStrRef(DebugStrOffset(0x0403_0201));
4626 test_parse_attribute(&buf, 4, &unit, form, value);
4627 }
4628
4629 #[test]
4630 #[cfg(target_pointer_width = "64")]
4631 fn test_parse_attribute_strp_64() {
4632 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4633 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4634 let form = constants::DW_FORM_strp;
4635 let value = AttributeValue::DebugStrRef(DebugStrOffset(0x0807_0605_0403_0201));
4636 test_parse_attribute(&buf, 8, &unit, form, value);
4637 }
4638
4639 #[test]
4640 fn test_parse_attribute_strp_sup_32() {
4641 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4642 let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4643 let form = constants::DW_FORM_strp_sup;
4644 let value = AttributeValue::DebugStrRefSup(DebugStrOffset(0x0403_0201));
4645 test_parse_attribute(&buf, 4, &unit, form, value);
4646 }
4647
4648 #[test]
4649 #[cfg(target_pointer_width = "64")]
4650 fn test_parse_attribute_strp_sup_64() {
4651 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4652 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4653 let form = constants::DW_FORM_strp_sup;
4654 let value = AttributeValue::DebugStrRefSup(DebugStrOffset(0x0807_0605_0403_0201));
4655 test_parse_attribute(&buf, 8, &unit, form, value);
4656 }
4657
4658 #[test]
4659 fn test_parse_attribute_gnu_strp_alt_32() {
4660 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4661 let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4662 let form = constants::DW_FORM_GNU_strp_alt;
4663 let value = AttributeValue::DebugStrRefSup(DebugStrOffset(0x0403_0201));
4664 test_parse_attribute(&buf, 4, &unit, form, value);
4665 }
4666
4667 #[test]
4668 #[cfg(target_pointer_width = "64")]
4669 fn test_parse_attribute_gnu_strp_alt_64() {
4670 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4671 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4672 let form = constants::DW_FORM_GNU_strp_alt;
4673 let value = AttributeValue::DebugStrRefSup(DebugStrOffset(0x0807_0605_0403_0201));
4674 test_parse_attribute(&buf, 8, &unit, form, value);
4675 }
4676
4677 #[test]
4678 fn test_parse_attribute_strx() {
4679 let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4680
4681 let bytes_written = {
4682 let mut writable = &mut buf[..];
4683 leb128::write::unsigned(&mut writable, 4097).expect("should write ok")
4684 };
4685
4686 let unit = test_parse_attribute_unit_default();
4687 let form = constants::DW_FORM_strx;
4688 let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(4097));
4689 test_parse_attribute(&buf, bytes_written, &unit, form, value);
4690 }
4691
4692 #[test]
4693 fn test_parse_attribute_strx1() {
4694 let buf = [0x01, 0x99, 0x99];
4695 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4696 let form = constants::DW_FORM_strx1;
4697 let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(0x01));
4698 test_parse_attribute(&buf, 1, &unit, form, value);
4699 }
4700
4701 #[test]
4702 fn test_parse_attribute_strx2() {
4703 let buf = [0x01, 0x02, 0x99, 0x99];
4704 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4705 let form = constants::DW_FORM_strx2;
4706 let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(0x0201));
4707 test_parse_attribute(&buf, 2, &unit, form, value);
4708 }
4709
4710 #[test]
4711 fn test_parse_attribute_strx3() {
4712 let buf = [0x01, 0x02, 0x03, 0x99, 0x99];
4713 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4714 let form = constants::DW_FORM_strx3;
4715 let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(0x03_0201));
4716 test_parse_attribute(&buf, 3, &unit, form, value);
4717 }
4718
4719 #[test]
4720 fn test_parse_attribute_strx4() {
4721 let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99];
4722 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4723 let form = constants::DW_FORM_strx4;
4724 let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(0x0403_0201));
4725 test_parse_attribute(&buf, 4, &unit, form, value);
4726 }
4727
4728 #[test]
4729 fn test_parse_attribute_addrx() {
4730 let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4731
4732 let bytes_written = {
4733 let mut writable = &mut buf[..];
4734 leb128::write::unsigned(&mut writable, 4097).expect("should write ok")
4735 };
4736
4737 let unit = test_parse_attribute_unit_default();
4738 let form = constants::DW_FORM_addrx;
4739 let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(4097));
4740 test_parse_attribute(&buf, bytes_written, &unit, form, value);
4741 }
4742
4743 #[test]
4744 fn test_parse_attribute_addrx1() {
4745 let buf = [0x01, 0x99, 0x99];
4746 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4747 let form = constants::DW_FORM_addrx1;
4748 let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(0x01));
4749 test_parse_attribute(&buf, 1, &unit, form, value);
4750 }
4751
4752 #[test]
4753 fn test_parse_attribute_addrx2() {
4754 let buf = [0x01, 0x02, 0x99, 0x99];
4755 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4756 let form = constants::DW_FORM_addrx2;
4757 let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(0x0201));
4758 test_parse_attribute(&buf, 2, &unit, form, value);
4759 }
4760
4761 #[test]
4762 fn test_parse_attribute_addrx3() {
4763 let buf = [0x01, 0x02, 0x03, 0x99, 0x99];
4764 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4765 let form = constants::DW_FORM_addrx3;
4766 let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(0x03_0201));
4767 test_parse_attribute(&buf, 3, &unit, form, value);
4768 }
4769
4770 #[test]
4771 fn test_parse_attribute_addrx4() {
4772 let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99];
4773 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4774 let form = constants::DW_FORM_addrx4;
4775 let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(0x0403_0201));
4776 test_parse_attribute(&buf, 4, &unit, form, value);
4777 }
4778
4779 #[test]
4780 fn test_parse_attribute_loclistx() {
4781 let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4782
4783 let bytes_written = {
4784 let mut writable = &mut buf[..];
4785 leb128::write::unsigned(&mut writable, 4097).expect("should write ok")
4786 };
4787
4788 let unit = test_parse_attribute_unit_default();
4789 let form = constants::DW_FORM_loclistx;
4790 let value = AttributeValue::DebugLocListsIndex(DebugLocListsIndex(4097));
4791 test_parse_attribute(&buf, bytes_written, &unit, form, value);
4792 }
4793
4794 #[test]
4795 fn test_parse_attribute_rnglistx() {
4796 let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4797
4798 let bytes_written = {
4799 let mut writable = &mut buf[..];
4800 leb128::write::unsigned(&mut writable, 4097).expect("should write ok")
4801 };
4802
4803 let unit = test_parse_attribute_unit_default();
4804 let form = constants::DW_FORM_rnglistx;
4805 let value = AttributeValue::DebugRngListsIndex(DebugRngListsIndex(4097));
4806 test_parse_attribute(&buf, bytes_written, &unit, form, value);
4807 }
4808
4809 #[test]
4810 fn test_parse_attribute_indirect() {
4811 let mut buf = [0; 100];
4812
4813 let bytes_written = {
4814 let mut writable = &mut buf[..];
4815 leb128::write::unsigned(&mut writable, constants::DW_FORM_udata.0.into())
4816 .expect("should write udata")
4817 + leb128::write::unsigned(&mut writable, 9_999_999).expect("should write value")
4818 };
4819
4820 let unit = test_parse_attribute_unit_default();
4821 let form = constants::DW_FORM_indirect;
4822 let value = AttributeValue::Udata(9_999_999);
4823 test_parse_attribute(&buf, bytes_written, &unit, form, value);
4824 }
4825
4826 #[test]
4827 fn test_parse_attribute_indirect_implicit_const() {
4828 let encoding = Encoding {
4829 format: Format::Dwarf32,
4830 version: 4,
4831 address_size: 4,
4832 };
4833 let mut buf = [0; 100];
4834 let mut writable = &mut buf[..];
4835 leb128::write::unsigned(&mut writable, constants::DW_FORM_implicit_const.0.into())
4836 .expect("should write implicit_const");
4837
4838 let input = &mut EndianSlice::new(&buf, LittleEndian);
4839 let spec =
4840 AttributeSpecification::new(constants::DW_AT_low_pc, constants::DW_FORM_indirect, None);
4841 assert_eq!(
4842 parse_attribute(input, encoding, spec),
4843 Err(Error::InvalidImplicitConst)
4844 );
4845 }
4846
4847 #[test]
4848 fn test_attrs_iter() {
4849 let encoding = Encoding {
4850 format: Format::Dwarf32,
4851 version: 4,
4852 address_size: 4,
4853 };
4854 let unit = UnitHeader::new(
4855 encoding,
4856 7,
4857 UnitType::Compilation,
4858 DebugAbbrevOffset(0x0807_0605),
4859 DebugInfoOffset(0).into(),
4860 EndianSlice::new(&[], LittleEndian),
4861 );
4862
4863 let abbrev = Abbreviation::new(
4864 42,
4865 constants::DW_TAG_subprogram,
4866 constants::DW_CHILDREN_yes,
4867 vec![
4868 AttributeSpecification::new(constants::DW_AT_name, constants::DW_FORM_string, None),
4869 AttributeSpecification::new(constants::DW_AT_low_pc, constants::DW_FORM_addr, None),
4870 AttributeSpecification::new(
4871 constants::DW_AT_high_pc,
4872 constants::DW_FORM_addr,
4873 None,
4874 ),
4875 ]
4876 .into(),
4877 );
4878
4879 let buf = [
4881 0x66, 0x6f, 0x6f, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x39, 0x05, 0x00, 0x00, 0xaa, 0xaa,
4882 0xaa, 0xaa,
4883 ];
4884
4885 let entry = DebuggingInformationEntry {
4886 offset: UnitOffset(0),
4887 attrs_slice: EndianSlice::new(&buf, LittleEndian),
4888 attrs_len: Cell::new(None),
4889 abbrev: &abbrev,
4890 unit: &unit,
4891 };
4892
4893 let mut attrs = AttrsIter {
4894 input: EndianSlice::new(&buf, LittleEndian),
4895 attributes: abbrev.attributes(),
4896 entry: &entry,
4897 };
4898
4899 match attrs.next() {
4900 Ok(Some(attr)) => {
4901 assert_eq!(
4902 attr,
4903 Attribute {
4904 name: constants::DW_AT_name,
4905 value: AttributeValue::String(EndianSlice::new(b"foo", LittleEndian)),
4906 }
4907 );
4908 }
4909 otherwise => {
4910 panic!("Unexpected parse result = {:#?}", otherwise);
4911 }
4912 }
4913
4914 assert!(entry.attrs_len.get().is_none());
4915
4916 match attrs.next() {
4917 Ok(Some(attr)) => {
4918 assert_eq!(
4919 attr,
4920 Attribute {
4921 name: constants::DW_AT_low_pc,
4922 value: AttributeValue::Addr(0x2a),
4923 }
4924 );
4925 }
4926 otherwise => {
4927 panic!("Unexpected parse result = {:#?}", otherwise);
4928 }
4929 }
4930
4931 assert!(entry.attrs_len.get().is_none());
4932
4933 match attrs.next() {
4934 Ok(Some(attr)) => {
4935 assert_eq!(
4936 attr,
4937 Attribute {
4938 name: constants::DW_AT_high_pc,
4939 value: AttributeValue::Addr(0x539),
4940 }
4941 );
4942 }
4943 otherwise => {
4944 panic!("Unexpected parse result = {:#?}", otherwise);
4945 }
4946 }
4947
4948 assert!(entry.attrs_len.get().is_none());
4949
4950 assert!(attrs.next().expect("should parse next").is_none());
4951 assert!(entry.attrs_len.get().is_some());
4952 assert_eq!(
4953 entry.attrs_len.get().expect("should have entry.attrs_len"),
4954 buf.len() - 4
4955 )
4956 }
4957
4958 #[test]
4959 fn test_attrs_iter_incomplete() {
4960 let encoding = Encoding {
4961 format: Format::Dwarf32,
4962 version: 4,
4963 address_size: 4,
4964 };
4965 let unit = UnitHeader::new(
4966 encoding,
4967 7,
4968 UnitType::Compilation,
4969 DebugAbbrevOffset(0x0807_0605),
4970 DebugInfoOffset(0).into(),
4971 EndianSlice::new(&[], LittleEndian),
4972 );
4973
4974 let abbrev = Abbreviation::new(
4975 42,
4976 constants::DW_TAG_subprogram,
4977 constants::DW_CHILDREN_yes,
4978 vec![
4979 AttributeSpecification::new(constants::DW_AT_name, constants::DW_FORM_string, None),
4980 AttributeSpecification::new(constants::DW_AT_low_pc, constants::DW_FORM_addr, None),
4981 AttributeSpecification::new(
4982 constants::DW_AT_high_pc,
4983 constants::DW_FORM_addr,
4984 None,
4985 ),
4986 ]
4987 .into(),
4988 );
4989
4990 let buf = [0x66, 0x6f, 0x6f, 0x00];
4992
4993 let entry = DebuggingInformationEntry {
4994 offset: UnitOffset(0),
4995 attrs_slice: EndianSlice::new(&buf, LittleEndian),
4996 attrs_len: Cell::new(None),
4997 abbrev: &abbrev,
4998 unit: &unit,
4999 };
5000
5001 let mut attrs = AttrsIter {
5002 input: EndianSlice::new(&buf, LittleEndian),
5003 attributes: abbrev.attributes(),
5004 entry: &entry,
5005 };
5006
5007 match attrs.next() {
5008 Ok(Some(attr)) => {
5009 assert_eq!(
5010 attr,
5011 Attribute {
5012 name: constants::DW_AT_name,
5013 value: AttributeValue::String(EndianSlice::new(b"foo", LittleEndian)),
5014 }
5015 );
5016 }
5017 otherwise => {
5018 panic!("Unexpected parse result = {:#?}", otherwise);
5019 }
5020 }
5021
5022 assert!(entry.attrs_len.get().is_none());
5023
5024 assert!(attrs.next().is_err());
5026 assert!(entry.attrs_len.get().is_none());
5027
5028 assert!(attrs.next().is_err());
5030 assert!(attrs.next().is_err());
5031 assert!(attrs.next().is_err());
5032 assert!(attrs.next().is_err());
5033 assert!(entry.attrs_len.get().is_none());
5034 }
5035
5036 fn assert_entry_name<Endian>(
5037 entry: &DebuggingInformationEntry<'_, '_, EndianSlice<'_, Endian>>,
5038 name: &str,
5039 ) where
5040 Endian: Endianity,
5041 {
5042 let value = entry
5043 .attr_value(constants::DW_AT_name)
5044 .expect("Should have parsed the name attribute")
5045 .expect("Should have found the name attribute");
5046
5047 assert_eq!(
5048 value,
5049 AttributeValue::String(EndianSlice::new(name.as_bytes(), Endian::default()))
5050 );
5051 }
5052
5053 fn assert_current_name<Endian>(
5054 cursor: &EntriesCursor<'_, '_, EndianSlice<'_, Endian>>,
5055 name: &str,
5056 ) where
5057 Endian: Endianity,
5058 {
5059 let entry = cursor.current().expect("Should have an entry result");
5060 assert_entry_name(entry, name);
5061 }
5062
5063 fn assert_next_entry<Endian>(
5064 cursor: &mut EntriesCursor<'_, '_, EndianSlice<'_, Endian>>,
5065 name: &str,
5066 ) where
5067 Endian: Endianity,
5068 {
5069 cursor
5070 .next_entry()
5071 .expect("Should parse next entry")
5072 .expect("Should have an entry");
5073 assert_current_name(cursor, name);
5074 }
5075
5076 fn assert_next_entry_null<Endian>(cursor: &mut EntriesCursor<'_, '_, EndianSlice<'_, Endian>>)
5077 where
5078 Endian: Endianity,
5079 {
5080 cursor
5081 .next_entry()
5082 .expect("Should parse next entry")
5083 .expect("Should have an entry");
5084 assert!(cursor.current().is_none());
5085 }
5086
5087 fn assert_next_dfs<Endian>(
5088 cursor: &mut EntriesCursor<'_, '_, EndianSlice<'_, Endian>>,
5089 name: &str,
5090 depth: isize,
5091 ) where
5092 Endian: Endianity,
5093 {
5094 {
5095 let (val, entry) = cursor
5096 .next_dfs()
5097 .expect("Should parse next dfs")
5098 .expect("Should not be done with traversal");
5099 assert_eq!(val, depth);
5100 assert_entry_name(entry, name);
5101 }
5102 assert_current_name(cursor, name);
5103 }
5104
5105 fn assert_next_sibling<Endian>(
5106 cursor: &mut EntriesCursor<'_, '_, EndianSlice<'_, Endian>>,
5107 name: &str,
5108 ) where
5109 Endian: Endianity,
5110 {
5111 {
5112 let entry = cursor
5113 .next_sibling()
5114 .expect("Should parse next sibling")
5115 .expect("Should not be done with traversal");
5116 assert_entry_name(entry, name);
5117 }
5118 assert_current_name(cursor, name);
5119 }
5120
5121 fn assert_valid_sibling_ptr<Endian>(cursor: &EntriesCursor<'_, '_, EndianSlice<'_, Endian>>)
5122 where
5123 Endian: Endianity,
5124 {
5125 let sibling_ptr = cursor
5126 .current()
5127 .expect("Should have current entry")
5128 .attr_value(constants::DW_AT_sibling);
5129 match sibling_ptr {
5130 Ok(Some(AttributeValue::UnitRef(offset))) => {
5131 cursor
5132 .unit
5133 .range_from(offset..)
5134 .expect("Sibling offset should be valid");
5135 }
5136 _ => panic!("Invalid sibling pointer {:?}", sibling_ptr),
5137 }
5138 }
5139
5140 fn entries_cursor_tests_abbrev_buf() -> Vec<u8> {
5141 #[rustfmt::skip]
5142 let section = Section::with_endian(Endian::Little)
5143 .abbrev(1, DW_TAG_subprogram, DW_CHILDREN_yes)
5144 .abbrev_attr(DW_AT_name, DW_FORM_string)
5145 .abbrev_attr_null()
5146 .abbrev_null();
5147 section.get_contents().unwrap()
5148 }
5149
5150 fn entries_cursor_tests_debug_info_buf() -> Vec<u8> {
5151 #[rustfmt::skip]
5152 let section = Section::with_endian(Endian::Little)
5153 .die(1, |s| s.attr_string("001"))
5154 .die(1, |s| s.attr_string("002"))
5155 .die(1, |s| s.attr_string("003"))
5156 .die_null()
5157 .die_null()
5158 .die(1, |s| s.attr_string("004"))
5159 .die(1, |s| s.attr_string("005"))
5160 .die_null()
5161 .die(1, |s| s.attr_string("006"))
5162 .die_null()
5163 .die_null()
5164 .die(1, |s| s.attr_string("007"))
5165 .die(1, |s| s.attr_string("008"))
5166 .die(1, |s| s.attr_string("009"))
5167 .die_null()
5168 .die_null()
5169 .die_null()
5170 .die(1, |s| s.attr_string("010"))
5171 .die_null()
5172 .die_null();
5173 let entries_buf = section.get_contents().unwrap();
5174
5175 let encoding = Encoding {
5176 format: Format::Dwarf32,
5177 version: 4,
5178 address_size: 4,
5179 };
5180 let mut unit = UnitHeader {
5181 encoding,
5182 unit_length: 0,
5183 unit_type: UnitType::Compilation,
5184 debug_abbrev_offset: DebugAbbrevOffset(0),
5185 unit_offset: DebugInfoOffset(0).into(),
5186 entries_buf: EndianSlice::new(&entries_buf, LittleEndian),
5187 };
5188 let section = Section::with_endian(Endian::Little).unit(&mut unit);
5189 section.get_contents().unwrap()
5190 }
5191
5192 #[test]
5193 fn test_cursor_next_entry_incomplete() {
5194 #[rustfmt::skip]
5195 let section = Section::with_endian(Endian::Little)
5196 .die(1, |s| s.attr_string("001"))
5197 .die(1, |s| s.attr_string("002"))
5198 .die(1, |s| s);
5199 let entries_buf = section.get_contents().unwrap();
5200
5201 let encoding = Encoding {
5202 format: Format::Dwarf32,
5203 version: 4,
5204 address_size: 4,
5205 };
5206 let mut unit = UnitHeader {
5207 encoding,
5208 unit_length: 0,
5209 unit_type: UnitType::Compilation,
5210 debug_abbrev_offset: DebugAbbrevOffset(0),
5211 unit_offset: DebugInfoOffset(0).into(),
5212 entries_buf: EndianSlice::new(&entries_buf, LittleEndian),
5213 };
5214 let section = Section::with_endian(Endian::Little).unit(&mut unit);
5215 let info_buf = §ion.get_contents().unwrap();
5216 let debug_info = DebugInfo::new(info_buf, LittleEndian);
5217
5218 let unit = debug_info
5219 .units()
5220 .next()
5221 .expect("should have a unit result")
5222 .expect("and it should be ok");
5223
5224 let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
5225 let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
5226
5227 let abbrevs = unit
5228 .abbreviations(&debug_abbrev)
5229 .expect("Should parse abbreviations");
5230
5231 let mut cursor = unit.entries(&abbrevs);
5232
5233 assert_next_entry(&mut cursor, "001");
5234 assert_next_entry(&mut cursor, "002");
5235
5236 {
5237 cursor
5239 .next_entry()
5240 .expect("Should parse next entry")
5241 .expect("Should have an entry");
5242 let entry = cursor.current().expect("Should have an entry result");
5243 assert!(entry.attrs().next().is_err());
5244 }
5245
5246 assert!(cursor.next_entry().is_err());
5247 assert!(cursor.next_entry().is_err());
5248 }
5249
5250 #[test]
5251 fn test_cursor_next_entry() {
5252 let info_buf = &entries_cursor_tests_debug_info_buf();
5253 let debug_info = DebugInfo::new(info_buf, LittleEndian);
5254
5255 let unit = debug_info
5256 .units()
5257 .next()
5258 .expect("should have a unit result")
5259 .expect("and it should be ok");
5260
5261 let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
5262 let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
5263
5264 let abbrevs = unit
5265 .abbreviations(&debug_abbrev)
5266 .expect("Should parse abbreviations");
5267
5268 let mut cursor = unit.entries(&abbrevs);
5269
5270 assert_next_entry(&mut cursor, "001");
5271 assert_next_entry(&mut cursor, "002");
5272 assert_next_entry(&mut cursor, "003");
5273 assert_next_entry_null(&mut cursor);
5274 assert_next_entry_null(&mut cursor);
5275 assert_next_entry(&mut cursor, "004");
5276 assert_next_entry(&mut cursor, "005");
5277 assert_next_entry_null(&mut cursor);
5278 assert_next_entry(&mut cursor, "006");
5279 assert_next_entry_null(&mut cursor);
5280 assert_next_entry_null(&mut cursor);
5281 assert_next_entry(&mut cursor, "007");
5282 assert_next_entry(&mut cursor, "008");
5283 assert_next_entry(&mut cursor, "009");
5284 assert_next_entry_null(&mut cursor);
5285 assert_next_entry_null(&mut cursor);
5286 assert_next_entry_null(&mut cursor);
5287 assert_next_entry(&mut cursor, "010");
5288 assert_next_entry_null(&mut cursor);
5289 assert_next_entry_null(&mut cursor);
5290
5291 assert!(cursor
5292 .next_entry()
5293 .expect("Should parse next entry")
5294 .is_none());
5295 assert!(cursor.current().is_none());
5296 }
5297
5298 #[test]
5299 fn test_cursor_next_dfs() {
5300 let info_buf = &entries_cursor_tests_debug_info_buf();
5301 let debug_info = DebugInfo::new(info_buf, LittleEndian);
5302
5303 let unit = debug_info
5304 .units()
5305 .next()
5306 .expect("should have a unit result")
5307 .expect("and it should be ok");
5308
5309 let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
5310 let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
5311
5312 let abbrevs = unit
5313 .abbreviations(&debug_abbrev)
5314 .expect("Should parse abbreviations");
5315
5316 let mut cursor = unit.entries(&abbrevs);
5317
5318 assert_next_dfs(&mut cursor, "001", 0);
5319 assert_next_dfs(&mut cursor, "002", 1);
5320 assert_next_dfs(&mut cursor, "003", 1);
5321 assert_next_dfs(&mut cursor, "004", -1);
5322 assert_next_dfs(&mut cursor, "005", 1);
5323 assert_next_dfs(&mut cursor, "006", 0);
5324 assert_next_dfs(&mut cursor, "007", -1);
5325 assert_next_dfs(&mut cursor, "008", 1);
5326 assert_next_dfs(&mut cursor, "009", 1);
5327 assert_next_dfs(&mut cursor, "010", -2);
5328
5329 assert!(cursor.next_dfs().expect("Should parse next dfs").is_none());
5330 assert!(cursor.current().is_none());
5331 }
5332
5333 #[test]
5334 fn test_cursor_next_sibling_no_sibling_ptr() {
5335 let info_buf = &entries_cursor_tests_debug_info_buf();
5336 let debug_info = DebugInfo::new(info_buf, LittleEndian);
5337
5338 let unit = debug_info
5339 .units()
5340 .next()
5341 .expect("should have a unit result")
5342 .expect("and it should be ok");
5343
5344 let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
5345 let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
5346
5347 let abbrevs = unit
5348 .abbreviations(&debug_abbrev)
5349 .expect("Should parse abbreviations");
5350
5351 let mut cursor = unit.entries(&abbrevs);
5352
5353 assert_next_dfs(&mut cursor, "001", 0);
5354
5355 assert_next_dfs(&mut cursor, "002", 1);
5358
5359 assert_next_sibling(&mut cursor, "004");
5362 assert_next_sibling(&mut cursor, "007");
5363 assert_next_sibling(&mut cursor, "010");
5364
5365 assert!(cursor
5368 .next_sibling()
5369 .expect("Should parse next sibling")
5370 .is_none());
5371 assert!(cursor.current().is_none());
5372 }
5373
5374 #[test]
5375 fn test_cursor_next_sibling_continuation() {
5376 let info_buf = &entries_cursor_tests_debug_info_buf();
5377 let debug_info = DebugInfo::new(info_buf, LittleEndian);
5378
5379 let unit = debug_info
5380 .units()
5381 .next()
5382 .expect("should have a unit result")
5383 .expect("and it should be ok");
5384
5385 let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
5386 let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
5387
5388 let abbrevs = unit
5389 .abbreviations(&debug_abbrev)
5390 .expect("Should parse abbreviations");
5391
5392 let mut cursor = unit.entries(&abbrevs);
5393
5394 assert_next_dfs(&mut cursor, "001", 0);
5395
5396 assert_next_dfs(&mut cursor, "002", 1);
5399
5400 assert_next_sibling(&mut cursor, "004");
5403 assert_next_dfs(&mut cursor, "005", 1);
5404 assert_next_sibling(&mut cursor, "006");
5405 assert!(cursor
5406 .next_sibling()
5407 .expect("Should parse next sibling")
5408 .is_none());
5409 assert!(cursor
5410 .next_sibling()
5411 .expect("Should parse next sibling")
5412 .is_none());
5413 assert!(cursor
5414 .next_sibling()
5415 .expect("Should parse next sibling")
5416 .is_none());
5417 assert!(cursor
5418 .next_sibling()
5419 .expect("Should parse next sibling")
5420 .is_none());
5421
5422 assert_next_dfs(&mut cursor, "007", -1);
5425 assert_next_sibling(&mut cursor, "010");
5426
5427 assert!(cursor
5430 .next_sibling()
5431 .expect("Should parse next sibling")
5432 .is_none());
5433 assert!(cursor.current().is_none());
5434 }
5435
5436 fn entries_cursor_sibling_abbrev_buf() -> Vec<u8> {
5437 #[rustfmt::skip]
5438 let section = Section::with_endian(Endian::Little)
5439 .abbrev(1, DW_TAG_subprogram, DW_CHILDREN_yes)
5440 .abbrev_attr(DW_AT_name, DW_FORM_string)
5441 .abbrev_attr(DW_AT_sibling, DW_FORM_ref1)
5442 .abbrev_attr_null()
5443 .abbrev(2, DW_TAG_subprogram, DW_CHILDREN_yes)
5444 .abbrev_attr(DW_AT_name, DW_FORM_string)
5445 .abbrev_attr_null()
5446 .abbrev_null();
5447 section.get_contents().unwrap()
5448 }
5449
5450 fn entries_cursor_sibling_entries_buf(header_size: usize) -> Vec<u8> {
5451 let start = Label::new();
5452 let sibling004_ref = Label::new();
5453 let sibling004 = Label::new();
5454 let sibling009_ref = Label::new();
5455 let sibling009 = Label::new();
5456
5457 #[rustfmt::skip]
5458 let section = Section::with_endian(Endian::Little)
5459 .mark(&start)
5460 .die(2, |s| s.attr_string("001"))
5461 .die(1, |s| s.attr_string("002").D8(&sibling004_ref))
5463 .die(10, |s| s.attr_string("003"))
5465 .die_null()
5466 .die_null()
5467 .mark(&sibling004)
5468 .die(1, |s| s.attr_string("004").attr_ref1(255))
5470 .die(2, |s| s.attr_string("005"))
5471 .die_null()
5472 .die_null()
5473 .die(2, |s| s.attr_string("006"))
5475 .die(1, |s| s.attr_string("007").D8(&sibling009_ref))
5477 .die(10, |s| s.attr_string("008"))
5479 .die_null()
5480 .die_null()
5481 .mark(&sibling009)
5482 .die(2, |s| s.attr_string("009"))
5483 .die_null()
5484 .die_null()
5485 .die(2, |s| s.attr_string("010"))
5487 .die(2, |s| s.attr_string("011"))
5488 .die_null()
5489 .die_null()
5490 .die_null();
5491
5492 let offset = header_size as u64 + (&sibling004 - &start) as u64;
5493 sibling004_ref.set_const(offset);
5494
5495 let offset = header_size as u64 + (&sibling009 - &start) as u64;
5496 sibling009_ref.set_const(offset);
5497
5498 section.get_contents().unwrap()
5499 }
5500
5501 fn test_cursor_next_sibling_with_ptr(
5502 cursor: &mut EntriesCursor<'_, '_, EndianSlice<'_, LittleEndian>>,
5503 ) {
5504 assert_next_dfs(cursor, "001", 0);
5505
5506 assert_next_dfs(cursor, "002", 1);
5509
5510 assert_valid_sibling_ptr(cursor);
5513 assert_next_sibling(cursor, "004");
5514 assert_next_sibling(cursor, "006");
5515 assert_next_sibling(cursor, "010");
5516
5517 assert!(cursor
5520 .next_sibling()
5521 .expect("Should parse next sibling")
5522 .is_none());
5523 assert!(cursor.current().is_none());
5524 }
5525
5526 #[test]
5527 fn test_debug_info_next_sibling_with_ptr() {
5528 let encoding = Encoding {
5529 format: Format::Dwarf32,
5530 version: 4,
5531 address_size: 4,
5532 };
5533
5534 let mut unit = UnitHeader {
5535 encoding,
5536 unit_length: 0,
5537 unit_type: UnitType::Compilation,
5538 debug_abbrev_offset: DebugAbbrevOffset(0),
5539 unit_offset: DebugInfoOffset(0).into(),
5540 entries_buf: EndianSlice::new(&[], LittleEndian),
5541 };
5542 let header_size = unit.size_of_header();
5543 let entries_buf = entries_cursor_sibling_entries_buf(header_size);
5544 unit.entries_buf = EndianSlice::new(&entries_buf, LittleEndian);
5545 let section = Section::with_endian(Endian::Little).unit(&mut unit);
5546 let info_buf = section.get_contents().unwrap();
5547 let debug_info = DebugInfo::new(&info_buf, LittleEndian);
5548
5549 let unit = debug_info
5550 .units()
5551 .next()
5552 .expect("should have a unit result")
5553 .expect("and it should be ok");
5554
5555 let abbrev_buf = entries_cursor_sibling_abbrev_buf();
5556 let debug_abbrev = DebugAbbrev::new(&abbrev_buf, LittleEndian);
5557
5558 let abbrevs = unit
5559 .abbreviations(&debug_abbrev)
5560 .expect("Should parse abbreviations");
5561
5562 let mut cursor = unit.entries(&abbrevs);
5563 test_cursor_next_sibling_with_ptr(&mut cursor);
5564 }
5565
5566 #[test]
5567 fn test_debug_types_next_sibling_with_ptr() {
5568 let encoding = Encoding {
5569 format: Format::Dwarf32,
5570 version: 4,
5571 address_size: 4,
5572 };
5573 let mut unit = UnitHeader {
5574 encoding,
5575 unit_length: 0,
5576 unit_type: UnitType::Type {
5577 type_signature: DebugTypeSignature(0),
5578 type_offset: UnitOffset(0),
5579 },
5580 debug_abbrev_offset: DebugAbbrevOffset(0),
5581 unit_offset: DebugTypesOffset(0).into(),
5582 entries_buf: EndianSlice::new(&[], LittleEndian),
5583 };
5584 let header_size = unit.size_of_header();
5585 let entries_buf = entries_cursor_sibling_entries_buf(header_size);
5586 unit.entries_buf = EndianSlice::new(&entries_buf, LittleEndian);
5587 let section = Section::with_endian(Endian::Little).unit(&mut unit);
5588 let info_buf = section.get_contents().unwrap();
5589 let debug_types = DebugTypes::new(&info_buf, LittleEndian);
5590
5591 let unit = debug_types
5592 .units()
5593 .next()
5594 .expect("should have a unit result")
5595 .expect("and it should be ok");
5596
5597 let abbrev_buf = entries_cursor_sibling_abbrev_buf();
5598 let debug_abbrev = DebugAbbrev::new(&abbrev_buf, LittleEndian);
5599
5600 let abbrevs = unit
5601 .abbreviations(&debug_abbrev)
5602 .expect("Should parse abbreviations");
5603
5604 let mut cursor = unit.entries(&abbrevs);
5605 test_cursor_next_sibling_with_ptr(&mut cursor);
5606 }
5607
5608 #[test]
5609 fn test_entries_at_offset() {
5610 let info_buf = &entries_cursor_tests_debug_info_buf();
5611 let debug_info = DebugInfo::new(info_buf, LittleEndian);
5612
5613 let unit = debug_info
5614 .units()
5615 .next()
5616 .expect("should have a unit result")
5617 .expect("and it should be ok");
5618
5619 let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
5620 let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
5621
5622 let abbrevs = unit
5623 .abbreviations(&debug_abbrev)
5624 .expect("Should parse abbreviations");
5625
5626 let mut cursor = unit
5627 .entries_at_offset(&abbrevs, UnitOffset(unit.header_size()))
5628 .unwrap();
5629 assert_next_entry(&mut cursor, "001");
5630
5631 let cursor = unit.entries_at_offset(&abbrevs, UnitOffset(0));
5632 match cursor {
5633 Err(Error::OffsetOutOfBounds) => {}
5634 otherwise => {
5635 panic!("Unexpected parse result = {:#?}", otherwise);
5636 }
5637 }
5638 }
5639
5640 fn entries_tree_tests_debug_abbrevs_buf() -> Vec<u8> {
5641 #[rustfmt::skip]
5642 let section = Section::with_endian(Endian::Little)
5643 .abbrev(1, DW_TAG_subprogram, DW_CHILDREN_yes)
5644 .abbrev_attr(DW_AT_name, DW_FORM_string)
5645 .abbrev_attr_null()
5646 .abbrev(2, DW_TAG_subprogram, DW_CHILDREN_no)
5647 .abbrev_attr(DW_AT_name, DW_FORM_string)
5648 .abbrev_attr_null()
5649 .abbrev_null()
5650 .get_contents()
5651 .unwrap();
5652 section
5653 }
5654
5655 fn entries_tree_tests_debug_info_buf(header_size: usize) -> (Vec<u8>, UnitOffset) {
5656 let start = Label::new();
5657 let entry2 = Label::new();
5658 #[rustfmt::skip]
5659 let section = Section::with_endian(Endian::Little)
5660 .mark(&start)
5661 .die(1, |s| s.attr_string("root"))
5662 .die(1, |s| s.attr_string("1"))
5663 .die(1, |s| s.attr_string("1a"))
5664 .die_null()
5665 .die(2, |s| s.attr_string("1b"))
5666 .die_null()
5667 .mark(&entry2)
5668 .die(1, |s| s.attr_string("2"))
5669 .die(1, |s| s.attr_string("2a"))
5670 .die(1, |s| s.attr_string("2a1"))
5671 .die_null()
5672 .die_null()
5673 .die(1, |s| s.attr_string("2b"))
5674 .die(2, |s| s.attr_string("2b1"))
5675 .die_null()
5676 .die_null()
5677 .die(1, |s| s.attr_string("3"))
5678 .die(1, |s| s.attr_string("3a"))
5679 .die(2, |s| s.attr_string("3a1"))
5680 .die(2, |s| s.attr_string("3a2"))
5681 .die_null()
5682 .die(2, |s| s.attr_string("3b"))
5683 .die_null()
5684 .die(2, |s| s.attr_string("final"))
5685 .die_null()
5686 .get_contents()
5687 .unwrap();
5688 let entry2 = UnitOffset(header_size + (&entry2 - &start) as usize);
5689 (section, entry2)
5690 }
5691
5692 #[test]
5693 fn test_entries_tree() {
5694 fn assert_entry<'input, 'abbrev, 'unit, 'tree, Endian>(
5695 node: Result<
5696 Option<EntriesTreeNode<'abbrev, 'unit, 'tree, EndianSlice<'input, Endian>>>,
5697 >,
5698 name: &str,
5699 ) -> EntriesTreeIter<'abbrev, 'unit, 'tree, EndianSlice<'input, Endian>>
5700 where
5701 Endian: Endianity,
5702 {
5703 let node = node
5704 .expect("Should parse entry")
5705 .expect("Should have entry");
5706 assert_entry_name(node.entry(), name);
5707 node.children()
5708 }
5709
5710 fn assert_null<E: Endianity>(
5711 node: Result<Option<EntriesTreeNode<'_, '_, '_, EndianSlice<'_, E>>>>,
5712 ) {
5713 match node {
5714 Ok(None) => {}
5715 otherwise => {
5716 panic!("Unexpected parse result = {:#?}", otherwise);
5717 }
5718 }
5719 }
5720
5721 let abbrevs_buf = entries_tree_tests_debug_abbrevs_buf();
5722 let debug_abbrev = DebugAbbrev::new(&abbrevs_buf, LittleEndian);
5723
5724 let encoding = Encoding {
5725 format: Format::Dwarf32,
5726 version: 4,
5727 address_size: 4,
5728 };
5729 let mut unit = UnitHeader {
5730 encoding,
5731 unit_length: 0,
5732 unit_type: UnitType::Compilation,
5733 debug_abbrev_offset: DebugAbbrevOffset(0),
5734 unit_offset: DebugInfoOffset(0).into(),
5735 entries_buf: EndianSlice::new(&[], LittleEndian),
5736 };
5737 let header_size = unit.size_of_header();
5738 let (entries_buf, entry2) = entries_tree_tests_debug_info_buf(header_size);
5739 unit.entries_buf = EndianSlice::new(&entries_buf, LittleEndian);
5740 let info_buf = Section::with_endian(Endian::Little)
5741 .unit(&mut unit)
5742 .get_contents()
5743 .unwrap();
5744 let debug_info = DebugInfo::new(&info_buf, LittleEndian);
5745
5746 let unit = debug_info
5747 .units()
5748 .next()
5749 .expect("Should parse unit")
5750 .expect("and it should be some");
5751 let abbrevs = unit
5752 .abbreviations(&debug_abbrev)
5753 .expect("Should parse abbreviations");
5754 let mut tree = unit
5755 .entries_tree(&abbrevs, None)
5756 .expect("Should have entries tree");
5757
5758 {
5760 let mut iter = assert_entry(tree.root().map(Some), "root");
5761 assert_entry(iter.next(), "1");
5762 }
5763 {
5764 let mut iter = assert_entry(tree.root().map(Some), "root");
5765 assert_entry(iter.next(), "1");
5766 }
5767
5768 let mut iter = assert_entry(tree.root().map(Some), "root");
5769 {
5770 let mut iter = assert_entry(iter.next(), "1");
5772 {
5773 let mut iter = assert_entry(iter.next(), "1a");
5775 assert_null(iter.next());
5776 assert_null(iter.next());
5777 }
5778 {
5779 let mut iter = assert_entry(iter.next(), "1b");
5781 assert_null(iter.next());
5782 assert_null(iter.next());
5783 }
5784 assert_null(iter.next());
5785 assert_null(iter.next());
5786 }
5787 {
5788 let mut iter = assert_entry(iter.next(), "2");
5790 assert_entry(iter.next(), "2a");
5791 assert_entry(iter.next(), "2b");
5792 assert_null(iter.next());
5793 }
5794 {
5795 let mut iter = assert_entry(iter.next(), "3");
5797 {
5798 let mut iter = assert_entry(iter.next(), "3a");
5799 assert_entry(iter.next(), "3a1");
5800 }
5802 assert_entry(iter.next(), "3b");
5803 assert_null(iter.next());
5804 }
5805 assert_entry(iter.next(), "final");
5806 assert_null(iter.next());
5807
5808 let mut tree = unit
5810 .entries_tree(&abbrevs, Some(entry2))
5811 .expect("Should have entries tree");
5812 let mut iter = assert_entry(tree.root().map(Some), "2");
5813 assert_entry(iter.next(), "2a");
5814 assert_entry(iter.next(), "2b");
5815 assert_null(iter.next());
5816 }
5817
5818 #[test]
5819 fn test_entries_raw() {
5820 fn assert_abbrev<'abbrev, Endian>(
5821 entries: &mut EntriesRaw<'abbrev, '_, EndianSlice<'_, Endian>>,
5822 tag: DwTag,
5823 ) -> &'abbrev Abbreviation
5824 where
5825 Endian: Endianity,
5826 {
5827 let abbrev = entries
5828 .read_abbreviation()
5829 .expect("Should parse abbrev")
5830 .expect("Should have abbrev");
5831 assert_eq!(abbrev.tag(), tag);
5832 abbrev
5833 }
5834
5835 fn assert_null<Endian>(entries: &mut EntriesRaw<'_, '_, EndianSlice<'_, Endian>>)
5836 where
5837 Endian: Endianity,
5838 {
5839 match entries.read_abbreviation() {
5840 Ok(None) => {}
5841 otherwise => {
5842 panic!("Unexpected parse result = {:#?}", otherwise);
5843 }
5844 }
5845 }
5846
5847 fn assert_attr<Endian>(
5848 entries: &mut EntriesRaw<'_, '_, EndianSlice<'_, Endian>>,
5849 spec: Option<AttributeSpecification>,
5850 name: DwAt,
5851 value: &str,
5852 ) where
5853 Endian: Endianity,
5854 {
5855 let spec = spec.expect("Should have attribute specification");
5856 let attr = entries
5857 .read_attribute(spec)
5858 .expect("Should parse attribute");
5859 assert_eq!(attr.name(), name);
5860 assert_eq!(
5861 attr.value(),
5862 AttributeValue::String(EndianSlice::new(value.as_bytes(), Endian::default()))
5863 );
5864 }
5865
5866 #[rustfmt::skip]
5867 let section = Section::with_endian(Endian::Little)
5868 .abbrev(1, DW_TAG_subprogram, DW_CHILDREN_yes)
5869 .abbrev_attr(DW_AT_name, DW_FORM_string)
5870 .abbrev_attr(DW_AT_linkage_name, DW_FORM_string)
5871 .abbrev_attr_null()
5872 .abbrev(2, DW_TAG_variable, DW_CHILDREN_no)
5873 .abbrev_attr(DW_AT_name, DW_FORM_string)
5874 .abbrev_attr_null()
5875 .abbrev_null();
5876 let abbrevs_buf = section.get_contents().unwrap();
5877 let debug_abbrev = DebugAbbrev::new(&abbrevs_buf, LittleEndian);
5878
5879 #[rustfmt::skip]
5880 let section = Section::with_endian(Endian::Little)
5881 .die(1, |s| s.attr_string("f1").attr_string("l1"))
5882 .die(2, |s| s.attr_string("v1"))
5883 .die(2, |s| s.attr_string("v2"))
5884 .die(1, |s| s.attr_string("f2").attr_string("l2"))
5885 .die_null()
5886 .die_null();
5887 let entries_buf = section.get_contents().unwrap();
5888
5889 let encoding = Encoding {
5890 format: Format::Dwarf32,
5891 version: 4,
5892 address_size: 4,
5893 };
5894 let mut unit = UnitHeader {
5895 encoding,
5896 unit_length: 0,
5897 unit_type: UnitType::Compilation,
5898 debug_abbrev_offset: DebugAbbrevOffset(0),
5899 unit_offset: DebugInfoOffset(0).into(),
5900 entries_buf: EndianSlice::new(&entries_buf, LittleEndian),
5901 };
5902 let section = Section::with_endian(Endian::Little).unit(&mut unit);
5903 let info_buf = section.get_contents().unwrap();
5904 let debug_info = DebugInfo::new(&info_buf, LittleEndian);
5905
5906 let unit = debug_info
5907 .units()
5908 .next()
5909 .expect("should have a unit result")
5910 .expect("and it should be ok");
5911
5912 let abbrevs = unit
5913 .abbreviations(&debug_abbrev)
5914 .expect("Should parse abbreviations");
5915
5916 let mut entries = unit
5917 .entries_raw(&abbrevs, None)
5918 .expect("Should have entries");
5919
5920 assert_eq!(entries.next_depth(), 0);
5921 let abbrev = assert_abbrev(&mut entries, DW_TAG_subprogram);
5922 let mut attrs = abbrev.attributes().iter().copied();
5923 assert_attr(&mut entries, attrs.next(), DW_AT_name, "f1");
5924 assert_attr(&mut entries, attrs.next(), DW_AT_linkage_name, "l1");
5925 assert!(attrs.next().is_none());
5926
5927 assert_eq!(entries.next_depth(), 1);
5928 let abbrev = assert_abbrev(&mut entries, DW_TAG_variable);
5929 let mut attrs = abbrev.attributes().iter().copied();
5930 assert_attr(&mut entries, attrs.next(), DW_AT_name, "v1");
5931 assert!(attrs.next().is_none());
5932
5933 assert_eq!(entries.next_depth(), 1);
5934 let abbrev = assert_abbrev(&mut entries, DW_TAG_variable);
5935 let mut attrs = abbrev.attributes().iter().copied();
5936 assert_attr(&mut entries, attrs.next(), DW_AT_name, "v2");
5937 assert!(attrs.next().is_none());
5938
5939 assert_eq!(entries.next_depth(), 1);
5940 let abbrev = assert_abbrev(&mut entries, DW_TAG_subprogram);
5941 let mut attrs = abbrev.attributes().iter().copied();
5942 assert_attr(&mut entries, attrs.next(), DW_AT_name, "f2");
5943 assert_attr(&mut entries, attrs.next(), DW_AT_linkage_name, "l2");
5944 assert!(attrs.next().is_none());
5945
5946 assert_eq!(entries.next_depth(), 2);
5947 assert_null(&mut entries);
5948
5949 assert_eq!(entries.next_depth(), 1);
5950 assert_null(&mut entries);
5951
5952 assert_eq!(entries.next_depth(), 0);
5953 assert!(entries.is_empty());
5954 }
5955
5956 #[test]
5957 fn test_debug_info_offset() {
5958 let padding = &[0; 10];
5959 let entries = &[0; 20];
5960 let encoding = Encoding {
5961 format: Format::Dwarf32,
5962 version: 4,
5963 address_size: 4,
5964 };
5965 let mut unit = UnitHeader {
5966 encoding,
5967 unit_length: 0,
5968 unit_type: UnitType::Compilation,
5969 debug_abbrev_offset: DebugAbbrevOffset(0),
5970 unit_offset: DebugInfoOffset(0).into(),
5971 entries_buf: EndianSlice::new(entries, LittleEndian),
5972 };
5973 Section::with_endian(Endian::Little)
5974 .append_bytes(padding)
5975 .unit(&mut unit);
5976 let offset = padding.len();
5977 let header_length = unit.size_of_header();
5978 let length = unit.length_including_self();
5979 assert_eq!(DebugInfoOffset(0).to_unit_offset(&unit), None);
5980 assert_eq!(DebugInfoOffset(offset - 1).to_unit_offset(&unit), None);
5981 assert_eq!(DebugInfoOffset(offset).to_unit_offset(&unit), None);
5982 assert_eq!(
5983 DebugInfoOffset(offset + header_length - 1).to_unit_offset(&unit),
5984 None
5985 );
5986 assert_eq!(
5987 DebugInfoOffset(offset + header_length).to_unit_offset(&unit),
5988 Some(UnitOffset(header_length))
5989 );
5990 assert_eq!(
5991 DebugInfoOffset(offset + length - 1).to_unit_offset(&unit),
5992 Some(UnitOffset(length - 1))
5993 );
5994 assert_eq!(DebugInfoOffset(offset + length).to_unit_offset(&unit), None);
5995 assert_eq!(
5996 UnitOffset(header_length).to_debug_info_offset(&unit),
5997 Some(DebugInfoOffset(offset + header_length))
5998 );
5999 assert_eq!(
6000 UnitOffset(length - 1).to_debug_info_offset(&unit),
6001 Some(DebugInfoOffset(offset + length - 1))
6002 );
6003 }
6004
6005 #[test]
6006 fn test_debug_types_offset() {
6007 let padding = &[0; 10];
6008 let entries = &[0; 20];
6009 let encoding = Encoding {
6010 format: Format::Dwarf32,
6011 version: 4,
6012 address_size: 4,
6013 };
6014 let mut unit = UnitHeader {
6015 encoding,
6016 unit_length: 0,
6017 unit_type: UnitType::Type {
6018 type_signature: DebugTypeSignature(0),
6019 type_offset: UnitOffset(0),
6020 },
6021 debug_abbrev_offset: DebugAbbrevOffset(0),
6022 unit_offset: DebugTypesOffset(0).into(),
6023 entries_buf: EndianSlice::new(entries, LittleEndian),
6024 };
6025 Section::with_endian(Endian::Little)
6026 .append_bytes(padding)
6027 .unit(&mut unit);
6028 let offset = padding.len();
6029 let header_length = unit.size_of_header();
6030 let length = unit.length_including_self();
6031 assert_eq!(DebugTypesOffset(0).to_unit_offset(&unit), None);
6032 assert_eq!(DebugTypesOffset(offset - 1).to_unit_offset(&unit), None);
6033 assert_eq!(DebugTypesOffset(offset).to_unit_offset(&unit), None);
6034 assert_eq!(
6035 DebugTypesOffset(offset + header_length - 1).to_unit_offset(&unit),
6036 None
6037 );
6038 assert_eq!(
6039 DebugTypesOffset(offset + header_length).to_unit_offset(&unit),
6040 Some(UnitOffset(header_length))
6041 );
6042 assert_eq!(
6043 DebugTypesOffset(offset + length - 1).to_unit_offset(&unit),
6044 Some(UnitOffset(length - 1))
6045 );
6046 assert_eq!(
6047 DebugTypesOffset(offset + length).to_unit_offset(&unit),
6048 None
6049 );
6050 assert_eq!(
6051 UnitOffset(header_length).to_debug_types_offset(&unit),
6052 Some(DebugTypesOffset(offset + header_length))
6053 );
6054 assert_eq!(
6055 UnitOffset(length - 1).to_debug_types_offset(&unit),
6056 Some(DebugTypesOffset(offset + length - 1))
6057 );
6058 }
6059
6060 #[test]
6061 fn test_length_including_self() {
6062 let encoding = Encoding {
6063 format: Format::Dwarf32,
6064 version: 4,
6065 address_size: 4,
6066 };
6067 let mut unit = UnitHeader {
6068 encoding,
6069 unit_length: 0,
6070 unit_type: UnitType::Compilation,
6071 debug_abbrev_offset: DebugAbbrevOffset(0),
6072 unit_offset: DebugInfoOffset(0).into(),
6073 entries_buf: EndianSlice::new(&[], LittleEndian),
6074 };
6075 unit.encoding.format = Format::Dwarf32;
6076 assert_eq!(unit.length_including_self(), 4);
6077 unit.encoding.format = Format::Dwarf64;
6078 assert_eq!(unit.length_including_self(), 12);
6079 unit.unit_length = 10;
6080 assert_eq!(unit.length_including_self(), 22);
6081 }
6082
6083 #[test]
6084 fn test_parse_type_unit_abbrevs() {
6085 let types_buf = [
6086 0x25, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04, 0x01, 0x66, 0x6f, 0x6f, 0x00, 0x01, 0x66, 0x6f, 0x6f, 0x00, 0x01, 0x66, 0x6f, 0x6f, 0x00, 0x00, 0x00, 0x00, ];
6107 let debug_types = DebugTypes::new(&types_buf, LittleEndian);
6108
6109 let abbrev_buf = [
6110 0x01, 0x2e, 0x01, 0x03, 0x08, 0x00, 0x00, 0x00, ];
6119
6120 let get_some_type_unit = || debug_types.units().next().unwrap().unwrap();
6121
6122 let unit = get_some_type_unit();
6123
6124 let read_debug_abbrev_section_somehow = || &abbrev_buf;
6125 let debug_abbrev = DebugAbbrev::new(read_debug_abbrev_section_somehow(), LittleEndian);
6126 let _abbrevs_for_unit = unit.abbreviations(&debug_abbrev).unwrap();
6127 }
6128}