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, ObjectMap, ObjectSection,
18     ObjectSegment, ObjectSymbol, ObjectSymbolTable, ReadRef, Relocation, Result, SectionFlags,
19     SectionIndex, SectionKind, SymbolFlags, SymbolIndex, SymbolKind, SymbolMap, SymbolMapName,
20     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 
segments(&'file self) -> SegmentIterator<'data, 'file, R>289     fn segments(&'file self) -> SegmentIterator<'data, 'file, R> {
290         SegmentIterator {
291             inner: map_inner!(self.inner, FileInternal, SegmentIteratorInternal, |x| x
292                 .segments()),
293         }
294     }
295 
section_by_name(&'file self, section_name: &str) -> Option<Section<'data, 'file, R>>296     fn section_by_name(&'file self, section_name: &str) -> Option<Section<'data, 'file, R>> {
297         map_inner_option!(self.inner, FileInternal, SectionInternal, |x| x
298             .section_by_name(section_name))
299         .map(|inner| Section { inner })
300     }
301 
section_by_index(&'file self, index: SectionIndex) -> Result<Section<'data, 'file, R>>302     fn section_by_index(&'file self, index: SectionIndex) -> Result<Section<'data, 'file, R>> {
303         map_inner_option!(self.inner, FileInternal, SectionInternal, |x| x
304             .section_by_index(index))
305         .map(|inner| Section { inner })
306     }
307 
sections(&'file self) -> SectionIterator<'data, 'file, R>308     fn sections(&'file self) -> SectionIterator<'data, 'file, R> {
309         SectionIterator {
310             inner: map_inner!(self.inner, FileInternal, SectionIteratorInternal, |x| x
311                 .sections()),
312         }
313     }
314 
comdats(&'file self) -> ComdatIterator<'data, 'file, R>315     fn comdats(&'file self) -> ComdatIterator<'data, 'file, R> {
316         ComdatIterator {
317             inner: map_inner!(self.inner, FileInternal, ComdatIteratorInternal, |x| x
318                 .comdats()),
319         }
320     }
321 
symbol_by_index(&'file self, index: SymbolIndex) -> Result<Symbol<'data, 'file, R>>322     fn symbol_by_index(&'file self, index: SymbolIndex) -> Result<Symbol<'data, 'file, R>> {
323         map_inner_option!(self.inner, FileInternal, SymbolInternal, |x| x
324             .symbol_by_index(index)
325             .map(|x| (x, PhantomData)))
326         .map(|inner| Symbol { inner })
327     }
328 
symbols(&'file self) -> SymbolIterator<'data, 'file, R>329     fn symbols(&'file self) -> SymbolIterator<'data, 'file, R> {
330         SymbolIterator {
331             inner: map_inner!(self.inner, FileInternal, SymbolIteratorInternal, |x| (
332                 x.symbols(),
333                 PhantomData
334             )),
335         }
336     }
337 
symbol_table(&'file self) -> Option<SymbolTable<'data, 'file, R>>338     fn symbol_table(&'file self) -> Option<SymbolTable<'data, 'file, R>> {
339         map_inner_option!(self.inner, FileInternal, SymbolTableInternal, |x| x
340             .symbol_table()
341             .map(|x| (x, PhantomData)))
342         .map(|inner| SymbolTable { inner })
343     }
344 
dynamic_symbols(&'file self) -> SymbolIterator<'data, 'file, R>345     fn dynamic_symbols(&'file self) -> SymbolIterator<'data, 'file, R> {
346         SymbolIterator {
347             inner: map_inner!(self.inner, FileInternal, SymbolIteratorInternal, |x| (
348                 x.dynamic_symbols(),
349                 PhantomData
350             )),
351         }
352     }
353 
dynamic_symbol_table(&'file self) -> Option<SymbolTable<'data, 'file, R>>354     fn dynamic_symbol_table(&'file self) -> Option<SymbolTable<'data, 'file, R>> {
355         map_inner_option!(self.inner, FileInternal, SymbolTableInternal, |x| x
356             .dynamic_symbol_table()
357             .map(|x| (x, PhantomData)))
358         .map(|inner| SymbolTable { inner })
359     }
360 
361     #[cfg(feature = "elf")]
dynamic_relocations(&'file self) -> Option<DynamicRelocationIterator<'data, 'file, R>>362     fn dynamic_relocations(&'file self) -> Option<DynamicRelocationIterator<'data, 'file, R>> {
363         let inner = match self.inner {
364             FileInternal::Elf32(ref elf) => {
365                 DynamicRelocationIteratorInternal::Elf32(elf.dynamic_relocations()?)
366             }
367             FileInternal::Elf64(ref elf) => {
368                 DynamicRelocationIteratorInternal::Elf64(elf.dynamic_relocations()?)
369             }
370             #[allow(unreachable_patterns)]
371             _ => return None,
372         };
373         Some(DynamicRelocationIterator { inner })
374     }
375 
376     #[cfg(not(feature = "elf"))]
dynamic_relocations(&'file self) -> Option<DynamicRelocationIterator<'data, 'file, R>>377     fn dynamic_relocations(&'file self) -> Option<DynamicRelocationIterator<'data, 'file, R>> {
378         None
379     }
380 
symbol_map(&self) -> SymbolMap<SymbolMapName<'data>>381     fn symbol_map(&self) -> SymbolMap<SymbolMapName<'data>> {
382         with_inner!(self.inner, FileInternal, |x| x.symbol_map())
383     }
384 
object_map(&self) -> ObjectMap<'data>385     fn object_map(&self) -> ObjectMap<'data> {
386         with_inner!(self.inner, FileInternal, |x| x.object_map())
387     }
388 
imports(&self) -> Result<Vec<Import<'data>>>389     fn imports(&self) -> Result<Vec<Import<'data>>> {
390         with_inner!(self.inner, FileInternal, |x| x.imports())
391     }
392 
exports(&self) -> Result<Vec<Export<'data>>>393     fn exports(&self) -> Result<Vec<Export<'data>>> {
394         with_inner!(self.inner, FileInternal, |x| x.exports())
395     }
396 
has_debug_symbols(&self) -> bool397     fn has_debug_symbols(&self) -> bool {
398         with_inner!(self.inner, FileInternal, |x| x.has_debug_symbols())
399     }
400 
401     #[inline]
mach_uuid(&self) -> Result<Option<[u8; 16]>>402     fn mach_uuid(&self) -> Result<Option<[u8; 16]>> {
403         with_inner!(self.inner, FileInternal, |x| x.mach_uuid())
404     }
405 
406     #[inline]
build_id(&self) -> Result<Option<&'data [u8]>>407     fn build_id(&self) -> Result<Option<&'data [u8]>> {
408         with_inner!(self.inner, FileInternal, |x| x.build_id())
409     }
410 
411     #[inline]
gnu_debuglink(&self) -> Result<Option<(&'data [u8], u32)>>412     fn gnu_debuglink(&self) -> Result<Option<(&'data [u8], u32)>> {
413         with_inner!(self.inner, FileInternal, |x| x.gnu_debuglink())
414     }
415 
416     #[inline]
gnu_debugaltlink(&self) -> Result<Option<(&'data [u8], &'data [u8])>>417     fn gnu_debugaltlink(&self) -> Result<Option<(&'data [u8], &'data [u8])>> {
418         with_inner!(self.inner, FileInternal, |x| x.gnu_debugaltlink())
419     }
420 
421     #[inline]
pdb_info(&self) -> Result<Option<CodeView>>422     fn pdb_info(&self) -> Result<Option<CodeView>> {
423         with_inner!(self.inner, FileInternal, |x| x.pdb_info())
424     }
425 
relative_address_base(&self) -> u64426     fn relative_address_base(&self) -> u64 {
427         with_inner!(self.inner, FileInternal, |x| x.relative_address_base())
428     }
429 
entry(&self) -> u64430     fn entry(&self) -> u64 {
431         with_inner!(self.inner, FileInternal, |x| x.entry())
432     }
433 
flags(&self) -> FileFlags434     fn flags(&self) -> FileFlags {
435         with_inner!(self.inner, FileInternal, |x| x.flags())
436     }
437 }
438 
439 /// An iterator over the segments of a `File`.
440 #[derive(Debug)]
441 pub struct SegmentIterator<'data, 'file, R: ReadRef<'data> = &'data [u8]>
442 where
443     'data: 'file,
444 {
445     inner: SegmentIteratorInternal<'data, 'file, R>,
446 }
447 
448 #[derive(Debug)]
449 enum SegmentIteratorInternal<'data, 'file, R: ReadRef<'data>>
450 where
451     'data: 'file,
452 {
453     #[cfg(feature = "coff")]
454     Coff(coff::CoffSegmentIterator<'data, 'file, R>),
455     #[cfg(feature = "elf")]
456     Elf32(elf::ElfSegmentIterator32<'data, 'file, Endianness, R>),
457     #[cfg(feature = "elf")]
458     Elf64(elf::ElfSegmentIterator64<'data, 'file, Endianness, R>),
459     #[cfg(feature = "macho")]
460     MachO32(macho::MachOSegmentIterator32<'data, 'file, Endianness, R>),
461     #[cfg(feature = "macho")]
462     MachO64(macho::MachOSegmentIterator64<'data, 'file, Endianness, R>),
463     #[cfg(feature = "pe")]
464     Pe32(pe::PeSegmentIterator32<'data, 'file, R>),
465     #[cfg(feature = "pe")]
466     Pe64(pe::PeSegmentIterator64<'data, 'file, R>),
467     #[cfg(feature = "wasm")]
468     Wasm(wasm::WasmSegmentIterator<'data, 'file, R>),
469 }
470 
471 impl<'data, 'file, R: ReadRef<'data>> Iterator for SegmentIterator<'data, 'file, R> {
472     type Item = Segment<'data, 'file, R>;
473 
next(&mut self) -> Option<Self::Item>474     fn next(&mut self) -> Option<Self::Item> {
475         next_inner!(self.inner, SegmentIteratorInternal, SegmentInternal)
476             .map(|inner| Segment { inner })
477     }
478 }
479 
480 /// A segment of a `File`.
481 pub struct Segment<'data, 'file, R: ReadRef<'data> = &'data [u8]>
482 where
483     'data: 'file,
484 {
485     inner: SegmentInternal<'data, 'file, R>,
486 }
487 
488 #[derive(Debug)]
489 enum SegmentInternal<'data, 'file, R: ReadRef<'data>>
490 where
491     'data: 'file,
492 {
493     #[cfg(feature = "coff")]
494     Coff(coff::CoffSegment<'data, 'file, R>),
495     #[cfg(feature = "elf")]
496     Elf32(elf::ElfSegment32<'data, 'file, Endianness, R>),
497     #[cfg(feature = "elf")]
498     Elf64(elf::ElfSegment64<'data, 'file, Endianness, R>),
499     #[cfg(feature = "macho")]
500     MachO32(macho::MachOSegment32<'data, 'file, Endianness, R>),
501     #[cfg(feature = "macho")]
502     MachO64(macho::MachOSegment64<'data, 'file, Endianness, R>),
503     #[cfg(feature = "pe")]
504     Pe32(pe::PeSegment32<'data, 'file, R>),
505     #[cfg(feature = "pe")]
506     Pe64(pe::PeSegment64<'data, 'file, R>),
507     #[cfg(feature = "wasm")]
508     Wasm(wasm::WasmSegment<'data, 'file, R>),
509 }
510 
511 impl<'data, 'file, R: ReadRef<'data>> fmt::Debug for Segment<'data, 'file, R> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result512     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
513         // It's painful to do much better than this
514         let mut s = f.debug_struct("Segment");
515         match self.name() {
516             Ok(Some(ref name)) => {
517                 s.field("name", name);
518             }
519             Ok(None) => {}
520             Err(_) => {
521                 s.field("name", &"<invalid>");
522             }
523         }
524         s.field("address", &self.address())
525             .field("size", &self.size())
526             .finish()
527     }
528 }
529 
530 impl<'data, 'file, R: ReadRef<'data>> read::private::Sealed for Segment<'data, 'file, R> {}
531 
532 impl<'data, 'file, R: ReadRef<'data>> ObjectSegment<'data> for Segment<'data, 'file, R> {
address(&self) -> u64533     fn address(&self) -> u64 {
534         with_inner!(self.inner, SegmentInternal, |x| x.address())
535     }
536 
size(&self) -> u64537     fn size(&self) -> u64 {
538         with_inner!(self.inner, SegmentInternal, |x| x.size())
539     }
540 
align(&self) -> u64541     fn align(&self) -> u64 {
542         with_inner!(self.inner, SegmentInternal, |x| x.align())
543     }
544 
file_range(&self) -> (u64, u64)545     fn file_range(&self) -> (u64, u64) {
546         with_inner!(self.inner, SegmentInternal, |x| x.file_range())
547     }
548 
data(&self) -> Result<&'data [u8]>549     fn data(&self) -> Result<&'data [u8]> {
550         with_inner!(self.inner, SegmentInternal, |x| x.data())
551     }
552 
data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>>553     fn data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>> {
554         with_inner!(self.inner, SegmentInternal, |x| x.data_range(address, size))
555     }
556 
name(&self) -> Result<Option<&str>>557     fn name(&self) -> Result<Option<&str>> {
558         with_inner!(self.inner, SegmentInternal, |x| x.name())
559     }
560 }
561 
562 /// An iterator of the sections of a `File`.
563 #[derive(Debug)]
564 pub struct SectionIterator<'data, 'file, R: ReadRef<'data> = &'data [u8]>
565 where
566     'data: 'file,
567 {
568     inner: SectionIteratorInternal<'data, 'file, R>,
569 }
570 
571 // we wrap our enums in a struct so that they are kept private.
572 #[derive(Debug)]
573 enum SectionIteratorInternal<'data, 'file, R: ReadRef<'data>>
574 where
575     'data: 'file,
576 {
577     #[cfg(feature = "coff")]
578     Coff(coff::CoffSectionIterator<'data, 'file, R>),
579     #[cfg(feature = "elf")]
580     Elf32(elf::ElfSectionIterator32<'data, 'file, Endianness, R>),
581     #[cfg(feature = "elf")]
582     Elf64(elf::ElfSectionIterator64<'data, 'file, Endianness, R>),
583     #[cfg(feature = "macho")]
584     MachO32(macho::MachOSectionIterator32<'data, 'file, Endianness, R>),
585     #[cfg(feature = "macho")]
586     MachO64(macho::MachOSectionIterator64<'data, 'file, Endianness, R>),
587     #[cfg(feature = "pe")]
588     Pe32(pe::PeSectionIterator32<'data, 'file, R>),
589     #[cfg(feature = "pe")]
590     Pe64(pe::PeSectionIterator64<'data, 'file, R>),
591     #[cfg(feature = "wasm")]
592     Wasm(wasm::WasmSectionIterator<'data, 'file, R>),
593 }
594 
595 impl<'data, 'file, R: ReadRef<'data>> Iterator for SectionIterator<'data, 'file, R> {
596     type Item = Section<'data, 'file, R>;
597 
next(&mut self) -> Option<Self::Item>598     fn next(&mut self) -> Option<Self::Item> {
599         next_inner!(self.inner, SectionIteratorInternal, SectionInternal)
600             .map(|inner| Section { inner })
601     }
602 }
603 
604 /// A Section of a File
605 pub struct Section<'data, 'file, R: ReadRef<'data> = &'data [u8]>
606 where
607     'data: 'file,
608 {
609     inner: SectionInternal<'data, 'file, R>,
610 }
611 
612 enum SectionInternal<'data, 'file, R: ReadRef<'data>>
613 where
614     'data: 'file,
615 {
616     #[cfg(feature = "coff")]
617     Coff(coff::CoffSection<'data, 'file, R>),
618     #[cfg(feature = "elf")]
619     Elf32(elf::ElfSection32<'data, 'file, Endianness, R>),
620     #[cfg(feature = "elf")]
621     Elf64(elf::ElfSection64<'data, 'file, Endianness, R>),
622     #[cfg(feature = "macho")]
623     MachO32(macho::MachOSection32<'data, 'file, Endianness, R>),
624     #[cfg(feature = "macho")]
625     MachO64(macho::MachOSection64<'data, 'file, Endianness, R>),
626     #[cfg(feature = "pe")]
627     Pe32(pe::PeSection32<'data, 'file, R>),
628     #[cfg(feature = "pe")]
629     Pe64(pe::PeSection64<'data, 'file, R>),
630     #[cfg(feature = "wasm")]
631     Wasm(wasm::WasmSection<'data, 'file, R>),
632 }
633 
634 impl<'data, 'file, R: ReadRef<'data>> fmt::Debug for Section<'data, 'file, R> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result635     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
636         // It's painful to do much better than this
637         let mut s = f.debug_struct("Section");
638         match self.segment_name() {
639             Ok(Some(ref name)) => {
640                 s.field("segment", name);
641             }
642             Ok(None) => {}
643             Err(_) => {
644                 s.field("segment", &"<invalid>");
645             }
646         }
647         s.field("name", &self.name().unwrap_or("<invalid>"))
648             .field("address", &self.address())
649             .field("size", &self.size())
650             .field("align", &self.align())
651             .field("kind", &self.kind())
652             .field("flags", &self.flags())
653             .finish()
654     }
655 }
656 
657 impl<'data, 'file, R: ReadRef<'data>> read::private::Sealed for Section<'data, 'file, R> {}
658 
659 impl<'data, 'file, R: ReadRef<'data>> ObjectSection<'data> for Section<'data, 'file, R> {
660     type RelocationIterator = SectionRelocationIterator<'data, 'file, R>;
661 
index(&self) -> SectionIndex662     fn index(&self) -> SectionIndex {
663         with_inner!(self.inner, SectionInternal, |x| x.index())
664     }
665 
address(&self) -> u64666     fn address(&self) -> u64 {
667         with_inner!(self.inner, SectionInternal, |x| x.address())
668     }
669 
size(&self) -> u64670     fn size(&self) -> u64 {
671         with_inner!(self.inner, SectionInternal, |x| x.size())
672     }
673 
align(&self) -> u64674     fn align(&self) -> u64 {
675         with_inner!(self.inner, SectionInternal, |x| x.align())
676     }
677 
file_range(&self) -> Option<(u64, u64)>678     fn file_range(&self) -> Option<(u64, u64)> {
679         with_inner!(self.inner, SectionInternal, |x| x.file_range())
680     }
681 
data(&self) -> Result<&'data [u8]>682     fn data(&self) -> Result<&'data [u8]> {
683         with_inner!(self.inner, SectionInternal, |x| x.data())
684     }
685 
data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>>686     fn data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>> {
687         with_inner!(self.inner, SectionInternal, |x| x.data_range(address, size))
688     }
689 
compressed_file_range(&self) -> Result<CompressedFileRange>690     fn compressed_file_range(&self) -> Result<CompressedFileRange> {
691         with_inner!(self.inner, SectionInternal, |x| x.compressed_file_range())
692     }
693 
compressed_data(&self) -> Result<CompressedData<'data>>694     fn compressed_data(&self) -> Result<CompressedData<'data>> {
695         with_inner!(self.inner, SectionInternal, |x| x.compressed_data())
696     }
697 
name(&self) -> Result<&str>698     fn name(&self) -> Result<&str> {
699         with_inner!(self.inner, SectionInternal, |x| x.name())
700     }
701 
segment_name(&self) -> Result<Option<&str>>702     fn segment_name(&self) -> Result<Option<&str>> {
703         with_inner!(self.inner, SectionInternal, |x| x.segment_name())
704     }
705 
kind(&self) -> SectionKind706     fn kind(&self) -> SectionKind {
707         with_inner!(self.inner, SectionInternal, |x| x.kind())
708     }
709 
relocations(&self) -> SectionRelocationIterator<'data, 'file, R>710     fn relocations(&self) -> SectionRelocationIterator<'data, 'file, R> {
711         SectionRelocationIterator {
712             inner: map_inner!(
713                 self.inner,
714                 SectionInternal,
715                 SectionRelocationIteratorInternal,
716                 |x| x.relocations()
717             ),
718         }
719     }
720 
flags(&self) -> SectionFlags721     fn flags(&self) -> SectionFlags {
722         with_inner!(self.inner, SectionInternal, |x| x.flags())
723     }
724 }
725 
726 /// An iterator of the COMDAT section groups of a `File`.
727 #[derive(Debug)]
728 pub struct ComdatIterator<'data, 'file, R: ReadRef<'data> = &'data [u8]>
729 where
730     'data: 'file,
731 {
732     inner: ComdatIteratorInternal<'data, 'file, R>,
733 }
734 
735 #[derive(Debug)]
736 enum ComdatIteratorInternal<'data, 'file, R: ReadRef<'data>>
737 where
738     'data: 'file,
739 {
740     #[cfg(feature = "coff")]
741     Coff(coff::CoffComdatIterator<'data, 'file, R>),
742     #[cfg(feature = "elf")]
743     Elf32(elf::ElfComdatIterator32<'data, 'file, Endianness, R>),
744     #[cfg(feature = "elf")]
745     Elf64(elf::ElfComdatIterator64<'data, 'file, Endianness, R>),
746     #[cfg(feature = "macho")]
747     MachO32(macho::MachOComdatIterator32<'data, 'file, Endianness, R>),
748     #[cfg(feature = "macho")]
749     MachO64(macho::MachOComdatIterator64<'data, 'file, Endianness, R>),
750     #[cfg(feature = "pe")]
751     Pe32(pe::PeComdatIterator32<'data, 'file, R>),
752     #[cfg(feature = "pe")]
753     Pe64(pe::PeComdatIterator64<'data, 'file, R>),
754     #[cfg(feature = "wasm")]
755     Wasm(wasm::WasmComdatIterator<'data, 'file, R>),
756 }
757 
758 impl<'data, 'file, R: ReadRef<'data>> Iterator for ComdatIterator<'data, 'file, R> {
759     type Item = Comdat<'data, 'file, R>;
760 
next(&mut self) -> Option<Self::Item>761     fn next(&mut self) -> Option<Self::Item> {
762         next_inner!(self.inner, ComdatIteratorInternal, ComdatInternal)
763             .map(|inner| Comdat { inner })
764     }
765 }
766 
767 /// A COMDAT section group of a `File`.
768 pub struct Comdat<'data, 'file, R: ReadRef<'data> = &'data [u8]>
769 where
770     'data: 'file,
771 {
772     inner: ComdatInternal<'data, 'file, R>,
773 }
774 
775 enum ComdatInternal<'data, 'file, R: ReadRef<'data>>
776 where
777     'data: 'file,
778 {
779     #[cfg(feature = "coff")]
780     Coff(coff::CoffComdat<'data, 'file, R>),
781     #[cfg(feature = "elf")]
782     Elf32(elf::ElfComdat32<'data, 'file, Endianness, R>),
783     #[cfg(feature = "elf")]
784     Elf64(elf::ElfComdat64<'data, 'file, Endianness, R>),
785     #[cfg(feature = "macho")]
786     MachO32(macho::MachOComdat32<'data, 'file, Endianness, R>),
787     #[cfg(feature = "macho")]
788     MachO64(macho::MachOComdat64<'data, 'file, Endianness, R>),
789     #[cfg(feature = "pe")]
790     Pe32(pe::PeComdat32<'data, 'file, R>),
791     #[cfg(feature = "pe")]
792     Pe64(pe::PeComdat64<'data, 'file, R>),
793     #[cfg(feature = "wasm")]
794     Wasm(wasm::WasmComdat<'data, 'file, R>),
795 }
796 
797 impl<'data, 'file, R: ReadRef<'data>> fmt::Debug for Comdat<'data, 'file, R> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result798     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
799         let mut s = f.debug_struct("Comdat");
800         s.field("symbol", &self.symbol())
801             .field("name", &self.name().unwrap_or("<invalid>"))
802             .field("kind", &self.kind())
803             .finish()
804     }
805 }
806 
807 impl<'data, 'file, R: ReadRef<'data>> read::private::Sealed for Comdat<'data, 'file, R> {}
808 
809 impl<'data, 'file, R: ReadRef<'data>> ObjectComdat<'data> for Comdat<'data, 'file, R> {
810     type SectionIterator = ComdatSectionIterator<'data, 'file, R>;
811 
kind(&self) -> ComdatKind812     fn kind(&self) -> ComdatKind {
813         with_inner!(self.inner, ComdatInternal, |x| x.kind())
814     }
815 
symbol(&self) -> SymbolIndex816     fn symbol(&self) -> SymbolIndex {
817         with_inner!(self.inner, ComdatInternal, |x| x.symbol())
818     }
819 
name(&self) -> Result<&str>820     fn name(&self) -> Result<&str> {
821         with_inner!(self.inner, ComdatInternal, |x| x.name())
822     }
823 
sections(&self) -> ComdatSectionIterator<'data, 'file, R>824     fn sections(&self) -> ComdatSectionIterator<'data, 'file, R> {
825         ComdatSectionIterator {
826             inner: map_inner!(
827                 self.inner,
828                 ComdatInternal,
829                 ComdatSectionIteratorInternal,
830                 |x| x.sections()
831             ),
832         }
833     }
834 }
835 
836 /// An iterator over COMDAT section entries.
837 #[derive(Debug)]
838 pub struct ComdatSectionIterator<'data, 'file, R: ReadRef<'data> = &'data [u8]>
839 where
840     'data: 'file,
841 {
842     inner: ComdatSectionIteratorInternal<'data, 'file, R>,
843 }
844 
845 #[derive(Debug)]
846 enum ComdatSectionIteratorInternal<'data, 'file, R: ReadRef<'data>>
847 where
848     'data: 'file,
849 {
850     #[cfg(feature = "coff")]
851     Coff(coff::CoffComdatSectionIterator<'data, 'file, R>),
852     #[cfg(feature = "elf")]
853     Elf32(elf::ElfComdatSectionIterator32<'data, 'file, Endianness, R>),
854     #[cfg(feature = "elf")]
855     Elf64(elf::ElfComdatSectionIterator64<'data, 'file, Endianness, R>),
856     #[cfg(feature = "macho")]
857     MachO32(macho::MachOComdatSectionIterator32<'data, 'file, Endianness, R>),
858     #[cfg(feature = "macho")]
859     MachO64(macho::MachOComdatSectionIterator64<'data, 'file, Endianness, R>),
860     #[cfg(feature = "pe")]
861     Pe32(pe::PeComdatSectionIterator32<'data, 'file, R>),
862     #[cfg(feature = "pe")]
863     Pe64(pe::PeComdatSectionIterator64<'data, 'file, R>),
864     #[cfg(feature = "wasm")]
865     Wasm(wasm::WasmComdatSectionIterator<'data, 'file, R>),
866 }
867 
868 impl<'data, 'file, R: ReadRef<'data>> Iterator for ComdatSectionIterator<'data, 'file, R> {
869     type Item = SectionIndex;
870 
next(&mut self) -> Option<Self::Item>871     fn next(&mut self) -> Option<Self::Item> {
872         with_inner_mut!(self.inner, ComdatSectionIteratorInternal, |x| x.next())
873     }
874 }
875 
876 /// A symbol table.
877 #[derive(Debug)]
878 pub struct SymbolTable<'data, 'file, R = &'data [u8]>
879 where
880     'data: 'file,
881     R: ReadRef<'data>,
882 {
883     inner: SymbolTableInternal<'data, 'file, R>,
884 }
885 
886 #[derive(Debug)]
887 enum SymbolTableInternal<'data, 'file, R>
888 where
889     'data: 'file,
890     R: ReadRef<'data>,
891 {
892     #[cfg(feature = "coff")]
893     Coff((coff::CoffSymbolTable<'data, 'file>, PhantomData<R>)),
894     #[cfg(feature = "elf")]
895     Elf32((elf::ElfSymbolTable32<'data, 'file>, PhantomData<R>)),
896     #[cfg(feature = "elf")]
897     Elf64((elf::ElfSymbolTable64<'data, 'file>, PhantomData<R>)),
898     #[cfg(feature = "macho")]
899     MachO32(
900         (
901             macho::MachOSymbolTable32<'data, 'file, Endianness, R>,
902             PhantomData<()>,
903         ),
904     ),
905     #[cfg(feature = "macho")]
906     MachO64(
907         (
908             macho::MachOSymbolTable64<'data, 'file, Endianness, R>,
909             PhantomData<()>,
910         ),
911     ),
912     #[cfg(feature = "pe")]
913     Pe32((coff::CoffSymbolTable<'data, 'file>, PhantomData<R>)),
914     #[cfg(feature = "pe")]
915     Pe64((coff::CoffSymbolTable<'data, 'file>, PhantomData<R>)),
916     #[cfg(feature = "wasm")]
917     Wasm((wasm::WasmSymbolTable<'data, 'file>, PhantomData<R>)),
918 }
919 
920 impl<'data, 'file, R: ReadRef<'data>> read::private::Sealed for SymbolTable<'data, 'file, R> {}
921 
922 impl<'data, 'file, R: ReadRef<'data>> ObjectSymbolTable<'data> for SymbolTable<'data, 'file, R> {
923     type Symbol = Symbol<'data, 'file, R>;
924     type SymbolIterator = SymbolIterator<'data, 'file, R>;
925 
symbols(&self) -> Self::SymbolIterator926     fn symbols(&self) -> Self::SymbolIterator {
927         SymbolIterator {
928             inner: map_inner!(
929                 self.inner,
930                 SymbolTableInternal,
931                 SymbolIteratorInternal,
932                 |x| (x.0.symbols(), PhantomData)
933             ),
934         }
935     }
936 
symbol_by_index(&self, index: SymbolIndex) -> Result<Self::Symbol>937     fn symbol_by_index(&self, index: SymbolIndex) -> Result<Self::Symbol> {
938         map_inner_option!(self.inner, SymbolTableInternal, SymbolInternal, |x| x
939             .0
940             .symbol_by_index(index)
941             .map(|x| (x, PhantomData)))
942         .map(|inner| Symbol { inner })
943     }
944 }
945 
946 /// An iterator over symbol table entries.
947 #[derive(Debug)]
948 pub struct SymbolIterator<'data, 'file, R = &'data [u8]>
949 where
950     'data: 'file,
951     R: ReadRef<'data>,
952 {
953     inner: SymbolIteratorInternal<'data, 'file, R>,
954 }
955 
956 #[derive(Debug)]
957 enum SymbolIteratorInternal<'data, 'file, R>
958 where
959     'data: 'file,
960     R: ReadRef<'data>,
961 {
962     #[cfg(feature = "coff")]
963     Coff((coff::CoffSymbolIterator<'data, 'file>, PhantomData<R>)),
964     #[cfg(feature = "elf")]
965     Elf32((elf::ElfSymbolIterator32<'data, 'file>, PhantomData<R>)),
966     #[cfg(feature = "elf")]
967     Elf64((elf::ElfSymbolIterator64<'data, 'file>, PhantomData<R>)),
968     #[cfg(feature = "macho")]
969     MachO32(
970         (
971             macho::MachOSymbolIterator32<'data, 'file, Endianness, R>,
972             PhantomData<()>,
973         ),
974     ),
975     #[cfg(feature = "macho")]
976     MachO64(
977         (
978             macho::MachOSymbolIterator64<'data, 'file, Endianness, R>,
979             PhantomData<()>,
980         ),
981     ),
982     #[cfg(feature = "pe")]
983     Pe32((coff::CoffSymbolIterator<'data, 'file>, PhantomData<R>)),
984     #[cfg(feature = "pe")]
985     Pe64((coff::CoffSymbolIterator<'data, 'file>, PhantomData<R>)),
986     #[cfg(feature = "wasm")]
987     Wasm((wasm::WasmSymbolIterator<'data, 'file>, PhantomData<R>)),
988 }
989 
990 impl<'data, 'file, R: ReadRef<'data>> Iterator for SymbolIterator<'data, 'file, R> {
991     type Item = Symbol<'data, 'file, R>;
992 
next(&mut self) -> Option<Self::Item>993     fn next(&mut self) -> Option<Self::Item> {
994         map_inner_option_mut!(self.inner, SymbolIteratorInternal, SymbolInternal, |iter| {
995             iter.0.next().map(|x| (x, PhantomData))
996         })
997         .map(|inner| Symbol { inner })
998     }
999 }
1000 
1001 /// A symbol table entry.
1002 pub struct Symbol<'data, 'file, R = &'data [u8]>
1003 where
1004     'data: 'file,
1005     R: ReadRef<'data>,
1006 {
1007     inner: SymbolInternal<'data, 'file, R>,
1008 }
1009 
1010 enum SymbolInternal<'data, 'file, R>
1011 where
1012     'data: 'file,
1013     R: ReadRef<'data>,
1014 {
1015     #[cfg(feature = "coff")]
1016     Coff((coff::CoffSymbol<'data, 'file>, PhantomData<R>)),
1017     #[cfg(feature = "elf")]
1018     Elf32((elf::ElfSymbol32<'data, 'file>, PhantomData<R>)),
1019     #[cfg(feature = "elf")]
1020     Elf64((elf::ElfSymbol64<'data, 'file>, PhantomData<R>)),
1021     #[cfg(feature = "macho")]
1022     MachO32(
1023         (
1024             macho::MachOSymbol32<'data, 'file, Endianness, R>,
1025             PhantomData<()>,
1026         ),
1027     ),
1028     #[cfg(feature = "macho")]
1029     MachO64(
1030         (
1031             macho::MachOSymbol64<'data, 'file, Endianness, R>,
1032             PhantomData<()>,
1033         ),
1034     ),
1035     #[cfg(feature = "pe")]
1036     Pe32((coff::CoffSymbol<'data, 'file>, PhantomData<R>)),
1037     #[cfg(feature = "pe")]
1038     Pe64((coff::CoffSymbol<'data, 'file>, PhantomData<R>)),
1039     #[cfg(feature = "wasm")]
1040     Wasm((wasm::WasmSymbol<'data, 'file>, PhantomData<R>)),
1041 }
1042 
1043 impl<'data, 'file, R: ReadRef<'data>> fmt::Debug for Symbol<'data, 'file, R> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1044     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1045         f.debug_struct("Symbol")
1046             .field("name", &self.name().unwrap_or("<invalid>"))
1047             .field("address", &self.address())
1048             .field("size", &self.size())
1049             .field("kind", &self.kind())
1050             .field("section", &self.section())
1051             .field("scope", &self.scope())
1052             .field("weak", &self.is_weak())
1053             .field("flags", &self.flags())
1054             .finish()
1055     }
1056 }
1057 
1058 impl<'data, 'file, R: ReadRef<'data>> read::private::Sealed for Symbol<'data, 'file, R> {}
1059 
1060 impl<'data, 'file, R: ReadRef<'data>> ObjectSymbol<'data> for Symbol<'data, 'file, R> {
index(&self) -> SymbolIndex1061     fn index(&self) -> SymbolIndex {
1062         with_inner!(self.inner, SymbolInternal, |x| x.0.index())
1063     }
1064 
name(&self) -> Result<&'data str>1065     fn name(&self) -> Result<&'data str> {
1066         with_inner!(self.inner, SymbolInternal, |x| x.0.name())
1067     }
1068 
address(&self) -> u641069     fn address(&self) -> u64 {
1070         with_inner!(self.inner, SymbolInternal, |x| x.0.address())
1071     }
1072 
size(&self) -> u641073     fn size(&self) -> u64 {
1074         with_inner!(self.inner, SymbolInternal, |x| x.0.size())
1075     }
1076 
kind(&self) -> SymbolKind1077     fn kind(&self) -> SymbolKind {
1078         with_inner!(self.inner, SymbolInternal, |x| x.0.kind())
1079     }
1080 
section(&self) -> SymbolSection1081     fn section(&self) -> SymbolSection {
1082         with_inner!(self.inner, SymbolInternal, |x| x.0.section())
1083     }
1084 
is_undefined(&self) -> bool1085     fn is_undefined(&self) -> bool {
1086         with_inner!(self.inner, SymbolInternal, |x| x.0.is_undefined())
1087     }
1088 
is_definition(&self) -> bool1089     fn is_definition(&self) -> bool {
1090         with_inner!(self.inner, SymbolInternal, |x| x.0.is_definition())
1091     }
1092 
is_common(&self) -> bool1093     fn is_common(&self) -> bool {
1094         with_inner!(self.inner, SymbolInternal, |x| x.0.is_common())
1095     }
1096 
is_weak(&self) -> bool1097     fn is_weak(&self) -> bool {
1098         with_inner!(self.inner, SymbolInternal, |x| x.0.is_weak())
1099     }
1100 
scope(&self) -> SymbolScope1101     fn scope(&self) -> SymbolScope {
1102         with_inner!(self.inner, SymbolInternal, |x| x.0.scope())
1103     }
1104 
is_global(&self) -> bool1105     fn is_global(&self) -> bool {
1106         with_inner!(self.inner, SymbolInternal, |x| x.0.is_global())
1107     }
1108 
is_local(&self) -> bool1109     fn is_local(&self) -> bool {
1110         with_inner!(self.inner, SymbolInternal, |x| x.0.is_local())
1111     }
1112 
flags(&self) -> SymbolFlags<SectionIndex>1113     fn flags(&self) -> SymbolFlags<SectionIndex> {
1114         with_inner!(self.inner, SymbolInternal, |x| x.0.flags())
1115     }
1116 }
1117 
1118 /// An iterator over dynamic relocation entries.
1119 #[derive(Debug)]
1120 pub struct DynamicRelocationIterator<'data, 'file, R = &'data [u8]>
1121 where
1122     'data: 'file,
1123     R: ReadRef<'data>,
1124 {
1125     inner: DynamicRelocationIteratorInternal<'data, 'file, R>,
1126 }
1127 
1128 #[derive(Debug)]
1129 enum DynamicRelocationIteratorInternal<'data, 'file, R>
1130 where
1131     'data: 'file,
1132     R: ReadRef<'data>,
1133 {
1134     #[cfg(feature = "elf")]
1135     Elf32(elf::ElfDynamicRelocationIterator32<'data, 'file, Endianness, R>),
1136     #[cfg(feature = "elf")]
1137     Elf64(elf::ElfDynamicRelocationIterator64<'data, 'file, Endianness, R>),
1138     // We need to always use the lifetime parameters.
1139     #[allow(unused)]
1140     None(PhantomData<(&'data (), &'file (), R)>),
1141 }
1142 
1143 impl<'data, 'file, R: ReadRef<'data>> Iterator for DynamicRelocationIterator<'data, 'file, R> {
1144     type Item = (u64, Relocation);
1145 
next(&mut self) -> Option<Self::Item>1146     fn next(&mut self) -> Option<Self::Item> {
1147         match self.inner {
1148             #[cfg(feature = "elf")]
1149             DynamicRelocationIteratorInternal::Elf32(ref mut elf) => elf.next(),
1150             #[cfg(feature = "elf")]
1151             DynamicRelocationIteratorInternal::Elf64(ref mut elf) => elf.next(),
1152             DynamicRelocationIteratorInternal::None(_) => None,
1153         }
1154     }
1155 }
1156 
1157 /// An iterator over section relocation entries.
1158 #[derive(Debug)]
1159 pub struct SectionRelocationIterator<'data, 'file, R: ReadRef<'data> = &'data [u8]>
1160 where
1161     'data: 'file,
1162 {
1163     inner: SectionRelocationIteratorInternal<'data, 'file, R>,
1164 }
1165 
1166 #[derive(Debug)]
1167 enum SectionRelocationIteratorInternal<'data, 'file, R: ReadRef<'data>>
1168 where
1169     'data: 'file,
1170 {
1171     #[cfg(feature = "coff")]
1172     Coff(coff::CoffRelocationIterator<'data, 'file, R>),
1173     #[cfg(feature = "elf")]
1174     Elf32(elf::ElfSectionRelocationIterator32<'data, 'file, Endianness, R>),
1175     #[cfg(feature = "elf")]
1176     Elf64(elf::ElfSectionRelocationIterator64<'data, 'file, Endianness, R>),
1177     #[cfg(feature = "macho")]
1178     MachO32(macho::MachORelocationIterator32<'data, 'file, Endianness, R>),
1179     #[cfg(feature = "macho")]
1180     MachO64(macho::MachORelocationIterator64<'data, 'file, Endianness, R>),
1181     #[cfg(feature = "pe")]
1182     Pe32(pe::PeRelocationIterator<'data, 'file, R>),
1183     #[cfg(feature = "pe")]
1184     Pe64(pe::PeRelocationIterator<'data, 'file, R>),
1185     #[cfg(feature = "wasm")]
1186     Wasm(wasm::WasmRelocationIterator<'data, 'file, R>),
1187 }
1188 
1189 impl<'data, 'file, R: ReadRef<'data>> Iterator for SectionRelocationIterator<'data, 'file, R> {
1190     type Item = (u64, Relocation);
1191 
next(&mut self) -> Option<Self::Item>1192     fn next(&mut self) -> Option<Self::Item> {
1193         with_inner_mut!(self.inner, SectionRelocationIteratorInternal, |x| x.next())
1194     }
1195 }
1196