1use alloc::vec::Vec;
2use std::ops::{Deref, DerefMut};
3use std::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, DebugLineStrOffsets,
13 DebugStrOffsets, Error, Expression, FileId, LineProgram, LineStringId, LocationListId,
14 LocationListOffsets, LocationListTable, RangeListId, RangeListOffsets, RangeListTable,
15 Reference, Result, Section, Sections, StringId, 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>(
103 &mut self,
104 sections: &mut Sections<W>,
105 line_strings: &DebugLineStrOffsets,
106 strings: &DebugStrOffsets,
107 ) -> Result<DebugInfoOffsets> {
108 let mut offsets = DebugInfoOffsets {
109 base_id: self.base_id,
110 units: Vec::new(),
111 };
112 for unit in &mut self.units {
113 let abbrev_offset = sections.debug_abbrev.offset();
115 let mut abbrevs = AbbreviationTable::default();
116
117 offsets.units.push(unit.write(
118 sections,
119 abbrev_offset,
120 &mut abbrevs,
121 line_strings,
122 strings,
123 )?);
124
125 abbrevs.write(&mut sections.debug_abbrev)?;
126 }
127
128 write_section_refs(
129 &mut sections.debug_info_refs,
130 &mut sections.debug_info.0,
131 &offsets,
132 )?;
133 write_section_refs(
134 &mut sections.debug_loc_refs,
135 &mut sections.debug_loc.0,
136 &offsets,
137 )?;
138 write_section_refs(
139 &mut sections.debug_loclists_refs,
140 &mut sections.debug_loclists.0,
141 &offsets,
142 )?;
143
144 Ok(offsets)
145 }
146}
147
148fn write_section_refs<W: Writer>(
149 references: &mut Vec<DebugInfoReference>,
150 w: &mut W,
151 offsets: &DebugInfoOffsets,
152) -> Result<()> {
153 for r in references.drain(..) {
154 let entry_offset = offsets.entry(r.unit, r.entry).0;
155 debug_assert_ne!(entry_offset, 0);
156 w.write_offset_at(r.offset, entry_offset, SectionId::DebugInfo, r.size)?;
157 }
158 Ok(())
159}
160
161#[derive(Debug)]
163pub struct Unit {
164 base_id: BaseId,
165 encoding: Encoding,
167 pub line_program: LineProgram,
169 pub ranges: RangeListTable,
171 pub locations: LocationListTable,
173 entries: Vec<DebuggingInformationEntry>,
182 root: UnitEntryId,
184}
185
186impl Unit {
187 pub fn new(encoding: Encoding, line_program: LineProgram) -> Self {
189 let base_id = BaseId::default();
190 let ranges = RangeListTable::default();
191 let locations = LocationListTable::default();
192 let mut entries = Vec::new();
193 let root = DebuggingInformationEntry::new(
194 base_id,
195 &mut entries,
196 None,
197 constants::DW_TAG_compile_unit,
198 );
199 Unit {
200 base_id,
201 encoding,
202 line_program,
203 ranges,
204 locations,
205 entries,
206 root,
207 }
208 }
209
210 #[inline]
212 pub fn encoding(&self) -> Encoding {
213 self.encoding
214 }
215
216 #[inline]
218 pub fn version(&self) -> u16 {
219 self.encoding.version
220 }
221
222 #[inline]
224 pub fn address_size(&self) -> u8 {
225 self.encoding.address_size
226 }
227
228 #[inline]
230 pub fn format(&self) -> Format {
231 self.encoding.format
232 }
233
234 #[inline]
238 pub fn count(&self) -> usize {
239 self.entries.len()
240 }
241
242 #[inline]
244 pub fn root(&self) -> UnitEntryId {
245 self.root
246 }
247
248 #[inline]
256 pub fn add(&mut self, parent: UnitEntryId, tag: constants::DwTag) -> UnitEntryId {
257 debug_assert_eq!(self.base_id, parent.base_id);
258 DebuggingInformationEntry::new(self.base_id, &mut self.entries, Some(parent), tag)
259 }
260
261 #[inline]
267 pub fn get(&self, id: UnitEntryId) -> &DebuggingInformationEntry {
268 debug_assert_eq!(self.base_id, id.base_id);
269 &self.entries[id.index]
270 }
271
272 #[inline]
278 pub fn get_mut(&mut self, id: UnitEntryId) -> &mut DebuggingInformationEntry {
279 debug_assert_eq!(self.base_id, id.base_id);
280 &mut self.entries[id.index]
281 }
282
283 fn line_program_in_use(&self) -> bool {
285 if self.line_program.is_none() {
286 return false;
287 }
288 if !self.line_program.is_empty() {
289 return true;
290 }
291
292 for entry in &self.entries {
293 for attr in &entry.attrs {
294 if let AttributeValue::FileIndex(Some(_)) = attr.value {
295 return true;
296 }
297 }
298 }
299
300 false
301 }
302
303 pub(crate) fn write<W: Writer>(
305 &mut self,
306 sections: &mut Sections<W>,
307 abbrev_offset: DebugAbbrevOffset,
308 abbrevs: &mut AbbreviationTable,
309 line_strings: &DebugLineStrOffsets,
310 strings: &DebugStrOffsets,
311 ) -> Result<UnitOffsets> {
312 let line_program = if self.line_program_in_use() {
313 self.entries[self.root.index]
314 .set(constants::DW_AT_stmt_list, AttributeValue::LineProgramRef);
315 Some(self.line_program.write(
316 &mut sections.debug_line,
317 self.encoding,
318 line_strings,
319 strings,
320 )?)
321 } else {
322 self.entries[self.root.index].delete(constants::DW_AT_stmt_list);
323 None
324 };
325
326 let w = &mut sections.debug_info;
328
329 let mut offsets = UnitOffsets {
330 base_id: self.base_id,
331 unit: w.offset(),
332 entries: vec![EntryOffset::none(); self.entries.len()],
334 };
335
336 let length_offset = w.write_initial_length(self.format())?;
337 let length_base = w.len();
338
339 w.write_u16(self.version())?;
340 if 2 <= self.version() && self.version() <= 4 {
341 w.write_offset(
342 abbrev_offset.0,
343 SectionId::DebugAbbrev,
344 self.format().word_size(),
345 )?;
346 w.write_u8(self.address_size())?;
347 } else if self.version() == 5 {
348 w.write_u8(constants::DW_UT_compile.0)?;
349 w.write_u8(self.address_size())?;
350 w.write_offset(
351 abbrev_offset.0,
352 SectionId::DebugAbbrev,
353 self.format().word_size(),
354 )?;
355 } else {
356 return Err(Error::UnsupportedVersion(self.version()));
357 }
358
359 self.reorder_base_types();
363 let mut offset = w.len();
364 self.entries[self.root.index].calculate_offsets(
365 self,
366 &mut offset,
367 &mut offsets,
368 abbrevs,
369 )?;
370
371 let range_lists = self.ranges.write(sections, self.encoding)?;
372 let loc_lists = self
374 .locations
375 .write(sections, self.encoding, Some(&offsets))?;
376
377 let w = &mut sections.debug_info;
378 let mut unit_refs = Vec::new();
379 self.entries[self.root.index].write(
380 w,
381 &mut sections.debug_info_refs,
382 &mut unit_refs,
383 self,
384 &mut offsets,
385 line_program,
386 line_strings,
387 strings,
388 &range_lists,
389 &loc_lists,
390 )?;
391
392 let length = (w.len() - length_base) as u64;
393 w.write_initial_length_at(length_offset, length, self.format())?;
394
395 for (offset, entry) in unit_refs {
396 w.write_udata_at(
398 offset.0,
399 offsets.unit_offset(entry),
400 self.format().word_size(),
401 )?;
402 }
403
404 Ok(offsets)
405 }
406
407 fn reorder_base_types(&mut self) {
410 let root = &self.entries[self.root.index];
411 let mut root_children = Vec::with_capacity(root.children.len());
412 for entry in &root.children {
413 if self.entries[entry.index].tag == constants::DW_TAG_base_type {
414 root_children.push(*entry);
415 }
416 }
417 for entry in &root.children {
418 if self.entries[entry.index].tag != constants::DW_TAG_base_type {
419 root_children.push(*entry);
420 }
421 }
422 self.entries[self.root.index].children = root_children;
423 }
424}
425
426#[derive(Debug)]
433pub struct DebuggingInformationEntry {
434 id: UnitEntryId,
435 parent: Option<UnitEntryId>,
436 tag: constants::DwTag,
437 sibling: bool,
439 attrs: Vec<Attribute>,
440 children: Vec<UnitEntryId>,
441}
442
443impl DebuggingInformationEntry {
444 #[allow(clippy::new_ret_no_self)]
450 fn new(
451 base_id: BaseId,
452 entries: &mut Vec<DebuggingInformationEntry>,
453 parent: Option<UnitEntryId>,
454 tag: constants::DwTag,
455 ) -> UnitEntryId {
456 let id = UnitEntryId::new(base_id, entries.len());
457 entries.push(DebuggingInformationEntry {
458 id,
459 parent,
460 tag,
461 sibling: false,
462 attrs: Vec::new(),
463 children: Vec::new(),
464 });
465 if let Some(parent) = parent {
466 debug_assert_eq!(base_id, parent.base_id);
467 assert_ne!(parent, id);
468 entries[parent.index].children.push(id);
469 }
470 id
471 }
472
473 #[inline]
475 pub fn id(&self) -> UnitEntryId {
476 self.id
477 }
478
479 #[inline]
481 pub fn parent(&self) -> Option<UnitEntryId> {
482 self.parent
483 }
484
485 #[inline]
487 pub fn tag(&self) -> constants::DwTag {
488 self.tag
489 }
490
491 #[inline]
493 pub fn sibling(&self) -> bool {
494 self.sibling
495 }
496
497 #[inline]
501 pub fn set_sibling(&mut self, sibling: bool) {
502 self.sibling = sibling;
503 }
504
505 #[inline]
507 pub fn attrs(&self) -> slice::Iter<'_, Attribute> {
508 self.attrs.iter()
509 }
510
511 #[inline]
513 pub fn attrs_mut(&mut self) -> slice::IterMut<'_, Attribute> {
514 self.attrs.iter_mut()
515 }
516
517 pub fn get(&self, name: constants::DwAt) -> Option<&AttributeValue> {
519 self.attrs
520 .iter()
521 .find(|attr| attr.name == name)
522 .map(|attr| &attr.value)
523 }
524
525 pub fn get_mut(&mut self, name: constants::DwAt) -> Option<&mut AttributeValue> {
527 self.attrs
528 .iter_mut()
529 .find(|attr| attr.name == name)
530 .map(|attr| &mut attr.value)
531 }
532
533 pub fn set(&mut self, name: constants::DwAt, value: AttributeValue) {
541 assert_ne!(name, constants::DW_AT_sibling);
542 if let Some(attr) = self.attrs.iter_mut().find(|attr| attr.name == name) {
543 attr.value = value;
544 return;
545 }
546 self.attrs.push(Attribute { name, value });
547 }
548
549 pub fn delete(&mut self, name: constants::DwAt) {
553 self.attrs.retain(|x| x.name != name);
554 }
555
556 #[inline]
560 pub fn children(&self) -> slice::Iter<'_, UnitEntryId> {
561 self.children.iter()
562 }
563
564 pub fn delete_child(&mut self, id: UnitEntryId) {
566 self.children.retain(|&child| child != id);
567 }
568
569 fn abbreviation(&self, encoding: Encoding) -> Result<Abbreviation> {
571 let mut attrs = Vec::new();
572
573 if self.sibling && !self.children.is_empty() {
574 let form = match encoding.format {
575 Format::Dwarf32 => constants::DW_FORM_ref4,
576 Format::Dwarf64 => constants::DW_FORM_ref8,
577 };
578 attrs.push(AttributeSpecification::new(constants::DW_AT_sibling, form));
579 }
580
581 for attr in &self.attrs {
582 attrs.push(attr.specification(encoding)?);
583 }
584
585 Ok(Abbreviation::new(
586 self.tag,
587 !self.children.is_empty(),
588 attrs,
589 ))
590 }
591
592 fn calculate_offsets(
593 &self,
594 unit: &Unit,
595 offset: &mut usize,
596 offsets: &mut UnitOffsets,
597 abbrevs: &mut AbbreviationTable,
598 ) -> Result<()> {
599 offsets.entries[self.id.index].offset = DebugInfoOffset(*offset);
600 offsets.entries[self.id.index].abbrev = abbrevs.add(self.abbreviation(unit.encoding())?);
601 *offset += self.size(unit, offsets);
602 if !self.children.is_empty() {
603 for child in &self.children {
604 unit.entries[child.index].calculate_offsets(unit, offset, offsets, abbrevs)?;
605 }
606 *offset += 1;
608 }
609 Ok(())
610 }
611
612 fn size(&self, unit: &Unit, offsets: &UnitOffsets) -> usize {
613 let mut size = uleb128_size(offsets.abbrev(self.id));
614 if self.sibling && !self.children.is_empty() {
615 size += unit.format().word_size() as usize;
616 }
617 for attr in &self.attrs {
618 size += attr.value.size(unit, offsets);
619 }
620 size
621 }
622
623 fn write<W: Writer>(
625 &self,
626 w: &mut DebugInfo<W>,
627 debug_info_refs: &mut Vec<DebugInfoReference>,
628 unit_refs: &mut Vec<(DebugInfoOffset, UnitEntryId)>,
629 unit: &Unit,
630 offsets: &mut UnitOffsets,
631 line_program: Option<DebugLineOffset>,
632 line_strings: &DebugLineStrOffsets,
633 strings: &DebugStrOffsets,
634 range_lists: &RangeListOffsets,
635 loc_lists: &LocationListOffsets,
636 ) -> Result<()> {
637 debug_assert_eq!(offsets.debug_info_offset(self.id), w.offset());
638 w.write_uleb128(offsets.abbrev(self.id))?;
639
640 let sibling_offset = if self.sibling && !self.children.is_empty() {
641 let offset = w.offset();
642 w.write_udata(0, unit.format().word_size())?;
643 Some(offset)
644 } else {
645 None
646 };
647
648 for attr in &self.attrs {
649 attr.value.write(
650 w,
651 debug_info_refs,
652 unit_refs,
653 unit,
654 offsets,
655 line_program,
656 line_strings,
657 strings,
658 range_lists,
659 loc_lists,
660 )?;
661 }
662
663 if !self.children.is_empty() {
664 for child in &self.children {
665 unit.entries[child.index].write(
666 w,
667 debug_info_refs,
668 unit_refs,
669 unit,
670 offsets,
671 line_program,
672 line_strings,
673 strings,
674 range_lists,
675 loc_lists,
676 )?;
677 }
678 w.write_u8(0)?;
680 }
681
682 if let Some(offset) = sibling_offset {
683 let next_offset = (w.offset().0 - offsets.unit.0) as u64;
684 w.write_udata_at(offset.0, next_offset, unit.format().word_size())?;
686 }
687 Ok(())
688 }
689}
690
691#[derive(Debug, Clone, PartialEq, Eq)]
694pub struct Attribute {
695 name: constants::DwAt,
696 value: AttributeValue,
697}
698
699impl Attribute {
700 #[inline]
702 pub fn name(&self) -> constants::DwAt {
703 self.name
704 }
705
706 #[inline]
708 pub fn get(&self) -> &AttributeValue {
709 &self.value
710 }
711
712 #[inline]
714 pub fn set(&mut self, value: AttributeValue) {
715 self.value = value;
716 }
717
718 fn specification(&self, encoding: Encoding) -> Result<AttributeSpecification> {
720 Ok(AttributeSpecification::new(
721 self.name,
722 self.value.form(encoding)?,
723 ))
724 }
725}
726
727#[derive(Debug, Clone, PartialEq, Eq)]
729pub enum AttributeValue {
730 Address(Address),
732
733 Block(Vec<u8>),
735
736 Data1(u8),
742
743 Data2(u16),
751
752 Data4(u32),
760
761 Data8(u64),
769
770 Sdata(i64),
772
773 Udata(u64),
775
776 Exprloc(Expression),
779
780 Flag(bool),
782
783 FlagPresent,
785
786 UnitRef(UnitEntryId),
788
789 DebugInfoRef(Reference),
791
792 DebugInfoRefSup(DebugInfoOffset),
798
799 LineProgramRef,
801
802 LocationListRef(LocationListId),
804
805 DebugMacinfoRef(DebugMacinfoOffset),
811
812 DebugMacroRef(DebugMacroOffset),
818
819 RangeListRef(RangeListId),
821
822 DebugTypesRef(DebugTypeSignature),
828
829 StringRef(StringId),
831
832 DebugStrRefSup(DebugStrOffset),
838
839 LineStringRef(LineStringId),
841
842 String(Vec<u8>),
845
846 Encoding(constants::DwAte),
848
849 DecimalSign(constants::DwDs),
851
852 Endianity(constants::DwEnd),
854
855 Accessibility(constants::DwAccess),
857
858 Visibility(constants::DwVis),
860
861 Virtuality(constants::DwVirtuality),
863
864 Language(constants::DwLang),
866
867 AddressClass(constants::DwAddr),
869
870 IdentifierCase(constants::DwId),
872
873 CallingConvention(constants::DwCc),
875
876 Inline(constants::DwInl),
878
879 Ordering(constants::DwOrd),
881
882 FileIndex(Option<FileId>),
885}
886
887impl AttributeValue {
888 pub fn form(&self, encoding: Encoding) -> Result<constants::DwForm> {
890 let form = match *self {
901 AttributeValue::Address(_) => constants::DW_FORM_addr,
902 AttributeValue::Block(_) => constants::DW_FORM_block,
903 AttributeValue::Data1(_) => constants::DW_FORM_data1,
904 AttributeValue::Data2(_) => constants::DW_FORM_data2,
905 AttributeValue::Data4(_) => constants::DW_FORM_data4,
906 AttributeValue::Data8(_) => constants::DW_FORM_data8,
907 AttributeValue::Exprloc(_) => constants::DW_FORM_exprloc,
908 AttributeValue::Flag(_) => constants::DW_FORM_flag,
909 AttributeValue::FlagPresent => constants::DW_FORM_flag_present,
910 AttributeValue::UnitRef(_) => {
911 match encoding.format {
914 Format::Dwarf32 => constants::DW_FORM_ref4,
915 Format::Dwarf64 => constants::DW_FORM_ref8,
916 }
917 }
918 AttributeValue::DebugInfoRef(_) => constants::DW_FORM_ref_addr,
919 AttributeValue::DebugInfoRefSup(_) => {
920 match encoding.format {
922 Format::Dwarf32 => constants::DW_FORM_ref_sup4,
923 Format::Dwarf64 => constants::DW_FORM_ref_sup8,
924 }
925 }
926 AttributeValue::LineProgramRef
927 | AttributeValue::LocationListRef(_)
928 | AttributeValue::DebugMacinfoRef(_)
929 | AttributeValue::DebugMacroRef(_)
930 | AttributeValue::RangeListRef(_) => {
931 if encoding.version == 2 || encoding.version == 3 {
932 match encoding.format {
933 Format::Dwarf32 => constants::DW_FORM_data4,
934 Format::Dwarf64 => constants::DW_FORM_data8,
935 }
936 } else {
937 constants::DW_FORM_sec_offset
938 }
939 }
940 AttributeValue::DebugTypesRef(_) => constants::DW_FORM_ref_sig8,
941 AttributeValue::StringRef(_) => constants::DW_FORM_strp,
942 AttributeValue::DebugStrRefSup(_) => constants::DW_FORM_strp_sup,
943 AttributeValue::LineStringRef(_) => constants::DW_FORM_line_strp,
944 AttributeValue::String(_) => constants::DW_FORM_string,
945 AttributeValue::Encoding(_)
946 | AttributeValue::DecimalSign(_)
947 | AttributeValue::Endianity(_)
948 | AttributeValue::Accessibility(_)
949 | AttributeValue::Visibility(_)
950 | AttributeValue::Virtuality(_)
951 | AttributeValue::Language(_)
952 | AttributeValue::AddressClass(_)
953 | AttributeValue::IdentifierCase(_)
954 | AttributeValue::CallingConvention(_)
955 | AttributeValue::Inline(_)
956 | AttributeValue::Ordering(_)
957 | AttributeValue::FileIndex(_)
958 | AttributeValue::Udata(_) => constants::DW_FORM_udata,
959 AttributeValue::Sdata(_) => constants::DW_FORM_sdata,
960 };
961 Ok(form)
962 }
963
964 fn size(&self, unit: &Unit, offsets: &UnitOffsets) -> usize {
965 macro_rules! debug_assert_form {
966 ($form:expr) => {
967 debug_assert_eq!(self.form(unit.encoding()).unwrap(), $form)
968 };
969 }
970 match *self {
971 AttributeValue::Address(_) => {
972 debug_assert_form!(constants::DW_FORM_addr);
973 unit.address_size() as usize
974 }
975 AttributeValue::Block(ref val) => {
976 debug_assert_form!(constants::DW_FORM_block);
977 uleb128_size(val.len() as u64) + val.len()
978 }
979 AttributeValue::Data1(_) => {
980 debug_assert_form!(constants::DW_FORM_data1);
981 1
982 }
983 AttributeValue::Data2(_) => {
984 debug_assert_form!(constants::DW_FORM_data2);
985 2
986 }
987 AttributeValue::Data4(_) => {
988 debug_assert_form!(constants::DW_FORM_data4);
989 4
990 }
991 AttributeValue::Data8(_) => {
992 debug_assert_form!(constants::DW_FORM_data8);
993 8
994 }
995 AttributeValue::Sdata(val) => {
996 debug_assert_form!(constants::DW_FORM_sdata);
997 sleb128_size(val)
998 }
999 AttributeValue::Udata(val) => {
1000 debug_assert_form!(constants::DW_FORM_udata);
1001 uleb128_size(val)
1002 }
1003 AttributeValue::Exprloc(ref val) => {
1004 debug_assert_form!(constants::DW_FORM_exprloc);
1005 let size = val.size(unit.encoding(), Some(offsets));
1006 uleb128_size(size as u64) + size
1007 }
1008 AttributeValue::Flag(_) => {
1009 debug_assert_form!(constants::DW_FORM_flag);
1010 1
1011 }
1012 AttributeValue::FlagPresent => {
1013 debug_assert_form!(constants::DW_FORM_flag_present);
1014 0
1015 }
1016 AttributeValue::UnitRef(_) => {
1017 match unit.format() {
1018 Format::Dwarf32 => debug_assert_form!(constants::DW_FORM_ref4),
1019 Format::Dwarf64 => debug_assert_form!(constants::DW_FORM_ref8),
1020 }
1021 unit.format().word_size() as usize
1022 }
1023 AttributeValue::DebugInfoRef(_) => {
1024 debug_assert_form!(constants::DW_FORM_ref_addr);
1025 if unit.version() == 2 {
1026 unit.address_size() as usize
1027 } else {
1028 unit.format().word_size() as usize
1029 }
1030 }
1031 AttributeValue::DebugInfoRefSup(_) => {
1032 match unit.format() {
1033 Format::Dwarf32 => debug_assert_form!(constants::DW_FORM_ref_sup4),
1034 Format::Dwarf64 => debug_assert_form!(constants::DW_FORM_ref_sup8),
1035 }
1036 unit.format().word_size() as usize
1037 }
1038 AttributeValue::LineProgramRef => {
1039 if unit.version() >= 4 {
1040 debug_assert_form!(constants::DW_FORM_sec_offset);
1041 }
1042 unit.format().word_size() as usize
1043 }
1044 AttributeValue::LocationListRef(_) => {
1045 if unit.version() >= 4 {
1046 debug_assert_form!(constants::DW_FORM_sec_offset);
1047 }
1048 unit.format().word_size() as usize
1049 }
1050 AttributeValue::DebugMacinfoRef(_) => {
1051 if unit.version() >= 4 {
1052 debug_assert_form!(constants::DW_FORM_sec_offset);
1053 }
1054 unit.format().word_size() as usize
1055 }
1056 AttributeValue::DebugMacroRef(_) => {
1057 if unit.version() >= 4 {
1058 debug_assert_form!(constants::DW_FORM_sec_offset);
1059 }
1060 unit.format().word_size() as usize
1061 }
1062 AttributeValue::RangeListRef(_) => {
1063 if unit.version() >= 4 {
1064 debug_assert_form!(constants::DW_FORM_sec_offset);
1065 }
1066 unit.format().word_size() as usize
1067 }
1068 AttributeValue::DebugTypesRef(_) => {
1069 debug_assert_form!(constants::DW_FORM_ref_sig8);
1070 8
1071 }
1072 AttributeValue::StringRef(_) => {
1073 debug_assert_form!(constants::DW_FORM_strp);
1074 unit.format().word_size() as usize
1075 }
1076 AttributeValue::DebugStrRefSup(_) => {
1077 debug_assert_form!(constants::DW_FORM_strp_sup);
1078 unit.format().word_size() as usize
1079 }
1080 AttributeValue::LineStringRef(_) => {
1081 debug_assert_form!(constants::DW_FORM_line_strp);
1082 unit.format().word_size() as usize
1083 }
1084 AttributeValue::String(ref val) => {
1085 debug_assert_form!(constants::DW_FORM_string);
1086 val.len() + 1
1087 }
1088 AttributeValue::Encoding(val) => {
1089 debug_assert_form!(constants::DW_FORM_udata);
1090 uleb128_size(val.0 as u64)
1091 }
1092 AttributeValue::DecimalSign(val) => {
1093 debug_assert_form!(constants::DW_FORM_udata);
1094 uleb128_size(val.0 as u64)
1095 }
1096 AttributeValue::Endianity(val) => {
1097 debug_assert_form!(constants::DW_FORM_udata);
1098 uleb128_size(val.0 as u64)
1099 }
1100 AttributeValue::Accessibility(val) => {
1101 debug_assert_form!(constants::DW_FORM_udata);
1102 uleb128_size(val.0 as u64)
1103 }
1104 AttributeValue::Visibility(val) => {
1105 debug_assert_form!(constants::DW_FORM_udata);
1106 uleb128_size(val.0 as u64)
1107 }
1108 AttributeValue::Virtuality(val) => {
1109 debug_assert_form!(constants::DW_FORM_udata);
1110 uleb128_size(val.0 as u64)
1111 }
1112 AttributeValue::Language(val) => {
1113 debug_assert_form!(constants::DW_FORM_udata);
1114 uleb128_size(val.0 as u64)
1115 }
1116 AttributeValue::AddressClass(val) => {
1117 debug_assert_form!(constants::DW_FORM_udata);
1118 uleb128_size(val.0)
1119 }
1120 AttributeValue::IdentifierCase(val) => {
1121 debug_assert_form!(constants::DW_FORM_udata);
1122 uleb128_size(val.0 as u64)
1123 }
1124 AttributeValue::CallingConvention(val) => {
1125 debug_assert_form!(constants::DW_FORM_udata);
1126 uleb128_size(val.0 as u64)
1127 }
1128 AttributeValue::Inline(val) => {
1129 debug_assert_form!(constants::DW_FORM_udata);
1130 uleb128_size(val.0 as u64)
1131 }
1132 AttributeValue::Ordering(val) => {
1133 debug_assert_form!(constants::DW_FORM_udata);
1134 uleb128_size(val.0 as u64)
1135 }
1136 AttributeValue::FileIndex(val) => {
1137 debug_assert_form!(constants::DW_FORM_udata);
1138 uleb128_size(val.map(|id| id.raw(unit.version())).unwrap_or(0))
1139 }
1140 }
1141 }
1142
1143 fn write<W: Writer>(
1145 &self,
1146 w: &mut DebugInfo<W>,
1147 debug_info_refs: &mut Vec<DebugInfoReference>,
1148 unit_refs: &mut Vec<(DebugInfoOffset, UnitEntryId)>,
1149 unit: &Unit,
1150 offsets: &UnitOffsets,
1151 line_program: Option<DebugLineOffset>,
1152 line_strings: &DebugLineStrOffsets,
1153 strings: &DebugStrOffsets,
1154 range_lists: &RangeListOffsets,
1155 loc_lists: &LocationListOffsets,
1156 ) -> Result<()> {
1157 macro_rules! debug_assert_form {
1158 ($form:expr) => {
1159 debug_assert_eq!(self.form(unit.encoding()).unwrap(), $form)
1160 };
1161 }
1162 match *self {
1163 AttributeValue::Address(val) => {
1164 debug_assert_form!(constants::DW_FORM_addr);
1165 w.write_address(val, unit.address_size())?;
1166 }
1167 AttributeValue::Block(ref val) => {
1168 debug_assert_form!(constants::DW_FORM_block);
1169 w.write_uleb128(val.len() as u64)?;
1170 w.write(val)?;
1171 }
1172 AttributeValue::Data1(val) => {
1173 debug_assert_form!(constants::DW_FORM_data1);
1174 w.write_u8(val)?;
1175 }
1176 AttributeValue::Data2(val) => {
1177 debug_assert_form!(constants::DW_FORM_data2);
1178 w.write_u16(val)?;
1179 }
1180 AttributeValue::Data4(val) => {
1181 debug_assert_form!(constants::DW_FORM_data4);
1182 w.write_u32(val)?;
1183 }
1184 AttributeValue::Data8(val) => {
1185 debug_assert_form!(constants::DW_FORM_data8);
1186 w.write_u64(val)?;
1187 }
1188 AttributeValue::Sdata(val) => {
1189 debug_assert_form!(constants::DW_FORM_sdata);
1190 w.write_sleb128(val)?;
1191 }
1192 AttributeValue::Udata(val) => {
1193 debug_assert_form!(constants::DW_FORM_udata);
1194 w.write_uleb128(val)?;
1195 }
1196 AttributeValue::Exprloc(ref val) => {
1197 debug_assert_form!(constants::DW_FORM_exprloc);
1198 w.write_uleb128(val.size(unit.encoding(), Some(offsets)) as u64)?;
1199 val.write(
1200 &mut w.0,
1201 Some(debug_info_refs),
1202 unit.encoding(),
1203 Some(offsets),
1204 )?;
1205 }
1206 AttributeValue::Flag(val) => {
1207 debug_assert_form!(constants::DW_FORM_flag);
1208 w.write_u8(val as u8)?;
1209 }
1210 AttributeValue::FlagPresent => {
1211 debug_assert_form!(constants::DW_FORM_flag_present);
1212 }
1213 AttributeValue::UnitRef(id) => {
1214 match unit.format() {
1215 Format::Dwarf32 => debug_assert_form!(constants::DW_FORM_ref4),
1216 Format::Dwarf64 => debug_assert_form!(constants::DW_FORM_ref8),
1217 }
1218 unit_refs.push((w.offset(), id));
1219 w.write_udata(0, unit.format().word_size())?;
1220 }
1221 AttributeValue::DebugInfoRef(reference) => {
1222 debug_assert_form!(constants::DW_FORM_ref_addr);
1223 let size = if unit.version() == 2 {
1224 unit.address_size()
1225 } else {
1226 unit.format().word_size()
1227 };
1228 match reference {
1229 Reference::Symbol(symbol) => w.write_reference(symbol, size)?,
1230 Reference::Entry(unit, entry) => {
1231 debug_info_refs.push(DebugInfoReference {
1232 offset: w.len(),
1233 unit,
1234 entry,
1235 size,
1236 });
1237 w.write_udata(0, size)?;
1238 }
1239 }
1240 }
1241 AttributeValue::DebugInfoRefSup(val) => {
1242 match unit.format() {
1243 Format::Dwarf32 => debug_assert_form!(constants::DW_FORM_ref_sup4),
1244 Format::Dwarf64 => debug_assert_form!(constants::DW_FORM_ref_sup8),
1245 }
1246 w.write_udata(val.0 as u64, unit.format().word_size())?;
1247 }
1248 AttributeValue::LineProgramRef => {
1249 if unit.version() >= 4 {
1250 debug_assert_form!(constants::DW_FORM_sec_offset);
1251 }
1252 match line_program {
1253 Some(line_program) => {
1254 w.write_offset(
1255 line_program.0,
1256 SectionId::DebugLine,
1257 unit.format().word_size(),
1258 )?;
1259 }
1260 None => return Err(Error::InvalidAttributeValue),
1261 }
1262 }
1263 AttributeValue::LocationListRef(val) => {
1264 if unit.version() >= 4 {
1265 debug_assert_form!(constants::DW_FORM_sec_offset);
1266 }
1267 let section = if unit.version() <= 4 {
1268 SectionId::DebugLoc
1269 } else {
1270 SectionId::DebugLocLists
1271 };
1272 w.write_offset(loc_lists.get(val).0, section, unit.format().word_size())?;
1273 }
1274 AttributeValue::DebugMacinfoRef(val) => {
1275 if unit.version() >= 4 {
1276 debug_assert_form!(constants::DW_FORM_sec_offset);
1277 }
1278 w.write_offset(val.0, SectionId::DebugMacinfo, unit.format().word_size())?;
1279 }
1280 AttributeValue::DebugMacroRef(val) => {
1281 if unit.version() >= 4 {
1282 debug_assert_form!(constants::DW_FORM_sec_offset);
1283 }
1284 w.write_offset(val.0, SectionId::DebugMacro, unit.format().word_size())?;
1285 }
1286 AttributeValue::RangeListRef(val) => {
1287 if unit.version() >= 4 {
1288 debug_assert_form!(constants::DW_FORM_sec_offset);
1289 }
1290 let section = if unit.version() <= 4 {
1291 SectionId::DebugRanges
1292 } else {
1293 SectionId::DebugRngLists
1294 };
1295 w.write_offset(range_lists.get(val).0, section, unit.format().word_size())?;
1296 }
1297 AttributeValue::DebugTypesRef(val) => {
1298 debug_assert_form!(constants::DW_FORM_ref_sig8);
1299 w.write_u64(val.0)?;
1300 }
1301 AttributeValue::StringRef(val) => {
1302 debug_assert_form!(constants::DW_FORM_strp);
1303 w.write_offset(
1304 strings.get(val).0,
1305 SectionId::DebugStr,
1306 unit.format().word_size(),
1307 )?;
1308 }
1309 AttributeValue::DebugStrRefSup(val) => {
1310 debug_assert_form!(constants::DW_FORM_strp_sup);
1311 w.write_udata(val.0 as u64, unit.format().word_size())?;
1312 }
1313 AttributeValue::LineStringRef(val) => {
1314 debug_assert_form!(constants::DW_FORM_line_strp);
1315 w.write_offset(
1316 line_strings.get(val).0,
1317 SectionId::DebugLineStr,
1318 unit.format().word_size(),
1319 )?;
1320 }
1321 AttributeValue::String(ref val) => {
1322 debug_assert_form!(constants::DW_FORM_string);
1323 w.write(val)?;
1324 w.write_u8(0)?;
1325 }
1326 AttributeValue::Encoding(val) => {
1327 debug_assert_form!(constants::DW_FORM_udata);
1328 w.write_uleb128(u64::from(val.0))?;
1329 }
1330 AttributeValue::DecimalSign(val) => {
1331 debug_assert_form!(constants::DW_FORM_udata);
1332 w.write_uleb128(u64::from(val.0))?;
1333 }
1334 AttributeValue::Endianity(val) => {
1335 debug_assert_form!(constants::DW_FORM_udata);
1336 w.write_uleb128(u64::from(val.0))?;
1337 }
1338 AttributeValue::Accessibility(val) => {
1339 debug_assert_form!(constants::DW_FORM_udata);
1340 w.write_uleb128(u64::from(val.0))?;
1341 }
1342 AttributeValue::Visibility(val) => {
1343 debug_assert_form!(constants::DW_FORM_udata);
1344 w.write_uleb128(u64::from(val.0))?;
1345 }
1346 AttributeValue::Virtuality(val) => {
1347 debug_assert_form!(constants::DW_FORM_udata);
1348 w.write_uleb128(u64::from(val.0))?;
1349 }
1350 AttributeValue::Language(val) => {
1351 debug_assert_form!(constants::DW_FORM_udata);
1352 w.write_uleb128(u64::from(val.0))?;
1353 }
1354 AttributeValue::AddressClass(val) => {
1355 debug_assert_form!(constants::DW_FORM_udata);
1356 w.write_uleb128(val.0)?;
1357 }
1358 AttributeValue::IdentifierCase(val) => {
1359 debug_assert_form!(constants::DW_FORM_udata);
1360 w.write_uleb128(u64::from(val.0))?;
1361 }
1362 AttributeValue::CallingConvention(val) => {
1363 debug_assert_form!(constants::DW_FORM_udata);
1364 w.write_uleb128(u64::from(val.0))?;
1365 }
1366 AttributeValue::Inline(val) => {
1367 debug_assert_form!(constants::DW_FORM_udata);
1368 w.write_uleb128(u64::from(val.0))?;
1369 }
1370 AttributeValue::Ordering(val) => {
1371 debug_assert_form!(constants::DW_FORM_udata);
1372 w.write_uleb128(u64::from(val.0))?;
1373 }
1374 AttributeValue::FileIndex(val) => {
1375 debug_assert_form!(constants::DW_FORM_udata);
1376 w.write_uleb128(val.map(|id| id.raw(unit.version())).unwrap_or(0))?;
1377 }
1378 }
1379 Ok(())
1380 }
1381}
1382
1383define_section!(
1384 DebugInfo,
1385 DebugInfoOffset,
1386 "A writable `.debug_info` section."
1387);
1388
1389#[derive(Debug, Default)]
1391pub struct DebugInfoOffsets {
1392 base_id: BaseId,
1393 units: Vec<UnitOffsets>,
1394}
1395
1396impl DebugInfoOffsets {
1397 #[inline]
1399 pub fn unit(&self, unit: UnitId) -> DebugInfoOffset {
1400 debug_assert_eq!(self.base_id, unit.base_id);
1401 self.units[unit.index].unit
1402 }
1403
1404 #[inline]
1406 pub fn entry(&self, unit: UnitId, entry: UnitEntryId) -> DebugInfoOffset {
1407 debug_assert_eq!(self.base_id, unit.base_id);
1408 self.units[unit.index].debug_info_offset(entry)
1409 }
1410}
1411
1412#[derive(Debug)]
1414pub(crate) struct UnitOffsets {
1415 base_id: BaseId,
1416 unit: DebugInfoOffset,
1417 entries: Vec<EntryOffset>,
1418}
1419
1420impl UnitOffsets {
1421 #[inline]
1423 pub(crate) fn debug_info_offset(&self, entry: UnitEntryId) -> DebugInfoOffset {
1424 debug_assert_eq!(self.base_id, entry.base_id);
1425 let offset = self.entries[entry.index].offset;
1426 debug_assert_ne!(offset.0, 0);
1427 offset
1428 }
1429
1430 #[inline]
1432 pub(crate) fn unit_offset(&self, entry: UnitEntryId) -> u64 {
1433 let offset = self.debug_info_offset(entry);
1434 (offset.0 - self.unit.0) as u64
1435 }
1436
1437 #[inline]
1439 pub(crate) fn abbrev(&self, entry: UnitEntryId) -> u64 {
1440 debug_assert_eq!(self.base_id, entry.base_id);
1441 self.entries[entry.index].abbrev
1442 }
1443}
1444
1445#[derive(Debug, Clone, Copy)]
1446pub(crate) struct EntryOffset {
1447 offset: DebugInfoOffset,
1448 abbrev: u64,
1449}
1450
1451impl EntryOffset {
1452 fn none() -> Self {
1453 EntryOffset {
1454 offset: DebugInfoOffset(0),
1455 abbrev: 0,
1456 }
1457 }
1458}
1459
1460#[derive(Debug, Clone, Copy)]
1462pub(crate) struct DebugInfoReference {
1463 pub offset: usize,
1465 pub size: u8,
1467 pub unit: UnitId,
1469 pub entry: UnitEntryId,
1471}
1472
1473#[cfg(feature = "read")]
1474pub(crate) mod convert {
1475 use super::*;
1476 use crate::common::{DwoId, UnitSectionOffset};
1477 use crate::read::{self, Reader};
1478 use crate::write::{self, ConvertError, ConvertResult, LocationList, RangeList};
1479 use std::collections::HashMap;
1480
1481 pub(crate) struct ConvertUnit<R: Reader<Offset = usize>> {
1482 from_unit: read::Unit<R>,
1483 base_id: BaseId,
1484 encoding: Encoding,
1485 entries: Vec<DebuggingInformationEntry>,
1486 entry_offsets: Vec<read::UnitOffset>,
1487 root: UnitEntryId,
1488 }
1489
1490 pub(crate) struct ConvertUnitContext<'a, R: Reader<Offset = usize>> {
1491 pub dwarf: &'a read::Dwarf<R>,
1492 pub unit: &'a read::Unit<R>,
1493 pub line_strings: &'a mut write::LineStringTable,
1494 pub strings: &'a mut write::StringTable,
1495 pub ranges: &'a mut write::RangeListTable,
1496 pub locations: &'a mut write::LocationListTable,
1497 pub convert_address: &'a dyn Fn(u64) -> Option<Address>,
1498 pub base_address: Address,
1499 pub line_program_offset: Option<DebugLineOffset>,
1500 pub line_program_files: Vec<FileId>,
1501 pub entry_ids: &'a HashMap<UnitSectionOffset, (UnitId, UnitEntryId)>,
1502 }
1503
1504 impl UnitTable {
1505 pub fn from<R: Reader<Offset = usize>>(
1516 dwarf: &read::Dwarf<R>,
1517 line_strings: &mut write::LineStringTable,
1518 strings: &mut write::StringTable,
1519 convert_address: &dyn Fn(u64) -> Option<Address>,
1520 ) -> ConvertResult<UnitTable> {
1521 let base_id = BaseId::default();
1522 let mut unit_entries = Vec::new();
1523 let mut entry_ids = HashMap::new();
1524
1525 let mut from_units = dwarf.units();
1526 while let Some(from_unit) = from_units.next()? {
1527 let unit_id = UnitId::new(base_id, unit_entries.len());
1528 unit_entries.push(Unit::convert_entries(
1529 from_unit,
1530 unit_id,
1531 &mut entry_ids,
1532 dwarf,
1533 )?);
1534 }
1535
1536 let mut units = Vec::new();
1539 for unit_entries in unit_entries.drain(..) {
1540 units.push(Unit::convert_attributes(
1541 unit_entries,
1542 &entry_ids,
1543 dwarf,
1544 line_strings,
1545 strings,
1546 convert_address,
1547 )?);
1548 }
1549
1550 Ok(UnitTable { base_id, units })
1551 }
1552 }
1553
1554 impl Unit {
1555 pub(crate) fn convert_entries<R: Reader<Offset = usize>>(
1559 from_header: read::UnitHeader<R>,
1560 unit_id: UnitId,
1561 entry_ids: &mut HashMap<UnitSectionOffset, (UnitId, UnitEntryId)>,
1562 dwarf: &read::Dwarf<R>,
1563 ) -> ConvertResult<ConvertUnit<R>> {
1564 match from_header.type_() {
1565 read::UnitType::Compilation => (),
1566 _ => return Err(ConvertError::UnsupportedUnitType),
1567 }
1568 let base_id = BaseId::default();
1569
1570 let from_unit = dwarf.unit(from_header)?;
1571 let encoding = from_unit.encoding();
1572
1573 let mut entries = Vec::new();
1574 let mut entry_offsets = Vec::new();
1575
1576 let mut from_tree = from_unit.entries_tree(None)?;
1577 let from_root = from_tree.root()?;
1578 let root = DebuggingInformationEntry::convert_entry(
1579 from_root,
1580 &from_unit,
1581 base_id,
1582 &mut entries,
1583 &mut entry_offsets,
1584 entry_ids,
1585 None,
1586 unit_id,
1587 )?;
1588
1589 Ok(ConvertUnit {
1590 from_unit,
1591 base_id,
1592 encoding,
1593 entries,
1594 entry_offsets,
1595 root,
1596 })
1597 }
1598
1599 fn convert_attributes<R: Reader<Offset = usize>>(
1601 unit: ConvertUnit<R>,
1602 entry_ids: &HashMap<UnitSectionOffset, (UnitId, UnitEntryId)>,
1603 dwarf: &read::Dwarf<R>,
1604 line_strings: &mut write::LineStringTable,
1605 strings: &mut write::StringTable,
1606 convert_address: &dyn Fn(u64) -> Option<Address>,
1607 ) -> ConvertResult<Unit> {
1608 let from_unit = unit.from_unit;
1609 let base_address =
1610 convert_address(from_unit.low_pc).ok_or(ConvertError::InvalidAddress)?;
1611
1612 let (line_program_offset, line_program, line_program_files) =
1613 match from_unit.line_program {
1614 Some(ref from_program) => {
1615 let from_program = from_program.clone();
1616 let line_program_offset = from_program.header().offset();
1617 let (line_program, line_program_files) = LineProgram::from(
1618 from_program,
1619 dwarf,
1620 line_strings,
1621 strings,
1622 convert_address,
1623 )?;
1624 (Some(line_program_offset), line_program, line_program_files)
1625 }
1626 None => (None, LineProgram::none(), Vec::new()),
1627 };
1628
1629 let mut ranges = RangeListTable::default();
1630 let mut locations = LocationListTable::default();
1631
1632 let mut context = ConvertUnitContext {
1633 entry_ids,
1634 dwarf,
1635 unit: &from_unit,
1636 line_strings,
1637 strings,
1638 ranges: &mut ranges,
1639 locations: &mut locations,
1640 convert_address,
1641 base_address,
1642 line_program_offset,
1643 line_program_files,
1644 };
1645
1646 let mut entries = unit.entries;
1647 for entry in &mut entries {
1648 entry.convert_attributes(&mut context, &unit.entry_offsets)?;
1649 }
1650
1651 Ok(Unit {
1652 base_id: unit.base_id,
1653 encoding: unit.encoding,
1654 line_program,
1655 ranges,
1656 locations,
1657 entries,
1658 root: unit.root,
1659 })
1660 }
1661 }
1662
1663 impl DebuggingInformationEntry {
1664 fn convert_entry<R: Reader<Offset = usize>>(
1668 from: read::EntriesTreeNode<'_, '_, '_, R>,
1669 from_unit: &read::Unit<R>,
1670 base_id: BaseId,
1671 entries: &mut Vec<DebuggingInformationEntry>,
1672 entry_offsets: &mut Vec<read::UnitOffset>,
1673 entry_ids: &mut HashMap<UnitSectionOffset, (UnitId, UnitEntryId)>,
1674 parent: Option<UnitEntryId>,
1675 unit_id: UnitId,
1676 ) -> ConvertResult<UnitEntryId> {
1677 let from_entry = from.entry();
1678 let id = DebuggingInformationEntry::new(base_id, entries, parent, from_entry.tag());
1679 let offset = from_entry.offset();
1680 entry_offsets.push(offset);
1681 entry_ids.insert(offset.to_unit_section_offset(from_unit), (unit_id, id));
1682
1683 let mut from_children = from.children();
1684 while let Some(from_child) = from_children.next()? {
1685 DebuggingInformationEntry::convert_entry(
1686 from_child,
1687 from_unit,
1688 base_id,
1689 entries,
1690 entry_offsets,
1691 entry_ids,
1692 Some(id),
1693 unit_id,
1694 )?;
1695 }
1696 Ok(id)
1697 }
1698
1699 fn convert_attributes<R: Reader<Offset = usize>>(
1701 &mut self,
1702 context: &mut ConvertUnitContext<'_, R>,
1703 entry_offsets: &[read::UnitOffset],
1704 ) -> ConvertResult<()> {
1705 let offset = entry_offsets[self.id.index];
1706 let from = context.unit.entry(offset)?;
1707 let mut from_attrs = from.attrs();
1708 while let Some(from_attr) = from_attrs.next()? {
1709 if from_attr.name() == constants::DW_AT_sibling {
1710 self.set_sibling(true);
1712 } else if let Some(attr) = Attribute::from(context, &from_attr)? {
1713 self.set(attr.name, attr.value);
1714 }
1715 }
1716 Ok(())
1717 }
1718 }
1719
1720 impl Attribute {
1721 pub(crate) fn from<R: Reader<Offset = usize>>(
1723 context: &mut ConvertUnitContext<'_, R>,
1724 from: &read::Attribute<R>,
1725 ) -> ConvertResult<Option<Attribute>> {
1726 let value = AttributeValue::from(context, from.value())?;
1727 Ok(value.map(|value| Attribute {
1728 name: from.name(),
1729 value,
1730 }))
1731 }
1732 }
1733
1734 impl AttributeValue {
1735 pub(crate) fn from<R: Reader<Offset = usize>>(
1737 context: &mut ConvertUnitContext<'_, R>,
1738 from: read::AttributeValue<R>,
1739 ) -> ConvertResult<Option<AttributeValue>> {
1740 let to = match from {
1741 read::AttributeValue::Addr(val) => match (context.convert_address)(val) {
1742 Some(val) => AttributeValue::Address(val),
1743 None => return Err(ConvertError::InvalidAddress),
1744 },
1745 read::AttributeValue::Block(r) => AttributeValue::Block(r.to_slice()?.into()),
1746 read::AttributeValue::Data1(val) => AttributeValue::Data1(val),
1747 read::AttributeValue::Data2(val) => AttributeValue::Data2(val),
1748 read::AttributeValue::Data4(val) => AttributeValue::Data4(val),
1749 read::AttributeValue::Data8(val) => AttributeValue::Data8(val),
1750 read::AttributeValue::Sdata(val) => AttributeValue::Sdata(val),
1751 read::AttributeValue::Udata(val) => AttributeValue::Udata(val),
1752 read::AttributeValue::Exprloc(expression) => {
1753 let expression = Expression::from(
1754 expression,
1755 context.unit.encoding(),
1756 Some(context.dwarf),
1757 Some(context.unit),
1758 Some(context.entry_ids),
1759 context.convert_address,
1760 )?;
1761 AttributeValue::Exprloc(expression)
1762 }
1763 read::AttributeValue::Flag(val) => AttributeValue::Flag(val),
1765 read::AttributeValue::DebugAddrBase(_base) => {
1766 return Ok(None);
1769 }
1770 read::AttributeValue::DebugAddrIndex(index) => {
1771 let val = context.dwarf.address(context.unit, index)?;
1772 match (context.convert_address)(val) {
1773 Some(val) => AttributeValue::Address(val),
1774 None => return Err(ConvertError::InvalidAddress),
1775 }
1776 }
1777 read::AttributeValue::UnitRef(val) => {
1778 if !context.unit.header.is_valid_offset(val) {
1779 return Err(ConvertError::InvalidUnitRef);
1780 }
1781 let id = context
1782 .entry_ids
1783 .get(&val.to_unit_section_offset(context.unit))
1784 .ok_or(ConvertError::InvalidUnitRef)?;
1785 AttributeValue::UnitRef(id.1)
1786 }
1787 read::AttributeValue::DebugInfoRef(val) => {
1788 let id = context
1790 .entry_ids
1791 .get(&UnitSectionOffset::DebugInfoOffset(val))
1792 .ok_or(ConvertError::InvalidDebugInfoRef)?;
1793 AttributeValue::DebugInfoRef(Reference::Entry(id.0, id.1))
1794 }
1795 read::AttributeValue::DebugInfoRefSup(val) => AttributeValue::DebugInfoRefSup(val),
1796 read::AttributeValue::DebugLineRef(val) => {
1797 if Some(val) == context.line_program_offset {
1800 AttributeValue::LineProgramRef
1801 } else {
1802 return Err(ConvertError::InvalidLineRef);
1803 }
1804 }
1805 read::AttributeValue::DebugMacinfoRef(val) => AttributeValue::DebugMacinfoRef(val),
1806 read::AttributeValue::DebugMacroRef(val) => AttributeValue::DebugMacroRef(val),
1807 read::AttributeValue::LocationListsRef(val) => {
1808 let iter = context
1809 .dwarf
1810 .locations
1811 .raw_locations(val, context.unit.encoding())?;
1812 let loc_list = LocationList::from(iter, context)?;
1813 let loc_id = context.locations.add(loc_list);
1814 AttributeValue::LocationListRef(loc_id)
1815 }
1816 read::AttributeValue::DebugLocListsBase(_base) => {
1817 return Ok(None);
1820 }
1821 read::AttributeValue::DebugLocListsIndex(index) => {
1822 let offset = context.dwarf.locations_offset(context.unit, index)?;
1823 let iter = context
1824 .dwarf
1825 .locations
1826 .raw_locations(offset, context.unit.encoding())?;
1827 let loc_list = LocationList::from(iter, context)?;
1828 let loc_id = context.locations.add(loc_list);
1829 AttributeValue::LocationListRef(loc_id)
1830 }
1831 read::AttributeValue::RangeListsRef(offset) => {
1832 let offset = context.dwarf.ranges_offset_from_raw(context.unit, offset);
1833 let iter = context.dwarf.raw_ranges(context.unit, offset)?;
1834 let range_list = RangeList::from(iter, context)?;
1835 let range_id = context.ranges.add(range_list);
1836 AttributeValue::RangeListRef(range_id)
1837 }
1838 read::AttributeValue::DebugRngListsBase(_base) => {
1839 return Ok(None);
1842 }
1843 read::AttributeValue::DebugRngListsIndex(index) => {
1844 let offset = context.dwarf.ranges_offset(context.unit, index)?;
1845 let iter = context
1846 .dwarf
1847 .ranges
1848 .raw_ranges(offset, context.unit.encoding())?;
1849 let range_list = RangeList::from(iter, context)?;
1850 let range_id = context.ranges.add(range_list);
1851 AttributeValue::RangeListRef(range_id)
1852 }
1853 read::AttributeValue::DebugTypesRef(val) => AttributeValue::DebugTypesRef(val),
1854 read::AttributeValue::DebugStrRef(offset) => {
1855 let r = context.dwarf.string(offset)?;
1856 let id = context.strings.add(r.to_slice()?);
1857 AttributeValue::StringRef(id)
1858 }
1859 read::AttributeValue::DebugStrRefSup(val) => AttributeValue::DebugStrRefSup(val),
1860 read::AttributeValue::DebugStrOffsetsBase(_base) => {
1861 return Ok(None);
1864 }
1865 read::AttributeValue::DebugStrOffsetsIndex(index) => {
1866 let offset = context.dwarf.string_offset(context.unit, index)?;
1867 let r = context.dwarf.string(offset)?;
1868 let id = context.strings.add(r.to_slice()?);
1869 AttributeValue::StringRef(id)
1870 }
1871 read::AttributeValue::DebugLineStrRef(offset) => {
1872 let r = context.dwarf.line_string(offset)?;
1873 let id = context.line_strings.add(r.to_slice()?);
1874 AttributeValue::LineStringRef(id)
1875 }
1876 read::AttributeValue::String(r) => AttributeValue::String(r.to_slice()?.into()),
1877 read::AttributeValue::Encoding(val) => AttributeValue::Encoding(val),
1878 read::AttributeValue::DecimalSign(val) => AttributeValue::DecimalSign(val),
1879 read::AttributeValue::Endianity(val) => AttributeValue::Endianity(val),
1880 read::AttributeValue::Accessibility(val) => AttributeValue::Accessibility(val),
1881 read::AttributeValue::Visibility(val) => AttributeValue::Visibility(val),
1882 read::AttributeValue::Virtuality(val) => AttributeValue::Virtuality(val),
1883 read::AttributeValue::Language(val) => AttributeValue::Language(val),
1884 read::AttributeValue::AddressClass(val) => AttributeValue::AddressClass(val),
1885 read::AttributeValue::IdentifierCase(val) => AttributeValue::IdentifierCase(val),
1886 read::AttributeValue::CallingConvention(val) => {
1887 AttributeValue::CallingConvention(val)
1888 }
1889 read::AttributeValue::Inline(val) => AttributeValue::Inline(val),
1890 read::AttributeValue::Ordering(val) => AttributeValue::Ordering(val),
1891 read::AttributeValue::FileIndex(val) => {
1892 if val == 0 && context.unit.encoding().version <= 4 {
1893 AttributeValue::FileIndex(None)
1894 } else {
1895 match context.line_program_files.get(val as usize) {
1896 Some(id) => AttributeValue::FileIndex(Some(*id)),
1897 None => return Err(ConvertError::InvalidFileIndex),
1898 }
1899 }
1900 }
1901 read::AttributeValue::SecOffset(_) => {
1903 return Err(ConvertError::InvalidAttributeValue);
1904 }
1905 read::AttributeValue::DwoId(DwoId(val)) => AttributeValue::Udata(val),
1906 };
1907 Ok(Some(to))
1908 }
1909 }
1910}
1911
1912#[cfg(test)]
1913#[cfg(feature = "read")]
1914mod tests {
1915 use super::*;
1916 use crate::common::LineEncoding;
1917 use crate::constants;
1918 use crate::read;
1919 use crate::write::{
1920 Dwarf, DwarfUnit, EndianVec, LineString, Location, LocationList, Range, RangeList,
1921 };
1922 use crate::LittleEndian;
1923 use std::mem;
1924
1925 #[test]
1926 fn test_unit_table() {
1927 let mut dwarf = Dwarf::new();
1928 let unit_id1 = dwarf.units.add(Unit::new(
1929 Encoding {
1930 version: 4,
1931 address_size: 8,
1932 format: Format::Dwarf32,
1933 },
1934 LineProgram::none(),
1935 ));
1936 let unit2 = dwarf.units.add(Unit::new(
1937 Encoding {
1938 version: 2,
1939 address_size: 4,
1940 format: Format::Dwarf64,
1941 },
1942 LineProgram::none(),
1943 ));
1944 let unit3 = dwarf.units.add(Unit::new(
1945 Encoding {
1946 version: 5,
1947 address_size: 4,
1948 format: Format::Dwarf32,
1949 },
1950 LineProgram::none(),
1951 ));
1952 assert_eq!(dwarf.units.count(), 3);
1953 {
1954 let unit1 = dwarf.units.get_mut(unit_id1);
1955 assert_eq!(unit1.version(), 4);
1956 assert_eq!(unit1.address_size(), 8);
1957 assert_eq!(unit1.format(), Format::Dwarf32);
1958 assert_eq!(unit1.count(), 1);
1959
1960 let root_id = unit1.root();
1961 assert_eq!(root_id, UnitEntryId::new(unit1.base_id, 0));
1962 {
1963 let root = unit1.get_mut(root_id);
1964 assert_eq!(root.id(), root_id);
1965 assert!(root.parent().is_none());
1966 assert_eq!(root.tag(), constants::DW_TAG_compile_unit);
1967
1968 assert!(root.get(constants::DW_AT_producer).is_none());
1970 assert!(root.get_mut(constants::DW_AT_producer).is_none());
1971 let mut producer = AttributeValue::String(b"root"[..].into());
1972 root.set(constants::DW_AT_producer, producer.clone());
1973 assert_eq!(root.get(constants::DW_AT_producer), Some(&producer));
1974 assert_eq!(root.get_mut(constants::DW_AT_producer), Some(&mut producer));
1975
1976 let mut attrs = root.attrs();
1978 let attr = attrs.next().unwrap();
1979 assert_eq!(attr.name(), constants::DW_AT_producer);
1980 assert_eq!(attr.get(), &producer);
1981 assert!(attrs.next().is_none());
1982 }
1983
1984 let child1 = unit1.add(root_id, constants::DW_TAG_subprogram);
1985 assert_eq!(child1, UnitEntryId::new(unit1.base_id, 1));
1986 {
1987 let child1 = unit1.get_mut(child1);
1988 assert_eq!(child1.parent(), Some(root_id));
1989
1990 let tmp = AttributeValue::String(b"tmp"[..].into());
1991 child1.set(constants::DW_AT_name, tmp.clone());
1992 assert_eq!(child1.get(constants::DW_AT_name), Some(&tmp));
1993
1994 let name = AttributeValue::StringRef(dwarf.strings.add(&b"child1"[..]));
1996 {
1997 let attr = child1.attrs_mut().next().unwrap();
1998 assert_eq!(attr.name(), constants::DW_AT_name);
1999 attr.set(name.clone());
2000 }
2001 assert_eq!(child1.get(constants::DW_AT_name), Some(&name));
2002 }
2003
2004 let child2 = unit1.add(root_id, constants::DW_TAG_subprogram);
2005 assert_eq!(child2, UnitEntryId::new(unit1.base_id, 2));
2006 {
2007 let child2 = unit1.get_mut(child2);
2008 assert_eq!(child2.parent(), Some(root_id));
2009
2010 let tmp = AttributeValue::String(b"tmp"[..].into());
2011 child2.set(constants::DW_AT_name, tmp.clone());
2012 assert_eq!(child2.get(constants::DW_AT_name), Some(&tmp));
2013
2014 let name = AttributeValue::StringRef(dwarf.strings.add(&b"child2"[..]));
2016 child2.set(constants::DW_AT_name, name.clone());
2017 assert_eq!(child2.get(constants::DW_AT_name), Some(&name));
2018 }
2019
2020 {
2021 let root = unit1.get(root_id);
2022 assert_eq!(
2023 root.children().cloned().collect::<Vec<_>>(),
2024 vec![child1, child2]
2025 );
2026 }
2027 }
2028 {
2029 let unit2 = dwarf.units.get(unit2);
2030 assert_eq!(unit2.version(), 2);
2031 assert_eq!(unit2.address_size(), 4);
2032 assert_eq!(unit2.format(), Format::Dwarf64);
2033 assert_eq!(unit2.count(), 1);
2034
2035 let root = unit2.root();
2036 assert_eq!(root, UnitEntryId::new(unit2.base_id, 0));
2037 let root = unit2.get(root);
2038 assert_eq!(root.id(), UnitEntryId::new(unit2.base_id, 0));
2039 assert!(root.parent().is_none());
2040 assert_eq!(root.tag(), constants::DW_TAG_compile_unit);
2041 }
2042
2043 let mut sections = Sections::new(EndianVec::new(LittleEndian));
2044 dwarf.write(&mut sections).unwrap();
2045
2046 println!("{:?}", sections.debug_str);
2047 println!("{:?}", sections.debug_info);
2048 println!("{:?}", sections.debug_abbrev);
2049
2050 let read_dwarf = sections.read(LittleEndian);
2051 let mut read_units = read_dwarf.units();
2052
2053 {
2054 let read_unit1 = read_units.next().unwrap().unwrap();
2055 let unit1 = dwarf.units.get(unit_id1);
2056 assert_eq!(unit1.version(), read_unit1.version());
2057 assert_eq!(unit1.address_size(), read_unit1.address_size());
2058 assert_eq!(unit1.format(), read_unit1.format());
2059
2060 let read_unit1 = read_dwarf.unit(read_unit1).unwrap();
2061 let mut read_entries = read_unit1.entries();
2062
2063 let root = unit1.get(unit1.root());
2064 {
2065 let (depth, read_root) = read_entries.next_dfs().unwrap().unwrap();
2066 assert_eq!(depth, 0);
2067 assert_eq!(root.tag(), read_root.tag());
2068 assert!(read_root.has_children());
2069
2070 let producer = match root.get(constants::DW_AT_producer).unwrap() {
2071 AttributeValue::String(ref producer) => &**producer,
2072 otherwise => panic!("unexpected {:?}", otherwise),
2073 };
2074 assert_eq!(producer, b"root");
2075 let read_producer = read_root
2076 .attr_value(constants::DW_AT_producer)
2077 .unwrap()
2078 .unwrap();
2079 assert_eq!(
2080 read_dwarf
2081 .attr_string(&read_unit1, read_producer)
2082 .unwrap()
2083 .slice(),
2084 producer
2085 );
2086 }
2087
2088 let mut children = root.children().cloned();
2089
2090 {
2091 let child = children.next().unwrap();
2092 assert_eq!(child, UnitEntryId::new(unit1.base_id, 1));
2093 let child = unit1.get(child);
2094 let (depth, read_child) = read_entries.next_dfs().unwrap().unwrap();
2095 assert_eq!(depth, 1);
2096 assert_eq!(child.tag(), read_child.tag());
2097 assert!(!read_child.has_children());
2098
2099 let name = match child.get(constants::DW_AT_name).unwrap() {
2100 AttributeValue::StringRef(name) => *name,
2101 otherwise => panic!("unexpected {:?}", otherwise),
2102 };
2103 let name = dwarf.strings.get(name);
2104 assert_eq!(name, b"child1");
2105 let read_name = read_child
2106 .attr_value(constants::DW_AT_name)
2107 .unwrap()
2108 .unwrap();
2109 assert_eq!(
2110 read_dwarf
2111 .attr_string(&read_unit1, read_name)
2112 .unwrap()
2113 .slice(),
2114 name
2115 );
2116 }
2117
2118 {
2119 let child = children.next().unwrap();
2120 assert_eq!(child, UnitEntryId::new(unit1.base_id, 2));
2121 let child = unit1.get(child);
2122 let (depth, read_child) = read_entries.next_dfs().unwrap().unwrap();
2123 assert_eq!(depth, 0);
2124 assert_eq!(child.tag(), read_child.tag());
2125 assert!(!read_child.has_children());
2126
2127 let name = match child.get(constants::DW_AT_name).unwrap() {
2128 AttributeValue::StringRef(name) => *name,
2129 otherwise => panic!("unexpected {:?}", otherwise),
2130 };
2131 let name = dwarf.strings.get(name);
2132 assert_eq!(name, b"child2");
2133 let read_name = read_child
2134 .attr_value(constants::DW_AT_name)
2135 .unwrap()
2136 .unwrap();
2137 assert_eq!(
2138 read_dwarf
2139 .attr_string(&read_unit1, read_name)
2140 .unwrap()
2141 .slice(),
2142 name
2143 );
2144 }
2145
2146 assert!(read_entries.next_dfs().unwrap().is_none());
2147 }
2148
2149 {
2150 let read_unit2 = read_units.next().unwrap().unwrap();
2151 let unit2 = dwarf.units.get(unit2);
2152 assert_eq!(unit2.version(), read_unit2.version());
2153 assert_eq!(unit2.address_size(), read_unit2.address_size());
2154 assert_eq!(unit2.format(), read_unit2.format());
2155
2156 let abbrevs = read_dwarf.abbreviations(&read_unit2).unwrap();
2157 let mut read_entries = read_unit2.entries(&abbrevs);
2158
2159 {
2160 let root = unit2.get(unit2.root());
2161 let (depth, read_root) = read_entries.next_dfs().unwrap().unwrap();
2162 assert_eq!(depth, 0);
2163 assert_eq!(root.tag(), read_root.tag());
2164 assert!(!read_root.has_children());
2165 }
2166
2167 assert!(read_entries.next_dfs().unwrap().is_none());
2168 }
2169
2170 {
2171 let read_unit3 = read_units.next().unwrap().unwrap();
2172 let unit3 = dwarf.units.get(unit3);
2173 assert_eq!(unit3.version(), read_unit3.version());
2174 assert_eq!(unit3.address_size(), read_unit3.address_size());
2175 assert_eq!(unit3.format(), read_unit3.format());
2176
2177 let abbrevs = read_dwarf.abbreviations(&read_unit3).unwrap();
2178 let mut read_entries = read_unit3.entries(&abbrevs);
2179
2180 {
2181 let root = unit3.get(unit3.root());
2182 let (depth, read_root) = read_entries.next_dfs().unwrap().unwrap();
2183 assert_eq!(depth, 0);
2184 assert_eq!(root.tag(), read_root.tag());
2185 assert!(!read_root.has_children());
2186 }
2187
2188 assert!(read_entries.next_dfs().unwrap().is_none());
2189 }
2190
2191 assert!(read_units.next().unwrap().is_none());
2192
2193 let convert_dwarf =
2194 Dwarf::from(&read_dwarf, &|address| Some(Address::Constant(address))).unwrap();
2195 assert_eq!(convert_dwarf.units.count(), dwarf.units.count());
2196
2197 for i in 0..convert_dwarf.units.count() {
2198 let unit_id = dwarf.units.id(i);
2199 let unit = dwarf.units.get(unit_id);
2200 let convert_unit_id = convert_dwarf.units.id(i);
2201 let convert_unit = convert_dwarf.units.get(convert_unit_id);
2202 assert_eq!(convert_unit.version(), unit.version());
2203 assert_eq!(convert_unit.address_size(), unit.address_size());
2204 assert_eq!(convert_unit.format(), unit.format());
2205 assert_eq!(convert_unit.count(), unit.count());
2206
2207 let root = unit.get(unit.root());
2208 let convert_root = convert_unit.get(convert_unit.root());
2209 assert_eq!(convert_root.tag(), root.tag());
2210 for (convert_attr, attr) in convert_root.attrs().zip(root.attrs()) {
2211 assert_eq!(convert_attr, attr);
2212 }
2213 }
2214 }
2215
2216 #[test]
2217 fn test_attribute_value() {
2218 let string_data = "string data";
2219 let line_string_data = "line string data";
2220
2221 let data = vec![1, 2, 3, 4];
2222 let read_data = read::EndianSlice::new(&[1, 2, 3, 4], LittleEndian);
2223
2224 let mut expression = Expression::new();
2225 expression.op_constu(57);
2226 let read_expression = read::Expression(read::EndianSlice::new(
2227 &[constants::DW_OP_constu.0, 57],
2228 LittleEndian,
2229 ));
2230
2231 let range = RangeList(vec![Range::StartEnd {
2232 begin: Address::Constant(0x1234),
2233 end: Address::Constant(0x2345),
2234 }]);
2235
2236 let location = LocationList(vec![Location::StartEnd {
2237 begin: Address::Constant(0x1234),
2238 end: Address::Constant(0x2345),
2239 data: expression.clone(),
2240 }]);
2241
2242 for &version in &[2, 3, 4, 5] {
2243 for &address_size in &[4, 8] {
2244 for &format in &[Format::Dwarf32, Format::Dwarf64] {
2245 let encoding = Encoding {
2246 format,
2247 version,
2248 address_size,
2249 };
2250
2251 let mut dwarf = Dwarf::new();
2252 let unit = dwarf.units.add(Unit::new(encoding, LineProgram::none()));
2253 let unit = dwarf.units.get_mut(unit);
2254 let loc_id = unit.locations.add(location.clone());
2255 let range_id = unit.ranges.add(range.clone());
2256 dwarf.strings.add("dummy string");
2258 let string_id = dwarf.strings.add(string_data);
2259 dwarf.line_strings.add("dummy line string");
2260 let line_string_id = dwarf.line_strings.add(line_string_data);
2261
2262 let attributes = &[
2263 (
2264 constants::DW_AT_name,
2265 AttributeValue::Address(Address::Constant(0x1234)),
2266 read::AttributeValue::Addr(0x1234),
2267 ),
2268 (
2269 constants::DW_AT_name,
2270 AttributeValue::Block(data.clone()),
2271 read::AttributeValue::Block(read_data),
2272 ),
2273 (
2274 constants::DW_AT_name,
2275 AttributeValue::Data1(0x12),
2276 read::AttributeValue::Data1(0x12),
2277 ),
2278 (
2279 constants::DW_AT_name,
2280 AttributeValue::Data2(0x1234),
2281 read::AttributeValue::Data2(0x1234),
2282 ),
2283 (
2284 constants::DW_AT_name,
2285 AttributeValue::Data4(0x1234),
2286 read::AttributeValue::Data4(0x1234),
2287 ),
2288 (
2289 constants::DW_AT_name,
2290 AttributeValue::Data8(0x1234),
2291 read::AttributeValue::Data8(0x1234),
2292 ),
2293 (
2294 constants::DW_AT_name,
2295 AttributeValue::Sdata(0x1234),
2296 read::AttributeValue::Sdata(0x1234),
2297 ),
2298 (
2299 constants::DW_AT_name,
2300 AttributeValue::Udata(0x1234),
2301 read::AttributeValue::Udata(0x1234),
2302 ),
2303 (
2304 constants::DW_AT_name,
2305 AttributeValue::Exprloc(expression.clone()),
2306 read::AttributeValue::Exprloc(read_expression),
2307 ),
2308 (
2309 constants::DW_AT_name,
2310 AttributeValue::Flag(false),
2311 read::AttributeValue::Flag(false),
2312 ),
2313 (
2321 constants::DW_AT_name,
2322 AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x1234)),
2323 read::AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x1234)),
2324 ),
2325 (
2326 constants::DW_AT_macro_info,
2327 AttributeValue::DebugMacinfoRef(DebugMacinfoOffset(0x1234)),
2328 read::AttributeValue::SecOffset(0x1234),
2329 ),
2330 (
2331 constants::DW_AT_macros,
2332 AttributeValue::DebugMacroRef(DebugMacroOffset(0x1234)),
2333 read::AttributeValue::SecOffset(0x1234),
2334 ),
2335 (
2336 constants::DW_AT_name,
2337 AttributeValue::DebugTypesRef(DebugTypeSignature(0x1234)),
2338 read::AttributeValue::DebugTypesRef(DebugTypeSignature(0x1234)),
2339 ),
2340 (
2341 constants::DW_AT_name,
2342 AttributeValue::DebugStrRefSup(DebugStrOffset(0x1234)),
2343 read::AttributeValue::DebugStrRefSup(DebugStrOffset(0x1234)),
2344 ),
2345 (
2346 constants::DW_AT_name,
2347 AttributeValue::String(data.clone()),
2348 read::AttributeValue::String(read_data),
2349 ),
2350 (
2351 constants::DW_AT_encoding,
2352 AttributeValue::Encoding(constants::DwAte(0x12)),
2353 read::AttributeValue::Udata(0x12),
2354 ),
2355 (
2356 constants::DW_AT_decimal_sign,
2357 AttributeValue::DecimalSign(constants::DwDs(0x12)),
2358 read::AttributeValue::Udata(0x12),
2359 ),
2360 (
2361 constants::DW_AT_endianity,
2362 AttributeValue::Endianity(constants::DwEnd(0x12)),
2363 read::AttributeValue::Udata(0x12),
2364 ),
2365 (
2366 constants::DW_AT_accessibility,
2367 AttributeValue::Accessibility(constants::DwAccess(0x12)),
2368 read::AttributeValue::Udata(0x12),
2369 ),
2370 (
2371 constants::DW_AT_visibility,
2372 AttributeValue::Visibility(constants::DwVis(0x12)),
2373 read::AttributeValue::Udata(0x12),
2374 ),
2375 (
2376 constants::DW_AT_virtuality,
2377 AttributeValue::Virtuality(constants::DwVirtuality(0x12)),
2378 read::AttributeValue::Udata(0x12),
2379 ),
2380 (
2381 constants::DW_AT_language,
2382 AttributeValue::Language(constants::DwLang(0x12)),
2383 read::AttributeValue::Udata(0x12),
2384 ),
2385 (
2386 constants::DW_AT_address_class,
2387 AttributeValue::AddressClass(constants::DwAddr(0x12)),
2388 read::AttributeValue::Udata(0x12),
2389 ),
2390 (
2391 constants::DW_AT_identifier_case,
2392 AttributeValue::IdentifierCase(constants::DwId(0x12)),
2393 read::AttributeValue::Udata(0x12),
2394 ),
2395 (
2396 constants::DW_AT_calling_convention,
2397 AttributeValue::CallingConvention(constants::DwCc(0x12)),
2398 read::AttributeValue::Udata(0x12),
2399 ),
2400 (
2401 constants::DW_AT_ordering,
2402 AttributeValue::Ordering(constants::DwOrd(0x12)),
2403 read::AttributeValue::Udata(0x12),
2404 ),
2405 (
2406 constants::DW_AT_inline,
2407 AttributeValue::Inline(constants::DwInl(0x12)),
2408 read::AttributeValue::Udata(0x12),
2409 ),
2410 ];
2411
2412 let mut add_attribute = |name, value| {
2413 let entry_id = unit.add(unit.root(), constants::DW_TAG_subprogram);
2414 let entry = unit.get_mut(entry_id);
2415 entry.set(name, value);
2416 };
2417 for (name, value, _) in attributes {
2418 add_attribute(*name, value.clone());
2419 }
2420 add_attribute(
2421 constants::DW_AT_location,
2422 AttributeValue::LocationListRef(loc_id),
2423 );
2424 add_attribute(
2425 constants::DW_AT_ranges,
2426 AttributeValue::RangeListRef(range_id),
2427 );
2428 add_attribute(constants::DW_AT_name, AttributeValue::StringRef(string_id));
2429 add_attribute(
2430 constants::DW_AT_name,
2431 AttributeValue::LineStringRef(line_string_id),
2432 );
2433
2434 let mut sections = Sections::new(EndianVec::new(LittleEndian));
2435 dwarf.write(&mut sections).unwrap();
2436
2437 let read_dwarf = sections.read(LittleEndian);
2438 let mut read_units = read_dwarf.units();
2439 let read_unit = read_units.next().unwrap().unwrap();
2440 let read_unit = read_dwarf.unit(read_unit).unwrap();
2441 let read_unit = read_unit.unit_ref(&read_dwarf);
2442 let mut read_entries = read_unit.entries();
2443 let (_, _root) = read_entries.next_dfs().unwrap().unwrap();
2444
2445 let mut get_attribute = |name| {
2446 let (_, entry) = read_entries.next_dfs().unwrap().unwrap();
2447 entry.attr(name).unwrap().unwrap()
2448 };
2449 for (name, _, expect_value) in attributes {
2450 let read_value = &get_attribute(*name).raw_value();
2451 let read_value = unsafe {
2454 mem::transmute::<
2455 &read::AttributeValue<read::EndianSlice<'_, LittleEndian>>,
2456 &read::AttributeValue<read::EndianSlice<'_, LittleEndian>>,
2457 >(read_value)
2458 };
2459 assert_eq!(read_value, expect_value);
2460 }
2461
2462 let read_attr = get_attribute(constants::DW_AT_location).value();
2463 let read::AttributeValue::LocationListsRef(read_loc_offset) = read_attr else {
2464 panic!("unexpected {:?}", read_attr);
2465 };
2466 let mut read_locations = read_unit.locations(read_loc_offset).unwrap();
2467 let read_location = read_locations.next().unwrap().unwrap();
2468 assert_eq!(read_location.range.begin, 0x1234);
2469 assert_eq!(read_location.range.end, 0x2345);
2470 assert_eq!(read_location.data, read_expression);
2471
2472 let read_attr = get_attribute(constants::DW_AT_ranges).value();
2473 let read::AttributeValue::RangeListsRef(read_range_offset) = read_attr else {
2474 panic!("unexpected {:?}", read_attr);
2475 };
2476 let read_range_offset = read_unit.ranges_offset_from_raw(read_range_offset);
2477 let mut read_ranges = read_unit.ranges(read_range_offset).unwrap();
2478 let read_range = read_ranges.next().unwrap().unwrap();
2479 assert_eq!(read_range.begin, 0x1234);
2480 assert_eq!(read_range.end, 0x2345);
2481
2482 let read_string = get_attribute(constants::DW_AT_name).raw_value();
2483 let read::AttributeValue::DebugStrRef(read_string_offset) = read_string else {
2484 panic!("unexpected {:?}", read_string);
2485 };
2486 assert_eq!(
2487 read_dwarf.string(read_string_offset).unwrap().slice(),
2488 string_data.as_bytes()
2489 );
2490
2491 let read_line_string = get_attribute(constants::DW_AT_name).raw_value();
2492 let read::AttributeValue::DebugLineStrRef(read_line_string_offset) =
2493 read_line_string
2494 else {
2495 panic!("unexpected {:?}", read_line_string);
2496 };
2497 assert_eq!(
2498 read_dwarf
2499 .line_string(read_line_string_offset)
2500 .unwrap()
2501 .slice(),
2502 line_string_data.as_bytes()
2503 );
2504
2505 let convert_dwarf =
2506 Dwarf::from(&read_dwarf, &|address| Some(Address::Constant(address)))
2507 .unwrap();
2508 let convert_unit = convert_dwarf.units.get(convert_dwarf.units.id(0));
2509 let convert_root = convert_unit.get(convert_unit.root());
2510 let mut convert_entries = convert_root.children();
2511
2512 let mut get_convert_attr = |name| {
2513 let convert_entry = convert_unit.get(*convert_entries.next().unwrap());
2514 convert_entry.get(name).unwrap()
2515 };
2516 for (name, attr, _) in attributes {
2517 let convert_attr = get_convert_attr(*name);
2518 assert_eq!(convert_attr, attr);
2519 }
2520
2521 let convert_attr = get_convert_attr(constants::DW_AT_location);
2522 let AttributeValue::LocationListRef(convert_loc_id) = convert_attr else {
2523 panic!("unexpected {:?}", convert_attr);
2524 };
2525 let convert_location = convert_unit.locations.get(*convert_loc_id);
2526 assert_eq!(*convert_location, location);
2527
2528 let convert_attr = get_convert_attr(constants::DW_AT_ranges);
2529 let AttributeValue::RangeListRef(convert_range_id) = convert_attr else {
2530 panic!("unexpected {:?}", convert_attr);
2531 };
2532 let convert_range = convert_unit.ranges.get(*convert_range_id);
2533 assert_eq!(*convert_range, range);
2534
2535 let convert_attr = get_convert_attr(constants::DW_AT_name);
2536 let AttributeValue::StringRef(convert_string_id) = convert_attr else {
2537 panic!("unexpected {:?}", convert_attr);
2538 };
2539 let convert_string = convert_dwarf.strings.get(*convert_string_id);
2540 assert_eq!(convert_string, string_data.as_bytes());
2541
2542 let convert_attr = get_convert_attr(constants::DW_AT_name);
2543 let AttributeValue::LineStringRef(convert_line_string_id) = convert_attr else {
2544 panic!("unexpected {:?}", convert_attr);
2545 };
2546 let convert_line_string =
2547 convert_dwarf.line_strings.get(*convert_line_string_id);
2548 assert_eq!(convert_line_string, line_string_data.as_bytes());
2549 }
2550 }
2551 }
2552 }
2553
2554 #[test]
2555 fn test_unit_ref() {
2556 let mut dwarf = Dwarf::new();
2557 let unit_id1 = dwarf.units.add(Unit::new(
2558 Encoding {
2559 version: 4,
2560 address_size: 8,
2561 format: Format::Dwarf32,
2562 },
2563 LineProgram::none(),
2564 ));
2565 assert_eq!(unit_id1, dwarf.units.id(0));
2566 let unit_id2 = dwarf.units.add(Unit::new(
2567 Encoding {
2568 version: 2,
2569 address_size: 4,
2570 format: Format::Dwarf64,
2571 },
2572 LineProgram::none(),
2573 ));
2574 assert_eq!(unit_id2, dwarf.units.id(1));
2575 let unit1_child1 = UnitEntryId::new(dwarf.units.get(unit_id1).base_id, 1);
2576 let unit1_child2 = UnitEntryId::new(dwarf.units.get(unit_id1).base_id, 2);
2577 let unit2_child1 = UnitEntryId::new(dwarf.units.get(unit_id2).base_id, 1);
2578 let unit2_child2 = UnitEntryId::new(dwarf.units.get(unit_id2).base_id, 2);
2579 {
2580 let unit1 = dwarf.units.get_mut(unit_id1);
2581 let root = unit1.root();
2582 let child_id1 = unit1.add(root, constants::DW_TAG_subprogram);
2583 assert_eq!(child_id1, unit1_child1);
2584 let child_id2 = unit1.add(root, constants::DW_TAG_subprogram);
2585 assert_eq!(child_id2, unit1_child2);
2586 {
2587 let child1 = unit1.get_mut(child_id1);
2588 child1.set(constants::DW_AT_type, AttributeValue::UnitRef(child_id2));
2589 }
2590 {
2591 let child2 = unit1.get_mut(child_id2);
2592 child2.set(
2593 constants::DW_AT_type,
2594 AttributeValue::DebugInfoRef(Reference::Entry(unit_id2, unit2_child1)),
2595 );
2596 }
2597 }
2598 {
2599 let unit2 = dwarf.units.get_mut(unit_id2);
2600 let root = unit2.root();
2601 let child_id1 = unit2.add(root, constants::DW_TAG_subprogram);
2602 assert_eq!(child_id1, unit2_child1);
2603 let child_id2 = unit2.add(root, constants::DW_TAG_subprogram);
2604 assert_eq!(child_id2, unit2_child2);
2605 {
2606 let child1 = unit2.get_mut(child_id1);
2607 child1.set(constants::DW_AT_type, AttributeValue::UnitRef(child_id2));
2608 }
2609 {
2610 let child2 = unit2.get_mut(child_id2);
2611 child2.set(
2612 constants::DW_AT_type,
2613 AttributeValue::DebugInfoRef(Reference::Entry(unit_id1, unit1_child1)),
2614 );
2615 }
2616 }
2617
2618 let mut sections = Sections::new(EndianVec::new(LittleEndian));
2619 dwarf.write(&mut sections).unwrap();
2620
2621 println!("{:?}", sections.debug_info);
2622 println!("{:?}", sections.debug_abbrev);
2623
2624 let read_dwarf = sections.read(LittleEndian);
2625 let mut read_units = read_dwarf.units();
2626
2627 let read_unit = read_units.next().unwrap().unwrap();
2628 let abbrevs = read_dwarf.abbreviations(&read_unit).unwrap();
2629 let mut read_entries = read_unit.entries(&abbrevs);
2630 let (_, _root) = read_entries.next_dfs().unwrap().unwrap();
2631 let (_, entry) = read_entries.next_dfs().unwrap().unwrap();
2632 let read_unit1_child1_attr = entry.attr_value(constants::DW_AT_type).unwrap();
2633 let read_unit1_child1_section_offset =
2634 entry.offset().to_debug_info_offset(&read_unit).unwrap();
2635 let (_, entry) = read_entries.next_dfs().unwrap().unwrap();
2636 let read_unit1_child2_attr = entry.attr_value(constants::DW_AT_type).unwrap();
2637 let read_unit1_child2_offset = entry.offset();
2638
2639 let read_unit = read_units.next().unwrap().unwrap();
2640 let abbrevs = read_dwarf.abbreviations(&read_unit).unwrap();
2641 let mut read_entries = read_unit.entries(&abbrevs);
2642 let (_, _root) = read_entries.next_dfs().unwrap().unwrap();
2643 let (_, entry) = read_entries.next_dfs().unwrap().unwrap();
2644 let read_unit2_child1_attr = entry.attr_value(constants::DW_AT_type).unwrap();
2645 let read_unit2_child1_section_offset =
2646 entry.offset().to_debug_info_offset(&read_unit).unwrap();
2647 let (_, entry) = read_entries.next_dfs().unwrap().unwrap();
2648 let read_unit2_child2_attr = entry.attr_value(constants::DW_AT_type).unwrap();
2649 let read_unit2_child2_offset = entry.offset();
2650
2651 assert_eq!(
2652 read_unit1_child1_attr,
2653 Some(read::AttributeValue::UnitRef(read_unit1_child2_offset))
2654 );
2655 assert_eq!(
2656 read_unit1_child2_attr,
2657 Some(read::AttributeValue::DebugInfoRef(
2658 read_unit2_child1_section_offset
2659 ))
2660 );
2661 assert_eq!(
2662 read_unit2_child1_attr,
2663 Some(read::AttributeValue::UnitRef(read_unit2_child2_offset))
2664 );
2665 assert_eq!(
2666 read_unit2_child2_attr,
2667 Some(read::AttributeValue::DebugInfoRef(
2668 read_unit1_child1_section_offset
2669 ))
2670 );
2671
2672 let convert_dwarf =
2673 Dwarf::from(&read_dwarf, &|address| Some(Address::Constant(address))).unwrap();
2674 let convert_units = &convert_dwarf.units;
2675 assert_eq!(convert_units.count(), dwarf.units.count());
2676
2677 for i in 0..convert_units.count() {
2678 let unit = dwarf.units.get(dwarf.units.id(i));
2679 let convert_unit = convert_units.get(convert_units.id(i));
2680 assert_eq!(convert_unit.version(), unit.version());
2681 assert_eq!(convert_unit.address_size(), unit.address_size());
2682 assert_eq!(convert_unit.format(), unit.format());
2683 assert_eq!(convert_unit.count(), unit.count());
2684
2685 let root = unit.get(unit.root());
2686 let convert_root = convert_unit.get(convert_unit.root());
2687 assert_eq!(convert_root.tag(), root.tag());
2688 for (convert_attr, attr) in convert_root.attrs().zip(root.attrs()) {
2689 assert_eq!(convert_attr, attr);
2690 }
2691
2692 let child1 = unit.get(UnitEntryId::new(unit.base_id, 1));
2693 let convert_child1 = convert_unit.get(UnitEntryId::new(convert_unit.base_id, 1));
2694 assert_eq!(convert_child1.tag(), child1.tag());
2695 for (convert_attr, attr) in convert_child1.attrs().zip(child1.attrs()) {
2696 assert_eq!(convert_attr.name, attr.name);
2697 match (convert_attr.value.clone(), attr.value.clone()) {
2698 (
2699 AttributeValue::DebugInfoRef(Reference::Entry(convert_unit, convert_entry)),
2700 AttributeValue::DebugInfoRef(Reference::Entry(unit, entry)),
2701 ) => {
2702 assert_eq!(convert_unit.index, unit.index);
2703 assert_eq!(convert_entry.index, entry.index);
2704 }
2705 (AttributeValue::UnitRef(convert_id), AttributeValue::UnitRef(id)) => {
2706 assert_eq!(convert_id.index, id.index);
2707 }
2708 (convert_value, value) => assert_eq!(convert_value, value),
2709 }
2710 }
2711
2712 let child2 = unit.get(UnitEntryId::new(unit.base_id, 2));
2713 let convert_child2 = convert_unit.get(UnitEntryId::new(convert_unit.base_id, 2));
2714 assert_eq!(convert_child2.tag(), child2.tag());
2715 for (convert_attr, attr) in convert_child2.attrs().zip(child2.attrs()) {
2716 assert_eq!(convert_attr.name, attr.name);
2717 match (convert_attr.value.clone(), attr.value.clone()) {
2718 (
2719 AttributeValue::DebugInfoRef(Reference::Entry(convert_unit, convert_entry)),
2720 AttributeValue::DebugInfoRef(Reference::Entry(unit, entry)),
2721 ) => {
2722 assert_eq!(convert_unit.index, unit.index);
2723 assert_eq!(convert_entry.index, entry.index);
2724 }
2725 (AttributeValue::UnitRef(convert_id), AttributeValue::UnitRef(id)) => {
2726 assert_eq!(convert_id.index, id.index);
2727 }
2728 (convert_value, value) => assert_eq!(convert_value, value),
2729 }
2730 }
2731 }
2732 }
2733
2734 #[test]
2735 fn test_sibling() {
2736 fn add_child(
2737 unit: &mut Unit,
2738 parent: UnitEntryId,
2739 tag: constants::DwTag,
2740 name: &str,
2741 ) -> UnitEntryId {
2742 let id = unit.add(parent, tag);
2743 let child = unit.get_mut(id);
2744 child.set(constants::DW_AT_name, AttributeValue::String(name.into()));
2745 child.set_sibling(true);
2746 id
2747 }
2748
2749 fn add_children(unit: &mut Unit) {
2750 let root = unit.root();
2751 let child1 = add_child(unit, root, constants::DW_TAG_subprogram, "child1");
2752 add_child(unit, child1, constants::DW_TAG_variable, "grandchild1");
2753 add_child(unit, root, constants::DW_TAG_subprogram, "child2");
2754 add_child(unit, root, constants::DW_TAG_subprogram, "child3");
2755 }
2756
2757 fn next_child<R: read::Reader<Offset = usize>>(
2758 entries: &mut read::EntriesCursor<'_, '_, R>,
2759 ) -> (read::UnitOffset, Option<read::UnitOffset>) {
2760 let (_, entry) = entries.next_dfs().unwrap().unwrap();
2761 let offset = entry.offset();
2762 let sibling =
2763 entry
2764 .attr_value(constants::DW_AT_sibling)
2765 .unwrap()
2766 .map(|attr| match attr {
2767 read::AttributeValue::UnitRef(offset) => offset,
2768 _ => panic!("bad sibling value"),
2769 });
2770 (offset, sibling)
2771 }
2772
2773 fn check_sibling<R: read::Reader<Offset = usize>>(
2774 unit: read::UnitHeader<R>,
2775 dwarf: &read::Dwarf<R>,
2776 ) {
2777 let unit = dwarf.unit(unit).unwrap();
2778 let mut entries = unit.entries();
2779 entries.next_dfs().unwrap().unwrap();
2781 let (_, sibling1) = next_child(&mut entries);
2783 entries.next_dfs().unwrap().unwrap();
2785 let (offset2, sibling2) = next_child(&mut entries);
2787 let (_, _) = next_child(&mut entries);
2789 assert_eq!(sibling1, Some(offset2));
2790 assert_eq!(sibling2, None);
2791 }
2792
2793 let encoding = Encoding {
2794 format: Format::Dwarf32,
2795 version: 4,
2796 address_size: 8,
2797 };
2798 let mut dwarf = Dwarf::new();
2799 let unit_id1 = dwarf.units.add(Unit::new(encoding, LineProgram::none()));
2800 add_children(dwarf.units.get_mut(unit_id1));
2801 let unit_id2 = dwarf.units.add(Unit::new(encoding, LineProgram::none()));
2802 add_children(dwarf.units.get_mut(unit_id2));
2803
2804 let mut sections = Sections::new(EndianVec::new(LittleEndian));
2805 dwarf.write(&mut sections).unwrap();
2806
2807 println!("{:?}", sections.debug_info);
2808 println!("{:?}", sections.debug_abbrev);
2809
2810 let read_dwarf = sections.read(LittleEndian);
2811 let mut read_units = read_dwarf.units();
2812 check_sibling(read_units.next().unwrap().unwrap(), &read_dwarf);
2813 check_sibling(read_units.next().unwrap().unwrap(), &read_dwarf);
2814 }
2815
2816 #[test]
2817 fn test_line_ref() {
2818 let dir_bytes = b"dir";
2819 let file_bytes1 = b"file1";
2820 let file_bytes2 = b"file2";
2821 let file_string1 = LineString::String(file_bytes1.to_vec());
2822 let file_string2 = LineString::String(file_bytes2.to_vec());
2823
2824 for &version in &[2, 3, 4, 5] {
2825 for &address_size in &[4, 8] {
2826 for &format in &[Format::Dwarf32, Format::Dwarf64] {
2827 let encoding = Encoding {
2828 format,
2829 version,
2830 address_size,
2831 };
2832
2833 let mut line_program = LineProgram::new(
2835 encoding,
2836 LineEncoding::default(),
2837 LineString::String(dir_bytes.to_vec()),
2838 file_string1.clone(),
2839 None,
2840 );
2841 let dir = line_program.default_directory();
2842 let file1 = line_program.add_file(file_string1.clone(), dir, None);
2844 let file2 = line_program.add_file(file_string2.clone(), dir, None);
2845
2846 let mut unit = Unit::new(encoding, line_program);
2847 let root = unit.get_mut(unit.root());
2848 root.set(
2849 constants::DW_AT_name,
2850 AttributeValue::String(file_bytes1.to_vec()),
2851 );
2852 root.set(
2853 constants::DW_AT_comp_dir,
2854 AttributeValue::String(dir_bytes.to_vec()),
2855 );
2856 root.set(constants::DW_AT_stmt_list, AttributeValue::LineProgramRef);
2857
2858 let child = unit.add(unit.root(), constants::DW_TAG_subprogram);
2859 unit.get_mut(child).set(
2860 constants::DW_AT_decl_file,
2861 AttributeValue::FileIndex(Some(file1)),
2862 );
2863
2864 let child = unit.add(unit.root(), constants::DW_TAG_subprogram);
2865 unit.get_mut(child).set(
2866 constants::DW_AT_call_file,
2867 AttributeValue::FileIndex(Some(file2)),
2868 );
2869
2870 let mut dwarf = Dwarf::new();
2871 dwarf.units.add(unit);
2872
2873 let mut sections = Sections::new(EndianVec::new(LittleEndian));
2874 dwarf.write(&mut sections).unwrap();
2875
2876 let read_dwarf = sections.read(LittleEndian);
2877 let mut read_units = read_dwarf.units();
2878 let read_unit = read_units.next().unwrap().unwrap();
2879 let read_unit = read_dwarf.unit(read_unit).unwrap();
2880 let read_unit = read_unit.unit_ref(&read_dwarf);
2881 let read_line_program = read_unit.line_program.as_ref().unwrap().header();
2882 let mut read_entries = read_unit.entries();
2883 let (_, _root) = read_entries.next_dfs().unwrap().unwrap();
2884
2885 let mut get_path = |name| {
2886 let (_, entry) = read_entries.next_dfs().unwrap().unwrap();
2887 let read_attr = entry.attr(name).unwrap().unwrap();
2888 let read::AttributeValue::FileIndex(read_file_index) = read_attr.value()
2889 else {
2890 panic!("unexpected {:?}", read_attr);
2891 };
2892 let read_file = read_line_program.file(read_file_index).unwrap();
2893 let read_path = read_unit
2894 .attr_string(read_file.path_name())
2895 .unwrap()
2896 .slice();
2897 (read_file_index, read_path)
2898 };
2899
2900 let (read_index, read_path) = get_path(constants::DW_AT_decl_file);
2901 assert_eq!(read_index, if version >= 5 { 0 } else { 1 });
2902 assert_eq!(read_path, file_bytes1);
2903
2904 let (read_index, read_path) = get_path(constants::DW_AT_call_file);
2905 assert_eq!(read_index, if version >= 5 { 1 } else { 2 });
2906 assert_eq!(read_path, file_bytes2);
2907
2908 let convert_dwarf =
2909 Dwarf::from(&read_dwarf, &|address| Some(Address::Constant(address)))
2910 .unwrap();
2911 let convert_unit = convert_dwarf.units.get(convert_dwarf.units.id(0));
2912 let convert_root = convert_unit.get(convert_unit.root());
2913 let mut convert_entries = convert_root.children();
2914
2915 let mut get_convert_path = |name| {
2916 let convert_entry = convert_unit.get(*convert_entries.next().unwrap());
2917 let convert_attr = convert_entry.get(name).unwrap();
2918 let AttributeValue::FileIndex(Some(convert_file_index)) = convert_attr
2919 else {
2920 panic!("unexpected {:?}", convert_attr);
2921 };
2922 convert_unit.line_program.get_file(*convert_file_index).0
2923 };
2924
2925 let convert_path = get_convert_path(constants::DW_AT_decl_file);
2926 assert_eq!(convert_path, &file_string1);
2927
2928 let convert_path = get_convert_path(constants::DW_AT_call_file);
2929 assert_eq!(convert_path, &file_string2);
2930 }
2931 }
2932 }
2933 }
2934
2935 #[test]
2936 fn test_line_program_used() {
2937 for used in [false, true] {
2938 let encoding = Encoding {
2939 format: Format::Dwarf32,
2940 version: 5,
2941 address_size: 8,
2942 };
2943
2944 let line_program = LineProgram::new(
2945 encoding,
2946 LineEncoding::default(),
2947 LineString::String(b"comp_dir".to_vec()),
2948 LineString::String(b"comp_name".to_vec()),
2949 None,
2950 );
2951
2952 let mut unit = Unit::new(encoding, line_program);
2953 let file_id = if used { Some(FileId::new(0)) } else { None };
2954 let root = unit.root();
2955 unit.get_mut(root).set(
2956 constants::DW_AT_decl_file,
2957 AttributeValue::FileIndex(file_id),
2958 );
2959
2960 let mut dwarf = Dwarf::new();
2961 dwarf.units.add(unit);
2962
2963 let mut sections = Sections::new(EndianVec::new(LittleEndian));
2964 dwarf.write(&mut sections).unwrap();
2965 assert_eq!(!used, sections.debug_line.slice().is_empty());
2966 }
2967 }
2968
2969 #[test]
2970 fn test_delete_child() {
2971 fn set_name(unit: &mut Unit, id: UnitEntryId, name: &str) {
2972 let entry = unit.get_mut(id);
2973 entry.set(constants::DW_AT_name, AttributeValue::String(name.into()));
2974 }
2975 fn check_name<R: read::Reader>(
2976 entry: &read::DebuggingInformationEntry<'_, '_, R>,
2977 unit: read::UnitRef<'_, R>,
2978 name: &str,
2979 ) {
2980 let name_attr = entry.attr(constants::DW_AT_name).unwrap().unwrap();
2981 let entry_name = unit.attr_string(name_attr.value()).unwrap();
2982 let entry_name_str = entry_name.to_string().unwrap();
2983 assert_eq!(entry_name_str, name);
2984 }
2985 let encoding = Encoding {
2986 format: Format::Dwarf32,
2987 version: 4,
2988 address_size: 8,
2989 };
2990 let mut dwarf = DwarfUnit::new(encoding);
2991 let root = dwarf.unit.root();
2992
2993 let child1 = dwarf.unit.add(root, constants::DW_TAG_subprogram);
2995 set_name(&mut dwarf.unit, child1, "child1");
2996 let grandchild1 = dwarf.unit.add(child1, constants::DW_TAG_variable);
2997 set_name(&mut dwarf.unit, grandchild1, "grandchild1");
2998 let child2 = dwarf.unit.add(root, constants::DW_TAG_subprogram);
2999 set_name(&mut dwarf.unit, child2, "child2");
3000 dwarf.unit.get_mut(root).delete_child(child1);
3002 let child3 = dwarf.unit.add(root, constants::DW_TAG_subprogram);
3003 set_name(&mut dwarf.unit, child3, "child3");
3004 let child4 = dwarf.unit.add(root, constants::DW_TAG_subprogram);
3005 set_name(&mut dwarf.unit, child4, "child4");
3006 let grandchild4 = dwarf.unit.add(child4, constants::DW_TAG_variable);
3007 set_name(&mut dwarf.unit, grandchild4, "grandchild4");
3008 dwarf.unit.get_mut(child4).delete_child(grandchild4);
3009
3010 let mut sections = Sections::new(EndianVec::new(LittleEndian));
3011
3012 dwarf.write(&mut sections).unwrap();
3014
3015 let read_dwarf = sections.read(LittleEndian);
3016 let read_unit = read_dwarf.units().next().unwrap().unwrap();
3017 let read_unit = read_dwarf.unit(read_unit).unwrap();
3018 let read_unit = read_unit.unit_ref(&read_dwarf);
3019 let mut entries = read_unit.entries();
3020 entries.next_dfs().unwrap().unwrap();
3022 let (_, read_child2) = entries.next_dfs().unwrap().unwrap();
3024 check_name(read_child2, read_unit, "child2");
3025 let (_, read_child3) = entries.next_dfs().unwrap().unwrap();
3027 check_name(read_child3, read_unit, "child3");
3028 let (_, read_child4) = entries.next_dfs().unwrap().unwrap();
3030 check_name(read_child4, read_unit, "child4");
3031 assert!(entries.next_dfs().unwrap().is_none());
3033 }
3034}