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