1 use alloc::vec::Vec;
2 
3 use crate::common::Encoding;
4 use crate::write::{
5     AbbreviationTable, LineProgram, LineStringTable, Result, Sections, StringTable, Unit,
6     UnitTable, Writer,
7 };
8 
9 /// Writable DWARF information for more than one unit.
10 #[derive(Debug, Default)]
11 pub 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 
29 impl Dwarf {
30     /// Create a new `Dwarf` instance.
31     #[inline]
new() -> Self32     pub fn new() -> Self {
33         Self::default()
34     }
35 
36     /// Write the DWARF information to the given sections.
write<W: Writer>(&mut self, sections: &mut Sections<W>) -> Result<()>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 
53 /// Writable DWARF information for a single unit.
54 #[derive(Debug)]
55 pub struct DwarfUnit {
56     /// A unit. This is primarily stored in the `.debug_info` section,
57     /// but also contains information that is stored in other sections.
58     pub unit: Unit,
59 
60     /// A table of strings that will be stored in the `.debug_line_str` section.
61     pub line_strings: LineStringTable,
62 
63     /// A table of strings that will be stored in the `.debug_str` section.
64     pub strings: StringTable,
65 }
66 
67 impl DwarfUnit {
68     /// Create a new `DwarfUnit`.
69     ///
70     /// Note: you should set `self.unit.line_program` after creation.
71     /// This cannot be done earlier because it may need to reference
72     /// `self.line_strings`.
new(encoding: Encoding) -> Self73     pub fn new(encoding: Encoding) -> Self {
74         let unit = Unit::new(encoding, LineProgram::none());
75         DwarfUnit {
76             unit,
77             line_strings: LineStringTable::default(),
78             strings: StringTable::default(),
79         }
80     }
81 
82     /// Write the DWARf information to the given sections.
write<W: Writer>(&mut self, sections: &mut Sections<W>) -> Result<()>83     pub fn write<W: Writer>(&mut self, sections: &mut Sections<W>) -> Result<()> {
84         let line_strings = self.line_strings.write(&mut sections.debug_line_str)?;
85         let strings = self.strings.write(&mut sections.debug_str)?;
86 
87         let abbrev_offset = sections.debug_abbrev.offset();
88         let mut abbrevs = AbbreviationTable::default();
89 
90         self.unit.write(
91             sections,
92             abbrev_offset,
93             &mut abbrevs,
94             &line_strings,
95             &strings,
96         )?;
97         // None should exist because we didn't give out any UnitId.
98         assert!(sections.debug_info_refs.is_empty());
99         assert!(sections.debug_loc_refs.is_empty());
100         assert!(sections.debug_loclists_refs.is_empty());
101 
102         abbrevs.write(&mut sections.debug_abbrev)?;
103         Ok(())
104     }
105 }
106 
107 #[cfg(feature = "read")]
108 pub(crate) mod convert {
109     use super::*;
110     use crate::read::{self, Reader};
111     use crate::write::{Address, ConvertResult};
112 
113     impl Dwarf {
114         /// Create a `write::Dwarf` by converting a `read::Dwarf`.
115         ///
116         /// `convert_address` is a function to convert read addresses into the `Address`
117         /// type. For non-relocatable addresses, this function may simply return
118         /// `Address::Constant(address)`. For relocatable addresses, it is the caller's
119         /// responsibility to determine the symbol and addend corresponding to the address
120         /// and return `Address::Symbol { symbol, addend }`.
from<R: Reader<Offset = usize>>( dwarf: &read::Dwarf<R>, convert_address: &dyn Fn(u64) -> Option<Address>, ) -> ConvertResult<Dwarf>121         pub fn from<R: Reader<Offset = usize>>(
122             dwarf: &read::Dwarf<R>,
123             convert_address: &dyn Fn(u64) -> Option<Address>,
124         ) -> ConvertResult<Dwarf> {
125             let mut line_strings = LineStringTable::default();
126             let mut strings = StringTable::default();
127             let units = UnitTable::from(dwarf, &mut line_strings, &mut strings, convert_address)?;
128             // TODO: convert the line programs that were not referenced by a unit.
129             let line_programs = Vec::new();
130             Ok(Dwarf {
131                 units,
132                 line_programs,
133                 line_strings,
134                 strings,
135             })
136         }
137     }
138 }
139