1 use alloc::vec::Vec;
2 use std::ops::{Deref, DerefMut};
3 use std::{slice, usize};
4
5 use crate::common::{
6 DebugAbbrevOffset, DebugInfoOffset, DebugLineOffset, DebugMacinfoOffset, DebugMacroOffset,
7 DebugStrOffset, DebugTypeSignature, Encoding, Format, SectionId,
8 };
9 use crate::constants;
10 use crate::leb128::write::{sleb128_size, uleb128_size};
11 use 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
18 define_id!(UnitId, "An identifier for a unit in a `UnitTable`.");
19
20 define_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)]
24 pub struct UnitTable {
25 base_id: BaseId,
26 units: Vec<Unit>,
27 }
28
29 impl 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]
add(&mut self, unit: Unit) -> UnitId36 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]
count(&self) -> usize44 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]
id(&self, index: usize) -> UnitId54 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]
get(&self, id: UnitId) -> &Unit65 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]
get_mut(&mut self, id: UnitId) -> &mut Unit76 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`.
write<W: Writer>( &mut self, sections: &mut Sections<W>, line_strings: &DebugLineStrOffsets, strings: &DebugStrOffsets, ) -> Result<DebugInfoOffsets>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
write_section_refs<W: Writer>( references: &mut Vec<DebugInfoReference>, w: &mut W, offsets: &DebugInfoOffsets, ) -> Result<()>131 fn write_section_refs<W: Writer>(
132 references: &mut Vec<DebugInfoReference>,
133 w: &mut W,
134 offsets: &DebugInfoOffsets,
135 ) -> Result<()> {
136 for r in references.drain(..) {
137 let entry_offset = offsets.entry(r.unit, r.entry).0;
138 debug_assert_ne!(entry_offset, 0);
139 w.write_offset_at(r.offset, entry_offset, SectionId::DebugInfo, r.size)?;
140 }
141 Ok(())
142 }
143
144 /// A unit's debugging information.
145 #[derive(Debug)]
146 pub 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 implemention:
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
169 impl Unit {
170 /// Create a new `Unit`.
new(encoding: Encoding, line_program: LineProgram) -> Self171 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]
encoding(&self) -> Encoding195 pub fn encoding(&self) -> Encoding {
196 self.encoding
197 }
198
199 /// Return the DWARF version for this unit.
200 #[inline]
version(&self) -> u16201 pub fn version(&self) -> u16 {
202 self.encoding.version
203 }
204
205 /// Return the address size in bytes for this unit.
206 #[inline]
address_size(&self) -> u8207 pub fn address_size(&self) -> u8 {
208 self.encoding.address_size
209 }
210
211 /// Return the DWARF format for this unit.
212 #[inline]
format(&self) -> Format213 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]
count(&self) -> usize221 pub fn count(&self) -> usize {
222 self.entries.len()
223 }
224
225 /// Return the id of the root entry.
226 #[inline]
root(&self) -> UnitEntryId227 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]
add(&mut self, parent: UnitEntryId, tag: constants::DwTag) -> UnitEntryId239 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]
get(&self, id: UnitEntryId) -> &DebuggingInformationEntry250 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]
get_mut(&mut self, id: UnitEntryId) -> &mut DebuggingInformationEntry261 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.
line_program_in_use(&self) -> bool267 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.
write<W: Writer>( &mut self, sections: &mut Sections<W>, abbrev_offset: DebugAbbrevOffset, abbrevs: &mut AbbreviationTable, line_strings: &DebugLineStrOffsets, strings: &DebugStrOffsets, ) -> Result<UnitOffsets>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 abbrevs,
369 line_program,
370 line_strings,
371 strings,
372 &range_lists,
373 &loc_lists,
374 )?;
375
376 let length = (w.len() - length_base) as u64;
377 w.write_initial_length_at(length_offset, length, self.format())?;
378
379 for (offset, entry) in unit_refs {
380 // This does not need relocation.
381 w.write_udata_at(
382 offset.0,
383 offsets.unit_offset(entry),
384 self.format().word_size(),
385 )?;
386 }
387
388 Ok(offsets)
389 }
390
391 /// Reorder base types to come first so that typed stack operations
392 /// can get their offset.
reorder_base_types(&mut self)393 fn reorder_base_types(&mut self) {
394 let root = &self.entries[self.root.index];
395 let mut root_children = Vec::with_capacity(root.children.len());
396 for entry in &root.children {
397 if self.entries[entry.index].tag == constants::DW_TAG_base_type {
398 root_children.push(*entry);
399 }
400 }
401 for entry in &root.children {
402 if self.entries[entry.index].tag != constants::DW_TAG_base_type {
403 root_children.push(*entry);
404 }
405 }
406 self.entries[self.root.index].children = root_children;
407 }
408 }
409
410 /// A Debugging Information Entry (DIE).
411 ///
412 /// DIEs have a set of attributes and optionally have children DIEs as well.
413 ///
414 /// DIEs form a tree without any cycles. This is enforced by specifying the
415 /// parent when creating a DIE, and disallowing changes of parent.
416 #[derive(Debug)]
417 pub struct DebuggingInformationEntry {
418 id: UnitEntryId,
419 parent: Option<UnitEntryId>,
420 tag: constants::DwTag,
421 /// Whether to emit `DW_AT_sibling`.
422 sibling: bool,
423 attrs: Vec<Attribute>,
424 children: Vec<UnitEntryId>,
425 }
426
427 impl DebuggingInformationEntry {
428 /// Create a new `DebuggingInformationEntry`.
429 ///
430 /// # Panics
431 ///
432 /// Panics if `parent` is invalid.
433 #[allow(clippy::new_ret_no_self)]
new( base_id: BaseId, entries: &mut Vec<DebuggingInformationEntry>, parent: Option<UnitEntryId>, tag: constants::DwTag, ) -> UnitEntryId434 fn new(
435 base_id: BaseId,
436 entries: &mut Vec<DebuggingInformationEntry>,
437 parent: Option<UnitEntryId>,
438 tag: constants::DwTag,
439 ) -> UnitEntryId {
440 let id = UnitEntryId::new(base_id, entries.len());
441 entries.push(DebuggingInformationEntry {
442 id,
443 parent,
444 tag,
445 sibling: false,
446 attrs: Vec::new(),
447 children: Vec::new(),
448 });
449 if let Some(parent) = parent {
450 debug_assert_eq!(base_id, parent.base_id);
451 assert_ne!(parent, id);
452 entries[parent.index].children.push(id);
453 }
454 id
455 }
456
457 /// Return the id of this entry.
458 #[inline]
id(&self) -> UnitEntryId459 pub fn id(&self) -> UnitEntryId {
460 self.id
461 }
462
463 /// Return the parent of this entry.
464 #[inline]
parent(&self) -> Option<UnitEntryId>465 pub fn parent(&self) -> Option<UnitEntryId> {
466 self.parent
467 }
468
469 /// Return the tag of this entry.
470 #[inline]
tag(&self) -> constants::DwTag471 pub fn tag(&self) -> constants::DwTag {
472 self.tag
473 }
474
475 /// Return `true` if a `DW_AT_sibling` attribute will be emitted.
476 #[inline]
sibling(&self) -> bool477 pub fn sibling(&self) -> bool {
478 self.sibling
479 }
480
481 /// Set whether a `DW_AT_sibling` attribute will be emitted.
482 ///
483 /// The attribute will only be emitted if the DIE has children.
484 #[inline]
set_sibling(&mut self, sibling: bool)485 pub fn set_sibling(&mut self, sibling: bool) {
486 self.sibling = sibling;
487 }
488
489 /// Iterate over the attributes of this entry.
490 #[inline]
attrs(&self) -> slice::Iter<Attribute>491 pub fn attrs(&self) -> slice::Iter<Attribute> {
492 self.attrs.iter()
493 }
494
495 /// Iterate over the attributes of this entry for modification.
496 #[inline]
attrs_mut(&mut self) -> slice::IterMut<Attribute>497 pub fn attrs_mut(&mut self) -> slice::IterMut<Attribute> {
498 self.attrs.iter_mut()
499 }
500
501 /// Get an attribute.
get(&self, name: constants::DwAt) -> Option<&AttributeValue>502 pub fn get(&self, name: constants::DwAt) -> Option<&AttributeValue> {
503 self.attrs
504 .iter()
505 .find(|attr| attr.name == name)
506 .map(|attr| &attr.value)
507 }
508
509 /// Get an attribute for modification.
get_mut(&mut self, name: constants::DwAt) -> Option<&mut AttributeValue>510 pub fn get_mut(&mut self, name: constants::DwAt) -> Option<&mut AttributeValue> {
511 self.attrs
512 .iter_mut()
513 .find(|attr| attr.name == name)
514 .map(|attr| &mut attr.value)
515 }
516
517 /// Set an attribute.
518 ///
519 /// Replaces any existing attribute with the same name.
520 ///
521 /// # Panics
522 ///
523 /// Panics if `name` is `DW_AT_sibling`. Use `set_sibling` instead.
set(&mut self, name: constants::DwAt, value: AttributeValue)524 pub fn set(&mut self, name: constants::DwAt, value: AttributeValue) {
525 assert_ne!(name, constants::DW_AT_sibling);
526 if let Some(attr) = self.attrs.iter_mut().find(|attr| attr.name == name) {
527 attr.value = value;
528 return;
529 }
530 self.attrs.push(Attribute { name, value });
531 }
532
533 /// Delete an attribute.
534 ///
535 /// Replaces any existing attribute with the same name.
delete(&mut self, name: constants::DwAt)536 pub fn delete(&mut self, name: constants::DwAt) {
537 self.attrs.retain(|x| x.name != name);
538 }
539
540 /// Iterate over the children of this entry.
541 ///
542 /// Note: use `Unit::add` to add a new child to this entry.
543 #[inline]
children(&self) -> slice::Iter<UnitEntryId>544 pub fn children(&self) -> slice::Iter<UnitEntryId> {
545 self.children.iter()
546 }
547
548 /// Return the type abbreviation for this DIE.
abbreviation(&self, encoding: Encoding) -> Result<Abbreviation>549 fn abbreviation(&self, encoding: Encoding) -> Result<Abbreviation> {
550 let mut attrs = Vec::new();
551
552 if self.sibling && !self.children.is_empty() {
553 let form = match encoding.format {
554 Format::Dwarf32 => constants::DW_FORM_ref4,
555 Format::Dwarf64 => constants::DW_FORM_ref8,
556 };
557 attrs.push(AttributeSpecification::new(constants::DW_AT_sibling, form));
558 }
559
560 for attr in &self.attrs {
561 attrs.push(attr.specification(encoding)?);
562 }
563
564 Ok(Abbreviation::new(
565 self.tag,
566 !self.children.is_empty(),
567 attrs,
568 ))
569 }
570
calculate_offsets( &self, unit: &Unit, offset: &mut usize, offsets: &mut UnitOffsets, abbrevs: &mut AbbreviationTable, ) -> Result<()>571 fn calculate_offsets(
572 &self,
573 unit: &Unit,
574 offset: &mut usize,
575 offsets: &mut UnitOffsets,
576 abbrevs: &mut AbbreviationTable,
577 ) -> Result<()> {
578 offsets.entries[self.id.index].offset = DebugInfoOffset(*offset);
579 offsets.entries[self.id.index].abbrev = abbrevs.add(self.abbreviation(unit.encoding())?);
580 *offset += self.size(unit, offsets);
581 if !self.children.is_empty() {
582 for child in &self.children {
583 unit.entries[child.index].calculate_offsets(unit, offset, offsets, abbrevs)?;
584 }
585 // Null child
586 *offset += 1;
587 }
588 Ok(())
589 }
590
size(&self, unit: &Unit, offsets: &UnitOffsets) -> usize591 fn size(&self, unit: &Unit, offsets: &UnitOffsets) -> usize {
592 let mut size = uleb128_size(offsets.abbrev(self.id));
593 if self.sibling && !self.children.is_empty() {
594 size += unit.format().word_size() as usize;
595 }
596 for attr in &self.attrs {
597 size += attr.value.size(unit, offsets);
598 }
599 size
600 }
601
602 /// Write the entry to the given sections.
603 #[allow(clippy::too_many_arguments)]
write<W: Writer>( &self, w: &mut DebugInfo<W>, debug_info_refs: &mut Vec<DebugInfoReference>, unit_refs: &mut Vec<(DebugInfoOffset, UnitEntryId)>, unit: &Unit, offsets: &mut UnitOffsets, abbrevs: &mut AbbreviationTable, line_program: Option<DebugLineOffset>, line_strings: &DebugLineStrOffsets, strings: &DebugStrOffsets, range_lists: &RangeListOffsets, loc_lists: &LocationListOffsets, ) -> Result<()>604 fn write<W: Writer>(
605 &self,
606 w: &mut DebugInfo<W>,
607 debug_info_refs: &mut Vec<DebugInfoReference>,
608 unit_refs: &mut Vec<(DebugInfoOffset, UnitEntryId)>,
609 unit: &Unit,
610 offsets: &mut UnitOffsets,
611 abbrevs: &mut AbbreviationTable,
612 line_program: Option<DebugLineOffset>,
613 line_strings: &DebugLineStrOffsets,
614 strings: &DebugStrOffsets,
615 range_lists: &RangeListOffsets,
616 loc_lists: &LocationListOffsets,
617 ) -> Result<()> {
618 debug_assert_eq!(offsets.debug_info_offset(self.id), w.offset());
619 w.write_uleb128(offsets.abbrev(self.id))?;
620
621 let sibling_offset = if self.sibling && !self.children.is_empty() {
622 let offset = w.offset();
623 w.write_udata(0, unit.format().word_size())?;
624 Some(offset)
625 } else {
626 None
627 };
628
629 for attr in &self.attrs {
630 attr.value.write(
631 w,
632 debug_info_refs,
633 unit_refs,
634 unit,
635 offsets,
636 line_program,
637 line_strings,
638 strings,
639 range_lists,
640 loc_lists,
641 )?;
642 }
643
644 if !self.children.is_empty() {
645 for child in &self.children {
646 unit.entries[child.index].write(
647 w,
648 debug_info_refs,
649 unit_refs,
650 unit,
651 offsets,
652 abbrevs,
653 line_program,
654 line_strings,
655 strings,
656 range_lists,
657 loc_lists,
658 )?;
659 }
660 // Null child
661 w.write_u8(0)?;
662 }
663
664 if let Some(offset) = sibling_offset {
665 let next_offset = (w.offset().0 - offsets.unit.0) as u64;
666 // This does not need relocation.
667 w.write_udata_at(offset.0, next_offset, unit.format().word_size())?;
668 }
669 Ok(())
670 }
671 }
672
673 /// An attribute in a `DebuggingInformationEntry`, consisting of a name and
674 /// associated value.
675 #[derive(Debug, Clone, PartialEq, Eq)]
676 pub struct Attribute {
677 name: constants::DwAt,
678 value: AttributeValue,
679 }
680
681 impl Attribute {
682 /// Get the name of this attribute.
683 #[inline]
name(&self) -> constants::DwAt684 pub fn name(&self) -> constants::DwAt {
685 self.name
686 }
687
688 /// Get the value of this attribute.
689 #[inline]
get(&self) -> &AttributeValue690 pub fn get(&self) -> &AttributeValue {
691 &self.value
692 }
693
694 /// Set the value of this attribute.
695 #[inline]
set(&mut self, value: AttributeValue)696 pub fn set(&mut self, value: AttributeValue) {
697 self.value = value;
698 }
699
700 /// Return the type specification for this attribute.
specification(&self, encoding: Encoding) -> Result<AttributeSpecification>701 fn specification(&self, encoding: Encoding) -> Result<AttributeSpecification> {
702 Ok(AttributeSpecification::new(
703 self.name,
704 self.value.form(encoding)?,
705 ))
706 }
707 }
708
709 /// The value of an attribute in a `DebuggingInformationEntry`.
710 #[derive(Debug, Clone, PartialEq, Eq)]
711 pub enum AttributeValue {
712 /// "Refers to some location in the address space of the described program."
713 Address(Address),
714
715 /// A slice of an arbitrary number of bytes.
716 Block(Vec<u8>),
717
718 /// A one byte constant data value. How to interpret the byte depends on context.
719 ///
720 /// From section 7 of the standard: "Depending on context, it may be a
721 /// signed integer, an unsigned integer, a floating-point constant, or
722 /// anything else."
723 Data1(u8),
724
725 /// A two byte constant data value. How to interpret the bytes depends on context.
726 ///
727 /// This value will be converted to the target endian before writing.
728 ///
729 /// From section 7 of the standard: "Depending on context, it may be a
730 /// signed integer, an unsigned integer, a floating-point constant, or
731 /// anything else."
732 Data2(u16),
733
734 /// A four byte constant data value. How to interpret the bytes depends on context.
735 ///
736 /// This value will be converted to the target endian before writing.
737 ///
738 /// From section 7 of the standard: "Depending on context, it may be a
739 /// signed integer, an unsigned integer, a floating-point constant, or
740 /// anything else."
741 Data4(u32),
742
743 /// An eight byte constant data value. How to interpret the bytes depends on context.
744 ///
745 /// This value will be converted to the target endian before writing.
746 ///
747 /// From section 7 of the standard: "Depending on context, it may be a
748 /// signed integer, an unsigned integer, a floating-point constant, or
749 /// anything else."
750 Data8(u64),
751
752 /// A signed integer constant.
753 Sdata(i64),
754
755 /// An unsigned integer constant.
756 Udata(u64),
757
758 /// "The information bytes contain a DWARF expression (see Section 2.5) or
759 /// location description (see Section 2.6)."
760 Exprloc(Expression),
761
762 /// A boolean that indicates presence or absence of the attribute.
763 Flag(bool),
764
765 /// An attribute that is always present.
766 FlagPresent,
767
768 /// A reference to a `DebuggingInformationEntry` in this unit.
769 UnitRef(UnitEntryId),
770
771 /// A reference to a `DebuggingInformationEntry` in a potentially different unit.
772 DebugInfoRef(Reference),
773
774 /// An offset into the `.debug_info` section of the supplementary object file.
775 ///
776 /// The API does not currently assist with generating this offset.
777 /// This variant will be removed from the API once support for writing
778 /// supplementary object files is implemented.
779 DebugInfoRefSup(DebugInfoOffset),
780
781 /// A reference to a line number program.
782 LineProgramRef,
783
784 /// A reference to a location list.
785 LocationListRef(LocationListId),
786
787 /// An offset into the `.debug_macinfo` section.
788 ///
789 /// The API does not currently assist with generating this offset.
790 /// This variant will be removed from the API once support for writing
791 /// `.debug_macinfo` sections is implemented.
792 DebugMacinfoRef(DebugMacinfoOffset),
793
794 /// An offset into the `.debug_macro` section.
795 ///
796 /// The API does not currently assist with generating this offset.
797 /// This variant will be removed from the API once support for writing
798 /// `.debug_macro` sections is implemented.
799 DebugMacroRef(DebugMacroOffset),
800
801 /// A reference to a range list.
802 RangeListRef(RangeListId),
803
804 /// A type signature.
805 ///
806 /// The API does not currently assist with generating this signature.
807 /// This variant will be removed from the API once support for writing
808 /// `.debug_types` sections is implemented.
809 DebugTypesRef(DebugTypeSignature),
810
811 /// A reference to a string in the `.debug_str` section.
812 StringRef(StringId),
813
814 /// An offset into the `.debug_str` section of the supplementary object file.
815 ///
816 /// The API does not currently assist with generating this offset.
817 /// This variant will be removed from the API once support for writing
818 /// supplementary object files is implemented.
819 DebugStrRefSup(DebugStrOffset),
820
821 /// A reference to a string in the `.debug_line_str` section.
822 LineStringRef(LineStringId),
823
824 /// A slice of bytes representing a string. Must not include null bytes.
825 /// Not guaranteed to be UTF-8 or anything like that.
826 String(Vec<u8>),
827
828 /// The value of a `DW_AT_encoding` attribute.
829 Encoding(constants::DwAte),
830
831 /// The value of a `DW_AT_decimal_sign` attribute.
832 DecimalSign(constants::DwDs),
833
834 /// The value of a `DW_AT_endianity` attribute.
835 Endianity(constants::DwEnd),
836
837 /// The value of a `DW_AT_accessibility` attribute.
838 Accessibility(constants::DwAccess),
839
840 /// The value of a `DW_AT_visibility` attribute.
841 Visibility(constants::DwVis),
842
843 /// The value of a `DW_AT_virtuality` attribute.
844 Virtuality(constants::DwVirtuality),
845
846 /// The value of a `DW_AT_language` attribute.
847 Language(constants::DwLang),
848
849 /// The value of a `DW_AT_address_class` attribute.
850 AddressClass(constants::DwAddr),
851
852 /// The value of a `DW_AT_identifier_case` attribute.
853 IdentifierCase(constants::DwId),
854
855 /// The value of a `DW_AT_calling_convention` attribute.
856 CallingConvention(constants::DwCc),
857
858 /// The value of a `DW_AT_inline` attribute.
859 Inline(constants::DwInl),
860
861 /// The value of a `DW_AT_ordering` attribute.
862 Ordering(constants::DwOrd),
863
864 /// An index into the filename entries from the line number information
865 /// table for the unit containing this value.
866 FileIndex(Option<FileId>),
867 }
868
869 impl AttributeValue {
870 /// Return the form that will be used to encode this value.
form(&self, encoding: Encoding) -> Result<constants::DwForm>871 pub fn form(&self, encoding: Encoding) -> Result<constants::DwForm> {
872 // TODO: missing forms:
873 // - DW_FORM_indirect
874 // - DW_FORM_implicit_const
875 // - FW_FORM_block1/block2/block4
876 // - DW_FORM_str/strx1/strx2/strx3/strx4
877 // - DW_FORM_addrx/addrx1/addrx2/addrx3/addrx4
878 // - DW_FORM_data16
879 // - DW_FORM_line_strp
880 // - DW_FORM_loclistx
881 // - DW_FORM_rnglistx
882 let form = match *self {
883 AttributeValue::Address(_) => constants::DW_FORM_addr,
884 AttributeValue::Block(_) => constants::DW_FORM_block,
885 AttributeValue::Data1(_) => constants::DW_FORM_data1,
886 AttributeValue::Data2(_) => constants::DW_FORM_data2,
887 AttributeValue::Data4(_) => constants::DW_FORM_data4,
888 AttributeValue::Data8(_) => constants::DW_FORM_data8,
889 AttributeValue::Exprloc(_) => constants::DW_FORM_exprloc,
890 AttributeValue::Flag(_) => constants::DW_FORM_flag,
891 AttributeValue::FlagPresent => constants::DW_FORM_flag_present,
892 AttributeValue::UnitRef(_) => {
893 // Using a fixed size format lets us write a placeholder before we know
894 // the value.
895 match encoding.format {
896 Format::Dwarf32 => constants::DW_FORM_ref4,
897 Format::Dwarf64 => constants::DW_FORM_ref8,
898 }
899 }
900 AttributeValue::DebugInfoRef(_) => constants::DW_FORM_ref_addr,
901 AttributeValue::DebugInfoRefSup(_) => {
902 // TODO: should this depend on the size of supplementary section?
903 match encoding.format {
904 Format::Dwarf32 => constants::DW_FORM_ref_sup4,
905 Format::Dwarf64 => constants::DW_FORM_ref_sup8,
906 }
907 }
908 AttributeValue::LineProgramRef
909 | AttributeValue::LocationListRef(_)
910 | AttributeValue::DebugMacinfoRef(_)
911 | AttributeValue::DebugMacroRef(_)
912 | AttributeValue::RangeListRef(_) => {
913 if encoding.version == 2 || encoding.version == 3 {
914 match encoding.format {
915 Format::Dwarf32 => constants::DW_FORM_data4,
916 Format::Dwarf64 => constants::DW_FORM_data8,
917 }
918 } else {
919 constants::DW_FORM_sec_offset
920 }
921 }
922 AttributeValue::DebugTypesRef(_) => constants::DW_FORM_ref_sig8,
923 AttributeValue::StringRef(_) => constants::DW_FORM_strp,
924 AttributeValue::DebugStrRefSup(_) => constants::DW_FORM_strp_sup,
925 AttributeValue::LineStringRef(_) => constants::DW_FORM_line_strp,
926 AttributeValue::String(_) => constants::DW_FORM_string,
927 AttributeValue::Encoding(_)
928 | AttributeValue::DecimalSign(_)
929 | AttributeValue::Endianity(_)
930 | AttributeValue::Accessibility(_)
931 | AttributeValue::Visibility(_)
932 | AttributeValue::Virtuality(_)
933 | AttributeValue::Language(_)
934 | AttributeValue::AddressClass(_)
935 | AttributeValue::IdentifierCase(_)
936 | AttributeValue::CallingConvention(_)
937 | AttributeValue::Inline(_)
938 | AttributeValue::Ordering(_)
939 | AttributeValue::FileIndex(_)
940 | AttributeValue::Udata(_) => constants::DW_FORM_udata,
941 AttributeValue::Sdata(_) => constants::DW_FORM_sdata,
942 };
943 Ok(form)
944 }
945
size(&self, unit: &Unit, offsets: &UnitOffsets) -> usize946 fn size(&self, unit: &Unit, offsets: &UnitOffsets) -> usize {
947 macro_rules! debug_assert_form {
948 ($form:expr) => {
949 debug_assert_eq!(self.form(unit.encoding()).unwrap(), $form)
950 };
951 }
952 match *self {
953 AttributeValue::Address(_) => {
954 debug_assert_form!(constants::DW_FORM_addr);
955 unit.address_size() as usize
956 }
957 AttributeValue::Block(ref val) => {
958 debug_assert_form!(constants::DW_FORM_block);
959 uleb128_size(val.len() as u64) + val.len()
960 }
961 AttributeValue::Data1(_) => {
962 debug_assert_form!(constants::DW_FORM_data1);
963 1
964 }
965 AttributeValue::Data2(_) => {
966 debug_assert_form!(constants::DW_FORM_data2);
967 2
968 }
969 AttributeValue::Data4(_) => {
970 debug_assert_form!(constants::DW_FORM_data4);
971 4
972 }
973 AttributeValue::Data8(_) => {
974 debug_assert_form!(constants::DW_FORM_data8);
975 8
976 }
977 AttributeValue::Sdata(val) => {
978 debug_assert_form!(constants::DW_FORM_sdata);
979 sleb128_size(val)
980 }
981 AttributeValue::Udata(val) => {
982 debug_assert_form!(constants::DW_FORM_udata);
983 uleb128_size(val)
984 }
985 AttributeValue::Exprloc(ref val) => {
986 debug_assert_form!(constants::DW_FORM_exprloc);
987 let size = val.size(unit.encoding(), Some(offsets));
988 uleb128_size(size as u64) + size
989 }
990 AttributeValue::Flag(_) => {
991 debug_assert_form!(constants::DW_FORM_flag);
992 1
993 }
994 AttributeValue::FlagPresent => {
995 debug_assert_form!(constants::DW_FORM_flag_present);
996 0
997 }
998 AttributeValue::UnitRef(_) => {
999 match unit.format() {
1000 Format::Dwarf32 => debug_assert_form!(constants::DW_FORM_ref4),
1001 Format::Dwarf64 => debug_assert_form!(constants::DW_FORM_ref8),
1002 }
1003 unit.format().word_size() as usize
1004 }
1005 AttributeValue::DebugInfoRef(_) => {
1006 debug_assert_form!(constants::DW_FORM_ref_addr);
1007 if unit.version() == 2 {
1008 unit.address_size() as usize
1009 } else {
1010 unit.format().word_size() as usize
1011 }
1012 }
1013 AttributeValue::DebugInfoRefSup(_) => {
1014 match unit.format() {
1015 Format::Dwarf32 => debug_assert_form!(constants::DW_FORM_ref_sup4),
1016 Format::Dwarf64 => debug_assert_form!(constants::DW_FORM_ref_sup8),
1017 }
1018 unit.format().word_size() as usize
1019 }
1020 AttributeValue::LineProgramRef => {
1021 if unit.version() >= 4 {
1022 debug_assert_form!(constants::DW_FORM_sec_offset);
1023 }
1024 unit.format().word_size() as usize
1025 }
1026 AttributeValue::LocationListRef(_) => {
1027 if unit.version() >= 4 {
1028 debug_assert_form!(constants::DW_FORM_sec_offset);
1029 }
1030 unit.format().word_size() as usize
1031 }
1032 AttributeValue::DebugMacinfoRef(_) => {
1033 if unit.version() >= 4 {
1034 debug_assert_form!(constants::DW_FORM_sec_offset);
1035 }
1036 unit.format().word_size() as usize
1037 }
1038 AttributeValue::DebugMacroRef(_) => {
1039 if unit.version() >= 4 {
1040 debug_assert_form!(constants::DW_FORM_sec_offset);
1041 }
1042 unit.format().word_size() as usize
1043 }
1044 AttributeValue::RangeListRef(_) => {
1045 if unit.version() >= 4 {
1046 debug_assert_form!(constants::DW_FORM_sec_offset);
1047 }
1048 unit.format().word_size() as usize
1049 }
1050 AttributeValue::DebugTypesRef(_) => {
1051 debug_assert_form!(constants::DW_FORM_ref_sig8);
1052 8
1053 }
1054 AttributeValue::StringRef(_) => {
1055 debug_assert_form!(constants::DW_FORM_strp);
1056 unit.format().word_size() as usize
1057 }
1058 AttributeValue::DebugStrRefSup(_) => {
1059 debug_assert_form!(constants::DW_FORM_strp_sup);
1060 unit.format().word_size() as usize
1061 }
1062 AttributeValue::LineStringRef(_) => {
1063 debug_assert_form!(constants::DW_FORM_line_strp);
1064 unit.format().word_size() as usize
1065 }
1066 AttributeValue::String(ref val) => {
1067 debug_assert_form!(constants::DW_FORM_string);
1068 val.len() + 1
1069 }
1070 AttributeValue::Encoding(val) => {
1071 debug_assert_form!(constants::DW_FORM_udata);
1072 uleb128_size(val.0 as u64)
1073 }
1074 AttributeValue::DecimalSign(val) => {
1075 debug_assert_form!(constants::DW_FORM_udata);
1076 uleb128_size(val.0 as u64)
1077 }
1078 AttributeValue::Endianity(val) => {
1079 debug_assert_form!(constants::DW_FORM_udata);
1080 uleb128_size(val.0 as u64)
1081 }
1082 AttributeValue::Accessibility(val) => {
1083 debug_assert_form!(constants::DW_FORM_udata);
1084 uleb128_size(val.0 as u64)
1085 }
1086 AttributeValue::Visibility(val) => {
1087 debug_assert_form!(constants::DW_FORM_udata);
1088 uleb128_size(val.0 as u64)
1089 }
1090 AttributeValue::Virtuality(val) => {
1091 debug_assert_form!(constants::DW_FORM_udata);
1092 uleb128_size(val.0 as u64)
1093 }
1094 AttributeValue::Language(val) => {
1095 debug_assert_form!(constants::DW_FORM_udata);
1096 uleb128_size(val.0 as u64)
1097 }
1098 AttributeValue::AddressClass(val) => {
1099 debug_assert_form!(constants::DW_FORM_udata);
1100 uleb128_size(val.0 as u64)
1101 }
1102 AttributeValue::IdentifierCase(val) => {
1103 debug_assert_form!(constants::DW_FORM_udata);
1104 uleb128_size(val.0 as u64)
1105 }
1106 AttributeValue::CallingConvention(val) => {
1107 debug_assert_form!(constants::DW_FORM_udata);
1108 uleb128_size(val.0 as u64)
1109 }
1110 AttributeValue::Inline(val) => {
1111 debug_assert_form!(constants::DW_FORM_udata);
1112 uleb128_size(val.0 as u64)
1113 }
1114 AttributeValue::Ordering(val) => {
1115 debug_assert_form!(constants::DW_FORM_udata);
1116 uleb128_size(val.0 as u64)
1117 }
1118 AttributeValue::FileIndex(val) => {
1119 debug_assert_form!(constants::DW_FORM_udata);
1120 uleb128_size(val.map(FileId::raw).unwrap_or(0))
1121 }
1122 }
1123 }
1124
1125 /// Write the attribute value to the given sections.
1126 #[allow(clippy::cyclomatic_complexity, clippy::too_many_arguments)]
write<W: Writer>( &self, w: &mut DebugInfo<W>, debug_info_refs: &mut Vec<DebugInfoReference>, unit_refs: &mut Vec<(DebugInfoOffset, UnitEntryId)>, unit: &Unit, offsets: &UnitOffsets, line_program: Option<DebugLineOffset>, line_strings: &DebugLineStrOffsets, strings: &DebugStrOffsets, range_lists: &RangeListOffsets, loc_lists: &LocationListOffsets, ) -> Result<()>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
1366 define_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)]
1374 pub struct DebugInfoOffsets {
1375 base_id: BaseId,
1376 units: Vec<UnitOffsets>,
1377 }
1378
1379 impl DebugInfoOffsets {
1380 #[cfg(test)]
unit_offsets(&self, unit: UnitId) -> &UnitOffsets1381 pub(crate) fn unit_offsets(&self, unit: UnitId) -> &UnitOffsets {
1382 debug_assert_eq!(self.base_id, unit.base_id);
1383 &self.units[unit.index]
1384 }
1385
1386 /// Get the `.debug_info` section offset for the given unit.
1387 #[inline]
unit(&self, unit: UnitId) -> DebugInfoOffset1388 pub fn unit(&self, unit: UnitId) -> DebugInfoOffset {
1389 debug_assert_eq!(self.base_id, unit.base_id);
1390 self.units[unit.index].unit
1391 }
1392
1393 /// Get the `.debug_info` section offset for the given entry.
1394 #[inline]
entry(&self, unit: UnitId, entry: UnitEntryId) -> DebugInfoOffset1395 pub fn entry(&self, unit: UnitId, entry: UnitEntryId) -> DebugInfoOffset {
1396 debug_assert_eq!(self.base_id, unit.base_id);
1397 self.units[unit.index].debug_info_offset(entry)
1398 }
1399 }
1400
1401 /// The section offsets of all elements of a unit within a `.debug_info` section.
1402 #[derive(Debug)]
1403 pub(crate) struct UnitOffsets {
1404 base_id: BaseId,
1405 unit: DebugInfoOffset,
1406 entries: Vec<EntryOffset>,
1407 }
1408
1409 impl UnitOffsets {
1410 #[cfg(test)]
none() -> Self1411 fn none() -> Self {
1412 UnitOffsets {
1413 base_id: BaseId::default(),
1414 unit: DebugInfoOffset(0),
1415 entries: Vec::new(),
1416 }
1417 }
1418
1419 /// Get the .debug_info offset for the given entry.
1420 #[inline]
debug_info_offset(&self, entry: UnitEntryId) -> DebugInfoOffset1421 pub(crate) fn debug_info_offset(&self, entry: UnitEntryId) -> DebugInfoOffset {
1422 debug_assert_eq!(self.base_id, entry.base_id);
1423 let offset = self.entries[entry.index].offset;
1424 debug_assert_ne!(offset.0, 0);
1425 offset
1426 }
1427
1428 /// Get the unit offset for the given entry.
1429 #[inline]
unit_offset(&self, entry: UnitEntryId) -> u641430 pub(crate) fn unit_offset(&self, entry: UnitEntryId) -> u64 {
1431 let offset = self.debug_info_offset(entry);
1432 (offset.0 - self.unit.0) as u64
1433 }
1434
1435 /// Get the abbreviation code for the given entry.
1436 #[inline]
abbrev(&self, entry: UnitEntryId) -> u641437 pub(crate) fn abbrev(&self, entry: UnitEntryId) -> u64 {
1438 debug_assert_eq!(self.base_id, entry.base_id);
1439 self.entries[entry.index].abbrev
1440 }
1441 }
1442
1443 #[derive(Debug, Clone, Copy)]
1444 pub(crate) struct EntryOffset {
1445 offset: DebugInfoOffset,
1446 abbrev: u64,
1447 }
1448
1449 impl EntryOffset {
none() -> Self1450 fn none() -> Self {
1451 EntryOffset {
1452 offset: DebugInfoOffset(0),
1453 abbrev: 0,
1454 }
1455 }
1456 }
1457
1458 /// A reference to a `.debug_info` entry that has yet to be resolved.
1459 #[derive(Debug, Clone, Copy)]
1460 pub(crate) struct DebugInfoReference {
1461 /// The offset within the section of the reference.
1462 pub offset: usize,
1463 /// The size of the reference.
1464 pub size: u8,
1465 /// The unit containing the entry.
1466 pub unit: UnitId,
1467 /// The entry being referenced.
1468 pub entry: UnitEntryId,
1469 }
1470
1471 #[cfg(feature = "read")]
1472 pub(crate) mod convert {
1473 use super::*;
1474 use crate::common::UnitSectionOffset;
1475 use crate::read::{self, Reader};
1476 use crate::write::{self, ConvertError, ConvertResult, LocationList, RangeList};
1477 use std::collections::HashMap;
1478
1479 pub(crate) struct ConvertUnit<R: Reader<Offset = usize>> {
1480 from_unit: read::Unit<R>,
1481 base_id: BaseId,
1482 encoding: Encoding,
1483 entries: Vec<DebuggingInformationEntry>,
1484 entry_offsets: Vec<read::UnitOffset>,
1485 root: UnitEntryId,
1486 }
1487
1488 pub(crate) struct ConvertUnitContext<'a, R: Reader<Offset = usize>> {
1489 pub dwarf: &'a read::Dwarf<R>,
1490 pub unit: &'a read::Unit<R>,
1491 pub line_strings: &'a mut write::LineStringTable,
1492 pub strings: &'a mut write::StringTable,
1493 pub ranges: &'a mut write::RangeListTable,
1494 pub locations: &'a mut write::LocationListTable,
1495 pub convert_address: &'a dyn Fn(u64) -> Option<Address>,
1496 pub base_address: Address,
1497 pub line_program_offset: Option<DebugLineOffset>,
1498 pub line_program_files: Vec<FileId>,
1499 pub entry_ids: &'a HashMap<UnitSectionOffset, (UnitId, UnitEntryId)>,
1500 }
1501
1502 impl UnitTable {
1503 /// Create a unit table by reading the data in the given sections.
1504 ///
1505 /// This also updates the given tables with the values that are referenced from
1506 /// attributes in this section.
1507 ///
1508 /// `convert_address` is a function to convert read addresses into the `Address`
1509 /// type. For non-relocatable addresses, this function may simply return
1510 /// `Address::Constant(address)`. For relocatable addresses, it is the caller's
1511 /// responsibility to determine the symbol and addend corresponding to the address
1512 /// and return `Address::Symbol { symbol, addend }`.
from<R: Reader<Offset = usize>>( dwarf: &read::Dwarf<R>, line_strings: &mut write::LineStringTable, strings: &mut write::StringTable, convert_address: &dyn Fn(u64) -> Option<Address>, ) -> ConvertResult<UnitTable>1513 pub fn from<R: Reader<Offset = usize>>(
1514 dwarf: &read::Dwarf<R>,
1515 line_strings: &mut write::LineStringTable,
1516 strings: &mut write::StringTable,
1517 convert_address: &dyn Fn(u64) -> Option<Address>,
1518 ) -> ConvertResult<UnitTable> {
1519 let base_id = BaseId::default();
1520 let mut unit_entries = Vec::new();
1521 let mut entry_ids = HashMap::new();
1522
1523 let mut from_units = dwarf.units();
1524 while let Some(from_unit) = from_units.next()? {
1525 let unit_id = UnitId::new(base_id, unit_entries.len());
1526 unit_entries.push(Unit::convert_entries(
1527 from_unit,
1528 unit_id,
1529 &mut entry_ids,
1530 dwarf,
1531 )?);
1532 }
1533
1534 // Attributes must be converted in a separate pass so that we can handle
1535 // references to other compilation units.
1536 let mut units = Vec::new();
1537 for unit_entries in unit_entries.drain(..) {
1538 units.push(Unit::convert_attributes(
1539 unit_entries,
1540 &entry_ids,
1541 dwarf,
1542 line_strings,
1543 strings,
1544 convert_address,
1545 )?);
1546 }
1547
1548 Ok(UnitTable { base_id, units })
1549 }
1550 }
1551
1552 impl Unit {
1553 /// Create a unit by reading the data in the input sections.
1554 ///
1555 /// Does not add entry attributes.
1556 #[allow(clippy::too_many_arguments)]
convert_entries<R: Reader<Offset = usize>>( from_header: read::CompilationUnitHeader<R>, unit_id: UnitId, entry_ids: &mut HashMap<UnitSectionOffset, (UnitId, UnitEntryId)>, dwarf: &read::Dwarf<R>, ) -> ConvertResult<ConvertUnit<R>>1557 pub(crate) fn convert_entries<R: Reader<Offset = usize>>(
1558 from_header: read::CompilationUnitHeader<R>,
1559 unit_id: UnitId,
1560 entry_ids: &mut HashMap<UnitSectionOffset, (UnitId, UnitEntryId)>,
1561 dwarf: &read::Dwarf<R>,
1562 ) -> ConvertResult<ConvertUnit<R>> {
1563 let base_id = BaseId::default();
1564
1565 let from_unit = dwarf.unit(from_header)?;
1566 let encoding = from_unit.encoding();
1567
1568 let mut entries = Vec::new();
1569 let mut entry_offsets = Vec::new();
1570
1571 let mut from_tree = from_unit.entries_tree(None)?;
1572 let from_root = from_tree.root()?;
1573 let root = DebuggingInformationEntry::convert_entry(
1574 from_root,
1575 &from_unit,
1576 base_id,
1577 &mut entries,
1578 &mut entry_offsets,
1579 entry_ids,
1580 None,
1581 unit_id,
1582 )?;
1583
1584 Ok(ConvertUnit {
1585 from_unit,
1586 base_id,
1587 encoding,
1588 entries,
1589 entry_offsets,
1590 root,
1591 })
1592 }
1593
1594 /// Create entry attributes by reading the data in the input sections.
convert_attributes<R: Reader<Offset = usize>>( unit: ConvertUnit<R>, entry_ids: &HashMap<UnitSectionOffset, (UnitId, UnitEntryId)>, dwarf: &read::Dwarf<R>, line_strings: &mut write::LineStringTable, strings: &mut write::StringTable, convert_address: &dyn Fn(u64) -> Option<Address>, ) -> ConvertResult<Unit>1595 fn convert_attributes<R: Reader<Offset = usize>>(
1596 unit: ConvertUnit<R>,
1597 entry_ids: &HashMap<UnitSectionOffset, (UnitId, UnitEntryId)>,
1598 dwarf: &read::Dwarf<R>,
1599 line_strings: &mut write::LineStringTable,
1600 strings: &mut write::StringTable,
1601 convert_address: &dyn Fn(u64) -> Option<Address>,
1602 ) -> ConvertResult<Unit> {
1603 let from_unit = unit.from_unit;
1604 let base_address =
1605 convert_address(from_unit.low_pc).ok_or(ConvertError::InvalidAddress)?;
1606
1607 let (line_program_offset, line_program, line_program_files) =
1608 match from_unit.line_program {
1609 Some(ref from_program) => {
1610 let from_program = from_program.clone();
1611 let line_program_offset = from_program.header().offset();
1612 let (line_program, line_program_files) = LineProgram::from(
1613 from_program,
1614 dwarf,
1615 line_strings,
1616 strings,
1617 convert_address,
1618 )?;
1619 (Some(line_program_offset), line_program, line_program_files)
1620 }
1621 None => (None, LineProgram::none(), Vec::new()),
1622 };
1623
1624 let mut ranges = RangeListTable::default();
1625 let mut locations = LocationListTable::default();
1626
1627 let mut context = ConvertUnitContext {
1628 entry_ids,
1629 dwarf,
1630 unit: &from_unit,
1631 line_strings,
1632 strings,
1633 ranges: &mut ranges,
1634 locations: &mut locations,
1635 convert_address,
1636 base_address,
1637 line_program_offset,
1638 line_program_files,
1639 };
1640
1641 let mut entries = unit.entries;
1642 for entry in &mut entries {
1643 entry.convert_attributes(&mut context, &unit.entry_offsets)?;
1644 }
1645
1646 Ok(Unit {
1647 base_id: unit.base_id,
1648 encoding: unit.encoding,
1649 line_program,
1650 ranges,
1651 locations,
1652 entries,
1653 root: unit.root,
1654 })
1655 }
1656 }
1657
1658 impl DebuggingInformationEntry {
1659 /// Create an entry by reading the data in the input sections.
1660 ///
1661 /// Does not add the entry attributes.
convert_entry<R: Reader<Offset = usize>>( from: read::EntriesTreeNode<R>, from_unit: &read::Unit<R>, base_id: BaseId, entries: &mut Vec<DebuggingInformationEntry>, entry_offsets: &mut Vec<read::UnitOffset>, entry_ids: &mut HashMap<UnitSectionOffset, (UnitId, UnitEntryId)>, parent: Option<UnitEntryId>, unit_id: UnitId, ) -> ConvertResult<UnitEntryId>1662 fn convert_entry<R: Reader<Offset = usize>>(
1663 from: read::EntriesTreeNode<R>,
1664 from_unit: &read::Unit<R>,
1665 base_id: BaseId,
1666 entries: &mut Vec<DebuggingInformationEntry>,
1667 entry_offsets: &mut Vec<read::UnitOffset>,
1668 entry_ids: &mut HashMap<UnitSectionOffset, (UnitId, UnitEntryId)>,
1669 parent: Option<UnitEntryId>,
1670 unit_id: UnitId,
1671 ) -> ConvertResult<UnitEntryId> {
1672 let from_entry = from.entry();
1673 let id = DebuggingInformationEntry::new(base_id, entries, parent, from_entry.tag());
1674 let offset = from_entry.offset();
1675 entry_offsets.push(offset);
1676 entry_ids.insert(offset.to_unit_section_offset(from_unit), (unit_id, id));
1677
1678 let mut from_children = from.children();
1679 while let Some(from_child) = from_children.next()? {
1680 DebuggingInformationEntry::convert_entry(
1681 from_child,
1682 from_unit,
1683 base_id,
1684 entries,
1685 entry_offsets,
1686 entry_ids,
1687 Some(id),
1688 unit_id,
1689 )?;
1690 }
1691 Ok(id)
1692 }
1693
1694 /// Create an entry's attributes by reading the data in the input sections.
convert_attributes<R: Reader<Offset = usize>>( &mut self, context: &mut ConvertUnitContext<R>, entry_offsets: &[read::UnitOffset], ) -> ConvertResult<()>1695 fn convert_attributes<R: Reader<Offset = usize>>(
1696 &mut self,
1697 context: &mut ConvertUnitContext<R>,
1698 entry_offsets: &[read::UnitOffset],
1699 ) -> ConvertResult<()> {
1700 let offset = entry_offsets[self.id.index];
1701 let from = context.unit.entry(offset)?;
1702 let mut from_attrs = from.attrs();
1703 while let Some(from_attr) = from_attrs.next()? {
1704 if from_attr.name() == constants::DW_AT_sibling {
1705 // This may point to a null entry, so we have to treat it differently.
1706 self.set_sibling(true);
1707 } else if let Some(attr) = Attribute::from(context, &from_attr)? {
1708 self.set(attr.name, attr.value);
1709 }
1710 }
1711 Ok(())
1712 }
1713 }
1714
1715 impl Attribute {
1716 /// Create an attribute by reading the data in the given sections.
from<R: Reader<Offset = usize>>( context: &mut ConvertUnitContext<R>, from: &read::Attribute<R>, ) -> ConvertResult<Option<Attribute>>1717 pub(crate) fn from<R: Reader<Offset = usize>>(
1718 context: &mut ConvertUnitContext<R>,
1719 from: &read::Attribute<R>,
1720 ) -> ConvertResult<Option<Attribute>> {
1721 let value = AttributeValue::from(context, from.value())?;
1722 Ok(value.map(|value| Attribute {
1723 name: from.name(),
1724 value,
1725 }))
1726 }
1727 }
1728
1729 impl AttributeValue {
1730 /// Create an attribute value by reading the data in the given sections.
from<R: Reader<Offset = usize>>( context: &mut ConvertUnitContext<R>, from: read::AttributeValue<R>, ) -> ConvertResult<Option<AttributeValue>>1731 pub(crate) fn from<R: Reader<Offset = usize>>(
1732 context: &mut ConvertUnitContext<R>,
1733 from: read::AttributeValue<R>,
1734 ) -> ConvertResult<Option<AttributeValue>> {
1735 let to = match from {
1736 read::AttributeValue::Addr(val) => match (context.convert_address)(val) {
1737 Some(val) => AttributeValue::Address(val),
1738 None => return Err(ConvertError::InvalidAddress),
1739 },
1740 read::AttributeValue::Block(r) => AttributeValue::Block(r.to_slice()?.into()),
1741 read::AttributeValue::Data1(val) => AttributeValue::Data1(val),
1742 read::AttributeValue::Data2(val) => AttributeValue::Data2(val),
1743 read::AttributeValue::Data4(val) => AttributeValue::Data4(val),
1744 read::AttributeValue::Data8(val) => AttributeValue::Data8(val),
1745 read::AttributeValue::Sdata(val) => AttributeValue::Sdata(val),
1746 read::AttributeValue::Udata(val) => AttributeValue::Udata(val),
1747 read::AttributeValue::Exprloc(expression) => {
1748 let expression = Expression::from(
1749 expression,
1750 context.unit.encoding(),
1751 Some(context.dwarf),
1752 Some(context.unit),
1753 Some(context.entry_ids),
1754 context.convert_address,
1755 )?;
1756 AttributeValue::Exprloc(expression)
1757 }
1758 // TODO: it would be nice to preserve the flag form.
1759 read::AttributeValue::Flag(val) => AttributeValue::Flag(val),
1760 read::AttributeValue::DebugAddrBase(_base) => {
1761 // We convert all address indices to addresses,
1762 // so this is unneeded.
1763 return Ok(None);
1764 }
1765 read::AttributeValue::DebugAddrIndex(index) => {
1766 let val = context.dwarf.address(context.unit, index)?;
1767 match (context.convert_address)(val) {
1768 Some(val) => AttributeValue::Address(val),
1769 None => return Err(ConvertError::InvalidAddress),
1770 }
1771 }
1772 read::AttributeValue::UnitRef(val) => {
1773 if !context.unit.header.is_valid_offset(val) {
1774 return Err(ConvertError::InvalidUnitRef);
1775 }
1776 let id = context
1777 .entry_ids
1778 .get(&val.to_unit_section_offset(context.unit))
1779 .ok_or(ConvertError::InvalidUnitRef)?;
1780 AttributeValue::UnitRef(id.1)
1781 }
1782 read::AttributeValue::DebugInfoRef(val) => {
1783 // TODO: support relocation of this value
1784 let id = context
1785 .entry_ids
1786 .get(&UnitSectionOffset::DebugInfoOffset(val))
1787 .ok_or(ConvertError::InvalidDebugInfoRef)?;
1788 AttributeValue::DebugInfoRef(Reference::Entry(id.0, id.1))
1789 }
1790 read::AttributeValue::DebugInfoRefSup(val) => AttributeValue::DebugInfoRefSup(val),
1791 read::AttributeValue::DebugLineRef(val) => {
1792 // There should only be the line program in the CU DIE which we've already
1793 // converted, so check if it matches that.
1794 if Some(val) == context.line_program_offset {
1795 AttributeValue::LineProgramRef
1796 } else {
1797 return Err(ConvertError::InvalidLineRef);
1798 }
1799 }
1800 read::AttributeValue::DebugMacinfoRef(val) => AttributeValue::DebugMacinfoRef(val),
1801 read::AttributeValue::DebugMacroRef(val) => AttributeValue::DebugMacroRef(val),
1802 read::AttributeValue::LocationListsRef(val) => {
1803 let iter = context
1804 .dwarf
1805 .locations
1806 .raw_locations(val, context.unit.encoding())?;
1807 let loc_list = LocationList::from(iter, context)?;
1808 let loc_id = context.locations.add(loc_list);
1809 AttributeValue::LocationListRef(loc_id)
1810 }
1811 read::AttributeValue::DebugLocListsBase(_base) => {
1812 // We convert all location list indices to offsets,
1813 // so this is unneeded.
1814 return Ok(None);
1815 }
1816 read::AttributeValue::DebugLocListsIndex(index) => {
1817 let offset = context.dwarf.locations_offset(context.unit, index)?;
1818 let iter = context
1819 .dwarf
1820 .locations
1821 .raw_locations(offset, context.unit.encoding())?;
1822 let loc_list = LocationList::from(iter, context)?;
1823 let loc_id = context.locations.add(loc_list);
1824 AttributeValue::LocationListRef(loc_id)
1825 }
1826 read::AttributeValue::RangeListsRef(val) => {
1827 let iter = context
1828 .dwarf
1829 .ranges
1830 .raw_ranges(val, context.unit.encoding())?;
1831 let range_list = RangeList::from(iter, context)?;
1832 let range_id = context.ranges.add(range_list);
1833 AttributeValue::RangeListRef(range_id)
1834 }
1835 read::AttributeValue::DebugRngListsBase(_base) => {
1836 // We convert all range list indices to offsets,
1837 // so this is unneeded.
1838 return Ok(None);
1839 }
1840 read::AttributeValue::DebugRngListsIndex(index) => {
1841 let offset = context.dwarf.ranges_offset(context.unit, index)?;
1842 let iter = context
1843 .dwarf
1844 .ranges
1845 .raw_ranges(offset, context.unit.encoding())?;
1846 let range_list = RangeList::from(iter, context)?;
1847 let range_id = context.ranges.add(range_list);
1848 AttributeValue::RangeListRef(range_id)
1849 }
1850 read::AttributeValue::DebugTypesRef(val) => AttributeValue::DebugTypesRef(val),
1851 read::AttributeValue::DebugStrRef(offset) => {
1852 let r = context.dwarf.string(offset)?;
1853 let id = context.strings.add(r.to_slice()?);
1854 AttributeValue::StringRef(id)
1855 }
1856 read::AttributeValue::DebugStrRefSup(val) => AttributeValue::DebugStrRefSup(val),
1857 read::AttributeValue::DebugStrOffsetsBase(_base) => {
1858 // We convert all string offsets to `.debug_str` references,
1859 // so this is unneeded.
1860 return Ok(None);
1861 }
1862 read::AttributeValue::DebugStrOffsetsIndex(index) => {
1863 let offset = context.dwarf.string_offset(context.unit, index)?;
1864 let r = context.dwarf.string(offset)?;
1865 let id = context.strings.add(r.to_slice()?);
1866 AttributeValue::StringRef(id)
1867 }
1868 read::AttributeValue::DebugLineStrRef(offset) => {
1869 let r = context.dwarf.line_string(offset)?;
1870 let id = context.line_strings.add(r.to_slice()?);
1871 AttributeValue::LineStringRef(id)
1872 }
1873 read::AttributeValue::String(r) => AttributeValue::String(r.to_slice()?.into()),
1874 read::AttributeValue::Encoding(val) => AttributeValue::Encoding(val),
1875 read::AttributeValue::DecimalSign(val) => AttributeValue::DecimalSign(val),
1876 read::AttributeValue::Endianity(val) => AttributeValue::Endianity(val),
1877 read::AttributeValue::Accessibility(val) => AttributeValue::Accessibility(val),
1878 read::AttributeValue::Visibility(val) => AttributeValue::Visibility(val),
1879 read::AttributeValue::Virtuality(val) => AttributeValue::Virtuality(val),
1880 read::AttributeValue::Language(val) => AttributeValue::Language(val),
1881 read::AttributeValue::AddressClass(val) => AttributeValue::AddressClass(val),
1882 read::AttributeValue::IdentifierCase(val) => AttributeValue::IdentifierCase(val),
1883 read::AttributeValue::CallingConvention(val) => {
1884 AttributeValue::CallingConvention(val)
1885 }
1886 read::AttributeValue::Inline(val) => AttributeValue::Inline(val),
1887 read::AttributeValue::Ordering(val) => AttributeValue::Ordering(val),
1888 read::AttributeValue::FileIndex(val) => {
1889 if val == 0 {
1890 // 0 means not specified, even for version 5.
1891 AttributeValue::FileIndex(None)
1892 } else {
1893 match context.line_program_files.get(val as usize) {
1894 Some(id) => AttributeValue::FileIndex(Some(*id)),
1895 None => return Err(ConvertError::InvalidFileIndex),
1896 }
1897 }
1898 }
1899 // Should always be a more specific section reference.
1900 read::AttributeValue::SecOffset(_) => {
1901 return Err(ConvertError::InvalidAttributeValue);
1902 }
1903 };
1904 Ok(Some(to))
1905 }
1906 }
1907 }
1908
1909 #[cfg(test)]
1910 #[cfg(feature = "read")]
1911 mod tests {
1912 use super::*;
1913 use crate::common::{
1914 DebugAddrBase, DebugLocListsBase, DebugRngListsBase, DebugStrOffsetsBase, LineEncoding,
1915 UnitSectionOffset,
1916 };
1917 use crate::constants;
1918 use crate::read;
1919 use crate::write::{
1920 DebugLine, DebugLineStr, DebugStr, EndianVec, LineString, LineStringTable, Location,
1921 LocationList, LocationListTable, Range, RangeList, RangeListOffsets, RangeListTable,
1922 StringTable,
1923 };
1924 use crate::LittleEndian;
1925 use std::collections::HashMap;
1926 use std::mem;
1927
1928 #[test]
1929 #[allow(clippy::cyclomatic_complexity)]
test_unit_table()1930 fn test_unit_table() {
1931 let mut strings = StringTable::default();
1932
1933 let mut units = UnitTable::default();
1934 let unit_id1 = units.add(Unit::new(
1935 Encoding {
1936 version: 4,
1937 address_size: 8,
1938 format: Format::Dwarf32,
1939 },
1940 LineProgram::none(),
1941 ));
1942 let unit2 = units.add(Unit::new(
1943 Encoding {
1944 version: 2,
1945 address_size: 4,
1946 format: Format::Dwarf64,
1947 },
1948 LineProgram::none(),
1949 ));
1950 let unit3 = units.add(Unit::new(
1951 Encoding {
1952 version: 5,
1953 address_size: 4,
1954 format: Format::Dwarf32,
1955 },
1956 LineProgram::none(),
1957 ));
1958 assert_eq!(units.count(), 3);
1959 {
1960 let unit1 = units.get_mut(unit_id1);
1961 assert_eq!(unit1.version(), 4);
1962 assert_eq!(unit1.address_size(), 8);
1963 assert_eq!(unit1.format(), Format::Dwarf32);
1964 assert_eq!(unit1.count(), 1);
1965
1966 let root_id = unit1.root();
1967 assert_eq!(root_id, UnitEntryId::new(unit1.base_id, 0));
1968 {
1969 let root = unit1.get_mut(root_id);
1970 assert_eq!(root.id(), root_id);
1971 assert!(root.parent().is_none());
1972 assert_eq!(root.tag(), constants::DW_TAG_compile_unit);
1973
1974 // Test get/get_mut
1975 assert!(root.get(constants::DW_AT_producer).is_none());
1976 assert!(root.get_mut(constants::DW_AT_producer).is_none());
1977 let mut producer = AttributeValue::String(b"root"[..].into());
1978 root.set(constants::DW_AT_producer, producer.clone());
1979 assert_eq!(root.get(constants::DW_AT_producer), Some(&producer));
1980 assert_eq!(root.get_mut(constants::DW_AT_producer), Some(&mut producer));
1981
1982 // Test attrs
1983 let mut attrs = root.attrs();
1984 let attr = attrs.next().unwrap();
1985 assert_eq!(attr.name(), constants::DW_AT_producer);
1986 assert_eq!(attr.get(), &producer);
1987 assert!(attrs.next().is_none());
1988 }
1989
1990 let child1 = unit1.add(root_id, constants::DW_TAG_subprogram);
1991 assert_eq!(child1, UnitEntryId::new(unit1.base_id, 1));
1992 {
1993 let child1 = unit1.get_mut(child1);
1994 assert_eq!(child1.parent(), Some(root_id));
1995
1996 let tmp = AttributeValue::String(b"tmp"[..].into());
1997 child1.set(constants::DW_AT_name, tmp.clone());
1998 assert_eq!(child1.get(constants::DW_AT_name), Some(&tmp));
1999
2000 // Test attrs_mut
2001 let name = AttributeValue::StringRef(strings.add(&b"child1"[..]));
2002 {
2003 let attr = child1.attrs_mut().next().unwrap();
2004 assert_eq!(attr.name(), constants::DW_AT_name);
2005 attr.set(name.clone());
2006 }
2007 assert_eq!(child1.get(constants::DW_AT_name), Some(&name));
2008 }
2009
2010 let child2 = unit1.add(root_id, constants::DW_TAG_subprogram);
2011 assert_eq!(child2, UnitEntryId::new(unit1.base_id, 2));
2012 {
2013 let child2 = unit1.get_mut(child2);
2014 assert_eq!(child2.parent(), Some(root_id));
2015
2016 let tmp = AttributeValue::String(b"tmp"[..].into());
2017 child2.set(constants::DW_AT_name, tmp.clone());
2018 assert_eq!(child2.get(constants::DW_AT_name), Some(&tmp));
2019
2020 // Test replace
2021 let name = AttributeValue::StringRef(strings.add(&b"child2"[..]));
2022 child2.set(constants::DW_AT_name, name.clone());
2023 assert_eq!(child2.get(constants::DW_AT_name), Some(&name));
2024 }
2025
2026 {
2027 let root = unit1.get(root_id);
2028 assert_eq!(
2029 root.children().cloned().collect::<Vec<_>>(),
2030 vec![child1, child2]
2031 );
2032 }
2033 }
2034 {
2035 let unit2 = units.get(unit2);
2036 assert_eq!(unit2.version(), 2);
2037 assert_eq!(unit2.address_size(), 4);
2038 assert_eq!(unit2.format(), Format::Dwarf64);
2039 assert_eq!(unit2.count(), 1);
2040
2041 let root = unit2.root();
2042 assert_eq!(root, UnitEntryId::new(unit2.base_id, 0));
2043 let root = unit2.get(root);
2044 assert_eq!(root.id(), UnitEntryId::new(unit2.base_id, 0));
2045 assert!(root.parent().is_none());
2046 assert_eq!(root.tag(), constants::DW_TAG_compile_unit);
2047 }
2048
2049 let mut sections = Sections::new(EndianVec::new(LittleEndian));
2050 let debug_line_str_offsets = DebugLineStrOffsets::none();
2051 let debug_str_offsets = strings.write(&mut sections.debug_str).unwrap();
2052 units
2053 .write(&mut sections, &debug_line_str_offsets, &debug_str_offsets)
2054 .unwrap();
2055
2056 println!("{:?}", sections.debug_str);
2057 println!("{:?}", sections.debug_info);
2058 println!("{:?}", sections.debug_abbrev);
2059
2060 let dwarf = read::Dwarf {
2061 debug_abbrev: read::DebugAbbrev::new(sections.debug_abbrev.slice(), LittleEndian),
2062 debug_info: read::DebugInfo::new(sections.debug_info.slice(), LittleEndian),
2063 debug_str: read::DebugStr::new(sections.debug_str.slice(), LittleEndian),
2064 ..Default::default()
2065 };
2066 let mut read_units = dwarf.units();
2067
2068 {
2069 let read_unit1 = read_units.next().unwrap().unwrap();
2070 let unit1 = units.get(unit_id1);
2071 assert_eq!(unit1.version(), read_unit1.version());
2072 assert_eq!(unit1.address_size(), read_unit1.address_size());
2073 assert_eq!(unit1.format(), read_unit1.format());
2074
2075 let read_unit1 = dwarf.unit(read_unit1).unwrap();
2076 let mut read_entries = read_unit1.entries();
2077
2078 let root = unit1.get(unit1.root());
2079 {
2080 let (depth, read_root) = read_entries.next_dfs().unwrap().unwrap();
2081 assert_eq!(depth, 0);
2082 assert_eq!(root.tag(), read_root.tag());
2083 assert!(read_root.has_children());
2084
2085 let producer = match root.get(constants::DW_AT_producer).unwrap() {
2086 AttributeValue::String(ref producer) => &**producer,
2087 otherwise => panic!("unexpected {:?}", otherwise),
2088 };
2089 assert_eq!(producer, b"root");
2090 let read_producer = read_root
2091 .attr_value(constants::DW_AT_producer)
2092 .unwrap()
2093 .unwrap();
2094 assert_eq!(
2095 dwarf
2096 .attr_string(&read_unit1, read_producer)
2097 .unwrap()
2098 .slice(),
2099 producer
2100 );
2101 }
2102
2103 let mut children = root.children().cloned();
2104
2105 {
2106 let child = children.next().unwrap();
2107 assert_eq!(child, UnitEntryId::new(unit1.base_id, 1));
2108 let child = unit1.get(child);
2109 let (depth, read_child) = read_entries.next_dfs().unwrap().unwrap();
2110 assert_eq!(depth, 1);
2111 assert_eq!(child.tag(), read_child.tag());
2112 assert!(!read_child.has_children());
2113
2114 let name = match child.get(constants::DW_AT_name).unwrap() {
2115 AttributeValue::StringRef(name) => *name,
2116 otherwise => panic!("unexpected {:?}", otherwise),
2117 };
2118 let name = strings.get(name);
2119 assert_eq!(name, b"child1");
2120 let read_name = read_child
2121 .attr_value(constants::DW_AT_name)
2122 .unwrap()
2123 .unwrap();
2124 assert_eq!(
2125 dwarf.attr_string(&read_unit1, read_name).unwrap().slice(),
2126 name
2127 );
2128 }
2129
2130 {
2131 let child = children.next().unwrap();
2132 assert_eq!(child, UnitEntryId::new(unit1.base_id, 2));
2133 let child = unit1.get(child);
2134 let (depth, read_child) = read_entries.next_dfs().unwrap().unwrap();
2135 assert_eq!(depth, 0);
2136 assert_eq!(child.tag(), read_child.tag());
2137 assert!(!read_child.has_children());
2138
2139 let name = match child.get(constants::DW_AT_name).unwrap() {
2140 AttributeValue::StringRef(name) => *name,
2141 otherwise => panic!("unexpected {:?}", otherwise),
2142 };
2143 let name = strings.get(name);
2144 assert_eq!(name, b"child2");
2145 let read_name = read_child
2146 .attr_value(constants::DW_AT_name)
2147 .unwrap()
2148 .unwrap();
2149 assert_eq!(
2150 dwarf.attr_string(&read_unit1, read_name).unwrap().slice(),
2151 name
2152 );
2153 }
2154
2155 assert!(read_entries.next_dfs().unwrap().is_none());
2156 }
2157
2158 {
2159 let read_unit2 = read_units.next().unwrap().unwrap();
2160 let unit2 = units.get(unit2);
2161 assert_eq!(unit2.version(), read_unit2.version());
2162 assert_eq!(unit2.address_size(), read_unit2.address_size());
2163 assert_eq!(unit2.format(), read_unit2.format());
2164
2165 let abbrevs = dwarf.abbreviations(&read_unit2).unwrap();
2166 let mut read_entries = read_unit2.entries(&abbrevs);
2167
2168 {
2169 let root = unit2.get(unit2.root());
2170 let (depth, read_root) = read_entries.next_dfs().unwrap().unwrap();
2171 assert_eq!(depth, 0);
2172 assert_eq!(root.tag(), read_root.tag());
2173 assert!(!read_root.has_children());
2174 }
2175
2176 assert!(read_entries.next_dfs().unwrap().is_none());
2177 }
2178
2179 {
2180 let read_unit3 = read_units.next().unwrap().unwrap();
2181 let unit3 = units.get(unit3);
2182 assert_eq!(unit3.version(), read_unit3.version());
2183 assert_eq!(unit3.address_size(), read_unit3.address_size());
2184 assert_eq!(unit3.format(), read_unit3.format());
2185
2186 let abbrevs = dwarf.abbreviations(&read_unit3).unwrap();
2187 let mut read_entries = read_unit3.entries(&abbrevs);
2188
2189 {
2190 let root = unit3.get(unit3.root());
2191 let (depth, read_root) = read_entries.next_dfs().unwrap().unwrap();
2192 assert_eq!(depth, 0);
2193 assert_eq!(root.tag(), read_root.tag());
2194 assert!(!read_root.has_children());
2195 }
2196
2197 assert!(read_entries.next_dfs().unwrap().is_none());
2198 }
2199
2200 assert!(read_units.next().unwrap().is_none());
2201
2202 let mut convert_line_strings = LineStringTable::default();
2203 let mut convert_strings = StringTable::default();
2204 let convert_units = UnitTable::from(
2205 &dwarf,
2206 &mut convert_line_strings,
2207 &mut convert_strings,
2208 &|address| Some(Address::Constant(address)),
2209 )
2210 .unwrap();
2211 assert_eq!(convert_units.count(), units.count());
2212
2213 for i in 0..convert_units.count() {
2214 let unit_id = units.id(i);
2215 let unit = units.get(unit_id);
2216 let convert_unit_id = convert_units.id(i);
2217 let convert_unit = convert_units.get(convert_unit_id);
2218 assert_eq!(convert_unit.version(), unit.version());
2219 assert_eq!(convert_unit.address_size(), unit.address_size());
2220 assert_eq!(convert_unit.format(), unit.format());
2221 assert_eq!(convert_unit.count(), unit.count());
2222
2223 let root = unit.get(unit.root());
2224 let convert_root = convert_unit.get(convert_unit.root());
2225 assert_eq!(convert_root.tag(), root.tag());
2226 for (convert_attr, attr) in convert_root.attrs().zip(root.attrs()) {
2227 assert_eq!(convert_attr, attr);
2228 }
2229 }
2230 }
2231
2232 #[test]
test_attribute_value()2233 fn test_attribute_value() {
2234 // Create a string table and a string with a non-zero id/offset.
2235 let mut strings = StringTable::default();
2236 strings.add("string one");
2237 let string_id = strings.add("string two");
2238 let mut debug_str = DebugStr::from(EndianVec::new(LittleEndian));
2239 let debug_str_offsets = strings.write(&mut debug_str).unwrap();
2240 let read_debug_str = read::DebugStr::new(debug_str.slice(), LittleEndian);
2241
2242 let mut line_strings = LineStringTable::default();
2243 line_strings.add("line string one");
2244 let line_string_id = line_strings.add("line string two");
2245 let mut debug_line_str = DebugLineStr::from(EndianVec::new(LittleEndian));
2246 let debug_line_str_offsets = line_strings.write(&mut debug_line_str).unwrap();
2247 let read_debug_line_str =
2248 read::DebugLineStr::from(read::EndianSlice::new(debug_line_str.slice(), LittleEndian));
2249
2250 let data = vec![1, 2, 3, 4];
2251 let read_data = read::EndianSlice::new(&[1, 2, 3, 4], LittleEndian);
2252
2253 let mut expression = Expression::new();
2254 expression.op_constu(57);
2255 let read_expression = read::Expression(read::EndianSlice::new(
2256 &[constants::DW_OP_constu.0, 57],
2257 LittleEndian,
2258 ));
2259
2260 let mut ranges = RangeListTable::default();
2261 let range_id = ranges.add(RangeList(vec![Range::StartEnd {
2262 begin: Address::Constant(0x1234),
2263 end: Address::Constant(0x2345),
2264 }]));
2265
2266 let mut locations = LocationListTable::default();
2267 let loc_id = locations.add(LocationList(vec![Location::StartEnd {
2268 begin: Address::Constant(0x1234),
2269 end: Address::Constant(0x2345),
2270 data: expression.clone(),
2271 }]));
2272
2273 for &version in &[2, 3, 4, 5] {
2274 for &address_size in &[4, 8] {
2275 for &format in &[Format::Dwarf32, Format::Dwarf64] {
2276 let encoding = Encoding {
2277 format,
2278 version,
2279 address_size,
2280 };
2281
2282 let mut sections = Sections::new(EndianVec::new(LittleEndian));
2283 let range_list_offsets = ranges.write(&mut sections, encoding).unwrap();
2284 let loc_list_offsets = locations.write(&mut sections, encoding, None).unwrap();
2285
2286 let read_debug_ranges =
2287 read::DebugRanges::new(sections.debug_ranges.slice(), LittleEndian);
2288 let read_debug_rnglists =
2289 read::DebugRngLists::new(sections.debug_rnglists.slice(), LittleEndian);
2290
2291 let read_debug_loc =
2292 read::DebugLoc::new(sections.debug_loc.slice(), LittleEndian);
2293 let read_debug_loclists =
2294 read::DebugLocLists::new(sections.debug_loclists.slice(), LittleEndian);
2295
2296 let mut units = UnitTable::default();
2297 let unit = units.add(Unit::new(encoding, LineProgram::none()));
2298 let unit = units.get(unit);
2299 let encoding = Encoding {
2300 format,
2301 version,
2302 address_size,
2303 };
2304 let from_unit = read::UnitHeader::new(
2305 encoding,
2306 0,
2307 DebugAbbrevOffset(0),
2308 read::EndianSlice::new(&[], LittleEndian),
2309 );
2310
2311 for &(ref name, ref value, ref expect_value) in &[
2312 (
2313 constants::DW_AT_name,
2314 AttributeValue::Address(Address::Constant(0x1234)),
2315 read::AttributeValue::Addr(0x1234),
2316 ),
2317 (
2318 constants::DW_AT_name,
2319 AttributeValue::Block(data.clone()),
2320 read::AttributeValue::Block(read_data),
2321 ),
2322 (
2323 constants::DW_AT_name,
2324 AttributeValue::Data1(0x12),
2325 read::AttributeValue::Data1(0x12),
2326 ),
2327 (
2328 constants::DW_AT_name,
2329 AttributeValue::Data2(0x1234),
2330 read::AttributeValue::Data2(0x1234),
2331 ),
2332 (
2333 constants::DW_AT_name,
2334 AttributeValue::Data4(0x1234),
2335 read::AttributeValue::Data4(0x1234),
2336 ),
2337 (
2338 constants::DW_AT_name,
2339 AttributeValue::Data8(0x1234),
2340 read::AttributeValue::Data8(0x1234),
2341 ),
2342 (
2343 constants::DW_AT_name,
2344 AttributeValue::Sdata(0x1234),
2345 read::AttributeValue::Sdata(0x1234),
2346 ),
2347 (
2348 constants::DW_AT_name,
2349 AttributeValue::Udata(0x1234),
2350 read::AttributeValue::Udata(0x1234),
2351 ),
2352 (
2353 constants::DW_AT_name,
2354 AttributeValue::Exprloc(expression.clone()),
2355 read::AttributeValue::Exprloc(read_expression),
2356 ),
2357 (
2358 constants::DW_AT_name,
2359 AttributeValue::Flag(false),
2360 read::AttributeValue::Flag(false),
2361 ),
2362 /*
2363 (
2364 constants::DW_AT_name,
2365 AttributeValue::FlagPresent,
2366 read::AttributeValue::Flag(true),
2367 ),
2368 */
2369 (
2370 constants::DW_AT_name,
2371 AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x1234)),
2372 read::AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x1234)),
2373 ),
2374 (
2375 constants::DW_AT_location,
2376 AttributeValue::LocationListRef(loc_id),
2377 read::AttributeValue::SecOffset(loc_list_offsets.get(loc_id).0),
2378 ),
2379 (
2380 constants::DW_AT_macro_info,
2381 AttributeValue::DebugMacinfoRef(DebugMacinfoOffset(0x1234)),
2382 read::AttributeValue::SecOffset(0x1234),
2383 ),
2384 (
2385 constants::DW_AT_macros,
2386 AttributeValue::DebugMacroRef(DebugMacroOffset(0x1234)),
2387 read::AttributeValue::SecOffset(0x1234),
2388 ),
2389 (
2390 constants::DW_AT_ranges,
2391 AttributeValue::RangeListRef(range_id),
2392 read::AttributeValue::SecOffset(range_list_offsets.get(range_id).0),
2393 ),
2394 (
2395 constants::DW_AT_name,
2396 AttributeValue::DebugTypesRef(DebugTypeSignature(0x1234)),
2397 read::AttributeValue::DebugTypesRef(DebugTypeSignature(0x1234)),
2398 ),
2399 (
2400 constants::DW_AT_name,
2401 AttributeValue::StringRef(string_id),
2402 read::AttributeValue::DebugStrRef(debug_str_offsets.get(string_id)),
2403 ),
2404 (
2405 constants::DW_AT_name,
2406 AttributeValue::DebugStrRefSup(DebugStrOffset(0x1234)),
2407 read::AttributeValue::DebugStrRefSup(DebugStrOffset(0x1234)),
2408 ),
2409 (
2410 constants::DW_AT_name,
2411 AttributeValue::LineStringRef(line_string_id),
2412 read::AttributeValue::DebugLineStrRef(
2413 debug_line_str_offsets.get(line_string_id),
2414 ),
2415 ),
2416 (
2417 constants::DW_AT_name,
2418 AttributeValue::String(data.clone()),
2419 read::AttributeValue::String(read_data),
2420 ),
2421 (
2422 constants::DW_AT_encoding,
2423 AttributeValue::Encoding(constants::DwAte(0x12)),
2424 read::AttributeValue::Udata(0x12),
2425 ),
2426 (
2427 constants::DW_AT_decimal_sign,
2428 AttributeValue::DecimalSign(constants::DwDs(0x12)),
2429 read::AttributeValue::Udata(0x12),
2430 ),
2431 (
2432 constants::DW_AT_endianity,
2433 AttributeValue::Endianity(constants::DwEnd(0x12)),
2434 read::AttributeValue::Udata(0x12),
2435 ),
2436 (
2437 constants::DW_AT_accessibility,
2438 AttributeValue::Accessibility(constants::DwAccess(0x12)),
2439 read::AttributeValue::Udata(0x12),
2440 ),
2441 (
2442 constants::DW_AT_visibility,
2443 AttributeValue::Visibility(constants::DwVis(0x12)),
2444 read::AttributeValue::Udata(0x12),
2445 ),
2446 (
2447 constants::DW_AT_virtuality,
2448 AttributeValue::Virtuality(constants::DwVirtuality(0x12)),
2449 read::AttributeValue::Udata(0x12),
2450 ),
2451 (
2452 constants::DW_AT_language,
2453 AttributeValue::Language(constants::DwLang(0x12)),
2454 read::AttributeValue::Udata(0x12),
2455 ),
2456 (
2457 constants::DW_AT_address_class,
2458 AttributeValue::AddressClass(constants::DwAddr(0x12)),
2459 read::AttributeValue::Udata(0x12),
2460 ),
2461 (
2462 constants::DW_AT_identifier_case,
2463 AttributeValue::IdentifierCase(constants::DwId(0x12)),
2464 read::AttributeValue::Udata(0x12),
2465 ),
2466 (
2467 constants::DW_AT_calling_convention,
2468 AttributeValue::CallingConvention(constants::DwCc(0x12)),
2469 read::AttributeValue::Udata(0x12),
2470 ),
2471 (
2472 constants::DW_AT_ordering,
2473 AttributeValue::Ordering(constants::DwOrd(0x12)),
2474 read::AttributeValue::Udata(0x12),
2475 ),
2476 (
2477 constants::DW_AT_inline,
2478 AttributeValue::Inline(constants::DwInl(0x12)),
2479 read::AttributeValue::Udata(0x12),
2480 ),
2481 ][..]
2482 {
2483 let form = value.form(encoding).unwrap();
2484 let attr = Attribute {
2485 name: *name,
2486 value: value.clone(),
2487 };
2488
2489 let offsets = UnitOffsets::none();
2490 let line_program_offset = None;
2491 let mut debug_info_refs = Vec::new();
2492 let mut unit_refs = Vec::new();
2493 let mut debug_info = DebugInfo::from(EndianVec::new(LittleEndian));
2494 attr.value
2495 .write(
2496 &mut debug_info,
2497 &mut debug_info_refs,
2498 &mut unit_refs,
2499 &unit,
2500 &offsets,
2501 line_program_offset,
2502 &debug_line_str_offsets,
2503 &debug_str_offsets,
2504 &range_list_offsets,
2505 &loc_list_offsets,
2506 )
2507 .unwrap();
2508
2509 let spec = read::AttributeSpecification::new(*name, form, None);
2510 let mut r = read::EndianSlice::new(debug_info.slice(), LittleEndian);
2511 let read_attr = read::parse_attribute(&mut r, encoding, spec).unwrap();
2512 let read_value = &read_attr.raw_value();
2513 // read::AttributeValue is invariant in the lifetime of R.
2514 // The lifetimes here are all okay, so transmute it.
2515 let read_value = unsafe {
2516 mem::transmute::<
2517 &read::AttributeValue<read::EndianSlice<LittleEndian>>,
2518 &read::AttributeValue<read::EndianSlice<LittleEndian>>,
2519 >(read_value)
2520 };
2521 assert_eq!(read_value, expect_value);
2522
2523 let dwarf = read::Dwarf {
2524 debug_str: read_debug_str.clone(),
2525 debug_line_str: read_debug_line_str.clone(),
2526 ranges: read::RangeLists::new(read_debug_ranges, read_debug_rnglists),
2527 locations: read::LocationLists::new(
2528 read_debug_loc,
2529 read_debug_loclists,
2530 ),
2531 ..Default::default()
2532 };
2533
2534 let unit = read::Unit {
2535 offset: UnitSectionOffset::DebugInfoOffset(DebugInfoOffset(0)),
2536 header: from_unit,
2537 abbreviations: read::Abbreviations::default(),
2538 name: None,
2539 comp_dir: None,
2540 low_pc: 0,
2541 str_offsets_base: DebugStrOffsetsBase(0),
2542 addr_base: DebugAddrBase(0),
2543 loclists_base: DebugLocListsBase(0),
2544 rnglists_base: DebugRngListsBase(0),
2545 line_program: None,
2546 };
2547
2548 let mut context = convert::ConvertUnitContext {
2549 dwarf: &dwarf,
2550 unit: &unit,
2551 line_strings: &mut line_strings,
2552 strings: &mut strings,
2553 ranges: &mut ranges,
2554 locations: &mut locations,
2555 convert_address: &|address| Some(Address::Constant(address)),
2556 base_address: Address::Constant(0),
2557 line_program_offset: None,
2558 line_program_files: Vec::new(),
2559 entry_ids: &HashMap::new(),
2560 };
2561
2562 let convert_attr =
2563 Attribute::from(&mut context, &read_attr).unwrap().unwrap();
2564 assert_eq!(convert_attr, attr);
2565 }
2566 }
2567 }
2568 }
2569 }
2570
2571 #[test]
2572 #[allow(clippy::cyclomatic_complexity)]
test_unit_ref()2573 fn test_unit_ref() {
2574 let mut units = UnitTable::default();
2575 let unit_id1 = units.add(Unit::new(
2576 Encoding {
2577 version: 4,
2578 address_size: 8,
2579 format: Format::Dwarf32,
2580 },
2581 LineProgram::none(),
2582 ));
2583 assert_eq!(unit_id1, units.id(0));
2584 let unit_id2 = units.add(Unit::new(
2585 Encoding {
2586 version: 2,
2587 address_size: 4,
2588 format: Format::Dwarf64,
2589 },
2590 LineProgram::none(),
2591 ));
2592 assert_eq!(unit_id2, units.id(1));
2593 let unit1_child1 = UnitEntryId::new(units.get(unit_id1).base_id, 1);
2594 let unit1_child2 = UnitEntryId::new(units.get(unit_id1).base_id, 2);
2595 let unit2_child1 = UnitEntryId::new(units.get(unit_id2).base_id, 1);
2596 let unit2_child2 = UnitEntryId::new(units.get(unit_id2).base_id, 2);
2597 {
2598 let unit1 = units.get_mut(unit_id1);
2599 let root = unit1.root();
2600 let child_id1 = unit1.add(root, constants::DW_TAG_subprogram);
2601 assert_eq!(child_id1, unit1_child1);
2602 let child_id2 = unit1.add(root, constants::DW_TAG_subprogram);
2603 assert_eq!(child_id2, unit1_child2);
2604 {
2605 let child1 = unit1.get_mut(child_id1);
2606 child1.set(constants::DW_AT_type, AttributeValue::UnitRef(child_id2));
2607 }
2608 {
2609 let child2 = unit1.get_mut(child_id2);
2610 child2.set(
2611 constants::DW_AT_type,
2612 AttributeValue::DebugInfoRef(Reference::Entry(unit_id2, unit2_child1)),
2613 );
2614 }
2615 }
2616 {
2617 let unit2 = units.get_mut(unit_id2);
2618 let root = unit2.root();
2619 let child_id1 = unit2.add(root, constants::DW_TAG_subprogram);
2620 assert_eq!(child_id1, unit2_child1);
2621 let child_id2 = unit2.add(root, constants::DW_TAG_subprogram);
2622 assert_eq!(child_id2, unit2_child2);
2623 {
2624 let child1 = unit2.get_mut(child_id1);
2625 child1.set(constants::DW_AT_type, AttributeValue::UnitRef(child_id2));
2626 }
2627 {
2628 let child2 = unit2.get_mut(child_id2);
2629 child2.set(
2630 constants::DW_AT_type,
2631 AttributeValue::DebugInfoRef(Reference::Entry(unit_id1, unit1_child1)),
2632 );
2633 }
2634 }
2635
2636 let debug_line_str_offsets = DebugLineStrOffsets::none();
2637 let debug_str_offsets = DebugStrOffsets::none();
2638 let mut sections = Sections::new(EndianVec::new(LittleEndian));
2639 let debug_info_offsets = units
2640 .write(&mut sections, &debug_line_str_offsets, &debug_str_offsets)
2641 .unwrap();
2642
2643 println!("{:?}", sections.debug_info);
2644 println!("{:?}", sections.debug_abbrev);
2645
2646 let dwarf = read::Dwarf {
2647 debug_abbrev: read::DebugAbbrev::new(sections.debug_abbrev.slice(), LittleEndian),
2648 debug_info: read::DebugInfo::new(sections.debug_info.slice(), LittleEndian),
2649 ..Default::default()
2650 };
2651
2652 let mut read_units = dwarf.units();
2653 {
2654 let read_unit1 = read_units.next().unwrap().unwrap();
2655 assert_eq!(read_unit1.offset(), debug_info_offsets.unit(unit_id1));
2656
2657 let abbrevs = dwarf.abbreviations(&read_unit1).unwrap();
2658 let mut read_entries = read_unit1.entries(&abbrevs);
2659 {
2660 let (_, _read_root) = read_entries.next_dfs().unwrap().unwrap();
2661 }
2662 {
2663 let (_, read_child1) = read_entries.next_dfs().unwrap().unwrap();
2664 let offset = debug_info_offsets
2665 .entry(unit_id1, unit1_child2)
2666 .to_unit_offset(&read_unit1)
2667 .unwrap();
2668 assert_eq!(
2669 read_child1.attr_value(constants::DW_AT_type).unwrap(),
2670 Some(read::AttributeValue::UnitRef(offset))
2671 );
2672 }
2673 {
2674 let (_, read_child2) = read_entries.next_dfs().unwrap().unwrap();
2675 let offset = debug_info_offsets.entry(unit_id2, unit2_child1);
2676 assert_eq!(
2677 read_child2.attr_value(constants::DW_AT_type).unwrap(),
2678 Some(read::AttributeValue::DebugInfoRef(offset))
2679 );
2680 }
2681 }
2682 {
2683 let read_unit2 = read_units.next().unwrap().unwrap();
2684 assert_eq!(read_unit2.offset(), debug_info_offsets.unit(unit_id2));
2685
2686 let abbrevs = dwarf.abbreviations(&read_unit2).unwrap();
2687 let mut read_entries = read_unit2.entries(&abbrevs);
2688 {
2689 let (_, _read_root) = read_entries.next_dfs().unwrap().unwrap();
2690 }
2691 {
2692 let (_, read_child1) = read_entries.next_dfs().unwrap().unwrap();
2693 let offset = debug_info_offsets
2694 .entry(unit_id2, unit2_child2)
2695 .to_unit_offset(&read_unit2)
2696 .unwrap();
2697 assert_eq!(
2698 read_child1.attr_value(constants::DW_AT_type).unwrap(),
2699 Some(read::AttributeValue::UnitRef(offset))
2700 );
2701 }
2702 {
2703 let (_, read_child2) = read_entries.next_dfs().unwrap().unwrap();
2704 let offset = debug_info_offsets.entry(unit_id1, unit1_child1);
2705 assert_eq!(
2706 read_child2.attr_value(constants::DW_AT_type).unwrap(),
2707 Some(read::AttributeValue::DebugInfoRef(offset))
2708 );
2709 }
2710 }
2711
2712 let mut convert_line_strings = LineStringTable::default();
2713 let mut convert_strings = StringTable::default();
2714 let convert_units = UnitTable::from(
2715 &dwarf,
2716 &mut convert_line_strings,
2717 &mut convert_strings,
2718 &|address| Some(Address::Constant(address)),
2719 )
2720 .unwrap();
2721 assert_eq!(convert_units.count(), units.count());
2722
2723 for i in 0..convert_units.count() {
2724 let unit = units.get(units.id(i));
2725 let convert_unit = convert_units.get(convert_units.id(i));
2726 assert_eq!(convert_unit.version(), unit.version());
2727 assert_eq!(convert_unit.address_size(), unit.address_size());
2728 assert_eq!(convert_unit.format(), unit.format());
2729 assert_eq!(convert_unit.count(), unit.count());
2730
2731 let root = unit.get(unit.root());
2732 let convert_root = convert_unit.get(convert_unit.root());
2733 assert_eq!(convert_root.tag(), root.tag());
2734 for (convert_attr, attr) in convert_root.attrs().zip(root.attrs()) {
2735 assert_eq!(convert_attr, attr);
2736 }
2737
2738 let child1 = unit.get(UnitEntryId::new(unit.base_id, 1));
2739 let convert_child1 = convert_unit.get(UnitEntryId::new(convert_unit.base_id, 1));
2740 assert_eq!(convert_child1.tag(), child1.tag());
2741 for (convert_attr, attr) in convert_child1.attrs().zip(child1.attrs()) {
2742 assert_eq!(convert_attr.name, attr.name);
2743 match (convert_attr.value.clone(), attr.value.clone()) {
2744 (
2745 AttributeValue::DebugInfoRef(Reference::Entry(convert_unit, convert_entry)),
2746 AttributeValue::DebugInfoRef(Reference::Entry(unit, entry)),
2747 ) => {
2748 assert_eq!(convert_unit.index, unit.index);
2749 assert_eq!(convert_entry.index, entry.index);
2750 }
2751 (AttributeValue::UnitRef(convert_id), AttributeValue::UnitRef(id)) => {
2752 assert_eq!(convert_id.index, id.index);
2753 }
2754 (convert_value, value) => assert_eq!(convert_value, value),
2755 }
2756 }
2757
2758 let child2 = unit.get(UnitEntryId::new(unit.base_id, 2));
2759 let convert_child2 = convert_unit.get(UnitEntryId::new(convert_unit.base_id, 2));
2760 assert_eq!(convert_child2.tag(), child2.tag());
2761 for (convert_attr, attr) in convert_child2.attrs().zip(child2.attrs()) {
2762 assert_eq!(convert_attr.name, attr.name);
2763 match (convert_attr.value.clone(), attr.value.clone()) {
2764 (
2765 AttributeValue::DebugInfoRef(Reference::Entry(convert_unit, convert_entry)),
2766 AttributeValue::DebugInfoRef(Reference::Entry(unit, entry)),
2767 ) => {
2768 assert_eq!(convert_unit.index, unit.index);
2769 assert_eq!(convert_entry.index, entry.index);
2770 }
2771 (AttributeValue::UnitRef(convert_id), AttributeValue::UnitRef(id)) => {
2772 assert_eq!(convert_id.index, id.index);
2773 }
2774 (convert_value, value) => assert_eq!(convert_value, value),
2775 }
2776 }
2777 }
2778 }
2779
2780 #[test]
test_sibling()2781 fn test_sibling() {
2782 fn add_child(
2783 unit: &mut Unit,
2784 parent: UnitEntryId,
2785 tag: constants::DwTag,
2786 name: &str,
2787 ) -> UnitEntryId {
2788 let id = unit.add(parent, tag);
2789 let child = unit.get_mut(id);
2790 child.set(constants::DW_AT_name, AttributeValue::String(name.into()));
2791 child.set_sibling(true);
2792 id
2793 }
2794
2795 fn add_children(units: &mut UnitTable, unit_id: UnitId) {
2796 let unit = units.get_mut(unit_id);
2797 let root = unit.root();
2798 let child1 = add_child(unit, root, constants::DW_TAG_subprogram, "child1");
2799 add_child(unit, child1, constants::DW_TAG_variable, "grandchild1");
2800 add_child(unit, root, constants::DW_TAG_subprogram, "child2");
2801 add_child(unit, root, constants::DW_TAG_subprogram, "child3");
2802 }
2803
2804 fn next_child<R: read::Reader<Offset = usize>>(
2805 entries: &mut read::EntriesCursor<R>,
2806 ) -> (read::UnitOffset, Option<read::UnitOffset>) {
2807 let (_, entry) = entries.next_dfs().unwrap().unwrap();
2808 let offset = entry.offset();
2809 let sibling =
2810 entry
2811 .attr_value(constants::DW_AT_sibling)
2812 .unwrap()
2813 .map(|attr| match attr {
2814 read::AttributeValue::UnitRef(offset) => offset,
2815 _ => panic!("bad sibling value"),
2816 });
2817 (offset, sibling)
2818 }
2819
2820 fn check_sibling<R: read::Reader<Offset = usize>>(
2821 unit: &read::CompilationUnitHeader<R>,
2822 debug_abbrev: &read::DebugAbbrev<R>,
2823 ) {
2824 let abbrevs = unit.abbreviations(debug_abbrev).unwrap();
2825 let mut entries = unit.entries(&abbrevs);
2826 // root
2827 entries.next_dfs().unwrap().unwrap();
2828 // child1
2829 let (_, sibling1) = next_child(&mut entries);
2830 // grandchild1
2831 entries.next_dfs().unwrap().unwrap();
2832 // child2
2833 let (offset2, sibling2) = next_child(&mut entries);
2834 // child3
2835 let (_, _) = next_child(&mut entries);
2836 assert_eq!(sibling1, Some(offset2));
2837 assert_eq!(sibling2, None);
2838 }
2839
2840 let encoding = Encoding {
2841 format: Format::Dwarf32,
2842 version: 4,
2843 address_size: 8,
2844 };
2845 let mut units = UnitTable::default();
2846 let unit_id1 = units.add(Unit::new(encoding, LineProgram::none()));
2847 add_children(&mut units, unit_id1);
2848 let unit_id2 = units.add(Unit::new(encoding, LineProgram::none()));
2849 add_children(&mut units, unit_id2);
2850
2851 let debug_line_str_offsets = DebugLineStrOffsets::none();
2852 let debug_str_offsets = DebugStrOffsets::none();
2853 let mut sections = Sections::new(EndianVec::new(LittleEndian));
2854 units
2855 .write(&mut sections, &debug_line_str_offsets, &debug_str_offsets)
2856 .unwrap();
2857
2858 println!("{:?}", sections.debug_info);
2859 println!("{:?}", sections.debug_abbrev);
2860
2861 let read_debug_info = read::DebugInfo::new(sections.debug_info.slice(), LittleEndian);
2862 let read_debug_abbrev = read::DebugAbbrev::new(sections.debug_abbrev.slice(), LittleEndian);
2863 let mut read_units = read_debug_info.units();
2864 check_sibling(&read_units.next().unwrap().unwrap(), &read_debug_abbrev);
2865 check_sibling(&read_units.next().unwrap().unwrap(), &read_debug_abbrev);
2866 }
2867
2868 #[test]
test_line_ref()2869 fn test_line_ref() {
2870 for &version in &[2, 3, 4, 5] {
2871 for &address_size in &[4, 8] {
2872 for &format in &[Format::Dwarf32, Format::Dwarf64] {
2873 let encoding = Encoding {
2874 format,
2875 version,
2876 address_size,
2877 };
2878
2879 // The line program we'll be referencing.
2880 let mut line_program = LineProgram::new(
2881 encoding,
2882 LineEncoding::default(),
2883 LineString::String(b"comp_dir".to_vec()),
2884 LineString::String(b"comp_name".to_vec()),
2885 None,
2886 );
2887 let dir = line_program.default_directory();
2888 let file1 =
2889 line_program.add_file(LineString::String(b"file1".to_vec()), dir, None);
2890 let file2 =
2891 line_program.add_file(LineString::String(b"file2".to_vec()), dir, None);
2892
2893 // Write, read, and convert the line program, so that we have the info
2894 // required to convert the attributes.
2895 let line_strings = DebugLineStrOffsets::none();
2896 let strings = DebugStrOffsets::none();
2897 let mut debug_line = DebugLine::from(EndianVec::new(LittleEndian));
2898 let line_program_offset = line_program
2899 .write(&mut debug_line, encoding, &line_strings, &strings)
2900 .unwrap();
2901 let read_debug_line = read::DebugLine::new(debug_line.slice(), LittleEndian);
2902 let read_line_program = read_debug_line
2903 .program(
2904 line_program_offset,
2905 address_size,
2906 Some(read::EndianSlice::new(b"comp_dir", LittleEndian)),
2907 Some(read::EndianSlice::new(b"comp_name", LittleEndian)),
2908 )
2909 .unwrap();
2910 let dwarf = read::Dwarf::default();
2911 let mut convert_line_strings = LineStringTable::default();
2912 let mut convert_strings = StringTable::default();
2913 let (_, line_program_files) = LineProgram::from(
2914 read_line_program,
2915 &dwarf,
2916 &mut convert_line_strings,
2917 &mut convert_strings,
2918 &|address| Some(Address::Constant(address)),
2919 )
2920 .unwrap();
2921
2922 // Fake the unit.
2923 let mut units = UnitTable::default();
2924 let unit = units.add(Unit::new(encoding, LineProgram::none()));
2925 let unit = units.get(unit);
2926 let from_unit = read::UnitHeader::new(
2927 encoding,
2928 0,
2929 DebugAbbrevOffset(0),
2930 read::EndianSlice::new(&[], LittleEndian),
2931 );
2932
2933 for &(ref name, ref value, ref expect_value) in &[
2934 (
2935 constants::DW_AT_stmt_list,
2936 AttributeValue::LineProgramRef,
2937 read::AttributeValue::SecOffset(line_program_offset.0),
2938 ),
2939 (
2940 constants::DW_AT_decl_file,
2941 AttributeValue::FileIndex(Some(file1)),
2942 read::AttributeValue::Udata(file1.raw()),
2943 ),
2944 (
2945 constants::DW_AT_decl_file,
2946 AttributeValue::FileIndex(Some(file2)),
2947 read::AttributeValue::Udata(file2.raw()),
2948 ),
2949 ][..]
2950 {
2951 let mut ranges = RangeListTable::default();
2952 let mut locations = LocationListTable::default();
2953 let mut strings = StringTable::default();
2954 let mut line_strings = LineStringTable::default();
2955
2956 let form = value.form(encoding).unwrap();
2957 let attr = Attribute {
2958 name: *name,
2959 value: value.clone(),
2960 };
2961
2962 let mut debug_info_refs = Vec::new();
2963 let mut unit_refs = Vec::new();
2964 let mut debug_info = DebugInfo::from(EndianVec::new(LittleEndian));
2965 let offsets = UnitOffsets::none();
2966 let debug_line_str_offsets = DebugLineStrOffsets::none();
2967 let debug_str_offsets = DebugStrOffsets::none();
2968 let range_list_offsets = RangeListOffsets::none();
2969 let loc_list_offsets = LocationListOffsets::none();
2970 attr.value
2971 .write(
2972 &mut debug_info,
2973 &mut debug_info_refs,
2974 &mut unit_refs,
2975 &unit,
2976 &offsets,
2977 Some(line_program_offset),
2978 &debug_line_str_offsets,
2979 &debug_str_offsets,
2980 &range_list_offsets,
2981 &loc_list_offsets,
2982 )
2983 .unwrap();
2984
2985 let spec = read::AttributeSpecification::new(*name, form, None);
2986 let mut r = read::EndianSlice::new(debug_info.slice(), LittleEndian);
2987 let read_attr = read::parse_attribute(&mut r, encoding, spec).unwrap();
2988 let read_value = &read_attr.raw_value();
2989 // read::AttributeValue is invariant in the lifetime of R.
2990 // The lifetimes here are all okay, so transmute it.
2991 let read_value = unsafe {
2992 mem::transmute::<
2993 &read::AttributeValue<read::EndianSlice<LittleEndian>>,
2994 &read::AttributeValue<read::EndianSlice<LittleEndian>>,
2995 >(read_value)
2996 };
2997 assert_eq!(read_value, expect_value);
2998
2999 let unit = read::Unit {
3000 offset: UnitSectionOffset::DebugInfoOffset(DebugInfoOffset(0)),
3001 header: from_unit,
3002 abbreviations: read::Abbreviations::default(),
3003 name: None,
3004 comp_dir: None,
3005 low_pc: 0,
3006 str_offsets_base: DebugStrOffsetsBase(0),
3007 addr_base: DebugAddrBase(0),
3008 loclists_base: DebugLocListsBase(0),
3009 rnglists_base: DebugRngListsBase(0),
3010 line_program: None,
3011 };
3012
3013 let mut context = convert::ConvertUnitContext {
3014 dwarf: &dwarf,
3015 unit: &unit,
3016 line_strings: &mut line_strings,
3017 strings: &mut strings,
3018 ranges: &mut ranges,
3019 locations: &mut locations,
3020 convert_address: &|address| Some(Address::Constant(address)),
3021 base_address: Address::Constant(0),
3022 line_program_offset: Some(line_program_offset),
3023 line_program_files: line_program_files.clone(),
3024 entry_ids: &HashMap::new(),
3025 };
3026
3027 let convert_attr =
3028 Attribute::from(&mut context, &read_attr).unwrap().unwrap();
3029 assert_eq!(convert_attr, attr);
3030 }
3031 }
3032 }
3033 }
3034 }
3035
3036 #[test]
test_line_program_used()3037 fn test_line_program_used() {
3038 for used in vec![false, true] {
3039 let encoding = Encoding {
3040 format: Format::Dwarf32,
3041 version: 5,
3042 address_size: 8,
3043 };
3044
3045 let line_program = LineProgram::new(
3046 encoding,
3047 LineEncoding::default(),
3048 LineString::String(b"comp_dir".to_vec()),
3049 LineString::String(b"comp_name".to_vec()),
3050 None,
3051 );
3052
3053 let mut unit = Unit::new(encoding, line_program);
3054 let file_id = if used { Some(FileId::new(0)) } else { None };
3055 let root = unit.root();
3056 unit.get_mut(root).set(
3057 constants::DW_AT_decl_file,
3058 AttributeValue::FileIndex(file_id),
3059 );
3060
3061 let mut units = UnitTable::default();
3062 units.add(unit);
3063
3064 let debug_line_str_offsets = DebugLineStrOffsets::none();
3065 let debug_str_offsets = DebugStrOffsets::none();
3066 let mut sections = Sections::new(EndianVec::new(LittleEndian));
3067 units
3068 .write(&mut sections, &debug_line_str_offsets, &debug_str_offsets)
3069 .unwrap();
3070 assert_eq!(!used, sections.debug_line.slice().is_empty());
3071 }
3072 }
3073 }
3074