1use alloc::vec::Vec;
2use core::ops::{Deref, DerefMut};
3use core::slice;
4
5use crate::common::{
6 DebugAbbrevOffset, DebugInfoOffset, DebugLineOffset, DebugMacinfoOffset, DebugMacroOffset,
7 DebugStrOffset, DebugTypeSignature, Encoding, Format, SectionId,
8};
9use crate::constants;
10use crate::leb128::write::{sleb128_size, uleb128_size};
11use crate::write::{
12 Abbreviation, AbbreviationTable, Address, AttributeSpecification, BaseId, Error, Expression,
13 FileId, LineProgram, LineStringId, LineStringTable, LocationListId, LocationListOffsets,
14 LocationListTable, RangeListId, RangeListOffsets, RangeListTable, Result, Section, Sections,
15 StringId, StringTable, Writer,
16};
17
18define_id!(UnitId, "An identifier for a unit in a `UnitTable`.");
19
20define_id!(UnitEntryId, "An identifier for an entry in a `Unit`.");
21
22#[derive(Debug, Default)]
24pub struct UnitTable {
25 base_id: BaseId,
26 units: Vec<Unit>,
27}
28
29impl UnitTable {
30 #[inline]
36 pub fn add(&mut self, unit: Unit) -> UnitId {
37 let id = UnitId::new(self.base_id, self.units.len());
38 self.units.push(unit);
39 id
40 }
41
42 #[inline]
44 pub fn count(&self) -> usize {
45 self.units.len()
46 }
47
48 #[inline]
54 pub fn id(&self, index: usize) -> UnitId {
55 assert!(index < self.count());
56 UnitId::new(self.base_id, index)
57 }
58
59 #[inline]
65 pub fn get(&self, id: UnitId) -> &Unit {
66 debug_assert_eq!(self.base_id, id.base_id);
67 &self.units[id.index]
68 }
69
70 #[inline]
76 pub fn get_mut(&mut self, id: UnitId) -> &mut Unit {
77 debug_assert_eq!(self.base_id, id.base_id);
78 &mut self.units[id.index]
79 }
80
81 pub fn iter(&self) -> impl Iterator<Item = (UnitId, &Unit)> {
83 self.units
84 .iter()
85 .enumerate()
86 .map(move |(index, unit)| (UnitId::new(self.base_id, index), unit))
87 }
88
89 pub fn iter_mut(&mut self) -> impl Iterator<Item = (UnitId, &mut Unit)> {
91 let base_id = self.base_id;
92 self.units
93 .iter_mut()
94 .enumerate()
95 .map(move |(index, unit)| (UnitId::new(base_id, index), unit))
96 }
97
98 pub fn write<W: Writer>(
100 &mut self,
101 sections: &mut Sections<W>,
102 line_strings: &mut LineStringTable,
103 strings: &mut StringTable,
104 ) -> Result<()> {
105 for unit in &mut self.units {
106 if unit.written {
107 continue;
108 }
109
110 let abbrev_offset = sections.debug_abbrev.offset();
112 let mut abbrevs = AbbreviationTable::default();
113
114 unit.write(sections, abbrev_offset, &mut abbrevs, line_strings, strings)?;
115
116 abbrevs.write(&mut sections.debug_abbrev)?;
117 }
118
119 self.write_debug_info_fixups(&mut sections.debug_info_fixups, &mut sections.debug_info.0)?;
120 self.write_debug_info_fixups(&mut sections.debug_loc_fixups, &mut sections.debug_loc.0)?;
121 self.write_debug_info_fixups(
122 &mut sections.debug_loclists_fixups,
123 &mut sections.debug_loclists.0,
124 )?;
125
126 Ok(())
127 }
128
129 fn write_debug_info_fixups<W: Writer>(
130 &self,
131 fixups: &mut Vec<DebugInfoFixup>,
132 w: &mut W,
133 ) -> Result<()> {
134 for fixup in fixups.drain(..) {
135 debug_assert_eq!(self.base_id, fixup.unit.base_id);
136 let entry_offset = self.units[fixup.unit.index]
137 .offsets
138 .debug_info_offset(fixup.entry)
139 .ok_or(Error::InvalidReference)?
140 .0;
141 w.write_offset_at(fixup.offset, entry_offset, SectionId::DebugInfo, fixup.size)?;
142 }
143 Ok(())
144 }
145}
146
147#[derive(Debug)]
149pub struct Unit {
150 base_id: BaseId,
151 encoding: Encoding,
153 pub line_program: LineProgram,
155 pub ranges: RangeListTable,
157 pub locations: LocationListTable,
159 entries: Vec<DebuggingInformationEntry>,
168 reserved: usize,
172 root: UnitEntryId,
174 written: bool,
176 offsets: UnitOffsets,
178}
179
180impl Unit {
181 pub fn new(encoding: Encoding, line_program: LineProgram) -> Self {
183 let base_id = BaseId::default();
184 let ranges = RangeListTable::default();
185 let locations = LocationListTable::default();
186 let root = UnitEntryId::new(base_id, 0);
187 let mut entry = DebuggingInformationEntry::new_reserved(root);
188 entry.tag = constants::DW_TAG_compile_unit;
189 let entries = vec![entry];
190 let offsets = UnitOffsets {
191 base_id,
192 unit: DebugInfoOffset(!0),
193 entries: Vec::new(),
194 };
195 Unit {
196 base_id,
197 encoding,
198 line_program,
199 ranges,
200 locations,
201 entries,
202 reserved: 1,
203 root,
204 written: false,
205 offsets,
206 }
207 }
208
209 #[inline]
211 pub fn set_encoding(&mut self, encoding: Encoding) {
212 self.encoding = encoding;
213 }
214
215 #[inline]
217 pub fn encoding(&self) -> Encoding {
218 self.encoding
219 }
220
221 #[inline]
223 pub fn version(&self) -> u16 {
224 self.encoding.version
225 }
226
227 #[inline]
229 pub fn address_size(&self) -> u8 {
230 self.encoding.address_size
231 }
232
233 #[inline]
235 pub fn format(&self) -> Format {
236 self.encoding.format
237 }
238
239 #[inline]
243 pub fn count(&self) -> usize {
244 self.entries.len()
245 }
246
247 #[inline]
249 pub fn root(&self) -> UnitEntryId {
250 self.root
251 }
252
253 pub fn reserve(&mut self) -> UnitEntryId {
264 let id = UnitEntryId::new(self.base_id, self.reserved);
265 self.reserved += 1;
266 id
267 }
268
269 pub fn add_reserved(&mut self, child: UnitEntryId, parent: UnitEntryId, tag: constants::DwTag) {
277 while self.entries.len() < self.reserved {
278 let id = UnitEntryId::new(self.base_id, self.entries.len());
279 self.entries
280 .push(DebuggingInformationEntry::new_reserved(id));
281 }
282 let entry = self.get_mut(child);
283 debug_assert_eq!(entry.parent, None);
284 debug_assert_eq!(entry.tag, constants::DW_TAG_null);
285 entry.parent = Some(parent);
286 entry.tag = tag;
287 self.get_mut(parent).children.push(child);
288 }
289
290 #[inline]
298 pub fn add(&mut self, parent: UnitEntryId, tag: constants::DwTag) -> UnitEntryId {
299 let id = self.reserve();
300 self.add_reserved(id, parent, tag);
301 id
302 }
303
304 #[inline]
310 pub fn get(&self, id: UnitEntryId) -> &DebuggingInformationEntry {
311 debug_assert_eq!(self.base_id, id.base_id);
312 &self.entries[id.index]
313 }
314
315 #[inline]
321 pub fn get_mut(&mut self, id: UnitEntryId) -> &mut DebuggingInformationEntry {
322 debug_assert_eq!(self.base_id, id.base_id);
323 &mut self.entries[id.index]
324 }
325
326 fn line_program_in_use(&self) -> bool {
328 if self.line_program.is_none() {
329 return false;
330 }
331 if !self.line_program.is_empty() {
332 return true;
333 }
334
335 for entry in &self.entries {
336 for attr in &entry.attrs {
337 if let AttributeValue::FileIndex(Some(_)) = attr.value {
338 return true;
339 }
340 }
341 }
342
343 false
344 }
345
346 pub(crate) fn write<W: Writer>(
348 &mut self,
349 sections: &mut Sections<W>,
350 abbrev_offset: DebugAbbrevOffset,
351 abbrevs: &mut AbbreviationTable,
352 line_strings: &mut LineStringTable,
353 strings: &mut StringTable,
354 ) -> Result<()> {
355 debug_assert!(!self.written);
356
357 let line_program = if self.line_program_in_use() {
358 self.entries[self.root.index]
359 .set(constants::DW_AT_stmt_list, AttributeValue::LineProgramRef);
360 Some(self.line_program.write(
361 &mut sections.debug_line,
362 self.encoding,
363 line_strings,
364 strings,
365 )?)
366 } else {
367 self.entries[self.root.index].delete(constants::DW_AT_stmt_list);
368 None
369 };
370
371 let w = &mut sections.debug_info;
373
374 let mut offsets = UnitOffsets {
375 base_id: self.base_id,
376 unit: w.offset(),
377 entries: vec![DebugInfoOffset(0); self.entries.len()],
379 };
380
381 let length_offset = w.write_initial_length(self.format())?;
382 let length_base = w.len();
383
384 w.write_u16(self.version())?;
385 if 2 <= self.version() && self.version() <= 4 {
386 w.write_offset(
387 abbrev_offset.0,
388 SectionId::DebugAbbrev,
389 self.format().word_size(),
390 )?;
391 w.write_u8(self.address_size())?;
392 } else if self.version() == 5 {
393 w.write_u8(constants::DW_UT_compile.0)?;
394 w.write_u8(self.address_size())?;
395 w.write_offset(
396 abbrev_offset.0,
397 SectionId::DebugAbbrev,
398 self.format().word_size(),
399 )?;
400 } else {
401 return Err(Error::UnsupportedVersion(self.version()));
402 }
403
404 self.reorder_base_types();
408 let mut codes = vec![0; self.entries.len()];
409 let mut offset = w.len();
410 self.entries[self.root.index].calculate_offsets(
411 self,
412 &mut offset,
413 &mut offsets,
414 abbrevs,
415 &mut codes,
416 )?;
417
418 let range_lists = self.ranges.write(sections, self.encoding)?;
419 let loc_lists = self
421 .locations
422 .write(sections, self.encoding, Some(&offsets))?;
423
424 let w = &mut sections.debug_info;
425 let mut unit_refs = Vec::new();
426 self.entries[self.root.index].write(
427 w,
428 &mut sections.debug_info_fixups,
429 &mut unit_refs,
430 self,
431 &offsets,
432 &codes,
433 line_program,
434 line_strings,
435 strings,
436 &range_lists,
437 &loc_lists,
438 )?;
439
440 let length = (w.len() - length_base) as u64;
441 w.write_initial_length_at(length_offset, length, self.format())?;
442
443 for (offset, entry) in unit_refs {
444 w.write_udata_at(
446 offset.0,
447 offsets.unit_offset(entry).ok_or(Error::InvalidReference)?,
448 self.format().word_size(),
449 )?;
450 }
451
452 self.offsets = offsets;
453 self.written = true;
454 Ok(())
455 }
456
457 fn skip(&mut self) {
458 self.written = true;
459 }
460
461 fn free(&mut self) {
462 self.line_program = LineProgram::none();
463 self.ranges = RangeListTable::default();
464 self.locations = LocationListTable::default();
465 self.entries = Vec::new();
466 }
467
468 fn reorder_base_types(&mut self) {
471 let root = &self.entries[self.root.index];
472 let mut root_children = Vec::with_capacity(root.children.len());
473 for entry in &root.children {
474 if self.entries[entry.index].tag == constants::DW_TAG_base_type {
475 root_children.push(*entry);
476 }
477 }
478 for entry in &root.children {
479 if self.entries[entry.index].tag != constants::DW_TAG_base_type {
480 root_children.push(*entry);
481 }
482 }
483 self.entries[self.root.index].children = root_children;
484 }
485}
486
487#[derive(Debug)]
494pub struct DebuggingInformationEntry {
495 id: UnitEntryId,
496 parent: Option<UnitEntryId>,
497 tag: constants::DwTag,
498 sibling: bool,
500 attrs: Vec<Attribute>,
501 children: Vec<UnitEntryId>,
502}
503
504impl DebuggingInformationEntry {
505 fn new_reserved(id: UnitEntryId) -> Self {
507 DebuggingInformationEntry {
508 id,
509 parent: None,
510 tag: constants::DW_TAG_null,
511 sibling: false,
512 attrs: Vec::new(),
513 children: Vec::new(),
514 }
515 }
516
517 #[inline]
519 pub fn id(&self) -> UnitEntryId {
520 self.id
521 }
522
523 #[inline]
525 pub fn parent(&self) -> Option<UnitEntryId> {
526 self.parent
527 }
528
529 #[inline]
531 pub fn tag(&self) -> constants::DwTag {
532 self.tag
533 }
534
535 #[inline]
537 pub fn sibling(&self) -> bool {
538 self.sibling
539 }
540
541 #[inline]
545 pub fn set_sibling(&mut self, sibling: bool) {
546 self.sibling = sibling;
547 }
548
549 #[inline]
551 pub fn attrs(&self) -> slice::Iter<'_, Attribute> {
552 self.attrs.iter()
553 }
554
555 #[inline]
557 pub fn attrs_mut(&mut self) -> slice::IterMut<'_, Attribute> {
558 self.attrs.iter_mut()
559 }
560
561 pub fn get(&self, name: constants::DwAt) -> Option<&AttributeValue> {
563 self.attrs
564 .iter()
565 .find(|attr| attr.name == name)
566 .map(|attr| &attr.value)
567 }
568
569 pub fn get_mut(&mut self, name: constants::DwAt) -> Option<&mut AttributeValue> {
571 self.attrs
572 .iter_mut()
573 .find(|attr| attr.name == name)
574 .map(|attr| &mut attr.value)
575 }
576
577 pub fn reserve(&mut self, additional: usize) {
582 self.attrs.reserve(additional);
583 }
584
585 pub fn set(&mut self, name: constants::DwAt, value: AttributeValue) {
593 debug_assert_ne!(name, constants::DW_AT_sibling);
594 if let Some(attr) = self.attrs.iter_mut().find(|attr| attr.name == name) {
595 attr.value = value;
596 return;
597 }
598 self.attrs.push(Attribute { name, value });
599 }
600
601 pub fn delete(&mut self, name: constants::DwAt) {
603 self.attrs.retain(|x| x.name != name);
604 }
605
606 #[inline]
610 pub fn children(&self) -> slice::Iter<'_, UnitEntryId> {
611 self.children.iter()
612 }
613
614 pub fn delete_child(&mut self, id: UnitEntryId) {
616 self.children.retain(|&child| child != id);
617 }
618
619 fn abbreviation(&self, encoding: Encoding) -> Result<Abbreviation> {
621 let sibling = self.sibling && !self.children.is_empty();
622 let mut attrs = Vec::with_capacity(usize::from(sibling) + self.attrs.len());
623
624 if sibling {
625 let form = match encoding.format {
626 Format::Dwarf32 => constants::DW_FORM_ref4,
627 Format::Dwarf64 => constants::DW_FORM_ref8,
628 };
629 attrs.push(AttributeSpecification::new(
630 constants::DW_AT_sibling,
631 form,
632 None,
633 ));
634 }
635
636 for attr in &self.attrs {
637 attrs.push(attr.specification(encoding)?);
638 }
639
640 Ok(Abbreviation::new(
641 self.tag,
642 !self.children.is_empty(),
643 attrs,
644 ))
645 }
646
647 fn calculate_offsets(
648 &self,
649 unit: &Unit,
650 offset: &mut usize,
651 offsets: &mut UnitOffsets,
652 abbrevs: &mut AbbreviationTable,
653 codes: &mut [u64],
654 ) -> Result<()> {
655 offsets.entries[self.id.index] = DebugInfoOffset(*offset);
656 let code = abbrevs.add(self.abbreviation(unit.encoding())?);
657 codes[self.id.index] = code;
658 *offset += self.size(unit, offsets, code)?;
659 if !self.children.is_empty() {
660 for child in &self.children {
661 unit.entries[child.index]
662 .calculate_offsets(unit, offset, offsets, abbrevs, codes)?;
663 }
664 *offset += 1;
666 }
667 Ok(())
668 }
669
670 fn size(&self, unit: &Unit, offsets: &UnitOffsets, code: u64) -> Result<usize> {
671 let mut size = uleb128_size(code);
672 if self.sibling && !self.children.is_empty() {
673 size += unit.format().word_size() as usize;
674 }
675 for attr in &self.attrs {
676 size += attr.value.size(unit, offsets)?;
677 }
678 Ok(size)
679 }
680
681 fn write<W: Writer>(
683 &self,
684 w: &mut DebugInfo<W>,
685 debug_info_refs: &mut Vec<DebugInfoFixup>,
686 unit_refs: &mut Vec<(DebugInfoOffset, UnitEntryId)>,
687 unit: &Unit,
688 offsets: &UnitOffsets,
689 codes: &[u64],
690 line_program: Option<DebugLineOffset>,
691 line_strings: &LineStringTable,
692 strings: &StringTable,
693 range_lists: &RangeListOffsets,
694 loc_lists: &LocationListOffsets,
695 ) -> Result<()> {
696 debug_assert_eq!(offsets.debug_info_offset(self.id), Some(w.offset()));
697 w.write_uleb128(codes[self.id.index])?;
698
699 let sibling_offset = if self.sibling && !self.children.is_empty() {
700 let offset = w.offset();
701 w.write_udata(0, unit.format().word_size())?;
702 Some(offset)
703 } else {
704 None
705 };
706
707 for attr in &self.attrs {
708 attr.value.write(
709 w,
710 debug_info_refs,
711 unit_refs,
712 unit,
713 offsets,
714 line_program,
715 line_strings,
716 strings,
717 range_lists,
718 loc_lists,
719 )?;
720 }
721
722 if !self.children.is_empty() {
723 for child in &self.children {
724 unit.entries[child.index].write(
725 w,
726 debug_info_refs,
727 unit_refs,
728 unit,
729 offsets,
730 codes,
731 line_program,
732 line_strings,
733 strings,
734 range_lists,
735 loc_lists,
736 )?;
737 }
738 w.write_u8(0)?;
740 }
741
742 if let Some(offset) = sibling_offset {
743 let next_offset = (w.offset().0 - offsets.unit.0) as u64;
744 w.write_udata_at(offset.0, next_offset, unit.format().word_size())?;
746 }
747 Ok(())
748 }
749}
750
751#[derive(Debug, Clone, PartialEq, Eq)]
754pub struct Attribute {
755 name: constants::DwAt,
756 value: AttributeValue,
757}
758
759impl Attribute {
760 #[inline]
762 pub fn name(&self) -> constants::DwAt {
763 self.name
764 }
765
766 #[inline]
768 pub fn get(&self) -> &AttributeValue {
769 &self.value
770 }
771
772 #[inline]
774 pub fn set(&mut self, value: AttributeValue) {
775 self.value = value;
776 }
777
778 fn specification(&self, encoding: Encoding) -> Result<AttributeSpecification> {
780 let (form, implicit_const) = self.value.form(encoding)?;
781 Ok(AttributeSpecification::new(self.name, form, implicit_const))
782 }
783}
784
785#[derive(Debug, Clone, PartialEq, Eq)]
787pub enum AttributeValue {
788 Address(Address),
790
791 Block(Vec<u8>),
793
794 Data1(u8),
800
801 Data2(u16),
809
810 Data4(u32),
818
819 Data8(u64),
827
828 Data16(u128),
836
837 Sdata(i64),
839
840 Udata(u64),
842
843 ImplicitConst(i64),
854
855 Exprloc(Expression),
860
861 Flag(bool),
863
864 FlagPresent,
868
869 UnitRef(UnitEntryId),
871
872 DebugInfoRef(DebugInfoRef),
874
875 DebugInfoRefSup(DebugInfoOffset),
881
882 LineProgramRef,
884
885 LocationListRef(LocationListId),
887
888 DebugMacinfoRef(DebugMacinfoOffset),
894
895 DebugMacroRef(DebugMacroOffset),
901
902 RangeListRef(RangeListId),
904
905 DebugTypesRef(DebugTypeSignature),
911
912 StringRef(StringId),
914
915 DebugStrRefSup(DebugStrOffset),
921
922 LineStringRef(LineStringId),
924
925 String(Vec<u8>),
928
929 Encoding(constants::DwAte),
931
932 DecimalSign(constants::DwDs),
934
935 Endianity(constants::DwEnd),
937
938 Accessibility(constants::DwAccess),
940
941 Visibility(constants::DwVis),
943
944 Virtuality(constants::DwVirtuality),
946
947 Language(constants::DwLang),
949
950 AddressClass(constants::DwAddr),
952
953 IdentifierCase(constants::DwId),
955
956 CallingConvention(constants::DwCc),
958
959 Inline(constants::DwInl),
961
962 Ordering(constants::DwOrd),
964
965 FileIndex(Option<FileId>),
968}
969
970impl AttributeValue {
971 pub fn form(&self, encoding: Encoding) -> Result<(constants::DwForm, Option<i64>)> {
973 let form = match *self {
982 AttributeValue::Address(_) => constants::DW_FORM_addr,
983 AttributeValue::Block(_) => constants::DW_FORM_block,
984 AttributeValue::Data1(_) => constants::DW_FORM_data1,
985 AttributeValue::Data2(_) => constants::DW_FORM_data2,
986 AttributeValue::Data4(_) => constants::DW_FORM_data4,
987 AttributeValue::Data8(_) => constants::DW_FORM_data8,
988 AttributeValue::Data16(_) => constants::DW_FORM_data16,
989 AttributeValue::Exprloc(_) => {
990 if encoding.version >= 4 {
991 constants::DW_FORM_exprloc
992 } else {
993 constants::DW_FORM_block
994 }
995 }
996 AttributeValue::Flag(_) => constants::DW_FORM_flag,
997 AttributeValue::FlagPresent => {
998 if encoding.version >= 4 {
999 constants::DW_FORM_flag_present
1000 } else {
1001 constants::DW_FORM_flag
1002 }
1003 }
1004 AttributeValue::UnitRef(_) => {
1005 match encoding.format {
1008 Format::Dwarf32 => constants::DW_FORM_ref4,
1009 Format::Dwarf64 => constants::DW_FORM_ref8,
1010 }
1011 }
1012 AttributeValue::DebugInfoRef(_) => constants::DW_FORM_ref_addr,
1013 AttributeValue::DebugInfoRefSup(_) => {
1014 match encoding.format {
1016 Format::Dwarf32 => constants::DW_FORM_ref_sup4,
1017 Format::Dwarf64 => constants::DW_FORM_ref_sup8,
1018 }
1019 }
1020 AttributeValue::LineProgramRef
1021 | AttributeValue::LocationListRef(_)
1022 | AttributeValue::DebugMacinfoRef(_)
1023 | AttributeValue::DebugMacroRef(_)
1024 | AttributeValue::RangeListRef(_) => {
1025 if encoding.version == 2 || encoding.version == 3 {
1026 match encoding.format {
1027 Format::Dwarf32 => constants::DW_FORM_data4,
1028 Format::Dwarf64 => constants::DW_FORM_data8,
1029 }
1030 } else {
1031 constants::DW_FORM_sec_offset
1032 }
1033 }
1034 AttributeValue::DebugTypesRef(_) => constants::DW_FORM_ref_sig8,
1035 AttributeValue::StringRef(_) => constants::DW_FORM_strp,
1036 AttributeValue::DebugStrRefSup(_) => constants::DW_FORM_strp_sup,
1037 AttributeValue::LineStringRef(_) => constants::DW_FORM_line_strp,
1038 AttributeValue::String(_) => constants::DW_FORM_string,
1039 AttributeValue::Encoding(_)
1040 | AttributeValue::DecimalSign(_)
1041 | AttributeValue::Endianity(_)
1042 | AttributeValue::Accessibility(_)
1043 | AttributeValue::Visibility(_)
1044 | AttributeValue::Virtuality(_)
1045 | AttributeValue::Language(_)
1046 | AttributeValue::AddressClass(_)
1047 | AttributeValue::IdentifierCase(_)
1048 | AttributeValue::CallingConvention(_)
1049 | AttributeValue::Inline(_)
1050 | AttributeValue::Ordering(_)
1051 | AttributeValue::FileIndex(_)
1052 | AttributeValue::Udata(_) => constants::DW_FORM_udata,
1053 AttributeValue::Sdata(_) => constants::DW_FORM_sdata,
1054 AttributeValue::ImplicitConst(val) => {
1055 if encoding.version >= 5 {
1056 return Ok((constants::DW_FORM_implicit_const, Some(val)));
1057 } else {
1058 constants::DW_FORM_sdata
1059 }
1060 }
1061 };
1062 Ok((form, None))
1063 }
1064
1065 fn size(&self, unit: &Unit, offsets: &UnitOffsets) -> Result<usize> {
1066 macro_rules! debug_assert_form {
1067 ($form:expr) => {
1068 debug_assert_eq!(self.form(unit.encoding()).unwrap().0, $form)
1069 };
1070 }
1071 Ok(match *self {
1072 AttributeValue::Address(_) => {
1073 debug_assert_form!(constants::DW_FORM_addr);
1074 unit.address_size() as usize
1075 }
1076 AttributeValue::Block(ref val) => {
1077 debug_assert_form!(constants::DW_FORM_block);
1078 uleb128_size(val.len() as u64) + val.len()
1079 }
1080 AttributeValue::Data1(_) => {
1081 debug_assert_form!(constants::DW_FORM_data1);
1082 1
1083 }
1084 AttributeValue::Data2(_) => {
1085 debug_assert_form!(constants::DW_FORM_data2);
1086 2
1087 }
1088 AttributeValue::Data4(_) => {
1089 debug_assert_form!(constants::DW_FORM_data4);
1090 4
1091 }
1092 AttributeValue::Data8(_) => {
1093 debug_assert_form!(constants::DW_FORM_data8);
1094 8
1095 }
1096 AttributeValue::Data16(_) => {
1097 debug_assert_form!(constants::DW_FORM_data16);
1098 16
1099 }
1100 AttributeValue::Sdata(val) => {
1101 debug_assert_form!(constants::DW_FORM_sdata);
1102 sleb128_size(val)
1103 }
1104 AttributeValue::ImplicitConst(val) => {
1105 if unit.version() >= 5 {
1106 debug_assert_form!(constants::DW_FORM_implicit_const);
1107 0
1108 } else {
1109 debug_assert_form!(constants::DW_FORM_sdata);
1110 sleb128_size(val)
1111 }
1112 }
1113 AttributeValue::Udata(val) => {
1114 debug_assert_form!(constants::DW_FORM_udata);
1115 uleb128_size(val)
1116 }
1117 AttributeValue::Exprloc(ref val) => {
1118 if unit.version() >= 4 {
1119 debug_assert_form!(constants::DW_FORM_exprloc);
1120 } else {
1121 debug_assert_form!(constants::DW_FORM_block);
1122 }
1123 let size = val.size(unit.encoding(), Some(offsets))?;
1124 uleb128_size(size as u64) + size
1125 }
1126 AttributeValue::Flag(_) => {
1127 debug_assert_form!(constants::DW_FORM_flag);
1128 1
1129 }
1130 AttributeValue::FlagPresent => {
1131 if unit.version() >= 4 {
1132 debug_assert_form!(constants::DW_FORM_flag_present);
1133 0
1134 } else {
1135 debug_assert_form!(constants::DW_FORM_flag);
1136 1
1137 }
1138 }
1139 AttributeValue::UnitRef(_) => {
1140 match unit.format() {
1141 Format::Dwarf32 => debug_assert_form!(constants::DW_FORM_ref4),
1142 Format::Dwarf64 => debug_assert_form!(constants::DW_FORM_ref8),
1143 }
1144 unit.format().word_size() as usize
1145 }
1146 AttributeValue::DebugInfoRef(_) => {
1147 debug_assert_form!(constants::DW_FORM_ref_addr);
1148 if unit.version() == 2 {
1149 unit.address_size() as usize
1150 } else {
1151 unit.format().word_size() as usize
1152 }
1153 }
1154 AttributeValue::DebugInfoRefSup(_) => {
1155 match unit.format() {
1156 Format::Dwarf32 => debug_assert_form!(constants::DW_FORM_ref_sup4),
1157 Format::Dwarf64 => debug_assert_form!(constants::DW_FORM_ref_sup8),
1158 }
1159 unit.format().word_size() as usize
1160 }
1161 AttributeValue::LineProgramRef => {
1162 if unit.version() >= 4 {
1163 debug_assert_form!(constants::DW_FORM_sec_offset);
1164 }
1165 unit.format().word_size() as usize
1166 }
1167 AttributeValue::LocationListRef(_) => {
1168 if unit.version() >= 4 {
1169 debug_assert_form!(constants::DW_FORM_sec_offset);
1170 }
1171 unit.format().word_size() as usize
1172 }
1173 AttributeValue::DebugMacinfoRef(_) => {
1174 if unit.version() >= 4 {
1175 debug_assert_form!(constants::DW_FORM_sec_offset);
1176 }
1177 unit.format().word_size() as usize
1178 }
1179 AttributeValue::DebugMacroRef(_) => {
1180 if unit.version() >= 4 {
1181 debug_assert_form!(constants::DW_FORM_sec_offset);
1182 }
1183 unit.format().word_size() as usize
1184 }
1185 AttributeValue::RangeListRef(_) => {
1186 if unit.version() >= 4 {
1187 debug_assert_form!(constants::DW_FORM_sec_offset);
1188 }
1189 unit.format().word_size() as usize
1190 }
1191 AttributeValue::DebugTypesRef(_) => {
1192 debug_assert_form!(constants::DW_FORM_ref_sig8);
1193 8
1194 }
1195 AttributeValue::StringRef(_) => {
1196 debug_assert_form!(constants::DW_FORM_strp);
1197 unit.format().word_size() as usize
1198 }
1199 AttributeValue::DebugStrRefSup(_) => {
1200 debug_assert_form!(constants::DW_FORM_strp_sup);
1201 unit.format().word_size() as usize
1202 }
1203 AttributeValue::LineStringRef(_) => {
1204 debug_assert_form!(constants::DW_FORM_line_strp);
1205 unit.format().word_size() as usize
1206 }
1207 AttributeValue::String(ref val) => {
1208 debug_assert_form!(constants::DW_FORM_string);
1209 val.len() + 1
1210 }
1211 AttributeValue::Encoding(val) => {
1212 debug_assert_form!(constants::DW_FORM_udata);
1213 uleb128_size(val.0 as u64)
1214 }
1215 AttributeValue::DecimalSign(val) => {
1216 debug_assert_form!(constants::DW_FORM_udata);
1217 uleb128_size(val.0 as u64)
1218 }
1219 AttributeValue::Endianity(val) => {
1220 debug_assert_form!(constants::DW_FORM_udata);
1221 uleb128_size(val.0 as u64)
1222 }
1223 AttributeValue::Accessibility(val) => {
1224 debug_assert_form!(constants::DW_FORM_udata);
1225 uleb128_size(val.0 as u64)
1226 }
1227 AttributeValue::Visibility(val) => {
1228 debug_assert_form!(constants::DW_FORM_udata);
1229 uleb128_size(val.0 as u64)
1230 }
1231 AttributeValue::Virtuality(val) => {
1232 debug_assert_form!(constants::DW_FORM_udata);
1233 uleb128_size(val.0 as u64)
1234 }
1235 AttributeValue::Language(val) => {
1236 debug_assert_form!(constants::DW_FORM_udata);
1237 uleb128_size(val.0 as u64)
1238 }
1239 AttributeValue::AddressClass(val) => {
1240 debug_assert_form!(constants::DW_FORM_udata);
1241 uleb128_size(val.0)
1242 }
1243 AttributeValue::IdentifierCase(val) => {
1244 debug_assert_form!(constants::DW_FORM_udata);
1245 uleb128_size(val.0 as u64)
1246 }
1247 AttributeValue::CallingConvention(val) => {
1248 debug_assert_form!(constants::DW_FORM_udata);
1249 uleb128_size(val.0 as u64)
1250 }
1251 AttributeValue::Inline(val) => {
1252 debug_assert_form!(constants::DW_FORM_udata);
1253 uleb128_size(val.0 as u64)
1254 }
1255 AttributeValue::Ordering(val) => {
1256 debug_assert_form!(constants::DW_FORM_udata);
1257 uleb128_size(val.0 as u64)
1258 }
1259 AttributeValue::FileIndex(val) => {
1260 debug_assert_form!(constants::DW_FORM_udata);
1261 uleb128_size(val.map(|id| id.raw(unit.version())).unwrap_or(0))
1262 }
1263 })
1264 }
1265
1266 fn write<W: Writer>(
1268 &self,
1269 w: &mut DebugInfo<W>,
1270 debug_info_refs: &mut Vec<DebugInfoFixup>,
1271 unit_refs: &mut Vec<(DebugInfoOffset, UnitEntryId)>,
1272 unit: &Unit,
1273 offsets: &UnitOffsets,
1274 line_program: Option<DebugLineOffset>,
1275 line_strings: &LineStringTable,
1276 strings: &StringTable,
1277 range_lists: &RangeListOffsets,
1278 loc_lists: &LocationListOffsets,
1279 ) -> Result<()> {
1280 macro_rules! debug_assert_form {
1281 ($form:expr) => {
1282 debug_assert_eq!(self.form(unit.encoding()).unwrap().0, $form)
1283 };
1284 }
1285 match *self {
1286 AttributeValue::Address(val) => {
1287 debug_assert_form!(constants::DW_FORM_addr);
1288 w.write_address(val, unit.address_size())?;
1289 }
1290 AttributeValue::Block(ref val) => {
1291 debug_assert_form!(constants::DW_FORM_block);
1292 w.write_uleb128(val.len() as u64)?;
1293 w.write(val)?;
1294 }
1295 AttributeValue::Data1(val) => {
1296 debug_assert_form!(constants::DW_FORM_data1);
1297 w.write_u8(val)?;
1298 }
1299 AttributeValue::Data2(val) => {
1300 debug_assert_form!(constants::DW_FORM_data2);
1301 w.write_u16(val)?;
1302 }
1303 AttributeValue::Data4(val) => {
1304 debug_assert_form!(constants::DW_FORM_data4);
1305 w.write_u32(val)?;
1306 }
1307 AttributeValue::Data8(val) => {
1308 debug_assert_form!(constants::DW_FORM_data8);
1309 w.write_u64(val)?;
1310 }
1311 AttributeValue::Data16(val) => {
1312 debug_assert_form!(constants::DW_FORM_data16);
1313 w.write_u128(val)?;
1314 }
1315 AttributeValue::Sdata(val) => {
1316 debug_assert_form!(constants::DW_FORM_sdata);
1317 w.write_sleb128(val)?;
1318 }
1319 AttributeValue::ImplicitConst(val) => {
1320 if unit.version() >= 5 {
1321 debug_assert_form!(constants::DW_FORM_implicit_const);
1322 } else {
1323 debug_assert_form!(constants::DW_FORM_sdata);
1324 w.write_sleb128(val)?;
1325 }
1326 }
1327 AttributeValue::Udata(val) => {
1328 debug_assert_form!(constants::DW_FORM_udata);
1329 w.write_uleb128(val)?;
1330 }
1331 AttributeValue::Exprloc(ref val) => {
1332 if unit.version() >= 4 {
1333 debug_assert_form!(constants::DW_FORM_exprloc);
1334 } else {
1335 debug_assert_form!(constants::DW_FORM_block);
1336 }
1337 w.write_uleb128(val.size(unit.encoding(), Some(offsets))? as u64)?;
1338 val.write(
1339 &mut w.0,
1340 Some(debug_info_refs),
1341 unit.encoding(),
1342 Some(offsets),
1343 )?;
1344 }
1345 AttributeValue::Flag(val) => {
1346 debug_assert_form!(constants::DW_FORM_flag);
1347 w.write_u8(val as u8)?;
1348 }
1349 AttributeValue::FlagPresent => {
1350 if unit.version() >= 4 {
1351 debug_assert_form!(constants::DW_FORM_flag_present);
1352 } else {
1353 debug_assert_form!(constants::DW_FORM_flag);
1354 w.write_u8(1)?;
1355 }
1356 }
1357 AttributeValue::UnitRef(id) => {
1358 match unit.format() {
1359 Format::Dwarf32 => debug_assert_form!(constants::DW_FORM_ref4),
1360 Format::Dwarf64 => debug_assert_form!(constants::DW_FORM_ref8),
1361 }
1362 unit_refs.push((w.offset(), id));
1363 w.write_udata(0, unit.format().word_size())?;
1364 }
1365 AttributeValue::DebugInfoRef(reference) => {
1366 debug_assert_form!(constants::DW_FORM_ref_addr);
1367 let size = if unit.version() == 2 {
1368 unit.address_size()
1369 } else {
1370 unit.format().word_size()
1371 };
1372 match reference {
1373 DebugInfoRef::Symbol(symbol) => w.write_reference(symbol, size)?,
1374 DebugInfoRef::Entry(unit, entry) => {
1375 debug_info_refs.push(DebugInfoFixup {
1376 offset: w.len(),
1377 unit,
1378 entry,
1379 size,
1380 });
1381 w.write_udata(0, size)?;
1382 }
1383 }
1384 }
1385 AttributeValue::DebugInfoRefSup(val) => {
1386 match unit.format() {
1387 Format::Dwarf32 => debug_assert_form!(constants::DW_FORM_ref_sup4),
1388 Format::Dwarf64 => debug_assert_form!(constants::DW_FORM_ref_sup8),
1389 }
1390 w.write_udata(val.0 as u64, unit.format().word_size())?;
1391 }
1392 AttributeValue::LineProgramRef => {
1393 if unit.version() >= 4 {
1394 debug_assert_form!(constants::DW_FORM_sec_offset);
1395 }
1396 match line_program {
1397 Some(line_program) => {
1398 w.write_offset(
1399 line_program.0,
1400 SectionId::DebugLine,
1401 unit.format().word_size(),
1402 )?;
1403 }
1404 None => return Err(Error::InvalidAttributeValue),
1405 }
1406 }
1407 AttributeValue::LocationListRef(val) => {
1408 if unit.version() >= 4 {
1409 debug_assert_form!(constants::DW_FORM_sec_offset);
1410 }
1411 let section = if unit.version() <= 4 {
1412 SectionId::DebugLoc
1413 } else {
1414 SectionId::DebugLocLists
1415 };
1416 w.write_offset(loc_lists.get(val).0, section, unit.format().word_size())?;
1417 }
1418 AttributeValue::DebugMacinfoRef(val) => {
1419 if unit.version() >= 4 {
1420 debug_assert_form!(constants::DW_FORM_sec_offset);
1421 }
1422 w.write_offset(val.0, SectionId::DebugMacinfo, unit.format().word_size())?;
1423 }
1424 AttributeValue::DebugMacroRef(val) => {
1425 if unit.version() >= 4 {
1426 debug_assert_form!(constants::DW_FORM_sec_offset);
1427 }
1428 w.write_offset(val.0, SectionId::DebugMacro, unit.format().word_size())?;
1429 }
1430 AttributeValue::RangeListRef(val) => {
1431 if unit.version() >= 4 {
1432 debug_assert_form!(constants::DW_FORM_sec_offset);
1433 }
1434 let section = if unit.version() <= 4 {
1435 SectionId::DebugRanges
1436 } else {
1437 SectionId::DebugRngLists
1438 };
1439 w.write_offset(range_lists.get(val).0, section, unit.format().word_size())?;
1440 }
1441 AttributeValue::DebugTypesRef(val) => {
1442 debug_assert_form!(constants::DW_FORM_ref_sig8);
1443 w.write_u64(val.0)?;
1444 }
1445 AttributeValue::StringRef(val) => {
1446 debug_assert_form!(constants::DW_FORM_strp);
1447 w.write_offset(
1448 strings.offset(val).0,
1449 SectionId::DebugStr,
1450 unit.format().word_size(),
1451 )?;
1452 }
1453 AttributeValue::DebugStrRefSup(val) => {
1454 debug_assert_form!(constants::DW_FORM_strp_sup);
1455 w.write_udata(val.0 as u64, unit.format().word_size())?;
1456 }
1457 AttributeValue::LineStringRef(val) => {
1458 debug_assert_form!(constants::DW_FORM_line_strp);
1459 w.write_offset(
1460 line_strings.offset(val).0,
1461 SectionId::DebugLineStr,
1462 unit.format().word_size(),
1463 )?;
1464 }
1465 AttributeValue::String(ref val) => {
1466 debug_assert_form!(constants::DW_FORM_string);
1467 w.write(val)?;
1468 w.write_u8(0)?;
1469 }
1470 AttributeValue::Encoding(val) => {
1471 debug_assert_form!(constants::DW_FORM_udata);
1472 w.write_uleb128(u64::from(val.0))?;
1473 }
1474 AttributeValue::DecimalSign(val) => {
1475 debug_assert_form!(constants::DW_FORM_udata);
1476 w.write_uleb128(u64::from(val.0))?;
1477 }
1478 AttributeValue::Endianity(val) => {
1479 debug_assert_form!(constants::DW_FORM_udata);
1480 w.write_uleb128(u64::from(val.0))?;
1481 }
1482 AttributeValue::Accessibility(val) => {
1483 debug_assert_form!(constants::DW_FORM_udata);
1484 w.write_uleb128(u64::from(val.0))?;
1485 }
1486 AttributeValue::Visibility(val) => {
1487 debug_assert_form!(constants::DW_FORM_udata);
1488 w.write_uleb128(u64::from(val.0))?;
1489 }
1490 AttributeValue::Virtuality(val) => {
1491 debug_assert_form!(constants::DW_FORM_udata);
1492 w.write_uleb128(u64::from(val.0))?;
1493 }
1494 AttributeValue::Language(val) => {
1495 debug_assert_form!(constants::DW_FORM_udata);
1496 w.write_uleb128(u64::from(val.0))?;
1497 }
1498 AttributeValue::AddressClass(val) => {
1499 debug_assert_form!(constants::DW_FORM_udata);
1500 w.write_uleb128(val.0)?;
1501 }
1502 AttributeValue::IdentifierCase(val) => {
1503 debug_assert_form!(constants::DW_FORM_udata);
1504 w.write_uleb128(u64::from(val.0))?;
1505 }
1506 AttributeValue::CallingConvention(val) => {
1507 debug_assert_form!(constants::DW_FORM_udata);
1508 w.write_uleb128(u64::from(val.0))?;
1509 }
1510 AttributeValue::Inline(val) => {
1511 debug_assert_form!(constants::DW_FORM_udata);
1512 w.write_uleb128(u64::from(val.0))?;
1513 }
1514 AttributeValue::Ordering(val) => {
1515 debug_assert_form!(constants::DW_FORM_udata);
1516 w.write_uleb128(u64::from(val.0))?;
1517 }
1518 AttributeValue::FileIndex(val) => {
1519 debug_assert_form!(constants::DW_FORM_udata);
1520 w.write_uleb128(val.map(|id| id.raw(unit.version())).unwrap_or(0))?;
1521 }
1522 }
1523 Ok(())
1524 }
1525}
1526
1527define_section!(
1528 DebugInfo,
1529 DebugInfoOffset,
1530 "A writable `.debug_info` section."
1531);
1532
1533#[derive(Debug)]
1535pub(crate) struct UnitOffsets {
1536 base_id: BaseId,
1537 unit: DebugInfoOffset,
1538 entries: Vec<DebugInfoOffset>,
1539}
1540
1541impl UnitOffsets {
1542 #[inline]
1546 fn debug_info_offset(&self, entry: UnitEntryId) -> Option<DebugInfoOffset> {
1547 debug_assert_eq!(self.base_id, entry.base_id);
1548 let offset = self.entries[entry.index];
1549 if offset.0 == 0 { None } else { Some(offset) }
1550 }
1551
1552 #[inline]
1558 pub(crate) fn unit_offset(&self, entry: UnitEntryId) -> Option<u64> {
1559 self.debug_info_offset(entry)
1560 .map(|offset| (offset.0 - self.unit.0) as u64)
1561 }
1562}
1563
1564#[deprecated(note = "Renamed to DebugInfoRef")]
1566pub type Reference = DebugInfoRef;
1567
1568#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1570pub enum DebugInfoRef {
1571 Symbol(usize),
1576 Entry(UnitId, UnitEntryId),
1580}
1581
1582#[derive(Debug, Clone, Copy)]
1584pub(crate) struct DebugInfoFixup {
1585 pub offset: usize,
1587 pub size: u8,
1589 pub unit: UnitId,
1591 pub entry: UnitEntryId,
1593}
1594
1595#[cfg(feature = "read")]
1596pub use convert::*;
1597#[cfg(feature = "read")]
1598pub(crate) mod convert {
1599 use super::*;
1600 use crate::common::{
1601 DwoId, LineEncoding, LocationListsOffset, RangeListsOffset, UnitSectionOffset,
1602 };
1603 use crate::read::{self, Reader, ReaderOffset};
1604 use crate::write::{
1605 self, ConvertError, ConvertLineProgram, ConvertResult, Dwarf, LocationList, RangeList,
1606 };
1607
1608 type FnvHashMap<K, V> = hashbrown::HashMap<K, V, fnv::FnvBuildHasher>;
1609
1610 #[derive(Debug, Default)]
1611 struct FilterDependencies {
1612 edges: FnvHashMap<UnitSectionOffset, Vec<UnitSectionOffset>>,
1613 required: Vec<UnitSectionOffset>,
1614 }
1615
1616 impl FilterDependencies {
1617 fn add_entry(&mut self, entry: UnitSectionOffset, deps: Vec<UnitSectionOffset>) {
1623 debug_assert!(!self.edges.contains_key(&entry));
1624 self.edges.insert(entry, deps);
1625 }
1626
1627 fn add_edge(&mut self, from: UnitSectionOffset, to: UnitSectionOffset) {
1634 self.edges.get_mut(&from).unwrap().push(to);
1635 }
1636
1637 fn require_entry(&mut self, entry: UnitSectionOffset) {
1642 self.required.push(entry);
1643 }
1644
1645 fn get_reachable(mut self) -> Vec<UnitSectionOffset> {
1647 let mut reachable = Vec::new();
1648 let mut queue = vec![self.required];
1649 while let Some(entries) = queue.pop() {
1650 for entry in entries {
1651 if let Some(deps) = self.edges.remove(&entry) {
1652 reachable.push(entry);
1653 queue.push(deps);
1654 }
1655 }
1656 }
1657 reachable.sort_unstable();
1658 reachable
1659 }
1660 }
1661
1662 #[derive(Debug)]
1696 pub struct FilterUnitSection<'a, R: Reader<Offset = usize>> {
1697 dwarf: &'a read::Dwarf<R>,
1698 unit_headers: read::DebugInfoUnitHeadersIter<R>,
1699 skeleton_unit: Option<read::UnitRef<'a, R>>,
1700 units: Vec<read::Unit<R>>,
1701 deps: FilterDependencies,
1702 }
1703
1704 impl<'a, R: Reader<Offset = usize>> FilterUnitSection<'a, R> {
1705 pub fn new(dwarf: &'a read::Dwarf<R>) -> ConvertResult<Self> {
1718 Ok(FilterUnitSection {
1719 dwarf,
1720 unit_headers: dwarf.units(),
1721 skeleton_unit: None,
1722 units: Vec::new(),
1723 deps: FilterDependencies::default(),
1724 })
1725 }
1726
1727 pub fn new_split(
1743 dwarf: &'a read::Dwarf<R>,
1744 skeleton_unit: read::UnitRef<'a, R>,
1745 ) -> ConvertResult<Self> {
1746 Ok(FilterUnitSection {
1747 dwarf,
1748 unit_headers: dwarf.units(),
1749 skeleton_unit: Some(skeleton_unit),
1750 units: Vec::new(),
1751 deps: FilterDependencies::default(),
1752 })
1753 }
1754
1755 pub fn read_unit(&'_ mut self) -> ConvertResult<Option<FilterUnit<'_, R>>> {
1757 let Some(header) = self.unit_headers.next()? else {
1758 return Ok(None);
1759 };
1760 let mut unit = self.dwarf.unit(header)?;
1761 if let Some(skeleton_unit) = self.skeleton_unit {
1762 unit.copy_relocated_attributes(&skeleton_unit);
1763 }
1764 self.units.push(unit);
1765 let unit = self.units.last().unwrap().unit_ref(self.dwarf);
1766
1767 FilterUnit::new(unit, self.skeleton_unit, &mut self.deps).map(Some)
1768 }
1769 }
1770
1771 #[derive(Debug)]
1778 pub struct FilterUnit<'a, R: Reader<Offset = usize>> {
1779 pub read_unit: read::UnitRef<'a, R>,
1781 pub read_skeleton_unit: Option<read::UnitRef<'a, R>>,
1783 entries: read::EntriesRaw<'a, R>,
1784 parents: Vec<FilterParent>,
1785 deps: &'a mut FilterDependencies,
1786 }
1787
1788 #[derive(Debug, Clone, Copy)]
1789 struct FilterParent {
1790 depth: isize,
1791 offset: read::UnitOffset,
1792 tag: constants::DwTag,
1793 }
1794
1795 impl<'a, R: Reader<Offset = usize>> FilterUnit<'a, R> {
1796 fn new(
1797 read_unit: read::UnitRef<'a, R>,
1798 read_skeleton_unit: Option<read::UnitRef<'a, R>>,
1799 deps: &'a mut FilterDependencies,
1800 ) -> ConvertResult<Self> {
1801 let mut entries = read_unit.entries_raw(None)?;
1802 let abbrev = entries
1803 .read_abbreviation()?
1804 .ok_or(read::Error::MissingUnitDie)?;
1805 entries.skip_attributes(abbrev.attributes())?;
1806 Ok(FilterUnit {
1807 read_unit,
1808 read_skeleton_unit,
1809 entries,
1810 parents: Vec::new(),
1811 deps,
1812 })
1813 }
1814
1815 pub fn null_entry(&self) -> FilterUnitEntry<'a, R> {
1817 FilterUnitEntry::null(self.read_unit)
1818 }
1819
1820 pub fn read_entry(&mut self, entry: &mut FilterUnitEntry<'a, R>) -> ConvertResult<bool> {
1833 loop {
1834 if self.entries.is_empty() {
1835 return Ok(false);
1836 }
1837
1838 if !self.entries.read_entry(&mut entry.read_entry)? {
1839 continue;
1841 }
1842 entry.read_unit = self.read_unit;
1843 Self::filter_attributes(entry)?;
1844
1845 while let Some(parent) = self.parents.last() {
1846 if parent.depth < entry.depth {
1847 break;
1848 }
1849 self.parents.pop();
1850 }
1851 let parent = self.parents.last().copied();
1852 entry.parent = parent.map(|p| p.offset);
1853 entry.parent_tag = parent.map(|p| p.tag);
1854
1855 if entry.has_children() {
1856 self.parents.push(FilterParent {
1857 depth: entry.depth,
1858 offset: entry.offset,
1859 tag: entry.tag,
1860 });
1861 }
1862
1863 let entry_offset = entry.offset.to_unit_section_offset(&self.read_unit);
1864 let mut deps = Vec::new();
1865 for attr in &entry.attrs {
1866 self.add_attribute_refs(&mut deps, attr.value())?;
1867 }
1868 if let Some(parent) = parent {
1869 let parent_offset = parent.offset.to_unit_section_offset(&self.read_unit);
1870 deps.push(parent_offset);
1871 if parent.tag != constants::DW_TAG_namespace && entry.has_die_back_edge() {
1872 self.deps.add_edge(parent_offset, entry_offset);
1873 }
1874 }
1875 self.deps.add_entry(entry_offset, deps);
1876
1877 return Ok(true);
1878 }
1879 }
1880
1881 fn filter_attributes(entry: &mut FilterUnitEntry<'a, R>) -> ConvertResult<()> {
1882 entry.read_entry.attrs.retain(|attr| {
1883 match attr.name() {
1884 constants::DW_AT_sibling
1887 | constants::DW_AT_str_offsets_base
1888 | constants::DW_AT_addr_base
1889 | constants::DW_AT_rnglists_base
1890 | constants::DW_AT_loclists_base
1891 | constants::DW_AT_dwo_name
1892 | constants::DW_AT_GNU_addr_base
1893 | constants::DW_AT_GNU_ranges_base
1894 | constants::DW_AT_GNU_dwo_name
1895 | constants::DW_AT_GNU_dwo_id => false,
1896 _ => true,
1897 }
1898 });
1899 Ok(())
1900 }
1901
1902 fn add_attribute_refs(
1903 &mut self,
1904 deps: &mut Vec<UnitSectionOffset>,
1905 value: read::AttributeValue<R>,
1906 ) -> ConvertResult<()> {
1907 match value {
1908 read::AttributeValue::UnitRef(val) => {
1909 if val.is_in_bounds(&self.read_unit) {
1911 deps.push(val.to_unit_section_offset(&self.read_unit));
1912 }
1913 }
1914 read::AttributeValue::DebugInfoRef(val) => {
1915 let offset = val
1916 .to_unit_section_offset(&self.read_unit)
1917 .ok_or(ConvertError::InvalidDebugInfoRef)?;
1918 deps.push(offset);
1919 }
1920 read::AttributeValue::Exprloc(expression) => {
1921 self.add_expression_refs(deps, expression.clone())?;
1922 }
1923 read::AttributeValue::LocationListsRef(val) => {
1924 self.add_location_refs(deps, val)?;
1925 }
1926 read::AttributeValue::DebugLocListsIndex(index) => {
1927 self.add_location_refs(deps, self.read_unit.locations_offset(index)?)?;
1928 }
1929 _ => (),
1930 }
1931 Ok(())
1932 }
1933
1934 fn add_location_refs(
1935 &mut self,
1936 deps: &mut Vec<UnitSectionOffset>,
1937 offset: LocationListsOffset,
1938 ) -> ConvertResult<()> {
1939 let mut locations = self.read_unit.locations(offset)?;
1940 while let Some(location) = locations.next()? {
1941 self.add_expression_refs(deps, location.data)?;
1942 }
1943 Ok(())
1944 }
1945
1946 fn add_expression_refs(
1947 &mut self,
1948 deps: &mut Vec<UnitSectionOffset>,
1949 expression: read::Expression<R>,
1950 ) -> ConvertResult<()> {
1951 let mut ops = expression.operations(self.read_unit.encoding());
1952 while let Ok(Some(op)) = ops.next() {
1954 match op {
1955 read::Operation::Deref {
1956 base_type: offset, ..
1957 }
1958 | read::Operation::RegisterOffset {
1959 base_type: offset, ..
1960 }
1961 | read::Operation::TypedLiteral {
1962 base_type: offset, ..
1963 }
1964 | read::Operation::Convert {
1965 base_type: offset, ..
1966 }
1967 | read::Operation::Reinterpret {
1968 base_type: offset, ..
1969 }
1970 | read::Operation::ParameterRef { offset, .. }
1971 | read::Operation::Call {
1972 offset: read::DieReference::UnitRef(offset),
1973 ..
1974 } => {
1975 if offset.is_in_bounds(&self.read_unit) {
1976 deps.push(offset.to_unit_section_offset(&self.read_unit));
1977 }
1978 }
1979 read::Operation::Call {
1980 offset: read::DieReference::DebugInfoRef(ref_offset),
1981 ..
1982 } => {
1983 let offset = ref_offset
1984 .to_unit_section_offset(&self.read_unit)
1985 .ok_or(ConvertError::InvalidDebugInfoRef)?;
1986 deps.push(offset);
1987 }
1988 _ => {}
1989 }
1990 }
1991 Ok(())
1992 }
1993
1994 pub fn require_entry(&mut self, offset: read::UnitOffset) {
2000 debug_assert!(offset.is_in_bounds(&self.read_unit));
2001 self.deps
2002 .require_entry(offset.to_unit_section_offset(&self.read_unit));
2003 }
2004 }
2005
2006 #[derive(Debug)]
2014 #[non_exhaustive]
2015 pub struct FilterUnitEntry<'a, R: Reader<Offset = usize>> {
2016 pub read_unit: read::UnitRef<'a, R>,
2020 pub read_entry: read::DebuggingInformationEntry<R>,
2022 pub parent: Option<read::UnitOffset>,
2026 pub parent_tag: Option<constants::DwTag>,
2030 }
2031
2032 impl<'a, R: Reader<Offset = usize>> Deref for FilterUnitEntry<'a, R> {
2033 type Target = read::DebuggingInformationEntry<R>;
2034
2035 fn deref(&self) -> &Self::Target {
2036 &self.read_entry
2037 }
2038 }
2039
2040 impl<'a, R: Reader<Offset = usize>> FilterUnitEntry<'a, R> {
2041 pub fn null(read_unit: read::UnitRef<'a, R>) -> Self {
2045 FilterUnitEntry {
2046 read_unit,
2047 read_entry: read::DebuggingInformationEntry::null(),
2048 parent: None,
2049 parent_tag: None,
2050 }
2051 }
2052
2053 fn has_die_back_edge(&self) -> bool {
2062 match self.tag {
2063 constants::DW_TAG_array_type
2064 | constants::DW_TAG_atomic_type
2065 | constants::DW_TAG_base_type
2066 | constants::DW_TAG_class_type
2067 | constants::DW_TAG_const_type
2068 | constants::DW_TAG_dwarf_procedure
2069 | constants::DW_TAG_entry_point
2070 | constants::DW_TAG_enumeration_type
2071 | constants::DW_TAG_pointer_type
2072 | constants::DW_TAG_ptr_to_member_type
2073 | constants::DW_TAG_reference_type
2074 | constants::DW_TAG_restrict_type
2075 | constants::DW_TAG_rvalue_reference_type
2076 | constants::DW_TAG_string_type
2077 | constants::DW_TAG_structure_type
2078 | constants::DW_TAG_typedef
2079 | constants::DW_TAG_union_type
2080 | constants::DW_TAG_unspecified_type
2081 | constants::DW_TAG_volatile_type
2082 | constants::DW_TAG_coarray_type
2083 | constants::DW_TAG_common_block
2084 | constants::DW_TAG_dynamic_type
2085 | constants::DW_TAG_file_type
2086 | constants::DW_TAG_immutable_type
2087 | constants::DW_TAG_interface_type
2088 | constants::DW_TAG_set_type
2089 | constants::DW_TAG_shared_type
2090 | constants::DW_TAG_subroutine_type
2091 | constants::DW_TAG_packed_type
2092 | constants::DW_TAG_template_alias
2093 | constants::DW_TAG_namelist
2094 | constants::DW_TAG_namespace
2095 | constants::DW_TAG_imported_unit
2096 | constants::DW_TAG_imported_declaration
2097 | constants::DW_TAG_imported_module
2098 | constants::DW_TAG_module => false,
2099 constants::DW_TAG_subprogram => self.has_attr(constants::DW_AT_declaration),
2100 _ => true,
2101 }
2102 }
2103 }
2104
2105 #[derive(Debug)]
2109 pub struct ConvertUnitSection<'a, R: Reader<Offset = usize>> {
2110 read_dwarf: &'a read::Dwarf<R>,
2111 read_units: Vec<(read::Unit<R>, UnitId)>,
2112 read_unit_index: usize,
2114 read_skeleton_unit: Option<read::UnitRef<'a, R>>,
2118 entry_ids: FnvHashMap<UnitSectionOffset, (UnitId, UnitEntryId)>,
2119 dwarf: &'a mut Dwarf,
2120 }
2121
2122 impl<'a, R: Reader<Offset = usize>> ConvertUnitSection<'a, R> {
2123 pub(crate) fn new(
2125 read_dwarf: &'a read::Dwarf<R>,
2126 dwarf: &'a mut Dwarf,
2127 ) -> ConvertResult<Self> {
2128 let mut convert = ConvertUnitSection {
2129 read_dwarf,
2130 read_units: Vec::new(),
2131 read_unit_index: 0,
2132 read_skeleton_unit: None,
2133 entry_ids: FnvHashMap::default(),
2134 dwarf,
2135 };
2136
2137 let mut offsets = Vec::new();
2140 let mut read_units = read_dwarf.units();
2141 while let Some(read_unit) = read_units.next()? {
2142 let read_unit = read_dwarf.unit(read_unit)?;
2143 read_entry_offsets(&read_unit, &mut offsets)?;
2144 convert.reserve_unit(read_unit, &offsets);
2145 }
2146
2147 Ok(convert)
2148 }
2149
2150 pub(crate) fn new_with_filter(
2156 dwarf: &'a mut Dwarf,
2157 filter: FilterUnitSection<'a, R>,
2158 ) -> ConvertResult<Self> {
2159 let mut convert = ConvertUnitSection {
2160 read_dwarf: filter.dwarf,
2161 read_units: Vec::new(),
2162 read_unit_index: 0,
2163 read_skeleton_unit: filter.skeleton_unit,
2164 entry_ids: FnvHashMap::default(),
2165 dwarf,
2166 };
2167
2168 let offsets = filter.deps.get_reachable();
2169
2170 let mut start;
2172 let mut end = 0;
2173 for unit in filter.units {
2174 start = end;
2175 while let Some(offset) = offsets.get(end) {
2176 if offset.to_unit_offset(&unit).is_none() {
2177 break;
2178 }
2179 end += 1;
2180 }
2181 convert.reserve_unit(unit, &offsets[start..end]);
2182 }
2183 debug_assert_eq!(end, offsets.len());
2184
2185 Ok(convert)
2186 }
2187
2188 fn reserve_unit(&mut self, unit: read::Unit<R>, offsets: &[UnitSectionOffset]) {
2192 let root_offset = unit.header.root_offset().to_unit_section_offset(&unit);
2193
2194 let unit_id = self
2195 .dwarf
2196 .units
2197 .add(Unit::new(unit.encoding(), LineProgram::none()));
2198 self.read_units.push((unit, unit_id));
2199 let unit = self.dwarf.units.get_mut(unit_id);
2200
2201 self.entry_ids.insert(root_offset, (unit_id, unit.root()));
2202 for offset in offsets {
2203 self.entry_ids.insert(*offset, (unit_id, unit.reserve()));
2204 }
2205 }
2206
2207 pub fn read_unit(
2214 &mut self,
2215 ) -> ConvertResult<Option<(ConvertUnit<'_, R>, ConvertUnitEntry<'_, R>)>> {
2216 let Some((read_unit, unit_id)) = self.read_units.get(self.read_unit_index) else {
2217 return Ok(None);
2218 };
2219 self.read_unit_index += 1;
2220
2221 let read_unit = read_unit.unit_ref(self.read_dwarf);
2222
2223 let mut unit = ConvertUnit {
2224 read_unit,
2225 read_skeleton_unit: self.read_skeleton_unit,
2226 unit_id: *unit_id,
2227 unit: self.dwarf.units.get_mut(*unit_id),
2228 entry_ids: &self.entry_ids,
2229 line_strings: &mut self.dwarf.line_strings,
2230 strings: &mut self.dwarf.strings,
2231 line_program_files: Vec::new(),
2232 read_entries: read_unit.entries_raw(None)?,
2233 parents: Vec::new(),
2234 };
2235 let mut root_entry = unit.null_entry();
2236 unit.read_entry(&mut root_entry)?
2237 .ok_or(read::Error::MissingUnitDie)?;
2238 Ok(Some((unit, root_entry)))
2239 }
2240 }
2241
2242 #[derive(Debug)]
2247 pub struct ConvertSplitUnitSection<'a, R: Reader<Offset = usize>> {
2248 read_dwarf: &'a read::Dwarf<R>,
2249 read_unit: read::Unit<R>,
2250 read_skeleton_unit: read::UnitRef<'a, R>,
2251 entry_ids: FnvHashMap<UnitSectionOffset, (UnitId, UnitEntryId)>,
2252 unit_id: UnitId,
2253 unit: &'a mut write::Unit,
2254 line_strings: &'a mut write::LineStringTable,
2255 strings: &'a mut write::StringTable,
2256 }
2257
2258 impl<'a, R: Reader<Offset = usize>> ConvertSplitUnitSection<'a, R> {
2259 fn new(
2260 skeleton: &'a mut ConvertUnit<'a, R>,
2261 split_dwarf: &'a read::Dwarf<R>,
2262 ) -> ConvertResult<Self> {
2263 debug_assert!(skeleton.read_skeleton_unit.is_none());
2264
2265 let split_unit_header = split_dwarf
2266 .units()
2267 .next()?
2268 .ok_or(read::Error::MissingSplitUnit)?;
2269 let mut split_unit = split_dwarf.unit(split_unit_header)?;
2270 split_unit.copy_relocated_attributes(&skeleton.read_unit);
2271
2272 let mut offsets = Vec::new();
2273 read_entry_offsets(&split_unit, &mut offsets)?;
2274
2275 Self::new_with_offsets(skeleton, split_dwarf, split_unit, offsets)
2276 }
2277
2278 fn new_with_filter(
2279 skeleton: &'a mut ConvertUnit<'a, R>,
2280 filter: FilterUnitSection<'a, R>,
2281 ) -> ConvertResult<Self> {
2282 debug_assert!(skeleton.read_skeleton_unit.is_none());
2283
2284 let split_unit = filter
2285 .units
2286 .into_iter()
2287 .next()
2288 .ok_or(read::Error::MissingSplitUnit)?;
2289
2290 let offsets = filter.deps.get_reachable();
2291
2292 Self::new_with_offsets(skeleton, filter.dwarf, split_unit, offsets)
2293 }
2294
2295 fn new_with_offsets(
2296 skeleton: &'a mut ConvertUnit<'a, R>,
2297 split_dwarf: &'a read::Dwarf<R>,
2298 split_unit: read::Unit<R>,
2299 offsets: Vec<UnitSectionOffset>,
2300 ) -> ConvertResult<Self> {
2301 let root_offset = split_unit
2302 .header
2303 .root_offset()
2304 .to_unit_section_offset(&split_unit);
2305
2306 let unit_id = skeleton.unit_id;
2308 let unit = &mut *skeleton.unit;
2309
2310 let mut entry_ids = FnvHashMap::default();
2311 entry_ids.insert(root_offset, (unit_id, unit.root()));
2312 for offset in offsets {
2313 entry_ids.insert(offset, (unit_id, unit.reserve()));
2314 }
2315
2316 Ok(ConvertSplitUnitSection {
2317 read_dwarf: split_dwarf,
2318 read_unit: split_unit,
2319 read_skeleton_unit: skeleton.read_unit,
2320 entry_ids,
2321 unit_id,
2322 unit,
2323 line_strings: skeleton.line_strings,
2324 strings: skeleton.strings,
2325 })
2326 }
2327
2328 pub fn read_unit(
2335 &'_ mut self,
2336 ) -> ConvertResult<(ConvertUnit<'_, R>, ConvertUnitEntry<'_, R>)> {
2337 let read_unit = self.read_unit.unit_ref(self.read_dwarf);
2338
2339 let mut unit = ConvertUnit {
2340 read_unit,
2341 read_skeleton_unit: Some(self.read_skeleton_unit),
2342 unit_id: self.unit_id,
2343 unit: self.unit,
2344 entry_ids: &self.entry_ids,
2345 line_strings: self.line_strings,
2346 strings: self.strings,
2347 line_program_files: Vec::new(),
2348 read_entries: read_unit.entries_raw(None)?,
2349 parents: Vec::new(),
2350 };
2351 let mut root_entry = unit.null_entry();
2352 unit.read_entry(&mut root_entry)?
2353 .ok_or(read::Error::MissingUnitDie)?;
2354 Ok((unit, root_entry))
2355 }
2356 }
2357
2358 fn read_entry_offsets<R: Reader<Offset = usize>>(
2364 unit: &read::Unit<R>,
2365 offsets: &mut Vec<UnitSectionOffset>,
2366 ) -> ConvertResult<()> {
2367 let mut read_entries = unit.entries_raw(None)?;
2368
2369 let abbrev = read_entries
2371 .read_abbreviation()?
2372 .ok_or(read::Error::MissingUnitDie)?;
2373 read_entries.skip_attributes(abbrev.attributes())?;
2374
2375 offsets.clear();
2376 while !read_entries.is_empty() {
2377 let offset = read_entries.next_offset();
2378 let Some(abbrev) = read_entries.read_abbreviation()? else {
2379 continue;
2380 };
2381 read_entries.skip_attributes(abbrev.attributes())?;
2382 offsets.push(offset.to_unit_section_offset(unit));
2383 }
2384
2385 Ok(())
2386 }
2387
2388 #[derive(Debug)]
2443 pub struct ConvertUnit<'a, R: Reader<Offset = usize>> {
2444 pub read_unit: read::UnitRef<'a, R>,
2446 pub read_skeleton_unit: Option<read::UnitRef<'a, R>>,
2448 unit_id: UnitId,
2449 pub unit: &'a mut write::Unit,
2451 pub line_strings: &'a mut write::LineStringTable,
2453 pub strings: &'a mut write::StringTable,
2455 line_program_files: Vec<FileId>,
2456 entry_ids: &'a FnvHashMap<UnitSectionOffset, (UnitId, UnitEntryId)>,
2457 read_entries: read::EntriesRaw<'a, R>,
2458 parents: Vec<(isize, UnitEntryId)>,
2459 }
2460
2461 impl<'a, R: Reader<Offset = usize>> ConvertUnit<'a, R> {
2462 pub fn convert_split(
2491 &'a mut self,
2492 split_dwarf: &'a read::Dwarf<R>,
2493 ) -> ConvertResult<ConvertSplitUnitSection<'a, R>> {
2494 ConvertSplitUnitSection::new(self, split_dwarf)
2495 }
2496
2497 pub fn convert_split_with_filter(
2536 &'a mut self,
2537 filter: FilterUnitSection<'a, R>,
2538 ) -> ConvertResult<ConvertSplitUnitSection<'a, R>> {
2539 ConvertSplitUnitSection::new_with_filter(self, filter)
2540 }
2541
2542 pub fn read_line_program(
2552 &'_ mut self,
2553 encoding: Option<Encoding>,
2554 line_encoding: Option<LineEncoding>,
2555 ) -> ConvertResult<Option<ConvertLineProgram<'_, R>>> {
2556 let read_unit = self.read_skeleton_unit.unwrap_or(self.read_unit);
2557 let Some(read_program) = &read_unit.line_program else {
2558 return Ok(None);
2559 };
2560 ConvertLineProgram::new(
2561 read_unit.dwarf,
2562 read_program.clone(),
2563 self.read_skeleton_unit
2565 .and_then(|_| self.read_unit.name.clone()),
2566 encoding,
2567 line_encoding,
2568 self.line_strings,
2569 self.strings,
2570 )
2571 .map(Some)
2572 }
2573
2574 pub fn set_line_program(
2579 &mut self,
2580 line_program: LineProgram,
2581 line_program_files: Vec<FileId>,
2582 ) {
2583 self.unit.line_program = line_program;
2584 self.line_program_files = line_program_files;
2585 }
2586
2587 pub fn null_entry(&self) -> ConvertUnitEntry<'a, R> {
2589 ConvertUnitEntry::null(self.read_unit)
2590 }
2591
2592 pub fn read_entry(
2602 &mut self,
2603 entry: &mut ConvertUnitEntry<'a, R>,
2604 ) -> ConvertResult<Option<Option<UnitEntryId>>> {
2605 loop {
2606 if self.read_entries.is_empty() {
2607 return Ok(None);
2608 }
2609
2610 if !self.read_entries.read_entry(&mut entry.read_entry)? {
2611 continue;
2613 };
2614 entry.read_unit = self.read_unit;
2615 entry.filter_attributes();
2616
2617 let section_offset = entry.offset.to_unit_section_offset(&self.read_unit);
2618 let id = self.entry_ids.get(§ion_offset).map(|entry| entry.1);
2619
2620 entry.parent = None;
2621 while let Some((parent_depth, parent_id)) = self.parents.last().copied() {
2622 if parent_depth < entry.depth {
2623 entry.parent = Some(parent_id);
2624 break;
2625 }
2626 self.parents.pop();
2627 }
2628
2629 if let Some(id) = id
2630 && entry.has_children()
2631 {
2632 self.parents.push((entry.depth, id));
2633 }
2634
2635 return Ok(Some(id));
2636 }
2637 }
2638
2639 pub fn add_entry(
2651 &mut self,
2652 id: Option<UnitEntryId>,
2653 entry: &ConvertUnitEntry<'_, R>,
2654 ) -> UnitEntryId {
2655 let parent = entry.parent.unwrap_or(self.unit.root());
2656 let id = match id {
2657 Some(id) => {
2658 self.unit.add_reserved(id, parent, entry.tag);
2659 id
2660 }
2661 None => self.unit.add(parent, entry.tag),
2662 };
2663 let new_entry = self.unit.get_mut(id);
2664 new_entry.set_sibling(entry.sibling);
2665 new_entry.reserve(entry.attrs.len());
2666 id
2667 }
2668
2669 pub fn write<W: Writer>(&mut self, sections: &mut Sections<W>) -> Result<()> {
2678 let abbrev_offset = sections.debug_abbrev.offset();
2679 let mut abbrevs = AbbreviationTable::default();
2680 self.unit.write(
2681 sections,
2682 abbrev_offset,
2683 &mut abbrevs,
2684 self.line_strings,
2685 self.strings,
2686 )?;
2687 abbrevs.write(&mut sections.debug_abbrev)?;
2688 self.unit.free();
2689 Ok(())
2690 }
2691
2692 pub fn skip(&mut self) {
2699 self.unit.skip();
2700 self.unit.free();
2701 }
2702
2703 pub fn convert(
2713 &mut self,
2714 root_entry: ConvertUnitEntry<'a, R>,
2715 convert_address: &dyn Fn(u64) -> Option<Address>,
2716 ) -> ConvertResult<()> {
2717 if let Some(convert_program) = self.read_line_program(None, None)? {
2718 let (program, files) = convert_program.convert(convert_address)?;
2719 self.set_line_program(program, files);
2720 }
2721 self.convert_attributes(self.unit.root(), &root_entry, convert_address)?;
2722 let mut entry = root_entry;
2723 while let Some(id) = self.read_entry(&mut entry)? {
2724 if id.is_none() {
2725 continue;
2726 }
2727 let id = self.add_entry(id, &entry);
2728 self.convert_attributes(id, &entry, convert_address)?;
2729 }
2730 Ok(())
2731 }
2732
2733 pub(crate) fn convert_attributes(
2734 &mut self,
2735 id: UnitEntryId,
2736 entry: &ConvertUnitEntry<'_, R>,
2737 convert_address: &dyn Fn(u64) -> Option<Address>,
2738 ) -> ConvertResult<()> {
2739 for attr in &entry.attrs {
2740 if attr.name() == constants::DW_AT_GNU_locviews {
2741 } else {
2744 let value =
2745 self.convert_attribute_value(entry.read_unit, attr, convert_address)?;
2746 self.unit.get_mut(id).set(attr.name(), value);
2747 }
2748 }
2749 Ok(())
2750 }
2751
2752 pub fn convert_attribute_value(
2759 &mut self,
2760 read_unit: read::UnitRef<'_, R>,
2761 attr: &read::Attribute<R>,
2762 convert_address: &dyn Fn(u64) -> Option<Address>,
2763 ) -> ConvertResult<AttributeValue> {
2764 if attr.form() == constants::DW_FORM_implicit_const {
2765 let implicit_const_value = match attr.raw_value() {
2766 read::AttributeValue::Sdata(val) => val,
2767 _ => return Err(ConvertError::InvalidAttributeValue),
2768 };
2769 return Ok(AttributeValue::ImplicitConst(implicit_const_value));
2773 }
2774 Ok(match attr.value() {
2775 read::AttributeValue::Addr(val) => match (convert_address)(val) {
2776 Some(val) => AttributeValue::Address(val),
2777 None => return Err(ConvertError::InvalidAddress),
2778 },
2779 read::AttributeValue::Block(r) => AttributeValue::Block(r.to_slice()?.into()),
2780 read::AttributeValue::Data1(val) => AttributeValue::Data1(val),
2781 read::AttributeValue::Data2(val) => AttributeValue::Data2(val),
2782 read::AttributeValue::Data4(val) => AttributeValue::Data4(val),
2783 read::AttributeValue::Data8(val) => AttributeValue::Data8(val),
2784 read::AttributeValue::Data16(val) => AttributeValue::Data16(val),
2785 read::AttributeValue::Sdata(val) => AttributeValue::Sdata(val),
2786 read::AttributeValue::Udata(val) => AttributeValue::Udata(val),
2787 read::AttributeValue::Exprloc(expression) => {
2788 if attr.name() == constants::DW_AT_vtable_elem_location {
2789 let bytecode = expression.0.to_slice()?;
2790 if bytecode.first().copied() == Some(constants::DW_OP_constu.0) {
2791 return Ok(AttributeValue::Exprloc(Expression::raw(bytecode.to_vec())));
2796 }
2797 }
2798 let expression =
2799 self.convert_expression(read_unit, expression, convert_address)?;
2800 AttributeValue::Exprloc(expression)
2801 }
2802 read::AttributeValue::Flag(val) => {
2803 if attr.form() == constants::DW_FORM_flag_present {
2804 AttributeValue::FlagPresent
2805 } else {
2806 AttributeValue::Flag(val)
2807 }
2808 }
2809 read::AttributeValue::DebugAddrIndex(index) => {
2810 let val = read_unit.address(index)?;
2811 match convert_address(val) {
2812 Some(val) => AttributeValue::Address(val),
2813 None => return Err(ConvertError::InvalidAddress),
2814 }
2815 }
2816 read::AttributeValue::UnitRef(val) => {
2817 AttributeValue::UnitRef(self.convert_unit_ref(val)?)
2819 }
2820 read::AttributeValue::DebugInfoRef(val) => {
2821 AttributeValue::DebugInfoRef(self.convert_debug_info_ref(val)?)
2823 }
2824 read::AttributeValue::DebugInfoRefSup(val) => AttributeValue::DebugInfoRefSup(val),
2825 read::AttributeValue::DebugLineRef(val) => {
2826 if Some(val)
2828 != read_unit
2829 .line_program
2830 .as_ref()
2831 .map(|program| program.header().offset())
2832 {
2833 return Err(ConvertError::InvalidLineRef);
2834 };
2835 AttributeValue::LineProgramRef
2836 }
2837 read::AttributeValue::DebugMacinfoRef(val) => AttributeValue::DebugMacinfoRef(val),
2838 read::AttributeValue::DebugMacroRef(val) => AttributeValue::DebugMacroRef(val),
2839 read::AttributeValue::LocationListsRef(val) => {
2840 let loc_list = self.convert_location_list(read_unit, val, convert_address)?;
2841 let loc_id = self.unit.locations.add(loc_list);
2842 AttributeValue::LocationListRef(loc_id)
2843 }
2844 read::AttributeValue::DebugLocListsIndex(index) => {
2845 let offset = read_unit.locations_offset(index)?;
2846 let loc_list =
2847 self.convert_location_list(read_unit, offset, convert_address)?;
2848 let loc_id = self.unit.locations.add(loc_list);
2849 AttributeValue::LocationListRef(loc_id)
2850 }
2851 read::AttributeValue::RangeListsRef(offset) => {
2852 let offset = read_unit.ranges_offset_from_raw(offset);
2853 let range_list = self.convert_range_list(read_unit, offset, convert_address)?;
2854 let range_id = self.unit.ranges.add(range_list);
2855 AttributeValue::RangeListRef(range_id)
2856 }
2857 read::AttributeValue::DebugRngListsIndex(index) => {
2858 let offset = read_unit.ranges_offset(index)?;
2859 let range_list = self.convert_range_list(read_unit, offset, convert_address)?;
2860 let range_id = self.unit.ranges.add(range_list);
2861 AttributeValue::RangeListRef(range_id)
2862 }
2863 read::AttributeValue::DebugTypesRef(val) => AttributeValue::DebugTypesRef(val),
2864 read::AttributeValue::DebugStrRef(offset) => {
2865 let r = read_unit.string(offset)?;
2866 let id = self.strings.add(r.to_slice()?);
2867 AttributeValue::StringRef(id)
2868 }
2869 read::AttributeValue::DebugStrRefSup(val) => AttributeValue::DebugStrRefSup(val),
2870 read::AttributeValue::DebugStrOffsetsIndex(index) => {
2871 let offset = read_unit.string_offset(index)?;
2872 let r = read_unit.string(offset)?;
2873 let id = self.strings.add(r.to_slice()?);
2874 AttributeValue::StringRef(id)
2875 }
2876 read::AttributeValue::DebugLineStrRef(offset) => {
2877 let r = read_unit.line_string(offset)?;
2878 let id = self.line_strings.add(r.to_slice()?);
2879 AttributeValue::LineStringRef(id)
2880 }
2881 read::AttributeValue::String(r) => AttributeValue::String(r.to_slice()?.into()),
2882 read::AttributeValue::Encoding(val) => AttributeValue::Encoding(val),
2883 read::AttributeValue::DecimalSign(val) => AttributeValue::DecimalSign(val),
2884 read::AttributeValue::Endianity(val) => AttributeValue::Endianity(val),
2885 read::AttributeValue::Accessibility(val) => AttributeValue::Accessibility(val),
2886 read::AttributeValue::Visibility(val) => AttributeValue::Visibility(val),
2887 read::AttributeValue::Virtuality(val) => AttributeValue::Virtuality(val),
2888 read::AttributeValue::Language(val) => AttributeValue::Language(val),
2889 read::AttributeValue::AddressClass(val) => AttributeValue::AddressClass(val),
2890 read::AttributeValue::IdentifierCase(val) => AttributeValue::IdentifierCase(val),
2891 read::AttributeValue::CallingConvention(val) => {
2892 AttributeValue::CallingConvention(val)
2893 }
2894 read::AttributeValue::Inline(val) => AttributeValue::Inline(val),
2895 read::AttributeValue::Ordering(val) => AttributeValue::Ordering(val),
2896 read::AttributeValue::FileIndex(val) => {
2897 AttributeValue::FileIndex(self.convert_file_index(read_unit, val)?)
2898 }
2899 read::AttributeValue::DwoId(DwoId(val)) => AttributeValue::Udata(val),
2900 read::AttributeValue::SecOffset(_) => {
2902 return Err(ConvertError::InvalidAttributeValue);
2903 }
2904 read::AttributeValue::DebugAddrBase(_)
2907 | read::AttributeValue::DebugLocListsBase(_)
2908 | read::AttributeValue::DebugRngListsBase(_)
2909 | read::AttributeValue::DebugStrOffsetsBase(_) => {
2910 return Err(ConvertError::InvalidAttributeValue);
2911 }
2912 })
2913 }
2914
2915 pub fn convert_expression(
2919 &self,
2920 read_unit: read::UnitRef<'_, R>,
2921 expression: read::Expression<R>,
2922 convert_address: &dyn Fn(u64) -> Option<Address>,
2923 ) -> ConvertResult<Expression> {
2924 Expression::from(
2925 expression,
2926 read_unit.encoding(),
2927 Some(read_unit),
2928 convert_address,
2929 self,
2930 )
2931 }
2932
2933 pub fn convert_file_index(
2938 &self,
2939 read_unit: read::UnitRef<'_, R>,
2940 index: u64,
2941 ) -> ConvertResult<Option<FileId>> {
2942 if index == 0 && read_unit.encoding().version <= 4 {
2943 return Ok(None);
2944 }
2945 match self.line_program_files.get(index as usize) {
2946 Some(id) => Ok(Some(*id)),
2947 None => Err(ConvertError::InvalidFileIndex),
2948 }
2949 }
2950
2951 pub fn convert_location_list(
2955 &self,
2956 read_unit: read::UnitRef<'_, R>,
2957 offset: LocationListsOffset,
2958 convert_address: &dyn Fn(u64) -> Option<Address>,
2959 ) -> ConvertResult<LocationList> {
2960 let iter = read_unit.raw_locations(offset)?;
2961 LocationList::from(iter, read_unit, convert_address, self)
2962 }
2963
2964 pub fn convert_range_list(
2968 &self,
2969 read_unit: read::UnitRef<'_, R>,
2970 offset: RangeListsOffset,
2971 convert_address: &dyn Fn(u64) -> Option<Address>,
2972 ) -> ConvertResult<RangeList> {
2973 let iter = read_unit.raw_ranges(offset)?;
2974 RangeList::from(iter, read_unit, convert_address)
2975 }
2976
2977 pub fn convert_unit_ref(&self, entry: read::UnitOffset) -> ConvertResult<UnitEntryId> {
2982 if !entry.is_in_bounds(&self.read_unit) {
2983 return Err(ConvertError::InvalidUnitRef);
2984 }
2985 let id = self
2986 .entry_ids
2987 .get(&entry.to_unit_section_offset(&self.read_unit))
2988 .ok_or(ConvertError::InvalidUnitRef)?;
2989 Ok(id.1)
2990 }
2991
2992 pub fn convert_debug_info_ref(
2997 &self,
2998 entry: DebugInfoOffset,
2999 ) -> ConvertResult<DebugInfoRef> {
3000 let offset = entry
3002 .to_unit_section_offset(&self.read_unit)
3003 .ok_or(ConvertError::InvalidDebugInfoRef)?;
3004 let id = self
3005 .entry_ids
3006 .get(&offset)
3007 .ok_or(ConvertError::InvalidDebugInfoRef)?;
3008 Ok(DebugInfoRef::Entry(id.0, id.1))
3009 }
3010 }
3011
3012 #[derive(Debug)]
3018 #[non_exhaustive]
3019 pub struct ConvertUnitEntry<'a, R: Reader<Offset = usize>> {
3020 pub read_unit: read::UnitRef<'a, R>,
3024 pub read_entry: read::DebuggingInformationEntry<R>,
3026 pub sibling: bool,
3028 pub parent: Option<UnitEntryId>,
3033 }
3034
3035 impl<'a, R: Reader<Offset = usize>> Deref for ConvertUnitEntry<'a, R> {
3036 type Target = read::DebuggingInformationEntry<R>;
3037
3038 fn deref(&self) -> &Self::Target {
3039 &self.read_entry
3040 }
3041 }
3042
3043 impl<'a, R: Reader<Offset = usize>> ConvertUnitEntry<'a, R> {
3044 pub fn null(read_unit: read::UnitRef<'a, R>) -> Self {
3048 ConvertUnitEntry {
3049 read_unit,
3050 read_entry: read::DebuggingInformationEntry::null(),
3051 sibling: false,
3052 parent: None,
3053 }
3054 }
3055
3056 pub fn read(
3064 read_unit: read::UnitRef<'a, R>,
3065 offset: read::UnitOffset,
3066 ) -> ConvertResult<ConvertUnitEntry<'a, R>> {
3067 let mut read_entries = read_unit.entries_raw(Some(offset))?;
3068 let mut read_entry = read::DebuggingInformationEntry::null();
3069 if !read_entries.read_entry(&mut read_entry)? {
3070 return Err(read::Error::NoEntryAtGivenOffset(offset.0.into_u64()).into());
3072 };
3073
3074 let mut entry = ConvertUnitEntry {
3075 read_unit,
3076 read_entry,
3077 sibling: false,
3078 parent: None,
3079 };
3080 entry.filter_attributes();
3081 Ok(entry)
3082 }
3083
3084 fn filter_attributes(&mut self) {
3085 self.sibling = false;
3086 self.read_entry.attrs.retain(|attr| {
3087 match attr.name() {
3088 constants::DW_AT_sibling => {
3090 self.sibling = true;
3091 false
3092 }
3093 constants::DW_AT_str_offsets_base
3096 | constants::DW_AT_addr_base
3097 | constants::DW_AT_rnglists_base
3098 | constants::DW_AT_loclists_base
3099 | constants::DW_AT_dwo_name
3100 | constants::DW_AT_GNU_addr_base
3101 | constants::DW_AT_GNU_ranges_base
3102 | constants::DW_AT_GNU_dwo_name
3103 | constants::DW_AT_GNU_dwo_id => false,
3104 _ => true,
3105 }
3106 });
3107 }
3108 }
3109
3110 pub(crate) trait ConvertDebugInfoRef {
3111 fn convert_unit_ref(&self, entry: read::UnitOffset) -> ConvertResult<UnitEntryId>;
3112 fn convert_debug_info_ref(&self, entry: DebugInfoOffset) -> ConvertResult<DebugInfoRef>;
3113 }
3114
3115 impl<'a, R: Reader<Offset = usize>> ConvertDebugInfoRef for ConvertUnit<'a, R> {
3116 fn convert_unit_ref(&self, entry: read::UnitOffset) -> ConvertResult<UnitEntryId> {
3117 ConvertUnit::convert_unit_ref(self, entry)
3118 }
3119
3120 fn convert_debug_info_ref(&self, entry: DebugInfoOffset) -> ConvertResult<DebugInfoRef> {
3121 ConvertUnit::convert_debug_info_ref(self, entry)
3122 }
3123 }
3124
3125 pub(crate) struct NoConvertDebugInfoRef;
3126
3127 impl ConvertDebugInfoRef for NoConvertDebugInfoRef {
3128 fn convert_unit_ref(&self, _entry: read::UnitOffset) -> ConvertResult<UnitEntryId> {
3129 Err(ConvertError::InvalidUnitRef)
3130 }
3131
3132 fn convert_debug_info_ref(&self, _entry: DebugInfoOffset) -> ConvertResult<DebugInfoRef> {
3133 Err(ConvertError::InvalidDebugInfoRef)
3134 }
3135 }
3136}
3137
3138#[cfg(test)]
3139#[cfg(feature = "read")]
3140mod tests {
3141 use super::*;
3142 use crate::LittleEndian;
3143 use crate::common::LineEncoding;
3144 use crate::constants;
3145 use crate::read;
3146 use crate::write::{
3147 Dwarf, DwarfUnit, EndianVec, LineString, Location, LocationList, Range, RangeList,
3148 };
3149 use core::mem;
3150
3151 #[test]
3152 fn test_unit_table() {
3153 let mut dwarf = Dwarf::new();
3154 let unit_id1 = dwarf.units.add(Unit::new(
3155 Encoding {
3156 version: 4,
3157 address_size: 8,
3158 format: Format::Dwarf32,
3159 },
3160 LineProgram::none(),
3161 ));
3162 let unit2 = dwarf.units.add(Unit::new(
3163 Encoding {
3164 version: 2,
3165 address_size: 4,
3166 format: Format::Dwarf64,
3167 },
3168 LineProgram::none(),
3169 ));
3170 let unit3 = dwarf.units.add(Unit::new(
3171 Encoding {
3172 version: 5,
3173 address_size: 4,
3174 format: Format::Dwarf32,
3175 },
3176 LineProgram::none(),
3177 ));
3178 assert_eq!(dwarf.units.count(), 3);
3179 {
3180 let unit1 = dwarf.units.get_mut(unit_id1);
3181 assert_eq!(unit1.version(), 4);
3182 assert_eq!(unit1.address_size(), 8);
3183 assert_eq!(unit1.format(), Format::Dwarf32);
3184 assert_eq!(unit1.count(), 1);
3185
3186 let root_id = unit1.root();
3187 assert_eq!(root_id, UnitEntryId::new(unit1.base_id, 0));
3188 {
3189 let root = unit1.get_mut(root_id);
3190 assert_eq!(root.id(), root_id);
3191 assert!(root.parent().is_none());
3192 assert_eq!(root.tag(), constants::DW_TAG_compile_unit);
3193
3194 assert!(root.get(constants::DW_AT_producer).is_none());
3196 assert!(root.get_mut(constants::DW_AT_producer).is_none());
3197 let mut producer = AttributeValue::String(b"root"[..].into());
3198 root.set(constants::DW_AT_producer, producer.clone());
3199 assert_eq!(root.get(constants::DW_AT_producer), Some(&producer));
3200 assert_eq!(root.get_mut(constants::DW_AT_producer), Some(&mut producer));
3201
3202 let mut attrs = root.attrs();
3204 let attr = attrs.next().unwrap();
3205 assert_eq!(attr.name(), constants::DW_AT_producer);
3206 assert_eq!(attr.get(), &producer);
3207 assert!(attrs.next().is_none());
3208 }
3209
3210 let child1 = unit1.add(root_id, constants::DW_TAG_subprogram);
3211 assert_eq!(child1, UnitEntryId::new(unit1.base_id, 1));
3212 {
3213 let child1 = unit1.get_mut(child1);
3214 assert_eq!(child1.parent(), Some(root_id));
3215
3216 let tmp = AttributeValue::String(b"tmp"[..].into());
3217 child1.set(constants::DW_AT_name, tmp.clone());
3218 assert_eq!(child1.get(constants::DW_AT_name), Some(&tmp));
3219
3220 let name = AttributeValue::StringRef(dwarf.strings.add(&b"child1"[..]));
3222 {
3223 let attr = child1.attrs_mut().next().unwrap();
3224 assert_eq!(attr.name(), constants::DW_AT_name);
3225 attr.set(name.clone());
3226 }
3227 assert_eq!(child1.get(constants::DW_AT_name), Some(&name));
3228 }
3229
3230 let child2 = unit1.add(root_id, constants::DW_TAG_subprogram);
3231 assert_eq!(child2, UnitEntryId::new(unit1.base_id, 2));
3232 {
3233 let child2 = unit1.get_mut(child2);
3234 assert_eq!(child2.parent(), Some(root_id));
3235
3236 let tmp = AttributeValue::String(b"tmp"[..].into());
3237 child2.set(constants::DW_AT_name, tmp.clone());
3238 assert_eq!(child2.get(constants::DW_AT_name), Some(&tmp));
3239
3240 let name = AttributeValue::StringRef(dwarf.strings.add(&b"child2"[..]));
3242 child2.set(constants::DW_AT_name, name.clone());
3243 assert_eq!(child2.get(constants::DW_AT_name), Some(&name));
3244 }
3245
3246 {
3247 let root = unit1.get(root_id);
3248 assert_eq!(
3249 root.children().cloned().collect::<Vec<_>>(),
3250 vec![child1, child2]
3251 );
3252 }
3253 }
3254 {
3255 let unit2 = dwarf.units.get(unit2);
3256 assert_eq!(unit2.version(), 2);
3257 assert_eq!(unit2.address_size(), 4);
3258 assert_eq!(unit2.format(), Format::Dwarf64);
3259 assert_eq!(unit2.count(), 1);
3260
3261 let root = unit2.root();
3262 assert_eq!(root, UnitEntryId::new(unit2.base_id, 0));
3263 let root = unit2.get(root);
3264 assert_eq!(root.id(), UnitEntryId::new(unit2.base_id, 0));
3265 assert!(root.parent().is_none());
3266 assert_eq!(root.tag(), constants::DW_TAG_compile_unit);
3267 }
3268
3269 let mut sections = Sections::new(EndianVec::new(LittleEndian));
3270 dwarf.write(&mut sections).unwrap();
3271
3272 let read_dwarf = sections.read(LittleEndian);
3273 let mut read_units = read_dwarf.units();
3274
3275 {
3276 let read_unit1 = read_units.next().unwrap().unwrap();
3277 let unit1 = dwarf.units.get(unit_id1);
3278 assert_eq!(unit1.version(), read_unit1.version());
3279 assert_eq!(unit1.address_size(), read_unit1.address_size());
3280 assert_eq!(unit1.format(), read_unit1.format());
3281
3282 let read_unit1 = read_dwarf.unit(read_unit1).unwrap();
3283 let mut read_entries = read_unit1.entries();
3284
3285 let root = unit1.get(unit1.root());
3286 {
3287 let read_root = read_entries.next_dfs().unwrap().unwrap();
3288 assert_eq!(read_root.depth(), 0);
3289 assert_eq!(root.tag(), read_root.tag());
3290 assert!(read_root.has_children());
3291
3292 let producer = match root.get(constants::DW_AT_producer).unwrap() {
3293 AttributeValue::String(producer) => &**producer,
3294 otherwise => panic!("unexpected {:?}", otherwise),
3295 };
3296 assert_eq!(producer, b"root");
3297 let read_producer = read_root.attr_value(constants::DW_AT_producer).unwrap();
3298 assert_eq!(
3299 read_dwarf
3300 .attr_string(&read_unit1, read_producer)
3301 .unwrap()
3302 .slice(),
3303 producer
3304 );
3305 }
3306
3307 let mut children = root.children().cloned();
3308
3309 {
3310 let child = children.next().unwrap();
3311 assert_eq!(child, UnitEntryId::new(unit1.base_id, 1));
3312 let child = unit1.get(child);
3313 let read_child = read_entries.next_dfs().unwrap().unwrap();
3314 assert_eq!(read_child.depth(), 1);
3315 assert_eq!(child.tag(), read_child.tag());
3316 assert!(!read_child.has_children());
3317
3318 let name = match child.get(constants::DW_AT_name).unwrap() {
3319 AttributeValue::StringRef(name) => *name,
3320 otherwise => panic!("unexpected {:?}", otherwise),
3321 };
3322 let name = dwarf.strings.get(name);
3323 assert_eq!(name, b"child1");
3324 let read_name = read_child.attr_value(constants::DW_AT_name).unwrap();
3325 assert_eq!(
3326 read_dwarf
3327 .attr_string(&read_unit1, read_name)
3328 .unwrap()
3329 .slice(),
3330 name
3331 );
3332 }
3333
3334 {
3335 let child = children.next().unwrap();
3336 assert_eq!(child, UnitEntryId::new(unit1.base_id, 2));
3337 let child = unit1.get(child);
3338 let read_child = read_entries.next_dfs().unwrap().unwrap();
3339 assert_eq!(read_child.depth(), 1);
3340 assert_eq!(child.tag(), read_child.tag());
3341 assert!(!read_child.has_children());
3342
3343 let name = match child.get(constants::DW_AT_name).unwrap() {
3344 AttributeValue::StringRef(name) => *name,
3345 otherwise => panic!("unexpected {:?}", otherwise),
3346 };
3347 let name = dwarf.strings.get(name);
3348 assert_eq!(name, b"child2");
3349 let read_name = read_child.attr_value(constants::DW_AT_name).unwrap();
3350 assert_eq!(
3351 read_dwarf
3352 .attr_string(&read_unit1, read_name)
3353 .unwrap()
3354 .slice(),
3355 name
3356 );
3357 }
3358
3359 assert!(read_entries.next_dfs().unwrap().is_none());
3360 }
3361
3362 {
3363 let read_unit2 = read_units.next().unwrap().unwrap();
3364 let unit2 = dwarf.units.get(unit2);
3365 assert_eq!(unit2.version(), read_unit2.version());
3366 assert_eq!(unit2.address_size(), read_unit2.address_size());
3367 assert_eq!(unit2.format(), read_unit2.format());
3368
3369 let abbrevs = read_dwarf.abbreviations(&read_unit2).unwrap();
3370 let mut read_entries = read_unit2.entries(&abbrevs);
3371
3372 {
3373 let root = unit2.get(unit2.root());
3374 let read_root = read_entries.next_dfs().unwrap().unwrap();
3375 assert_eq!(read_root.depth(), 0);
3376 assert_eq!(root.tag(), read_root.tag());
3377 assert!(!read_root.has_children());
3378 }
3379
3380 assert!(read_entries.next_dfs().unwrap().is_none());
3381 }
3382
3383 {
3384 let read_unit3 = read_units.next().unwrap().unwrap();
3385 let unit3 = dwarf.units.get(unit3);
3386 assert_eq!(unit3.version(), read_unit3.version());
3387 assert_eq!(unit3.address_size(), read_unit3.address_size());
3388 assert_eq!(unit3.format(), read_unit3.format());
3389
3390 let abbrevs = read_dwarf.abbreviations(&read_unit3).unwrap();
3391 let mut read_entries = read_unit3.entries(&abbrevs);
3392
3393 {
3394 let root = unit3.get(unit3.root());
3395 let read_root = read_entries.next_dfs().unwrap().unwrap();
3396 assert_eq!(read_root.depth(), 0);
3397 assert_eq!(root.tag(), read_root.tag());
3398 assert!(!read_root.has_children());
3399 }
3400
3401 assert!(read_entries.next_dfs().unwrap().is_none());
3402 }
3403
3404 assert!(read_units.next().unwrap().is_none());
3405
3406 let convert_dwarf =
3407 Dwarf::from(&read_dwarf, &|address| Some(Address::Constant(address))).unwrap();
3408 assert_eq!(convert_dwarf.units.count(), dwarf.units.count());
3409
3410 for i in 0..convert_dwarf.units.count() {
3411 let unit_id = dwarf.units.id(i);
3412 let unit = dwarf.units.get(unit_id);
3413 let convert_unit_id = convert_dwarf.units.id(i);
3414 let convert_unit = convert_dwarf.units.get(convert_unit_id);
3415 assert_eq!(convert_unit.version(), unit.version());
3416 assert_eq!(convert_unit.address_size(), unit.address_size());
3417 assert_eq!(convert_unit.format(), unit.format());
3418 assert_eq!(convert_unit.count(), unit.count());
3419
3420 let root = unit.get(unit.root());
3421 let convert_root = convert_unit.get(convert_unit.root());
3422 assert_eq!(convert_root.tag(), root.tag());
3423 for (convert_attr, attr) in convert_root.attrs().zip(root.attrs()) {
3424 assert_eq!(convert_attr, attr);
3425 }
3426 }
3427 }
3428
3429 #[test]
3430 fn test_attribute_value() {
3431 let string_data = "string data";
3432 let line_string_data = "line string data";
3433
3434 let data = vec![1, 2, 3, 4];
3435 let read_data = read::EndianSlice::new(&[1, 2, 3, 4], LittleEndian);
3436
3437 let mut expression = Expression::new();
3438 expression.op_constu(57);
3439 let read_expression = read::Expression(read::EndianSlice::new(
3440 &[constants::DW_OP_constu.0, 57],
3441 LittleEndian,
3442 ));
3443
3444 let range = RangeList(vec![Range::StartEnd {
3445 begin: Address::Constant(0x1234),
3446 end: Address::Constant(0x2345),
3447 }]);
3448
3449 let location = LocationList(vec![Location::StartEnd {
3450 begin: Address::Constant(0x1234),
3451 end: Address::Constant(0x2345),
3452 data: expression.clone(),
3453 }]);
3454
3455 for &version in &[2, 3, 4, 5] {
3456 for &address_size in &[4, 8] {
3457 for &format in &[Format::Dwarf32, Format::Dwarf64] {
3458 let encoding = Encoding {
3459 format,
3460 version,
3461 address_size,
3462 };
3463
3464 let mut dwarf = Dwarf::new();
3465 let unit = dwarf.units.add(Unit::new(encoding, LineProgram::none()));
3466 let unit = dwarf.units.get_mut(unit);
3467 let loc_id = unit.locations.add(location.clone());
3468 let range_id = unit.ranges.add(range.clone());
3469 dwarf.strings.add("dummy string");
3471 let string_id = dwarf.strings.add(string_data);
3472 dwarf.line_strings.add("dummy line string");
3473 let line_string_id = dwarf.line_strings.add(line_string_data);
3474
3475 let mut attributes = vec![
3476 (
3477 constants::DW_AT_name,
3478 AttributeValue::Address(Address::Constant(0x1234)),
3479 read::AttributeValue::Addr(0x1234),
3480 ),
3481 (
3482 constants::DW_AT_name,
3483 AttributeValue::Block(data.clone()),
3484 read::AttributeValue::Block(read_data),
3485 ),
3486 (
3487 constants::DW_AT_name,
3488 AttributeValue::Data1(0x12),
3489 read::AttributeValue::Data1(0x12),
3490 ),
3491 (
3492 constants::DW_AT_name,
3493 AttributeValue::Data2(0x1234),
3494 read::AttributeValue::Data2(0x1234),
3495 ),
3496 (
3497 constants::DW_AT_name,
3498 AttributeValue::Data4(0x1234),
3499 read::AttributeValue::Data4(0x1234),
3500 ),
3501 (
3502 constants::DW_AT_name,
3503 AttributeValue::Data8(0x1234),
3504 read::AttributeValue::Data8(0x1234),
3505 ),
3506 (
3507 constants::DW_AT_name,
3508 AttributeValue::Data16(0x1234),
3509 read::AttributeValue::Data16(0x1234),
3510 ),
3511 (
3512 constants::DW_AT_name,
3513 AttributeValue::Sdata(0x1234),
3514 read::AttributeValue::Sdata(0x1234),
3515 ),
3516 (
3517 constants::DW_AT_name,
3518 AttributeValue::Udata(0x1234),
3519 read::AttributeValue::Udata(0x1234),
3520 ),
3521 (
3522 constants::DW_AT_name,
3523 AttributeValue::Flag(false),
3524 read::AttributeValue::Flag(false),
3525 ),
3526 (
3527 constants::DW_AT_name,
3528 AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x1234)),
3529 read::AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x1234)),
3530 ),
3531 (
3532 constants::DW_AT_macro_info,
3533 AttributeValue::DebugMacinfoRef(DebugMacinfoOffset(0x1234)),
3534 read::AttributeValue::SecOffset(0x1234),
3535 ),
3536 (
3537 constants::DW_AT_macros,
3538 AttributeValue::DebugMacroRef(DebugMacroOffset(0x1234)),
3539 read::AttributeValue::SecOffset(0x1234),
3540 ),
3541 (
3542 constants::DW_AT_name,
3543 AttributeValue::DebugTypesRef(DebugTypeSignature(0x1234)),
3544 read::AttributeValue::DebugTypesRef(DebugTypeSignature(0x1234)),
3545 ),
3546 (
3547 constants::DW_AT_name,
3548 AttributeValue::DebugStrRefSup(DebugStrOffset(0x1234)),
3549 read::AttributeValue::DebugStrRefSup(DebugStrOffset(0x1234)),
3550 ),
3551 (
3552 constants::DW_AT_name,
3553 AttributeValue::String(data.clone()),
3554 read::AttributeValue::String(read_data),
3555 ),
3556 (
3557 constants::DW_AT_encoding,
3558 AttributeValue::Encoding(constants::DwAte(0x12)),
3559 read::AttributeValue::Udata(0x12),
3560 ),
3561 (
3562 constants::DW_AT_decimal_sign,
3563 AttributeValue::DecimalSign(constants::DwDs(0x12)),
3564 read::AttributeValue::Udata(0x12),
3565 ),
3566 (
3567 constants::DW_AT_endianity,
3568 AttributeValue::Endianity(constants::DwEnd(0x12)),
3569 read::AttributeValue::Udata(0x12),
3570 ),
3571 (
3572 constants::DW_AT_accessibility,
3573 AttributeValue::Accessibility(constants::DwAccess(0x12)),
3574 read::AttributeValue::Udata(0x12),
3575 ),
3576 (
3577 constants::DW_AT_visibility,
3578 AttributeValue::Visibility(constants::DwVis(0x12)),
3579 read::AttributeValue::Udata(0x12),
3580 ),
3581 (
3582 constants::DW_AT_virtuality,
3583 AttributeValue::Virtuality(constants::DwVirtuality(0x12)),
3584 read::AttributeValue::Udata(0x12),
3585 ),
3586 (
3587 constants::DW_AT_language,
3588 AttributeValue::Language(constants::DwLang(0x12)),
3589 read::AttributeValue::Udata(0x12),
3590 ),
3591 (
3592 constants::DW_AT_address_class,
3593 AttributeValue::AddressClass(constants::DwAddr(0x12)),
3594 read::AttributeValue::Udata(0x12),
3595 ),
3596 (
3597 constants::DW_AT_identifier_case,
3598 AttributeValue::IdentifierCase(constants::DwId(0x12)),
3599 read::AttributeValue::Udata(0x12),
3600 ),
3601 (
3602 constants::DW_AT_calling_convention,
3603 AttributeValue::CallingConvention(constants::DwCc(0x12)),
3604 read::AttributeValue::Udata(0x12),
3605 ),
3606 (
3607 constants::DW_AT_ordering,
3608 AttributeValue::Ordering(constants::DwOrd(0x12)),
3609 read::AttributeValue::Udata(0x12),
3610 ),
3611 (
3612 constants::DW_AT_inline,
3613 AttributeValue::Inline(constants::DwInl(0x12)),
3614 read::AttributeValue::Udata(0x12),
3615 ),
3616 ];
3617 let mut attributes2 = Vec::new();
3618 if version >= 4 {
3619 attributes.push((
3620 constants::DW_AT_location,
3621 AttributeValue::Exprloc(expression.clone()),
3622 read::AttributeValue::Exprloc(read_expression),
3623 ));
3624 } else {
3625 attributes.push((
3626 constants::DW_AT_location,
3627 AttributeValue::Exprloc(expression.clone()),
3628 read::AttributeValue::Block(read_expression.0),
3629 ));
3630 }
3631 if version >= 4 {
3632 attributes.push((
3633 constants::DW_AT_name,
3634 AttributeValue::FlagPresent,
3635 read::AttributeValue::Flag(true),
3636 ));
3637 } else {
3638 attributes2.push((
3639 constants::DW_AT_name,
3640 AttributeValue::FlagPresent,
3641 read::AttributeValue::Flag(true),
3642 AttributeValue::Flag(true),
3643 ));
3644 };
3645 if version >= 5 {
3646 attributes.push((
3647 constants::DW_AT_language,
3648 AttributeValue::ImplicitConst(0x12),
3649 read::AttributeValue::Sdata(0x12),
3650 ));
3651 } else {
3652 attributes2.push((
3653 constants::DW_AT_language,
3654 AttributeValue::ImplicitConst(0x12),
3655 read::AttributeValue::Sdata(0x12),
3656 AttributeValue::Language(constants::DwLang(0x12)),
3657 ));
3658 }
3659
3660 let mut add_attribute = |name, value| {
3661 let entry_id = unit.add(unit.root(), constants::DW_TAG_subprogram);
3662 let entry = unit.get_mut(entry_id);
3663 entry.set(name, value);
3664 };
3665 for (name, value, _) in &attributes {
3666 add_attribute(*name, value.clone());
3667 }
3668 for (name, value, _, _) in &attributes2 {
3669 add_attribute(*name, value.clone());
3670 }
3671 add_attribute(
3672 constants::DW_AT_location,
3673 AttributeValue::LocationListRef(loc_id),
3674 );
3675 add_attribute(
3676 constants::DW_AT_ranges,
3677 AttributeValue::RangeListRef(range_id),
3678 );
3679 add_attribute(constants::DW_AT_name, AttributeValue::StringRef(string_id));
3680 add_attribute(
3681 constants::DW_AT_name,
3682 AttributeValue::LineStringRef(line_string_id),
3683 );
3684
3685 let mut sections = Sections::new(EndianVec::new(LittleEndian));
3686 dwarf.write(&mut sections).unwrap();
3687
3688 let read_dwarf = sections.read(LittleEndian);
3689 let mut read_units = read_dwarf.units();
3690 let read_unit = read_units.next().unwrap().unwrap();
3691 let read_unit = read_dwarf.unit(read_unit).unwrap();
3692 let read_unit = read_unit.unit_ref(&read_dwarf);
3693 let mut read_entries = read_unit.entries();
3694 let _root = read_entries.next_dfs().unwrap().unwrap();
3695
3696 let mut get_attribute = |name| {
3697 let entry = read_entries.next_dfs().unwrap().unwrap();
3698 *entry.attr(name).unwrap()
3699 };
3700 for (name, _, expect_value) in &attributes {
3701 let read_value = &get_attribute(*name).raw_value();
3702 let read_value = unsafe {
3705 mem::transmute::<
3706 &read::AttributeValue<read::EndianSlice<'_, LittleEndian>>,
3707 &read::AttributeValue<read::EndianSlice<'_, LittleEndian>>,
3708 >(read_value)
3709 };
3710 assert_eq!(read_value, expect_value);
3711 }
3712 for (name, _, expect_value, _) in &attributes2 {
3713 let read_value = &get_attribute(*name).raw_value();
3714 let read_value = unsafe {
3717 mem::transmute::<
3718 &read::AttributeValue<read::EndianSlice<'_, LittleEndian>>,
3719 &read::AttributeValue<read::EndianSlice<'_, LittleEndian>>,
3720 >(read_value)
3721 };
3722 assert_eq!(read_value, expect_value);
3723 }
3724
3725 let read_attr = get_attribute(constants::DW_AT_location).value();
3726 let read::AttributeValue::LocationListsRef(read_loc_offset) = read_attr else {
3727 panic!("unexpected {:?}", read_attr);
3728 };
3729 let mut read_locations = read_unit.locations(read_loc_offset).unwrap();
3730 let read_location = read_locations.next().unwrap().unwrap();
3731 assert_eq!(read_location.range.begin, 0x1234);
3732 assert_eq!(read_location.range.end, 0x2345);
3733 assert_eq!(read_location.data, read_expression);
3734
3735 let read_attr = get_attribute(constants::DW_AT_ranges).value();
3736 let read::AttributeValue::RangeListsRef(read_range_offset) = read_attr else {
3737 panic!("unexpected {:?}", read_attr);
3738 };
3739 let read_range_offset = read_unit.ranges_offset_from_raw(read_range_offset);
3740 let mut read_ranges = read_unit.ranges(read_range_offset).unwrap();
3741 let read_range = read_ranges.next().unwrap().unwrap();
3742 assert_eq!(read_range.begin, 0x1234);
3743 assert_eq!(read_range.end, 0x2345);
3744
3745 let read_string = get_attribute(constants::DW_AT_name).raw_value();
3746 let read::AttributeValue::DebugStrRef(read_string_offset) = read_string else {
3747 panic!("unexpected {:?}", read_string);
3748 };
3749 assert_eq!(
3750 read_dwarf.string(read_string_offset).unwrap().slice(),
3751 string_data.as_bytes()
3752 );
3753
3754 let read_line_string = get_attribute(constants::DW_AT_name).raw_value();
3755 let read::AttributeValue::DebugLineStrRef(read_line_string_offset) =
3756 read_line_string
3757 else {
3758 panic!("unexpected {:?}", read_line_string);
3759 };
3760 assert_eq!(
3761 read_dwarf
3762 .line_string(read_line_string_offset)
3763 .unwrap()
3764 .slice(),
3765 line_string_data.as_bytes()
3766 );
3767
3768 let convert_dwarf =
3769 Dwarf::from(&read_dwarf, &|address| Some(Address::Constant(address)))
3770 .unwrap();
3771 let convert_unit = convert_dwarf.units.get(convert_dwarf.units.id(0));
3772 let convert_root = convert_unit.get(convert_unit.root());
3773 let mut convert_entries = convert_root.children();
3774
3775 let mut get_convert_attr = |name| {
3776 let convert_entry = convert_unit.get(*convert_entries.next().unwrap());
3777 convert_entry.get(name).unwrap()
3778 };
3779 for (name, attr, _) in &attributes {
3780 let convert_attr = get_convert_attr(*name);
3781 assert_eq!(convert_attr, attr);
3782 }
3783 for (name, _, _, attr) in &attributes2 {
3784 let convert_attr = get_convert_attr(*name);
3785 assert_eq!(convert_attr, attr);
3786 }
3787
3788 let convert_attr = get_convert_attr(constants::DW_AT_location);
3789 let AttributeValue::LocationListRef(convert_loc_id) = convert_attr else {
3790 panic!("unexpected {:?}", convert_attr);
3791 };
3792 let convert_location = convert_unit.locations.get(*convert_loc_id);
3793 assert_eq!(*convert_location, location);
3794
3795 let convert_attr = get_convert_attr(constants::DW_AT_ranges);
3796 let AttributeValue::RangeListRef(convert_range_id) = convert_attr else {
3797 panic!("unexpected {:?}", convert_attr);
3798 };
3799 let convert_range = convert_unit.ranges.get(*convert_range_id);
3800 assert_eq!(*convert_range, range);
3801
3802 let convert_attr = get_convert_attr(constants::DW_AT_name);
3803 let AttributeValue::StringRef(convert_string_id) = convert_attr else {
3804 panic!("unexpected {:?}", convert_attr);
3805 };
3806 let convert_string = convert_dwarf.strings.get(*convert_string_id);
3807 assert_eq!(convert_string, string_data.as_bytes());
3808
3809 let convert_attr = get_convert_attr(constants::DW_AT_name);
3810 let AttributeValue::LineStringRef(convert_line_string_id) = convert_attr else {
3811 panic!("unexpected {:?}", convert_attr);
3812 };
3813 let convert_line_string =
3814 convert_dwarf.line_strings.get(*convert_line_string_id);
3815 assert_eq!(convert_line_string, line_string_data.as_bytes());
3816 }
3817 }
3818 }
3819 }
3820
3821 #[test]
3822 fn test_unit_ref() {
3823 let mut dwarf = Dwarf::new();
3824 let unit_id1 = dwarf.units.add(Unit::new(
3825 Encoding {
3826 version: 4,
3827 address_size: 8,
3828 format: Format::Dwarf32,
3829 },
3830 LineProgram::none(),
3831 ));
3832 assert_eq!(unit_id1, dwarf.units.id(0));
3833 let unit_id2 = dwarf.units.add(Unit::new(
3834 Encoding {
3835 version: 2,
3836 address_size: 4,
3837 format: Format::Dwarf64,
3838 },
3839 LineProgram::none(),
3840 ));
3841 assert_eq!(unit_id2, dwarf.units.id(1));
3842 let unit1_child1 = UnitEntryId::new(dwarf.units.get(unit_id1).base_id, 1);
3843 let unit1_child2 = UnitEntryId::new(dwarf.units.get(unit_id1).base_id, 2);
3844 let unit2_child1 = UnitEntryId::new(dwarf.units.get(unit_id2).base_id, 1);
3845 let unit2_child2 = UnitEntryId::new(dwarf.units.get(unit_id2).base_id, 2);
3846 {
3847 let unit1 = dwarf.units.get_mut(unit_id1);
3848 let root = unit1.root();
3849 let child_id1 = unit1.add(root, constants::DW_TAG_subprogram);
3850 assert_eq!(child_id1, unit1_child1);
3851 let child_id2 = unit1.add(root, constants::DW_TAG_subprogram);
3852 assert_eq!(child_id2, unit1_child2);
3853 {
3854 let child1 = unit1.get_mut(child_id1);
3855 child1.set(constants::DW_AT_type, AttributeValue::UnitRef(child_id2));
3856 }
3857 {
3858 let child2 = unit1.get_mut(child_id2);
3859 child2.set(
3860 constants::DW_AT_type,
3861 AttributeValue::DebugInfoRef(DebugInfoRef::Entry(unit_id2, unit2_child1)),
3862 );
3863 }
3864 }
3865 {
3866 let unit2 = dwarf.units.get_mut(unit_id2);
3867 let root = unit2.root();
3868 let child_id1 = unit2.add(root, constants::DW_TAG_subprogram);
3869 assert_eq!(child_id1, unit2_child1);
3870 let child_id2 = unit2.add(root, constants::DW_TAG_subprogram);
3871 assert_eq!(child_id2, unit2_child2);
3872 {
3873 let child1 = unit2.get_mut(child_id1);
3874 child1.set(constants::DW_AT_type, AttributeValue::UnitRef(child_id2));
3875 }
3876 {
3877 let child2 = unit2.get_mut(child_id2);
3878 child2.set(
3879 constants::DW_AT_type,
3880 AttributeValue::DebugInfoRef(DebugInfoRef::Entry(unit_id1, unit1_child1)),
3881 );
3882 }
3883 }
3884
3885 let mut sections = Sections::new(EndianVec::new(LittleEndian));
3886 dwarf.write(&mut sections).unwrap();
3887
3888 let read_dwarf = sections.read(LittleEndian);
3889 let mut read_units = read_dwarf.units();
3890
3891 let read_unit = read_units.next().unwrap().unwrap();
3892 let abbrevs = read_dwarf.abbreviations(&read_unit).unwrap();
3893 let mut read_entries = read_unit.entries(&abbrevs);
3894 let _root = read_entries.next_dfs().unwrap().unwrap();
3895 let entry = read_entries.next_dfs().unwrap().unwrap();
3896 let read_unit1_child1_attr = entry.attr_value(constants::DW_AT_type);
3897 let read_unit1_child1_section_offset =
3898 entry.offset().to_debug_info_offset(&read_unit).unwrap();
3899 let entry = read_entries.next_dfs().unwrap().unwrap();
3900 let read_unit1_child2_attr = entry.attr_value(constants::DW_AT_type);
3901 let read_unit1_child2_offset = entry.offset();
3902
3903 let read_unit = read_units.next().unwrap().unwrap();
3904 let abbrevs = read_dwarf.abbreviations(&read_unit).unwrap();
3905 let mut read_entries = read_unit.entries(&abbrevs);
3906 let _root = read_entries.next_dfs().unwrap().unwrap();
3907 let entry = read_entries.next_dfs().unwrap().unwrap();
3908 let read_unit2_child1_attr = entry.attr_value(constants::DW_AT_type);
3909 let read_unit2_child1_section_offset =
3910 entry.offset().to_debug_info_offset(&read_unit).unwrap();
3911 let entry = read_entries.next_dfs().unwrap().unwrap();
3912 let read_unit2_child2_attr = entry.attr_value(constants::DW_AT_type);
3913 let read_unit2_child2_offset = entry.offset();
3914
3915 assert_eq!(
3916 read_unit1_child1_attr,
3917 Some(read::AttributeValue::UnitRef(read_unit1_child2_offset))
3918 );
3919 assert_eq!(
3920 read_unit1_child2_attr,
3921 Some(read::AttributeValue::DebugInfoRef(
3922 read_unit2_child1_section_offset
3923 ))
3924 );
3925 assert_eq!(
3926 read_unit2_child1_attr,
3927 Some(read::AttributeValue::UnitRef(read_unit2_child2_offset))
3928 );
3929 assert_eq!(
3930 read_unit2_child2_attr,
3931 Some(read::AttributeValue::DebugInfoRef(
3932 read_unit1_child1_section_offset
3933 ))
3934 );
3935
3936 let convert_dwarf =
3937 Dwarf::from(&read_dwarf, &|address| Some(Address::Constant(address))).unwrap();
3938 let convert_units = &convert_dwarf.units;
3939 assert_eq!(convert_units.count(), dwarf.units.count());
3940
3941 for i in 0..convert_units.count() {
3942 let unit = dwarf.units.get(dwarf.units.id(i));
3943 let convert_unit = convert_units.get(convert_units.id(i));
3944 assert_eq!(convert_unit.version(), unit.version());
3945 assert_eq!(convert_unit.address_size(), unit.address_size());
3946 assert_eq!(convert_unit.format(), unit.format());
3947 assert_eq!(convert_unit.count(), unit.count());
3948
3949 let root = unit.get(unit.root());
3950 let convert_root = convert_unit.get(convert_unit.root());
3951 assert_eq!(convert_root.tag(), root.tag());
3952 for (convert_attr, attr) in convert_root.attrs().zip(root.attrs()) {
3953 assert_eq!(convert_attr, attr);
3954 }
3955
3956 let child1 = unit.get(UnitEntryId::new(unit.base_id, 1));
3957 let convert_child1 = convert_unit.get(UnitEntryId::new(convert_unit.base_id, 1));
3958 assert_eq!(convert_child1.tag(), child1.tag());
3959 for (convert_attr, attr) in convert_child1.attrs().zip(child1.attrs()) {
3960 assert_eq!(convert_attr.name, attr.name);
3961 match (convert_attr.value.clone(), attr.value.clone()) {
3962 (
3963 AttributeValue::DebugInfoRef(DebugInfoRef::Entry(
3964 convert_unit,
3965 convert_entry,
3966 )),
3967 AttributeValue::DebugInfoRef(DebugInfoRef::Entry(unit, entry)),
3968 ) => {
3969 assert_eq!(convert_unit.index, unit.index);
3970 assert_eq!(convert_entry.index, entry.index);
3971 }
3972 (AttributeValue::UnitRef(convert_id), AttributeValue::UnitRef(id)) => {
3973 assert_eq!(convert_id.index, id.index);
3974 }
3975 (convert_value, value) => assert_eq!(convert_value, value),
3976 }
3977 }
3978
3979 let child2 = unit.get(UnitEntryId::new(unit.base_id, 2));
3980 let convert_child2 = convert_unit.get(UnitEntryId::new(convert_unit.base_id, 2));
3981 assert_eq!(convert_child2.tag(), child2.tag());
3982 for (convert_attr, attr) in convert_child2.attrs().zip(child2.attrs()) {
3983 assert_eq!(convert_attr.name, attr.name);
3984 match (convert_attr.value.clone(), attr.value.clone()) {
3985 (
3986 AttributeValue::DebugInfoRef(DebugInfoRef::Entry(
3987 convert_unit,
3988 convert_entry,
3989 )),
3990 AttributeValue::DebugInfoRef(DebugInfoRef::Entry(unit, entry)),
3991 ) => {
3992 assert_eq!(convert_unit.index, unit.index);
3993 assert_eq!(convert_entry.index, entry.index);
3994 }
3995 (AttributeValue::UnitRef(convert_id), AttributeValue::UnitRef(id)) => {
3996 assert_eq!(convert_id.index, id.index);
3997 }
3998 (convert_value, value) => assert_eq!(convert_value, value),
3999 }
4000 }
4001 }
4002 }
4003
4004 #[test]
4005 fn test_sibling() {
4006 fn add_child(
4007 unit: &mut Unit,
4008 parent: UnitEntryId,
4009 tag: constants::DwTag,
4010 name: &str,
4011 ) -> UnitEntryId {
4012 let id = unit.add(parent, tag);
4013 let child = unit.get_mut(id);
4014 child.set(constants::DW_AT_name, AttributeValue::String(name.into()));
4015 child.set_sibling(true);
4016 id
4017 }
4018
4019 fn add_children(unit: &mut Unit) {
4020 let root = unit.root();
4021 let child1 = add_child(unit, root, constants::DW_TAG_subprogram, "child1");
4022 add_child(unit, child1, constants::DW_TAG_variable, "grandchild1");
4023 add_child(unit, root, constants::DW_TAG_subprogram, "child2");
4024 add_child(unit, root, constants::DW_TAG_subprogram, "child3");
4025 }
4026
4027 fn next_child<R: read::Reader<Offset = usize>>(
4028 entries: &mut read::EntriesCursor<'_, R>,
4029 ) -> (read::UnitOffset, Option<read::UnitOffset>) {
4030 let entry = entries.next_dfs().unwrap().unwrap();
4031 let offset = entry.offset();
4032 let sibling = entry
4033 .attr_value(constants::DW_AT_sibling)
4034 .map(|attr| match attr {
4035 read::AttributeValue::UnitRef(offset) => offset,
4036 _ => panic!("bad sibling value"),
4037 });
4038 (offset, sibling)
4039 }
4040
4041 fn check_sibling<R: read::Reader<Offset = usize>>(
4042 unit: read::UnitHeader<R>,
4043 dwarf: &read::Dwarf<R>,
4044 ) {
4045 let unit = dwarf.unit(unit).unwrap();
4046 let mut entries = unit.entries();
4047 entries.next_dfs().unwrap().unwrap();
4049 let (_, sibling1) = next_child(&mut entries);
4051 entries.next_dfs().unwrap().unwrap();
4053 let (offset2, sibling2) = next_child(&mut entries);
4055 let (_, _) = next_child(&mut entries);
4057 assert_eq!(sibling1, Some(offset2));
4058 assert_eq!(sibling2, None);
4059 }
4060
4061 let encoding = Encoding {
4062 format: Format::Dwarf32,
4063 version: 4,
4064 address_size: 8,
4065 };
4066 let mut dwarf = Dwarf::new();
4067 let unit_id1 = dwarf.units.add(Unit::new(encoding, LineProgram::none()));
4068 add_children(dwarf.units.get_mut(unit_id1));
4069 let unit_id2 = dwarf.units.add(Unit::new(encoding, LineProgram::none()));
4070 add_children(dwarf.units.get_mut(unit_id2));
4071
4072 let mut sections = Sections::new(EndianVec::new(LittleEndian));
4073 dwarf.write(&mut sections).unwrap();
4074
4075 let read_dwarf = sections.read(LittleEndian);
4076 let mut read_units = read_dwarf.units();
4077 check_sibling(read_units.next().unwrap().unwrap(), &read_dwarf);
4078 check_sibling(read_units.next().unwrap().unwrap(), &read_dwarf);
4079 }
4080
4081 #[test]
4082 fn test_line_ref() {
4083 let dir_bytes = b"dir";
4084 let file_bytes1 = b"file1";
4085 let file_bytes2 = b"file2";
4086 let file_string1 = LineString::String(file_bytes1.to_vec());
4087 let file_string2 = LineString::String(file_bytes2.to_vec());
4088
4089 for &version in &[2, 3, 4, 5] {
4090 for &address_size in &[4, 8] {
4091 for &format in &[Format::Dwarf32, Format::Dwarf64] {
4092 let encoding = Encoding {
4093 format,
4094 version,
4095 address_size,
4096 };
4097
4098 let mut line_program = LineProgram::new(
4100 encoding,
4101 LineEncoding::default(),
4102 LineString::String(dir_bytes.to_vec()),
4103 None,
4104 file_string1.clone(),
4105 None,
4106 );
4107 let dir = line_program.default_directory();
4108 let file1 = line_program.add_file(file_string1.clone(), dir, None);
4110 let file2 = line_program.add_file(file_string2.clone(), dir, None);
4111
4112 let mut unit = Unit::new(encoding, line_program);
4113 let root = unit.get_mut(unit.root());
4114 root.set(
4115 constants::DW_AT_name,
4116 AttributeValue::String(file_bytes1.to_vec()),
4117 );
4118 root.set(
4119 constants::DW_AT_comp_dir,
4120 AttributeValue::String(dir_bytes.to_vec()),
4121 );
4122 root.set(constants::DW_AT_stmt_list, AttributeValue::LineProgramRef);
4123
4124 let child = unit.add(unit.root(), constants::DW_TAG_subprogram);
4125 unit.get_mut(child).set(
4126 constants::DW_AT_decl_file,
4127 AttributeValue::FileIndex(Some(file1)),
4128 );
4129
4130 let child = unit.add(unit.root(), constants::DW_TAG_subprogram);
4131 unit.get_mut(child).set(
4132 constants::DW_AT_call_file,
4133 AttributeValue::FileIndex(Some(file2)),
4134 );
4135
4136 let mut dwarf = Dwarf::new();
4137 dwarf.units.add(unit);
4138
4139 let mut sections = Sections::new(EndianVec::new(LittleEndian));
4140 dwarf.write(&mut sections).unwrap();
4141
4142 let read_dwarf = sections.read(LittleEndian);
4143 let mut read_units = read_dwarf.units();
4144 let read_unit = read_units.next().unwrap().unwrap();
4145 let read_unit = read_dwarf.unit(read_unit).unwrap();
4146 let read_unit = read_unit.unit_ref(&read_dwarf);
4147 let read_line_program = read_unit.line_program.as_ref().unwrap().header();
4148 let mut read_entries = read_unit.entries();
4149 let _root = read_entries.next_dfs().unwrap().unwrap();
4150
4151 let mut get_path = |name| {
4152 let entry = read_entries.next_dfs().unwrap().unwrap();
4153 let read_attr = entry.attr(name).unwrap();
4154 let read::AttributeValue::FileIndex(read_file_index) = read_attr.value()
4155 else {
4156 panic!("unexpected {:?}", read_attr);
4157 };
4158 let read_file = read_line_program.file(read_file_index).unwrap();
4159 let read_path = read_unit
4160 .attr_string(read_file.path_name())
4161 .unwrap()
4162 .slice();
4163 (read_file_index, read_path)
4164 };
4165
4166 let (read_index, read_path) = get_path(constants::DW_AT_decl_file);
4167 assert_eq!(read_index, if version >= 5 { 0 } else { 1 });
4168 assert_eq!(read_path, file_bytes1);
4169
4170 let (read_index, read_path) = get_path(constants::DW_AT_call_file);
4171 assert_eq!(read_index, if version >= 5 { 1 } else { 2 });
4172 assert_eq!(read_path, file_bytes2);
4173
4174 let convert_dwarf =
4175 Dwarf::from(&read_dwarf, &|address| Some(Address::Constant(address)))
4176 .unwrap();
4177 let convert_unit = convert_dwarf.units.get(convert_dwarf.units.id(0));
4178 let convert_root = convert_unit.get(convert_unit.root());
4179 let mut convert_entries = convert_root.children();
4180
4181 let mut get_convert_path = |name| {
4182 let convert_entry = convert_unit.get(*convert_entries.next().unwrap());
4183 let convert_attr = convert_entry.get(name).unwrap();
4184 let AttributeValue::FileIndex(Some(convert_file_index)) = convert_attr
4185 else {
4186 panic!("unexpected {:?}", convert_attr);
4187 };
4188 convert_unit.line_program.get_file(*convert_file_index).0
4189 };
4190
4191 let convert_path = get_convert_path(constants::DW_AT_decl_file);
4192 assert_eq!(convert_dwarf.get_line_string(convert_path), file_bytes1);
4193
4194 let convert_path = get_convert_path(constants::DW_AT_call_file);
4195 assert_eq!(convert_dwarf.get_line_string(convert_path), file_bytes2);
4196 }
4197 }
4198 }
4199 }
4200
4201 #[test]
4202 fn test_line_program_used() {
4203 for used in [false, true] {
4204 let encoding = Encoding {
4205 format: Format::Dwarf32,
4206 version: 5,
4207 address_size: 8,
4208 };
4209
4210 let line_program = LineProgram::new(
4211 encoding,
4212 LineEncoding::default(),
4213 LineString::String(b"comp_dir".to_vec()),
4214 None,
4215 LineString::String(b"comp_name".to_vec()),
4216 None,
4217 );
4218
4219 let mut unit = Unit::new(encoding, line_program);
4220 let file_id = if used { Some(FileId::new(0)) } else { None };
4221 let root = unit.root();
4222 unit.get_mut(root).set(
4223 constants::DW_AT_decl_file,
4224 AttributeValue::FileIndex(file_id),
4225 );
4226
4227 let mut dwarf = Dwarf::new();
4228 dwarf.units.add(unit);
4229
4230 let mut sections = Sections::new(EndianVec::new(LittleEndian));
4231 dwarf.write(&mut sections).unwrap();
4232 assert_eq!(!used, sections.debug_line.slice().is_empty());
4233 }
4234 }
4235
4236 #[test]
4237 fn test_delete_child() {
4238 fn set_name(unit: &mut Unit, id: UnitEntryId, name: &str) {
4239 let entry = unit.get_mut(id);
4240 entry.set(constants::DW_AT_name, AttributeValue::String(name.into()));
4241 }
4242 fn check_name<R: read::Reader>(
4243 entry: &read::DebuggingInformationEntry<R>,
4244 unit: read::UnitRef<'_, R>,
4245 name: &str,
4246 ) {
4247 let name_attr = entry.attr(constants::DW_AT_name).unwrap();
4248 let entry_name = unit.attr_string(name_attr.value()).unwrap();
4249 let entry_name_str = entry_name.to_string().unwrap();
4250 assert_eq!(entry_name_str, name);
4251 }
4252 let encoding = Encoding {
4253 format: Format::Dwarf32,
4254 version: 4,
4255 address_size: 8,
4256 };
4257 let mut dwarf = DwarfUnit::new(encoding);
4258 let root = dwarf.unit.root();
4259
4260 let child1 = dwarf.unit.add(root, constants::DW_TAG_subprogram);
4262 set_name(&mut dwarf.unit, child1, "child1");
4263 let grandchild1 = dwarf.unit.add(child1, constants::DW_TAG_variable);
4264 set_name(&mut dwarf.unit, grandchild1, "grandchild1");
4265 let child2 = dwarf.unit.add(root, constants::DW_TAG_subprogram);
4266 set_name(&mut dwarf.unit, child2, "child2");
4267 dwarf.unit.get_mut(root).delete_child(child1);
4269 let child3 = dwarf.unit.add(root, constants::DW_TAG_subprogram);
4270 set_name(&mut dwarf.unit, child3, "child3");
4271 let child4 = dwarf.unit.add(root, constants::DW_TAG_subprogram);
4272 set_name(&mut dwarf.unit, child4, "child4");
4273 let grandchild4 = dwarf.unit.add(child4, constants::DW_TAG_variable);
4274 set_name(&mut dwarf.unit, grandchild4, "grandchild4");
4275 dwarf.unit.get_mut(child4).delete_child(grandchild4);
4276
4277 let mut sections = Sections::new(EndianVec::new(LittleEndian));
4278
4279 dwarf.write(&mut sections).unwrap();
4281
4282 let read_dwarf = sections.read(LittleEndian);
4283 let read_unit = read_dwarf.units().next().unwrap().unwrap();
4284 let read_unit = read_dwarf.unit(read_unit).unwrap();
4285 let read_unit = read_unit.unit_ref(&read_dwarf);
4286 let mut entries = read_unit.entries();
4287 entries.next_dfs().unwrap().unwrap();
4289 let read_child2 = entries.next_dfs().unwrap().unwrap();
4291 check_name(read_child2, read_unit, "child2");
4292 let read_child3 = entries.next_dfs().unwrap().unwrap();
4294 check_name(read_child3, read_unit, "child3");
4295 let read_child4 = entries.next_dfs().unwrap().unwrap();
4297 check_name(read_child4, read_unit, "child4");
4298 assert!(entries.next_dfs().unwrap().is_none());
4300 }
4301
4302 #[test]
4303 fn test_missing_unit_ref() {
4304 let encoding = Encoding {
4305 format: Format::Dwarf32,
4306 version: 5,
4307 address_size: 8,
4308 };
4309
4310 let mut dwarf = Dwarf::new();
4311 let unit_id = dwarf.units.add(Unit::new(encoding, LineProgram::none()));
4312 let unit = dwarf.units.get_mut(unit_id);
4313
4314 let entry_id = unit.add(unit.root(), constants::DW_TAG_const_type);
4316 unit.get_mut(unit.root()).delete_child(entry_id);
4318
4319 let subprogram_id = unit.add(unit.root(), constants::DW_TAG_subprogram);
4321 unit.get_mut(subprogram_id)
4322 .set(constants::DW_AT_type, AttributeValue::UnitRef(entry_id));
4323
4324 let mut sections = Sections::new(EndianVec::new(LittleEndian));
4326 assert_eq!(dwarf.write(&mut sections), Err(Error::InvalidReference));
4327 }
4328
4329 #[test]
4330 fn test_missing_debuginfo_ref() {
4331 let encoding = Encoding {
4332 format: Format::Dwarf32,
4333 version: 5,
4334 address_size: 8,
4335 };
4336
4337 let mut dwarf = Dwarf::new();
4338 let unit_id = dwarf.units.add(Unit::new(encoding, LineProgram::none()));
4339 let unit = dwarf.units.get_mut(unit_id);
4340
4341 let entry_id = unit.add(unit.root(), constants::DW_TAG_const_type);
4343 unit.get_mut(unit.root()).delete_child(entry_id);
4345
4346 let subprogram_id = unit.add(unit.root(), constants::DW_TAG_subprogram);
4348 unit.get_mut(subprogram_id).set(
4349 constants::DW_AT_type,
4350 AttributeValue::DebugInfoRef(DebugInfoRef::Entry(unit_id, entry_id)),
4351 );
4352
4353 let mut sections = Sections::new(EndianVec::new(LittleEndian));
4355 assert_eq!(dwarf.write(&mut sections), Err(Error::InvalidReference));
4356 }
4357}