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