]>
Commit | Line | Data |
---|---|---|
a2a8927a XL |
1 | use alloc::fmt; |
2 | use alloc::vec::Vec; | |
3 | use core::marker::PhantomData; | |
4 | ||
5 | #[cfg(feature = "coff")] | |
6 | use crate::read::coff; | |
7 | #[cfg(feature = "elf")] | |
8 | use crate::read::elf; | |
9 | #[cfg(feature = "macho")] | |
10 | use crate::read::macho; | |
11 | #[cfg(feature = "pe")] | |
12 | use crate::read::pe; | |
13 | #[cfg(feature = "wasm")] | |
14 | use crate::read::wasm; | |
f25598a0 FG |
15 | #[cfg(feature = "xcoff")] |
16 | use crate::read::xcoff; | |
a2a8927a XL |
17 | use crate::read::{ |
18 | self, Architecture, BinaryFormat, CodeView, ComdatKind, CompressedData, CompressedFileRange, | |
19 | Error, Export, FileFlags, FileKind, Import, Object, ObjectComdat, ObjectKind, ObjectMap, | |
20 | ObjectSection, ObjectSegment, ObjectSymbol, ObjectSymbolTable, ReadRef, Relocation, Result, | |
5099ac24 FG |
21 | SectionFlags, SectionIndex, SectionKind, SegmentFlags, SymbolFlags, SymbolIndex, SymbolKind, |
22 | SymbolMap, SymbolMapName, SymbolScope, SymbolSection, | |
a2a8927a XL |
23 | }; |
24 | #[allow(unused_imports)] | |
5099ac24 | 25 | use crate::{AddressSize, Endian, Endianness}; |
a2a8927a XL |
26 | |
27 | /// Evaluate an expression on the contents of a file format enum. | |
28 | /// | |
29 | /// This is a hack to avoid virtual calls. | |
30 | macro_rules! with_inner { | |
31 | ($inner:expr, $enum:ident, | $var:ident | $body:expr) => { | |
32 | match $inner { | |
33 | #[cfg(feature = "coff")] | |
34 | $enum::Coff(ref $var) => $body, | |
35 | #[cfg(feature = "elf")] | |
36 | $enum::Elf32(ref $var) => $body, | |
37 | #[cfg(feature = "elf")] | |
38 | $enum::Elf64(ref $var) => $body, | |
39 | #[cfg(feature = "macho")] | |
40 | $enum::MachO32(ref $var) => $body, | |
41 | #[cfg(feature = "macho")] | |
42 | $enum::MachO64(ref $var) => $body, | |
43 | #[cfg(feature = "pe")] | |
44 | $enum::Pe32(ref $var) => $body, | |
45 | #[cfg(feature = "pe")] | |
46 | $enum::Pe64(ref $var) => $body, | |
47 | #[cfg(feature = "wasm")] | |
48 | $enum::Wasm(ref $var) => $body, | |
f25598a0 FG |
49 | #[cfg(feature = "xcoff")] |
50 | $enum::Xcoff32(ref $var) => $body, | |
51 | #[cfg(feature = "xcoff")] | |
52 | $enum::Xcoff64(ref $var) => $body, | |
a2a8927a XL |
53 | } |
54 | }; | |
55 | } | |
56 | ||
57 | macro_rules! with_inner_mut { | |
58 | ($inner:expr, $enum:ident, | $var:ident | $body:expr) => { | |
59 | match $inner { | |
60 | #[cfg(feature = "coff")] | |
61 | $enum::Coff(ref mut $var) => $body, | |
62 | #[cfg(feature = "elf")] | |
63 | $enum::Elf32(ref mut $var) => $body, | |
64 | #[cfg(feature = "elf")] | |
65 | $enum::Elf64(ref mut $var) => $body, | |
66 | #[cfg(feature = "macho")] | |
67 | $enum::MachO32(ref mut $var) => $body, | |
68 | #[cfg(feature = "macho")] | |
69 | $enum::MachO64(ref mut $var) => $body, | |
70 | #[cfg(feature = "pe")] | |
71 | $enum::Pe32(ref mut $var) => $body, | |
72 | #[cfg(feature = "pe")] | |
73 | $enum::Pe64(ref mut $var) => $body, | |
74 | #[cfg(feature = "wasm")] | |
75 | $enum::Wasm(ref mut $var) => $body, | |
f25598a0 FG |
76 | #[cfg(feature = "xcoff")] |
77 | $enum::Xcoff32(ref mut $var) => $body, | |
78 | #[cfg(feature = "xcoff")] | |
79 | $enum::Xcoff64(ref mut $var) => $body, | |
a2a8927a XL |
80 | } |
81 | }; | |
82 | } | |
83 | ||
84 | /// Like `with_inner!`, but wraps the result in another enum. | |
85 | macro_rules! map_inner { | |
86 | ($inner:expr, $from:ident, $to:ident, | $var:ident | $body:expr) => { | |
87 | match $inner { | |
88 | #[cfg(feature = "coff")] | |
89 | $from::Coff(ref $var) => $to::Coff($body), | |
90 | #[cfg(feature = "elf")] | |
91 | $from::Elf32(ref $var) => $to::Elf32($body), | |
92 | #[cfg(feature = "elf")] | |
93 | $from::Elf64(ref $var) => $to::Elf64($body), | |
94 | #[cfg(feature = "macho")] | |
95 | $from::MachO32(ref $var) => $to::MachO32($body), | |
96 | #[cfg(feature = "macho")] | |
97 | $from::MachO64(ref $var) => $to::MachO64($body), | |
98 | #[cfg(feature = "pe")] | |
99 | $from::Pe32(ref $var) => $to::Pe32($body), | |
100 | #[cfg(feature = "pe")] | |
101 | $from::Pe64(ref $var) => $to::Pe64($body), | |
102 | #[cfg(feature = "wasm")] | |
103 | $from::Wasm(ref $var) => $to::Wasm($body), | |
f25598a0 FG |
104 | #[cfg(feature = "xcoff")] |
105 | $from::Xcoff32(ref $var) => $to::Xcoff32($body), | |
106 | #[cfg(feature = "xcoff")] | |
107 | $from::Xcoff64(ref $var) => $to::Xcoff64($body), | |
a2a8927a XL |
108 | } |
109 | }; | |
110 | } | |
111 | ||
112 | /// Like `map_inner!`, but the result is a Result or Option. | |
113 | macro_rules! map_inner_option { | |
114 | ($inner:expr, $from:ident, $to:ident, | $var:ident | $body:expr) => { | |
115 | match $inner { | |
116 | #[cfg(feature = "coff")] | |
117 | $from::Coff(ref $var) => $body.map($to::Coff), | |
118 | #[cfg(feature = "elf")] | |
119 | $from::Elf32(ref $var) => $body.map($to::Elf32), | |
120 | #[cfg(feature = "elf")] | |
121 | $from::Elf64(ref $var) => $body.map($to::Elf64), | |
122 | #[cfg(feature = "macho")] | |
123 | $from::MachO32(ref $var) => $body.map($to::MachO32), | |
124 | #[cfg(feature = "macho")] | |
125 | $from::MachO64(ref $var) => $body.map($to::MachO64), | |
126 | #[cfg(feature = "pe")] | |
127 | $from::Pe32(ref $var) => $body.map($to::Pe32), | |
128 | #[cfg(feature = "pe")] | |
129 | $from::Pe64(ref $var) => $body.map($to::Pe64), | |
130 | #[cfg(feature = "wasm")] | |
131 | $from::Wasm(ref $var) => $body.map($to::Wasm), | |
f25598a0 FG |
132 | #[cfg(feature = "xcoff")] |
133 | $from::Xcoff32(ref $var) => $body.map($to::Xcoff32), | |
134 | #[cfg(feature = "xcoff")] | |
135 | $from::Xcoff64(ref $var) => $body.map($to::Xcoff64), | |
a2a8927a XL |
136 | } |
137 | }; | |
138 | } | |
139 | ||
140 | macro_rules! map_inner_option_mut { | |
141 | ($inner:expr, $from:ident, $to:ident, | $var:ident | $body:expr) => { | |
142 | match $inner { | |
143 | #[cfg(feature = "coff")] | |
144 | $from::Coff(ref mut $var) => $body.map($to::Coff), | |
145 | #[cfg(feature = "elf")] | |
146 | $from::Elf32(ref mut $var) => $body.map($to::Elf32), | |
147 | #[cfg(feature = "elf")] | |
148 | $from::Elf64(ref mut $var) => $body.map($to::Elf64), | |
149 | #[cfg(feature = "macho")] | |
150 | $from::MachO32(ref mut $var) => $body.map($to::MachO32), | |
151 | #[cfg(feature = "macho")] | |
152 | $from::MachO64(ref mut $var) => $body.map($to::MachO64), | |
153 | #[cfg(feature = "pe")] | |
154 | $from::Pe32(ref mut $var) => $body.map($to::Pe32), | |
155 | #[cfg(feature = "pe")] | |
156 | $from::Pe64(ref mut $var) => $body.map($to::Pe64), | |
157 | #[cfg(feature = "wasm")] | |
158 | $from::Wasm(ref mut $var) => $body.map($to::Wasm), | |
f25598a0 FG |
159 | #[cfg(feature = "xcoff")] |
160 | $from::Xcoff32(ref mut $var) => $body.map($to::Xcoff32), | |
161 | #[cfg(feature = "xcoff")] | |
162 | $from::Xcoff64(ref mut $var) => $body.map($to::Xcoff64), | |
a2a8927a XL |
163 | } |
164 | }; | |
165 | } | |
166 | ||
167 | /// Call `next` for a file format iterator. | |
168 | macro_rules! next_inner { | |
169 | ($inner:expr, $from:ident, $to:ident) => { | |
170 | match $inner { | |
171 | #[cfg(feature = "coff")] | |
172 | $from::Coff(ref mut iter) => iter.next().map($to::Coff), | |
173 | #[cfg(feature = "elf")] | |
174 | $from::Elf32(ref mut iter) => iter.next().map($to::Elf32), | |
175 | #[cfg(feature = "elf")] | |
176 | $from::Elf64(ref mut iter) => iter.next().map($to::Elf64), | |
177 | #[cfg(feature = "macho")] | |
178 | $from::MachO32(ref mut iter) => iter.next().map($to::MachO32), | |
179 | #[cfg(feature = "macho")] | |
180 | $from::MachO64(ref mut iter) => iter.next().map($to::MachO64), | |
181 | #[cfg(feature = "pe")] | |
182 | $from::Pe32(ref mut iter) => iter.next().map($to::Pe32), | |
183 | #[cfg(feature = "pe")] | |
184 | $from::Pe64(ref mut iter) => iter.next().map($to::Pe64), | |
185 | #[cfg(feature = "wasm")] | |
186 | $from::Wasm(ref mut iter) => iter.next().map($to::Wasm), | |
f25598a0 FG |
187 | #[cfg(feature = "xcoff")] |
188 | $from::Xcoff32(ref mut iter) => iter.next().map($to::Xcoff32), | |
189 | #[cfg(feature = "xcoff")] | |
190 | $from::Xcoff64(ref mut iter) => iter.next().map($to::Xcoff64), | |
a2a8927a XL |
191 | } |
192 | }; | |
193 | } | |
194 | ||
195 | /// An object file. | |
196 | /// | |
197 | /// Most functionality is provided by the `Object` trait implementation. | |
198 | #[derive(Debug)] | |
199 | pub struct File<'data, R: ReadRef<'data> = &'data [u8]> { | |
200 | inner: FileInternal<'data, R>, | |
201 | } | |
202 | ||
203 | #[derive(Debug)] | |
204 | enum FileInternal<'data, R: ReadRef<'data>> { | |
205 | #[cfg(feature = "coff")] | |
206 | Coff(coff::CoffFile<'data, R>), | |
207 | #[cfg(feature = "elf")] | |
208 | Elf32(elf::ElfFile32<'data, Endianness, R>), | |
209 | #[cfg(feature = "elf")] | |
210 | Elf64(elf::ElfFile64<'data, Endianness, R>), | |
211 | #[cfg(feature = "macho")] | |
212 | MachO32(macho::MachOFile32<'data, Endianness, R>), | |
213 | #[cfg(feature = "macho")] | |
214 | MachO64(macho::MachOFile64<'data, Endianness, R>), | |
215 | #[cfg(feature = "pe")] | |
216 | Pe32(pe::PeFile32<'data, R>), | |
217 | #[cfg(feature = "pe")] | |
218 | Pe64(pe::PeFile64<'data, R>), | |
219 | #[cfg(feature = "wasm")] | |
220 | Wasm(wasm::WasmFile<'data, R>), | |
f25598a0 FG |
221 | #[cfg(feature = "xcoff")] |
222 | Xcoff32(xcoff::XcoffFile32<'data, R>), | |
223 | #[cfg(feature = "xcoff")] | |
224 | Xcoff64(xcoff::XcoffFile64<'data, R>), | |
a2a8927a XL |
225 | } |
226 | ||
227 | impl<'data, R: ReadRef<'data>> File<'data, R> { | |
228 | /// Parse the raw file data. | |
229 | pub fn parse(data: R) -> Result<Self> { | |
230 | let inner = match FileKind::parse(data)? { | |
231 | #[cfg(feature = "elf")] | |
232 | FileKind::Elf32 => FileInternal::Elf32(elf::ElfFile32::parse(data)?), | |
233 | #[cfg(feature = "elf")] | |
234 | FileKind::Elf64 => FileInternal::Elf64(elf::ElfFile64::parse(data)?), | |
235 | #[cfg(feature = "macho")] | |
236 | FileKind::MachO32 => FileInternal::MachO32(macho::MachOFile32::parse(data)?), | |
237 | #[cfg(feature = "macho")] | |
238 | FileKind::MachO64 => FileInternal::MachO64(macho::MachOFile64::parse(data)?), | |
239 | #[cfg(feature = "wasm")] | |
240 | FileKind::Wasm => FileInternal::Wasm(wasm::WasmFile::parse(data)?), | |
241 | #[cfg(feature = "pe")] | |
242 | FileKind::Pe32 => FileInternal::Pe32(pe::PeFile32::parse(data)?), | |
243 | #[cfg(feature = "pe")] | |
244 | FileKind::Pe64 => FileInternal::Pe64(pe::PeFile64::parse(data)?), | |
245 | #[cfg(feature = "coff")] | |
246 | FileKind::Coff => FileInternal::Coff(coff::CoffFile::parse(data)?), | |
f25598a0 FG |
247 | #[cfg(feature = "xcoff")] |
248 | FileKind::Xcoff32 => FileInternal::Xcoff32(xcoff::XcoffFile32::parse(data)?), | |
249 | #[cfg(feature = "xcoff")] | |
250 | FileKind::Xcoff64 => FileInternal::Xcoff64(xcoff::XcoffFile64::parse(data)?), | |
a2a8927a XL |
251 | #[allow(unreachable_patterns)] |
252 | _ => return Err(Error("Unsupported file format")), | |
253 | }; | |
254 | Ok(File { inner }) | |
255 | } | |
256 | ||
5099ac24 FG |
257 | /// Parse a Mach-O image from the dyld shared cache. |
258 | #[cfg(feature = "macho")] | |
259 | pub fn parse_dyld_cache_image<'cache, E: Endian>( | |
260 | image: &macho::DyldCacheImage<'data, 'cache, E, R>, | |
261 | ) -> Result<Self> { | |
262 | let inner = match image.cache.architecture().address_size() { | |
263 | Some(AddressSize::U64) => { | |
264 | FileInternal::MachO64(macho::MachOFile64::parse_dyld_cache_image(image)?) | |
265 | } | |
266 | Some(AddressSize::U32) => { | |
267 | FileInternal::MachO32(macho::MachOFile32::parse_dyld_cache_image(image)?) | |
268 | } | |
a2a8927a XL |
269 | _ => return Err(Error("Unsupported file format")), |
270 | }; | |
5099ac24 | 271 | Ok(File { inner }) |
a2a8927a XL |
272 | } |
273 | ||
274 | /// Return the file format. | |
275 | pub fn format(&self) -> BinaryFormat { | |
276 | match self.inner { | |
277 | #[cfg(feature = "coff")] | |
278 | FileInternal::Coff(_) => BinaryFormat::Coff, | |
279 | #[cfg(feature = "elf")] | |
280 | FileInternal::Elf32(_) | FileInternal::Elf64(_) => BinaryFormat::Elf, | |
281 | #[cfg(feature = "macho")] | |
282 | FileInternal::MachO32(_) | FileInternal::MachO64(_) => BinaryFormat::MachO, | |
283 | #[cfg(feature = "pe")] | |
284 | FileInternal::Pe32(_) | FileInternal::Pe64(_) => BinaryFormat::Pe, | |
285 | #[cfg(feature = "wasm")] | |
286 | FileInternal::Wasm(_) => BinaryFormat::Wasm, | |
f25598a0 FG |
287 | #[cfg(feature = "xcoff")] |
288 | FileInternal::Xcoff32(_) | FileInternal::Xcoff64(_) => BinaryFormat::Xcoff, | |
a2a8927a XL |
289 | } |
290 | } | |
291 | } | |
292 | ||
293 | impl<'data, R: ReadRef<'data>> read::private::Sealed for File<'data, R> {} | |
294 | ||
295 | impl<'data, 'file, R> Object<'data, 'file> for File<'data, R> | |
296 | where | |
297 | 'data: 'file, | |
298 | R: 'file + ReadRef<'data>, | |
299 | { | |
300 | type Segment = Segment<'data, 'file, R>; | |
301 | type SegmentIterator = SegmentIterator<'data, 'file, R>; | |
302 | type Section = Section<'data, 'file, R>; | |
303 | type SectionIterator = SectionIterator<'data, 'file, R>; | |
304 | type Comdat = Comdat<'data, 'file, R>; | |
305 | type ComdatIterator = ComdatIterator<'data, 'file, R>; | |
306 | type Symbol = Symbol<'data, 'file, R>; | |
307 | type SymbolIterator = SymbolIterator<'data, 'file, R>; | |
308 | type SymbolTable = SymbolTable<'data, 'file, R>; | |
309 | type DynamicRelocationIterator = DynamicRelocationIterator<'data, 'file, R>; | |
310 | ||
311 | fn architecture(&self) -> Architecture { | |
312 | with_inner!(self.inner, FileInternal, |x| x.architecture()) | |
313 | } | |
314 | ||
315 | fn is_little_endian(&self) -> bool { | |
316 | with_inner!(self.inner, FileInternal, |x| x.is_little_endian()) | |
317 | } | |
318 | ||
319 | fn is_64(&self) -> bool { | |
320 | with_inner!(self.inner, FileInternal, |x| x.is_64()) | |
321 | } | |
322 | ||
323 | fn kind(&self) -> ObjectKind { | |
324 | with_inner!(self.inner, FileInternal, |x| x.kind()) | |
325 | } | |
326 | ||
327 | fn segments(&'file self) -> SegmentIterator<'data, 'file, R> { | |
328 | SegmentIterator { | |
329 | inner: map_inner!(self.inner, FileInternal, SegmentIteratorInternal, |x| x | |
330 | .segments()), | |
331 | } | |
332 | } | |
333 | ||
334 | fn section_by_name_bytes(&'file self, section_name: &[u8]) -> Option<Section<'data, 'file, R>> { | |
335 | map_inner_option!(self.inner, FileInternal, SectionInternal, |x| x | |
336 | .section_by_name_bytes(section_name)) | |
337 | .map(|inner| Section { inner }) | |
338 | } | |
339 | ||
340 | fn section_by_index(&'file self, index: SectionIndex) -> Result<Section<'data, 'file, R>> { | |
341 | map_inner_option!(self.inner, FileInternal, SectionInternal, |x| x | |
342 | .section_by_index(index)) | |
343 | .map(|inner| Section { inner }) | |
344 | } | |
345 | ||
346 | fn sections(&'file self) -> SectionIterator<'data, 'file, R> { | |
347 | SectionIterator { | |
348 | inner: map_inner!(self.inner, FileInternal, SectionIteratorInternal, |x| x | |
349 | .sections()), | |
350 | } | |
351 | } | |
352 | ||
353 | fn comdats(&'file self) -> ComdatIterator<'data, 'file, R> { | |
354 | ComdatIterator { | |
355 | inner: map_inner!(self.inner, FileInternal, ComdatIteratorInternal, |x| x | |
356 | .comdats()), | |
357 | } | |
358 | } | |
359 | ||
360 | fn symbol_by_index(&'file self, index: SymbolIndex) -> Result<Symbol<'data, 'file, R>> { | |
361 | map_inner_option!(self.inner, FileInternal, SymbolInternal, |x| x | |
362 | .symbol_by_index(index) | |
363 | .map(|x| (x, PhantomData))) | |
364 | .map(|inner| Symbol { inner }) | |
365 | } | |
366 | ||
367 | fn symbols(&'file self) -> SymbolIterator<'data, 'file, R> { | |
368 | SymbolIterator { | |
369 | inner: map_inner!(self.inner, FileInternal, SymbolIteratorInternal, |x| ( | |
370 | x.symbols(), | |
371 | PhantomData | |
372 | )), | |
373 | } | |
374 | } | |
375 | ||
376 | fn symbol_table(&'file self) -> Option<SymbolTable<'data, 'file, R>> { | |
377 | map_inner_option!(self.inner, FileInternal, SymbolTableInternal, |x| x | |
378 | .symbol_table() | |
379 | .map(|x| (x, PhantomData))) | |
380 | .map(|inner| SymbolTable { inner }) | |
381 | } | |
382 | ||
383 | fn dynamic_symbols(&'file self) -> SymbolIterator<'data, 'file, R> { | |
384 | SymbolIterator { | |
385 | inner: map_inner!(self.inner, FileInternal, SymbolIteratorInternal, |x| ( | |
386 | x.dynamic_symbols(), | |
387 | PhantomData | |
388 | )), | |
389 | } | |
390 | } | |
391 | ||
392 | fn dynamic_symbol_table(&'file self) -> Option<SymbolTable<'data, 'file, R>> { | |
393 | map_inner_option!(self.inner, FileInternal, SymbolTableInternal, |x| x | |
394 | .dynamic_symbol_table() | |
395 | .map(|x| (x, PhantomData))) | |
396 | .map(|inner| SymbolTable { inner }) | |
397 | } | |
398 | ||
399 | #[cfg(feature = "elf")] | |
400 | fn dynamic_relocations(&'file self) -> Option<DynamicRelocationIterator<'data, 'file, R>> { | |
401 | let inner = match self.inner { | |
402 | FileInternal::Elf32(ref elf) => { | |
403 | DynamicRelocationIteratorInternal::Elf32(elf.dynamic_relocations()?) | |
404 | } | |
405 | FileInternal::Elf64(ref elf) => { | |
406 | DynamicRelocationIteratorInternal::Elf64(elf.dynamic_relocations()?) | |
407 | } | |
408 | #[allow(unreachable_patterns)] | |
409 | _ => return None, | |
410 | }; | |
411 | Some(DynamicRelocationIterator { inner }) | |
412 | } | |
413 | ||
414 | #[cfg(not(feature = "elf"))] | |
415 | fn dynamic_relocations(&'file self) -> Option<DynamicRelocationIterator<'data, 'file, R>> { | |
416 | None | |
417 | } | |
418 | ||
419 | fn symbol_map(&self) -> SymbolMap<SymbolMapName<'data>> { | |
420 | with_inner!(self.inner, FileInternal, |x| x.symbol_map()) | |
421 | } | |
422 | ||
423 | fn object_map(&self) -> ObjectMap<'data> { | |
424 | with_inner!(self.inner, FileInternal, |x| x.object_map()) | |
425 | } | |
426 | ||
427 | fn imports(&self) -> Result<Vec<Import<'data>>> { | |
428 | with_inner!(self.inner, FileInternal, |x| x.imports()) | |
429 | } | |
430 | ||
431 | fn exports(&self) -> Result<Vec<Export<'data>>> { | |
432 | with_inner!(self.inner, FileInternal, |x| x.exports()) | |
433 | } | |
434 | ||
435 | fn has_debug_symbols(&self) -> bool { | |
436 | with_inner!(self.inner, FileInternal, |x| x.has_debug_symbols()) | |
437 | } | |
438 | ||
439 | #[inline] | |
440 | fn mach_uuid(&self) -> Result<Option<[u8; 16]>> { | |
441 | with_inner!(self.inner, FileInternal, |x| x.mach_uuid()) | |
442 | } | |
443 | ||
444 | #[inline] | |
445 | fn build_id(&self) -> Result<Option<&'data [u8]>> { | |
446 | with_inner!(self.inner, FileInternal, |x| x.build_id()) | |
447 | } | |
448 | ||
449 | #[inline] | |
450 | fn gnu_debuglink(&self) -> Result<Option<(&'data [u8], u32)>> { | |
451 | with_inner!(self.inner, FileInternal, |x| x.gnu_debuglink()) | |
452 | } | |
453 | ||
454 | #[inline] | |
455 | fn gnu_debugaltlink(&self) -> Result<Option<(&'data [u8], &'data [u8])>> { | |
456 | with_inner!(self.inner, FileInternal, |x| x.gnu_debugaltlink()) | |
457 | } | |
458 | ||
459 | #[inline] | |
460 | fn pdb_info(&self) -> Result<Option<CodeView>> { | |
461 | with_inner!(self.inner, FileInternal, |x| x.pdb_info()) | |
462 | } | |
463 | ||
464 | fn relative_address_base(&self) -> u64 { | |
465 | with_inner!(self.inner, FileInternal, |x| x.relative_address_base()) | |
466 | } | |
467 | ||
468 | fn entry(&self) -> u64 { | |
469 | with_inner!(self.inner, FileInternal, |x| x.entry()) | |
470 | } | |
471 | ||
472 | fn flags(&self) -> FileFlags { | |
473 | with_inner!(self.inner, FileInternal, |x| x.flags()) | |
474 | } | |
475 | } | |
476 | ||
477 | /// An iterator over the segments of a `File`. | |
478 | #[derive(Debug)] | |
479 | pub struct SegmentIterator<'data, 'file, R: ReadRef<'data> = &'data [u8]> | |
480 | where | |
481 | 'data: 'file, | |
482 | { | |
483 | inner: SegmentIteratorInternal<'data, 'file, R>, | |
484 | } | |
485 | ||
486 | #[derive(Debug)] | |
487 | enum SegmentIteratorInternal<'data, 'file, R: ReadRef<'data>> | |
488 | where | |
489 | 'data: 'file, | |
490 | { | |
491 | #[cfg(feature = "coff")] | |
492 | Coff(coff::CoffSegmentIterator<'data, 'file, R>), | |
493 | #[cfg(feature = "elf")] | |
494 | Elf32(elf::ElfSegmentIterator32<'data, 'file, Endianness, R>), | |
495 | #[cfg(feature = "elf")] | |
496 | Elf64(elf::ElfSegmentIterator64<'data, 'file, Endianness, R>), | |
497 | #[cfg(feature = "macho")] | |
498 | MachO32(macho::MachOSegmentIterator32<'data, 'file, Endianness, R>), | |
499 | #[cfg(feature = "macho")] | |
500 | MachO64(macho::MachOSegmentIterator64<'data, 'file, Endianness, R>), | |
501 | #[cfg(feature = "pe")] | |
502 | Pe32(pe::PeSegmentIterator32<'data, 'file, R>), | |
503 | #[cfg(feature = "pe")] | |
504 | Pe64(pe::PeSegmentIterator64<'data, 'file, R>), | |
505 | #[cfg(feature = "wasm")] | |
506 | Wasm(wasm::WasmSegmentIterator<'data, 'file, R>), | |
f25598a0 FG |
507 | #[cfg(feature = "xcoff")] |
508 | Xcoff32(xcoff::XcoffSegmentIterator32<'data, 'file, R>), | |
509 | #[cfg(feature = "xcoff")] | |
510 | Xcoff64(xcoff::XcoffSegmentIterator64<'data, 'file, R>), | |
a2a8927a XL |
511 | } |
512 | ||
513 | impl<'data, 'file, R: ReadRef<'data>> Iterator for SegmentIterator<'data, 'file, R> { | |
514 | type Item = Segment<'data, 'file, R>; | |
515 | ||
516 | fn next(&mut self) -> Option<Self::Item> { | |
517 | next_inner!(self.inner, SegmentIteratorInternal, SegmentInternal) | |
518 | .map(|inner| Segment { inner }) | |
519 | } | |
520 | } | |
521 | ||
522 | /// A segment of a `File`. | |
523 | pub struct Segment<'data, 'file, R: ReadRef<'data> = &'data [u8]> | |
524 | where | |
525 | 'data: 'file, | |
526 | { | |
527 | inner: SegmentInternal<'data, 'file, R>, | |
528 | } | |
529 | ||
530 | #[derive(Debug)] | |
531 | enum SegmentInternal<'data, 'file, R: ReadRef<'data>> | |
532 | where | |
533 | 'data: 'file, | |
534 | { | |
535 | #[cfg(feature = "coff")] | |
536 | Coff(coff::CoffSegment<'data, 'file, R>), | |
537 | #[cfg(feature = "elf")] | |
538 | Elf32(elf::ElfSegment32<'data, 'file, Endianness, R>), | |
539 | #[cfg(feature = "elf")] | |
540 | Elf64(elf::ElfSegment64<'data, 'file, Endianness, R>), | |
541 | #[cfg(feature = "macho")] | |
542 | MachO32(macho::MachOSegment32<'data, 'file, Endianness, R>), | |
543 | #[cfg(feature = "macho")] | |
544 | MachO64(macho::MachOSegment64<'data, 'file, Endianness, R>), | |
545 | #[cfg(feature = "pe")] | |
546 | Pe32(pe::PeSegment32<'data, 'file, R>), | |
547 | #[cfg(feature = "pe")] | |
548 | Pe64(pe::PeSegment64<'data, 'file, R>), | |
549 | #[cfg(feature = "wasm")] | |
550 | Wasm(wasm::WasmSegment<'data, 'file, R>), | |
f25598a0 FG |
551 | #[cfg(feature = "xcoff")] |
552 | Xcoff32(xcoff::XcoffSegment32<'data, 'file, R>), | |
553 | #[cfg(feature = "xcoff")] | |
554 | Xcoff64(xcoff::XcoffSegment64<'data, 'file, R>), | |
a2a8927a XL |
555 | } |
556 | ||
557 | impl<'data, 'file, R: ReadRef<'data>> fmt::Debug for Segment<'data, 'file, R> { | |
558 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
559 | // It's painful to do much better than this | |
560 | let mut s = f.debug_struct("Segment"); | |
561 | match self.name() { | |
562 | Ok(Some(ref name)) => { | |
563 | s.field("name", name); | |
564 | } | |
565 | Ok(None) => {} | |
566 | Err(_) => { | |
567 | s.field("name", &"<invalid>"); | |
568 | } | |
569 | } | |
570 | s.field("address", &self.address()) | |
571 | .field("size", &self.size()) | |
572 | .finish() | |
573 | } | |
574 | } | |
575 | ||
576 | impl<'data, 'file, R: ReadRef<'data>> read::private::Sealed for Segment<'data, 'file, R> {} | |
577 | ||
578 | impl<'data, 'file, R: ReadRef<'data>> ObjectSegment<'data> for Segment<'data, 'file, R> { | |
579 | fn address(&self) -> u64 { | |
580 | with_inner!(self.inner, SegmentInternal, |x| x.address()) | |
581 | } | |
582 | ||
583 | fn size(&self) -> u64 { | |
584 | with_inner!(self.inner, SegmentInternal, |x| x.size()) | |
585 | } | |
586 | ||
587 | fn align(&self) -> u64 { | |
588 | with_inner!(self.inner, SegmentInternal, |x| x.align()) | |
589 | } | |
590 | ||
591 | fn file_range(&self) -> (u64, u64) { | |
592 | with_inner!(self.inner, SegmentInternal, |x| x.file_range()) | |
593 | } | |
594 | ||
595 | fn data(&self) -> Result<&'data [u8]> { | |
596 | with_inner!(self.inner, SegmentInternal, |x| x.data()) | |
597 | } | |
598 | ||
599 | fn data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>> { | |
600 | with_inner!(self.inner, SegmentInternal, |x| x.data_range(address, size)) | |
601 | } | |
602 | ||
603 | fn name_bytes(&self) -> Result<Option<&[u8]>> { | |
604 | with_inner!(self.inner, SegmentInternal, |x| x.name_bytes()) | |
605 | } | |
606 | ||
607 | fn name(&self) -> Result<Option<&str>> { | |
608 | with_inner!(self.inner, SegmentInternal, |x| x.name()) | |
609 | } | |
5099ac24 FG |
610 | |
611 | fn flags(&self) -> SegmentFlags { | |
612 | with_inner!(self.inner, SegmentInternal, |x| x.flags()) | |
613 | } | |
a2a8927a XL |
614 | } |
615 | ||
616 | /// An iterator of the sections of a `File`. | |
617 | #[derive(Debug)] | |
618 | pub struct SectionIterator<'data, 'file, R: ReadRef<'data> = &'data [u8]> | |
619 | where | |
620 | 'data: 'file, | |
621 | { | |
622 | inner: SectionIteratorInternal<'data, 'file, R>, | |
623 | } | |
624 | ||
625 | // we wrap our enums in a struct so that they are kept private. | |
626 | #[derive(Debug)] | |
627 | enum SectionIteratorInternal<'data, 'file, R: ReadRef<'data>> | |
628 | where | |
629 | 'data: 'file, | |
630 | { | |
631 | #[cfg(feature = "coff")] | |
632 | Coff(coff::CoffSectionIterator<'data, 'file, R>), | |
633 | #[cfg(feature = "elf")] | |
634 | Elf32(elf::ElfSectionIterator32<'data, 'file, Endianness, R>), | |
635 | #[cfg(feature = "elf")] | |
636 | Elf64(elf::ElfSectionIterator64<'data, 'file, Endianness, R>), | |
637 | #[cfg(feature = "macho")] | |
638 | MachO32(macho::MachOSectionIterator32<'data, 'file, Endianness, R>), | |
639 | #[cfg(feature = "macho")] | |
640 | MachO64(macho::MachOSectionIterator64<'data, 'file, Endianness, R>), | |
641 | #[cfg(feature = "pe")] | |
642 | Pe32(pe::PeSectionIterator32<'data, 'file, R>), | |
643 | #[cfg(feature = "pe")] | |
644 | Pe64(pe::PeSectionIterator64<'data, 'file, R>), | |
645 | #[cfg(feature = "wasm")] | |
646 | Wasm(wasm::WasmSectionIterator<'data, 'file, R>), | |
f25598a0 FG |
647 | #[cfg(feature = "xcoff")] |
648 | Xcoff32(xcoff::XcoffSectionIterator32<'data, 'file, R>), | |
649 | #[cfg(feature = "xcoff")] | |
650 | Xcoff64(xcoff::XcoffSectionIterator64<'data, 'file, R>), | |
a2a8927a XL |
651 | } |
652 | ||
653 | impl<'data, 'file, R: ReadRef<'data>> Iterator for SectionIterator<'data, 'file, R> { | |
654 | type Item = Section<'data, 'file, R>; | |
655 | ||
656 | fn next(&mut self) -> Option<Self::Item> { | |
657 | next_inner!(self.inner, SectionIteratorInternal, SectionInternal) | |
658 | .map(|inner| Section { inner }) | |
659 | } | |
660 | } | |
661 | ||
662 | /// A Section of a File | |
663 | pub struct Section<'data, 'file, R: ReadRef<'data> = &'data [u8]> | |
664 | where | |
665 | 'data: 'file, | |
666 | { | |
667 | inner: SectionInternal<'data, 'file, R>, | |
668 | } | |
669 | ||
670 | enum SectionInternal<'data, 'file, R: ReadRef<'data>> | |
671 | where | |
672 | 'data: 'file, | |
673 | { | |
674 | #[cfg(feature = "coff")] | |
675 | Coff(coff::CoffSection<'data, 'file, R>), | |
676 | #[cfg(feature = "elf")] | |
677 | Elf32(elf::ElfSection32<'data, 'file, Endianness, R>), | |
678 | #[cfg(feature = "elf")] | |
679 | Elf64(elf::ElfSection64<'data, 'file, Endianness, R>), | |
680 | #[cfg(feature = "macho")] | |
681 | MachO32(macho::MachOSection32<'data, 'file, Endianness, R>), | |
682 | #[cfg(feature = "macho")] | |
683 | MachO64(macho::MachOSection64<'data, 'file, Endianness, R>), | |
684 | #[cfg(feature = "pe")] | |
685 | Pe32(pe::PeSection32<'data, 'file, R>), | |
686 | #[cfg(feature = "pe")] | |
687 | Pe64(pe::PeSection64<'data, 'file, R>), | |
688 | #[cfg(feature = "wasm")] | |
689 | Wasm(wasm::WasmSection<'data, 'file, R>), | |
f25598a0 FG |
690 | #[cfg(feature = "xcoff")] |
691 | Xcoff32(xcoff::XcoffSection32<'data, 'file, R>), | |
692 | #[cfg(feature = "xcoff")] | |
693 | Xcoff64(xcoff::XcoffSection64<'data, 'file, R>), | |
a2a8927a XL |
694 | } |
695 | ||
696 | impl<'data, 'file, R: ReadRef<'data>> fmt::Debug for Section<'data, 'file, R> { | |
697 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
698 | // It's painful to do much better than this | |
699 | let mut s = f.debug_struct("Section"); | |
700 | match self.segment_name() { | |
701 | Ok(Some(ref name)) => { | |
702 | s.field("segment", name); | |
703 | } | |
704 | Ok(None) => {} | |
705 | Err(_) => { | |
706 | s.field("segment", &"<invalid>"); | |
707 | } | |
708 | } | |
709 | s.field("name", &self.name().unwrap_or("<invalid>")) | |
710 | .field("address", &self.address()) | |
711 | .field("size", &self.size()) | |
712 | .field("align", &self.align()) | |
713 | .field("kind", &self.kind()) | |
714 | .field("flags", &self.flags()) | |
715 | .finish() | |
716 | } | |
717 | } | |
718 | ||
719 | impl<'data, 'file, R: ReadRef<'data>> read::private::Sealed for Section<'data, 'file, R> {} | |
720 | ||
721 | impl<'data, 'file, R: ReadRef<'data>> ObjectSection<'data> for Section<'data, 'file, R> { | |
722 | type RelocationIterator = SectionRelocationIterator<'data, 'file, R>; | |
723 | ||
724 | fn index(&self) -> SectionIndex { | |
725 | with_inner!(self.inner, SectionInternal, |x| x.index()) | |
726 | } | |
727 | ||
728 | fn address(&self) -> u64 { | |
729 | with_inner!(self.inner, SectionInternal, |x| x.address()) | |
730 | } | |
731 | ||
732 | fn size(&self) -> u64 { | |
733 | with_inner!(self.inner, SectionInternal, |x| x.size()) | |
734 | } | |
735 | ||
736 | fn align(&self) -> u64 { | |
737 | with_inner!(self.inner, SectionInternal, |x| x.align()) | |
738 | } | |
739 | ||
740 | fn file_range(&self) -> Option<(u64, u64)> { | |
741 | with_inner!(self.inner, SectionInternal, |x| x.file_range()) | |
742 | } | |
743 | ||
744 | fn data(&self) -> Result<&'data [u8]> { | |
745 | with_inner!(self.inner, SectionInternal, |x| x.data()) | |
746 | } | |
747 | ||
748 | fn data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>> { | |
749 | with_inner!(self.inner, SectionInternal, |x| x.data_range(address, size)) | |
750 | } | |
751 | ||
752 | fn compressed_file_range(&self) -> Result<CompressedFileRange> { | |
753 | with_inner!(self.inner, SectionInternal, |x| x.compressed_file_range()) | |
754 | } | |
755 | ||
756 | fn compressed_data(&self) -> Result<CompressedData<'data>> { | |
757 | with_inner!(self.inner, SectionInternal, |x| x.compressed_data()) | |
758 | } | |
759 | ||
760 | fn name_bytes(&self) -> Result<&[u8]> { | |
761 | with_inner!(self.inner, SectionInternal, |x| x.name_bytes()) | |
762 | } | |
763 | ||
764 | fn name(&self) -> Result<&str> { | |
765 | with_inner!(self.inner, SectionInternal, |x| x.name()) | |
766 | } | |
767 | ||
768 | fn segment_name_bytes(&self) -> Result<Option<&[u8]>> { | |
769 | with_inner!(self.inner, SectionInternal, |x| x.segment_name_bytes()) | |
770 | } | |
771 | ||
772 | fn segment_name(&self) -> Result<Option<&str>> { | |
773 | with_inner!(self.inner, SectionInternal, |x| x.segment_name()) | |
774 | } | |
775 | ||
776 | fn kind(&self) -> SectionKind { | |
777 | with_inner!(self.inner, SectionInternal, |x| x.kind()) | |
778 | } | |
779 | ||
780 | fn relocations(&self) -> SectionRelocationIterator<'data, 'file, R> { | |
781 | SectionRelocationIterator { | |
782 | inner: map_inner!( | |
783 | self.inner, | |
784 | SectionInternal, | |
785 | SectionRelocationIteratorInternal, | |
786 | |x| x.relocations() | |
787 | ), | |
788 | } | |
789 | } | |
790 | ||
791 | fn flags(&self) -> SectionFlags { | |
792 | with_inner!(self.inner, SectionInternal, |x| x.flags()) | |
793 | } | |
794 | } | |
795 | ||
796 | /// An iterator of the COMDAT section groups of a `File`. | |
797 | #[derive(Debug)] | |
798 | pub struct ComdatIterator<'data, 'file, R: ReadRef<'data> = &'data [u8]> | |
799 | where | |
800 | 'data: 'file, | |
801 | { | |
802 | inner: ComdatIteratorInternal<'data, 'file, R>, | |
803 | } | |
804 | ||
805 | #[derive(Debug)] | |
806 | enum ComdatIteratorInternal<'data, 'file, R: ReadRef<'data>> | |
807 | where | |
808 | 'data: 'file, | |
809 | { | |
810 | #[cfg(feature = "coff")] | |
811 | Coff(coff::CoffComdatIterator<'data, 'file, R>), | |
812 | #[cfg(feature = "elf")] | |
813 | Elf32(elf::ElfComdatIterator32<'data, 'file, Endianness, R>), | |
814 | #[cfg(feature = "elf")] | |
815 | Elf64(elf::ElfComdatIterator64<'data, 'file, Endianness, R>), | |
816 | #[cfg(feature = "macho")] | |
817 | MachO32(macho::MachOComdatIterator32<'data, 'file, Endianness, R>), | |
818 | #[cfg(feature = "macho")] | |
819 | MachO64(macho::MachOComdatIterator64<'data, 'file, Endianness, R>), | |
820 | #[cfg(feature = "pe")] | |
821 | Pe32(pe::PeComdatIterator32<'data, 'file, R>), | |
822 | #[cfg(feature = "pe")] | |
823 | Pe64(pe::PeComdatIterator64<'data, 'file, R>), | |
824 | #[cfg(feature = "wasm")] | |
825 | Wasm(wasm::WasmComdatIterator<'data, 'file, R>), | |
f25598a0 FG |
826 | #[cfg(feature = "xcoff")] |
827 | Xcoff32(xcoff::XcoffComdatIterator32<'data, 'file, R>), | |
828 | #[cfg(feature = "xcoff")] | |
829 | Xcoff64(xcoff::XcoffComdatIterator64<'data, 'file, R>), | |
a2a8927a XL |
830 | } |
831 | ||
832 | impl<'data, 'file, R: ReadRef<'data>> Iterator for ComdatIterator<'data, 'file, R> { | |
833 | type Item = Comdat<'data, 'file, R>; | |
834 | ||
835 | fn next(&mut self) -> Option<Self::Item> { | |
836 | next_inner!(self.inner, ComdatIteratorInternal, ComdatInternal) | |
837 | .map(|inner| Comdat { inner }) | |
838 | } | |
839 | } | |
840 | ||
841 | /// A COMDAT section group of a `File`. | |
842 | pub struct Comdat<'data, 'file, R: ReadRef<'data> = &'data [u8]> | |
843 | where | |
844 | 'data: 'file, | |
845 | { | |
846 | inner: ComdatInternal<'data, 'file, R>, | |
847 | } | |
848 | ||
849 | enum ComdatInternal<'data, 'file, R: ReadRef<'data>> | |
850 | where | |
851 | 'data: 'file, | |
852 | { | |
853 | #[cfg(feature = "coff")] | |
854 | Coff(coff::CoffComdat<'data, 'file, R>), | |
855 | #[cfg(feature = "elf")] | |
856 | Elf32(elf::ElfComdat32<'data, 'file, Endianness, R>), | |
857 | #[cfg(feature = "elf")] | |
858 | Elf64(elf::ElfComdat64<'data, 'file, Endianness, R>), | |
859 | #[cfg(feature = "macho")] | |
860 | MachO32(macho::MachOComdat32<'data, 'file, Endianness, R>), | |
861 | #[cfg(feature = "macho")] | |
862 | MachO64(macho::MachOComdat64<'data, 'file, Endianness, R>), | |
863 | #[cfg(feature = "pe")] | |
864 | Pe32(pe::PeComdat32<'data, 'file, R>), | |
865 | #[cfg(feature = "pe")] | |
866 | Pe64(pe::PeComdat64<'data, 'file, R>), | |
867 | #[cfg(feature = "wasm")] | |
868 | Wasm(wasm::WasmComdat<'data, 'file, R>), | |
f25598a0 FG |
869 | #[cfg(feature = "xcoff")] |
870 | Xcoff32(xcoff::XcoffComdat32<'data, 'file, R>), | |
871 | #[cfg(feature = "xcoff")] | |
872 | Xcoff64(xcoff::XcoffComdat64<'data, 'file, R>), | |
a2a8927a XL |
873 | } |
874 | ||
875 | impl<'data, 'file, R: ReadRef<'data>> fmt::Debug for Comdat<'data, 'file, R> { | |
876 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
877 | let mut s = f.debug_struct("Comdat"); | |
878 | s.field("symbol", &self.symbol()) | |
879 | .field("name", &self.name().unwrap_or("<invalid>")) | |
880 | .field("kind", &self.kind()) | |
881 | .finish() | |
882 | } | |
883 | } | |
884 | ||
885 | impl<'data, 'file, R: ReadRef<'data>> read::private::Sealed for Comdat<'data, 'file, R> {} | |
886 | ||
887 | impl<'data, 'file, R: ReadRef<'data>> ObjectComdat<'data> for Comdat<'data, 'file, R> { | |
888 | type SectionIterator = ComdatSectionIterator<'data, 'file, R>; | |
889 | ||
890 | fn kind(&self) -> ComdatKind { | |
891 | with_inner!(self.inner, ComdatInternal, |x| x.kind()) | |
892 | } | |
893 | ||
894 | fn symbol(&self) -> SymbolIndex { | |
895 | with_inner!(self.inner, ComdatInternal, |x| x.symbol()) | |
896 | } | |
897 | ||
898 | fn name_bytes(&self) -> Result<&[u8]> { | |
899 | with_inner!(self.inner, ComdatInternal, |x| x.name_bytes()) | |
900 | } | |
901 | ||
902 | fn name(&self) -> Result<&str> { | |
903 | with_inner!(self.inner, ComdatInternal, |x| x.name()) | |
904 | } | |
905 | ||
906 | fn sections(&self) -> ComdatSectionIterator<'data, 'file, R> { | |
907 | ComdatSectionIterator { | |
908 | inner: map_inner!( | |
909 | self.inner, | |
910 | ComdatInternal, | |
911 | ComdatSectionIteratorInternal, | |
912 | |x| x.sections() | |
913 | ), | |
914 | } | |
915 | } | |
916 | } | |
917 | ||
918 | /// An iterator over COMDAT section entries. | |
919 | #[derive(Debug)] | |
920 | pub struct ComdatSectionIterator<'data, 'file, R: ReadRef<'data> = &'data [u8]> | |
921 | where | |
922 | 'data: 'file, | |
923 | { | |
924 | inner: ComdatSectionIteratorInternal<'data, 'file, R>, | |
925 | } | |
926 | ||
927 | #[derive(Debug)] | |
928 | enum ComdatSectionIteratorInternal<'data, 'file, R: ReadRef<'data>> | |
929 | where | |
930 | 'data: 'file, | |
931 | { | |
932 | #[cfg(feature = "coff")] | |
933 | Coff(coff::CoffComdatSectionIterator<'data, 'file, R>), | |
934 | #[cfg(feature = "elf")] | |
935 | Elf32(elf::ElfComdatSectionIterator32<'data, 'file, Endianness, R>), | |
936 | #[cfg(feature = "elf")] | |
937 | Elf64(elf::ElfComdatSectionIterator64<'data, 'file, Endianness, R>), | |
938 | #[cfg(feature = "macho")] | |
939 | MachO32(macho::MachOComdatSectionIterator32<'data, 'file, Endianness, R>), | |
940 | #[cfg(feature = "macho")] | |
941 | MachO64(macho::MachOComdatSectionIterator64<'data, 'file, Endianness, R>), | |
942 | #[cfg(feature = "pe")] | |
943 | Pe32(pe::PeComdatSectionIterator32<'data, 'file, R>), | |
944 | #[cfg(feature = "pe")] | |
945 | Pe64(pe::PeComdatSectionIterator64<'data, 'file, R>), | |
946 | #[cfg(feature = "wasm")] | |
947 | Wasm(wasm::WasmComdatSectionIterator<'data, 'file, R>), | |
f25598a0 FG |
948 | #[cfg(feature = "xcoff")] |
949 | Xcoff32(xcoff::XcoffComdatSectionIterator32<'data, 'file, R>), | |
950 | #[cfg(feature = "xcoff")] | |
951 | Xcoff64(xcoff::XcoffComdatSectionIterator64<'data, 'file, R>), | |
a2a8927a XL |
952 | } |
953 | ||
954 | impl<'data, 'file, R: ReadRef<'data>> Iterator for ComdatSectionIterator<'data, 'file, R> { | |
955 | type Item = SectionIndex; | |
956 | ||
957 | fn next(&mut self) -> Option<Self::Item> { | |
958 | with_inner_mut!(self.inner, ComdatSectionIteratorInternal, |x| x.next()) | |
959 | } | |
960 | } | |
961 | ||
962 | /// A symbol table. | |
963 | #[derive(Debug)] | |
964 | pub struct SymbolTable<'data, 'file, R = &'data [u8]> | |
965 | where | |
966 | 'data: 'file, | |
967 | R: ReadRef<'data>, | |
968 | { | |
969 | inner: SymbolTableInternal<'data, 'file, R>, | |
970 | } | |
971 | ||
972 | #[derive(Debug)] | |
973 | enum SymbolTableInternal<'data, 'file, R> | |
974 | where | |
975 | 'data: 'file, | |
976 | R: ReadRef<'data>, | |
977 | { | |
978 | #[cfg(feature = "coff")] | |
979 | Coff((coff::CoffSymbolTable<'data, 'file, R>, PhantomData<R>)), | |
980 | #[cfg(feature = "elf")] | |
981 | Elf32( | |
982 | ( | |
983 | elf::ElfSymbolTable32<'data, 'file, Endianness, R>, | |
984 | PhantomData<R>, | |
985 | ), | |
986 | ), | |
987 | #[cfg(feature = "elf")] | |
988 | Elf64( | |
989 | ( | |
990 | elf::ElfSymbolTable64<'data, 'file, Endianness, R>, | |
991 | PhantomData<R>, | |
992 | ), | |
993 | ), | |
994 | #[cfg(feature = "macho")] | |
995 | MachO32( | |
996 | ( | |
997 | macho::MachOSymbolTable32<'data, 'file, Endianness, R>, | |
998 | PhantomData<()>, | |
999 | ), | |
1000 | ), | |
1001 | #[cfg(feature = "macho")] | |
1002 | MachO64( | |
1003 | ( | |
1004 | macho::MachOSymbolTable64<'data, 'file, Endianness, R>, | |
1005 | PhantomData<()>, | |
1006 | ), | |
1007 | ), | |
1008 | #[cfg(feature = "pe")] | |
1009 | Pe32((coff::CoffSymbolTable<'data, 'file, R>, PhantomData<R>)), | |
1010 | #[cfg(feature = "pe")] | |
1011 | Pe64((coff::CoffSymbolTable<'data, 'file, R>, PhantomData<R>)), | |
1012 | #[cfg(feature = "wasm")] | |
1013 | Wasm((wasm::WasmSymbolTable<'data, 'file>, PhantomData<R>)), | |
f25598a0 FG |
1014 | #[cfg(feature = "xcoff")] |
1015 | Xcoff32((xcoff::XcoffSymbolTable32<'data, 'file, R>, PhantomData<R>)), | |
1016 | #[cfg(feature = "xcoff")] | |
1017 | Xcoff64((xcoff::XcoffSymbolTable64<'data, 'file, R>, PhantomData<R>)), | |
a2a8927a XL |
1018 | } |
1019 | ||
1020 | impl<'data, 'file, R: ReadRef<'data>> read::private::Sealed for SymbolTable<'data, 'file, R> {} | |
1021 | ||
1022 | impl<'data, 'file, R: ReadRef<'data>> ObjectSymbolTable<'data> for SymbolTable<'data, 'file, R> { | |
1023 | type Symbol = Symbol<'data, 'file, R>; | |
1024 | type SymbolIterator = SymbolIterator<'data, 'file, R>; | |
1025 | ||
1026 | fn symbols(&self) -> Self::SymbolIterator { | |
1027 | SymbolIterator { | |
1028 | inner: map_inner!( | |
1029 | self.inner, | |
1030 | SymbolTableInternal, | |
1031 | SymbolIteratorInternal, | |
1032 | |x| (x.0.symbols(), PhantomData) | |
1033 | ), | |
1034 | } | |
1035 | } | |
1036 | ||
1037 | fn symbol_by_index(&self, index: SymbolIndex) -> Result<Self::Symbol> { | |
1038 | map_inner_option!(self.inner, SymbolTableInternal, SymbolInternal, |x| x | |
1039 | .0 | |
1040 | .symbol_by_index(index) | |
1041 | .map(|x| (x, PhantomData))) | |
1042 | .map(|inner| Symbol { inner }) | |
1043 | } | |
1044 | } | |
1045 | ||
1046 | /// An iterator over symbol table entries. | |
1047 | #[derive(Debug)] | |
1048 | pub struct SymbolIterator<'data, 'file, R = &'data [u8]> | |
1049 | where | |
1050 | 'data: 'file, | |
1051 | R: ReadRef<'data>, | |
1052 | { | |
1053 | inner: SymbolIteratorInternal<'data, 'file, R>, | |
1054 | } | |
1055 | ||
1056 | #[derive(Debug)] | |
1057 | enum SymbolIteratorInternal<'data, 'file, R> | |
1058 | where | |
1059 | 'data: 'file, | |
1060 | R: ReadRef<'data>, | |
1061 | { | |
1062 | #[cfg(feature = "coff")] | |
1063 | Coff((coff::CoffSymbolIterator<'data, 'file, R>, PhantomData<R>)), | |
1064 | #[cfg(feature = "elf")] | |
1065 | Elf32( | |
1066 | ( | |
1067 | elf::ElfSymbolIterator32<'data, 'file, Endianness, R>, | |
1068 | PhantomData<R>, | |
1069 | ), | |
1070 | ), | |
1071 | #[cfg(feature = "elf")] | |
1072 | Elf64( | |
1073 | ( | |
1074 | elf::ElfSymbolIterator64<'data, 'file, Endianness, R>, | |
1075 | PhantomData<R>, | |
1076 | ), | |
1077 | ), | |
1078 | #[cfg(feature = "macho")] | |
1079 | MachO32( | |
1080 | ( | |
1081 | macho::MachOSymbolIterator32<'data, 'file, Endianness, R>, | |
1082 | PhantomData<()>, | |
1083 | ), | |
1084 | ), | |
1085 | #[cfg(feature = "macho")] | |
1086 | MachO64( | |
1087 | ( | |
1088 | macho::MachOSymbolIterator64<'data, 'file, Endianness, R>, | |
1089 | PhantomData<()>, | |
1090 | ), | |
1091 | ), | |
1092 | #[cfg(feature = "pe")] | |
1093 | Pe32((coff::CoffSymbolIterator<'data, 'file, R>, PhantomData<R>)), | |
1094 | #[cfg(feature = "pe")] | |
1095 | Pe64((coff::CoffSymbolIterator<'data, 'file, R>, PhantomData<R>)), | |
1096 | #[cfg(feature = "wasm")] | |
1097 | Wasm((wasm::WasmSymbolIterator<'data, 'file>, PhantomData<R>)), | |
f25598a0 FG |
1098 | #[cfg(feature = "xcoff")] |
1099 | Xcoff32( | |
1100 | ( | |
1101 | xcoff::XcoffSymbolIterator32<'data, 'file, R>, | |
1102 | PhantomData<R>, | |
1103 | ), | |
1104 | ), | |
1105 | #[cfg(feature = "xcoff")] | |
1106 | Xcoff64( | |
1107 | ( | |
1108 | xcoff::XcoffSymbolIterator64<'data, 'file, R>, | |
1109 | PhantomData<R>, | |
1110 | ), | |
1111 | ), | |
a2a8927a XL |
1112 | } |
1113 | ||
1114 | impl<'data, 'file, R: ReadRef<'data>> Iterator for SymbolIterator<'data, 'file, R> { | |
1115 | type Item = Symbol<'data, 'file, R>; | |
1116 | ||
1117 | fn next(&mut self) -> Option<Self::Item> { | |
1118 | map_inner_option_mut!(self.inner, SymbolIteratorInternal, SymbolInternal, |iter| { | |
1119 | iter.0.next().map(|x| (x, PhantomData)) | |
1120 | }) | |
1121 | .map(|inner| Symbol { inner }) | |
1122 | } | |
1123 | } | |
1124 | ||
1125 | /// A symbol table entry. | |
1126 | pub struct Symbol<'data, 'file, R = &'data [u8]> | |
1127 | where | |
1128 | 'data: 'file, | |
1129 | R: ReadRef<'data>, | |
1130 | { | |
1131 | inner: SymbolInternal<'data, 'file, R>, | |
1132 | } | |
1133 | ||
1134 | enum SymbolInternal<'data, 'file, R> | |
1135 | where | |
1136 | 'data: 'file, | |
1137 | R: ReadRef<'data>, | |
1138 | { | |
1139 | #[cfg(feature = "coff")] | |
1140 | Coff((coff::CoffSymbol<'data, 'file, R>, PhantomData<R>)), | |
1141 | #[cfg(feature = "elf")] | |
1142 | Elf32( | |
1143 | ( | |
1144 | elf::ElfSymbol32<'data, 'file, Endianness, R>, | |
1145 | PhantomData<R>, | |
1146 | ), | |
1147 | ), | |
1148 | #[cfg(feature = "elf")] | |
1149 | Elf64( | |
1150 | ( | |
1151 | elf::ElfSymbol64<'data, 'file, Endianness, R>, | |
1152 | PhantomData<R>, | |
1153 | ), | |
1154 | ), | |
1155 | #[cfg(feature = "macho")] | |
1156 | MachO32( | |
1157 | ( | |
1158 | macho::MachOSymbol32<'data, 'file, Endianness, R>, | |
1159 | PhantomData<()>, | |
1160 | ), | |
1161 | ), | |
1162 | #[cfg(feature = "macho")] | |
1163 | MachO64( | |
1164 | ( | |
1165 | macho::MachOSymbol64<'data, 'file, Endianness, R>, | |
1166 | PhantomData<()>, | |
1167 | ), | |
1168 | ), | |
1169 | #[cfg(feature = "pe")] | |
1170 | Pe32((coff::CoffSymbol<'data, 'file, R>, PhantomData<R>)), | |
1171 | #[cfg(feature = "pe")] | |
1172 | Pe64((coff::CoffSymbol<'data, 'file, R>, PhantomData<R>)), | |
1173 | #[cfg(feature = "wasm")] | |
1174 | Wasm((wasm::WasmSymbol<'data, 'file>, PhantomData<R>)), | |
f25598a0 FG |
1175 | #[cfg(feature = "xcoff")] |
1176 | Xcoff32((xcoff::XcoffSymbol32<'data, 'file, R>, PhantomData<R>)), | |
1177 | #[cfg(feature = "xcoff")] | |
1178 | Xcoff64((xcoff::XcoffSymbol64<'data, 'file, R>, PhantomData<R>)), | |
a2a8927a XL |
1179 | } |
1180 | ||
1181 | impl<'data, 'file, R: ReadRef<'data>> fmt::Debug for Symbol<'data, 'file, R> { | |
1182 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
1183 | f.debug_struct("Symbol") | |
1184 | .field("name", &self.name().unwrap_or("<invalid>")) | |
1185 | .field("address", &self.address()) | |
1186 | .field("size", &self.size()) | |
1187 | .field("kind", &self.kind()) | |
1188 | .field("section", &self.section()) | |
1189 | .field("scope", &self.scope()) | |
1190 | .field("weak", &self.is_weak()) | |
1191 | .field("flags", &self.flags()) | |
1192 | .finish() | |
1193 | } | |
1194 | } | |
1195 | ||
1196 | impl<'data, 'file, R: ReadRef<'data>> read::private::Sealed for Symbol<'data, 'file, R> {} | |
1197 | ||
1198 | impl<'data, 'file, R: ReadRef<'data>> ObjectSymbol<'data> for Symbol<'data, 'file, R> { | |
1199 | fn index(&self) -> SymbolIndex { | |
1200 | with_inner!(self.inner, SymbolInternal, |x| x.0.index()) | |
1201 | } | |
1202 | ||
1203 | fn name_bytes(&self) -> Result<&'data [u8]> { | |
1204 | with_inner!(self.inner, SymbolInternal, |x| x.0.name_bytes()) | |
1205 | } | |
1206 | ||
1207 | fn name(&self) -> Result<&'data str> { | |
1208 | with_inner!(self.inner, SymbolInternal, |x| x.0.name()) | |
1209 | } | |
1210 | ||
1211 | fn address(&self) -> u64 { | |
1212 | with_inner!(self.inner, SymbolInternal, |x| x.0.address()) | |
1213 | } | |
1214 | ||
1215 | fn size(&self) -> u64 { | |
1216 | with_inner!(self.inner, SymbolInternal, |x| x.0.size()) | |
1217 | } | |
1218 | ||
1219 | fn kind(&self) -> SymbolKind { | |
1220 | with_inner!(self.inner, SymbolInternal, |x| x.0.kind()) | |
1221 | } | |
1222 | ||
1223 | fn section(&self) -> SymbolSection { | |
1224 | with_inner!(self.inner, SymbolInternal, |x| x.0.section()) | |
1225 | } | |
1226 | ||
1227 | fn is_undefined(&self) -> bool { | |
1228 | with_inner!(self.inner, SymbolInternal, |x| x.0.is_undefined()) | |
1229 | } | |
1230 | ||
1231 | fn is_definition(&self) -> bool { | |
1232 | with_inner!(self.inner, SymbolInternal, |x| x.0.is_definition()) | |
1233 | } | |
1234 | ||
1235 | fn is_common(&self) -> bool { | |
1236 | with_inner!(self.inner, SymbolInternal, |x| x.0.is_common()) | |
1237 | } | |
1238 | ||
1239 | fn is_weak(&self) -> bool { | |
1240 | with_inner!(self.inner, SymbolInternal, |x| x.0.is_weak()) | |
1241 | } | |
1242 | ||
1243 | fn scope(&self) -> SymbolScope { | |
1244 | with_inner!(self.inner, SymbolInternal, |x| x.0.scope()) | |
1245 | } | |
1246 | ||
1247 | fn is_global(&self) -> bool { | |
1248 | with_inner!(self.inner, SymbolInternal, |x| x.0.is_global()) | |
1249 | } | |
1250 | ||
1251 | fn is_local(&self) -> bool { | |
1252 | with_inner!(self.inner, SymbolInternal, |x| x.0.is_local()) | |
1253 | } | |
1254 | ||
1255 | fn flags(&self) -> SymbolFlags<SectionIndex> { | |
1256 | with_inner!(self.inner, SymbolInternal, |x| x.0.flags()) | |
1257 | } | |
1258 | } | |
1259 | ||
1260 | /// An iterator over dynamic relocation entries. | |
1261 | #[derive(Debug)] | |
1262 | pub struct DynamicRelocationIterator<'data, 'file, R = &'data [u8]> | |
1263 | where | |
1264 | 'data: 'file, | |
1265 | R: ReadRef<'data>, | |
1266 | { | |
1267 | inner: DynamicRelocationIteratorInternal<'data, 'file, R>, | |
1268 | } | |
1269 | ||
1270 | #[derive(Debug)] | |
1271 | enum DynamicRelocationIteratorInternal<'data, 'file, R> | |
1272 | where | |
1273 | 'data: 'file, | |
1274 | R: ReadRef<'data>, | |
1275 | { | |
1276 | #[cfg(feature = "elf")] | |
1277 | Elf32(elf::ElfDynamicRelocationIterator32<'data, 'file, Endianness, R>), | |
1278 | #[cfg(feature = "elf")] | |
1279 | Elf64(elf::ElfDynamicRelocationIterator64<'data, 'file, Endianness, R>), | |
1280 | // We need to always use the lifetime parameters. | |
1281 | #[allow(unused)] | |
1282 | None(PhantomData<(&'data (), &'file (), R)>), | |
1283 | } | |
1284 | ||
1285 | impl<'data, 'file, R: ReadRef<'data>> Iterator for DynamicRelocationIterator<'data, 'file, R> { | |
1286 | type Item = (u64, Relocation); | |
1287 | ||
1288 | fn next(&mut self) -> Option<Self::Item> { | |
1289 | match self.inner { | |
1290 | #[cfg(feature = "elf")] | |
1291 | DynamicRelocationIteratorInternal::Elf32(ref mut elf) => elf.next(), | |
1292 | #[cfg(feature = "elf")] | |
1293 | DynamicRelocationIteratorInternal::Elf64(ref mut elf) => elf.next(), | |
1294 | DynamicRelocationIteratorInternal::None(_) => None, | |
1295 | } | |
1296 | } | |
1297 | } | |
1298 | ||
1299 | /// An iterator over section relocation entries. | |
1300 | #[derive(Debug)] | |
1301 | pub struct SectionRelocationIterator<'data, 'file, R: ReadRef<'data> = &'data [u8]> | |
1302 | where | |
1303 | 'data: 'file, | |
1304 | { | |
1305 | inner: SectionRelocationIteratorInternal<'data, 'file, R>, | |
1306 | } | |
1307 | ||
1308 | #[derive(Debug)] | |
1309 | enum SectionRelocationIteratorInternal<'data, 'file, R: ReadRef<'data>> | |
1310 | where | |
1311 | 'data: 'file, | |
1312 | { | |
1313 | #[cfg(feature = "coff")] | |
1314 | Coff(coff::CoffRelocationIterator<'data, 'file, R>), | |
1315 | #[cfg(feature = "elf")] | |
1316 | Elf32(elf::ElfSectionRelocationIterator32<'data, 'file, Endianness, R>), | |
1317 | #[cfg(feature = "elf")] | |
1318 | Elf64(elf::ElfSectionRelocationIterator64<'data, 'file, Endianness, R>), | |
1319 | #[cfg(feature = "macho")] | |
1320 | MachO32(macho::MachORelocationIterator32<'data, 'file, Endianness, R>), | |
1321 | #[cfg(feature = "macho")] | |
1322 | MachO64(macho::MachORelocationIterator64<'data, 'file, Endianness, R>), | |
1323 | #[cfg(feature = "pe")] | |
1324 | Pe32(pe::PeRelocationIterator<'data, 'file, R>), | |
1325 | #[cfg(feature = "pe")] | |
1326 | Pe64(pe::PeRelocationIterator<'data, 'file, R>), | |
1327 | #[cfg(feature = "wasm")] | |
1328 | Wasm(wasm::WasmRelocationIterator<'data, 'file, R>), | |
f25598a0 FG |
1329 | #[cfg(feature = "xcoff")] |
1330 | Xcoff32(xcoff::XcoffRelocationIterator32<'data, 'file, R>), | |
1331 | #[cfg(feature = "xcoff")] | |
1332 | Xcoff64(xcoff::XcoffRelocationIterator64<'data, 'file, R>), | |
a2a8927a XL |
1333 | } |
1334 | ||
1335 | impl<'data, 'file, R: ReadRef<'data>> Iterator for SectionRelocationIterator<'data, 'file, R> { | |
1336 | type Item = (u64, Relocation); | |
1337 | ||
1338 | fn next(&mut self) -> Option<Self::Item> { | |
1339 | with_inner_mut!(self.inner, SectionRelocationIteratorInternal, |x| x.next()) | |
1340 | } | |
1341 | } |