1use alloc::string::String;
2use alloc::sync::Arc;
3
4use crate::common::{
5 DebugAddrBase, DebugAddrIndex, DebugInfoOffset, DebugLineStrOffset, DebugLocListsBase,
6 DebugLocListsIndex, DebugMacinfoOffset, DebugRngListsBase, DebugRngListsIndex, DebugStrOffset,
7 DebugStrOffsetsBase, DebugStrOffsetsIndex, DebugTypeSignature, DwarfFileType, DwoId, Encoding,
8 LocationListsOffset, RangeListsOffset, RawRangeListsOffset, SectionId,
9};
10use crate::read::{
11 Abbreviations, AbbreviationsCache, AbbreviationsCacheStrategy, AttributeValue, DebugAbbrev,
12 DebugAddr, DebugAranges, DebugCuIndex, DebugInfo, DebugInfoUnitHeadersIter, DebugLine,
13 DebugLineStr, DebugLoc, DebugLocLists, DebugMacinfo, DebugMacro, DebugNames, DebugRanges,
14 DebugRngLists, DebugStr, DebugStrOffsets, DebugTuIndex, DebugTypes, DebugTypesUnitHeadersIter,
15 DebuggingInformationEntry, EntriesCursor, EntriesRaw, EntriesTree, Error,
16 IncompleteLineProgram, IndexSectionId, LocListIter, LocationLists, MacroIter, Range,
17 RangeLists, RawLocListIter, RawRngListIter, Reader, ReaderOffset, ReaderOffsetId, Result,
18 RngListIter, Section, UnitHeader, UnitIndex, UnitIndexSectionIterator, UnitOffset, UnitType,
19};
20use crate::{DebugMacroOffset, constants};
21
22#[derive(Debug, Default)]
50pub struct DwarfSections<T> {
51 pub debug_abbrev: DebugAbbrev<T>,
53 pub debug_addr: DebugAddr<T>,
55 pub debug_aranges: DebugAranges<T>,
57 pub debug_info: DebugInfo<T>,
59 pub debug_line: DebugLine<T>,
61 pub debug_line_str: DebugLineStr<T>,
63 pub debug_macinfo: DebugMacinfo<T>,
65 pub debug_macro: DebugMacro<T>,
67 pub debug_names: DebugNames<T>,
69 pub debug_str: DebugStr<T>,
71 pub debug_str_offsets: DebugStrOffsets<T>,
73 pub debug_types: DebugTypes<T>,
75 pub debug_loc: DebugLoc<T>,
77 pub debug_loclists: DebugLocLists<T>,
79 pub debug_ranges: DebugRanges<T>,
81 pub debug_rnglists: DebugRngLists<T>,
83}
84
85impl<T> DwarfSections<T> {
86 pub fn load<F, E>(mut section: F) -> core::result::Result<Self, E>
91 where
92 F: FnMut(SectionId) -> core::result::Result<T, E>,
93 {
94 Ok(DwarfSections {
95 debug_abbrev: Section::load(&mut section)?,
97 debug_addr: Section::load(&mut section)?,
98 debug_aranges: Section::load(&mut section)?,
99 debug_info: Section::load(&mut section)?,
100 debug_line: Section::load(&mut section)?,
101 debug_line_str: Section::load(&mut section)?,
102 debug_macinfo: Section::load(&mut section)?,
103 debug_macro: Section::load(&mut section)?,
104 debug_names: Section::load(&mut section)?,
105 debug_str: Section::load(&mut section)?,
106 debug_str_offsets: Section::load(&mut section)?,
107 debug_types: Section::load(&mut section)?,
108 debug_loc: Section::load(&mut section)?,
109 debug_loclists: Section::load(&mut section)?,
110 debug_ranges: Section::load(&mut section)?,
111 debug_rnglists: Section::load(&mut section)?,
112 })
113 }
114
115 pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> Dwarf<R>
117 where
118 F: FnMut(&'a T) -> R,
119 {
120 Dwarf::from_sections(DwarfSections {
121 debug_abbrev: self.debug_abbrev.borrow(&mut borrow),
122 debug_addr: self.debug_addr.borrow(&mut borrow),
123 debug_aranges: self.debug_aranges.borrow(&mut borrow),
124 debug_info: self.debug_info.borrow(&mut borrow),
125 debug_line: self.debug_line.borrow(&mut borrow),
126 debug_line_str: self.debug_line_str.borrow(&mut borrow),
127 debug_macinfo: self.debug_macinfo.borrow(&mut borrow),
128 debug_macro: self.debug_macro.borrow(&mut borrow),
129 debug_names: self.debug_names.borrow(&mut borrow),
130 debug_str: self.debug_str.borrow(&mut borrow),
131 debug_str_offsets: self.debug_str_offsets.borrow(&mut borrow),
132 debug_types: self.debug_types.borrow(&mut borrow),
133 debug_loc: self.debug_loc.borrow(&mut borrow),
134 debug_loclists: self.debug_loclists.borrow(&mut borrow),
135 debug_ranges: self.debug_ranges.borrow(&mut borrow),
136 debug_rnglists: self.debug_rnglists.borrow(&mut borrow),
137 })
138 }
139
140 pub fn borrow_with_sup<'a, F, R>(&'a self, sup: Option<&'a Self>, mut borrow: F) -> Dwarf<R>
162 where
163 F: FnMut(&'a T) -> R,
164 {
165 let mut dwarf = self.borrow(&mut borrow);
166 if let Some(sup) = sup {
167 dwarf.set_sup(sup.borrow(&mut borrow));
168 }
169 dwarf
170 }
171}
172
173#[derive(Debug, Default)]
175pub struct Dwarf<R> {
176 pub debug_abbrev: DebugAbbrev<R>,
178
179 pub debug_addr: DebugAddr<R>,
181
182 pub debug_aranges: DebugAranges<R>,
184
185 pub debug_info: DebugInfo<R>,
187
188 pub debug_line: DebugLine<R>,
190
191 pub debug_line_str: DebugLineStr<R>,
193
194 pub debug_macinfo: DebugMacinfo<R>,
196
197 pub debug_macro: DebugMacro<R>,
199
200 pub debug_names: DebugNames<R>,
202
203 pub debug_str: DebugStr<R>,
205
206 pub debug_str_offsets: DebugStrOffsets<R>,
208
209 pub debug_types: DebugTypes<R>,
211
212 pub locations: LocationLists<R>,
214
215 pub ranges: RangeLists<R>,
217
218 pub file_type: DwarfFileType,
220
221 pub sup: Option<Arc<Dwarf<R>>>,
223
224 pub abbreviations_cache: AbbreviationsCache,
226}
227
228impl<T> Dwarf<T> {
229 pub fn load<F, E>(section: F) -> core::result::Result<Self, E>
237 where
238 F: FnMut(SectionId) -> core::result::Result<T, E>,
239 {
240 let sections = DwarfSections::load(section)?;
241 Ok(Self::from_sections(sections))
242 }
243
244 pub fn load_sup<F, E>(&mut self, section: F) -> core::result::Result<(), E>
250 where
251 F: FnMut(SectionId) -> core::result::Result<T, E>,
252 {
253 self.set_sup(Self::load(section)?);
254 Ok(())
255 }
256
257 fn from_sections(sections: DwarfSections<T>) -> Self {
261 Dwarf {
262 debug_abbrev: sections.debug_abbrev,
263 debug_addr: sections.debug_addr,
264 debug_aranges: sections.debug_aranges,
265 debug_info: sections.debug_info,
266 debug_line: sections.debug_line,
267 debug_line_str: sections.debug_line_str,
268 debug_macinfo: sections.debug_macinfo,
269 debug_macro: sections.debug_macro,
270 debug_names: sections.debug_names,
271 debug_str: sections.debug_str,
272 debug_str_offsets: sections.debug_str_offsets,
273 debug_types: sections.debug_types,
274 locations: LocationLists::new(sections.debug_loc, sections.debug_loclists),
275 ranges: RangeLists::new(sections.debug_ranges, sections.debug_rnglists),
276 file_type: DwarfFileType::Main,
277 sup: None,
278 abbreviations_cache: AbbreviationsCache::new(),
279 }
280 }
281
282 #[deprecated(note = "use `DwarfSections::borrow` instead")]
310 pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> Dwarf<R>
311 where
312 F: FnMut(&'a T) -> R,
313 {
314 Dwarf {
315 debug_abbrev: self.debug_abbrev.borrow(&mut borrow),
316 debug_addr: self.debug_addr.borrow(&mut borrow),
317 debug_aranges: self.debug_aranges.borrow(&mut borrow),
318 debug_info: self.debug_info.borrow(&mut borrow),
319 debug_line: self.debug_line.borrow(&mut borrow),
320 debug_line_str: self.debug_line_str.borrow(&mut borrow),
321 debug_macinfo: self.debug_macinfo.borrow(&mut borrow),
322 debug_macro: self.debug_macro.borrow(&mut borrow),
323 debug_names: self.debug_names.borrow(&mut borrow),
324 debug_str: self.debug_str.borrow(&mut borrow),
325 debug_str_offsets: self.debug_str_offsets.borrow(&mut borrow),
326 debug_types: self.debug_types.borrow(&mut borrow),
327 locations: self.locations.borrow(&mut borrow),
328 ranges: self.ranges.borrow(&mut borrow),
329 file_type: self.file_type,
330 sup: self.sup().map(|sup| Arc::new(sup.borrow(borrow))),
331 abbreviations_cache: AbbreviationsCache::new(),
332 }
333 }
334
335 pub fn set_sup(&mut self, sup: Dwarf<T>) {
337 self.sup = Some(Arc::new(sup));
338 }
339
340 pub fn sup(&self) -> Option<&Dwarf<T>> {
342 self.sup.as_ref().map(Arc::as_ref)
343 }
344}
345
346impl<R: Reader> Dwarf<R> {
347 pub fn populate_abbreviations_cache(&mut self, strategy: AbbreviationsCacheStrategy) {
355 self.abbreviations_cache
356 .populate(strategy, &self.debug_abbrev, self.debug_info.units());
357 }
358
359 #[inline]
361 pub fn units(&self) -> DebugInfoUnitHeadersIter<R> {
362 self.debug_info.units()
363 }
364
365 #[inline]
367 pub fn unit_header(&self, offset: DebugInfoOffset<R::Offset>) -> Result<UnitHeader<R>> {
368 self.debug_info.header_from_offset(offset)
369 }
370
371 #[inline]
373 pub fn unit(&self, header: UnitHeader<R>) -> Result<Unit<R>> {
374 Unit::new(self, header)
375 }
376
377 #[inline]
379 pub fn type_units(&self) -> DebugTypesUnitHeadersIter<R> {
380 self.debug_types.units()
381 }
382
383 #[inline]
385 pub fn abbreviations(&self, unit: &UnitHeader<R>) -> Result<Arc<Abbreviations>> {
386 self.abbreviations_cache
387 .get(&self.debug_abbrev, unit.debug_abbrev_offset())
388 }
389
390 #[inline]
392 pub fn string_offset(
393 &self,
394 unit: &Unit<R>,
395 index: DebugStrOffsetsIndex<R::Offset>,
396 ) -> Result<DebugStrOffset<R::Offset>> {
397 self.debug_str_offsets
398 .get_str_offset(unit.header.format(), unit.str_offsets_base, index)
399 }
400
401 #[inline]
403 pub fn string(&self, offset: DebugStrOffset<R::Offset>) -> Result<R> {
404 self.debug_str.get_str(offset)
405 }
406
407 #[inline]
409 pub fn line_string(&self, offset: DebugLineStrOffset<R::Offset>) -> Result<R> {
410 self.debug_line_str.get_str(offset)
411 }
412
413 #[inline]
416 pub fn sup_string(&self, offset: DebugStrOffset<R::Offset>) -> Result<R> {
417 if let Some(sup) = self.sup() {
418 sup.debug_str.get_str(offset)
419 } else {
420 Err(Error::ExpectedStringAttributeValue)
421 }
422 }
423
424 pub fn attr_string(&self, unit: &Unit<R>, attr: AttributeValue<R>) -> Result<R> {
439 match attr {
440 AttributeValue::String(string) => Ok(string),
441 AttributeValue::DebugStrRef(offset) => self.string(offset),
442 AttributeValue::DebugStrRefSup(offset) => self.sup_string(offset),
443 AttributeValue::DebugLineStrRef(offset) => self.line_string(offset),
444 AttributeValue::DebugStrOffsetsIndex(index) => {
445 let offset = self.string_offset(unit, index)?;
446 self.string(offset)
447 }
448 _ => Err(Error::ExpectedStringAttributeValue),
449 }
450 }
451
452 pub fn attr_line_string(&self, attr: AttributeValue<R>) -> Result<R> {
468 match attr {
469 AttributeValue::String(string) => Ok(string),
470 AttributeValue::DebugStrRef(offset) => self.string(offset),
471 AttributeValue::DebugStrRefSup(offset) => self.sup_string(offset),
472 AttributeValue::DebugLineStrRef(offset) => self.line_string(offset),
473 _ => Err(Error::ExpectedStringAttributeValue),
474 }
475 }
476
477 pub fn address(&self, unit: &Unit<R>, index: DebugAddrIndex<R::Offset>) -> Result<u64> {
479 self.debug_addr
480 .get_address(unit.encoding().address_size, unit.addr_base, index)
481 }
482
483 pub fn attr_address(&self, unit: &Unit<R>, attr: AttributeValue<R>) -> Result<Option<u64>> {
493 match attr {
494 AttributeValue::Addr(addr) => Ok(Some(addr)),
495 AttributeValue::DebugAddrIndex(index) => self.address(unit, index).map(Some),
496 _ => Ok(None),
497 }
498 }
499
500 pub fn ranges_offset_from_raw(
504 &self,
505 unit: &Unit<R>,
506 offset: RawRangeListsOffset<R::Offset>,
507 ) -> RangeListsOffset<R::Offset> {
508 if self.file_type == DwarfFileType::Dwo && unit.header.version() < 5 {
509 RangeListsOffset(offset.0.wrapping_add(unit.rnglists_base.0))
510 } else {
511 RangeListsOffset(offset.0)
512 }
513 }
514
515 pub fn ranges_offset(
517 &self,
518 unit: &Unit<R>,
519 index: DebugRngListsIndex<R::Offset>,
520 ) -> Result<RangeListsOffset<R::Offset>> {
521 self.ranges
522 .get_offset(unit.encoding(), unit.rnglists_base, index)
523 }
524
525 pub fn ranges(
527 &self,
528 unit: &Unit<R>,
529 offset: RangeListsOffset<R::Offset>,
530 ) -> Result<RngListIter<R>> {
531 self.ranges.ranges(
532 offset,
533 unit.encoding(),
534 unit.low_pc,
535 &self.debug_addr,
536 unit.addr_base,
537 )
538 }
539
540 pub fn raw_ranges(
542 &self,
543 unit: &Unit<R>,
544 offset: RangeListsOffset<R::Offset>,
545 ) -> Result<RawRngListIter<R>> {
546 self.ranges.raw_ranges(offset, unit.encoding())
547 }
548
549 pub fn attr_ranges_offset(
559 &self,
560 unit: &Unit<R>,
561 attr: AttributeValue<R>,
562 ) -> Result<Option<RangeListsOffset<R::Offset>>> {
563 match attr {
564 AttributeValue::RangeListsRef(offset) => {
565 Ok(Some(self.ranges_offset_from_raw(unit, offset)))
566 }
567 AttributeValue::DebugRngListsIndex(index) => self.ranges_offset(unit, index).map(Some),
568 _ => Ok(None),
569 }
570 }
571
572 pub fn attr_ranges(
582 &self,
583 unit: &Unit<R>,
584 attr: AttributeValue<R>,
585 ) -> Result<Option<RngListIter<R>>> {
586 match self.attr_ranges_offset(unit, attr)? {
587 Some(offset) => Ok(Some(self.ranges(unit, offset)?)),
588 None => Ok(None),
589 }
590 }
591
592 pub fn die_ranges(
596 &self,
597 unit: &Unit<R>,
598 entry: &DebuggingInformationEntry<R>,
599 ) -> Result<RangeIter<R>> {
600 let mut low_pc = None;
601 let mut high_pc = None;
602 let mut size = None;
603 for attr in entry.attrs() {
604 match attr.name() {
605 constants::DW_AT_low_pc => {
606 low_pc = Some(
607 self.attr_address(unit, attr.value())?
608 .ok_or(Error::UnsupportedAttributeForm(attr.form()))?,
609 );
610 }
611 constants::DW_AT_high_pc => match attr.value() {
612 AttributeValue::Udata(val) => size = Some(val),
613 value => {
614 high_pc = Some(
615 self.attr_address(unit, value)?
616 .ok_or(Error::UnsupportedAttributeForm(attr.form()))?,
617 );
618 }
619 },
620 constants::DW_AT_ranges => {
621 if let Some(list) = self.attr_ranges(unit, attr.value())? {
622 return Ok(RangeIter(RangeIterInner::List(list)));
623 }
624 }
625 _ => {}
626 }
627 }
628 let range = low_pc.and_then(|begin| {
629 let end = size.map(|size| begin + size).or(high_pc);
630 end.map(|end| Range { begin, end })
632 });
633 Ok(RangeIter(RangeIterInner::Single(range)))
634 }
635
636 pub fn unit_ranges(&self, unit: &Unit<R>) -> Result<RangeIter<R>> {
641 let mut cursor = unit.header.entries(&unit.abbreviations);
642 cursor.next_dfs()?;
643 let root = cursor.current().ok_or(Error::MissingUnitDie)?;
644 self.die_ranges(unit, root)
645 }
646
647 pub fn locations_offset(
649 &self,
650 unit: &Unit<R>,
651 index: DebugLocListsIndex<R::Offset>,
652 ) -> Result<LocationListsOffset<R::Offset>> {
653 self.locations
654 .get_offset(unit.encoding(), unit.loclists_base, index)
655 }
656
657 pub fn locations(
659 &self,
660 unit: &Unit<R>,
661 offset: LocationListsOffset<R::Offset>,
662 ) -> Result<LocListIter<R>> {
663 match self.file_type {
664 DwarfFileType::Main => self.locations.locations(
665 offset,
666 unit.encoding(),
667 unit.low_pc,
668 &self.debug_addr,
669 unit.addr_base,
670 ),
671 DwarfFileType::Dwo => self.locations.locations_dwo(
672 offset,
673 unit.encoding(),
674 unit.low_pc,
675 &self.debug_addr,
676 unit.addr_base,
677 ),
678 }
679 }
680
681 pub fn raw_locations(
683 &self,
684 unit: &Unit<R>,
685 offset: LocationListsOffset<R::Offset>,
686 ) -> Result<RawLocListIter<R>> {
687 match self.file_type {
688 DwarfFileType::Main => self.locations.raw_locations(offset, unit.encoding()),
689 DwarfFileType::Dwo => self.locations.raw_locations_dwo(offset, unit.encoding()),
690 }
691 }
692
693 pub fn attr_locations_offset(
703 &self,
704 unit: &Unit<R>,
705 attr: AttributeValue<R>,
706 ) -> Result<Option<LocationListsOffset<R::Offset>>> {
707 match attr {
708 AttributeValue::LocationListsRef(offset) => Ok(Some(offset)),
709 AttributeValue::DebugLocListsIndex(index) => {
710 self.locations_offset(unit, index).map(Some)
711 }
712 _ => Ok(None),
713 }
714 }
715
716 pub fn attr_locations(
726 &self,
727 unit: &Unit<R>,
728 attr: AttributeValue<R>,
729 ) -> Result<Option<LocListIter<R>>> {
730 match self.attr_locations_offset(unit, attr)? {
731 Some(offset) => Ok(Some(self.locations(unit, offset)?)),
732 None => Ok(None),
733 }
734 }
735
736 pub fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option<(bool, SectionId, R::Offset)> {
740 None.or_else(|| self.debug_abbrev.lookup_offset_id(id))
741 .or_else(|| self.debug_addr.lookup_offset_id(id))
742 .or_else(|| self.debug_aranges.lookup_offset_id(id))
743 .or_else(|| self.debug_info.lookup_offset_id(id))
744 .or_else(|| self.debug_line.lookup_offset_id(id))
745 .or_else(|| self.debug_line_str.lookup_offset_id(id))
746 .or_else(|| self.debug_str.lookup_offset_id(id))
747 .or_else(|| self.debug_str_offsets.lookup_offset_id(id))
748 .or_else(|| self.debug_types.lookup_offset_id(id))
749 .or_else(|| self.locations.lookup_offset_id(id))
750 .or_else(|| self.ranges.lookup_offset_id(id))
751 .map(|(id, offset)| (false, id, offset))
752 .or_else(|| {
753 self.sup()
754 .and_then(|sup| sup.lookup_offset_id(id))
755 .map(|(_, id, offset)| (true, id, offset))
756 })
757 }
758
759 pub fn format_error(&self, err: Error) -> String {
763 #[allow(clippy::single_match)]
764 match err {
765 Error::UnexpectedEof(id) => match self.lookup_offset_id(id) {
766 Some((sup, section, offset)) => {
767 return format!(
768 "{} at {}{}+0x{:x}",
769 err,
770 section.name(),
771 if sup { "(sup)" } else { "" },
772 offset.into_u64(),
773 );
774 }
775 None => {}
776 },
777 _ => {}
778 }
779 format!("{}", err)
780 }
781
782 pub fn macinfo(&self, offset: DebugMacinfoOffset<R::Offset>) -> Result<MacroIter<R>> {
784 self.debug_macinfo.get_macinfo(offset)
785 }
786
787 pub fn macros(&self, offset: DebugMacroOffset<R::Offset>) -> Result<MacroIter<R>> {
789 self.debug_macro.get_macros(offset)
790 }
791}
792
793impl<R: Clone> Dwarf<R> {
794 pub fn make_dwo(&mut self, parent: &Dwarf<R>) {
798 self.file_type = DwarfFileType::Dwo;
799 self.debug_addr = parent.debug_addr.clone();
801 self.ranges
804 .set_debug_ranges(parent.ranges.debug_ranges().clone());
805 self.sup.clone_from(&parent.sup);
806 }
807}
808
809#[derive(Debug, Default)]
838pub struct DwarfPackageSections<T> {
839 pub cu_index: DebugCuIndex<T>,
841 pub tu_index: DebugTuIndex<T>,
843 pub debug_abbrev: DebugAbbrev<T>,
845 pub debug_info: DebugInfo<T>,
847 pub debug_line: DebugLine<T>,
849 pub debug_macinfo: DebugMacinfo<T>,
853 pub debug_macro: DebugMacro<T>,
855 pub debug_str: DebugStr<T>,
857 pub debug_str_offsets: DebugStrOffsets<T>,
859 pub debug_loc: DebugLoc<T>,
863 pub debug_loclists: DebugLocLists<T>,
865 pub debug_rnglists: DebugRngLists<T>,
867 pub debug_types: DebugTypes<T>,
871}
872
873impl<T> DwarfPackageSections<T> {
874 pub fn load<F, E>(mut section: F) -> core::result::Result<Self, E>
879 where
880 F: FnMut(SectionId) -> core::result::Result<T, E>,
881 E: From<Error>,
882 {
883 Ok(DwarfPackageSections {
884 cu_index: Section::load(&mut section)?,
886 tu_index: Section::load(&mut section)?,
887 debug_abbrev: Section::load(&mut section)?,
888 debug_info: Section::load(&mut section)?,
889 debug_line: Section::load(&mut section)?,
890 debug_macinfo: Section::load(&mut section)?,
891 debug_macro: Section::load(&mut section)?,
892 debug_str: Section::load(&mut section)?,
893 debug_str_offsets: Section::load(&mut section)?,
894 debug_loc: Section::load(&mut section)?,
895 debug_loclists: Section::load(&mut section)?,
896 debug_rnglists: Section::load(&mut section)?,
897 debug_types: Section::load(&mut section)?,
898 })
899 }
900
901 pub fn borrow<'a, F, R>(&'a self, mut borrow: F, empty: R) -> Result<DwarfPackage<R>>
903 where
904 F: FnMut(&'a T) -> R,
905 R: Reader,
906 {
907 DwarfPackage::from_sections(
908 DwarfPackageSections {
909 cu_index: self.cu_index.borrow(&mut borrow),
910 tu_index: self.tu_index.borrow(&mut borrow),
911 debug_abbrev: self.debug_abbrev.borrow(&mut borrow),
912 debug_info: self.debug_info.borrow(&mut borrow),
913 debug_line: self.debug_line.borrow(&mut borrow),
914 debug_macinfo: self.debug_macinfo.borrow(&mut borrow),
915 debug_macro: self.debug_macro.borrow(&mut borrow),
916 debug_str: self.debug_str.borrow(&mut borrow),
917 debug_str_offsets: self.debug_str_offsets.borrow(&mut borrow),
918 debug_loc: self.debug_loc.borrow(&mut borrow),
919 debug_loclists: self.debug_loclists.borrow(&mut borrow),
920 debug_rnglists: self.debug_rnglists.borrow(&mut borrow),
921 debug_types: self.debug_types.borrow(&mut borrow),
922 },
923 empty,
924 )
925 }
926}
927
928#[derive(Debug)]
930pub struct DwarfPackage<R: Reader> {
931 pub cu_index: UnitIndex<R>,
933
934 pub tu_index: UnitIndex<R>,
936
937 pub debug_abbrev: DebugAbbrev<R>,
939
940 pub debug_info: DebugInfo<R>,
942
943 pub debug_line: DebugLine<R>,
945
946 pub debug_macinfo: DebugMacinfo<R>,
948
949 pub debug_macro: DebugMacro<R>,
951
952 pub debug_str: DebugStr<R>,
954
955 pub debug_str_offsets: DebugStrOffsets<R>,
957
958 pub debug_loc: DebugLoc<R>,
962
963 pub debug_loclists: DebugLocLists<R>,
965
966 pub debug_rnglists: DebugRngLists<R>,
968
969 pub debug_types: DebugTypes<R>,
973
974 pub empty: R,
978}
979
980impl<R: Reader> DwarfPackage<R> {
981 pub fn load<F, E>(section: F, empty: R) -> core::result::Result<Self, E>
986 where
987 F: FnMut(SectionId) -> core::result::Result<R, E>,
988 E: From<Error>,
989 {
990 let sections = DwarfPackageSections::load(section)?;
991 Ok(Self::from_sections(sections, empty)?)
992 }
993
994 fn from_sections(sections: DwarfPackageSections<R>, empty: R) -> Result<Self> {
996 Ok(DwarfPackage {
997 cu_index: sections.cu_index.index()?,
998 tu_index: sections.tu_index.index()?,
999 debug_abbrev: sections.debug_abbrev,
1000 debug_info: sections.debug_info,
1001 debug_line: sections.debug_line,
1002 debug_macinfo: sections.debug_macinfo,
1003 debug_macro: sections.debug_macro,
1004 debug_str: sections.debug_str,
1005 debug_str_offsets: sections.debug_str_offsets,
1006 debug_loc: sections.debug_loc,
1007 debug_loclists: sections.debug_loclists,
1008 debug_rnglists: sections.debug_rnglists,
1009 debug_types: sections.debug_types,
1010 empty,
1011 })
1012 }
1013
1014 pub fn find_cu(&self, id: DwoId, parent: &Dwarf<R>) -> Result<Option<Dwarf<R>>> {
1033 let row = match self.cu_index.find(id.0) {
1034 Some(row) => row,
1035 None => return Ok(None),
1036 };
1037 self.cu_sections(row, parent).map(Some)
1038 }
1039
1040 pub fn find_tu(
1043 &self,
1044 signature: DebugTypeSignature,
1045 parent: &Dwarf<R>,
1046 ) -> Result<Option<Dwarf<R>>> {
1047 let row = match self.tu_index.find(signature.0) {
1048 Some(row) => row,
1049 None => return Ok(None),
1050 };
1051 self.tu_sections(row, parent).map(Some)
1052 }
1053
1054 pub fn cu_sections(&self, index: u32, parent: &Dwarf<R>) -> Result<Dwarf<R>> {
1060 self.sections(self.cu_index.sections(index)?, parent)
1061 }
1062
1063 pub fn tu_sections(&self, index: u32, parent: &Dwarf<R>) -> Result<Dwarf<R>> {
1069 self.sections(self.tu_index.sections(index)?, parent)
1070 }
1071
1072 pub fn sections(
1076 &self,
1077 sections: UnitIndexSectionIterator<'_, R>,
1078 parent: &Dwarf<R>,
1079 ) -> Result<Dwarf<R>> {
1080 let mut abbrev_offset = 0;
1081 let mut abbrev_size = 0;
1082 let mut info_offset = 0;
1083 let mut info_size = 0;
1084 let mut line_offset = 0;
1085 let mut line_size = 0;
1086 let mut loc_offset = 0;
1087 let mut loc_size = 0;
1088 let mut loclists_offset = 0;
1089 let mut loclists_size = 0;
1090 let mut macinfo_offset = 0;
1091 let mut macinfo_size = 0;
1092 let mut macro_offset = 0;
1093 let mut macro_size = 0;
1094 let mut str_offsets_offset = 0;
1095 let mut str_offsets_size = 0;
1096 let mut rnglists_offset = 0;
1097 let mut rnglists_size = 0;
1098 let mut types_offset = 0;
1099 let mut types_size = 0;
1100 for section in sections {
1101 match section.section {
1102 IndexSectionId::DebugAbbrev => {
1103 abbrev_offset = section.offset;
1104 abbrev_size = section.size;
1105 }
1106 IndexSectionId::DebugInfo => {
1107 info_offset = section.offset;
1108 info_size = section.size;
1109 }
1110 IndexSectionId::DebugLine => {
1111 line_offset = section.offset;
1112 line_size = section.size;
1113 }
1114 IndexSectionId::DebugLoc => {
1115 loc_offset = section.offset;
1116 loc_size = section.size;
1117 }
1118 IndexSectionId::DebugLocLists => {
1119 loclists_offset = section.offset;
1120 loclists_size = section.size;
1121 }
1122 IndexSectionId::DebugMacinfo => {
1123 macinfo_offset = section.offset;
1124 macinfo_size = section.size;
1125 }
1126 IndexSectionId::DebugMacro => {
1127 macro_offset = section.offset;
1128 macro_size = section.size;
1129 }
1130 IndexSectionId::DebugStrOffsets => {
1131 str_offsets_offset = section.offset;
1132 str_offsets_size = section.size;
1133 }
1134 IndexSectionId::DebugRngLists => {
1135 rnglists_offset = section.offset;
1136 rnglists_size = section.size;
1137 }
1138 IndexSectionId::DebugTypes => {
1139 types_offset = section.offset;
1140 types_size = section.size;
1141 }
1142 }
1143 }
1144
1145 let debug_abbrev = self.debug_abbrev.dwp_range(abbrev_offset, abbrev_size)?;
1146 let debug_info = self.debug_info.dwp_range(info_offset, info_size)?;
1147 let debug_line = self.debug_line.dwp_range(line_offset, line_size)?;
1148 let debug_loc = self.debug_loc.dwp_range(loc_offset, loc_size)?;
1149 let debug_loclists = self
1150 .debug_loclists
1151 .dwp_range(loclists_offset, loclists_size)?;
1152 let debug_macinfo = self.debug_macinfo.dwp_range(macinfo_offset, macinfo_size)?;
1153 let debug_macro = self.debug_macro.dwp_range(macro_offset, macro_size)?;
1154 let debug_str_offsets = self
1155 .debug_str_offsets
1156 .dwp_range(str_offsets_offset, str_offsets_size)?;
1157 let debug_rnglists = self
1158 .debug_rnglists
1159 .dwp_range(rnglists_offset, rnglists_size)?;
1160 let debug_types = self.debug_types.dwp_range(types_offset, types_size)?;
1161
1162 let debug_str = self.debug_str.clone();
1163
1164 let debug_addr = parent.debug_addr.clone();
1165 let debug_ranges = parent.ranges.debug_ranges().clone();
1166
1167 let debug_aranges = self.empty.clone().into();
1168 let debug_line_str = self.empty.clone().into();
1169 let debug_names = self.empty.clone().into();
1170
1171 Ok(Dwarf {
1172 debug_abbrev,
1173 debug_addr,
1174 debug_aranges,
1175 debug_info,
1176 debug_line,
1177 debug_line_str,
1178 debug_macinfo,
1179 debug_macro,
1180 debug_names,
1181 debug_str,
1182 debug_str_offsets,
1183 debug_types,
1184 locations: LocationLists::new(debug_loc, debug_loclists),
1185 ranges: RangeLists::new(debug_ranges, debug_rnglists),
1186 file_type: DwarfFileType::Dwo,
1187 sup: parent.sup.clone(),
1188 abbreviations_cache: AbbreviationsCache::new(),
1189 })
1190 }
1191}
1192
1193#[derive(Debug)]
1196pub struct Unit<R, Offset = <R as Reader>::Offset>
1197where
1198 R: Reader<Offset = Offset>,
1199 Offset: ReaderOffset,
1200{
1201 pub header: UnitHeader<R, Offset>,
1203
1204 pub abbreviations: Arc<Abbreviations>,
1206
1207 pub name: Option<R>,
1209
1210 pub comp_dir: Option<R>,
1212
1213 pub low_pc: u64,
1215
1216 pub str_offsets_base: DebugStrOffsetsBase<Offset>,
1218
1219 pub addr_base: DebugAddrBase<Offset>,
1221
1222 pub loclists_base: DebugLocListsBase<Offset>,
1224
1225 pub rnglists_base: DebugRngListsBase<Offset>,
1227
1228 pub line_program: Option<IncompleteLineProgram<R, Offset>>,
1230
1231 pub dwo_id: Option<DwoId>,
1233}
1234
1235impl<R: Reader> core::ops::Deref for Unit<R> {
1236 type Target = UnitHeader<R>;
1237
1238 fn deref(&self) -> &Self::Target {
1239 &self.header
1240 }
1241}
1242
1243impl<R: Reader> Unit<R> {
1244 #[inline]
1246 pub fn new(dwarf: &Dwarf<R>, header: UnitHeader<R>) -> Result<Self> {
1247 let abbreviations = dwarf.abbreviations(&header)?;
1248 Self::new_with_abbreviations(dwarf, header, abbreviations)
1249 }
1250
1251 #[inline]
1257 pub fn new_with_abbreviations(
1258 dwarf: &Dwarf<R>,
1259 header: UnitHeader<R>,
1260 abbreviations: Arc<Abbreviations>,
1261 ) -> Result<Self> {
1262 let mut unit = Unit {
1263 abbreviations,
1264 name: None,
1265 comp_dir: None,
1266 low_pc: 0,
1267 str_offsets_base: DebugStrOffsetsBase::default_for_encoding_and_file(
1268 header.encoding(),
1269 dwarf.file_type,
1270 ),
1271 addr_base: DebugAddrBase(R::Offset::from_u8(0)),
1273 loclists_base: DebugLocListsBase::default_for_encoding_and_file(
1274 header.encoding(),
1275 dwarf.file_type,
1276 ),
1277 rnglists_base: DebugRngListsBase::default_for_encoding_and_file(
1278 header.encoding(),
1279 dwarf.file_type,
1280 ),
1281 line_program: None,
1282 dwo_id: match header.type_() {
1283 UnitType::Skeleton(dwo_id) | UnitType::SplitCompilation(dwo_id) => Some(dwo_id),
1284 _ => None,
1285 },
1286 header,
1287 };
1288 let mut name = None;
1289 let mut comp_dir = None;
1290 let mut line_program_offset = None;
1291 let mut low_pc_attr = None;
1292
1293 {
1294 let mut cursor = unit.header.entries(&unit.abbreviations);
1295 cursor.next_dfs()?;
1296 let root = cursor.current().ok_or(Error::MissingUnitDie)?;
1297 for attr in root.attrs() {
1298 match attr.name() {
1299 constants::DW_AT_name => {
1300 name = Some(attr.value());
1301 }
1302 constants::DW_AT_comp_dir => {
1303 comp_dir = Some(attr.value());
1304 }
1305 constants::DW_AT_low_pc => {
1306 low_pc_attr = Some(attr.value());
1307 }
1308 constants::DW_AT_stmt_list => {
1309 if let AttributeValue::DebugLineRef(offset) = attr.value() {
1310 line_program_offset = Some(offset);
1311 }
1312 }
1313 constants::DW_AT_str_offsets_base => {
1314 if let AttributeValue::DebugStrOffsetsBase(base) = attr.value() {
1315 unit.str_offsets_base = base;
1316 }
1317 }
1318 constants::DW_AT_addr_base | constants::DW_AT_GNU_addr_base => {
1319 if let AttributeValue::DebugAddrBase(base) = attr.value() {
1320 unit.addr_base = base;
1321 }
1322 }
1323 constants::DW_AT_loclists_base => {
1324 if let AttributeValue::DebugLocListsBase(base) = attr.value() {
1325 unit.loclists_base = base;
1326 }
1327 }
1328 constants::DW_AT_rnglists_base | constants::DW_AT_GNU_ranges_base => {
1329 if let AttributeValue::DebugRngListsBase(base) = attr.value() {
1330 unit.rnglists_base = base;
1331 }
1332 }
1333 constants::DW_AT_GNU_dwo_id => {
1334 if unit.dwo_id.is_none()
1335 && let AttributeValue::DwoId(dwo_id) = attr.value()
1336 {
1337 unit.dwo_id = Some(dwo_id);
1338 }
1339 }
1340 _ => {}
1341 }
1342 }
1343 }
1344
1345 unit.name = match name {
1346 Some(val) => dwarf.attr_string(&unit, val).ok(),
1347 None => None,
1348 };
1349 unit.comp_dir = match comp_dir {
1350 Some(val) => dwarf.attr_string(&unit, val).ok(),
1351 None => None,
1352 };
1353 unit.line_program = match line_program_offset {
1354 Some(offset) => Some(dwarf.debug_line.program(
1355 offset,
1356 unit.header.address_size(),
1357 unit.comp_dir.clone(),
1358 unit.name.clone(),
1359 )?),
1360 None => None,
1361 };
1362 if let Some(low_pc_attr) = low_pc_attr
1363 && let Some(addr) = dwarf.attr_address(&unit, low_pc_attr)?
1364 {
1365 unit.low_pc = addr;
1366 }
1367 Ok(unit)
1368 }
1369
1370 pub fn unit_ref<'a>(&'a self, dwarf: &'a Dwarf<R>) -> UnitRef<'a, R> {
1372 UnitRef::new(dwarf, self)
1373 }
1374
1375 #[inline]
1377 pub fn encoding(&self) -> Encoding {
1378 self.header.encoding()
1379 }
1380
1381 pub fn entry(&self, offset: UnitOffset<R::Offset>) -> Result<DebuggingInformationEntry<R>> {
1383 self.header.entry(&self.abbreviations, offset)
1384 }
1385
1386 #[inline]
1388 pub fn entries(&self) -> EntriesCursor<'_, R> {
1389 self.header.entries(&self.abbreviations)
1390 }
1391
1392 #[inline]
1395 pub fn entries_at_offset(&self, offset: UnitOffset<R::Offset>) -> Result<EntriesCursor<'_, R>> {
1396 self.header.entries_at_offset(&self.abbreviations, offset)
1397 }
1398
1399 #[inline]
1402 pub fn entries_tree(
1403 &self,
1404 offset: Option<UnitOffset<R::Offset>>,
1405 ) -> Result<EntriesTree<'_, R>> {
1406 self.header.entries_tree(&self.abbreviations, offset)
1407 }
1408
1409 #[inline]
1411 pub fn entries_raw(&self, offset: Option<UnitOffset<R::Offset>>) -> Result<EntriesRaw<'_, R>> {
1412 self.header.entries_raw(&self.abbreviations, offset)
1413 }
1414
1415 pub fn copy_relocated_attributes(&mut self, other: &Unit<R>) {
1419 self.low_pc = other.low_pc;
1420 self.addr_base = other.addr_base;
1421 if self.header.version() < 5 {
1422 self.rnglists_base = other.rnglists_base;
1423 }
1424 }
1425
1426 pub fn dwo_name(&self) -> Result<Option<AttributeValue<R>>> {
1432 let mut entries = self.entries();
1433 entries.next_entry()?;
1434 let entry = entries.current().ok_or(Error::MissingUnitDie)?;
1435 if self.header.version() < 5 {
1436 Ok(entry.attr_value(constants::DW_AT_GNU_dwo_name))
1437 } else {
1438 Ok(entry.attr_value(constants::DW_AT_dwo_name))
1439 }
1440 }
1441}
1442
1443#[derive(Debug)]
1450pub struct UnitRef<'a, R: Reader> {
1451 pub dwarf: &'a Dwarf<R>,
1453
1454 pub unit: &'a Unit<R>,
1456}
1457
1458impl<'a, R: Reader> Clone for UnitRef<'a, R> {
1459 fn clone(&self) -> Self {
1460 *self
1461 }
1462}
1463
1464impl<'a, R: Reader> Copy for UnitRef<'a, R> {}
1465
1466impl<'a, R: Reader> core::ops::Deref for UnitRef<'a, R> {
1467 type Target = &'a Unit<R>;
1468
1469 fn deref(&self) -> &Self::Target {
1470 &self.unit
1471 }
1472}
1473
1474impl<'a, R: Reader> UnitRef<'a, R> {
1475 pub fn new(dwarf: &'a Dwarf<R>, unit: &'a Unit<R>) -> Self {
1477 UnitRef { dwarf, unit }
1478 }
1479
1480 #[inline]
1482 pub fn string_offset(
1483 &self,
1484 index: DebugStrOffsetsIndex<R::Offset>,
1485 ) -> Result<DebugStrOffset<R::Offset>> {
1486 self.dwarf.string_offset(self.unit, index)
1487 }
1488
1489 #[inline]
1491 pub fn string(&self, offset: DebugStrOffset<R::Offset>) -> Result<R> {
1492 self.dwarf.string(offset)
1493 }
1494
1495 #[inline]
1497 pub fn line_string(&self, offset: DebugLineStrOffset<R::Offset>) -> Result<R> {
1498 self.dwarf.line_string(offset)
1499 }
1500
1501 #[inline]
1504 pub fn sup_string(&self, offset: DebugStrOffset<R::Offset>) -> Result<R> {
1505 self.dwarf.sup_string(offset)
1506 }
1507
1508 pub fn attr_string(&self, attr: AttributeValue<R>) -> Result<R> {
1512 self.dwarf.attr_string(self.unit, attr)
1513 }
1514
1515 pub fn address(&self, index: DebugAddrIndex<R::Offset>) -> Result<u64> {
1517 self.dwarf.address(self.unit, index)
1518 }
1519
1520 pub fn attr_address(&self, attr: AttributeValue<R>) -> Result<Option<u64>> {
1524 self.dwarf.attr_address(self.unit, attr)
1525 }
1526
1527 pub fn ranges_offset_from_raw(
1531 &self,
1532 offset: RawRangeListsOffset<R::Offset>,
1533 ) -> RangeListsOffset<R::Offset> {
1534 self.dwarf.ranges_offset_from_raw(self.unit, offset)
1535 }
1536
1537 pub fn ranges_offset(
1539 &self,
1540 index: DebugRngListsIndex<R::Offset>,
1541 ) -> Result<RangeListsOffset<R::Offset>> {
1542 self.dwarf.ranges_offset(self.unit, index)
1543 }
1544
1545 pub fn ranges(&self, offset: RangeListsOffset<R::Offset>) -> Result<RngListIter<R>> {
1547 self.dwarf.ranges(self.unit, offset)
1548 }
1549
1550 pub fn raw_ranges(&self, offset: RangeListsOffset<R::Offset>) -> Result<RawRngListIter<R>> {
1552 self.dwarf.raw_ranges(self.unit, offset)
1553 }
1554
1555 pub fn attr_ranges_offset(
1559 &self,
1560 attr: AttributeValue<R>,
1561 ) -> Result<Option<RangeListsOffset<R::Offset>>> {
1562 self.dwarf.attr_ranges_offset(self.unit, attr)
1563 }
1564
1565 pub fn attr_ranges(&self, attr: AttributeValue<R>) -> Result<Option<RngListIter<R>>> {
1569 self.dwarf.attr_ranges(self.unit, attr)
1570 }
1571
1572 pub fn die_ranges(&self, entry: &DebuggingInformationEntry<R>) -> Result<RangeIter<R>> {
1576 self.dwarf.die_ranges(self.unit, entry)
1577 }
1578
1579 pub fn unit_ranges(&self) -> Result<RangeIter<R>> {
1584 self.dwarf.unit_ranges(self.unit)
1585 }
1586
1587 pub fn locations_offset(
1589 &self,
1590 index: DebugLocListsIndex<R::Offset>,
1591 ) -> Result<LocationListsOffset<R::Offset>> {
1592 self.dwarf.locations_offset(self.unit, index)
1593 }
1594
1595 pub fn locations(&self, offset: LocationListsOffset<R::Offset>) -> Result<LocListIter<R>> {
1597 self.dwarf.locations(self.unit, offset)
1598 }
1599
1600 pub fn raw_locations(
1602 &self,
1603 offset: LocationListsOffset<R::Offset>,
1604 ) -> Result<RawLocListIter<R>> {
1605 self.dwarf.raw_locations(self.unit, offset)
1606 }
1607
1608 pub fn attr_locations_offset(
1612 &self,
1613 attr: AttributeValue<R>,
1614 ) -> Result<Option<LocationListsOffset<R::Offset>>> {
1615 self.dwarf.attr_locations_offset(self.unit, attr)
1616 }
1617
1618 pub fn attr_locations(&self, attr: AttributeValue<R>) -> Result<Option<LocListIter<R>>> {
1622 self.dwarf.attr_locations(self.unit, attr)
1623 }
1624
1625 pub fn macinfo(&self, offset: DebugMacinfoOffset<R::Offset>) -> Result<MacroIter<R>> {
1627 self.dwarf.macinfo(offset)
1628 }
1629
1630 pub fn macros(&self, offset: DebugMacroOffset<R::Offset>) -> Result<MacroIter<R>> {
1632 self.dwarf.macros(offset)
1633 }
1634}
1635
1636#[derive(Debug)]
1640pub struct RangeIter<R: Reader>(RangeIterInner<R>);
1641
1642#[derive(Debug)]
1643enum RangeIterInner<R: Reader> {
1644 Single(Option<Range>),
1645 List(RngListIter<R>),
1646}
1647
1648impl<R: Reader> Default for RangeIter<R> {
1649 fn default() -> Self {
1650 RangeIter(RangeIterInner::Single(None))
1651 }
1652}
1653
1654impl<R: Reader> RangeIter<R> {
1655 pub fn next(&mut self) -> Result<Option<Range>> {
1657 match self.0 {
1658 RangeIterInner::Single(ref mut range) => Ok(range.take()),
1659 RangeIterInner::List(ref mut list) => list.next(),
1660 }
1661 }
1662}
1663
1664#[cfg(feature = "fallible-iterator")]
1665impl<R: Reader> fallible_iterator::FallibleIterator for RangeIter<R> {
1666 type Item = Range;
1667 type Error = Error;
1668
1669 #[inline]
1670 fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
1671 RangeIter::next(self)
1672 }
1673}
1674
1675impl<R: Reader> Iterator for RangeIter<R> {
1676 type Item = Result<Range>;
1677
1678 #[inline]
1679 fn next(&mut self) -> Option<Self::Item> {
1680 RangeIter::next(self).transpose()
1681 }
1682}
1683
1684#[cfg(test)]
1685mod tests {
1686 use super::*;
1687 use crate::read::EndianSlice;
1688 use crate::{Endianity, LittleEndian};
1689
1690 #[test]
1692 fn test_dwarf_variance() {
1693 fn _f<'a: 'b, 'b, E: Endianity>(x: Dwarf<EndianSlice<'a, E>>) -> Dwarf<EndianSlice<'b, E>> {
1695 x
1696 }
1697 }
1698
1699 #[test]
1701 fn test_dwarf_unit_variance() {
1702 fn _f<'a: 'b, 'b, E: Endianity>(x: Unit<EndianSlice<'a, E>>) -> Unit<EndianSlice<'b, E>> {
1704 x
1705 }
1706 }
1707
1708 #[test]
1709 fn test_send() {
1710 fn assert_is_send<T: Send>() {}
1711 assert_is_send::<Dwarf<EndianSlice<'_, LittleEndian>>>();
1712 assert_is_send::<Unit<EndianSlice<'_, LittleEndian>>>();
1713 }
1714
1715 #[test]
1716 fn test_format_error() {
1717 let dwarf_sections = DwarfSections::load(|_| -> Result<_> { Ok(vec![1, 2]) }).unwrap();
1718 let sup_sections = DwarfSections::load(|_| -> Result<_> { Ok(vec![1, 2]) }).unwrap();
1719 let dwarf = dwarf_sections.borrow_with_sup(Some(&sup_sections), |section| {
1720 EndianSlice::new(section, LittleEndian)
1721 });
1722
1723 match dwarf.debug_str.get_str(DebugStrOffset(1)) {
1724 Ok(r) => panic!("Unexpected str {:?}", r),
1725 Err(e) => {
1726 assert_eq!(
1727 dwarf.format_error(e),
1728 "unexpected end of input at .debug_str+0x1"
1729 );
1730 }
1731 }
1732 match dwarf.sup().unwrap().debug_str.get_str(DebugStrOffset(1)) {
1733 Ok(r) => panic!("Unexpected str {:?}", r),
1734 Err(e) => {
1735 assert_eq!(
1736 dwarf.format_error(e),
1737 "unexpected end of input at .debug_str(sup)+0x1"
1738 );
1739 }
1740 }
1741 assert_eq!(dwarf.format_error(Error::Io), format!("{}", Error::Io));
1742 }
1743}