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/// A table of units that will be stored in the `.debug_info` section.
23#[derive(Debug, Default)]
24pub struct UnitTable {
25 base_id: BaseId,
26 units: Vec<Unit>,
27}
28
29impl UnitTable {
30 /// Create a new unit and add it to the table.
31 ///
32 /// `address_size` must be in bytes.
33 ///
34 /// Returns the `UnitId` of the new unit.
35 #[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 /// Return the number of units.
43 #[inline]
44 pub fn count(&self) -> usize {
45 self.units.len()
46 }
47
48 /// Return the id of a unit.
49 ///
50 /// # Panics
51 ///
52 /// Panics if `index >= self.count()`.
53 #[inline]
54 pub fn id(&self, index: usize) -> UnitId {
55 assert!(index < self.count());
56 UnitId::new(self.base_id, index)
57 }
58
59 /// Get a reference to a unit.
60 ///
61 /// # Panics
62 ///
63 /// Panics if `id` is invalid.
64 #[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 /// Get a mutable reference to a unit.
71 ///
72 /// # Panics
73 ///
74 /// Panics if `id` is invalid.
75 #[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 /// Get an iterator for the units.
82 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 /// Get a mutable iterator for the units.
90 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 /// Write the units to the given sections.
99 ///
100 /// `strings` must contain the `.debug_str` offsets of the corresponding
101 /// `StringTable`.
102 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 // TODO: maybe share abbreviation tables
114 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: DebugInfoReference in references.drain(..) {
154 let entry_offset: usize = offsets.entry(r.unit, r.entry).0;
155 debug_assert_ne!(entry_offset, 0);
156 w.write_offset_at(r.offset, val:entry_offset, _section:SectionId::DebugInfo, r.size)?;
157 }
158 Ok(())
159}
160
161/// A unit's debugging information.
162#[derive(Debug)]
163pub struct Unit {
164 base_id: BaseId,
165 /// The encoding parameters for this unit.
166 encoding: Encoding,
167 /// The line number program for this unit.
168 pub line_program: LineProgram,
169 /// A table of range lists used by this unit.
170 pub ranges: RangeListTable,
171 /// A table of location lists used by this unit.
172 pub locations: LocationListTable,
173 /// All entries in this unit. The order is unrelated to the tree order.
174 // Requirements:
175 // - entries form a tree
176 // - entries can be added in any order
177 // - entries have a fixed id
178 // - able to quickly lookup an entry from its id
179 // Limitations of current implementation:
180 // - mutable iteration of children is messy due to borrow checker
181 entries: Vec<DebuggingInformationEntry>,
182 /// The index of the root entry in entries.
183 root: UnitEntryId,
184}
185
186impl Unit {
187 /// Create a new `Unit`.
188 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 /// Return the encoding parameters for this unit.
211 #[inline]
212 pub fn encoding(&self) -> Encoding {
213 self.encoding
214 }
215
216 /// Return the DWARF version for this unit.
217 #[inline]
218 pub fn version(&self) -> u16 {
219 self.encoding.version
220 }
221
222 /// Return the address size in bytes for this unit.
223 #[inline]
224 pub fn address_size(&self) -> u8 {
225 self.encoding.address_size
226 }
227
228 /// Return the DWARF format for this unit.
229 #[inline]
230 pub fn format(&self) -> Format {
231 self.encoding.format
232 }
233
234 /// Return the number of `DebuggingInformationEntry`s created for this unit.
235 ///
236 /// This includes entries that no longer have a parent.
237 #[inline]
238 pub fn count(&self) -> usize {
239 self.entries.len()
240 }
241
242 /// Return the id of the root entry.
243 #[inline]
244 pub fn root(&self) -> UnitEntryId {
245 self.root
246 }
247
248 /// Add a new `DebuggingInformationEntry` to this unit and return its id.
249 ///
250 /// The `parent` must be within the same unit.
251 ///
252 /// # Panics
253 ///
254 /// Panics if `parent` is invalid.
255 #[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 /// Get a reference to an entry.
262 ///
263 /// # Panics
264 ///
265 /// Panics if `id` is invalid.
266 #[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 /// Get a mutable reference to an entry.
273 ///
274 /// # Panics
275 ///
276 /// Panics if `id` is invalid.
277 #[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 /// Return true if `self.line_program` is used by a DIE.
284 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 /// Write the unit to the given sections.
304 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 // TODO: use .debug_types for type units in DWARF v4.
327 let w = &mut sections.debug_info;
328
329 let mut offsets = UnitOffsets {
330 base_id: self.base_id,
331 unit: w.offset(),
332 // Entries can be written in any order, so create the complete vec now.
333 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 // Calculate all DIE offsets, so that we are able to output references to them.
360 // However, references to base types in expressions use ULEB128, so base types
361 // must be moved to the front before we can calculate offsets.
362 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 // Location lists can't be written until we have DIE offsets.
373 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 // This does not need relocation.
397 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 /// Reorder base types to come first so that typed stack operations
408 /// can get their offset.
409 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/// A Debugging Information Entry (DIE).
427///
428/// DIEs have a set of attributes and optionally have children DIEs as well.
429///
430/// DIEs form a tree without any cycles. This is enforced by specifying the
431/// parent when creating a DIE, and disallowing changes of parent.
432#[derive(Debug)]
433pub struct DebuggingInformationEntry {
434 id: UnitEntryId,
435 parent: Option<UnitEntryId>,
436 tag: constants::DwTag,
437 /// Whether to emit `DW_AT_sibling`.
438 sibling: bool,
439 attrs: Vec<Attribute>,
440 children: Vec<UnitEntryId>,
441}
442
443impl DebuggingInformationEntry {
444 /// Create a new `DebuggingInformationEntry`.
445 ///
446 /// # Panics
447 ///
448 /// Panics if `parent` is invalid.
449 #[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 /// Return the id of this entry.
474 #[inline]
475 pub fn id(&self) -> UnitEntryId {
476 self.id
477 }
478
479 /// Return the parent of this entry.
480 #[inline]
481 pub fn parent(&self) -> Option<UnitEntryId> {
482 self.parent
483 }
484
485 /// Return the tag of this entry.
486 #[inline]
487 pub fn tag(&self) -> constants::DwTag {
488 self.tag
489 }
490
491 /// Return `true` if a `DW_AT_sibling` attribute will be emitted.
492 #[inline]
493 pub fn sibling(&self) -> bool {
494 self.sibling
495 }
496
497 /// Set whether a `DW_AT_sibling` attribute will be emitted.
498 ///
499 /// The attribute will only be emitted if the DIE has children.
500 #[inline]
501 pub fn set_sibling(&mut self, sibling: bool) {
502 self.sibling = sibling;
503 }
504
505 /// Iterate over the attributes of this entry.
506 #[inline]
507 pub fn attrs(&self) -> slice::Iter<'_, Attribute> {
508 self.attrs.iter()
509 }
510
511 /// Iterate over the attributes of this entry for modification.
512 #[inline]
513 pub fn attrs_mut(&mut self) -> slice::IterMut<'_, Attribute> {
514 self.attrs.iter_mut()
515 }
516
517 /// Get an attribute.
518 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 /// Get an attribute for modification.
526 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 /// Set an attribute.
534 ///
535 /// Replaces any existing attribute with the same name.
536 ///
537 /// # Panics
538 ///
539 /// Panics if `name` is `DW_AT_sibling`. Use `set_sibling` instead.
540 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 /// Delete an attribute.
550 ///
551 /// Replaces any existing attribute with the same name.
552 pub fn delete(&mut self, name: constants::DwAt) {
553 self.attrs.retain(|x| x.name != name);
554 }
555
556 /// Iterate over the children of this entry.
557 ///
558 /// Note: use `Unit::add` to add a new child to this entry.
559 #[inline]
560 pub fn children(&self) -> slice::Iter<'_, UnitEntryId> {
561 self.children.iter()
562 }
563
564 /// Delete a child entry and all of its children.
565 pub fn delete_child(&mut self, id: UnitEntryId) {
566 self.children.retain(|&child| child != id);
567 }
568
569 /// Return the type abbreviation for this DIE.
570 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 // Null child
607 *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 /// Write the entry to the given sections.
624 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 // Null child
679 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 // This does not need relocation.
685 w.write_udata_at(offset.0, next_offset, unit.format().word_size())?;
686 }
687 Ok(())
688 }
689}
690
691/// An attribute in a `DebuggingInformationEntry`, consisting of a name and
692/// associated value.
693#[derive(Debug, Clone, PartialEq, Eq)]
694pub struct Attribute {
695 name: constants::DwAt,
696 value: AttributeValue,
697}
698
699impl Attribute {
700 /// Get the name of this attribute.
701 #[inline]
702 pub fn name(&self) -> constants::DwAt {
703 self.name
704 }
705
706 /// Get the value of this attribute.
707 #[inline]
708 pub fn get(&self) -> &AttributeValue {
709 &self.value
710 }
711
712 /// Set the value of this attribute.
713 #[inline]
714 pub fn set(&mut self, value: AttributeValue) {
715 self.value = value;
716 }
717
718 /// Return the type specification for this attribute.
719 fn specification(&self, encoding: Encoding) -> Result<AttributeSpecification> {
720 Ok(AttributeSpecification::new(
721 self.name,
722 self.value.form(encoding)?,
723 ))
724 }
725}
726
727/// The value of an attribute in a `DebuggingInformationEntry`.
728#[derive(Debug, Clone, PartialEq, Eq)]
729pub enum AttributeValue {
730 /// "Refers to some location in the address space of the described program."
731 Address(Address),
732
733 /// A slice of an arbitrary number of bytes.
734 Block(Vec<u8>),
735
736 /// A one byte constant data value. How to interpret the byte depends on context.
737 ///
738 /// From section 7 of the standard: "Depending on context, it may be a
739 /// signed integer, an unsigned integer, a floating-point constant, or
740 /// anything else."
741 Data1(u8),
742
743 /// A two byte constant data value. How to interpret the bytes depends on context.
744 ///
745 /// This value will be converted to the target endian before writing.
746 ///
747 /// From section 7 of the standard: "Depending on context, it may be a
748 /// signed integer, an unsigned integer, a floating-point constant, or
749 /// anything else."
750 Data2(u16),
751
752 /// A four byte constant data value. How to interpret the bytes depends on context.
753 ///
754 /// This value will be converted to the target endian before writing.
755 ///
756 /// From section 7 of the standard: "Depending on context, it may be a
757 /// signed integer, an unsigned integer, a floating-point constant, or
758 /// anything else."
759 Data4(u32),
760
761 /// An eight byte constant data value. How to interpret the bytes depends on context.
762 ///
763 /// This value will be converted to the target endian before writing.
764 ///
765 /// From section 7 of the standard: "Depending on context, it may be a
766 /// signed integer, an unsigned integer, a floating-point constant, or
767 /// anything else."
768 Data8(u64),
769
770 /// A signed integer constant.
771 Sdata(i64),
772
773 /// An unsigned integer constant.
774 Udata(u64),
775
776 /// "The information bytes contain a DWARF expression (see Section 2.5) or
777 /// location description (see Section 2.6)."
778 Exprloc(Expression),
779
780 /// A boolean that indicates presence or absence of the attribute.
781 Flag(bool),
782
783 /// An attribute that is always present.
784 FlagPresent,
785
786 /// A reference to a `DebuggingInformationEntry` in this unit.
787 UnitRef(UnitEntryId),
788
789 /// A reference to a `DebuggingInformationEntry` in a potentially different unit.
790 DebugInfoRef(Reference),
791
792 /// An offset into the `.debug_info` section of the supplementary object file.
793 ///
794 /// The API does not currently assist with generating this offset.
795 /// This variant will be removed from the API once support for writing
796 /// supplementary object files is implemented.
797 DebugInfoRefSup(DebugInfoOffset),
798
799 /// A reference to a line number program.
800 LineProgramRef,
801
802 /// A reference to a location list.
803 LocationListRef(LocationListId),
804
805 /// An offset into the `.debug_macinfo` section.
806 ///
807 /// The API does not currently assist with generating this offset.
808 /// This variant will be removed from the API once support for writing
809 /// `.debug_macinfo` sections is implemented.
810 DebugMacinfoRef(DebugMacinfoOffset),
811
812 /// An offset into the `.debug_macro` section.
813 ///
814 /// The API does not currently assist with generating this offset.
815 /// This variant will be removed from the API once support for writing
816 /// `.debug_macro` sections is implemented.
817 DebugMacroRef(DebugMacroOffset),
818
819 /// A reference to a range list.
820 RangeListRef(RangeListId),
821
822 /// A type signature.
823 ///
824 /// The API does not currently assist with generating this signature.
825 /// This variant will be removed from the API once support for writing
826 /// `.debug_types` sections is implemented.
827 DebugTypesRef(DebugTypeSignature),
828
829 /// A reference to a string in the `.debug_str` section.
830 StringRef(StringId),
831
832 /// An offset into the `.debug_str` section of the supplementary object file.
833 ///
834 /// The API does not currently assist with generating this offset.
835 /// This variant will be removed from the API once support for writing
836 /// supplementary object files is implemented.
837 DebugStrRefSup(DebugStrOffset),
838
839 /// A reference to a string in the `.debug_line_str` section.
840 LineStringRef(LineStringId),
841
842 /// A slice of bytes representing a string. Must not include null bytes.
843 /// Not guaranteed to be UTF-8 or anything like that.
844 String(Vec<u8>),
845
846 /// The value of a `DW_AT_encoding` attribute.
847 Encoding(constants::DwAte),
848
849 /// The value of a `DW_AT_decimal_sign` attribute.
850 DecimalSign(constants::DwDs),
851
852 /// The value of a `DW_AT_endianity` attribute.
853 Endianity(constants::DwEnd),
854
855 /// The value of a `DW_AT_accessibility` attribute.
856 Accessibility(constants::DwAccess),
857
858 /// The value of a `DW_AT_visibility` attribute.
859 Visibility(constants::DwVis),
860
861 /// The value of a `DW_AT_virtuality` attribute.
862 Virtuality(constants::DwVirtuality),
863
864 /// The value of a `DW_AT_language` attribute.
865 Language(constants::DwLang),
866
867 /// The value of a `DW_AT_address_class` attribute.
868 AddressClass(constants::DwAddr),
869
870 /// The value of a `DW_AT_identifier_case` attribute.
871 IdentifierCase(constants::DwId),
872
873 /// The value of a `DW_AT_calling_convention` attribute.
874 CallingConvention(constants::DwCc),
875
876 /// The value of a `DW_AT_inline` attribute.
877 Inline(constants::DwInl),
878
879 /// The value of a `DW_AT_ordering` attribute.
880 Ordering(constants::DwOrd),
881
882 /// An index into the filename entries from the line number information
883 /// table for the unit containing this value.
884 FileIndex(Option<FileId>),
885}
886
887impl AttributeValue {
888 /// Return the form that will be used to encode this value.
889 pub fn form(&self, encoding: Encoding) -> Result<constants::DwForm> {
890 // TODO: missing forms:
891 // - DW_FORM_indirect
892 // - DW_FORM_implicit_const
893 // - FW_FORM_block1/block2/block4
894 // - DW_FORM_str/strx1/strx2/strx3/strx4
895 // - DW_FORM_addrx/addrx1/addrx2/addrx3/addrx4
896 // - DW_FORM_data16
897 // - DW_FORM_line_strp
898 // - DW_FORM_loclistx
899 // - DW_FORM_rnglistx
900 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 // Using a fixed size format lets us write a placeholder before we know
912 // the value.
913 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 // TODO: should this depend on the size of supplementary section?
921 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 /// Write the attribute value to the given sections.
1144 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/// The section offsets of all elements within a `.debug_info` section.
1390#[derive(Debug, Default)]
1391pub struct DebugInfoOffsets {
1392 base_id: BaseId,
1393 units: Vec<UnitOffsets>,
1394}
1395
1396impl DebugInfoOffsets {
1397 /// Get the `.debug_info` section offset for the given unit.
1398 #[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 /// Get the `.debug_info` section offset for the given entry.
1405 #[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/// The section offsets of all elements of a unit within a `.debug_info` section.
1413#[derive(Debug)]
1414pub(crate) struct UnitOffsets {
1415 base_id: BaseId,
1416 unit: DebugInfoOffset,
1417 entries: Vec<EntryOffset>,
1418}
1419
1420impl UnitOffsets {
1421 /// Get the .debug_info offset for the given entry.
1422 #[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: DebugInfoOffset = self.entries[entry.index].offset;
1426 debug_assert_ne!(offset.0, 0);
1427 offset
1428 }
1429
1430 /// Get the unit offset for the given entry.
1431 #[inline]
1432 pub(crate) fn unit_offset(&self, entry: UnitEntryId) -> u64 {
1433 let offset: DebugInfoOffset = self.debug_info_offset(entry);
1434 (offset.0 - self.unit.0) as u64
1435 }
1436
1437 /// Get the abbreviation code for the given entry.
1438 #[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/// A reference to a `.debug_info` entry that has yet to be resolved.
1461#[derive(Debug, Clone, Copy)]
1462pub(crate) struct DebugInfoReference {
1463 /// The offset within the section of the reference.
1464 pub offset: usize,
1465 /// The size of the reference.
1466 pub size: u8,
1467 /// The unit containing the entry.
1468 pub unit: UnitId,
1469 /// The entry being referenced.
1470 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 /// Create a unit table by reading the data in the given sections.
1506 ///
1507 /// This also updates the given tables with the values that are referenced from
1508 /// attributes in this section.
1509 ///
1510 /// `convert_address` is a function to convert read addresses into the `Address`
1511 /// type. For non-relocatable addresses, this function may simply return
1512 /// `Address::Constant(address)`. For relocatable addresses, it is the caller's
1513 /// responsibility to determine the symbol and addend corresponding to the address
1514 /// and return `Address::Symbol { symbol, addend }`.
1515 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 // Attributes must be converted in a separate pass so that we can handle
1537 // references to other compilation units.
1538 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 /// Create a unit by reading the data in the input sections.
1556 ///
1557 /// Does not add entry attributes.
1558 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 /// Create entry attributes by reading the data in the input sections.
1600 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 /// Create an entry by reading the data in the input sections.
1665 ///
1666 /// Does not add the entry attributes.
1667 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 /// Create an entry's attributes by reading the data in the input sections.
1700 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 // This may point to a null entry, so we have to treat it differently.
1711 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 /// Create an attribute by reading the data in the given sections.
1722 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 /// Create an attribute value by reading the data in the given sections.
1736 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 // TODO: it would be nice to preserve the flag form.
1764 read::AttributeValue::Flag(val) => AttributeValue::Flag(val),
1765 read::AttributeValue::DebugAddrBase(_base) => {
1766 // We convert all address indices to addresses,
1767 // so this is unneeded.
1768 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 // TODO: support relocation of this value
1789 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 // There should only be the line program in the CU DIE which we've already
1798 // converted, so check if it matches that.
1799 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 // We convert all location list indices to offsets,
1818 // so this is unneeded.
1819 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 // We convert all range list indices to offsets,
1840 // so this is unneeded.
1841 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 // We convert all string offsets to `.debug_str` references,
1862 // so this is unneeded.
1863 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 // Should always be a more specific section reference.
1902 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 // Test get/get_mut
1969 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 // Test attrs
1977 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 // Test attrs_mut
1995 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 // Test replace
2015 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 // Create a string with a non-zero id/offset.
2257 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 /*
2314 (
2315 constants::DW_AT_name,
2316 AttributeValue::FlagPresent,
2317 read::AttributeValue::Flag(true),
2318 ),
2319 */
2320 (
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 // read::AttributeValue is invariant in the lifetime of R.
2452 // The lifetimes here are all okay, so transmute it.
2453 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 // root
2780 entries.next_dfs().unwrap().unwrap();
2781 // child1
2782 let (_, sibling1) = next_child(&mut entries);
2783 // grandchild1
2784 entries.next_dfs().unwrap().unwrap();
2785 // child2
2786 let (offset2, sibling2) = next_child(&mut entries);
2787 // child3
2788 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 // The line program we'll be referencing.
2834 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 // For version >= 5, this will reuse the existing file at index 0.
2843 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 // Add and delete entries in the root unit
2994 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 // This deletes both `child1` and its child `grandchild1`
3001 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 // Write DWARF data which should only include `child2`, `child3` and `child4`
3013 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 // root
3021 entries.next_dfs().unwrap().unwrap();
3022 // child2
3023 let (_, read_child2) = entries.next_dfs().unwrap().unwrap();
3024 check_name(read_child2, read_unit, "child2");
3025 // child3
3026 let (_, read_child3) = entries.next_dfs().unwrap().unwrap();
3027 check_name(read_child3, read_unit, "child3");
3028 // child4
3029 let (_, read_child4) = entries.next_dfs().unwrap().unwrap();
3030 check_name(read_child4, read_unit, "child4");
3031 // There should be no more entries
3032 assert!(entries.next_dfs().unwrap().is_none());
3033 }
3034}
3035