]>
Commit | Line | Data |
---|---|---|
fe692bf9 FG |
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 = 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`. | |
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 | } |