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 ] |
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: DebugLineStrOffsets = self.line_strings.write(&mut sections.debug_line_str)?; |
39 | let strings: DebugStrOffsets = self.strings.write(&mut sections.debug_str)?; |
40 | self.units.write(sections, &line_strings, &strings)?; |
41 | for line_program: <&Vec as IntoIterator>::Item 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`. |
73 | 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. |
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 }`. |
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 | |