gimli/write/
dwarf.rs

1use alloc::vec::Vec;
2
3use crate::common::Encoding;
4use crate::write::{
5    AbbreviationTable, LineProgram, LineString, LineStringTable, Result, Sections, StringTable,
6    Unit, UnitTable, Writer,
7};
8
9/// Writable DWARF information for more than one unit.
10#[derive(Debug, Default)]
11pub struct Dwarf {
12    /// A table of units. These are primarily stored in the `.debug_info` section,
13    /// but they also contain information that is stored in other sections.
14    pub units: UnitTable,
15
16    /// Extra line number programs that are not associated with a unit.
17    ///
18    /// These should only be used when generating DWARF5 line-only debug
19    /// information.
20    pub line_programs: Vec<LineProgram>,
21
22    /// A table of strings that will be stored in the `.debug_line_str` section.
23    pub line_strings: LineStringTable,
24
25    /// A table of strings that will be stored in the `.debug_str` section.
26    pub strings: StringTable,
27}
28
29impl Dwarf {
30    /// Create a new `Dwarf` instance.
31    #[inline]
32    pub fn new() -> Self {
33        Self::default()
34    }
35
36    /// Write the DWARF information to the given sections.
37    pub fn write<W: Writer>(&mut self, sections: &mut Sections<W>) -> Result<()> {
38        let line_strings = self.line_strings.write(&mut sections.debug_line_str)?;
39        let strings = self.strings.write(&mut sections.debug_str)?;
40        self.units.write(sections, &line_strings, &strings)?;
41        for line_program in &self.line_programs {
42            line_program.write(
43                &mut sections.debug_line,
44                line_program.encoding(),
45                &line_strings,
46                &strings,
47            )?;
48        }
49        Ok(())
50    }
51
52    /// Get a reference to the data for a line string.
53    pub fn get_line_string<'a>(&'a self, string: &'a LineString) -> &'a [u8] {
54        string.get(&self.strings, &self.line_strings)
55    }
56}
57
58/// Writable DWARF information for a single unit.
59#[derive(Debug)]
60pub struct DwarfUnit {
61    /// A unit. This is primarily stored in the `.debug_info` section,
62    /// but also contains information that is stored in other sections.
63    pub unit: Unit,
64
65    /// A table of strings that will be stored in the `.debug_line_str` section.
66    pub line_strings: LineStringTable,
67
68    /// A table of strings that will be stored in the `.debug_str` section.
69    pub strings: StringTable,
70}
71
72impl DwarfUnit {
73    /// Create a new `DwarfUnit`.
74    ///
75    /// Note: you should set `self.unit.line_program` after creation.
76    /// This cannot be done earlier because it may need to reference
77    /// `self.line_strings`.
78    pub fn new(encoding: Encoding) -> Self {
79        let unit = Unit::new(encoding, LineProgram::none());
80        DwarfUnit {
81            unit,
82            line_strings: LineStringTable::default(),
83            strings: StringTable::default(),
84        }
85    }
86
87    /// Write the DWARf information to the given sections.
88    pub fn write<W: Writer>(&mut self, sections: &mut Sections<W>) -> Result<()> {
89        let line_strings = self.line_strings.write(&mut sections.debug_line_str)?;
90        let strings = self.strings.write(&mut sections.debug_str)?;
91
92        let abbrev_offset = sections.debug_abbrev.offset();
93        let mut abbrevs = AbbreviationTable::default();
94
95        self.unit.write(
96            sections,
97            abbrev_offset,
98            &mut abbrevs,
99            &line_strings,
100            &strings,
101        )?;
102        // None should exist because we didn't give out any UnitId.
103        assert!(sections.debug_info_refs.is_empty());
104        assert!(sections.debug_loc_refs.is_empty());
105        assert!(sections.debug_loclists_refs.is_empty());
106
107        abbrevs.write(&mut sections.debug_abbrev)?;
108        Ok(())
109    }
110
111    /// Get a reference to the data for a line string.
112    pub fn get_line_string<'a>(&'a self, string: &'a LineString) -> &'a [u8] {
113        string.get(&self.strings, &self.line_strings)
114    }
115}
116
117#[cfg(feature = "read")]
118pub(crate) mod convert {
119    use super::*;
120    use crate::read::{self, Reader};
121    use crate::write::{Address, ConvertResult};
122
123    impl Dwarf {
124        /// Create a `write::Dwarf` by converting a `read::Dwarf`.
125        ///
126        /// `convert_address` is a function to convert read addresses into the `Address`
127        /// type. For non-relocatable addresses, this function may simply return
128        /// `Address::Constant(address)`. For relocatable addresses, it is the caller's
129        /// responsibility to determine the symbol and addend corresponding to the address
130        /// and return `Address::Symbol { symbol, addend }`.
131        pub fn from<R: Reader<Offset = usize>>(
132            dwarf: &read::Dwarf<R>,
133            convert_address: &dyn Fn(u64) -> Option<Address>,
134        ) -> ConvertResult<Dwarf> {
135            let mut line_strings = LineStringTable::default();
136            let mut strings = StringTable::default();
137            let units = UnitTable::from(dwarf, &mut line_strings, &mut strings, convert_address)?;
138            // TODO: convert the line programs that were not referenced by a unit.
139            let line_programs = Vec::new();
140            Ok(Dwarf {
141                units,
142                line_programs,
143                line_strings,
144                strings,
145            })
146        }
147    }
148}