1 | use std::error::Error as StdError; |
2 | use std::fmt; |
3 | |
4 | pub(crate) type Result<T> = std::result::Result<T, Error>; |
5 | |
6 | /// Helper trait for converting an error to a `&dyn std::error::Error`. |
7 | pub trait AsDynError<'a> { |
8 | fn as_dyn_error(&self) -> &(dyn StdError + 'a); |
9 | } |
10 | |
11 | impl<'a, T: StdError + 'a> AsDynError<'a> for T { |
12 | #[inline ] |
13 | fn as_dyn_error(&self) -> &(dyn StdError + 'a) { |
14 | self |
15 | } |
16 | } |
17 | |
18 | /// Diagnostics (and contexts) emitted during DWARF packaging. |
19 | #[derive (Debug)] |
20 | #[non_exhaustive ] |
21 | pub enum Error { |
22 | /// Failure to read input file. |
23 | /// |
24 | /// This error occurs in the `Session::read_input` function provided by the user of `thorin`. |
25 | ReadInput(std::io::Error), |
26 | /// Failed to parse kind of input file. |
27 | /// |
28 | /// Input file kind is necessary to determine how to parse the rest of the input, and to |
29 | /// validate that the input file is of a type that `thorin` can process. |
30 | ParseFileKind(object::Error), |
31 | /// Failed to parse object file. |
32 | ParseObjectFile(object::Error), |
33 | /// Failed to parse archive file. |
34 | ParseArchiveFile(object::Error), |
35 | /// Failed to parse archive member. |
36 | ParseArchiveMember(object::Error), |
37 | /// Invalid kind of input. |
38 | /// |
39 | /// Only archive and elf files are supported input files. |
40 | InvalidInputKind, |
41 | /// Failed to decompress data. |
42 | /// |
43 | /// `thorin` uses `object` for decompression, so `object` probably didn't have support for the |
44 | /// type of compression used. |
45 | DecompressData(object::Error), |
46 | /// Section without a name. |
47 | NamelessSection(object::Error, usize), |
48 | /// Relocation has invalid symbol for a section. |
49 | RelocationWithInvalidSymbol(String, usize), |
50 | /// Multiple relocations for a section. |
51 | MultipleRelocations(String, usize), |
52 | /// Unsupported relocations for a section. |
53 | UnsupportedRelocation(String, usize), |
54 | /// Input object that has a `DwoId` (or `DebugTypeSignature`) does not have a |
55 | /// `DW_AT_GNU_dwo_name` or `DW_AT_dwo_name` attribute. |
56 | MissingDwoName(u64), |
57 | /// Input object has no compilation units. |
58 | NoCompilationUnits, |
59 | /// No top-level debugging information entry in unit. |
60 | NoDie, |
61 | /// Top-level debugging information entry is not a compilation/type unit. |
62 | TopLevelDieNotUnit, |
63 | /// Section required of input DWARF objects was missing. |
64 | MissingRequiredSection(&'static str), |
65 | /// Failed to parse unit abbreviations. |
66 | ParseUnitAbbreviations(gimli::read::Error), |
67 | /// Failed to parse unit attribute. |
68 | ParseUnitAttribute(gimli::read::Error), |
69 | /// Failed to parse unit header. |
70 | ParseUnitHeader(gimli::read::Error), |
71 | /// Failed to parse unit. |
72 | ParseUnit(gimli::read::Error), |
73 | /// Input DWARF package has a different index version than the version being output. |
74 | IncompatibleIndexVersion(String, u16, u16), |
75 | /// Failed to read string offset from `.debug_str_offsets` at index. |
76 | OffsetAtIndex(gimli::read::Error, u64), |
77 | /// Failed to read string from `.debug_str` at offset. |
78 | StrAtOffset(gimli::read::Error, usize), |
79 | /// Failed to parse index section. |
80 | /// |
81 | /// If an input file is a DWARF package, its index section needs to be read to ensure that the |
82 | /// contributions within it are preserved. |
83 | ParseIndex(gimli::read::Error, String), |
84 | /// Compilation unit in DWARF package is not its index. |
85 | UnitNotInIndex(u64), |
86 | /// Row for a compilation unit is not in the index. |
87 | RowNotInIndex(gimli::read::Error, u32), |
88 | /// Section not found in unit's row in index, i.e. a DWARF package contains a section but its |
89 | /// index doesn't record contributions to it. |
90 | SectionNotInRow, |
91 | /// Compilation unit in input DWARF object has no content. |
92 | EmptyUnit(u64), |
93 | /// Found multiple `.debug_info.dwo` sections. |
94 | MultipleDebugInfoSection, |
95 | /// Found multiple `.debug_types.dwo` sections in a DWARF package file. |
96 | MultipleDebugTypesSection, |
97 | /// Found a regular compilation unit in a DWARF object. |
98 | NotSplitUnit, |
99 | /// Found duplicate split compilation unit. |
100 | DuplicateUnit(u64), |
101 | /// Unit referenced by an executable was not found. |
102 | MissingReferencedUnit(u64), |
103 | /// No output object was created from inputs |
104 | NoOutputObjectCreated, |
105 | /// Input objects have different encodings. |
106 | MixedInputEncodings, |
107 | |
108 | /// Catch-all for `std::io::Error`. |
109 | Io(std::io::Error), |
110 | /// Catch-all for `object::Error`. |
111 | ObjectRead(object::Error), |
112 | /// Catch-all for `object::write::Error`. |
113 | ObjectWrite(object::write::Error), |
114 | /// Catch-all for `gimli::read::Error`. |
115 | GimliRead(gimli::read::Error), |
116 | /// Catch-all for `gimli::write::Error`. |
117 | GimliWrite(gimli::write::Error), |
118 | } |
119 | |
120 | impl StdError for Error { |
121 | fn source(&self) -> Option<&(dyn StdError + 'static)> { |
122 | match self { |
123 | Error::ReadInput(source) => Some(source.as_dyn_error()), |
124 | Error::ParseFileKind(source) => Some(source.as_dyn_error()), |
125 | Error::ParseObjectFile(source) => Some(source.as_dyn_error()), |
126 | Error::ParseArchiveFile(source) => Some(source.as_dyn_error()), |
127 | Error::ParseArchiveMember(source) => Some(source.as_dyn_error()), |
128 | Error::InvalidInputKind => None, |
129 | Error::DecompressData(source) => Some(source.as_dyn_error()), |
130 | Error::NamelessSection(source, _) => Some(source.as_dyn_error()), |
131 | Error::RelocationWithInvalidSymbol(_, _) => None, |
132 | Error::MultipleRelocations(_, _) => None, |
133 | Error::UnsupportedRelocation(_, _) => None, |
134 | Error::MissingDwoName(_) => None, |
135 | Error::NoCompilationUnits => None, |
136 | Error::NoDie => None, |
137 | Error::TopLevelDieNotUnit => None, |
138 | Error::MissingRequiredSection(_) => None, |
139 | Error::ParseUnitAbbreviations(source) => Some(source.as_dyn_error()), |
140 | Error::ParseUnitAttribute(source) => Some(source.as_dyn_error()), |
141 | Error::ParseUnitHeader(source) => Some(source.as_dyn_error()), |
142 | Error::ParseUnit(source) => Some(source.as_dyn_error()), |
143 | Error::IncompatibleIndexVersion(_, _, _) => None, |
144 | Error::OffsetAtIndex(source, _) => Some(source.as_dyn_error()), |
145 | Error::StrAtOffset(source, _) => Some(source.as_dyn_error()), |
146 | Error::ParseIndex(source, _) => Some(source.as_dyn_error()), |
147 | Error::UnitNotInIndex(_) => None, |
148 | Error::RowNotInIndex(source, _) => Some(source.as_dyn_error()), |
149 | Error::SectionNotInRow => None, |
150 | Error::EmptyUnit(_) => None, |
151 | Error::MultipleDebugInfoSection => None, |
152 | Error::MultipleDebugTypesSection => None, |
153 | Error::NotSplitUnit => None, |
154 | Error::DuplicateUnit(_) => None, |
155 | Error::MissingReferencedUnit(_) => None, |
156 | Error::NoOutputObjectCreated => None, |
157 | Error::MixedInputEncodings => None, |
158 | Error::Io(transparent) => StdError::source(transparent.as_dyn_error()), |
159 | Error::ObjectRead(transparent) => StdError::source(transparent.as_dyn_error()), |
160 | Error::ObjectWrite(transparent) => StdError::source(transparent.as_dyn_error()), |
161 | Error::GimliRead(transparent) => StdError::source(transparent.as_dyn_error()), |
162 | Error::GimliWrite(transparent) => StdError::source(transparent.as_dyn_error()), |
163 | } |
164 | } |
165 | } |
166 | |
167 | impl fmt::Display for Error { |
168 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
169 | match self { |
170 | Error::ReadInput(_) => write!(f, "Failed to read input file" ), |
171 | Error::ParseFileKind(_) => write!(f, "Failed to parse input file kind" ), |
172 | Error::ParseObjectFile(_) => write!(f, "Failed to parse input object file" ), |
173 | Error::ParseArchiveFile(_) => write!(f, "Failed to parse input archive file" ), |
174 | Error::ParseArchiveMember(_) => write!(f, "Failed to parse archive member" ), |
175 | Error::InvalidInputKind => write!(f, "Input is not an archive or elf object" ), |
176 | Error::DecompressData(_) => write!(f, "Failed to decompress compressed section" ), |
177 | Error::NamelessSection(_, offset) => { |
178 | write!(f, "Section without name at offset 0x {:08x}" , offset) |
179 | } |
180 | Error::RelocationWithInvalidSymbol(section, offset) => write!( |
181 | f, |
182 | "Relocation with invalid symbol for section ` {}` at offset 0x {:08x}" , |
183 | section, offset |
184 | ), |
185 | Error::MultipleRelocations(section, offset) => write!( |
186 | f, |
187 | "Multiple relocations for section ` {}` at offset 0x {:08x}" , |
188 | section, offset |
189 | ), |
190 | Error::UnsupportedRelocation(section, offset) => write!( |
191 | f, |
192 | "Unsupported relocation for section {} at offset 0x {:08x}" , |
193 | section, offset |
194 | ), |
195 | Error::MissingDwoName(id) => { |
196 | write!(f, "Missing path attribute to DWARF object (0x {:08x})" , id) |
197 | } |
198 | Error::NoCompilationUnits => { |
199 | write!(f, "Input object has no compilation units" ) |
200 | } |
201 | Error::NoDie => { |
202 | write!(f, "No top-level debugging information entry in compilation/type unit" ) |
203 | } |
204 | Error::TopLevelDieNotUnit => { |
205 | write!(f, "Top-level debugging information entry is not a compilation/type unit" ) |
206 | } |
207 | Error::MissingRequiredSection(section) => { |
208 | write!(f, "Input object missing required section ` {}`" , section) |
209 | } |
210 | Error::ParseUnitAbbreviations(_) => write!(f, "Failed to parse unit abbreviations" ), |
211 | Error::ParseUnitAttribute(_) => write!(f, "Failed to parse unit attribute" ), |
212 | Error::ParseUnitHeader(_) => write!(f, "Failed to parse unit header" ), |
213 | Error::ParseUnit(_) => write!(f, "Failed to parse unit" ), |
214 | Error::IncompatibleIndexVersion(section, format, actual) => { |
215 | write!( |
216 | f, |
217 | "Incompatible ` {}` index version: found version {}, expected version {}" , |
218 | section, actual, format |
219 | ) |
220 | } |
221 | Error::OffsetAtIndex(_, index) => { |
222 | write!(f, "Read offset at index {} of `.debug_str_offsets.dwo` section" , index) |
223 | } |
224 | Error::StrAtOffset(_, offset) => { |
225 | write!(f, "Read string at offset 0x {:08x} of `.debug_str.dwo` section" , offset) |
226 | } |
227 | Error::ParseIndex(_, section) => { |
228 | write!(f, "Failed to parse ` {}` index section" , section) |
229 | } |
230 | Error::UnitNotInIndex(unit) => { |
231 | write!(f, "Unit 0x {0:08x} from input package is not in its index" , unit) |
232 | } |
233 | Error::RowNotInIndex(_, row) => { |
234 | write!(f, "Row {0} found in index's hash table not present in index" , row) |
235 | } |
236 | Error::SectionNotInRow => write!(f, "Section not found in unit's row in index" ), |
237 | Error::EmptyUnit(unit) => { |
238 | write!(f, "Unit 0x {:08x} in input DWARF object with no data" , unit) |
239 | } |
240 | Error::MultipleDebugInfoSection => { |
241 | write!(f, "Multiple `.debug_info.dwo` sections" ) |
242 | } |
243 | Error::MultipleDebugTypesSection => { |
244 | write!(f, "Multiple `.debug_types.dwo` sections in a package" ) |
245 | } |
246 | Error::NotSplitUnit => { |
247 | write!(f, "Regular compilation unit in object (missing dwo identifier)" ) |
248 | } |
249 | Error::DuplicateUnit(unit) => { |
250 | write!(f, "Duplicate split compilation unit (0x {:08x})" , unit) |
251 | } |
252 | Error::MissingReferencedUnit(unit) => { |
253 | write!(f, "Unit 0x {:08x} referenced by executable was not found" , unit) |
254 | } |
255 | Error::NoOutputObjectCreated => write!(f, "No output object was created from inputs" ), |
256 | Error::MixedInputEncodings => write!(f, "Input objects haved mixed encodings" ), |
257 | Error::Io(e) => fmt::Display::fmt(e, f), |
258 | Error::ObjectRead(e) => fmt::Display::fmt(e, f), |
259 | Error::ObjectWrite(e) => fmt::Display::fmt(e, f), |
260 | Error::GimliRead(e) => fmt::Display::fmt(e, f), |
261 | Error::GimliWrite(e) => fmt::Display::fmt(e, f), |
262 | } |
263 | } |
264 | } |
265 | |
266 | impl From<std::io::Error> for Error { |
267 | fn from(source: std::io::Error) -> Self { |
268 | Error::Io(source) |
269 | } |
270 | } |
271 | |
272 | impl From<object::Error> for Error { |
273 | fn from(source: object::Error) -> Self { |
274 | Error::ObjectRead(source) |
275 | } |
276 | } |
277 | |
278 | impl From<object::write::Error> for Error { |
279 | fn from(source: object::write::Error) -> Self { |
280 | Error::ObjectWrite(source) |
281 | } |
282 | } |
283 | |
284 | impl From<gimli::read::Error> for Error { |
285 | fn from(source: gimli::read::Error) -> Self { |
286 | Error::GimliRead(source) |
287 | } |
288 | } |
289 | |
290 | impl From<gimli::write::Error> for Error { |
291 | fn from(source: gimli::write::Error) -> Self { |
292 | Error::GimliWrite(source) |
293 | } |
294 | } |
295 | |