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 have_base_address = self.entries[self.root.index].attrs.iter().any(|attr| {
419 attr.name == constants::DW_AT_low_pc
420 && attr.value != AttributeValue::Address(Address::Constant(0))
421 });
422 let range_lists = self
423 .ranges
424 .write(sections, self.encoding, have_base_address)?;
425 let loc_lists =
427 self.locations
428 .write(sections, self.encoding, have_base_address, Some(&offsets))?;
429
430 let w = &mut sections.debug_info;
431 let mut unit_refs = Vec::new();
432 self.entries[self.root.index].write(
433 w,
434 &mut sections.debug_info_fixups,
435 &mut unit_refs,
436 self,
437 &offsets,
438 &codes,
439 line_program,
440 line_strings,
441 strings,
442 &range_lists,
443 &loc_lists,
444 )?;
445
446 let length = (w.len() - length_base) as u64;
447 w.write_initial_length_at(length_offset, length, self.format())?;
448
449 for (offset, entry) in unit_refs {
450 w.write_udata_at(
452 offset.0,
453 offsets.unit_offset(entry).ok_or(Error::InvalidReference)?,
454 self.format().word_size(),
455 )?;
456 }
457
458 self.offsets = offsets;
459 self.written = true;
460 Ok(())
461 }
462
463 fn skip(&mut self) {
464 self.written = true;
465 }
466
467 fn free(&mut self) {
468 self.line_program = LineProgram::none();
469 self.ranges = RangeListTable::default();
470 self.locations = LocationListTable::default();
471 self.entries = Vec::new();
472 }
473
474 fn reorder_base_types(&mut self) {
477 let root = &self.entries[self.root.index];
478 let mut root_children = Vec::with_capacity(root.children.len());
479 for entry in &root.children {
480 if self.entries[entry.index].tag == constants::DW_TAG_base_type {
481 root_children.push(*entry);
482 }
483 }
484 for entry in &root.children {
485 if self.entries[entry.index].tag != constants::DW_TAG_base_type {
486 root_children.push(*entry);
487 }
488 }
489 self.entries[self.root.index].children = root_children;
490 }
491}
492
493#[derive(Debug)]
500pub struct DebuggingInformationEntry {
501 id: UnitEntryId,
502 parent: Option<UnitEntryId>,
503 tag: constants::DwTag,
504 sibling: bool,
506 attrs: Vec<Attribute>,
507 children: Vec<UnitEntryId>,
508}
509
510impl DebuggingInformationEntry {
511 fn new_reserved(id: UnitEntryId) -> Self {
513 DebuggingInformationEntry {
514 id,
515 parent: None,
516 tag: constants::DW_TAG_null,
517 sibling: false,
518 attrs: Vec::new(),
519 children: Vec::new(),
520 }
521 }
522
523 #[inline]
525 pub fn id(&self) -> UnitEntryId {
526 self.id
527 }
528
529 #[inline]
531 pub fn parent(&self) -> Option<UnitEntryId> {
532 self.parent
533 }
534
535 #[inline]
537 pub fn tag(&self) -> constants::DwTag {
538 self.tag
539 }
540
541 #[inline]
543 pub fn sibling(&self) -> bool {
544 self.sibling
545 }
546
547 #[inline]
551 pub fn set_sibling(&mut self, sibling: bool) {
552 self.sibling = sibling;
553 }
554
555 #[inline]
557 pub fn attrs(&self) -> slice::Iter<'_, Attribute> {
558 self.attrs.iter()
559 }
560
561 #[inline]
563 pub fn attrs_mut(&mut self) -> slice::IterMut<'_, Attribute> {
564 self.attrs.iter_mut()
565 }
566
567 pub fn get(&self, name: constants::DwAt) -> Option<&AttributeValue> {
569 self.attrs
570 .iter()
571 .find(|attr| attr.name == name)
572 .map(|attr| &attr.value)
573 }
574
575 pub fn get_mut(&mut self, name: constants::DwAt) -> Option<&mut AttributeValue> {
577 self.attrs
578 .iter_mut()
579 .find(|attr| attr.name == name)
580 .map(|attr| &mut attr.value)
581 }
582
583 pub fn reserve(&mut self, additional: usize) {
588 self.attrs.reserve(additional);
589 }
590
591 pub fn set(&mut self, name: constants::DwAt, value: AttributeValue) {
599 debug_assert_ne!(name, constants::DW_AT_sibling);
600 if let Some(attr) = self.attrs.iter_mut().find(|attr| attr.name == name) {
601 attr.value = value;
602 return;
603 }
604 self.attrs.push(Attribute { name, value });
605 }
606
607 pub fn delete(&mut self, name: constants::DwAt) {
609 self.attrs.retain(|x| x.name != name);
610 }
611
612 #[inline]
616 pub fn children(&self) -> slice::Iter<'_, UnitEntryId> {
617 self.children.iter()
618 }
619
620 pub fn delete_child(&mut self, id: UnitEntryId) {
622 self.children.retain(|&child| child != id);
623 }
624
625 fn abbreviation(&self, encoding: Encoding) -> Result<Abbreviation> {
627 let sibling = self.sibling && !self.children.is_empty();
628 let mut attrs = Vec::with_capacity(usize::from(sibling) + self.attrs.len());
629
630 if sibling {
631 let form = match encoding.format {
632 Format::Dwarf32 => constants::DW_FORM_ref4,
633 Format::Dwarf64 => constants::DW_FORM_ref8,
634 };
635 attrs.push(AttributeSpecification::new(
636 constants::DW_AT_sibling,
637 form,
638 None,
639 ));
640 }
641
642 for attr in &self.attrs {
643 attrs.push(attr.specification(encoding)?);
644 }
645
646 Ok(Abbreviation::new(
647 self.tag,
648 !self.children.is_empty(),
649 attrs,
650 ))
651 }
652
653 fn calculate_offsets(
654 &self,
655 unit: &Unit,
656 offset: &mut usize,
657 offsets: &mut UnitOffsets,
658 abbrevs: &mut AbbreviationTable,
659 codes: &mut [u64],
660 ) -> Result<()> {
661 offsets.entries[self.id.index] = DebugInfoOffset(*offset);
662 let code = abbrevs.add(self.abbreviation(unit.encoding())?);
663 codes[self.id.index] = code;
664 *offset += self.size(unit, offsets, code)?;
665 if !self.children.is_empty() {
666 for child in &self.children {
667 unit.entries[child.index]
668 .calculate_offsets(unit, offset, offsets, abbrevs, codes)?;
669 }
670 *offset += 1;
672 }
673 Ok(())
674 }
675
676 fn size(&self, unit: &Unit, offsets: &UnitOffsets, code: u64) -> Result<usize> {
677 let mut size = uleb128_size(code);
678 if self.sibling && !self.children.is_empty() {
679 size += unit.format().word_size() as usize;
680 }
681 for attr in &self.attrs {
682 size += attr.value.size(unit, offsets)?;
683 }
684 Ok(size)
685 }
686
687 fn write<W: Writer>(
689 &self,
690 w: &mut DebugInfo<W>,
691 debug_info_refs: &mut Vec<DebugInfoFixup>,
692 unit_refs: &mut Vec<(DebugInfoOffset, UnitEntryId)>,
693 unit: &Unit,
694 offsets: &UnitOffsets,
695 codes: &[u64],
696 line_program: Option<DebugLineOffset>,
697 line_strings: &LineStringTable,
698 strings: &StringTable,
699 range_lists: &RangeListOffsets,
700 loc_lists: &LocationListOffsets,
701 ) -> Result<()> {
702 debug_assert_eq!(offsets.debug_info_offset(self.id), Some(w.offset()));
703 w.write_uleb128(codes[self.id.index])?;
704
705 let sibling_offset = if self.sibling && !self.children.is_empty() {
706 let offset = w.offset();
707 w.write_udata(0, unit.format().word_size())?;
708 Some(offset)
709 } else {
710 None
711 };
712
713 for attr in &self.attrs {
714 attr.value.write(
715 w,
716 debug_info_refs,
717 unit_refs,
718 unit,
719 offsets,
720 line_program,
721 line_strings,
722 strings,
723 range_lists,
724 loc_lists,
725 )?;
726 }
727
728 if !self.children.is_empty() {
729 for child in &self.children {
730 unit.entries[child.index].write(
731 w,
732 debug_info_refs,
733 unit_refs,
734 unit,
735 offsets,
736 codes,
737 line_program,
738 line_strings,
739 strings,
740 range_lists,
741 loc_lists,
742 )?;
743 }
744 w.write_u8(0)?;
746 }
747
748 if let Some(offset) = sibling_offset {
749 let next_offset = (w.offset().0 - offsets.unit.0) as u64;
750 w.write_udata_at(offset.0, next_offset, unit.format().word_size())?;
752 }
753 Ok(())
754 }
755}
756
757#[derive(Debug, Clone, PartialEq, Eq)]
760pub struct Attribute {
761 name: constants::DwAt,
762 value: AttributeValue,
763}
764
765impl Attribute {
766 #[inline]
768 pub fn name(&self) -> constants::DwAt {
769 self.name
770 }
771
772 #[inline]
774 pub fn get(&self) -> &AttributeValue {
775 &self.value
776 }
777
778 #[inline]
780 pub fn set(&mut self, value: AttributeValue) {
781 self.value = value;
782 }
783
784 fn specification(&self, encoding: Encoding) -> Result<AttributeSpecification> {
786 let (form, implicit_const) = self.value.form(encoding)?;
787 Ok(AttributeSpecification::new(self.name, form, implicit_const))
788 }
789}
790
791#[derive(Debug, Clone, PartialEq, Eq)]
793pub enum AttributeValue {
794 Address(Address),
796
797 Block(Vec<u8>),
799
800 Data1(u8),
806
807 Data2(u16),
815
816 Data4(u32),
824
825 Data8(u64),
833
834 Data16(u128),
842
843 Sdata(i64),
845
846 Udata(u64),
848
849 ImplicitConst(i64),
860
861 Exprloc(Expression),
866
867 Flag(bool),
869
870 FlagPresent,
874
875 UnitRef(UnitEntryId),
877
878 DebugInfoRef(DebugInfoRef),
880
881 DebugInfoRefSup(DebugInfoOffset),
887
888 LineProgramRef,
890
891 LocationListRef(LocationListId),
893
894 DebugMacinfoRef(DebugMacinfoOffset),
900
901 DebugMacroRef(DebugMacroOffset),
907
908 RangeListRef(RangeListId),
910
911 DebugTypesRef(DebugTypeSignature),
917
918 StringRef(StringId),
920
921 DebugStrRefSup(DebugStrOffset),
927
928 LineStringRef(LineStringId),
930
931 String(Vec<u8>),
934
935 Encoding(constants::DwAte),
937
938 DecimalSign(constants::DwDs),
940
941 Endianity(constants::DwEnd),
943
944 Accessibility(constants::DwAccess),
946
947 Visibility(constants::DwVis),
949
950 Virtuality(constants::DwVirtuality),
952
953 Language(constants::DwLang),
955
956 AddressClass(constants::DwAddr),
958
959 IdentifierCase(constants::DwId),
961
962 CallingConvention(constants::DwCc),
964
965 Inline(constants::DwInl),
967
968 Ordering(constants::DwOrd),
970
971 FileIndex(Option<FileId>),
974}
975
976impl AttributeValue {
977 pub fn form(&self, encoding: Encoding) -> Result<(constants::DwForm, Option<i64>)> {
979 let form = match *self {
988 AttributeValue::Address(_) => constants::DW_FORM_addr,
989 AttributeValue::Block(_) => constants::DW_FORM_block,
990 AttributeValue::Data1(_) => constants::DW_FORM_data1,
991 AttributeValue::Data2(_) => constants::DW_FORM_data2,
992 AttributeValue::Data4(_) => constants::DW_FORM_data4,
993 AttributeValue::Data8(_) => constants::DW_FORM_data8,
994 AttributeValue::Data16(_) => constants::DW_FORM_data16,
995 AttributeValue::Exprloc(_) => {
996 if encoding.version >= 4 {
997 constants::DW_FORM_exprloc
998 } else {
999 constants::DW_FORM_block
1000 }
1001 }
1002 AttributeValue::Flag(_) => constants::DW_FORM_flag,
1003 AttributeValue::FlagPresent => {
1004 if encoding.version >= 4 {
1005 constants::DW_FORM_flag_present
1006 } else {
1007 constants::DW_FORM_flag
1008 }
1009 }
1010 AttributeValue::UnitRef(_) => {
1011 match encoding.format {
1014 Format::Dwarf32 => constants::DW_FORM_ref4,
1015 Format::Dwarf64 => constants::DW_FORM_ref8,
1016 }
1017 }
1018 AttributeValue::DebugInfoRef(_) => constants::DW_FORM_ref_addr,
1019 AttributeValue::DebugInfoRefSup(_) => {
1020 match encoding.format {
1022 Format::Dwarf32 => constants::DW_FORM_ref_sup4,
1023 Format::Dwarf64 => constants::DW_FORM_ref_sup8,
1024 }
1025 }
1026 AttributeValue::LineProgramRef
1027 | AttributeValue::LocationListRef(_)
1028 | AttributeValue::DebugMacinfoRef(_)
1029 | AttributeValue::DebugMacroRef(_)
1030 | AttributeValue::RangeListRef(_) => {
1031 if encoding.version == 2 || encoding.version == 3 {
1032 match encoding.format {
1033 Format::Dwarf32 => constants::DW_FORM_data4,
1034 Format::Dwarf64 => constants::DW_FORM_data8,
1035 }
1036 } else {
1037 constants::DW_FORM_sec_offset
1038 }
1039 }
1040 AttributeValue::DebugTypesRef(_) => constants::DW_FORM_ref_sig8,
1041 AttributeValue::StringRef(_) => constants::DW_FORM_strp,
1042 AttributeValue::DebugStrRefSup(_) => constants::DW_FORM_strp_sup,
1043 AttributeValue::LineStringRef(_) => constants::DW_FORM_line_strp,
1044 AttributeValue::String(_) => constants::DW_FORM_string,
1045 AttributeValue::Encoding(_)
1046 | AttributeValue::DecimalSign(_)
1047 | AttributeValue::Endianity(_)
1048 | AttributeValue::Accessibility(_)
1049 | AttributeValue::Visibility(_)
1050 | AttributeValue::Virtuality(_)
1051 | AttributeValue::Language(_)
1052 | AttributeValue::AddressClass(_)
1053 | AttributeValue::IdentifierCase(_)
1054 | AttributeValue::CallingConvention(_)
1055 | AttributeValue::Inline(_)
1056 | AttributeValue::Ordering(_)
1057 | AttributeValue::FileIndex(_)
1058 | AttributeValue::Udata(_) => constants::DW_FORM_udata,
1059 AttributeValue::Sdata(_) => constants::DW_FORM_sdata,
1060 AttributeValue::ImplicitConst(val) => {
1061 if encoding.version >= 5 {
1062 return Ok((constants::DW_FORM_implicit_const, Some(val)));
1063 } else {
1064 constants::DW_FORM_sdata
1065 }
1066 }
1067 };
1068 Ok((form, None))
1069 }
1070
1071 fn size(&self, unit: &Unit, offsets: &UnitOffsets) -> Result<usize> {
1072 macro_rules! debug_assert_form {
1073 ($form:expr) => {
1074 debug_assert_eq!(self.form(unit.encoding()).unwrap().0, $form)
1075 };
1076 }
1077 Ok(match *self {
1078 AttributeValue::Address(_) => {
1079 debug_assert_form!(constants::DW_FORM_addr);
1080 unit.address_size() as usize
1081 }
1082 AttributeValue::Block(ref val) => {
1083 debug_assert_form!(constants::DW_FORM_block);
1084 uleb128_size(val.len() as u64) + val.len()
1085 }
1086 AttributeValue::Data1(_) => {
1087 debug_assert_form!(constants::DW_FORM_data1);
1088 1
1089 }
1090 AttributeValue::Data2(_) => {
1091 debug_assert_form!(constants::DW_FORM_data2);
1092 2
1093 }
1094 AttributeValue::Data4(_) => {
1095 debug_assert_form!(constants::DW_FORM_data4);
1096 4
1097 }
1098 AttributeValue::Data8(_) => {
1099 debug_assert_form!(constants::DW_FORM_data8);
1100 8
1101 }
1102 AttributeValue::Data16(_) => {
1103 debug_assert_form!(constants::DW_FORM_data16);
1104 16
1105 }
1106 AttributeValue::Sdata(val) => {
1107 debug_assert_form!(constants::DW_FORM_sdata);
1108 sleb128_size(val)
1109 }
1110 AttributeValue::ImplicitConst(val) => {
1111 if unit.version() >= 5 {
1112 debug_assert_form!(constants::DW_FORM_implicit_const);
1113 0
1114 } else {
1115 debug_assert_form!(constants::DW_FORM_sdata);
1116 sleb128_size(val)
1117 }
1118 }
1119 AttributeValue::Udata(val) => {
1120 debug_assert_form!(constants::DW_FORM_udata);
1121 uleb128_size(val)
1122 }
1123 AttributeValue::Exprloc(ref val) => {
1124 if unit.version() >= 4 {
1125 debug_assert_form!(constants::DW_FORM_exprloc);
1126 } else {
1127 debug_assert_form!(constants::DW_FORM_block);
1128 }
1129 let size = val.size(unit.encoding(), Some(offsets))?;
1130 uleb128_size(size as u64) + size
1131 }
1132 AttributeValue::Flag(_) => {
1133 debug_assert_form!(constants::DW_FORM_flag);
1134 1
1135 }
1136 AttributeValue::FlagPresent => {
1137 if unit.version() >= 4 {
1138 debug_assert_form!(constants::DW_FORM_flag_present);
1139 0
1140 } else {
1141 debug_assert_form!(constants::DW_FORM_flag);
1142 1
1143 }
1144 }
1145 AttributeValue::UnitRef(_) => {
1146 match unit.format() {
1147 Format::Dwarf32 => debug_assert_form!(constants::DW_FORM_ref4),
1148 Format::Dwarf64 => debug_assert_form!(constants::DW_FORM_ref8),
1149 }
1150 unit.format().word_size() as usize
1151 }
1152 AttributeValue::DebugInfoRef(_) => {
1153 debug_assert_form!(constants::DW_FORM_ref_addr);
1154 if unit.version() == 2 {
1155 unit.address_size() as usize
1156 } else {
1157 unit.format().word_size() as usize
1158 }
1159 }
1160 AttributeValue::DebugInfoRefSup(_) => {
1161 match unit.format() {
1162 Format::Dwarf32 => debug_assert_form!(constants::DW_FORM_ref_sup4),
1163 Format::Dwarf64 => debug_assert_form!(constants::DW_FORM_ref_sup8),
1164 }
1165 unit.format().word_size() as usize
1166 }
1167 AttributeValue::LineProgramRef => {
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::LocationListRef(_) => {
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::DebugMacinfoRef(_) => {
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::DebugMacroRef(_) => {
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::RangeListRef(_) => {
1192 if unit.version() >= 4 {
1193 debug_assert_form!(constants::DW_FORM_sec_offset);
1194 }
1195 unit.format().word_size() as usize
1196 }
1197 AttributeValue::DebugTypesRef(_) => {
1198 debug_assert_form!(constants::DW_FORM_ref_sig8);
1199 8
1200 }
1201 AttributeValue::StringRef(_) => {
1202 debug_assert_form!(constants::DW_FORM_strp);
1203 unit.format().word_size() as usize
1204 }
1205 AttributeValue::DebugStrRefSup(_) => {
1206 debug_assert_form!(constants::DW_FORM_strp_sup);
1207 unit.format().word_size() as usize
1208 }
1209 AttributeValue::LineStringRef(_) => {
1210 debug_assert_form!(constants::DW_FORM_line_strp);
1211 unit.format().word_size() as usize
1212 }
1213 AttributeValue::String(ref val) => {
1214 debug_assert_form!(constants::DW_FORM_string);
1215 val.len() + 1
1216 }
1217 AttributeValue::Encoding(val) => {
1218 debug_assert_form!(constants::DW_FORM_udata);
1219 uleb128_size(val.0 as u64)
1220 }
1221 AttributeValue::DecimalSign(val) => {
1222 debug_assert_form!(constants::DW_FORM_udata);
1223 uleb128_size(val.0 as u64)
1224 }
1225 AttributeValue::Endianity(val) => {
1226 debug_assert_form!(constants::DW_FORM_udata);
1227 uleb128_size(val.0 as u64)
1228 }
1229 AttributeValue::Accessibility(val) => {
1230 debug_assert_form!(constants::DW_FORM_udata);
1231 uleb128_size(val.0 as u64)
1232 }
1233 AttributeValue::Visibility(val) => {
1234 debug_assert_form!(constants::DW_FORM_udata);
1235 uleb128_size(val.0 as u64)
1236 }
1237 AttributeValue::Virtuality(val) => {
1238 debug_assert_form!(constants::DW_FORM_udata);
1239 uleb128_size(val.0 as u64)
1240 }
1241 AttributeValue::Language(val) => {
1242 debug_assert_form!(constants::DW_FORM_udata);
1243 uleb128_size(val.0 as u64)
1244 }
1245 AttributeValue::AddressClass(val) => {
1246 debug_assert_form!(constants::DW_FORM_udata);
1247 uleb128_size(val.0)
1248 }
1249 AttributeValue::IdentifierCase(val) => {
1250 debug_assert_form!(constants::DW_FORM_udata);
1251 uleb128_size(val.0 as u64)
1252 }
1253 AttributeValue::CallingConvention(val) => {
1254 debug_assert_form!(constants::DW_FORM_udata);
1255 uleb128_size(val.0 as u64)
1256 }
1257 AttributeValue::Inline(val) => {
1258 debug_assert_form!(constants::DW_FORM_udata);
1259 uleb128_size(val.0 as u64)
1260 }
1261 AttributeValue::Ordering(val) => {
1262 debug_assert_form!(constants::DW_FORM_udata);
1263 uleb128_size(val.0 as u64)
1264 }
1265 AttributeValue::FileIndex(val) => {
1266 debug_assert_form!(constants::DW_FORM_udata);
1267 uleb128_size(val.map(|id| id.raw(unit.version())).unwrap_or(0))
1268 }
1269 })
1270 }
1271
1272 fn write<W: Writer>(
1274 &self,
1275 w: &mut DebugInfo<W>,
1276 debug_info_refs: &mut Vec<DebugInfoFixup>,
1277 unit_refs: &mut Vec<(DebugInfoOffset, UnitEntryId)>,
1278 unit: &Unit,
1279 offsets: &UnitOffsets,
1280 line_program: Option<DebugLineOffset>,
1281 line_strings: &LineStringTable,
1282 strings: &StringTable,
1283 range_lists: &RangeListOffsets,
1284 loc_lists: &LocationListOffsets,
1285 ) -> Result<()> {
1286 macro_rules! debug_assert_form {
1287 ($form:expr) => {
1288 debug_assert_eq!(self.form(unit.encoding()).unwrap().0, $form)
1289 };
1290 }
1291 match *self {
1292 AttributeValue::Address(val) => {
1293 debug_assert_form!(constants::DW_FORM_addr);
1294 w.write_address(val, unit.address_size())?;
1295 }
1296 AttributeValue::Block(ref val) => {
1297 debug_assert_form!(constants::DW_FORM_block);
1298 w.write_uleb128(val.len() as u64)?;
1299 w.write(val)?;
1300 }
1301 AttributeValue::Data1(val) => {
1302 debug_assert_form!(constants::DW_FORM_data1);
1303 w.write_u8(val)?;
1304 }
1305 AttributeValue::Data2(val) => {
1306 debug_assert_form!(constants::DW_FORM_data2);
1307 w.write_u16(val)?;
1308 }
1309 AttributeValue::Data4(val) => {
1310 debug_assert_form!(constants::DW_FORM_data4);
1311 w.write_u32(val)?;
1312 }
1313 AttributeValue::Data8(val) => {
1314 debug_assert_form!(constants::DW_FORM_data8);
1315 w.write_u64(val)?;
1316 }
1317 AttributeValue::Data16(val) => {
1318 debug_assert_form!(constants::DW_FORM_data16);
1319 w.write_u128(val)?;
1320 }
1321 AttributeValue::Sdata(val) => {
1322 debug_assert_form!(constants::DW_FORM_sdata);
1323 w.write_sleb128(val)?;
1324 }
1325 AttributeValue::ImplicitConst(val) => {
1326 if unit.version() >= 5 {
1327 debug_assert_form!(constants::DW_FORM_implicit_const);
1328 } else {
1329 debug_assert_form!(constants::DW_FORM_sdata);
1330 w.write_sleb128(val)?;
1331 }
1332 }
1333 AttributeValue::Udata(val) => {
1334 debug_assert_form!(constants::DW_FORM_udata);
1335 w.write_uleb128(val)?;
1336 }
1337 AttributeValue::Exprloc(ref val) => {
1338 if unit.version() >= 4 {
1339 debug_assert_form!(constants::DW_FORM_exprloc);
1340 } else {
1341 debug_assert_form!(constants::DW_FORM_block);
1342 }
1343 w.write_uleb128(val.size(unit.encoding(), Some(offsets))? as u64)?;
1344 val.write(
1345 &mut w.0,
1346 Some(debug_info_refs),
1347 unit.encoding(),
1348 Some(offsets),
1349 )?;
1350 }
1351 AttributeValue::Flag(val) => {
1352 debug_assert_form!(constants::DW_FORM_flag);
1353 w.write_u8(val as u8)?;
1354 }
1355 AttributeValue::FlagPresent => {
1356 if unit.version() >= 4 {
1357 debug_assert_form!(constants::DW_FORM_flag_present);
1358 } else {
1359 debug_assert_form!(constants::DW_FORM_flag);
1360 w.write_u8(1)?;
1361 }
1362 }
1363 AttributeValue::UnitRef(id) => {
1364 match unit.format() {
1365 Format::Dwarf32 => debug_assert_form!(constants::DW_FORM_ref4),
1366 Format::Dwarf64 => debug_assert_form!(constants::DW_FORM_ref8),
1367 }
1368 unit_refs.push((w.offset(), id));
1369 w.write_udata(0, unit.format().word_size())?;
1370 }
1371 AttributeValue::DebugInfoRef(reference) => {
1372 debug_assert_form!(constants::DW_FORM_ref_addr);
1373 let size = if unit.version() == 2 {
1374 unit.address_size()
1375 } else {
1376 unit.format().word_size()
1377 };
1378 match reference {
1379 DebugInfoRef::Symbol(symbol) => w.write_reference(symbol, size)?,
1380 DebugInfoRef::Entry(unit, entry) => {
1381 debug_info_refs.push(DebugInfoFixup {
1382 offset: w.len(),
1383 unit,
1384 entry,
1385 size,
1386 });
1387 w.write_udata(0, size)?;
1388 }
1389 }
1390 }
1391 AttributeValue::DebugInfoRefSup(val) => {
1392 match unit.format() {
1393 Format::Dwarf32 => debug_assert_form!(constants::DW_FORM_ref_sup4),
1394 Format::Dwarf64 => debug_assert_form!(constants::DW_FORM_ref_sup8),
1395 }
1396 w.write_udata(val.0 as u64, unit.format().word_size())?;
1397 }
1398 AttributeValue::LineProgramRef => {
1399 if unit.version() >= 4 {
1400 debug_assert_form!(constants::DW_FORM_sec_offset);
1401 }
1402 match line_program {
1403 Some(line_program) => {
1404 w.write_offset(
1405 line_program.0,
1406 SectionId::DebugLine,
1407 unit.format().word_size(),
1408 )?;
1409 }
1410 None => return Err(Error::InvalidAttributeValue),
1411 }
1412 }
1413 AttributeValue::LocationListRef(val) => {
1414 if unit.version() >= 4 {
1415 debug_assert_form!(constants::DW_FORM_sec_offset);
1416 }
1417 let section = if unit.version() <= 4 {
1418 SectionId::DebugLoc
1419 } else {
1420 SectionId::DebugLocLists
1421 };
1422 w.write_offset(loc_lists.get(val).0, section, unit.format().word_size())?;
1423 }
1424 AttributeValue::DebugMacinfoRef(val) => {
1425 if unit.version() >= 4 {
1426 debug_assert_form!(constants::DW_FORM_sec_offset);
1427 }
1428 w.write_offset(val.0, SectionId::DebugMacinfo, unit.format().word_size())?;
1429 }
1430 AttributeValue::DebugMacroRef(val) => {
1431 if unit.version() >= 4 {
1432 debug_assert_form!(constants::DW_FORM_sec_offset);
1433 }
1434 w.write_offset(val.0, SectionId::DebugMacro, unit.format().word_size())?;
1435 }
1436 AttributeValue::RangeListRef(val) => {
1437 if unit.version() >= 4 {
1438 debug_assert_form!(constants::DW_FORM_sec_offset);
1439 }
1440 let section = if unit.version() <= 4 {
1441 SectionId::DebugRanges
1442 } else {
1443 SectionId::DebugRngLists
1444 };
1445 w.write_offset(range_lists.get(val).0, section, unit.format().word_size())?;
1446 }
1447 AttributeValue::DebugTypesRef(val) => {
1448 debug_assert_form!(constants::DW_FORM_ref_sig8);
1449 w.write_u64(val.0)?;
1450 }
1451 AttributeValue::StringRef(val) => {
1452 debug_assert_form!(constants::DW_FORM_strp);
1453 w.write_offset(
1454 strings.offset(val).0,
1455 SectionId::DebugStr,
1456 unit.format().word_size(),
1457 )?;
1458 }
1459 AttributeValue::DebugStrRefSup(val) => {
1460 debug_assert_form!(constants::DW_FORM_strp_sup);
1461 w.write_udata(val.0 as u64, unit.format().word_size())?;
1462 }
1463 AttributeValue::LineStringRef(val) => {
1464 debug_assert_form!(constants::DW_FORM_line_strp);
1465 w.write_offset(
1466 line_strings.offset(val).0,
1467 SectionId::DebugLineStr,
1468 unit.format().word_size(),
1469 )?;
1470 }
1471 AttributeValue::String(ref val) => {
1472 debug_assert_form!(constants::DW_FORM_string);
1473 w.write(val)?;
1474 w.write_u8(0)?;
1475 }
1476 AttributeValue::Encoding(val) => {
1477 debug_assert_form!(constants::DW_FORM_udata);
1478 w.write_uleb128(u64::from(val.0))?;
1479 }
1480 AttributeValue::DecimalSign(val) => {
1481 debug_assert_form!(constants::DW_FORM_udata);
1482 w.write_uleb128(u64::from(val.0))?;
1483 }
1484 AttributeValue::Endianity(val) => {
1485 debug_assert_form!(constants::DW_FORM_udata);
1486 w.write_uleb128(u64::from(val.0))?;
1487 }
1488 AttributeValue::Accessibility(val) => {
1489 debug_assert_form!(constants::DW_FORM_udata);
1490 w.write_uleb128(u64::from(val.0))?;
1491 }
1492 AttributeValue::Visibility(val) => {
1493 debug_assert_form!(constants::DW_FORM_udata);
1494 w.write_uleb128(u64::from(val.0))?;
1495 }
1496 AttributeValue::Virtuality(val) => {
1497 debug_assert_form!(constants::DW_FORM_udata);
1498 w.write_uleb128(u64::from(val.0))?;
1499 }
1500 AttributeValue::Language(val) => {
1501 debug_assert_form!(constants::DW_FORM_udata);
1502 w.write_uleb128(u64::from(val.0))?;
1503 }
1504 AttributeValue::AddressClass(val) => {
1505 debug_assert_form!(constants::DW_FORM_udata);
1506 w.write_uleb128(val.0)?;
1507 }
1508 AttributeValue::IdentifierCase(val) => {
1509 debug_assert_form!(constants::DW_FORM_udata);
1510 w.write_uleb128(u64::from(val.0))?;
1511 }
1512 AttributeValue::CallingConvention(val) => {
1513 debug_assert_form!(constants::DW_FORM_udata);
1514 w.write_uleb128(u64::from(val.0))?;
1515 }
1516 AttributeValue::Inline(val) => {
1517 debug_assert_form!(constants::DW_FORM_udata);
1518 w.write_uleb128(u64::from(val.0))?;
1519 }
1520 AttributeValue::Ordering(val) => {
1521 debug_assert_form!(constants::DW_FORM_udata);
1522 w.write_uleb128(u64::from(val.0))?;
1523 }
1524 AttributeValue::FileIndex(val) => {
1525 debug_assert_form!(constants::DW_FORM_udata);
1526 w.write_uleb128(val.map(|id| id.raw(unit.version())).unwrap_or(0))?;
1527 }
1528 }
1529 Ok(())
1530 }
1531}
1532
1533define_section!(
1534 DebugInfo,
1535 DebugInfoOffset,
1536 "A writable `.debug_info` section."
1537);
1538
1539#[derive(Debug)]
1541pub(crate) struct UnitOffsets {
1542 base_id: BaseId,
1543 unit: DebugInfoOffset,
1544 entries: Vec<DebugInfoOffset>,
1545}
1546
1547impl UnitOffsets {
1548 #[inline]
1552 fn debug_info_offset(&self, entry: UnitEntryId) -> Option<DebugInfoOffset> {
1553 debug_assert_eq!(self.base_id, entry.base_id);
1554 let offset = self.entries[entry.index];
1555 if offset.0 == 0 { None } else { Some(offset) }
1556 }
1557
1558 #[inline]
1564 pub(crate) fn unit_offset(&self, entry: UnitEntryId) -> Option<u64> {
1565 self.debug_info_offset(entry)
1566 .map(|offset| (offset.0 - self.unit.0) as u64)
1567 }
1568}
1569
1570#[deprecated(note = "Renamed to DebugInfoRef")]
1572pub type Reference = DebugInfoRef;
1573
1574#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1576pub enum DebugInfoRef {
1577 Symbol(usize),
1582 Entry(UnitId, UnitEntryId),
1586}
1587
1588#[derive(Debug, Clone, Copy)]
1590pub(crate) struct DebugInfoFixup {
1591 pub offset: usize,
1593 pub size: u8,
1595 pub unit: UnitId,
1597 pub entry: UnitEntryId,
1599}
1600
1601#[cfg(feature = "read")]
1602pub use convert::*;
1603#[cfg(feature = "read")]
1604pub(crate) mod convert {
1605 use super::*;
1606 use crate::common::{
1607 DwoId, LineEncoding, LocationListsOffset, RangeListsOffset, UnitSectionOffset,
1608 };
1609 use crate::read::{self, Reader, ReaderOffset};
1610 use crate::write::{
1611 self, ConvertError, ConvertLineProgram, ConvertResult, Dwarf, LocationList, RangeList,
1612 };
1613
1614 type FnvHashMap<K, V> = hashbrown::HashMap<K, V, fnv::FnvBuildHasher>;
1615
1616 #[derive(Debug, Default)]
1617 struct FilterDependencies {
1618 edges: FnvHashMap<UnitSectionOffset, Vec<UnitSectionOffset>>,
1619 required: Vec<UnitSectionOffset>,
1620 }
1621
1622 impl FilterDependencies {
1623 fn add_entry(&mut self, entry: UnitSectionOffset, deps: Vec<UnitSectionOffset>) {
1629 debug_assert!(!self.edges.contains_key(&entry));
1630 self.edges.insert(entry, deps);
1631 }
1632
1633 fn add_edge(&mut self, from: UnitSectionOffset, to: UnitSectionOffset) {
1640 self.edges.get_mut(&from).unwrap().push(to);
1641 }
1642
1643 fn require_entry(&mut self, entry: UnitSectionOffset) {
1648 self.required.push(entry);
1649 }
1650
1651 fn get_reachable(mut self) -> Vec<UnitSectionOffset> {
1653 let mut reachable = Vec::new();
1654 let mut queue = vec![self.required];
1655 while let Some(entries) = queue.pop() {
1656 for entry in entries {
1657 if let Some(deps) = self.edges.remove(&entry) {
1658 reachable.push(entry);
1659 queue.push(deps);
1660 }
1661 }
1662 }
1663 reachable.sort_unstable();
1664 reachable
1665 }
1666 }
1667
1668 #[derive(Debug)]
1702 pub struct FilterUnitSection<'a, R: Reader<Offset = usize>> {
1703 dwarf: &'a read::Dwarf<R>,
1704 unit_headers: read::DebugInfoUnitHeadersIter<R>,
1705 skeleton_unit: Option<read::UnitRef<'a, R>>,
1706 units: Vec<read::Unit<R>>,
1707 deps: FilterDependencies,
1708 }
1709
1710 impl<'a, R: Reader<Offset = usize>> FilterUnitSection<'a, R> {
1711 pub fn new(dwarf: &'a read::Dwarf<R>) -> ConvertResult<Self> {
1724 Ok(FilterUnitSection {
1725 dwarf,
1726 unit_headers: dwarf.units(),
1727 skeleton_unit: None,
1728 units: Vec::new(),
1729 deps: FilterDependencies::default(),
1730 })
1731 }
1732
1733 pub fn new_split(
1749 dwarf: &'a read::Dwarf<R>,
1750 skeleton_unit: read::UnitRef<'a, R>,
1751 ) -> ConvertResult<Self> {
1752 Ok(FilterUnitSection {
1753 dwarf,
1754 unit_headers: dwarf.units(),
1755 skeleton_unit: Some(skeleton_unit),
1756 units: Vec::new(),
1757 deps: FilterDependencies::default(),
1758 })
1759 }
1760
1761 pub fn read_unit(&'_ mut self) -> ConvertResult<Option<FilterUnit<'_, R>>> {
1763 let Some(header) = self.unit_headers.next()? else {
1764 return Ok(None);
1765 };
1766 let mut unit = self.dwarf.unit(header)?;
1767 if let Some(skeleton_unit) = self.skeleton_unit {
1768 unit.copy_relocated_attributes(&skeleton_unit);
1769 }
1770 self.units.push(unit);
1771 let unit = self.units.last().unwrap().unit_ref(self.dwarf);
1772
1773 FilterUnit::new(unit, self.skeleton_unit, &mut self.deps).map(Some)
1774 }
1775 }
1776
1777 #[derive(Debug)]
1784 pub struct FilterUnit<'a, R: Reader<Offset = usize>> {
1785 pub read_unit: read::UnitRef<'a, R>,
1787 pub read_skeleton_unit: Option<read::UnitRef<'a, R>>,
1789 entries: read::EntriesRaw<'a, R>,
1790 parents: Vec<FilterParent>,
1791 deps: &'a mut FilterDependencies,
1792 }
1793
1794 #[derive(Debug, Clone, Copy)]
1795 struct FilterParent {
1796 depth: isize,
1797 offset: read::UnitOffset,
1798 tag: constants::DwTag,
1799 }
1800
1801 impl<'a, R: Reader<Offset = usize>> FilterUnit<'a, R> {
1802 fn new(
1803 read_unit: read::UnitRef<'a, R>,
1804 read_skeleton_unit: Option<read::UnitRef<'a, R>>,
1805 deps: &'a mut FilterDependencies,
1806 ) -> ConvertResult<Self> {
1807 let mut entries = read_unit.entries_raw(None)?;
1808 let abbrev = entries
1809 .read_abbreviation()?
1810 .ok_or(read::Error::MissingUnitDie)?;
1811 entries.skip_attributes(abbrev.attributes())?;
1812 Ok(FilterUnit {
1813 read_unit,
1814 read_skeleton_unit,
1815 entries,
1816 parents: Vec::new(),
1817 deps,
1818 })
1819 }
1820
1821 pub fn null_entry(&self) -> FilterUnitEntry<'a, R> {
1823 FilterUnitEntry::null(self.read_unit)
1824 }
1825
1826 pub fn read_entry(&mut self, entry: &mut FilterUnitEntry<'a, R>) -> ConvertResult<bool> {
1839 loop {
1840 if self.entries.is_empty() {
1841 return Ok(false);
1842 }
1843
1844 if !self.entries.read_entry(&mut entry.read_entry)? {
1845 continue;
1847 }
1848 entry.read_unit = self.read_unit;
1849 Self::filter_attributes(entry)?;
1850
1851 while let Some(parent) = self.parents.last() {
1852 if parent.depth < entry.depth {
1853 break;
1854 }
1855 self.parents.pop();
1856 }
1857 let parent = self.parents.last().copied();
1858 entry.parent = parent.map(|p| p.offset);
1859 entry.parent_tag = parent.map(|p| p.tag);
1860
1861 if entry.has_children() {
1862 self.parents.push(FilterParent {
1863 depth: entry.depth,
1864 offset: entry.offset,
1865 tag: entry.tag,
1866 });
1867 }
1868
1869 let entry_offset = entry.offset.to_unit_section_offset(&self.read_unit);
1870 let mut deps = Vec::new();
1871 for attr in &entry.attrs {
1872 self.add_attribute_refs(&mut deps, attr.value())?;
1873 }
1874 if let Some(parent) = parent {
1875 let parent_offset = parent.offset.to_unit_section_offset(&self.read_unit);
1876 deps.push(parent_offset);
1877 if parent.tag != constants::DW_TAG_namespace && entry.has_die_back_edge() {
1878 self.deps.add_edge(parent_offset, entry_offset);
1879 }
1880 }
1881 self.deps.add_entry(entry_offset, deps);
1882
1883 return Ok(true);
1884 }
1885 }
1886
1887 fn filter_attributes(entry: &mut FilterUnitEntry<'a, R>) -> ConvertResult<()> {
1888 entry.read_entry.attrs.retain(|attr| {
1889 match attr.name() {
1890 constants::DW_AT_sibling
1893 | constants::DW_AT_str_offsets_base
1894 | constants::DW_AT_addr_base
1895 | constants::DW_AT_rnglists_base
1896 | constants::DW_AT_loclists_base
1897 | constants::DW_AT_dwo_name
1898 | constants::DW_AT_GNU_addr_base
1899 | constants::DW_AT_GNU_ranges_base
1900 | constants::DW_AT_GNU_dwo_name
1901 | constants::DW_AT_GNU_dwo_id => false,
1902 _ => true,
1903 }
1904 });
1905 Ok(())
1906 }
1907
1908 fn add_attribute_refs(
1909 &mut self,
1910 deps: &mut Vec<UnitSectionOffset>,
1911 value: read::AttributeValue<R>,
1912 ) -> ConvertResult<()> {
1913 match value {
1914 read::AttributeValue::UnitRef(val) => {
1915 if val.is_in_bounds(&self.read_unit) {
1917 deps.push(val.to_unit_section_offset(&self.read_unit));
1918 }
1919 }
1920 read::AttributeValue::DebugInfoRef(val) => {
1921 let offset = val
1922 .to_unit_section_offset(&self.read_unit)
1923 .ok_or(ConvertError::InvalidDebugInfoRef)?;
1924 deps.push(offset);
1925 }
1926 read::AttributeValue::Exprloc(expression) => {
1927 self.add_expression_refs(deps, expression.clone())?;
1928 }
1929 read::AttributeValue::LocationListsRef(val) => {
1930 self.add_location_refs(deps, val)?;
1931 }
1932 read::AttributeValue::DebugLocListsIndex(index) => {
1933 self.add_location_refs(deps, self.read_unit.locations_offset(index)?)?;
1934 }
1935 _ => (),
1936 }
1937 Ok(())
1938 }
1939
1940 fn add_location_refs(
1941 &mut self,
1942 deps: &mut Vec<UnitSectionOffset>,
1943 offset: LocationListsOffset,
1944 ) -> ConvertResult<()> {
1945 let mut locations = self.read_unit.locations(offset)?;
1946 while let Some(location) = locations.next()? {
1947 self.add_expression_refs(deps, location.data)?;
1948 }
1949 Ok(())
1950 }
1951
1952 fn add_expression_refs(
1953 &mut self,
1954 deps: &mut Vec<UnitSectionOffset>,
1955 expression: read::Expression<R>,
1956 ) -> ConvertResult<()> {
1957 let mut ops = expression.operations(self.read_unit.encoding());
1958 while let Ok(Some(op)) = ops.next() {
1960 match op {
1961 read::Operation::Deref {
1962 base_type: offset, ..
1963 }
1964 | read::Operation::RegisterOffset {
1965 base_type: offset, ..
1966 }
1967 | read::Operation::TypedLiteral {
1968 base_type: offset, ..
1969 }
1970 | read::Operation::Convert {
1971 base_type: offset, ..
1972 }
1973 | read::Operation::Reinterpret {
1974 base_type: offset, ..
1975 }
1976 | read::Operation::ParameterRef { offset, .. }
1977 | read::Operation::Call {
1978 offset: read::DieReference::UnitRef(offset),
1979 ..
1980 } => {
1981 if offset.is_in_bounds(&self.read_unit) {
1982 deps.push(offset.to_unit_section_offset(&self.read_unit));
1983 }
1984 }
1985 read::Operation::Call {
1986 offset: read::DieReference::DebugInfoRef(ref_offset),
1987 ..
1988 } => {
1989 let offset = ref_offset
1990 .to_unit_section_offset(&self.read_unit)
1991 .ok_or(ConvertError::InvalidDebugInfoRef)?;
1992 deps.push(offset);
1993 }
1994 _ => {}
1995 }
1996 }
1997 Ok(())
1998 }
1999
2000 pub fn require_entry(&mut self, offset: read::UnitOffset) {
2006 debug_assert!(offset.is_in_bounds(&self.read_unit));
2007 self.deps
2008 .require_entry(offset.to_unit_section_offset(&self.read_unit));
2009 }
2010 }
2011
2012 #[derive(Debug)]
2020 #[non_exhaustive]
2021 pub struct FilterUnitEntry<'a, R: Reader<Offset = usize>> {
2022 pub read_unit: read::UnitRef<'a, R>,
2026 pub read_entry: read::DebuggingInformationEntry<R>,
2028 pub parent: Option<read::UnitOffset>,
2032 pub parent_tag: Option<constants::DwTag>,
2036 }
2037
2038 impl<'a, R: Reader<Offset = usize>> Deref for FilterUnitEntry<'a, R> {
2039 type Target = read::DebuggingInformationEntry<R>;
2040
2041 fn deref(&self) -> &Self::Target {
2042 &self.read_entry
2043 }
2044 }
2045
2046 impl<'a, R: Reader<Offset = usize>> FilterUnitEntry<'a, R> {
2047 pub fn null(read_unit: read::UnitRef<'a, R>) -> Self {
2051 FilterUnitEntry {
2052 read_unit,
2053 read_entry: read::DebuggingInformationEntry::null(),
2054 parent: None,
2055 parent_tag: None,
2056 }
2057 }
2058
2059 fn has_die_back_edge(&self) -> bool {
2068 match self.tag {
2069 constants::DW_TAG_array_type
2070 | constants::DW_TAG_atomic_type
2071 | constants::DW_TAG_base_type
2072 | constants::DW_TAG_class_type
2073 | constants::DW_TAG_const_type
2074 | constants::DW_TAG_dwarf_procedure
2075 | constants::DW_TAG_entry_point
2076 | constants::DW_TAG_enumeration_type
2077 | constants::DW_TAG_pointer_type
2078 | constants::DW_TAG_ptr_to_member_type
2079 | constants::DW_TAG_reference_type
2080 | constants::DW_TAG_restrict_type
2081 | constants::DW_TAG_rvalue_reference_type
2082 | constants::DW_TAG_string_type
2083 | constants::DW_TAG_structure_type
2084 | constants::DW_TAG_typedef
2085 | constants::DW_TAG_union_type
2086 | constants::DW_TAG_unspecified_type
2087 | constants::DW_TAG_volatile_type
2088 | constants::DW_TAG_coarray_type
2089 | constants::DW_TAG_common_block
2090 | constants::DW_TAG_dynamic_type
2091 | constants::DW_TAG_file_type
2092 | constants::DW_TAG_immutable_type
2093 | constants::DW_TAG_interface_type
2094 | constants::DW_TAG_set_type
2095 | constants::DW_TAG_shared_type
2096 | constants::DW_TAG_subroutine_type
2097 | constants::DW_TAG_packed_type
2098 | constants::DW_TAG_template_alias
2099 | constants::DW_TAG_namelist
2100 | constants::DW_TAG_namespace
2101 | constants::DW_TAG_imported_unit
2102 | constants::DW_TAG_imported_declaration
2103 | constants::DW_TAG_imported_module
2104 | constants::DW_TAG_module => false,
2105 constants::DW_TAG_subprogram => self.has_attr(constants::DW_AT_declaration),
2106 _ => true,
2107 }
2108 }
2109 }
2110
2111 #[derive(Debug)]
2115 pub struct ConvertUnitSection<'a, R: Reader<Offset = usize>> {
2116 read_dwarf: &'a read::Dwarf<R>,
2117 read_units: Vec<(read::Unit<R>, UnitId)>,
2118 read_unit_index: usize,
2120 read_skeleton_unit: Option<read::UnitRef<'a, R>>,
2124 entry_ids: FnvHashMap<UnitSectionOffset, (UnitId, UnitEntryId)>,
2125 dwarf: &'a mut Dwarf,
2126 }
2127
2128 impl<'a, R: Reader<Offset = usize>> ConvertUnitSection<'a, R> {
2129 pub(crate) fn new(
2131 read_dwarf: &'a read::Dwarf<R>,
2132 dwarf: &'a mut Dwarf,
2133 ) -> ConvertResult<Self> {
2134 let mut convert = ConvertUnitSection {
2135 read_dwarf,
2136 read_units: Vec::new(),
2137 read_unit_index: 0,
2138 read_skeleton_unit: None,
2139 entry_ids: FnvHashMap::default(),
2140 dwarf,
2141 };
2142
2143 let mut offsets = Vec::new();
2146 let mut read_units = read_dwarf.units();
2147 while let Some(read_unit) = read_units.next()? {
2148 let read_unit = read_dwarf.unit(read_unit)?;
2149 read_entry_offsets(&read_unit, &mut offsets)?;
2150 convert.reserve_unit(read_unit, &offsets);
2151 }
2152
2153 Ok(convert)
2154 }
2155
2156 pub(crate) fn new_with_filter(
2162 dwarf: &'a mut Dwarf,
2163 filter: FilterUnitSection<'a, R>,
2164 ) -> ConvertResult<Self> {
2165 let mut convert = ConvertUnitSection {
2166 read_dwarf: filter.dwarf,
2167 read_units: Vec::new(),
2168 read_unit_index: 0,
2169 read_skeleton_unit: filter.skeleton_unit,
2170 entry_ids: FnvHashMap::default(),
2171 dwarf,
2172 };
2173
2174 let offsets = filter.deps.get_reachable();
2175
2176 let mut start;
2178 let mut end = 0;
2179 for unit in filter.units {
2180 start = end;
2181 while let Some(offset) = offsets.get(end) {
2182 if offset.to_unit_offset(&unit).is_none() {
2183 break;
2184 }
2185 end += 1;
2186 }
2187 convert.reserve_unit(unit, &offsets[start..end]);
2188 }
2189 debug_assert_eq!(end, offsets.len());
2190
2191 Ok(convert)
2192 }
2193
2194 fn reserve_unit(&mut self, unit: read::Unit<R>, offsets: &[UnitSectionOffset]) {
2198 let root_offset = unit.header.root_offset().to_unit_section_offset(&unit);
2199
2200 let unit_id = self
2201 .dwarf
2202 .units
2203 .add(Unit::new(unit.encoding(), LineProgram::none()));
2204 self.read_units.push((unit, unit_id));
2205 let unit = self.dwarf.units.get_mut(unit_id);
2206
2207 self.entry_ids.insert(root_offset, (unit_id, unit.root()));
2208 for offset in offsets {
2209 self.entry_ids.insert(*offset, (unit_id, unit.reserve()));
2210 }
2211 }
2212
2213 pub fn read_unit(
2220 &mut self,
2221 ) -> ConvertResult<Option<(ConvertUnit<'_, R>, ConvertUnitEntry<'_, R>)>> {
2222 let Some((read_unit, unit_id)) = self.read_units.get(self.read_unit_index) else {
2223 return Ok(None);
2224 };
2225 self.read_unit_index += 1;
2226
2227 let read_unit = read_unit.unit_ref(self.read_dwarf);
2228
2229 let mut unit = ConvertUnit {
2230 read_unit,
2231 read_skeleton_unit: self.read_skeleton_unit,
2232 unit_id: *unit_id,
2233 unit: self.dwarf.units.get_mut(*unit_id),
2234 entry_ids: &self.entry_ids,
2235 line_strings: &mut self.dwarf.line_strings,
2236 strings: &mut self.dwarf.strings,
2237 line_program_files: Vec::new(),
2238 read_entries: read_unit.entries_raw(None)?,
2239 parents: Vec::new(),
2240 };
2241 let mut root_entry = unit.null_entry();
2242 unit.read_entry(&mut root_entry)?
2243 .ok_or(read::Error::MissingUnitDie)?;
2244 Ok(Some((unit, root_entry)))
2245 }
2246 }
2247
2248 #[derive(Debug)]
2253 pub struct ConvertSplitUnitSection<'a, R: Reader<Offset = usize>> {
2254 read_dwarf: &'a read::Dwarf<R>,
2255 read_unit: read::Unit<R>,
2256 read_skeleton_unit: read::UnitRef<'a, R>,
2257 entry_ids: FnvHashMap<UnitSectionOffset, (UnitId, UnitEntryId)>,
2258 unit_id: UnitId,
2259 unit: &'a mut write::Unit,
2260 line_strings: &'a mut write::LineStringTable,
2261 strings: &'a mut write::StringTable,
2262 }
2263
2264 impl<'a, R: Reader<Offset = usize>> ConvertSplitUnitSection<'a, R> {
2265 fn new(
2266 skeleton: &'a mut ConvertUnit<'a, R>,
2267 split_dwarf: &'a read::Dwarf<R>,
2268 ) -> ConvertResult<Self> {
2269 debug_assert!(skeleton.read_skeleton_unit.is_none());
2270
2271 let split_unit_header = split_dwarf
2272 .units()
2273 .next()?
2274 .ok_or(read::Error::MissingSplitUnit)?;
2275 let mut split_unit = split_dwarf.unit(split_unit_header)?;
2276 split_unit.copy_relocated_attributes(&skeleton.read_unit);
2277
2278 let mut offsets = Vec::new();
2279 read_entry_offsets(&split_unit, &mut offsets)?;
2280
2281 Self::new_with_offsets(skeleton, split_dwarf, split_unit, offsets)
2282 }
2283
2284 fn new_with_filter(
2285 skeleton: &'a mut ConvertUnit<'a, R>,
2286 filter: FilterUnitSection<'a, R>,
2287 ) -> ConvertResult<Self> {
2288 debug_assert!(skeleton.read_skeleton_unit.is_none());
2289
2290 let split_unit = filter
2291 .units
2292 .into_iter()
2293 .next()
2294 .ok_or(read::Error::MissingSplitUnit)?;
2295
2296 let offsets = filter.deps.get_reachable();
2297
2298 Self::new_with_offsets(skeleton, filter.dwarf, split_unit, offsets)
2299 }
2300
2301 fn new_with_offsets(
2302 skeleton: &'a mut ConvertUnit<'a, R>,
2303 split_dwarf: &'a read::Dwarf<R>,
2304 split_unit: read::Unit<R>,
2305 offsets: Vec<UnitSectionOffset>,
2306 ) -> ConvertResult<Self> {
2307 let root_offset = split_unit
2308 .header
2309 .root_offset()
2310 .to_unit_section_offset(&split_unit);
2311
2312 let unit_id = skeleton.unit_id;
2314 let unit = &mut *skeleton.unit;
2315
2316 let mut entry_ids = FnvHashMap::default();
2317 entry_ids.insert(root_offset, (unit_id, unit.root()));
2318 for offset in offsets {
2319 entry_ids.insert(offset, (unit_id, unit.reserve()));
2320 }
2321
2322 Ok(ConvertSplitUnitSection {
2323 read_dwarf: split_dwarf,
2324 read_unit: split_unit,
2325 read_skeleton_unit: skeleton.read_unit,
2326 entry_ids,
2327 unit_id,
2328 unit,
2329 line_strings: skeleton.line_strings,
2330 strings: skeleton.strings,
2331 })
2332 }
2333
2334 pub fn read_unit(
2341 &'_ mut self,
2342 ) -> ConvertResult<(ConvertUnit<'_, R>, ConvertUnitEntry<'_, R>)> {
2343 let read_unit = self.read_unit.unit_ref(self.read_dwarf);
2344
2345 let mut unit = ConvertUnit {
2346 read_unit,
2347 read_skeleton_unit: Some(self.read_skeleton_unit),
2348 unit_id: self.unit_id,
2349 unit: self.unit,
2350 entry_ids: &self.entry_ids,
2351 line_strings: self.line_strings,
2352 strings: self.strings,
2353 line_program_files: Vec::new(),
2354 read_entries: read_unit.entries_raw(None)?,
2355 parents: Vec::new(),
2356 };
2357 let mut root_entry = unit.null_entry();
2358 unit.read_entry(&mut root_entry)?
2359 .ok_or(read::Error::MissingUnitDie)?;
2360 Ok((unit, root_entry))
2361 }
2362 }
2363
2364 fn read_entry_offsets<R: Reader<Offset = usize>>(
2370 unit: &read::Unit<R>,
2371 offsets: &mut Vec<UnitSectionOffset>,
2372 ) -> ConvertResult<()> {
2373 let mut read_entries = unit.entries_raw(None)?;
2374
2375 let abbrev = read_entries
2377 .read_abbreviation()?
2378 .ok_or(read::Error::MissingUnitDie)?;
2379 read_entries.skip_attributes(abbrev.attributes())?;
2380
2381 offsets.clear();
2382 while !read_entries.is_empty() {
2383 let offset = read_entries.next_offset();
2384 let Some(abbrev) = read_entries.read_abbreviation()? else {
2385 continue;
2386 };
2387 read_entries.skip_attributes(abbrev.attributes())?;
2388 offsets.push(offset.to_unit_section_offset(unit));
2389 }
2390
2391 Ok(())
2392 }
2393
2394 #[derive(Debug)]
2449 pub struct ConvertUnit<'a, R: Reader<Offset = usize>> {
2450 pub read_unit: read::UnitRef<'a, R>,
2452 pub read_skeleton_unit: Option<read::UnitRef<'a, R>>,
2454 unit_id: UnitId,
2455 pub unit: &'a mut write::Unit,
2457 pub line_strings: &'a mut write::LineStringTable,
2459 pub strings: &'a mut write::StringTable,
2461 line_program_files: Vec<FileId>,
2462 entry_ids: &'a FnvHashMap<UnitSectionOffset, (UnitId, UnitEntryId)>,
2463 read_entries: read::EntriesRaw<'a, R>,
2464 parents: Vec<(isize, UnitEntryId)>,
2465 }
2466
2467 impl<'a, R: Reader<Offset = usize>> ConvertUnit<'a, R> {
2468 pub fn convert_split(
2497 &'a mut self,
2498 split_dwarf: &'a read::Dwarf<R>,
2499 ) -> ConvertResult<ConvertSplitUnitSection<'a, R>> {
2500 ConvertSplitUnitSection::new(self, split_dwarf)
2501 }
2502
2503 pub fn convert_split_with_filter(
2542 &'a mut self,
2543 filter: FilterUnitSection<'a, R>,
2544 ) -> ConvertResult<ConvertSplitUnitSection<'a, R>> {
2545 ConvertSplitUnitSection::new_with_filter(self, filter)
2546 }
2547
2548 pub fn read_line_program(
2558 &'_ mut self,
2559 encoding: Option<Encoding>,
2560 line_encoding: Option<LineEncoding>,
2561 ) -> ConvertResult<Option<ConvertLineProgram<'_, R>>> {
2562 let read_unit = self.read_skeleton_unit.unwrap_or(self.read_unit);
2563 let Some(read_program) = &read_unit.line_program else {
2564 return Ok(None);
2565 };
2566 ConvertLineProgram::new(
2567 read_unit.dwarf,
2568 read_program.clone(),
2569 self.read_skeleton_unit
2571 .and_then(|_| self.read_unit.name.clone()),
2572 encoding,
2573 line_encoding,
2574 self.line_strings,
2575 self.strings,
2576 )
2577 .map(Some)
2578 }
2579
2580 pub fn set_line_program(
2585 &mut self,
2586 line_program: LineProgram,
2587 line_program_files: Vec<FileId>,
2588 ) {
2589 self.unit.line_program = line_program;
2590 self.line_program_files = line_program_files;
2591 }
2592
2593 pub fn null_entry(&self) -> ConvertUnitEntry<'a, R> {
2595 ConvertUnitEntry::null(self.read_unit)
2596 }
2597
2598 pub fn read_entry(
2608 &mut self,
2609 entry: &mut ConvertUnitEntry<'a, R>,
2610 ) -> ConvertResult<Option<Option<UnitEntryId>>> {
2611 loop {
2612 if self.read_entries.is_empty() {
2613 return Ok(None);
2614 }
2615
2616 if !self.read_entries.read_entry(&mut entry.read_entry)? {
2617 continue;
2619 };
2620 entry.read_unit = self.read_unit;
2621 entry.filter_attributes();
2622
2623 let section_offset = entry.offset.to_unit_section_offset(&self.read_unit);
2624 let id = self.entry_ids.get(§ion_offset).map(|entry| entry.1);
2625
2626 entry.parent = None;
2627 while let Some((parent_depth, parent_id)) = self.parents.last().copied() {
2628 if parent_depth < entry.depth {
2629 entry.parent = Some(parent_id);
2630 break;
2631 }
2632 self.parents.pop();
2633 }
2634
2635 if let Some(id) = id
2636 && entry.has_children()
2637 {
2638 self.parents.push((entry.depth, id));
2639 }
2640
2641 return Ok(Some(id));
2642 }
2643 }
2644
2645 pub fn add_entry(
2657 &mut self,
2658 id: Option<UnitEntryId>,
2659 entry: &ConvertUnitEntry<'_, R>,
2660 ) -> UnitEntryId {
2661 let parent = entry.parent.unwrap_or(self.unit.root());
2662 let id = match id {
2663 Some(id) => {
2664 self.unit.add_reserved(id, parent, entry.tag);
2665 id
2666 }
2667 None => self.unit.add(parent, entry.tag),
2668 };
2669 let new_entry = self.unit.get_mut(id);
2670 new_entry.set_sibling(entry.sibling);
2671 new_entry.reserve(entry.attrs.len());
2672 id
2673 }
2674
2675 pub fn write<W: Writer>(&mut self, sections: &mut Sections<W>) -> Result<()> {
2684 let abbrev_offset = sections.debug_abbrev.offset();
2685 let mut abbrevs = AbbreviationTable::default();
2686 self.unit.write(
2687 sections,
2688 abbrev_offset,
2689 &mut abbrevs,
2690 self.line_strings,
2691 self.strings,
2692 )?;
2693 abbrevs.write(&mut sections.debug_abbrev)?;
2694 self.unit.free();
2695 Ok(())
2696 }
2697
2698 pub fn skip(&mut self) {
2705 self.unit.skip();
2706 self.unit.free();
2707 }
2708
2709 pub fn convert(
2719 &mut self,
2720 root_entry: ConvertUnitEntry<'a, R>,
2721 convert_address: &dyn Fn(u64) -> Option<Address>,
2722 ) -> ConvertResult<()> {
2723 if let Some(convert_program) = self.read_line_program(None, None)? {
2724 let (program, files) = convert_program.convert(convert_address)?;
2725 self.set_line_program(program, files);
2726 }
2727 self.convert_attributes(self.unit.root(), &root_entry, convert_address)?;
2728 let mut entry = root_entry;
2729 while let Some(id) = self.read_entry(&mut entry)? {
2730 if id.is_none() {
2731 continue;
2732 }
2733 let id = self.add_entry(id, &entry);
2734 self.convert_attributes(id, &entry, convert_address)?;
2735 }
2736 Ok(())
2737 }
2738
2739 pub(crate) fn convert_attributes(
2740 &mut self,
2741 id: UnitEntryId,
2742 entry: &ConvertUnitEntry<'_, R>,
2743 convert_address: &dyn Fn(u64) -> Option<Address>,
2744 ) -> ConvertResult<()> {
2745 for attr in &entry.attrs {
2746 if attr.name() == constants::DW_AT_GNU_locviews {
2747 } else {
2750 let value =
2751 self.convert_attribute_value(entry.read_unit, attr, convert_address)?;
2752 self.unit.get_mut(id).set(attr.name(), value);
2753 }
2754 }
2755 Ok(())
2756 }
2757
2758 pub fn convert_attribute_value(
2765 &mut self,
2766 read_unit: read::UnitRef<'_, R>,
2767 attr: &read::Attribute<R>,
2768 convert_address: &dyn Fn(u64) -> Option<Address>,
2769 ) -> ConvertResult<AttributeValue> {
2770 if attr.form() == constants::DW_FORM_implicit_const {
2771 let implicit_const_value = match attr.raw_value() {
2772 read::AttributeValue::Sdata(val) => val,
2773 _ => return Err(ConvertError::InvalidAttributeValue),
2774 };
2775 return Ok(AttributeValue::ImplicitConst(implicit_const_value));
2779 }
2780 Ok(match attr.value() {
2781 read::AttributeValue::Addr(val) => match (convert_address)(val) {
2782 Some(val) => AttributeValue::Address(val),
2783 None => return Err(ConvertError::InvalidAddress),
2784 },
2785 read::AttributeValue::Block(r) => AttributeValue::Block(r.to_slice()?.into()),
2786 read::AttributeValue::Data1(val) => AttributeValue::Data1(val),
2787 read::AttributeValue::Data2(val) => AttributeValue::Data2(val),
2788 read::AttributeValue::Data4(val) => AttributeValue::Data4(val),
2789 read::AttributeValue::Data8(val) => AttributeValue::Data8(val),
2790 read::AttributeValue::Data16(val) => AttributeValue::Data16(val),
2791 read::AttributeValue::Sdata(val) => AttributeValue::Sdata(val),
2792 read::AttributeValue::Udata(val) => AttributeValue::Udata(val),
2793 read::AttributeValue::Exprloc(expression) => {
2794 if attr.name() == constants::DW_AT_vtable_elem_location {
2795 let bytecode = expression.0.to_slice()?;
2796 if bytecode.first().copied() == Some(constants::DW_OP_constu.0) {
2797 return Ok(AttributeValue::Exprloc(Expression::raw(bytecode.to_vec())));
2802 }
2803 }
2804 let expression =
2805 self.convert_expression(read_unit, expression, convert_address)?;
2806 AttributeValue::Exprloc(expression)
2807 }
2808 read::AttributeValue::Flag(val) => {
2809 if attr.form() == constants::DW_FORM_flag_present {
2810 AttributeValue::FlagPresent
2811 } else {
2812 AttributeValue::Flag(val)
2813 }
2814 }
2815 read::AttributeValue::DebugAddrIndex(index) => {
2816 let val = read_unit.address(index)?;
2817 match convert_address(val) {
2818 Some(val) => AttributeValue::Address(val),
2819 None => return Err(ConvertError::InvalidAddress),
2820 }
2821 }
2822 read::AttributeValue::UnitRef(val) => {
2823 AttributeValue::UnitRef(self.convert_unit_ref(val)?)
2825 }
2826 read::AttributeValue::DebugInfoRef(val) => {
2827 AttributeValue::DebugInfoRef(self.convert_debug_info_ref(val)?)
2829 }
2830 read::AttributeValue::DebugInfoRefSup(val) => AttributeValue::DebugInfoRefSup(val),
2831 read::AttributeValue::DebugLineRef(val) => {
2832 if Some(val)
2834 != read_unit
2835 .line_program
2836 .as_ref()
2837 .map(|program| program.header().offset())
2838 {
2839 return Err(ConvertError::InvalidLineRef);
2840 };
2841 AttributeValue::LineProgramRef
2842 }
2843 read::AttributeValue::DebugMacinfoRef(val) => AttributeValue::DebugMacinfoRef(val),
2844 read::AttributeValue::DebugMacroRef(val) => AttributeValue::DebugMacroRef(val),
2845 read::AttributeValue::LocationListsRef(val) => {
2846 let loc_list = self.convert_location_list(read_unit, val, convert_address)?;
2847 let loc_id = self.unit.locations.add(loc_list);
2848 AttributeValue::LocationListRef(loc_id)
2849 }
2850 read::AttributeValue::DebugLocListsIndex(index) => {
2851 let offset = read_unit.locations_offset(index)?;
2852 let loc_list =
2853 self.convert_location_list(read_unit, offset, convert_address)?;
2854 let loc_id = self.unit.locations.add(loc_list);
2855 AttributeValue::LocationListRef(loc_id)
2856 }
2857 read::AttributeValue::RangeListsRef(offset) => {
2858 let offset = read_unit.ranges_offset_from_raw(offset);
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::DebugRngListsIndex(index) => {
2864 let offset = read_unit.ranges_offset(index)?;
2865 let range_list = self.convert_range_list(read_unit, offset, convert_address)?;
2866 let range_id = self.unit.ranges.add(range_list);
2867 AttributeValue::RangeListRef(range_id)
2868 }
2869 read::AttributeValue::DebugTypesRef(val) => AttributeValue::DebugTypesRef(val),
2870 read::AttributeValue::DebugStrRef(offset) => {
2871 let r = read_unit.string(offset)?;
2872 let id = self.strings.add(r.to_slice()?);
2873 AttributeValue::StringRef(id)
2874 }
2875 read::AttributeValue::DebugStrRefSup(val) => AttributeValue::DebugStrRefSup(val),
2876 read::AttributeValue::DebugStrOffsetsIndex(index) => {
2877 let offset = read_unit.string_offset(index)?;
2878 let r = read_unit.string(offset)?;
2879 let id = self.strings.add(r.to_slice()?);
2880 AttributeValue::StringRef(id)
2881 }
2882 read::AttributeValue::DebugLineStrRef(offset) => {
2883 let r = read_unit.line_string(offset)?;
2884 let id = self.line_strings.add(r.to_slice()?);
2885 AttributeValue::LineStringRef(id)
2886 }
2887 read::AttributeValue::String(r) => AttributeValue::String(r.to_slice()?.into()),
2888 read::AttributeValue::Encoding(val) => AttributeValue::Encoding(val),
2889 read::AttributeValue::DecimalSign(val) => AttributeValue::DecimalSign(val),
2890 read::AttributeValue::Endianity(val) => AttributeValue::Endianity(val),
2891 read::AttributeValue::Accessibility(val) => AttributeValue::Accessibility(val),
2892 read::AttributeValue::Visibility(val) => AttributeValue::Visibility(val),
2893 read::AttributeValue::Virtuality(val) => AttributeValue::Virtuality(val),
2894 read::AttributeValue::Language(val) => AttributeValue::Language(val),
2895 read::AttributeValue::AddressClass(val) => AttributeValue::AddressClass(val),
2896 read::AttributeValue::IdentifierCase(val) => AttributeValue::IdentifierCase(val),
2897 read::AttributeValue::CallingConvention(val) => {
2898 AttributeValue::CallingConvention(val)
2899 }
2900 read::AttributeValue::Inline(val) => AttributeValue::Inline(val),
2901 read::AttributeValue::Ordering(val) => AttributeValue::Ordering(val),
2902 read::AttributeValue::FileIndex(val) => {
2903 AttributeValue::FileIndex(self.convert_file_index(read_unit, val)?)
2904 }
2905 read::AttributeValue::DwoId(DwoId(val)) => AttributeValue::Udata(val),
2906 read::AttributeValue::SecOffset(_) => {
2908 return Err(ConvertError::InvalidAttributeValue);
2909 }
2910 read::AttributeValue::DebugAddrBase(_)
2913 | read::AttributeValue::DebugLocListsBase(_)
2914 | read::AttributeValue::DebugRngListsBase(_)
2915 | read::AttributeValue::DebugStrOffsetsBase(_) => {
2916 return Err(ConvertError::InvalidAttributeValue);
2917 }
2918 })
2919 }
2920
2921 pub fn convert_expression(
2925 &self,
2926 read_unit: read::UnitRef<'_, R>,
2927 expression: read::Expression<R>,
2928 convert_address: &dyn Fn(u64) -> Option<Address>,
2929 ) -> ConvertResult<Expression> {
2930 Expression::from(
2931 expression,
2932 read_unit.encoding(),
2933 Some(read_unit),
2934 convert_address,
2935 self,
2936 )
2937 }
2938
2939 pub fn convert_file_index(
2944 &self,
2945 read_unit: read::UnitRef<'_, R>,
2946 index: u64,
2947 ) -> ConvertResult<Option<FileId>> {
2948 if index == 0 && read_unit.encoding().version <= 4 {
2949 return Ok(None);
2950 }
2951 match self.line_program_files.get(index as usize) {
2952 Some(id) => Ok(Some(*id)),
2953 None => Err(ConvertError::InvalidFileIndex),
2954 }
2955 }
2956
2957 pub fn convert_location_list(
2961 &self,
2962 read_unit: read::UnitRef<'_, R>,
2963 offset: LocationListsOffset,
2964 convert_address: &dyn Fn(u64) -> Option<Address>,
2965 ) -> ConvertResult<LocationList> {
2966 let iter = read_unit.raw_locations(offset)?;
2967 LocationList::from(iter, read_unit, convert_address, self)
2968 }
2969
2970 pub fn convert_range_list(
2974 &self,
2975 read_unit: read::UnitRef<'_, R>,
2976 offset: RangeListsOffset,
2977 convert_address: &dyn Fn(u64) -> Option<Address>,
2978 ) -> ConvertResult<RangeList> {
2979 let iter = read_unit.raw_ranges(offset)?;
2980 RangeList::from(iter, read_unit, convert_address)
2981 }
2982
2983 pub fn convert_unit_ref(&self, entry: read::UnitOffset) -> ConvertResult<UnitEntryId> {
2988 if !entry.is_in_bounds(&self.read_unit) {
2989 return Err(ConvertError::InvalidUnitRef);
2990 }
2991 let id = self
2992 .entry_ids
2993 .get(&entry.to_unit_section_offset(&self.read_unit))
2994 .ok_or(ConvertError::InvalidUnitRef)?;
2995 Ok(id.1)
2996 }
2997
2998 pub fn convert_debug_info_ref(
3003 &self,
3004 entry: DebugInfoOffset,
3005 ) -> ConvertResult<DebugInfoRef> {
3006 let offset = entry
3008 .to_unit_section_offset(&self.read_unit)
3009 .ok_or(ConvertError::InvalidDebugInfoRef)?;
3010 let id = self
3011 .entry_ids
3012 .get(&offset)
3013 .ok_or(ConvertError::InvalidDebugInfoRef)?;
3014 Ok(DebugInfoRef::Entry(id.0, id.1))
3015 }
3016 }
3017
3018 #[derive(Debug)]
3024 #[non_exhaustive]
3025 pub struct ConvertUnitEntry<'a, R: Reader<Offset = usize>> {
3026 pub read_unit: read::UnitRef<'a, R>,
3030 pub read_entry: read::DebuggingInformationEntry<R>,
3032 pub sibling: bool,
3034 pub parent: Option<UnitEntryId>,
3039 }
3040
3041 impl<'a, R: Reader<Offset = usize>> Deref for ConvertUnitEntry<'a, R> {
3042 type Target = read::DebuggingInformationEntry<R>;
3043
3044 fn deref(&self) -> &Self::Target {
3045 &self.read_entry
3046 }
3047 }
3048
3049 impl<'a, R: Reader<Offset = usize>> ConvertUnitEntry<'a, R> {
3050 pub fn null(read_unit: read::UnitRef<'a, R>) -> Self {
3054 ConvertUnitEntry {
3055 read_unit,
3056 read_entry: read::DebuggingInformationEntry::null(),
3057 sibling: false,
3058 parent: None,
3059 }
3060 }
3061
3062 pub fn read(
3070 read_unit: read::UnitRef<'a, R>,
3071 offset: read::UnitOffset,
3072 ) -> ConvertResult<ConvertUnitEntry<'a, R>> {
3073 let mut read_entries = read_unit.entries_raw(Some(offset))?;
3074 let mut read_entry = read::DebuggingInformationEntry::null();
3075 if !read_entries.read_entry(&mut read_entry)? {
3076 return Err(read::Error::NoEntryAtGivenOffset(offset.0.into_u64()).into());
3078 };
3079
3080 let mut entry = ConvertUnitEntry {
3081 read_unit,
3082 read_entry,
3083 sibling: false,
3084 parent: None,
3085 };
3086 entry.filter_attributes();
3087 Ok(entry)
3088 }
3089
3090 fn filter_attributes(&mut self) {
3091 self.sibling = false;
3092 self.read_entry.attrs.retain(|attr| {
3093 match attr.name() {
3094 constants::DW_AT_sibling => {
3096 self.sibling = true;
3097 false
3098 }
3099 constants::DW_AT_str_offsets_base
3102 | constants::DW_AT_addr_base
3103 | constants::DW_AT_rnglists_base
3104 | constants::DW_AT_loclists_base
3105 | constants::DW_AT_dwo_name
3106 | constants::DW_AT_GNU_addr_base
3107 | constants::DW_AT_GNU_ranges_base
3108 | constants::DW_AT_GNU_dwo_name
3109 | constants::DW_AT_GNU_dwo_id => false,
3110 _ => true,
3111 }
3112 });
3113 }
3114 }
3115
3116 pub(crate) trait ConvertDebugInfoRef {
3117 fn convert_unit_ref(&self, entry: read::UnitOffset) -> ConvertResult<UnitEntryId>;
3118 fn convert_debug_info_ref(&self, entry: DebugInfoOffset) -> ConvertResult<DebugInfoRef>;
3119 }
3120
3121 impl<'a, R: Reader<Offset = usize>> ConvertDebugInfoRef for ConvertUnit<'a, R> {
3122 fn convert_unit_ref(&self, entry: read::UnitOffset) -> ConvertResult<UnitEntryId> {
3123 ConvertUnit::convert_unit_ref(self, entry)
3124 }
3125
3126 fn convert_debug_info_ref(&self, entry: DebugInfoOffset) -> ConvertResult<DebugInfoRef> {
3127 ConvertUnit::convert_debug_info_ref(self, entry)
3128 }
3129 }
3130
3131 pub(crate) struct NoConvertDebugInfoRef;
3132
3133 impl ConvertDebugInfoRef for NoConvertDebugInfoRef {
3134 fn convert_unit_ref(&self, _entry: read::UnitOffset) -> ConvertResult<UnitEntryId> {
3135 Err(ConvertError::InvalidUnitRef)
3136 }
3137
3138 fn convert_debug_info_ref(&self, _entry: DebugInfoOffset) -> ConvertResult<DebugInfoRef> {
3139 Err(ConvertError::InvalidDebugInfoRef)
3140 }
3141 }
3142}
3143
3144#[cfg(test)]
3145#[cfg(feature = "read")]
3146mod tests {
3147 use super::*;
3148 use crate::LittleEndian;
3149 use crate::common::LineEncoding;
3150 use crate::constants;
3151 use crate::read;
3152 use crate::write::{
3153 Dwarf, DwarfUnit, EndianVec, LineString, Location, LocationList, Range, RangeList,
3154 };
3155 use core::mem;
3156
3157 #[test]
3158 fn test_unit_table() {
3159 let mut dwarf = Dwarf::new();
3160 let unit_id1 = dwarf.units.add(Unit::new(
3161 Encoding {
3162 version: 4,
3163 address_size: 8,
3164 format: Format::Dwarf32,
3165 },
3166 LineProgram::none(),
3167 ));
3168 let unit2 = dwarf.units.add(Unit::new(
3169 Encoding {
3170 version: 2,
3171 address_size: 4,
3172 format: Format::Dwarf64,
3173 },
3174 LineProgram::none(),
3175 ));
3176 let unit3 = dwarf.units.add(Unit::new(
3177 Encoding {
3178 version: 5,
3179 address_size: 4,
3180 format: Format::Dwarf32,
3181 },
3182 LineProgram::none(),
3183 ));
3184 assert_eq!(dwarf.units.count(), 3);
3185 {
3186 let unit1 = dwarf.units.get_mut(unit_id1);
3187 assert_eq!(unit1.version(), 4);
3188 assert_eq!(unit1.address_size(), 8);
3189 assert_eq!(unit1.format(), Format::Dwarf32);
3190 assert_eq!(unit1.count(), 1);
3191
3192 let root_id = unit1.root();
3193 assert_eq!(root_id, UnitEntryId::new(unit1.base_id, 0));
3194 {
3195 let root = unit1.get_mut(root_id);
3196 assert_eq!(root.id(), root_id);
3197 assert!(root.parent().is_none());
3198 assert_eq!(root.tag(), constants::DW_TAG_compile_unit);
3199
3200 assert!(root.get(constants::DW_AT_producer).is_none());
3202 assert!(root.get_mut(constants::DW_AT_producer).is_none());
3203 let mut producer = AttributeValue::String(b"root"[..].into());
3204 root.set(constants::DW_AT_producer, producer.clone());
3205 assert_eq!(root.get(constants::DW_AT_producer), Some(&producer));
3206 assert_eq!(root.get_mut(constants::DW_AT_producer), Some(&mut producer));
3207
3208 let mut attrs = root.attrs();
3210 let attr = attrs.next().unwrap();
3211 assert_eq!(attr.name(), constants::DW_AT_producer);
3212 assert_eq!(attr.get(), &producer);
3213 assert!(attrs.next().is_none());
3214 }
3215
3216 let child1 = unit1.add(root_id, constants::DW_TAG_subprogram);
3217 assert_eq!(child1, UnitEntryId::new(unit1.base_id, 1));
3218 {
3219 let child1 = unit1.get_mut(child1);
3220 assert_eq!(child1.parent(), Some(root_id));
3221
3222 let tmp = AttributeValue::String(b"tmp"[..].into());
3223 child1.set(constants::DW_AT_name, tmp.clone());
3224 assert_eq!(child1.get(constants::DW_AT_name), Some(&tmp));
3225
3226 let name = AttributeValue::StringRef(dwarf.strings.add(&b"child1"[..]));
3228 {
3229 let attr = child1.attrs_mut().next().unwrap();
3230 assert_eq!(attr.name(), constants::DW_AT_name);
3231 attr.set(name.clone());
3232 }
3233 assert_eq!(child1.get(constants::DW_AT_name), Some(&name));
3234 }
3235
3236 let child2 = unit1.add(root_id, constants::DW_TAG_subprogram);
3237 assert_eq!(child2, UnitEntryId::new(unit1.base_id, 2));
3238 {
3239 let child2 = unit1.get_mut(child2);
3240 assert_eq!(child2.parent(), Some(root_id));
3241
3242 let tmp = AttributeValue::String(b"tmp"[..].into());
3243 child2.set(constants::DW_AT_name, tmp.clone());
3244 assert_eq!(child2.get(constants::DW_AT_name), Some(&tmp));
3245
3246 let name = AttributeValue::StringRef(dwarf.strings.add(&b"child2"[..]));
3248 child2.set(constants::DW_AT_name, name.clone());
3249 assert_eq!(child2.get(constants::DW_AT_name), Some(&name));
3250 }
3251
3252 {
3253 let root = unit1.get(root_id);
3254 assert_eq!(
3255 root.children().cloned().collect::<Vec<_>>(),
3256 vec![child1, child2]
3257 );
3258 }
3259 }
3260 {
3261 let unit2 = dwarf.units.get(unit2);
3262 assert_eq!(unit2.version(), 2);
3263 assert_eq!(unit2.address_size(), 4);
3264 assert_eq!(unit2.format(), Format::Dwarf64);
3265 assert_eq!(unit2.count(), 1);
3266
3267 let root = unit2.root();
3268 assert_eq!(root, UnitEntryId::new(unit2.base_id, 0));
3269 let root = unit2.get(root);
3270 assert_eq!(root.id(), UnitEntryId::new(unit2.base_id, 0));
3271 assert!(root.parent().is_none());
3272 assert_eq!(root.tag(), constants::DW_TAG_compile_unit);
3273 }
3274
3275 let mut sections = Sections::new(EndianVec::new(LittleEndian));
3276 dwarf.write(&mut sections).unwrap();
3277
3278 let read_dwarf = sections.read(LittleEndian);
3279 let mut read_units = read_dwarf.units();
3280
3281 {
3282 let read_unit1 = read_units.next().unwrap().unwrap();
3283 let unit1 = dwarf.units.get(unit_id1);
3284 assert_eq!(unit1.version(), read_unit1.version());
3285 assert_eq!(unit1.address_size(), read_unit1.address_size());
3286 assert_eq!(unit1.format(), read_unit1.format());
3287
3288 let read_unit1 = read_dwarf.unit(read_unit1).unwrap();
3289 let mut read_entries = read_unit1.entries();
3290
3291 let root = unit1.get(unit1.root());
3292 {
3293 let read_root = read_entries.next_dfs().unwrap().unwrap();
3294 assert_eq!(read_root.depth(), 0);
3295 assert_eq!(root.tag(), read_root.tag());
3296 assert!(read_root.has_children());
3297
3298 let producer = match root.get(constants::DW_AT_producer).unwrap() {
3299 AttributeValue::String(producer) => &**producer,
3300 otherwise => panic!("unexpected {:?}", otherwise),
3301 };
3302 assert_eq!(producer, b"root");
3303 let read_producer = read_root.attr_value(constants::DW_AT_producer).unwrap();
3304 assert_eq!(
3305 read_dwarf
3306 .attr_string(&read_unit1, read_producer)
3307 .unwrap()
3308 .slice(),
3309 producer
3310 );
3311 }
3312
3313 let mut children = root.children().cloned();
3314
3315 {
3316 let child = children.next().unwrap();
3317 assert_eq!(child, UnitEntryId::new(unit1.base_id, 1));
3318 let child = unit1.get(child);
3319 let read_child = read_entries.next_dfs().unwrap().unwrap();
3320 assert_eq!(read_child.depth(), 1);
3321 assert_eq!(child.tag(), read_child.tag());
3322 assert!(!read_child.has_children());
3323
3324 let name = match child.get(constants::DW_AT_name).unwrap() {
3325 AttributeValue::StringRef(name) => *name,
3326 otherwise => panic!("unexpected {:?}", otherwise),
3327 };
3328 let name = dwarf.strings.get(name);
3329 assert_eq!(name, b"child1");
3330 let read_name = read_child.attr_value(constants::DW_AT_name).unwrap();
3331 assert_eq!(
3332 read_dwarf
3333 .attr_string(&read_unit1, read_name)
3334 .unwrap()
3335 .slice(),
3336 name
3337 );
3338 }
3339
3340 {
3341 let child = children.next().unwrap();
3342 assert_eq!(child, UnitEntryId::new(unit1.base_id, 2));
3343 let child = unit1.get(child);
3344 let read_child = read_entries.next_dfs().unwrap().unwrap();
3345 assert_eq!(read_child.depth(), 1);
3346 assert_eq!(child.tag(), read_child.tag());
3347 assert!(!read_child.has_children());
3348
3349 let name = match child.get(constants::DW_AT_name).unwrap() {
3350 AttributeValue::StringRef(name) => *name,
3351 otherwise => panic!("unexpected {:?}", otherwise),
3352 };
3353 let name = dwarf.strings.get(name);
3354 assert_eq!(name, b"child2");
3355 let read_name = read_child.attr_value(constants::DW_AT_name).unwrap();
3356 assert_eq!(
3357 read_dwarf
3358 .attr_string(&read_unit1, read_name)
3359 .unwrap()
3360 .slice(),
3361 name
3362 );
3363 }
3364
3365 assert!(read_entries.next_dfs().unwrap().is_none());
3366 }
3367
3368 {
3369 let read_unit2 = read_units.next().unwrap().unwrap();
3370 let unit2 = dwarf.units.get(unit2);
3371 assert_eq!(unit2.version(), read_unit2.version());
3372 assert_eq!(unit2.address_size(), read_unit2.address_size());
3373 assert_eq!(unit2.format(), read_unit2.format());
3374
3375 let abbrevs = read_dwarf.abbreviations(&read_unit2).unwrap();
3376 let mut read_entries = read_unit2.entries(&abbrevs);
3377
3378 {
3379 let root = unit2.get(unit2.root());
3380 let read_root = read_entries.next_dfs().unwrap().unwrap();
3381 assert_eq!(read_root.depth(), 0);
3382 assert_eq!(root.tag(), read_root.tag());
3383 assert!(!read_root.has_children());
3384 }
3385
3386 assert!(read_entries.next_dfs().unwrap().is_none());
3387 }
3388
3389 {
3390 let read_unit3 = read_units.next().unwrap().unwrap();
3391 let unit3 = dwarf.units.get(unit3);
3392 assert_eq!(unit3.version(), read_unit3.version());
3393 assert_eq!(unit3.address_size(), read_unit3.address_size());
3394 assert_eq!(unit3.format(), read_unit3.format());
3395
3396 let abbrevs = read_dwarf.abbreviations(&read_unit3).unwrap();
3397 let mut read_entries = read_unit3.entries(&abbrevs);
3398
3399 {
3400 let root = unit3.get(unit3.root());
3401 let read_root = read_entries.next_dfs().unwrap().unwrap();
3402 assert_eq!(read_root.depth(), 0);
3403 assert_eq!(root.tag(), read_root.tag());
3404 assert!(!read_root.has_children());
3405 }
3406
3407 assert!(read_entries.next_dfs().unwrap().is_none());
3408 }
3409
3410 assert!(read_units.next().unwrap().is_none());
3411
3412 let convert_dwarf =
3413 Dwarf::from(&read_dwarf, &|address| Some(Address::Constant(address))).unwrap();
3414 assert_eq!(convert_dwarf.units.count(), dwarf.units.count());
3415
3416 for i in 0..convert_dwarf.units.count() {
3417 let unit_id = dwarf.units.id(i);
3418 let unit = dwarf.units.get(unit_id);
3419 let convert_unit_id = convert_dwarf.units.id(i);
3420 let convert_unit = convert_dwarf.units.get(convert_unit_id);
3421 assert_eq!(convert_unit.version(), unit.version());
3422 assert_eq!(convert_unit.address_size(), unit.address_size());
3423 assert_eq!(convert_unit.format(), unit.format());
3424 assert_eq!(convert_unit.count(), unit.count());
3425
3426 let root = unit.get(unit.root());
3427 let convert_root = convert_unit.get(convert_unit.root());
3428 assert_eq!(convert_root.tag(), root.tag());
3429 for (convert_attr, attr) in convert_root.attrs().zip(root.attrs()) {
3430 assert_eq!(convert_attr, attr);
3431 }
3432 }
3433 }
3434
3435 #[test]
3436 fn test_attribute_value() {
3437 let string_data = "string data";
3438 let line_string_data = "line string data";
3439
3440 let data = vec![1, 2, 3, 4];
3441 let read_data = read::EndianSlice::new(&[1, 2, 3, 4], LittleEndian);
3442
3443 let mut expression = Expression::new();
3444 expression.op_constu(57);
3445 let read_expression = read::Expression(read::EndianSlice::new(
3446 &[constants::DW_OP_constu.0, 57],
3447 LittleEndian,
3448 ));
3449
3450 let range = RangeList(vec![Range::StartEnd {
3451 begin: Address::Constant(0x1234),
3452 end: Address::Constant(0x2345),
3453 }]);
3454
3455 let location = LocationList(vec![Location::StartEnd {
3456 begin: Address::Constant(0x1234),
3457 end: Address::Constant(0x2345),
3458 data: expression.clone(),
3459 }]);
3460
3461 for &version in &[2, 3, 4, 5] {
3462 for &address_size in &[4, 8] {
3463 for &format in &[Format::Dwarf32, Format::Dwarf64] {
3464 let encoding = Encoding {
3465 format,
3466 version,
3467 address_size,
3468 };
3469
3470 let mut dwarf = Dwarf::new();
3471 let unit = dwarf.units.add(Unit::new(encoding, LineProgram::none()));
3472 let unit = dwarf.units.get_mut(unit);
3473 let loc_id = unit.locations.add(location.clone());
3474 let range_id = unit.ranges.add(range.clone());
3475 dwarf.strings.add("dummy string");
3477 let string_id = dwarf.strings.add(string_data);
3478 dwarf.line_strings.add("dummy line string");
3479 let line_string_id = dwarf.line_strings.add(line_string_data);
3480
3481 let mut attributes = vec![
3482 (
3483 constants::DW_AT_name,
3484 AttributeValue::Address(Address::Constant(0x1234)),
3485 read::AttributeValue::Addr(0x1234),
3486 ),
3487 (
3488 constants::DW_AT_name,
3489 AttributeValue::Block(data.clone()),
3490 read::AttributeValue::Block(read_data),
3491 ),
3492 (
3493 constants::DW_AT_name,
3494 AttributeValue::Data1(0x12),
3495 read::AttributeValue::Data1(0x12),
3496 ),
3497 (
3498 constants::DW_AT_name,
3499 AttributeValue::Data2(0x1234),
3500 read::AttributeValue::Data2(0x1234),
3501 ),
3502 (
3503 constants::DW_AT_name,
3504 AttributeValue::Data4(0x1234),
3505 read::AttributeValue::Data4(0x1234),
3506 ),
3507 (
3508 constants::DW_AT_name,
3509 AttributeValue::Data8(0x1234),
3510 read::AttributeValue::Data8(0x1234),
3511 ),
3512 (
3513 constants::DW_AT_name,
3514 AttributeValue::Data16(0x1234),
3515 read::AttributeValue::Data16(0x1234),
3516 ),
3517 (
3518 constants::DW_AT_name,
3519 AttributeValue::Sdata(0x1234),
3520 read::AttributeValue::Sdata(0x1234),
3521 ),
3522 (
3523 constants::DW_AT_name,
3524 AttributeValue::Udata(0x1234),
3525 read::AttributeValue::Udata(0x1234),
3526 ),
3527 (
3528 constants::DW_AT_name,
3529 AttributeValue::Flag(false),
3530 read::AttributeValue::Flag(false),
3531 ),
3532 (
3533 constants::DW_AT_name,
3534 AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x1234)),
3535 read::AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x1234)),
3536 ),
3537 (
3538 constants::DW_AT_macro_info,
3539 AttributeValue::DebugMacinfoRef(DebugMacinfoOffset(0x1234)),
3540 read::AttributeValue::SecOffset(0x1234),
3541 ),
3542 (
3543 constants::DW_AT_macros,
3544 AttributeValue::DebugMacroRef(DebugMacroOffset(0x1234)),
3545 read::AttributeValue::SecOffset(0x1234),
3546 ),
3547 (
3548 constants::DW_AT_name,
3549 AttributeValue::DebugTypesRef(DebugTypeSignature(0x1234)),
3550 read::AttributeValue::DebugTypesRef(DebugTypeSignature(0x1234)),
3551 ),
3552 (
3553 constants::DW_AT_name,
3554 AttributeValue::DebugStrRefSup(DebugStrOffset(0x1234)),
3555 read::AttributeValue::DebugStrRefSup(DebugStrOffset(0x1234)),
3556 ),
3557 (
3558 constants::DW_AT_name,
3559 AttributeValue::String(data.clone()),
3560 read::AttributeValue::String(read_data),
3561 ),
3562 (
3563 constants::DW_AT_encoding,
3564 AttributeValue::Encoding(constants::DwAte(0x12)),
3565 read::AttributeValue::Udata(0x12),
3566 ),
3567 (
3568 constants::DW_AT_decimal_sign,
3569 AttributeValue::DecimalSign(constants::DwDs(0x12)),
3570 read::AttributeValue::Udata(0x12),
3571 ),
3572 (
3573 constants::DW_AT_endianity,
3574 AttributeValue::Endianity(constants::DwEnd(0x12)),
3575 read::AttributeValue::Udata(0x12),
3576 ),
3577 (
3578 constants::DW_AT_accessibility,
3579 AttributeValue::Accessibility(constants::DwAccess(0x12)),
3580 read::AttributeValue::Udata(0x12),
3581 ),
3582 (
3583 constants::DW_AT_visibility,
3584 AttributeValue::Visibility(constants::DwVis(0x12)),
3585 read::AttributeValue::Udata(0x12),
3586 ),
3587 (
3588 constants::DW_AT_virtuality,
3589 AttributeValue::Virtuality(constants::DwVirtuality(0x12)),
3590 read::AttributeValue::Udata(0x12),
3591 ),
3592 (
3593 constants::DW_AT_language,
3594 AttributeValue::Language(constants::DwLang(0x12)),
3595 read::AttributeValue::Udata(0x12),
3596 ),
3597 (
3598 constants::DW_AT_address_class,
3599 AttributeValue::AddressClass(constants::DwAddr(0x12)),
3600 read::AttributeValue::Udata(0x12),
3601 ),
3602 (
3603 constants::DW_AT_identifier_case,
3604 AttributeValue::IdentifierCase(constants::DwId(0x12)),
3605 read::AttributeValue::Udata(0x12),
3606 ),
3607 (
3608 constants::DW_AT_calling_convention,
3609 AttributeValue::CallingConvention(constants::DwCc(0x12)),
3610 read::AttributeValue::Udata(0x12),
3611 ),
3612 (
3613 constants::DW_AT_ordering,
3614 AttributeValue::Ordering(constants::DwOrd(0x12)),
3615 read::AttributeValue::Udata(0x12),
3616 ),
3617 (
3618 constants::DW_AT_inline,
3619 AttributeValue::Inline(constants::DwInl(0x12)),
3620 read::AttributeValue::Udata(0x12),
3621 ),
3622 ];
3623 let mut attributes2 = Vec::new();
3624 if version >= 4 {
3625 attributes.push((
3626 constants::DW_AT_location,
3627 AttributeValue::Exprloc(expression.clone()),
3628 read::AttributeValue::Exprloc(read_expression),
3629 ));
3630 } else {
3631 attributes.push((
3632 constants::DW_AT_location,
3633 AttributeValue::Exprloc(expression.clone()),
3634 read::AttributeValue::Block(read_expression.0),
3635 ));
3636 }
3637 if version >= 4 {
3638 attributes.push((
3639 constants::DW_AT_name,
3640 AttributeValue::FlagPresent,
3641 read::AttributeValue::Flag(true),
3642 ));
3643 } else {
3644 attributes2.push((
3645 constants::DW_AT_name,
3646 AttributeValue::FlagPresent,
3647 read::AttributeValue::Flag(true),
3648 AttributeValue::Flag(true),
3649 ));
3650 };
3651 if version >= 5 {
3652 attributes.push((
3653 constants::DW_AT_language,
3654 AttributeValue::ImplicitConst(0x12),
3655 read::AttributeValue::Sdata(0x12),
3656 ));
3657 } else {
3658 attributes2.push((
3659 constants::DW_AT_language,
3660 AttributeValue::ImplicitConst(0x12),
3661 read::AttributeValue::Sdata(0x12),
3662 AttributeValue::Language(constants::DwLang(0x12)),
3663 ));
3664 }
3665
3666 let mut add_attribute = |name, value| {
3667 let entry_id = unit.add(unit.root(), constants::DW_TAG_subprogram);
3668 let entry = unit.get_mut(entry_id);
3669 entry.set(name, value);
3670 };
3671 for (name, value, _) in &attributes {
3672 add_attribute(*name, value.clone());
3673 }
3674 for (name, value, _, _) in &attributes2 {
3675 add_attribute(*name, value.clone());
3676 }
3677 add_attribute(
3678 constants::DW_AT_location,
3679 AttributeValue::LocationListRef(loc_id),
3680 );
3681 add_attribute(
3682 constants::DW_AT_ranges,
3683 AttributeValue::RangeListRef(range_id),
3684 );
3685 add_attribute(constants::DW_AT_name, AttributeValue::StringRef(string_id));
3686 add_attribute(
3687 constants::DW_AT_name,
3688 AttributeValue::LineStringRef(line_string_id),
3689 );
3690
3691 let mut sections = Sections::new(EndianVec::new(LittleEndian));
3692 dwarf.write(&mut sections).unwrap();
3693
3694 let read_dwarf = sections.read(LittleEndian);
3695 let mut read_units = read_dwarf.units();
3696 let read_unit = read_units.next().unwrap().unwrap();
3697 let read_unit = read_dwarf.unit(read_unit).unwrap();
3698 let read_unit = read_unit.unit_ref(&read_dwarf);
3699 let mut read_entries = read_unit.entries();
3700 let _root = read_entries.next_dfs().unwrap().unwrap();
3701
3702 let mut get_attribute = |name| {
3703 let entry = read_entries.next_dfs().unwrap().unwrap();
3704 *entry.attr(name).unwrap()
3705 };
3706 for (name, _, expect_value) in &attributes {
3707 let read_value = &get_attribute(*name).raw_value();
3708 let read_value = unsafe {
3711 mem::transmute::<
3712 &read::AttributeValue<read::EndianSlice<'_, LittleEndian>>,
3713 &read::AttributeValue<read::EndianSlice<'_, LittleEndian>>,
3714 >(read_value)
3715 };
3716 assert_eq!(read_value, expect_value);
3717 }
3718 for (name, _, expect_value, _) in &attributes2 {
3719 let read_value = &get_attribute(*name).raw_value();
3720 let read_value = unsafe {
3723 mem::transmute::<
3724 &read::AttributeValue<read::EndianSlice<'_, LittleEndian>>,
3725 &read::AttributeValue<read::EndianSlice<'_, LittleEndian>>,
3726 >(read_value)
3727 };
3728 assert_eq!(read_value, expect_value);
3729 }
3730
3731 let read_attr = get_attribute(constants::DW_AT_location).value();
3732 let read::AttributeValue::LocationListsRef(read_loc_offset) = read_attr else {
3733 panic!("unexpected {:?}", read_attr);
3734 };
3735 let mut read_locations = read_unit.locations(read_loc_offset).unwrap();
3736 let read_location = read_locations.next().unwrap().unwrap();
3737 assert_eq!(read_location.range.begin, 0x1234);
3738 assert_eq!(read_location.range.end, 0x2345);
3739 assert_eq!(read_location.data, read_expression);
3740
3741 let read_attr = get_attribute(constants::DW_AT_ranges).value();
3742 let read::AttributeValue::RangeListsRef(read_range_offset) = read_attr else {
3743 panic!("unexpected {:?}", read_attr);
3744 };
3745 let read_range_offset = read_unit.ranges_offset_from_raw(read_range_offset);
3746 let mut read_ranges = read_unit.ranges(read_range_offset).unwrap();
3747 let read_range = read_ranges.next().unwrap().unwrap();
3748 assert_eq!(read_range.begin, 0x1234);
3749 assert_eq!(read_range.end, 0x2345);
3750
3751 let read_string = get_attribute(constants::DW_AT_name).raw_value();
3752 let read::AttributeValue::DebugStrRef(read_string_offset) = read_string else {
3753 panic!("unexpected {:?}", read_string);
3754 };
3755 assert_eq!(
3756 read_dwarf.string(read_string_offset).unwrap().slice(),
3757 string_data.as_bytes()
3758 );
3759
3760 let read_line_string = get_attribute(constants::DW_AT_name).raw_value();
3761 let read::AttributeValue::DebugLineStrRef(read_line_string_offset) =
3762 read_line_string
3763 else {
3764 panic!("unexpected {:?}", read_line_string);
3765 };
3766 assert_eq!(
3767 read_dwarf
3768 .line_string(read_line_string_offset)
3769 .unwrap()
3770 .slice(),
3771 line_string_data.as_bytes()
3772 );
3773
3774 let convert_dwarf =
3775 Dwarf::from(&read_dwarf, &|address| Some(Address::Constant(address)))
3776 .unwrap();
3777 let convert_unit = convert_dwarf.units.get(convert_dwarf.units.id(0));
3778 let convert_root = convert_unit.get(convert_unit.root());
3779 let mut convert_entries = convert_root.children();
3780
3781 let mut get_convert_attr = |name| {
3782 let convert_entry = convert_unit.get(*convert_entries.next().unwrap());
3783 convert_entry.get(name).unwrap()
3784 };
3785 for (name, attr, _) in &attributes {
3786 let convert_attr = get_convert_attr(*name);
3787 assert_eq!(convert_attr, attr);
3788 }
3789 for (name, _, _, attr) in &attributes2 {
3790 let convert_attr = get_convert_attr(*name);
3791 assert_eq!(convert_attr, attr);
3792 }
3793
3794 let convert_attr = get_convert_attr(constants::DW_AT_location);
3795 let AttributeValue::LocationListRef(convert_loc_id) = convert_attr else {
3796 panic!("unexpected {:?}", convert_attr);
3797 };
3798 let convert_location = convert_unit.locations.get(*convert_loc_id);
3799 assert_eq!(*convert_location, location);
3800
3801 let convert_attr = get_convert_attr(constants::DW_AT_ranges);
3802 let AttributeValue::RangeListRef(convert_range_id) = convert_attr else {
3803 panic!("unexpected {:?}", convert_attr);
3804 };
3805 let convert_range = convert_unit.ranges.get(*convert_range_id);
3806 assert_eq!(*convert_range, range);
3807
3808 let convert_attr = get_convert_attr(constants::DW_AT_name);
3809 let AttributeValue::StringRef(convert_string_id) = convert_attr else {
3810 panic!("unexpected {:?}", convert_attr);
3811 };
3812 let convert_string = convert_dwarf.strings.get(*convert_string_id);
3813 assert_eq!(convert_string, string_data.as_bytes());
3814
3815 let convert_attr = get_convert_attr(constants::DW_AT_name);
3816 let AttributeValue::LineStringRef(convert_line_string_id) = convert_attr else {
3817 panic!("unexpected {:?}", convert_attr);
3818 };
3819 let convert_line_string =
3820 convert_dwarf.line_strings.get(*convert_line_string_id);
3821 assert_eq!(convert_line_string, line_string_data.as_bytes());
3822 }
3823 }
3824 }
3825 }
3826
3827 #[test]
3828 fn test_unit_ref() {
3829 let mut dwarf = Dwarf::new();
3830 let unit_id1 = dwarf.units.add(Unit::new(
3831 Encoding {
3832 version: 4,
3833 address_size: 8,
3834 format: Format::Dwarf32,
3835 },
3836 LineProgram::none(),
3837 ));
3838 assert_eq!(unit_id1, dwarf.units.id(0));
3839 let unit_id2 = dwarf.units.add(Unit::new(
3840 Encoding {
3841 version: 2,
3842 address_size: 4,
3843 format: Format::Dwarf64,
3844 },
3845 LineProgram::none(),
3846 ));
3847 assert_eq!(unit_id2, dwarf.units.id(1));
3848 let unit1_child1 = UnitEntryId::new(dwarf.units.get(unit_id1).base_id, 1);
3849 let unit1_child2 = UnitEntryId::new(dwarf.units.get(unit_id1).base_id, 2);
3850 let unit2_child1 = UnitEntryId::new(dwarf.units.get(unit_id2).base_id, 1);
3851 let unit2_child2 = UnitEntryId::new(dwarf.units.get(unit_id2).base_id, 2);
3852 {
3853 let unit1 = dwarf.units.get_mut(unit_id1);
3854 let root = unit1.root();
3855 let child_id1 = unit1.add(root, constants::DW_TAG_subprogram);
3856 assert_eq!(child_id1, unit1_child1);
3857 let child_id2 = unit1.add(root, constants::DW_TAG_subprogram);
3858 assert_eq!(child_id2, unit1_child2);
3859 {
3860 let child1 = unit1.get_mut(child_id1);
3861 child1.set(constants::DW_AT_type, AttributeValue::UnitRef(child_id2));
3862 }
3863 {
3864 let child2 = unit1.get_mut(child_id2);
3865 child2.set(
3866 constants::DW_AT_type,
3867 AttributeValue::DebugInfoRef(DebugInfoRef::Entry(unit_id2, unit2_child1)),
3868 );
3869 }
3870 }
3871 {
3872 let unit2 = dwarf.units.get_mut(unit_id2);
3873 let root = unit2.root();
3874 let child_id1 = unit2.add(root, constants::DW_TAG_subprogram);
3875 assert_eq!(child_id1, unit2_child1);
3876 let child_id2 = unit2.add(root, constants::DW_TAG_subprogram);
3877 assert_eq!(child_id2, unit2_child2);
3878 {
3879 let child1 = unit2.get_mut(child_id1);
3880 child1.set(constants::DW_AT_type, AttributeValue::UnitRef(child_id2));
3881 }
3882 {
3883 let child2 = unit2.get_mut(child_id2);
3884 child2.set(
3885 constants::DW_AT_type,
3886 AttributeValue::DebugInfoRef(DebugInfoRef::Entry(unit_id1, unit1_child1)),
3887 );
3888 }
3889 }
3890
3891 let mut sections = Sections::new(EndianVec::new(LittleEndian));
3892 dwarf.write(&mut sections).unwrap();
3893
3894 let read_dwarf = sections.read(LittleEndian);
3895 let mut read_units = read_dwarf.units();
3896
3897 let read_unit = read_units.next().unwrap().unwrap();
3898 let abbrevs = read_dwarf.abbreviations(&read_unit).unwrap();
3899 let mut read_entries = read_unit.entries(&abbrevs);
3900 let _root = read_entries.next_dfs().unwrap().unwrap();
3901 let entry = read_entries.next_dfs().unwrap().unwrap();
3902 let read_unit1_child1_attr = entry.attr_value(constants::DW_AT_type);
3903 let read_unit1_child1_section_offset =
3904 entry.offset().to_debug_info_offset(&read_unit).unwrap();
3905 let entry = read_entries.next_dfs().unwrap().unwrap();
3906 let read_unit1_child2_attr = entry.attr_value(constants::DW_AT_type);
3907 let read_unit1_child2_offset = entry.offset();
3908
3909 let read_unit = read_units.next().unwrap().unwrap();
3910 let abbrevs = read_dwarf.abbreviations(&read_unit).unwrap();
3911 let mut read_entries = read_unit.entries(&abbrevs);
3912 let _root = read_entries.next_dfs().unwrap().unwrap();
3913 let entry = read_entries.next_dfs().unwrap().unwrap();
3914 let read_unit2_child1_attr = entry.attr_value(constants::DW_AT_type);
3915 let read_unit2_child1_section_offset =
3916 entry.offset().to_debug_info_offset(&read_unit).unwrap();
3917 let entry = read_entries.next_dfs().unwrap().unwrap();
3918 let read_unit2_child2_attr = entry.attr_value(constants::DW_AT_type);
3919 let read_unit2_child2_offset = entry.offset();
3920
3921 assert_eq!(
3922 read_unit1_child1_attr,
3923 Some(read::AttributeValue::UnitRef(read_unit1_child2_offset))
3924 );
3925 assert_eq!(
3926 read_unit1_child2_attr,
3927 Some(read::AttributeValue::DebugInfoRef(
3928 read_unit2_child1_section_offset
3929 ))
3930 );
3931 assert_eq!(
3932 read_unit2_child1_attr,
3933 Some(read::AttributeValue::UnitRef(read_unit2_child2_offset))
3934 );
3935 assert_eq!(
3936 read_unit2_child2_attr,
3937 Some(read::AttributeValue::DebugInfoRef(
3938 read_unit1_child1_section_offset
3939 ))
3940 );
3941
3942 let convert_dwarf =
3943 Dwarf::from(&read_dwarf, &|address| Some(Address::Constant(address))).unwrap();
3944 let convert_units = &convert_dwarf.units;
3945 assert_eq!(convert_units.count(), dwarf.units.count());
3946
3947 for i in 0..convert_units.count() {
3948 let unit = dwarf.units.get(dwarf.units.id(i));
3949 let convert_unit = convert_units.get(convert_units.id(i));
3950 assert_eq!(convert_unit.version(), unit.version());
3951 assert_eq!(convert_unit.address_size(), unit.address_size());
3952 assert_eq!(convert_unit.format(), unit.format());
3953 assert_eq!(convert_unit.count(), unit.count());
3954
3955 let root = unit.get(unit.root());
3956 let convert_root = convert_unit.get(convert_unit.root());
3957 assert_eq!(convert_root.tag(), root.tag());
3958 for (convert_attr, attr) in convert_root.attrs().zip(root.attrs()) {
3959 assert_eq!(convert_attr, attr);
3960 }
3961
3962 let child1 = unit.get(UnitEntryId::new(unit.base_id, 1));
3963 let convert_child1 = convert_unit.get(UnitEntryId::new(convert_unit.base_id, 1));
3964 assert_eq!(convert_child1.tag(), child1.tag());
3965 for (convert_attr, attr) in convert_child1.attrs().zip(child1.attrs()) {
3966 assert_eq!(convert_attr.name, attr.name);
3967 match (convert_attr.value.clone(), attr.value.clone()) {
3968 (
3969 AttributeValue::DebugInfoRef(DebugInfoRef::Entry(
3970 convert_unit,
3971 convert_entry,
3972 )),
3973 AttributeValue::DebugInfoRef(DebugInfoRef::Entry(unit, entry)),
3974 ) => {
3975 assert_eq!(convert_unit.index, unit.index);
3976 assert_eq!(convert_entry.index, entry.index);
3977 }
3978 (AttributeValue::UnitRef(convert_id), AttributeValue::UnitRef(id)) => {
3979 assert_eq!(convert_id.index, id.index);
3980 }
3981 (convert_value, value) => assert_eq!(convert_value, value),
3982 }
3983 }
3984
3985 let child2 = unit.get(UnitEntryId::new(unit.base_id, 2));
3986 let convert_child2 = convert_unit.get(UnitEntryId::new(convert_unit.base_id, 2));
3987 assert_eq!(convert_child2.tag(), child2.tag());
3988 for (convert_attr, attr) in convert_child2.attrs().zip(child2.attrs()) {
3989 assert_eq!(convert_attr.name, attr.name);
3990 match (convert_attr.value.clone(), attr.value.clone()) {
3991 (
3992 AttributeValue::DebugInfoRef(DebugInfoRef::Entry(
3993 convert_unit,
3994 convert_entry,
3995 )),
3996 AttributeValue::DebugInfoRef(DebugInfoRef::Entry(unit, entry)),
3997 ) => {
3998 assert_eq!(convert_unit.index, unit.index);
3999 assert_eq!(convert_entry.index, entry.index);
4000 }
4001 (AttributeValue::UnitRef(convert_id), AttributeValue::UnitRef(id)) => {
4002 assert_eq!(convert_id.index, id.index);
4003 }
4004 (convert_value, value) => assert_eq!(convert_value, value),
4005 }
4006 }
4007 }
4008 }
4009
4010 #[test]
4011 fn test_sibling() {
4012 fn add_child(
4013 unit: &mut Unit,
4014 parent: UnitEntryId,
4015 tag: constants::DwTag,
4016 name: &str,
4017 ) -> UnitEntryId {
4018 let id = unit.add(parent, tag);
4019 let child = unit.get_mut(id);
4020 child.set(constants::DW_AT_name, AttributeValue::String(name.into()));
4021 child.set_sibling(true);
4022 id
4023 }
4024
4025 fn add_children(unit: &mut Unit) {
4026 let root = unit.root();
4027 let child1 = add_child(unit, root, constants::DW_TAG_subprogram, "child1");
4028 add_child(unit, child1, constants::DW_TAG_variable, "grandchild1");
4029 add_child(unit, root, constants::DW_TAG_subprogram, "child2");
4030 add_child(unit, root, constants::DW_TAG_subprogram, "child3");
4031 }
4032
4033 fn next_child<R: read::Reader<Offset = usize>>(
4034 entries: &mut read::EntriesCursor<'_, R>,
4035 ) -> (read::UnitOffset, Option<read::UnitOffset>) {
4036 let entry = entries.next_dfs().unwrap().unwrap();
4037 let offset = entry.offset();
4038 let sibling = entry
4039 .attr_value(constants::DW_AT_sibling)
4040 .map(|attr| match attr {
4041 read::AttributeValue::UnitRef(offset) => offset,
4042 _ => panic!("bad sibling value"),
4043 });
4044 (offset, sibling)
4045 }
4046
4047 fn check_sibling<R: read::Reader<Offset = usize>>(
4048 unit: read::UnitHeader<R>,
4049 dwarf: &read::Dwarf<R>,
4050 ) {
4051 let unit = dwarf.unit(unit).unwrap();
4052 let mut entries = unit.entries();
4053 entries.next_dfs().unwrap().unwrap();
4055 let (_, sibling1) = next_child(&mut entries);
4057 entries.next_dfs().unwrap().unwrap();
4059 let (offset2, sibling2) = next_child(&mut entries);
4061 let (_, _) = next_child(&mut entries);
4063 assert_eq!(sibling1, Some(offset2));
4064 assert_eq!(sibling2, None);
4065 }
4066
4067 let encoding = Encoding {
4068 format: Format::Dwarf32,
4069 version: 4,
4070 address_size: 8,
4071 };
4072 let mut dwarf = Dwarf::new();
4073 let unit_id1 = dwarf.units.add(Unit::new(encoding, LineProgram::none()));
4074 add_children(dwarf.units.get_mut(unit_id1));
4075 let unit_id2 = dwarf.units.add(Unit::new(encoding, LineProgram::none()));
4076 add_children(dwarf.units.get_mut(unit_id2));
4077
4078 let mut sections = Sections::new(EndianVec::new(LittleEndian));
4079 dwarf.write(&mut sections).unwrap();
4080
4081 let read_dwarf = sections.read(LittleEndian);
4082 let mut read_units = read_dwarf.units();
4083 check_sibling(read_units.next().unwrap().unwrap(), &read_dwarf);
4084 check_sibling(read_units.next().unwrap().unwrap(), &read_dwarf);
4085 }
4086
4087 #[test]
4088 fn test_line_ref() {
4089 let dir_bytes = b"dir";
4090 let file_bytes1 = b"file1";
4091 let file_bytes2 = b"file2";
4092 let file_string1 = LineString::String(file_bytes1.to_vec());
4093 let file_string2 = LineString::String(file_bytes2.to_vec());
4094
4095 for &version in &[2, 3, 4, 5] {
4096 for &address_size in &[4, 8] {
4097 for &format in &[Format::Dwarf32, Format::Dwarf64] {
4098 let encoding = Encoding {
4099 format,
4100 version,
4101 address_size,
4102 };
4103
4104 let mut line_program = LineProgram::new(
4106 encoding,
4107 LineEncoding::default(),
4108 LineString::String(dir_bytes.to_vec()),
4109 None,
4110 file_string1.clone(),
4111 None,
4112 );
4113 let dir = line_program.default_directory();
4114 let file1 = line_program.add_file(file_string1.clone(), dir, None);
4116 let file2 = line_program.add_file(file_string2.clone(), dir, None);
4117
4118 let mut unit = Unit::new(encoding, line_program);
4119 let root = unit.get_mut(unit.root());
4120 root.set(
4121 constants::DW_AT_name,
4122 AttributeValue::String(file_bytes1.to_vec()),
4123 );
4124 root.set(
4125 constants::DW_AT_comp_dir,
4126 AttributeValue::String(dir_bytes.to_vec()),
4127 );
4128 root.set(constants::DW_AT_stmt_list, AttributeValue::LineProgramRef);
4129
4130 let child = unit.add(unit.root(), constants::DW_TAG_subprogram);
4131 unit.get_mut(child).set(
4132 constants::DW_AT_decl_file,
4133 AttributeValue::FileIndex(Some(file1)),
4134 );
4135
4136 let child = unit.add(unit.root(), constants::DW_TAG_subprogram);
4137 unit.get_mut(child).set(
4138 constants::DW_AT_call_file,
4139 AttributeValue::FileIndex(Some(file2)),
4140 );
4141
4142 let mut dwarf = Dwarf::new();
4143 dwarf.units.add(unit);
4144
4145 let mut sections = Sections::new(EndianVec::new(LittleEndian));
4146 dwarf.write(&mut sections).unwrap();
4147
4148 let read_dwarf = sections.read(LittleEndian);
4149 let mut read_units = read_dwarf.units();
4150 let read_unit = read_units.next().unwrap().unwrap();
4151 let read_unit = read_dwarf.unit(read_unit).unwrap();
4152 let read_unit = read_unit.unit_ref(&read_dwarf);
4153 let read_line_program = read_unit.line_program.as_ref().unwrap().header();
4154 let mut read_entries = read_unit.entries();
4155 let _root = read_entries.next_dfs().unwrap().unwrap();
4156
4157 let mut get_path = |name| {
4158 let entry = read_entries.next_dfs().unwrap().unwrap();
4159 let read_attr = entry.attr(name).unwrap();
4160 let read::AttributeValue::FileIndex(read_file_index) = read_attr.value()
4161 else {
4162 panic!("unexpected {:?}", read_attr);
4163 };
4164 let read_file = read_line_program.file(read_file_index).unwrap();
4165 let read_path = read_unit
4166 .attr_string(read_file.path_name())
4167 .unwrap()
4168 .slice();
4169 (read_file_index, read_path)
4170 };
4171
4172 let (read_index, read_path) = get_path(constants::DW_AT_decl_file);
4173 assert_eq!(read_index, if version >= 5 { 0 } else { 1 });
4174 assert_eq!(read_path, file_bytes1);
4175
4176 let (read_index, read_path) = get_path(constants::DW_AT_call_file);
4177 assert_eq!(read_index, if version >= 5 { 1 } else { 2 });
4178 assert_eq!(read_path, file_bytes2);
4179
4180 let convert_dwarf =
4181 Dwarf::from(&read_dwarf, &|address| Some(Address::Constant(address)))
4182 .unwrap();
4183 let convert_unit = convert_dwarf.units.get(convert_dwarf.units.id(0));
4184 let convert_root = convert_unit.get(convert_unit.root());
4185 let mut convert_entries = convert_root.children();
4186
4187 let mut get_convert_path = |name| {
4188 let convert_entry = convert_unit.get(*convert_entries.next().unwrap());
4189 let convert_attr = convert_entry.get(name).unwrap();
4190 let AttributeValue::FileIndex(Some(convert_file_index)) = convert_attr
4191 else {
4192 panic!("unexpected {:?}", convert_attr);
4193 };
4194 convert_unit.line_program.get_file(*convert_file_index).0
4195 };
4196
4197 let convert_path = get_convert_path(constants::DW_AT_decl_file);
4198 assert_eq!(convert_dwarf.get_line_string(convert_path), file_bytes1);
4199
4200 let convert_path = get_convert_path(constants::DW_AT_call_file);
4201 assert_eq!(convert_dwarf.get_line_string(convert_path), file_bytes2);
4202 }
4203 }
4204 }
4205 }
4206
4207 #[test]
4208 fn test_line_program_used() {
4209 for used in [false, true] {
4210 let encoding = Encoding {
4211 format: Format::Dwarf32,
4212 version: 5,
4213 address_size: 8,
4214 };
4215
4216 let line_program = LineProgram::new(
4217 encoding,
4218 LineEncoding::default(),
4219 LineString::String(b"comp_dir".to_vec()),
4220 None,
4221 LineString::String(b"comp_name".to_vec()),
4222 None,
4223 );
4224
4225 let mut unit = Unit::new(encoding, line_program);
4226 let file_id = if used { Some(FileId::new(0)) } else { None };
4227 let root = unit.root();
4228 unit.get_mut(root).set(
4229 constants::DW_AT_decl_file,
4230 AttributeValue::FileIndex(file_id),
4231 );
4232
4233 let mut dwarf = Dwarf::new();
4234 dwarf.units.add(unit);
4235
4236 let mut sections = Sections::new(EndianVec::new(LittleEndian));
4237 dwarf.write(&mut sections).unwrap();
4238 assert_eq!(!used, sections.debug_line.slice().is_empty());
4239 }
4240 }
4241
4242 #[test]
4243 fn test_delete_child() {
4244 fn set_name(unit: &mut Unit, id: UnitEntryId, name: &str) {
4245 let entry = unit.get_mut(id);
4246 entry.set(constants::DW_AT_name, AttributeValue::String(name.into()));
4247 }
4248 fn check_name<R: read::Reader>(
4249 entry: &read::DebuggingInformationEntry<R>,
4250 unit: read::UnitRef<'_, R>,
4251 name: &str,
4252 ) {
4253 let name_attr = entry.attr(constants::DW_AT_name).unwrap();
4254 let entry_name = unit.attr_string(name_attr.value()).unwrap();
4255 let entry_name_str = entry_name.to_string().unwrap();
4256 assert_eq!(entry_name_str, name);
4257 }
4258 let encoding = Encoding {
4259 format: Format::Dwarf32,
4260 version: 4,
4261 address_size: 8,
4262 };
4263 let mut dwarf = DwarfUnit::new(encoding);
4264 let root = dwarf.unit.root();
4265
4266 let child1 = dwarf.unit.add(root, constants::DW_TAG_subprogram);
4268 set_name(&mut dwarf.unit, child1, "child1");
4269 let grandchild1 = dwarf.unit.add(child1, constants::DW_TAG_variable);
4270 set_name(&mut dwarf.unit, grandchild1, "grandchild1");
4271 let child2 = dwarf.unit.add(root, constants::DW_TAG_subprogram);
4272 set_name(&mut dwarf.unit, child2, "child2");
4273 dwarf.unit.get_mut(root).delete_child(child1);
4275 let child3 = dwarf.unit.add(root, constants::DW_TAG_subprogram);
4276 set_name(&mut dwarf.unit, child3, "child3");
4277 let child4 = dwarf.unit.add(root, constants::DW_TAG_subprogram);
4278 set_name(&mut dwarf.unit, child4, "child4");
4279 let grandchild4 = dwarf.unit.add(child4, constants::DW_TAG_variable);
4280 set_name(&mut dwarf.unit, grandchild4, "grandchild4");
4281 dwarf.unit.get_mut(child4).delete_child(grandchild4);
4282
4283 let mut sections = Sections::new(EndianVec::new(LittleEndian));
4284
4285 dwarf.write(&mut sections).unwrap();
4287
4288 let read_dwarf = sections.read(LittleEndian);
4289 let read_unit = read_dwarf.units().next().unwrap().unwrap();
4290 let read_unit = read_dwarf.unit(read_unit).unwrap();
4291 let read_unit = read_unit.unit_ref(&read_dwarf);
4292 let mut entries = read_unit.entries();
4293 entries.next_dfs().unwrap().unwrap();
4295 let read_child2 = entries.next_dfs().unwrap().unwrap();
4297 check_name(read_child2, read_unit, "child2");
4298 let read_child3 = entries.next_dfs().unwrap().unwrap();
4300 check_name(read_child3, read_unit, "child3");
4301 let read_child4 = entries.next_dfs().unwrap().unwrap();
4303 check_name(read_child4, read_unit, "child4");
4304 assert!(entries.next_dfs().unwrap().is_none());
4306 }
4307
4308 #[test]
4309 fn test_missing_unit_ref() {
4310 let encoding = Encoding {
4311 format: Format::Dwarf32,
4312 version: 5,
4313 address_size: 8,
4314 };
4315
4316 let mut dwarf = Dwarf::new();
4317 let unit_id = dwarf.units.add(Unit::new(encoding, LineProgram::none()));
4318 let unit = dwarf.units.get_mut(unit_id);
4319
4320 let entry_id = unit.add(unit.root(), constants::DW_TAG_const_type);
4322 unit.get_mut(unit.root()).delete_child(entry_id);
4324
4325 let subprogram_id = unit.add(unit.root(), constants::DW_TAG_subprogram);
4327 unit.get_mut(subprogram_id)
4328 .set(constants::DW_AT_type, AttributeValue::UnitRef(entry_id));
4329
4330 let mut sections = Sections::new(EndianVec::new(LittleEndian));
4332 assert_eq!(dwarf.write(&mut sections), Err(Error::InvalidReference));
4333 }
4334
4335 #[test]
4336 fn test_missing_debuginfo_ref() {
4337 let encoding = Encoding {
4338 format: Format::Dwarf32,
4339 version: 5,
4340 address_size: 8,
4341 };
4342
4343 let mut dwarf = Dwarf::new();
4344 let unit_id = dwarf.units.add(Unit::new(encoding, LineProgram::none()));
4345 let unit = dwarf.units.get_mut(unit_id);
4346
4347 let entry_id = unit.add(unit.root(), constants::DW_TAG_const_type);
4349 unit.get_mut(unit.root()).delete_child(entry_id);
4351
4352 let subprogram_id = unit.add(unit.root(), constants::DW_TAG_subprogram);
4354 unit.get_mut(subprogram_id).set(
4355 constants::DW_AT_type,
4356 AttributeValue::DebugInfoRef(DebugInfoRef::Entry(unit_id, entry_id)),
4357 );
4358
4359 let mut sections = Sections::new(EndianVec::new(LittleEndian));
4361 assert_eq!(dwarf.write(&mut sections), Err(Error::InvalidReference));
4362 }
4363}