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