1use alloc::vec::Vec;
2use std::ops::{Deref, DerefMut};
3use std::{slice, usize};
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 /// Write the units to the given sections.
82 ///
83 /// `strings` must contain the `.debug_str` offsets of the corresponding
84 /// `StringTable`.
85 pub fn write<W: Writer>(
86 &mut self,
87 sections: &mut Sections<W>,
88 line_strings: &DebugLineStrOffsets,
89 strings: &DebugStrOffsets,
90 ) -> Result<DebugInfoOffsets> {
91 let mut offsets = DebugInfoOffsets {
92 base_id: self.base_id,
93 units: Vec::new(),
94 };
95 for unit in &mut self.units {
96 // TODO: maybe share abbreviation tables
97 let abbrev_offset = sections.debug_abbrev.offset();
98 let mut abbrevs = AbbreviationTable::default();
99
100 offsets.units.push(unit.write(
101 sections,
102 abbrev_offset,
103 &mut abbrevs,
104 line_strings,
105 strings,
106 )?);
107
108 abbrevs.write(&mut sections.debug_abbrev)?;
109 }
110
111 write_section_refs(
112 &mut sections.debug_info_refs,
113 &mut sections.debug_info.0,
114 &offsets,
115 )?;
116 write_section_refs(
117 &mut sections.debug_loc_refs,
118 &mut sections.debug_loc.0,
119 &offsets,
120 )?;
121 write_section_refs(
122 &mut sections.debug_loclists_refs,
123 &mut sections.debug_loclists.0,
124 &offsets,
125 )?;
126
127 Ok(offsets)
128 }
129}
130
131fn write_section_refs<W: Writer>(
132 references: &mut Vec<DebugInfoReference>,
133 w: &mut W,
134 offsets: &DebugInfoOffsets,
135) -> Result<()> {
136 for r: as IntoIterator>::Item in references.drain(..) {
137 let entry_offset: usize = offsets.entry(r.unit, r.entry).0;
138 debug_assert_ne!(entry_offset, 0);
139 w.write_offset_at(r.offset, val:entry_offset, _section:SectionId::DebugInfo, r.size)?;
140 }
141 Ok(())
142}
143
144/// A unit's debugging information.
145#[derive(Debug)]
146pub struct Unit {
147 base_id: BaseId,
148 /// The encoding parameters for this unit.
149 encoding: Encoding,
150 /// The line number program for this unit.
151 pub line_program: LineProgram,
152 /// A table of range lists used by this unit.
153 pub ranges: RangeListTable,
154 /// A table of location lists used by this unit.
155 pub locations: LocationListTable,
156 /// All entries in this unit. The order is unrelated to the tree order.
157 // Requirements:
158 // - entries form a tree
159 // - entries can be added in any order
160 // - entries have a fixed id
161 // - able to quickly lookup an entry from its id
162 // Limitations of current implementation:
163 // - mutable iteration of children is messy due to borrow checker
164 entries: Vec<DebuggingInformationEntry>,
165 /// The index of the root entry in entries.
166 root: UnitEntryId,
167}
168
169impl Unit {
170 /// Create a new `Unit`.
171 pub fn new(encoding: Encoding, line_program: LineProgram) -> Self {
172 let base_id = BaseId::default();
173 let ranges = RangeListTable::default();
174 let locations = LocationListTable::default();
175 let mut entries = Vec::new();
176 let root = DebuggingInformationEntry::new(
177 base_id,
178 &mut entries,
179 None,
180 constants::DW_TAG_compile_unit,
181 );
182 Unit {
183 base_id,
184 encoding,
185 line_program,
186 ranges,
187 locations,
188 entries,
189 root,
190 }
191 }
192
193 /// Return the encoding parameters for this unit.
194 #[inline]
195 pub fn encoding(&self) -> Encoding {
196 self.encoding
197 }
198
199 /// Return the DWARF version for this unit.
200 #[inline]
201 pub fn version(&self) -> u16 {
202 self.encoding.version
203 }
204
205 /// Return the address size in bytes for this unit.
206 #[inline]
207 pub fn address_size(&self) -> u8 {
208 self.encoding.address_size
209 }
210
211 /// Return the DWARF format for this unit.
212 #[inline]
213 pub fn format(&self) -> Format {
214 self.encoding.format
215 }
216
217 /// Return the number of `DebuggingInformationEntry`s created for this unit.
218 ///
219 /// This includes entries that no longer have a parent.
220 #[inline]
221 pub fn count(&self) -> usize {
222 self.entries.len()
223 }
224
225 /// Return the id of the root entry.
226 #[inline]
227 pub fn root(&self) -> UnitEntryId {
228 self.root
229 }
230
231 /// Add a new `DebuggingInformationEntry` to this unit and return its id.
232 ///
233 /// The `parent` must be within the same unit.
234 ///
235 /// # Panics
236 ///
237 /// Panics if `parent` is invalid.
238 #[inline]
239 pub fn add(&mut self, parent: UnitEntryId, tag: constants::DwTag) -> UnitEntryId {
240 debug_assert_eq!(self.base_id, parent.base_id);
241 DebuggingInformationEntry::new(self.base_id, &mut self.entries, Some(parent), tag)
242 }
243
244 /// Get a reference to an entry.
245 ///
246 /// # Panics
247 ///
248 /// Panics if `id` is invalid.
249 #[inline]
250 pub fn get(&self, id: UnitEntryId) -> &DebuggingInformationEntry {
251 debug_assert_eq!(self.base_id, id.base_id);
252 &self.entries[id.index]
253 }
254
255 /// Get a mutable reference to an entry.
256 ///
257 /// # Panics
258 ///
259 /// Panics if `id` is invalid.
260 #[inline]
261 pub fn get_mut(&mut self, id: UnitEntryId) -> &mut DebuggingInformationEntry {
262 debug_assert_eq!(self.base_id, id.base_id);
263 &mut self.entries[id.index]
264 }
265
266 /// Return true if `self.line_program` is used by a DIE.
267 fn line_program_in_use(&self) -> bool {
268 if self.line_program.is_none() {
269 return false;
270 }
271 if !self.line_program.is_empty() {
272 return true;
273 }
274
275 for entry in &self.entries {
276 for attr in &entry.attrs {
277 if let AttributeValue::FileIndex(Some(_)) = attr.value {
278 return true;
279 }
280 }
281 }
282
283 false
284 }
285
286 /// Write the unit to the given sections.
287 pub(crate) fn write<W: Writer>(
288 &mut self,
289 sections: &mut Sections<W>,
290 abbrev_offset: DebugAbbrevOffset,
291 abbrevs: &mut AbbreviationTable,
292 line_strings: &DebugLineStrOffsets,
293 strings: &DebugStrOffsets,
294 ) -> Result<UnitOffsets> {
295 let line_program = if self.line_program_in_use() {
296 self.entries[self.root.index]
297 .set(constants::DW_AT_stmt_list, AttributeValue::LineProgramRef);
298 Some(self.line_program.write(
299 &mut sections.debug_line,
300 self.encoding,
301 line_strings,
302 strings,
303 )?)
304 } else {
305 self.entries[self.root.index].delete(constants::DW_AT_stmt_list);
306 None
307 };
308
309 // TODO: use .debug_types for type units in DWARF v4.
310 let w = &mut sections.debug_info;
311
312 let mut offsets = UnitOffsets {
313 base_id: self.base_id,
314 unit: w.offset(),
315 // Entries can be written in any order, so create the complete vec now.
316 entries: vec![EntryOffset::none(); self.entries.len()],
317 };
318
319 let length_offset = w.write_initial_length(self.format())?;
320 let length_base = w.len();
321
322 w.write_u16(self.version())?;
323 if 2 <= self.version() && self.version() <= 4 {
324 w.write_offset(
325 abbrev_offset.0,
326 SectionId::DebugAbbrev,
327 self.format().word_size(),
328 )?;
329 w.write_u8(self.address_size())?;
330 } else if self.version() == 5 {
331 w.write_u8(constants::DW_UT_compile.0)?;
332 w.write_u8(self.address_size())?;
333 w.write_offset(
334 abbrev_offset.0,
335 SectionId::DebugAbbrev,
336 self.format().word_size(),
337 )?;
338 } else {
339 return Err(Error::UnsupportedVersion(self.version()));
340 }
341
342 // Calculate all DIE offsets, so that we are able to output references to them.
343 // However, references to base types in expressions use ULEB128, so base types
344 // must be moved to the front before we can calculate offsets.
345 self.reorder_base_types();
346 let mut offset = w.len();
347 self.entries[self.root.index].calculate_offsets(
348 self,
349 &mut offset,
350 &mut offsets,
351 abbrevs,
352 )?;
353
354 let range_lists = self.ranges.write(sections, self.encoding)?;
355 // Location lists can't be written until we have DIE offsets.
356 let loc_lists = self
357 .locations
358 .write(sections, self.encoding, Some(&offsets))?;
359
360 let w = &mut sections.debug_info;
361 let mut unit_refs = Vec::new();
362 self.entries[self.root.index].write(
363 w,
364 &mut sections.debug_info_refs,
365 &mut unit_refs,
366 self,
367 &mut offsets,
368 line_program,
369 line_strings,
370 strings,
371 &range_lists,
372 &loc_lists,
373 )?;
374
375 let length = (w.len() - length_base) as u64;
376 w.write_initial_length_at(length_offset, length, self.format())?;
377
378 for (offset, entry) in unit_refs {
379 // This does not need relocation.
380 w.write_udata_at(
381 offset.0,
382 offsets.unit_offset(entry),
383 self.format().word_size(),
384 )?;
385 }
386
387 Ok(offsets)
388 }
389
390 /// Reorder base types to come first so that typed stack operations
391 /// can get their offset.
392 fn reorder_base_types(&mut self) {
393 let root = &self.entries[self.root.index];
394 let mut root_children = Vec::with_capacity(root.children.len());
395 for entry in &root.children {
396 if self.entries[entry.index].tag == constants::DW_TAG_base_type {
397 root_children.push(*entry);
398 }
399 }
400 for entry in &root.children {
401 if self.entries[entry.index].tag != constants::DW_TAG_base_type {
402 root_children.push(*entry);
403 }
404 }
405 self.entries[self.root.index].children = root_children;
406 }
407}
408
409/// A Debugging Information Entry (DIE).
410///
411/// DIEs have a set of attributes and optionally have children DIEs as well.
412///
413/// DIEs form a tree without any cycles. This is enforced by specifying the
414/// parent when creating a DIE, and disallowing changes of parent.
415#[derive(Debug)]
416pub struct DebuggingInformationEntry {
417 id: UnitEntryId,
418 parent: Option<UnitEntryId>,
419 tag: constants::DwTag,
420 /// Whether to emit `DW_AT_sibling`.
421 sibling: bool,
422 attrs: Vec<Attribute>,
423 children: Vec<UnitEntryId>,
424}
425
426impl DebuggingInformationEntry {
427 /// Create a new `DebuggingInformationEntry`.
428 ///
429 /// # Panics
430 ///
431 /// Panics if `parent` is invalid.
432 #[allow(clippy::new_ret_no_self)]
433 fn new(
434 base_id: BaseId,
435 entries: &mut Vec<DebuggingInformationEntry>,
436 parent: Option<UnitEntryId>,
437 tag: constants::DwTag,
438 ) -> UnitEntryId {
439 let id = UnitEntryId::new(base_id, entries.len());
440 entries.push(DebuggingInformationEntry {
441 id,
442 parent,
443 tag,
444 sibling: false,
445 attrs: Vec::new(),
446 children: Vec::new(),
447 });
448 if let Some(parent) = parent {
449 debug_assert_eq!(base_id, parent.base_id);
450 assert_ne!(parent, id);
451 entries[parent.index].children.push(id);
452 }
453 id
454 }
455
456 /// Return the id of this entry.
457 #[inline]
458 pub fn id(&self) -> UnitEntryId {
459 self.id
460 }
461
462 /// Return the parent of this entry.
463 #[inline]
464 pub fn parent(&self) -> Option<UnitEntryId> {
465 self.parent
466 }
467
468 /// Return the tag of this entry.
469 #[inline]
470 pub fn tag(&self) -> constants::DwTag {
471 self.tag
472 }
473
474 /// Return `true` if a `DW_AT_sibling` attribute will be emitted.
475 #[inline]
476 pub fn sibling(&self) -> bool {
477 self.sibling
478 }
479
480 /// Set whether a `DW_AT_sibling` attribute will be emitted.
481 ///
482 /// The attribute will only be emitted if the DIE has children.
483 #[inline]
484 pub fn set_sibling(&mut self, sibling: bool) {
485 self.sibling = sibling;
486 }
487
488 /// Iterate over the attributes of this entry.
489 #[inline]
490 pub fn attrs(&self) -> slice::Iter<Attribute> {
491 self.attrs.iter()
492 }
493
494 /// Iterate over the attributes of this entry for modification.
495 #[inline]
496 pub fn attrs_mut(&mut self) -> slice::IterMut<Attribute> {
497 self.attrs.iter_mut()
498 }
499
500 /// Get an attribute.
501 pub fn get(&self, name: constants::DwAt) -> Option<&AttributeValue> {
502 self.attrs
503 .iter()
504 .find(|attr| attr.name == name)
505 .map(|attr| &attr.value)
506 }
507
508 /// Get an attribute for modification.
509 pub fn get_mut(&mut self, name: constants::DwAt) -> Option<&mut AttributeValue> {
510 self.attrs
511 .iter_mut()
512 .find(|attr| attr.name == name)
513 .map(|attr| &mut attr.value)
514 }
515
516 /// Set an attribute.
517 ///
518 /// Replaces any existing attribute with the same name.
519 ///
520 /// # Panics
521 ///
522 /// Panics if `name` is `DW_AT_sibling`. Use `set_sibling` instead.
523 pub fn set(&mut self, name: constants::DwAt, value: AttributeValue) {
524 assert_ne!(name, constants::DW_AT_sibling);
525 if let Some(attr) = self.attrs.iter_mut().find(|attr| attr.name == name) {
526 attr.value = value;
527 return;
528 }
529 self.attrs.push(Attribute { name, value });
530 }
531
532 /// Delete an attribute.
533 ///
534 /// Replaces any existing attribute with the same name.
535 pub fn delete(&mut self, name: constants::DwAt) {
536 self.attrs.retain(|x| x.name != name);
537 }
538
539 /// Iterate over the children of this entry.
540 ///
541 /// Note: use `Unit::add` to add a new child to this entry.
542 #[inline]
543 pub fn children(&self) -> slice::Iter<UnitEntryId> {
544 self.children.iter()
545 }
546
547 /// Delete a child entry and all of its children.
548 pub fn delete_child(&mut self, id: UnitEntryId) {
549 self.children.retain(|&child| child != id);
550 }
551
552 /// Return the type abbreviation for this DIE.
553 fn abbreviation(&self, encoding: Encoding) -> Result<Abbreviation> {
554 let mut attrs = Vec::new();
555
556 if self.sibling && !self.children.is_empty() {
557 let form = match encoding.format {
558 Format::Dwarf32 => constants::DW_FORM_ref4,
559 Format::Dwarf64 => constants::DW_FORM_ref8,
560 };
561 attrs.push(AttributeSpecification::new(constants::DW_AT_sibling, form));
562 }
563
564 for attr in &self.attrs {
565 attrs.push(attr.specification(encoding)?);
566 }
567
568 Ok(Abbreviation::new(
569 self.tag,
570 !self.children.is_empty(),
571 attrs,
572 ))
573 }
574
575 fn calculate_offsets(
576 &self,
577 unit: &Unit,
578 offset: &mut usize,
579 offsets: &mut UnitOffsets,
580 abbrevs: &mut AbbreviationTable,
581 ) -> Result<()> {
582 offsets.entries[self.id.index].offset = DebugInfoOffset(*offset);
583 offsets.entries[self.id.index].abbrev = abbrevs.add(self.abbreviation(unit.encoding())?);
584 *offset += self.size(unit, offsets);
585 if !self.children.is_empty() {
586 for child in &self.children {
587 unit.entries[child.index].calculate_offsets(unit, offset, offsets, abbrevs)?;
588 }
589 // Null child
590 *offset += 1;
591 }
592 Ok(())
593 }
594
595 fn size(&self, unit: &Unit, offsets: &UnitOffsets) -> usize {
596 let mut size = uleb128_size(offsets.abbrev(self.id));
597 if self.sibling && !self.children.is_empty() {
598 size += unit.format().word_size() as usize;
599 }
600 for attr in &self.attrs {
601 size += attr.value.size(unit, offsets);
602 }
603 size
604 }
605
606 /// Write the entry to the given sections.
607 fn write<W: Writer>(
608 &self,
609 w: &mut DebugInfo<W>,
610 debug_info_refs: &mut Vec<DebugInfoReference>,
611 unit_refs: &mut Vec<(DebugInfoOffset, UnitEntryId)>,
612 unit: &Unit,
613 offsets: &mut UnitOffsets,
614 line_program: Option<DebugLineOffset>,
615 line_strings: &DebugLineStrOffsets,
616 strings: &DebugStrOffsets,
617 range_lists: &RangeListOffsets,
618 loc_lists: &LocationListOffsets,
619 ) -> Result<()> {
620 debug_assert_eq!(offsets.debug_info_offset(self.id), w.offset());
621 w.write_uleb128(offsets.abbrev(self.id))?;
622
623 let sibling_offset = if self.sibling && !self.children.is_empty() {
624 let offset = w.offset();
625 w.write_udata(0, unit.format().word_size())?;
626 Some(offset)
627 } else {
628 None
629 };
630
631 for attr in &self.attrs {
632 attr.value.write(
633 w,
634 debug_info_refs,
635 unit_refs,
636 unit,
637 offsets,
638 line_program,
639 line_strings,
640 strings,
641 range_lists,
642 loc_lists,
643 )?;
644 }
645
646 if !self.children.is_empty() {
647 for child in &self.children {
648 unit.entries[child.index].write(
649 w,
650 debug_info_refs,
651 unit_refs,
652 unit,
653 offsets,
654 line_program,
655 line_strings,
656 strings,
657 range_lists,
658 loc_lists,
659 )?;
660 }
661 // Null child
662 w.write_u8(0)?;
663 }
664
665 if let Some(offset) = sibling_offset {
666 let next_offset = (w.offset().0 - offsets.unit.0) as u64;
667 // This does not need relocation.
668 w.write_udata_at(offset.0, next_offset, unit.format().word_size())?;
669 }
670 Ok(())
671 }
672}
673
674/// An attribute in a `DebuggingInformationEntry`, consisting of a name and
675/// associated value.
676#[derive(Debug, Clone, PartialEq, Eq)]
677pub struct Attribute {
678 name: constants::DwAt,
679 value: AttributeValue,
680}
681
682impl Attribute {
683 /// Get the name of this attribute.
684 #[inline]
685 pub fn name(&self) -> constants::DwAt {
686 self.name
687 }
688
689 /// Get the value of this attribute.
690 #[inline]
691 pub fn get(&self) -> &AttributeValue {
692 &self.value
693 }
694
695 /// Set the value of this attribute.
696 #[inline]
697 pub fn set(&mut self, value: AttributeValue) {
698 self.value = value;
699 }
700
701 /// Return the type specification for this attribute.
702 fn specification(&self, encoding: Encoding) -> Result<AttributeSpecification> {
703 Ok(AttributeSpecification::new(
704 self.name,
705 self.value.form(encoding)?,
706 ))
707 }
708}
709
710/// The value of an attribute in a `DebuggingInformationEntry`.
711#[derive(Debug, Clone, PartialEq, Eq)]
712pub enum AttributeValue {
713 /// "Refers to some location in the address space of the described program."
714 Address(Address),
715
716 /// A slice of an arbitrary number of bytes.
717 Block(Vec<u8>),
718
719 /// A one byte constant data value. How to interpret the byte depends on context.
720 ///
721 /// From section 7 of the standard: "Depending on context, it may be a
722 /// signed integer, an unsigned integer, a floating-point constant, or
723 /// anything else."
724 Data1(u8),
725
726 /// A two byte constant data value. How to interpret the bytes depends on context.
727 ///
728 /// This value will be converted to the target endian before writing.
729 ///
730 /// From section 7 of the standard: "Depending on context, it may be a
731 /// signed integer, an unsigned integer, a floating-point constant, or
732 /// anything else."
733 Data2(u16),
734
735 /// A four byte constant data value. How to interpret the bytes depends on context.
736 ///
737 /// This value will be converted to the target endian before writing.
738 ///
739 /// From section 7 of the standard: "Depending on context, it may be a
740 /// signed integer, an unsigned integer, a floating-point constant, or
741 /// anything else."
742 Data4(u32),
743
744 /// An eight byte constant data value. How to interpret the bytes depends on context.
745 ///
746 /// This value will be converted to the target endian before writing.
747 ///
748 /// From section 7 of the standard: "Depending on context, it may be a
749 /// signed integer, an unsigned integer, a floating-point constant, or
750 /// anything else."
751 Data8(u64),
752
753 /// A signed integer constant.
754 Sdata(i64),
755
756 /// An unsigned integer constant.
757 Udata(u64),
758
759 /// "The information bytes contain a DWARF expression (see Section 2.5) or
760 /// location description (see Section 2.6)."
761 Exprloc(Expression),
762
763 /// A boolean that indicates presence or absence of the attribute.
764 Flag(bool),
765
766 /// An attribute that is always present.
767 FlagPresent,
768
769 /// A reference to a `DebuggingInformationEntry` in this unit.
770 UnitRef(UnitEntryId),
771
772 /// A reference to a `DebuggingInformationEntry` in a potentially different unit.
773 DebugInfoRef(Reference),
774
775 /// An offset into the `.debug_info` section of the supplementary object file.
776 ///
777 /// The API does not currently assist with generating this offset.
778 /// This variant will be removed from the API once support for writing
779 /// supplementary object files is implemented.
780 DebugInfoRefSup(DebugInfoOffset),
781
782 /// A reference to a line number program.
783 LineProgramRef,
784
785 /// A reference to a location list.
786 LocationListRef(LocationListId),
787
788 /// An offset into the `.debug_macinfo` section.
789 ///
790 /// The API does not currently assist with generating this offset.
791 /// This variant will be removed from the API once support for writing
792 /// `.debug_macinfo` sections is implemented.
793 DebugMacinfoRef(DebugMacinfoOffset),
794
795 /// An offset into the `.debug_macro` section.
796 ///
797 /// The API does not currently assist with generating this offset.
798 /// This variant will be removed from the API once support for writing
799 /// `.debug_macro` sections is implemented.
800 DebugMacroRef(DebugMacroOffset),
801
802 /// A reference to a range list.
803 RangeListRef(RangeListId),
804
805 /// A type signature.
806 ///
807 /// The API does not currently assist with generating this signature.
808 /// This variant will be removed from the API once support for writing
809 /// `.debug_types` sections is implemented.
810 DebugTypesRef(DebugTypeSignature),
811
812 /// A reference to a string in the `.debug_str` section.
813 StringRef(StringId),
814
815 /// An offset into the `.debug_str` section of the supplementary object file.
816 ///
817 /// The API does not currently assist with generating this offset.
818 /// This variant will be removed from the API once support for writing
819 /// supplementary object files is implemented.
820 DebugStrRefSup(DebugStrOffset),
821
822 /// A reference to a string in the `.debug_line_str` section.
823 LineStringRef(LineStringId),
824
825 /// A slice of bytes representing a string. Must not include null bytes.
826 /// Not guaranteed to be UTF-8 or anything like that.
827 String(Vec<u8>),
828
829 /// The value of a `DW_AT_encoding` attribute.
830 Encoding(constants::DwAte),
831
832 /// The value of a `DW_AT_decimal_sign` attribute.
833 DecimalSign(constants::DwDs),
834
835 /// The value of a `DW_AT_endianity` attribute.
836 Endianity(constants::DwEnd),
837
838 /// The value of a `DW_AT_accessibility` attribute.
839 Accessibility(constants::DwAccess),
840
841 /// The value of a `DW_AT_visibility` attribute.
842 Visibility(constants::DwVis),
843
844 /// The value of a `DW_AT_virtuality` attribute.
845 Virtuality(constants::DwVirtuality),
846
847 /// The value of a `DW_AT_language` attribute.
848 Language(constants::DwLang),
849
850 /// The value of a `DW_AT_address_class` attribute.
851 AddressClass(constants::DwAddr),
852
853 /// The value of a `DW_AT_identifier_case` attribute.
854 IdentifierCase(constants::DwId),
855
856 /// The value of a `DW_AT_calling_convention` attribute.
857 CallingConvention(constants::DwCc),
858
859 /// The value of a `DW_AT_inline` attribute.
860 Inline(constants::DwInl),
861
862 /// The value of a `DW_AT_ordering` attribute.
863 Ordering(constants::DwOrd),
864
865 /// An index into the filename entries from the line number information
866 /// table for the unit containing this value.
867 FileIndex(Option<FileId>),
868}
869
870impl AttributeValue {
871 /// Return the form that will be used to encode this value.
872 pub fn form(&self, encoding: Encoding) -> Result<constants::DwForm> {
873 // TODO: missing forms:
874 // - DW_FORM_indirect
875 // - DW_FORM_implicit_const
876 // - FW_FORM_block1/block2/block4
877 // - DW_FORM_str/strx1/strx2/strx3/strx4
878 // - DW_FORM_addrx/addrx1/addrx2/addrx3/addrx4
879 // - DW_FORM_data16
880 // - DW_FORM_line_strp
881 // - DW_FORM_loclistx
882 // - DW_FORM_rnglistx
883 let form = match *self {
884 AttributeValue::Address(_) => constants::DW_FORM_addr,
885 AttributeValue::Block(_) => constants::DW_FORM_block,
886 AttributeValue::Data1(_) => constants::DW_FORM_data1,
887 AttributeValue::Data2(_) => constants::DW_FORM_data2,
888 AttributeValue::Data4(_) => constants::DW_FORM_data4,
889 AttributeValue::Data8(_) => constants::DW_FORM_data8,
890 AttributeValue::Exprloc(_) => constants::DW_FORM_exprloc,
891 AttributeValue::Flag(_) => constants::DW_FORM_flag,
892 AttributeValue::FlagPresent => constants::DW_FORM_flag_present,
893 AttributeValue::UnitRef(_) => {
894 // Using a fixed size format lets us write a placeholder before we know
895 // the value.
896 match encoding.format {
897 Format::Dwarf32 => constants::DW_FORM_ref4,
898 Format::Dwarf64 => constants::DW_FORM_ref8,
899 }
900 }
901 AttributeValue::DebugInfoRef(_) => constants::DW_FORM_ref_addr,
902 AttributeValue::DebugInfoRefSup(_) => {
903 // TODO: should this depend on the size of supplementary section?
904 match encoding.format {
905 Format::Dwarf32 => constants::DW_FORM_ref_sup4,
906 Format::Dwarf64 => constants::DW_FORM_ref_sup8,
907 }
908 }
909 AttributeValue::LineProgramRef
910 | AttributeValue::LocationListRef(_)
911 | AttributeValue::DebugMacinfoRef(_)
912 | AttributeValue::DebugMacroRef(_)
913 | AttributeValue::RangeListRef(_) => {
914 if encoding.version == 2 || encoding.version == 3 {
915 match encoding.format {
916 Format::Dwarf32 => constants::DW_FORM_data4,
917 Format::Dwarf64 => constants::DW_FORM_data8,
918 }
919 } else {
920 constants::DW_FORM_sec_offset
921 }
922 }
923 AttributeValue::DebugTypesRef(_) => constants::DW_FORM_ref_sig8,
924 AttributeValue::StringRef(_) => constants::DW_FORM_strp,
925 AttributeValue::DebugStrRefSup(_) => constants::DW_FORM_strp_sup,
926 AttributeValue::LineStringRef(_) => constants::DW_FORM_line_strp,
927 AttributeValue::String(_) => constants::DW_FORM_string,
928 AttributeValue::Encoding(_)
929 | AttributeValue::DecimalSign(_)
930 | AttributeValue::Endianity(_)
931 | AttributeValue::Accessibility(_)
932 | AttributeValue::Visibility(_)
933 | AttributeValue::Virtuality(_)
934 | AttributeValue::Language(_)
935 | AttributeValue::AddressClass(_)
936 | AttributeValue::IdentifierCase(_)
937 | AttributeValue::CallingConvention(_)
938 | AttributeValue::Inline(_)
939 | AttributeValue::Ordering(_)
940 | AttributeValue::FileIndex(_)
941 | AttributeValue::Udata(_) => constants::DW_FORM_udata,
942 AttributeValue::Sdata(_) => constants::DW_FORM_sdata,
943 };
944 Ok(form)
945 }
946
947 fn size(&self, unit: &Unit, offsets: &UnitOffsets) -> usize {
948 macro_rules! debug_assert_form {
949 ($form:expr) => {
950 debug_assert_eq!(self.form(unit.encoding()).unwrap(), $form)
951 };
952 }
953 match *self {
954 AttributeValue::Address(_) => {
955 debug_assert_form!(constants::DW_FORM_addr);
956 unit.address_size() as usize
957 }
958 AttributeValue::Block(ref val) => {
959 debug_assert_form!(constants::DW_FORM_block);
960 uleb128_size(val.len() as u64) + val.len()
961 }
962 AttributeValue::Data1(_) => {
963 debug_assert_form!(constants::DW_FORM_data1);
964 1
965 }
966 AttributeValue::Data2(_) => {
967 debug_assert_form!(constants::DW_FORM_data2);
968 2
969 }
970 AttributeValue::Data4(_) => {
971 debug_assert_form!(constants::DW_FORM_data4);
972 4
973 }
974 AttributeValue::Data8(_) => {
975 debug_assert_form!(constants::DW_FORM_data8);
976 8
977 }
978 AttributeValue::Sdata(val) => {
979 debug_assert_form!(constants::DW_FORM_sdata);
980 sleb128_size(val)
981 }
982 AttributeValue::Udata(val) => {
983 debug_assert_form!(constants::DW_FORM_udata);
984 uleb128_size(val)
985 }
986 AttributeValue::Exprloc(ref val) => {
987 debug_assert_form!(constants::DW_FORM_exprloc);
988 let size = val.size(unit.encoding(), Some(offsets));
989 uleb128_size(size as u64) + size
990 }
991 AttributeValue::Flag(_) => {
992 debug_assert_form!(constants::DW_FORM_flag);
993 1
994 }
995 AttributeValue::FlagPresent => {
996 debug_assert_form!(constants::DW_FORM_flag_present);
997 0
998 }
999 AttributeValue::UnitRef(_) => {
1000 match unit.format() {
1001 Format::Dwarf32 => debug_assert_form!(constants::DW_FORM_ref4),
1002 Format::Dwarf64 => debug_assert_form!(constants::DW_FORM_ref8),
1003 }
1004 unit.format().word_size() as usize
1005 }
1006 AttributeValue::DebugInfoRef(_) => {
1007 debug_assert_form!(constants::DW_FORM_ref_addr);
1008 if unit.version() == 2 {
1009 unit.address_size() as usize
1010 } else {
1011 unit.format().word_size() as usize
1012 }
1013 }
1014 AttributeValue::DebugInfoRefSup(_) => {
1015 match unit.format() {
1016 Format::Dwarf32 => debug_assert_form!(constants::DW_FORM_ref_sup4),
1017 Format::Dwarf64 => debug_assert_form!(constants::DW_FORM_ref_sup8),
1018 }
1019 unit.format().word_size() as usize
1020 }
1021 AttributeValue::LineProgramRef => {
1022 if unit.version() >= 4 {
1023 debug_assert_form!(constants::DW_FORM_sec_offset);
1024 }
1025 unit.format().word_size() as usize
1026 }
1027 AttributeValue::LocationListRef(_) => {
1028 if unit.version() >= 4 {
1029 debug_assert_form!(constants::DW_FORM_sec_offset);
1030 }
1031 unit.format().word_size() as usize
1032 }
1033 AttributeValue::DebugMacinfoRef(_) => {
1034 if unit.version() >= 4 {
1035 debug_assert_form!(constants::DW_FORM_sec_offset);
1036 }
1037 unit.format().word_size() as usize
1038 }
1039 AttributeValue::DebugMacroRef(_) => {
1040 if unit.version() >= 4 {
1041 debug_assert_form!(constants::DW_FORM_sec_offset);
1042 }
1043 unit.format().word_size() as usize
1044 }
1045 AttributeValue::RangeListRef(_) => {
1046 if unit.version() >= 4 {
1047 debug_assert_form!(constants::DW_FORM_sec_offset);
1048 }
1049 unit.format().word_size() as usize
1050 }
1051 AttributeValue::DebugTypesRef(_) => {
1052 debug_assert_form!(constants::DW_FORM_ref_sig8);
1053 8
1054 }
1055 AttributeValue::StringRef(_) => {
1056 debug_assert_form!(constants::DW_FORM_strp);
1057 unit.format().word_size() as usize
1058 }
1059 AttributeValue::DebugStrRefSup(_) => {
1060 debug_assert_form!(constants::DW_FORM_strp_sup);
1061 unit.format().word_size() as usize
1062 }
1063 AttributeValue::LineStringRef(_) => {
1064 debug_assert_form!(constants::DW_FORM_line_strp);
1065 unit.format().word_size() as usize
1066 }
1067 AttributeValue::String(ref val) => {
1068 debug_assert_form!(constants::DW_FORM_string);
1069 val.len() + 1
1070 }
1071 AttributeValue::Encoding(val) => {
1072 debug_assert_form!(constants::DW_FORM_udata);
1073 uleb128_size(val.0 as u64)
1074 }
1075 AttributeValue::DecimalSign(val) => {
1076 debug_assert_form!(constants::DW_FORM_udata);
1077 uleb128_size(val.0 as u64)
1078 }
1079 AttributeValue::Endianity(val) => {
1080 debug_assert_form!(constants::DW_FORM_udata);
1081 uleb128_size(val.0 as u64)
1082 }
1083 AttributeValue::Accessibility(val) => {
1084 debug_assert_form!(constants::DW_FORM_udata);
1085 uleb128_size(val.0 as u64)
1086 }
1087 AttributeValue::Visibility(val) => {
1088 debug_assert_form!(constants::DW_FORM_udata);
1089 uleb128_size(val.0 as u64)
1090 }
1091 AttributeValue::Virtuality(val) => {
1092 debug_assert_form!(constants::DW_FORM_udata);
1093 uleb128_size(val.0 as u64)
1094 }
1095 AttributeValue::Language(val) => {
1096 debug_assert_form!(constants::DW_FORM_udata);
1097 uleb128_size(val.0 as u64)
1098 }
1099 AttributeValue::AddressClass(val) => {
1100 debug_assert_form!(constants::DW_FORM_udata);
1101 uleb128_size(val.0 as u64)
1102 }
1103 AttributeValue::IdentifierCase(val) => {
1104 debug_assert_form!(constants::DW_FORM_udata);
1105 uleb128_size(val.0 as u64)
1106 }
1107 AttributeValue::CallingConvention(val) => {
1108 debug_assert_form!(constants::DW_FORM_udata);
1109 uleb128_size(val.0 as u64)
1110 }
1111 AttributeValue::Inline(val) => {
1112 debug_assert_form!(constants::DW_FORM_udata);
1113 uleb128_size(val.0 as u64)
1114 }
1115 AttributeValue::Ordering(val) => {
1116 debug_assert_form!(constants::DW_FORM_udata);
1117 uleb128_size(val.0 as u64)
1118 }
1119 AttributeValue::FileIndex(val) => {
1120 debug_assert_form!(constants::DW_FORM_udata);
1121 uleb128_size(val.map(FileId::raw).unwrap_or(0))
1122 }
1123 }
1124 }
1125
1126 /// Write the attribute value to the given sections.
1127 fn write<W: Writer>(
1128 &self,
1129 w: &mut DebugInfo<W>,
1130 debug_info_refs: &mut Vec<DebugInfoReference>,
1131 unit_refs: &mut Vec<(DebugInfoOffset, UnitEntryId)>,
1132 unit: &Unit,
1133 offsets: &UnitOffsets,
1134 line_program: Option<DebugLineOffset>,
1135 line_strings: &DebugLineStrOffsets,
1136 strings: &DebugStrOffsets,
1137 range_lists: &RangeListOffsets,
1138 loc_lists: &LocationListOffsets,
1139 ) -> Result<()> {
1140 macro_rules! debug_assert_form {
1141 ($form:expr) => {
1142 debug_assert_eq!(self.form(unit.encoding()).unwrap(), $form)
1143 };
1144 }
1145 match *self {
1146 AttributeValue::Address(val) => {
1147 debug_assert_form!(constants::DW_FORM_addr);
1148 w.write_address(val, unit.address_size())?;
1149 }
1150 AttributeValue::Block(ref val) => {
1151 debug_assert_form!(constants::DW_FORM_block);
1152 w.write_uleb128(val.len() as u64)?;
1153 w.write(val)?;
1154 }
1155 AttributeValue::Data1(val) => {
1156 debug_assert_form!(constants::DW_FORM_data1);
1157 w.write_u8(val)?;
1158 }
1159 AttributeValue::Data2(val) => {
1160 debug_assert_form!(constants::DW_FORM_data2);
1161 w.write_u16(val)?;
1162 }
1163 AttributeValue::Data4(val) => {
1164 debug_assert_form!(constants::DW_FORM_data4);
1165 w.write_u32(val)?;
1166 }
1167 AttributeValue::Data8(val) => {
1168 debug_assert_form!(constants::DW_FORM_data8);
1169 w.write_u64(val)?;
1170 }
1171 AttributeValue::Sdata(val) => {
1172 debug_assert_form!(constants::DW_FORM_sdata);
1173 w.write_sleb128(val)?;
1174 }
1175 AttributeValue::Udata(val) => {
1176 debug_assert_form!(constants::DW_FORM_udata);
1177 w.write_uleb128(val)?;
1178 }
1179 AttributeValue::Exprloc(ref val) => {
1180 debug_assert_form!(constants::DW_FORM_exprloc);
1181 w.write_uleb128(val.size(unit.encoding(), Some(offsets)) as u64)?;
1182 val.write(
1183 &mut w.0,
1184 Some(debug_info_refs),
1185 unit.encoding(),
1186 Some(offsets),
1187 )?;
1188 }
1189 AttributeValue::Flag(val) => {
1190 debug_assert_form!(constants::DW_FORM_flag);
1191 w.write_u8(val as u8)?;
1192 }
1193 AttributeValue::FlagPresent => {
1194 debug_assert_form!(constants::DW_FORM_flag_present);
1195 }
1196 AttributeValue::UnitRef(id) => {
1197 match unit.format() {
1198 Format::Dwarf32 => debug_assert_form!(constants::DW_FORM_ref4),
1199 Format::Dwarf64 => debug_assert_form!(constants::DW_FORM_ref8),
1200 }
1201 unit_refs.push((w.offset(), id));
1202 w.write_udata(0, unit.format().word_size())?;
1203 }
1204 AttributeValue::DebugInfoRef(reference) => {
1205 debug_assert_form!(constants::DW_FORM_ref_addr);
1206 let size = if unit.version() == 2 {
1207 unit.address_size()
1208 } else {
1209 unit.format().word_size()
1210 };
1211 match reference {
1212 Reference::Symbol(symbol) => w.write_reference(symbol, size)?,
1213 Reference::Entry(unit, entry) => {
1214 debug_info_refs.push(DebugInfoReference {
1215 offset: w.len(),
1216 unit,
1217 entry,
1218 size,
1219 });
1220 w.write_udata(0, size)?;
1221 }
1222 }
1223 }
1224 AttributeValue::DebugInfoRefSup(val) => {
1225 match unit.format() {
1226 Format::Dwarf32 => debug_assert_form!(constants::DW_FORM_ref_sup4),
1227 Format::Dwarf64 => debug_assert_form!(constants::DW_FORM_ref_sup8),
1228 }
1229 w.write_udata(val.0 as u64, unit.format().word_size())?;
1230 }
1231 AttributeValue::LineProgramRef => {
1232 if unit.version() >= 4 {
1233 debug_assert_form!(constants::DW_FORM_sec_offset);
1234 }
1235 match line_program {
1236 Some(line_program) => {
1237 w.write_offset(
1238 line_program.0,
1239 SectionId::DebugLine,
1240 unit.format().word_size(),
1241 )?;
1242 }
1243 None => return Err(Error::InvalidAttributeValue),
1244 }
1245 }
1246 AttributeValue::LocationListRef(val) => {
1247 if unit.version() >= 4 {
1248 debug_assert_form!(constants::DW_FORM_sec_offset);
1249 }
1250 let section = if unit.version() <= 4 {
1251 SectionId::DebugLoc
1252 } else {
1253 SectionId::DebugLocLists
1254 };
1255 w.write_offset(loc_lists.get(val).0, section, unit.format().word_size())?;
1256 }
1257 AttributeValue::DebugMacinfoRef(val) => {
1258 if unit.version() >= 4 {
1259 debug_assert_form!(constants::DW_FORM_sec_offset);
1260 }
1261 w.write_offset(val.0, SectionId::DebugMacinfo, unit.format().word_size())?;
1262 }
1263 AttributeValue::DebugMacroRef(val) => {
1264 if unit.version() >= 4 {
1265 debug_assert_form!(constants::DW_FORM_sec_offset);
1266 }
1267 w.write_offset(val.0, SectionId::DebugMacro, unit.format().word_size())?;
1268 }
1269 AttributeValue::RangeListRef(val) => {
1270 if unit.version() >= 4 {
1271 debug_assert_form!(constants::DW_FORM_sec_offset);
1272 }
1273 let section = if unit.version() <= 4 {
1274 SectionId::DebugRanges
1275 } else {
1276 SectionId::DebugRngLists
1277 };
1278 w.write_offset(range_lists.get(val).0, section, unit.format().word_size())?;
1279 }
1280 AttributeValue::DebugTypesRef(val) => {
1281 debug_assert_form!(constants::DW_FORM_ref_sig8);
1282 w.write_u64(val.0)?;
1283 }
1284 AttributeValue::StringRef(val) => {
1285 debug_assert_form!(constants::DW_FORM_strp);
1286 w.write_offset(
1287 strings.get(val).0,
1288 SectionId::DebugStr,
1289 unit.format().word_size(),
1290 )?;
1291 }
1292 AttributeValue::DebugStrRefSup(val) => {
1293 debug_assert_form!(constants::DW_FORM_strp_sup);
1294 w.write_udata(val.0 as u64, unit.format().word_size())?;
1295 }
1296 AttributeValue::LineStringRef(val) => {
1297 debug_assert_form!(constants::DW_FORM_line_strp);
1298 w.write_offset(
1299 line_strings.get(val).0,
1300 SectionId::DebugLineStr,
1301 unit.format().word_size(),
1302 )?;
1303 }
1304 AttributeValue::String(ref val) => {
1305 debug_assert_form!(constants::DW_FORM_string);
1306 w.write(val)?;
1307 w.write_u8(0)?;
1308 }
1309 AttributeValue::Encoding(val) => {
1310 debug_assert_form!(constants::DW_FORM_udata);
1311 w.write_uleb128(u64::from(val.0))?;
1312 }
1313 AttributeValue::DecimalSign(val) => {
1314 debug_assert_form!(constants::DW_FORM_udata);
1315 w.write_uleb128(u64::from(val.0))?;
1316 }
1317 AttributeValue::Endianity(val) => {
1318 debug_assert_form!(constants::DW_FORM_udata);
1319 w.write_uleb128(u64::from(val.0))?;
1320 }
1321 AttributeValue::Accessibility(val) => {
1322 debug_assert_form!(constants::DW_FORM_udata);
1323 w.write_uleb128(u64::from(val.0))?;
1324 }
1325 AttributeValue::Visibility(val) => {
1326 debug_assert_form!(constants::DW_FORM_udata);
1327 w.write_uleb128(u64::from(val.0))?;
1328 }
1329 AttributeValue::Virtuality(val) => {
1330 debug_assert_form!(constants::DW_FORM_udata);
1331 w.write_uleb128(u64::from(val.0))?;
1332 }
1333 AttributeValue::Language(val) => {
1334 debug_assert_form!(constants::DW_FORM_udata);
1335 w.write_uleb128(u64::from(val.0))?;
1336 }
1337 AttributeValue::AddressClass(val) => {
1338 debug_assert_form!(constants::DW_FORM_udata);
1339 w.write_uleb128(val.0)?;
1340 }
1341 AttributeValue::IdentifierCase(val) => {
1342 debug_assert_form!(constants::DW_FORM_udata);
1343 w.write_uleb128(u64::from(val.0))?;
1344 }
1345 AttributeValue::CallingConvention(val) => {
1346 debug_assert_form!(constants::DW_FORM_udata);
1347 w.write_uleb128(u64::from(val.0))?;
1348 }
1349 AttributeValue::Inline(val) => {
1350 debug_assert_form!(constants::DW_FORM_udata);
1351 w.write_uleb128(u64::from(val.0))?;
1352 }
1353 AttributeValue::Ordering(val) => {
1354 debug_assert_form!(constants::DW_FORM_udata);
1355 w.write_uleb128(u64::from(val.0))?;
1356 }
1357 AttributeValue::FileIndex(val) => {
1358 debug_assert_form!(constants::DW_FORM_udata);
1359 w.write_uleb128(val.map(FileId::raw).unwrap_or(0))?;
1360 }
1361 }
1362 Ok(())
1363 }
1364}
1365
1366define_section!(
1367 DebugInfo,
1368 DebugInfoOffset,
1369 "A writable `.debug_info` section."
1370);
1371
1372/// The section offsets of all elements within a `.debug_info` section.
1373#[derive(Debug, Default)]
1374pub struct DebugInfoOffsets {
1375 base_id: BaseId,
1376 units: Vec<UnitOffsets>,
1377}
1378
1379impl DebugInfoOffsets {
1380 #[cfg(test)]
1381 #[cfg(feature = "read")]
1382 pub(crate) fn unit_offsets(&self, unit: UnitId) -> &UnitOffsets {
1383 debug_assert_eq!(self.base_id, unit.base_id);
1384 &self.units[unit.index]
1385 }
1386
1387 /// Get the `.debug_info` section offset for the given unit.
1388 #[inline]
1389 pub fn unit(&self, unit: UnitId) -> DebugInfoOffset {
1390 debug_assert_eq!(self.base_id, unit.base_id);
1391 self.units[unit.index].unit
1392 }
1393
1394 /// Get the `.debug_info` section offset for the given entry.
1395 #[inline]
1396 pub fn entry(&self, unit: UnitId, entry: UnitEntryId) -> DebugInfoOffset {
1397 debug_assert_eq!(self.base_id, unit.base_id);
1398 self.units[unit.index].debug_info_offset(entry)
1399 }
1400}
1401
1402/// The section offsets of all elements of a unit within a `.debug_info` section.
1403#[derive(Debug)]
1404pub(crate) struct UnitOffsets {
1405 base_id: BaseId,
1406 unit: DebugInfoOffset,
1407 entries: Vec<EntryOffset>,
1408}
1409
1410impl UnitOffsets {
1411 #[cfg(test)]
1412 #[cfg(feature = "read")]
1413 fn none() -> Self {
1414 UnitOffsets {
1415 base_id: BaseId::default(),
1416 unit: DebugInfoOffset(0),
1417 entries: Vec::new(),
1418 }
1419 }
1420
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 = 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 = 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 {
1893 // 0 means not specified, even for version 5.
1894 AttributeValue::FileIndex(None)
1895 } else {
1896 match context.line_program_files.get(val as usize) {
1897 Some(id) => AttributeValue::FileIndex(Some(*id)),
1898 None => return Err(ConvertError::InvalidFileIndex),
1899 }
1900 }
1901 }
1902 // Should always be a more specific section reference.
1903 read::AttributeValue::SecOffset(_) => {
1904 return Err(ConvertError::InvalidAttributeValue);
1905 }
1906 read::AttributeValue::DwoId(DwoId(val)) => AttributeValue::Udata(val),
1907 };
1908 Ok(Some(to))
1909 }
1910 }
1911}
1912
1913#[cfg(test)]
1914#[cfg(feature = "read")]
1915mod tests {
1916 use super::*;
1917 use crate::common::{
1918 DebugAddrBase, DebugLocListsBase, DebugRngListsBase, DebugStrOffsetsBase, LineEncoding,
1919 };
1920 use crate::constants;
1921 use crate::read;
1922 use crate::write::{
1923 DebugLine, DebugLineStr, DebugStr, DwarfUnit, EndianVec, LineString, LineStringTable,
1924 Location, LocationList, LocationListTable, Range, RangeList, RangeListOffsets,
1925 RangeListTable, StringTable,
1926 };
1927 use crate::LittleEndian;
1928 use std::collections::HashMap;
1929 use std::mem;
1930 use std::sync::Arc;
1931
1932 #[test]
1933 fn test_unit_table() {
1934 let mut strings = StringTable::default();
1935
1936 let mut units = UnitTable::default();
1937 let unit_id1 = units.add(Unit::new(
1938 Encoding {
1939 version: 4,
1940 address_size: 8,
1941 format: Format::Dwarf32,
1942 },
1943 LineProgram::none(),
1944 ));
1945 let unit2 = units.add(Unit::new(
1946 Encoding {
1947 version: 2,
1948 address_size: 4,
1949 format: Format::Dwarf64,
1950 },
1951 LineProgram::none(),
1952 ));
1953 let unit3 = units.add(Unit::new(
1954 Encoding {
1955 version: 5,
1956 address_size: 4,
1957 format: Format::Dwarf32,
1958 },
1959 LineProgram::none(),
1960 ));
1961 assert_eq!(units.count(), 3);
1962 {
1963 let unit1 = units.get_mut(unit_id1);
1964 assert_eq!(unit1.version(), 4);
1965 assert_eq!(unit1.address_size(), 8);
1966 assert_eq!(unit1.format(), Format::Dwarf32);
1967 assert_eq!(unit1.count(), 1);
1968
1969 let root_id = unit1.root();
1970 assert_eq!(root_id, UnitEntryId::new(unit1.base_id, 0));
1971 {
1972 let root = unit1.get_mut(root_id);
1973 assert_eq!(root.id(), root_id);
1974 assert!(root.parent().is_none());
1975 assert_eq!(root.tag(), constants::DW_TAG_compile_unit);
1976
1977 // Test get/get_mut
1978 assert!(root.get(constants::DW_AT_producer).is_none());
1979 assert!(root.get_mut(constants::DW_AT_producer).is_none());
1980 let mut producer = AttributeValue::String(b"root"[..].into());
1981 root.set(constants::DW_AT_producer, producer.clone());
1982 assert_eq!(root.get(constants::DW_AT_producer), Some(&producer));
1983 assert_eq!(root.get_mut(constants::DW_AT_producer), Some(&mut producer));
1984
1985 // Test attrs
1986 let mut attrs = root.attrs();
1987 let attr = attrs.next().unwrap();
1988 assert_eq!(attr.name(), constants::DW_AT_producer);
1989 assert_eq!(attr.get(), &producer);
1990 assert!(attrs.next().is_none());
1991 }
1992
1993 let child1 = unit1.add(root_id, constants::DW_TAG_subprogram);
1994 assert_eq!(child1, UnitEntryId::new(unit1.base_id, 1));
1995 {
1996 let child1 = unit1.get_mut(child1);
1997 assert_eq!(child1.parent(), Some(root_id));
1998
1999 let tmp = AttributeValue::String(b"tmp"[..].into());
2000 child1.set(constants::DW_AT_name, tmp.clone());
2001 assert_eq!(child1.get(constants::DW_AT_name), Some(&tmp));
2002
2003 // Test attrs_mut
2004 let name = AttributeValue::StringRef(strings.add(&b"child1"[..]));
2005 {
2006 let attr = child1.attrs_mut().next().unwrap();
2007 assert_eq!(attr.name(), constants::DW_AT_name);
2008 attr.set(name.clone());
2009 }
2010 assert_eq!(child1.get(constants::DW_AT_name), Some(&name));
2011 }
2012
2013 let child2 = unit1.add(root_id, constants::DW_TAG_subprogram);
2014 assert_eq!(child2, UnitEntryId::new(unit1.base_id, 2));
2015 {
2016 let child2 = unit1.get_mut(child2);
2017 assert_eq!(child2.parent(), Some(root_id));
2018
2019 let tmp = AttributeValue::String(b"tmp"[..].into());
2020 child2.set(constants::DW_AT_name, tmp.clone());
2021 assert_eq!(child2.get(constants::DW_AT_name), Some(&tmp));
2022
2023 // Test replace
2024 let name = AttributeValue::StringRef(strings.add(&b"child2"[..]));
2025 child2.set(constants::DW_AT_name, name.clone());
2026 assert_eq!(child2.get(constants::DW_AT_name), Some(&name));
2027 }
2028
2029 {
2030 let root = unit1.get(root_id);
2031 assert_eq!(
2032 root.children().cloned().collect::<Vec<_>>(),
2033 vec![child1, child2]
2034 );
2035 }
2036 }
2037 {
2038 let unit2 = units.get(unit2);
2039 assert_eq!(unit2.version(), 2);
2040 assert_eq!(unit2.address_size(), 4);
2041 assert_eq!(unit2.format(), Format::Dwarf64);
2042 assert_eq!(unit2.count(), 1);
2043
2044 let root = unit2.root();
2045 assert_eq!(root, UnitEntryId::new(unit2.base_id, 0));
2046 let root = unit2.get(root);
2047 assert_eq!(root.id(), UnitEntryId::new(unit2.base_id, 0));
2048 assert!(root.parent().is_none());
2049 assert_eq!(root.tag(), constants::DW_TAG_compile_unit);
2050 }
2051
2052 let mut sections = Sections::new(EndianVec::new(LittleEndian));
2053 let debug_line_str_offsets = DebugLineStrOffsets::none();
2054 let debug_str_offsets = strings.write(&mut sections.debug_str).unwrap();
2055 units
2056 .write(&mut sections, &debug_line_str_offsets, &debug_str_offsets)
2057 .unwrap();
2058
2059 println!("{:?}", sections.debug_str);
2060 println!("{:?}", sections.debug_info);
2061 println!("{:?}", sections.debug_abbrev);
2062
2063 let dwarf = read::Dwarf {
2064 debug_abbrev: read::DebugAbbrev::new(sections.debug_abbrev.slice(), LittleEndian),
2065 debug_info: read::DebugInfo::new(sections.debug_info.slice(), LittleEndian),
2066 debug_str: read::DebugStr::new(sections.debug_str.slice(), LittleEndian),
2067 ..Default::default()
2068 };
2069 let mut read_units = dwarf.units();
2070
2071 {
2072 let read_unit1 = read_units.next().unwrap().unwrap();
2073 let unit1 = units.get(unit_id1);
2074 assert_eq!(unit1.version(), read_unit1.version());
2075 assert_eq!(unit1.address_size(), read_unit1.address_size());
2076 assert_eq!(unit1.format(), read_unit1.format());
2077
2078 let read_unit1 = dwarf.unit(read_unit1).unwrap();
2079 let mut read_entries = read_unit1.entries();
2080
2081 let root = unit1.get(unit1.root());
2082 {
2083 let (depth, read_root) = read_entries.next_dfs().unwrap().unwrap();
2084 assert_eq!(depth, 0);
2085 assert_eq!(root.tag(), read_root.tag());
2086 assert!(read_root.has_children());
2087
2088 let producer = match root.get(constants::DW_AT_producer).unwrap() {
2089 AttributeValue::String(ref producer) => &**producer,
2090 otherwise => panic!("unexpected {:?}", otherwise),
2091 };
2092 assert_eq!(producer, b"root");
2093 let read_producer = read_root
2094 .attr_value(constants::DW_AT_producer)
2095 .unwrap()
2096 .unwrap();
2097 assert_eq!(
2098 dwarf
2099 .attr_string(&read_unit1, read_producer)
2100 .unwrap()
2101 .slice(),
2102 producer
2103 );
2104 }
2105
2106 let mut children = root.children().cloned();
2107
2108 {
2109 let child = children.next().unwrap();
2110 assert_eq!(child, UnitEntryId::new(unit1.base_id, 1));
2111 let child = unit1.get(child);
2112 let (depth, read_child) = read_entries.next_dfs().unwrap().unwrap();
2113 assert_eq!(depth, 1);
2114 assert_eq!(child.tag(), read_child.tag());
2115 assert!(!read_child.has_children());
2116
2117 let name = match child.get(constants::DW_AT_name).unwrap() {
2118 AttributeValue::StringRef(name) => *name,
2119 otherwise => panic!("unexpected {:?}", otherwise),
2120 };
2121 let name = strings.get(name);
2122 assert_eq!(name, b"child1");
2123 let read_name = read_child
2124 .attr_value(constants::DW_AT_name)
2125 .unwrap()
2126 .unwrap();
2127 assert_eq!(
2128 dwarf.attr_string(&read_unit1, read_name).unwrap().slice(),
2129 name
2130 );
2131 }
2132
2133 {
2134 let child = children.next().unwrap();
2135 assert_eq!(child, UnitEntryId::new(unit1.base_id, 2));
2136 let child = unit1.get(child);
2137 let (depth, read_child) = read_entries.next_dfs().unwrap().unwrap();
2138 assert_eq!(depth, 0);
2139 assert_eq!(child.tag(), read_child.tag());
2140 assert!(!read_child.has_children());
2141
2142 let name = match child.get(constants::DW_AT_name).unwrap() {
2143 AttributeValue::StringRef(name) => *name,
2144 otherwise => panic!("unexpected {:?}", otherwise),
2145 };
2146 let name = strings.get(name);
2147 assert_eq!(name, b"child2");
2148 let read_name = read_child
2149 .attr_value(constants::DW_AT_name)
2150 .unwrap()
2151 .unwrap();
2152 assert_eq!(
2153 dwarf.attr_string(&read_unit1, read_name).unwrap().slice(),
2154 name
2155 );
2156 }
2157
2158 assert!(read_entries.next_dfs().unwrap().is_none());
2159 }
2160
2161 {
2162 let read_unit2 = read_units.next().unwrap().unwrap();
2163 let unit2 = units.get(unit2);
2164 assert_eq!(unit2.version(), read_unit2.version());
2165 assert_eq!(unit2.address_size(), read_unit2.address_size());
2166 assert_eq!(unit2.format(), read_unit2.format());
2167
2168 let abbrevs = dwarf.abbreviations(&read_unit2).unwrap();
2169 let mut read_entries = read_unit2.entries(&abbrevs);
2170
2171 {
2172 let root = unit2.get(unit2.root());
2173 let (depth, read_root) = read_entries.next_dfs().unwrap().unwrap();
2174 assert_eq!(depth, 0);
2175 assert_eq!(root.tag(), read_root.tag());
2176 assert!(!read_root.has_children());
2177 }
2178
2179 assert!(read_entries.next_dfs().unwrap().is_none());
2180 }
2181
2182 {
2183 let read_unit3 = read_units.next().unwrap().unwrap();
2184 let unit3 = units.get(unit3);
2185 assert_eq!(unit3.version(), read_unit3.version());
2186 assert_eq!(unit3.address_size(), read_unit3.address_size());
2187 assert_eq!(unit3.format(), read_unit3.format());
2188
2189 let abbrevs = dwarf.abbreviations(&read_unit3).unwrap();
2190 let mut read_entries = read_unit3.entries(&abbrevs);
2191
2192 {
2193 let root = unit3.get(unit3.root());
2194 let (depth, read_root) = read_entries.next_dfs().unwrap().unwrap();
2195 assert_eq!(depth, 0);
2196 assert_eq!(root.tag(), read_root.tag());
2197 assert!(!read_root.has_children());
2198 }
2199
2200 assert!(read_entries.next_dfs().unwrap().is_none());
2201 }
2202
2203 assert!(read_units.next().unwrap().is_none());
2204
2205 let mut convert_line_strings = LineStringTable::default();
2206 let mut convert_strings = StringTable::default();
2207 let convert_units = UnitTable::from(
2208 &dwarf,
2209 &mut convert_line_strings,
2210 &mut convert_strings,
2211 &|address| Some(Address::Constant(address)),
2212 )
2213 .unwrap();
2214 assert_eq!(convert_units.count(), units.count());
2215
2216 for i in 0..convert_units.count() {
2217 let unit_id = units.id(i);
2218 let unit = units.get(unit_id);
2219 let convert_unit_id = convert_units.id(i);
2220 let convert_unit = convert_units.get(convert_unit_id);
2221 assert_eq!(convert_unit.version(), unit.version());
2222 assert_eq!(convert_unit.address_size(), unit.address_size());
2223 assert_eq!(convert_unit.format(), unit.format());
2224 assert_eq!(convert_unit.count(), unit.count());
2225
2226 let root = unit.get(unit.root());
2227 let convert_root = convert_unit.get(convert_unit.root());
2228 assert_eq!(convert_root.tag(), root.tag());
2229 for (convert_attr, attr) in convert_root.attrs().zip(root.attrs()) {
2230 assert_eq!(convert_attr, attr);
2231 }
2232 }
2233 }
2234
2235 #[test]
2236 fn test_attribute_value() {
2237 // Create a string table and a string with a non-zero id/offset.
2238 let mut strings = StringTable::default();
2239 strings.add("string one");
2240 let string_id = strings.add("string two");
2241 let mut debug_str = DebugStr::from(EndianVec::new(LittleEndian));
2242 let debug_str_offsets = strings.write(&mut debug_str).unwrap();
2243 let read_debug_str = read::DebugStr::new(debug_str.slice(), LittleEndian);
2244
2245 let mut line_strings = LineStringTable::default();
2246 line_strings.add("line string one");
2247 let line_string_id = line_strings.add("line string two");
2248 let mut debug_line_str = DebugLineStr::from(EndianVec::new(LittleEndian));
2249 let debug_line_str_offsets = line_strings.write(&mut debug_line_str).unwrap();
2250 let read_debug_line_str =
2251 read::DebugLineStr::from(read::EndianSlice::new(debug_line_str.slice(), LittleEndian));
2252
2253 let data = vec![1, 2, 3, 4];
2254 let read_data = read::EndianSlice::new(&[1, 2, 3, 4], LittleEndian);
2255
2256 let mut expression = Expression::new();
2257 expression.op_constu(57);
2258 let read_expression = read::Expression(read::EndianSlice::new(
2259 &[constants::DW_OP_constu.0, 57],
2260 LittleEndian,
2261 ));
2262
2263 let mut ranges = RangeListTable::default();
2264 let range_id = ranges.add(RangeList(vec![Range::StartEnd {
2265 begin: Address::Constant(0x1234),
2266 end: Address::Constant(0x2345),
2267 }]));
2268
2269 let mut locations = LocationListTable::default();
2270 let loc_id = locations.add(LocationList(vec![Location::StartEnd {
2271 begin: Address::Constant(0x1234),
2272 end: Address::Constant(0x2345),
2273 data: expression.clone(),
2274 }]));
2275
2276 for &version in &[2, 3, 4, 5] {
2277 for &address_size in &[4, 8] {
2278 for &format in &[Format::Dwarf32, Format::Dwarf64] {
2279 let encoding = Encoding {
2280 format,
2281 version,
2282 address_size,
2283 };
2284
2285 let mut sections = Sections::new(EndianVec::new(LittleEndian));
2286 let range_list_offsets = ranges.write(&mut sections, encoding).unwrap();
2287 let loc_list_offsets = locations.write(&mut sections, encoding, None).unwrap();
2288
2289 let read_debug_ranges =
2290 read::DebugRanges::new(sections.debug_ranges.slice(), LittleEndian);
2291 let read_debug_rnglists =
2292 read::DebugRngLists::new(sections.debug_rnglists.slice(), LittleEndian);
2293
2294 let read_debug_loc =
2295 read::DebugLoc::new(sections.debug_loc.slice(), LittleEndian);
2296 let read_debug_loclists =
2297 read::DebugLocLists::new(sections.debug_loclists.slice(), LittleEndian);
2298
2299 let mut units = UnitTable::default();
2300 let unit = units.add(Unit::new(encoding, LineProgram::none()));
2301 let unit = units.get(unit);
2302 let encoding = Encoding {
2303 format,
2304 version,
2305 address_size,
2306 };
2307 let from_unit = read::UnitHeader::new(
2308 encoding,
2309 0,
2310 read::UnitType::Compilation,
2311 DebugAbbrevOffset(0),
2312 DebugInfoOffset(0).into(),
2313 read::EndianSlice::new(&[], LittleEndian),
2314 );
2315
2316 for &(ref name, ref value, ref expect_value) in &[
2317 (
2318 constants::DW_AT_name,
2319 AttributeValue::Address(Address::Constant(0x1234)),
2320 read::AttributeValue::Addr(0x1234),
2321 ),
2322 (
2323 constants::DW_AT_name,
2324 AttributeValue::Block(data.clone()),
2325 read::AttributeValue::Block(read_data),
2326 ),
2327 (
2328 constants::DW_AT_name,
2329 AttributeValue::Data1(0x12),
2330 read::AttributeValue::Data1(0x12),
2331 ),
2332 (
2333 constants::DW_AT_name,
2334 AttributeValue::Data2(0x1234),
2335 read::AttributeValue::Data2(0x1234),
2336 ),
2337 (
2338 constants::DW_AT_name,
2339 AttributeValue::Data4(0x1234),
2340 read::AttributeValue::Data4(0x1234),
2341 ),
2342 (
2343 constants::DW_AT_name,
2344 AttributeValue::Data8(0x1234),
2345 read::AttributeValue::Data8(0x1234),
2346 ),
2347 (
2348 constants::DW_AT_name,
2349 AttributeValue::Sdata(0x1234),
2350 read::AttributeValue::Sdata(0x1234),
2351 ),
2352 (
2353 constants::DW_AT_name,
2354 AttributeValue::Udata(0x1234),
2355 read::AttributeValue::Udata(0x1234),
2356 ),
2357 (
2358 constants::DW_AT_name,
2359 AttributeValue::Exprloc(expression.clone()),
2360 read::AttributeValue::Exprloc(read_expression),
2361 ),
2362 (
2363 constants::DW_AT_name,
2364 AttributeValue::Flag(false),
2365 read::AttributeValue::Flag(false),
2366 ),
2367 /*
2368 (
2369 constants::DW_AT_name,
2370 AttributeValue::FlagPresent,
2371 read::AttributeValue::Flag(true),
2372 ),
2373 */
2374 (
2375 constants::DW_AT_name,
2376 AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x1234)),
2377 read::AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x1234)),
2378 ),
2379 (
2380 constants::DW_AT_location,
2381 AttributeValue::LocationListRef(loc_id),
2382 read::AttributeValue::SecOffset(loc_list_offsets.get(loc_id).0),
2383 ),
2384 (
2385 constants::DW_AT_macro_info,
2386 AttributeValue::DebugMacinfoRef(DebugMacinfoOffset(0x1234)),
2387 read::AttributeValue::SecOffset(0x1234),
2388 ),
2389 (
2390 constants::DW_AT_macros,
2391 AttributeValue::DebugMacroRef(DebugMacroOffset(0x1234)),
2392 read::AttributeValue::SecOffset(0x1234),
2393 ),
2394 (
2395 constants::DW_AT_ranges,
2396 AttributeValue::RangeListRef(range_id),
2397 read::AttributeValue::SecOffset(range_list_offsets.get(range_id).0),
2398 ),
2399 (
2400 constants::DW_AT_name,
2401 AttributeValue::DebugTypesRef(DebugTypeSignature(0x1234)),
2402 read::AttributeValue::DebugTypesRef(DebugTypeSignature(0x1234)),
2403 ),
2404 (
2405 constants::DW_AT_name,
2406 AttributeValue::StringRef(string_id),
2407 read::AttributeValue::DebugStrRef(debug_str_offsets.get(string_id)),
2408 ),
2409 (
2410 constants::DW_AT_name,
2411 AttributeValue::DebugStrRefSup(DebugStrOffset(0x1234)),
2412 read::AttributeValue::DebugStrRefSup(DebugStrOffset(0x1234)),
2413 ),
2414 (
2415 constants::DW_AT_name,
2416 AttributeValue::LineStringRef(line_string_id),
2417 read::AttributeValue::DebugLineStrRef(
2418 debug_line_str_offsets.get(line_string_id),
2419 ),
2420 ),
2421 (
2422 constants::DW_AT_name,
2423 AttributeValue::String(data.clone()),
2424 read::AttributeValue::String(read_data),
2425 ),
2426 (
2427 constants::DW_AT_encoding,
2428 AttributeValue::Encoding(constants::DwAte(0x12)),
2429 read::AttributeValue::Udata(0x12),
2430 ),
2431 (
2432 constants::DW_AT_decimal_sign,
2433 AttributeValue::DecimalSign(constants::DwDs(0x12)),
2434 read::AttributeValue::Udata(0x12),
2435 ),
2436 (
2437 constants::DW_AT_endianity,
2438 AttributeValue::Endianity(constants::DwEnd(0x12)),
2439 read::AttributeValue::Udata(0x12),
2440 ),
2441 (
2442 constants::DW_AT_accessibility,
2443 AttributeValue::Accessibility(constants::DwAccess(0x12)),
2444 read::AttributeValue::Udata(0x12),
2445 ),
2446 (
2447 constants::DW_AT_visibility,
2448 AttributeValue::Visibility(constants::DwVis(0x12)),
2449 read::AttributeValue::Udata(0x12),
2450 ),
2451 (
2452 constants::DW_AT_virtuality,
2453 AttributeValue::Virtuality(constants::DwVirtuality(0x12)),
2454 read::AttributeValue::Udata(0x12),
2455 ),
2456 (
2457 constants::DW_AT_language,
2458 AttributeValue::Language(constants::DwLang(0x12)),
2459 read::AttributeValue::Udata(0x12),
2460 ),
2461 (
2462 constants::DW_AT_address_class,
2463 AttributeValue::AddressClass(constants::DwAddr(0x12)),
2464 read::AttributeValue::Udata(0x12),
2465 ),
2466 (
2467 constants::DW_AT_identifier_case,
2468 AttributeValue::IdentifierCase(constants::DwId(0x12)),
2469 read::AttributeValue::Udata(0x12),
2470 ),
2471 (
2472 constants::DW_AT_calling_convention,
2473 AttributeValue::CallingConvention(constants::DwCc(0x12)),
2474 read::AttributeValue::Udata(0x12),
2475 ),
2476 (
2477 constants::DW_AT_ordering,
2478 AttributeValue::Ordering(constants::DwOrd(0x12)),
2479 read::AttributeValue::Udata(0x12),
2480 ),
2481 (
2482 constants::DW_AT_inline,
2483 AttributeValue::Inline(constants::DwInl(0x12)),
2484 read::AttributeValue::Udata(0x12),
2485 ),
2486 ][..]
2487 {
2488 let form = value.form(encoding).unwrap();
2489 let attr = Attribute {
2490 name: *name,
2491 value: value.clone(),
2492 };
2493
2494 let offsets = UnitOffsets::none();
2495 let line_program_offset = None;
2496 let mut debug_info_refs = Vec::new();
2497 let mut unit_refs = Vec::new();
2498 let mut debug_info = DebugInfo::from(EndianVec::new(LittleEndian));
2499 attr.value
2500 .write(
2501 &mut debug_info,
2502 &mut debug_info_refs,
2503 &mut unit_refs,
2504 &unit,
2505 &offsets,
2506 line_program_offset,
2507 &debug_line_str_offsets,
2508 &debug_str_offsets,
2509 &range_list_offsets,
2510 &loc_list_offsets,
2511 )
2512 .unwrap();
2513
2514 let spec = read::AttributeSpecification::new(*name, form, None);
2515 let mut r = read::EndianSlice::new(debug_info.slice(), LittleEndian);
2516 let read_attr = read::parse_attribute(&mut r, encoding, spec).unwrap();
2517 let read_value = &read_attr.raw_value();
2518 // read::AttributeValue is invariant in the lifetime of R.
2519 // The lifetimes here are all okay, so transmute it.
2520 let read_value = unsafe {
2521 mem::transmute::<
2522 &read::AttributeValue<read::EndianSlice<LittleEndian>>,
2523 &read::AttributeValue<read::EndianSlice<LittleEndian>>,
2524 >(read_value)
2525 };
2526 assert_eq!(read_value, expect_value);
2527
2528 let dwarf = read::Dwarf {
2529 debug_str: read_debug_str.clone(),
2530 debug_line_str: read_debug_line_str.clone(),
2531 ranges: read::RangeLists::new(read_debug_ranges, read_debug_rnglists),
2532 locations: read::LocationLists::new(
2533 read_debug_loc,
2534 read_debug_loclists,
2535 ),
2536 ..Default::default()
2537 };
2538
2539 let unit = read::Unit {
2540 header: from_unit,
2541 abbreviations: Arc::new(read::Abbreviations::default()),
2542 name: None,
2543 comp_dir: None,
2544 low_pc: 0,
2545 str_offsets_base: DebugStrOffsetsBase(0),
2546 addr_base: DebugAddrBase(0),
2547 loclists_base: DebugLocListsBase(0),
2548 rnglists_base: DebugRngListsBase(0),
2549 line_program: None,
2550 dwo_id: None,
2551 };
2552
2553 let mut context = convert::ConvertUnitContext {
2554 dwarf: &dwarf,
2555 unit: &unit,
2556 line_strings: &mut line_strings,
2557 strings: &mut strings,
2558 ranges: &mut ranges,
2559 locations: &mut locations,
2560 convert_address: &|address| Some(Address::Constant(address)),
2561 base_address: Address::Constant(0),
2562 line_program_offset: None,
2563 line_program_files: Vec::new(),
2564 entry_ids: &HashMap::new(),
2565 };
2566
2567 let convert_attr =
2568 Attribute::from(&mut context, &read_attr).unwrap().unwrap();
2569 assert_eq!(convert_attr, attr);
2570 }
2571 }
2572 }
2573 }
2574 }
2575
2576 #[test]
2577 fn test_unit_ref() {
2578 let mut units = UnitTable::default();
2579 let unit_id1 = units.add(Unit::new(
2580 Encoding {
2581 version: 4,
2582 address_size: 8,
2583 format: Format::Dwarf32,
2584 },
2585 LineProgram::none(),
2586 ));
2587 assert_eq!(unit_id1, units.id(0));
2588 let unit_id2 = units.add(Unit::new(
2589 Encoding {
2590 version: 2,
2591 address_size: 4,
2592 format: Format::Dwarf64,
2593 },
2594 LineProgram::none(),
2595 ));
2596 assert_eq!(unit_id2, units.id(1));
2597 let unit1_child1 = UnitEntryId::new(units.get(unit_id1).base_id, 1);
2598 let unit1_child2 = UnitEntryId::new(units.get(unit_id1).base_id, 2);
2599 let unit2_child1 = UnitEntryId::new(units.get(unit_id2).base_id, 1);
2600 let unit2_child2 = UnitEntryId::new(units.get(unit_id2).base_id, 2);
2601 {
2602 let unit1 = units.get_mut(unit_id1);
2603 let root = unit1.root();
2604 let child_id1 = unit1.add(root, constants::DW_TAG_subprogram);
2605 assert_eq!(child_id1, unit1_child1);
2606 let child_id2 = unit1.add(root, constants::DW_TAG_subprogram);
2607 assert_eq!(child_id2, unit1_child2);
2608 {
2609 let child1 = unit1.get_mut(child_id1);
2610 child1.set(constants::DW_AT_type, AttributeValue::UnitRef(child_id2));
2611 }
2612 {
2613 let child2 = unit1.get_mut(child_id2);
2614 child2.set(
2615 constants::DW_AT_type,
2616 AttributeValue::DebugInfoRef(Reference::Entry(unit_id2, unit2_child1)),
2617 );
2618 }
2619 }
2620 {
2621 let unit2 = units.get_mut(unit_id2);
2622 let root = unit2.root();
2623 let child_id1 = unit2.add(root, constants::DW_TAG_subprogram);
2624 assert_eq!(child_id1, unit2_child1);
2625 let child_id2 = unit2.add(root, constants::DW_TAG_subprogram);
2626 assert_eq!(child_id2, unit2_child2);
2627 {
2628 let child1 = unit2.get_mut(child_id1);
2629 child1.set(constants::DW_AT_type, AttributeValue::UnitRef(child_id2));
2630 }
2631 {
2632 let child2 = unit2.get_mut(child_id2);
2633 child2.set(
2634 constants::DW_AT_type,
2635 AttributeValue::DebugInfoRef(Reference::Entry(unit_id1, unit1_child1)),
2636 );
2637 }
2638 }
2639
2640 let debug_line_str_offsets = DebugLineStrOffsets::none();
2641 let debug_str_offsets = DebugStrOffsets::none();
2642 let mut sections = Sections::new(EndianVec::new(LittleEndian));
2643 let debug_info_offsets = units
2644 .write(&mut sections, &debug_line_str_offsets, &debug_str_offsets)
2645 .unwrap();
2646
2647 println!("{:?}", sections.debug_info);
2648 println!("{:?}", sections.debug_abbrev);
2649
2650 let dwarf = read::Dwarf {
2651 debug_abbrev: read::DebugAbbrev::new(sections.debug_abbrev.slice(), LittleEndian),
2652 debug_info: read::DebugInfo::new(sections.debug_info.slice(), LittleEndian),
2653 ..Default::default()
2654 };
2655
2656 let mut read_units = dwarf.units();
2657 {
2658 let read_unit1 = read_units.next().unwrap().unwrap();
2659 assert_eq!(
2660 read_unit1.offset(),
2661 debug_info_offsets.unit(unit_id1).into()
2662 );
2663
2664 let abbrevs = dwarf.abbreviations(&read_unit1).unwrap();
2665 let mut read_entries = read_unit1.entries(&abbrevs);
2666 {
2667 let (_, _read_root) = read_entries.next_dfs().unwrap().unwrap();
2668 }
2669 {
2670 let (_, read_child1) = read_entries.next_dfs().unwrap().unwrap();
2671 let offset = debug_info_offsets
2672 .entry(unit_id1, unit1_child2)
2673 .to_unit_offset(&read_unit1)
2674 .unwrap();
2675 assert_eq!(
2676 read_child1.attr_value(constants::DW_AT_type).unwrap(),
2677 Some(read::AttributeValue::UnitRef(offset))
2678 );
2679 }
2680 {
2681 let (_, read_child2) = read_entries.next_dfs().unwrap().unwrap();
2682 let offset = debug_info_offsets.entry(unit_id2, unit2_child1);
2683 assert_eq!(
2684 read_child2.attr_value(constants::DW_AT_type).unwrap(),
2685 Some(read::AttributeValue::DebugInfoRef(offset))
2686 );
2687 }
2688 }
2689 {
2690 let read_unit2 = read_units.next().unwrap().unwrap();
2691 assert_eq!(
2692 read_unit2.offset(),
2693 debug_info_offsets.unit(unit_id2).into()
2694 );
2695
2696 let abbrevs = dwarf.abbreviations(&read_unit2).unwrap();
2697 let mut read_entries = read_unit2.entries(&abbrevs);
2698 {
2699 let (_, _read_root) = read_entries.next_dfs().unwrap().unwrap();
2700 }
2701 {
2702 let (_, read_child1) = read_entries.next_dfs().unwrap().unwrap();
2703 let offset = debug_info_offsets
2704 .entry(unit_id2, unit2_child2)
2705 .to_unit_offset(&read_unit2)
2706 .unwrap();
2707 assert_eq!(
2708 read_child1.attr_value(constants::DW_AT_type).unwrap(),
2709 Some(read::AttributeValue::UnitRef(offset))
2710 );
2711 }
2712 {
2713 let (_, read_child2) = read_entries.next_dfs().unwrap().unwrap();
2714 let offset = debug_info_offsets.entry(unit_id1, unit1_child1);
2715 assert_eq!(
2716 read_child2.attr_value(constants::DW_AT_type).unwrap(),
2717 Some(read::AttributeValue::DebugInfoRef(offset))
2718 );
2719 }
2720 }
2721
2722 let mut convert_line_strings = LineStringTable::default();
2723 let mut convert_strings = StringTable::default();
2724 let convert_units = UnitTable::from(
2725 &dwarf,
2726 &mut convert_line_strings,
2727 &mut convert_strings,
2728 &|address| Some(Address::Constant(address)),
2729 )
2730 .unwrap();
2731 assert_eq!(convert_units.count(), units.count());
2732
2733 for i in 0..convert_units.count() {
2734 let unit = units.get(units.id(i));
2735 let convert_unit = convert_units.get(convert_units.id(i));
2736 assert_eq!(convert_unit.version(), unit.version());
2737 assert_eq!(convert_unit.address_size(), unit.address_size());
2738 assert_eq!(convert_unit.format(), unit.format());
2739 assert_eq!(convert_unit.count(), unit.count());
2740
2741 let root = unit.get(unit.root());
2742 let convert_root = convert_unit.get(convert_unit.root());
2743 assert_eq!(convert_root.tag(), root.tag());
2744 for (convert_attr, attr) in convert_root.attrs().zip(root.attrs()) {
2745 assert_eq!(convert_attr, attr);
2746 }
2747
2748 let child1 = unit.get(UnitEntryId::new(unit.base_id, 1));
2749 let convert_child1 = convert_unit.get(UnitEntryId::new(convert_unit.base_id, 1));
2750 assert_eq!(convert_child1.tag(), child1.tag());
2751 for (convert_attr, attr) in convert_child1.attrs().zip(child1.attrs()) {
2752 assert_eq!(convert_attr.name, attr.name);
2753 match (convert_attr.value.clone(), attr.value.clone()) {
2754 (
2755 AttributeValue::DebugInfoRef(Reference::Entry(convert_unit, convert_entry)),
2756 AttributeValue::DebugInfoRef(Reference::Entry(unit, entry)),
2757 ) => {
2758 assert_eq!(convert_unit.index, unit.index);
2759 assert_eq!(convert_entry.index, entry.index);
2760 }
2761 (AttributeValue::UnitRef(convert_id), AttributeValue::UnitRef(id)) => {
2762 assert_eq!(convert_id.index, id.index);
2763 }
2764 (convert_value, value) => assert_eq!(convert_value, value),
2765 }
2766 }
2767
2768 let child2 = unit.get(UnitEntryId::new(unit.base_id, 2));
2769 let convert_child2 = convert_unit.get(UnitEntryId::new(convert_unit.base_id, 2));
2770 assert_eq!(convert_child2.tag(), child2.tag());
2771 for (convert_attr, attr) in convert_child2.attrs().zip(child2.attrs()) {
2772 assert_eq!(convert_attr.name, attr.name);
2773 match (convert_attr.value.clone(), attr.value.clone()) {
2774 (
2775 AttributeValue::DebugInfoRef(Reference::Entry(convert_unit, convert_entry)),
2776 AttributeValue::DebugInfoRef(Reference::Entry(unit, entry)),
2777 ) => {
2778 assert_eq!(convert_unit.index, unit.index);
2779 assert_eq!(convert_entry.index, entry.index);
2780 }
2781 (AttributeValue::UnitRef(convert_id), AttributeValue::UnitRef(id)) => {
2782 assert_eq!(convert_id.index, id.index);
2783 }
2784 (convert_value, value) => assert_eq!(convert_value, value),
2785 }
2786 }
2787 }
2788 }
2789
2790 #[test]
2791 fn test_sibling() {
2792 fn add_child(
2793 unit: &mut Unit,
2794 parent: UnitEntryId,
2795 tag: constants::DwTag,
2796 name: &str,
2797 ) -> UnitEntryId {
2798 let id = unit.add(parent, tag);
2799 let child = unit.get_mut(id);
2800 child.set(constants::DW_AT_name, AttributeValue::String(name.into()));
2801 child.set_sibling(true);
2802 id
2803 }
2804
2805 fn add_children(units: &mut UnitTable, unit_id: UnitId) {
2806 let unit = units.get_mut(unit_id);
2807 let root = unit.root();
2808 let child1 = add_child(unit, root, constants::DW_TAG_subprogram, "child1");
2809 add_child(unit, child1, constants::DW_TAG_variable, "grandchild1");
2810 add_child(unit, root, constants::DW_TAG_subprogram, "child2");
2811 add_child(unit, root, constants::DW_TAG_subprogram, "child3");
2812 }
2813
2814 fn next_child<R: read::Reader<Offset = usize>>(
2815 entries: &mut read::EntriesCursor<R>,
2816 ) -> (read::UnitOffset, Option<read::UnitOffset>) {
2817 let (_, entry) = entries.next_dfs().unwrap().unwrap();
2818 let offset = entry.offset();
2819 let sibling =
2820 entry
2821 .attr_value(constants::DW_AT_sibling)
2822 .unwrap()
2823 .map(|attr| match attr {
2824 read::AttributeValue::UnitRef(offset) => offset,
2825 _ => panic!("bad sibling value"),
2826 });
2827 (offset, sibling)
2828 }
2829
2830 fn check_sibling<R: read::Reader<Offset = usize>>(
2831 unit: &read::UnitHeader<R>,
2832 debug_abbrev: &read::DebugAbbrev<R>,
2833 ) {
2834 let abbrevs = unit.abbreviations(debug_abbrev).unwrap();
2835 let mut entries = unit.entries(&abbrevs);
2836 // root
2837 entries.next_dfs().unwrap().unwrap();
2838 // child1
2839 let (_, sibling1) = next_child(&mut entries);
2840 // grandchild1
2841 entries.next_dfs().unwrap().unwrap();
2842 // child2
2843 let (offset2, sibling2) = next_child(&mut entries);
2844 // child3
2845 let (_, _) = next_child(&mut entries);
2846 assert_eq!(sibling1, Some(offset2));
2847 assert_eq!(sibling2, None);
2848 }
2849
2850 let encoding = Encoding {
2851 format: Format::Dwarf32,
2852 version: 4,
2853 address_size: 8,
2854 };
2855 let mut units = UnitTable::default();
2856 let unit_id1 = units.add(Unit::new(encoding, LineProgram::none()));
2857 add_children(&mut units, unit_id1);
2858 let unit_id2 = units.add(Unit::new(encoding, LineProgram::none()));
2859 add_children(&mut units, unit_id2);
2860
2861 let debug_line_str_offsets = DebugLineStrOffsets::none();
2862 let debug_str_offsets = DebugStrOffsets::none();
2863 let mut sections = Sections::new(EndianVec::new(LittleEndian));
2864 units
2865 .write(&mut sections, &debug_line_str_offsets, &debug_str_offsets)
2866 .unwrap();
2867
2868 println!("{:?}", sections.debug_info);
2869 println!("{:?}", sections.debug_abbrev);
2870
2871 let read_debug_info = read::DebugInfo::new(sections.debug_info.slice(), LittleEndian);
2872 let read_debug_abbrev = read::DebugAbbrev::new(sections.debug_abbrev.slice(), LittleEndian);
2873 let mut read_units = read_debug_info.units();
2874 check_sibling(&read_units.next().unwrap().unwrap(), &read_debug_abbrev);
2875 check_sibling(&read_units.next().unwrap().unwrap(), &read_debug_abbrev);
2876 }
2877
2878 #[test]
2879 fn test_line_ref() {
2880 for &version in &[2, 3, 4, 5] {
2881 for &address_size in &[4, 8] {
2882 for &format in &[Format::Dwarf32, Format::Dwarf64] {
2883 let encoding = Encoding {
2884 format,
2885 version,
2886 address_size,
2887 };
2888
2889 // The line program we'll be referencing.
2890 let mut line_program = LineProgram::new(
2891 encoding,
2892 LineEncoding::default(),
2893 LineString::String(b"comp_dir".to_vec()),
2894 LineString::String(b"comp_name".to_vec()),
2895 None,
2896 );
2897 let dir = line_program.default_directory();
2898 let file1 =
2899 line_program.add_file(LineString::String(b"file1".to_vec()), dir, None);
2900 let file2 =
2901 line_program.add_file(LineString::String(b"file2".to_vec()), dir, None);
2902
2903 // Write, read, and convert the line program, so that we have the info
2904 // required to convert the attributes.
2905 let line_strings = DebugLineStrOffsets::none();
2906 let strings = DebugStrOffsets::none();
2907 let mut debug_line = DebugLine::from(EndianVec::new(LittleEndian));
2908 let line_program_offset = line_program
2909 .write(&mut debug_line, encoding, &line_strings, &strings)
2910 .unwrap();
2911 let read_debug_line = read::DebugLine::new(debug_line.slice(), LittleEndian);
2912 let read_line_program = read_debug_line
2913 .program(
2914 line_program_offset,
2915 address_size,
2916 Some(read::EndianSlice::new(b"comp_dir", LittleEndian)),
2917 Some(read::EndianSlice::new(b"comp_name", LittleEndian)),
2918 )
2919 .unwrap();
2920 let dwarf = read::Dwarf::default();
2921 let mut convert_line_strings = LineStringTable::default();
2922 let mut convert_strings = StringTable::default();
2923 let (_, line_program_files) = LineProgram::from(
2924 read_line_program,
2925 &dwarf,
2926 &mut convert_line_strings,
2927 &mut convert_strings,
2928 &|address| Some(Address::Constant(address)),
2929 )
2930 .unwrap();
2931
2932 // Fake the unit.
2933 let mut units = UnitTable::default();
2934 let unit = units.add(Unit::new(encoding, LineProgram::none()));
2935 let unit = units.get(unit);
2936 let from_unit = read::UnitHeader::new(
2937 encoding,
2938 0,
2939 read::UnitType::Compilation,
2940 DebugAbbrevOffset(0),
2941 DebugInfoOffset(0).into(),
2942 read::EndianSlice::new(&[], LittleEndian),
2943 );
2944
2945 for &(ref name, ref value, ref expect_value) in &[
2946 (
2947 constants::DW_AT_stmt_list,
2948 AttributeValue::LineProgramRef,
2949 read::AttributeValue::SecOffset(line_program_offset.0),
2950 ),
2951 (
2952 constants::DW_AT_decl_file,
2953 AttributeValue::FileIndex(Some(file1)),
2954 read::AttributeValue::Udata(file1.raw()),
2955 ),
2956 (
2957 constants::DW_AT_decl_file,
2958 AttributeValue::FileIndex(Some(file2)),
2959 read::AttributeValue::Udata(file2.raw()),
2960 ),
2961 ][..]
2962 {
2963 let mut ranges = RangeListTable::default();
2964 let mut locations = LocationListTable::default();
2965 let mut strings = StringTable::default();
2966 let mut line_strings = LineStringTable::default();
2967
2968 let form = value.form(encoding).unwrap();
2969 let attr = Attribute {
2970 name: *name,
2971 value: value.clone(),
2972 };
2973
2974 let mut debug_info_refs = Vec::new();
2975 let mut unit_refs = Vec::new();
2976 let mut debug_info = DebugInfo::from(EndianVec::new(LittleEndian));
2977 let offsets = UnitOffsets::none();
2978 let debug_line_str_offsets = DebugLineStrOffsets::none();
2979 let debug_str_offsets = DebugStrOffsets::none();
2980 let range_list_offsets = RangeListOffsets::none();
2981 let loc_list_offsets = LocationListOffsets::none();
2982 attr.value
2983 .write(
2984 &mut debug_info,
2985 &mut debug_info_refs,
2986 &mut unit_refs,
2987 &unit,
2988 &offsets,
2989 Some(line_program_offset),
2990 &debug_line_str_offsets,
2991 &debug_str_offsets,
2992 &range_list_offsets,
2993 &loc_list_offsets,
2994 )
2995 .unwrap();
2996
2997 let spec = read::AttributeSpecification::new(*name, form, None);
2998 let mut r = read::EndianSlice::new(debug_info.slice(), LittleEndian);
2999 let read_attr = read::parse_attribute(&mut r, encoding, spec).unwrap();
3000 let read_value = &read_attr.raw_value();
3001 // read::AttributeValue is invariant in the lifetime of R.
3002 // The lifetimes here are all okay, so transmute it.
3003 let read_value = unsafe {
3004 mem::transmute::<
3005 &read::AttributeValue<read::EndianSlice<LittleEndian>>,
3006 &read::AttributeValue<read::EndianSlice<LittleEndian>>,
3007 >(read_value)
3008 };
3009 assert_eq!(read_value, expect_value);
3010
3011 let unit = read::Unit {
3012 header: from_unit,
3013 abbreviations: Arc::new(read::Abbreviations::default()),
3014 name: None,
3015 comp_dir: None,
3016 low_pc: 0,
3017 str_offsets_base: DebugStrOffsetsBase(0),
3018 addr_base: DebugAddrBase(0),
3019 loclists_base: DebugLocListsBase(0),
3020 rnglists_base: DebugRngListsBase(0),
3021 line_program: None,
3022 dwo_id: None,
3023 };
3024
3025 let mut context = convert::ConvertUnitContext {
3026 dwarf: &dwarf,
3027 unit: &unit,
3028 line_strings: &mut line_strings,
3029 strings: &mut strings,
3030 ranges: &mut ranges,
3031 locations: &mut locations,
3032 convert_address: &|address| Some(Address::Constant(address)),
3033 base_address: Address::Constant(0),
3034 line_program_offset: Some(line_program_offset),
3035 line_program_files: line_program_files.clone(),
3036 entry_ids: &HashMap::new(),
3037 };
3038
3039 let convert_attr =
3040 Attribute::from(&mut context, &read_attr).unwrap().unwrap();
3041 assert_eq!(convert_attr, attr);
3042 }
3043 }
3044 }
3045 }
3046 }
3047
3048 #[test]
3049 fn test_line_program_used() {
3050 for used in vec![false, true] {
3051 let encoding = Encoding {
3052 format: Format::Dwarf32,
3053 version: 5,
3054 address_size: 8,
3055 };
3056
3057 let line_program = LineProgram::new(
3058 encoding,
3059 LineEncoding::default(),
3060 LineString::String(b"comp_dir".to_vec()),
3061 LineString::String(b"comp_name".to_vec()),
3062 None,
3063 );
3064
3065 let mut unit = Unit::new(encoding, line_program);
3066 let file_id = if used { Some(FileId::new(0)) } else { None };
3067 let root = unit.root();
3068 unit.get_mut(root).set(
3069 constants::DW_AT_decl_file,
3070 AttributeValue::FileIndex(file_id),
3071 );
3072
3073 let mut units = UnitTable::default();
3074 units.add(unit);
3075
3076 let debug_line_str_offsets = DebugLineStrOffsets::none();
3077 let debug_str_offsets = DebugStrOffsets::none();
3078 let mut sections = Sections::new(EndianVec::new(LittleEndian));
3079 units
3080 .write(&mut sections, &debug_line_str_offsets, &debug_str_offsets)
3081 .unwrap();
3082 assert_eq!(!used, sections.debug_line.slice().is_empty());
3083 }
3084 }
3085
3086 #[test]
3087 fn test_delete_child() {
3088 fn set_name(unit: &mut Unit, id: UnitEntryId, name: &str) {
3089 let entry = unit.get_mut(id);
3090 entry.set(constants::DW_AT_name, AttributeValue::String(name.into()));
3091 }
3092 fn check_name<R: read::Reader>(
3093 entry: &read::DebuggingInformationEntry<R>,
3094 debug_str: &read::DebugStr<R>,
3095 name: &str,
3096 ) {
3097 let name_attr = entry.attr(constants::DW_AT_name).unwrap().unwrap();
3098 let entry_name = name_attr.string_value(debug_str).unwrap();
3099 let entry_name_str = entry_name.to_string().unwrap();
3100 assert_eq!(entry_name_str, name);
3101 }
3102 let encoding = Encoding {
3103 format: Format::Dwarf32,
3104 version: 4,
3105 address_size: 8,
3106 };
3107 let mut dwarf = DwarfUnit::new(encoding);
3108 let root = dwarf.unit.root();
3109
3110 // Add and delete entries in the root unit
3111 let child1 = dwarf.unit.add(root, constants::DW_TAG_subprogram);
3112 set_name(&mut dwarf.unit, child1, "child1");
3113 let grandchild1 = dwarf.unit.add(child1, constants::DW_TAG_variable);
3114 set_name(&mut dwarf.unit, grandchild1, "grandchild1");
3115 let child2 = dwarf.unit.add(root, constants::DW_TAG_subprogram);
3116 set_name(&mut dwarf.unit, child2, "child2");
3117 // This deletes both `child1` and its child `grandchild1`
3118 dwarf.unit.get_mut(root).delete_child(child1);
3119 let child3 = dwarf.unit.add(root, constants::DW_TAG_subprogram);
3120 set_name(&mut dwarf.unit, child3, "child3");
3121 let child4 = dwarf.unit.add(root, constants::DW_TAG_subprogram);
3122 set_name(&mut dwarf.unit, child4, "child4");
3123 let grandchild4 = dwarf.unit.add(child4, constants::DW_TAG_variable);
3124 set_name(&mut dwarf.unit, grandchild4, "grandchild4");
3125 dwarf.unit.get_mut(child4).delete_child(grandchild4);
3126
3127 let mut sections = Sections::new(EndianVec::new(LittleEndian));
3128
3129 // Write DWARF data which should only include `child2`, `child3` and `child4`
3130 dwarf.write(&mut sections).unwrap();
3131
3132 let read_debug_info = read::DebugInfo::new(sections.debug_info.slice(), LittleEndian);
3133 let read_debug_abbrev = read::DebugAbbrev::new(sections.debug_abbrev.slice(), LittleEndian);
3134 let read_debug_str = read::DebugStr::new(sections.debug_str.slice(), LittleEndian);
3135 let read_unit = read_debug_info.units().next().unwrap().unwrap();
3136 let abbrevs = read_unit.abbreviations(&read_debug_abbrev).unwrap();
3137 let mut entries = read_unit.entries(&abbrevs);
3138 // root
3139 entries.next_dfs().unwrap().unwrap();
3140 // child2
3141 let (_, read_child2) = entries.next_dfs().unwrap().unwrap();
3142 check_name(read_child2, &read_debug_str, "child2");
3143 // child3
3144 let (_, read_child3) = entries.next_dfs().unwrap().unwrap();
3145 check_name(read_child3, &read_debug_str, "child3");
3146 // child4
3147 let (_, read_child4) = entries.next_dfs().unwrap().unwrap();
3148 check_name(read_child4, &read_debug_str, "child4");
3149 // There should be no more entries
3150 assert!(entries.next_dfs().unwrap().is_none());
3151 }
3152}
3153