gimli/write/
unit.rs

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