1 use alloc::fmt;
2 
3 #[cfg(feature = "coff")]
4 use crate::read::coff;
5 #[cfg(feature = "elf")]
6 use crate::read::elf;
7 #[cfg(feature = "macho")]
8 use crate::read::macho;
9 #[cfg(feature = "pe")]
10 use crate::read::pe;
11 #[cfg(feature = "wasm")]
12 use crate::read::wasm;
13 use crate::read::{
14     self, Architecture, BinaryFormat, ComdatKind, CompressedData, Error, FileFlags, Object,
15     ObjectComdat, ObjectMap, ObjectSection, ObjectSegment, ObjectSymbol, ObjectSymbolTable,
16     Relocation, Result, SectionFlags, SectionIndex, SectionKind, SymbolFlags, SymbolIndex,
17     SymbolKind, SymbolMap, SymbolMapName, SymbolScope, SymbolSection,
18 };
19 
20 /// Evaluate an expression on the contents of a file format enum.
21 ///
22 /// This is a hack to avoid virtual calls.
23 macro_rules! with_inner {
24     ($inner:expr, $enum:ident, | $var:ident | $body:expr) => {
25         match $inner {
26             #[cfg(feature = "coff")]
27             $enum::Coff(ref $var) => $body,
28             #[cfg(feature = "elf")]
29             $enum::Elf32(ref $var) => $body,
30             #[cfg(feature = "elf")]
31             $enum::Elf64(ref $var) => $body,
32             #[cfg(feature = "macho")]
33             $enum::MachO32(ref $var) => $body,
34             #[cfg(feature = "macho")]
35             $enum::MachO64(ref $var) => $body,
36             #[cfg(feature = "pe")]
37             $enum::Pe32(ref $var) => $body,
38             #[cfg(feature = "pe")]
39             $enum::Pe64(ref $var) => $body,
40             #[cfg(feature = "wasm")]
41             $enum::Wasm(ref $var) => $body,
42         }
43     };
44 }
45 
46 macro_rules! with_inner_mut {
47     ($inner:expr, $enum:ident, | $var:ident | $body:expr) => {
48         match $inner {
49             #[cfg(feature = "coff")]
50             $enum::Coff(ref mut $var) => $body,
51             #[cfg(feature = "elf")]
52             $enum::Elf32(ref mut $var) => $body,
53             #[cfg(feature = "elf")]
54             $enum::Elf64(ref mut $var) => $body,
55             #[cfg(feature = "macho")]
56             $enum::MachO32(ref mut $var) => $body,
57             #[cfg(feature = "macho")]
58             $enum::MachO64(ref mut $var) => $body,
59             #[cfg(feature = "pe")]
60             $enum::Pe32(ref mut $var) => $body,
61             #[cfg(feature = "pe")]
62             $enum::Pe64(ref mut $var) => $body,
63             #[cfg(feature = "wasm")]
64             $enum::Wasm(ref mut $var) => $body,
65         }
66     };
67 }
68 
69 /// Like `with_inner!`, but wraps the result in another enum.
70 macro_rules! map_inner {
71     ($inner:expr, $from:ident, $to:ident, | $var:ident | $body:expr) => {
72         match $inner {
73             #[cfg(feature = "coff")]
74             $from::Coff(ref $var) => $to::Coff($body),
75             #[cfg(feature = "elf")]
76             $from::Elf32(ref $var) => $to::Elf32($body),
77             #[cfg(feature = "elf")]
78             $from::Elf64(ref $var) => $to::Elf64($body),
79             #[cfg(feature = "macho")]
80             $from::MachO32(ref $var) => $to::MachO32($body),
81             #[cfg(feature = "macho")]
82             $from::MachO64(ref $var) => $to::MachO64($body),
83             #[cfg(feature = "pe")]
84             $from::Pe32(ref $var) => $to::Pe32($body),
85             #[cfg(feature = "pe")]
86             $from::Pe64(ref $var) => $to::Pe64($body),
87             #[cfg(feature = "wasm")]
88             $from::Wasm(ref $var) => $to::Wasm($body),
89         }
90     };
91 }
92 
93 /// Like `map_inner!`, but the result is a Result or Option.
94 macro_rules! map_inner_option {
95     ($inner:expr, $from:ident, $to:ident, | $var:ident | $body:expr) => {
96         match $inner {
97             #[cfg(feature = "coff")]
98             $from::Coff(ref $var) => $body.map($to::Coff),
99             #[cfg(feature = "elf")]
100             $from::Elf32(ref $var) => $body.map($to::Elf32),
101             #[cfg(feature = "elf")]
102             $from::Elf64(ref $var) => $body.map($to::Elf64),
103             #[cfg(feature = "macho")]
104             $from::MachO32(ref $var) => $body.map($to::MachO32),
105             #[cfg(feature = "macho")]
106             $from::MachO64(ref $var) => $body.map($to::MachO64),
107             #[cfg(feature = "pe")]
108             $from::Pe32(ref $var) => $body.map($to::Pe32),
109             #[cfg(feature = "pe")]
110             $from::Pe64(ref $var) => $body.map($to::Pe64),
111             #[cfg(feature = "wasm")]
112             $from::Wasm(ref $var) => $body.map($to::Wasm),
113         }
114     };
115 }
116 
117 /// Call `next` for a file format iterator.
118 macro_rules! next_inner {
119     ($inner:expr, $from:ident, $to:ident) => {
120         match $inner {
121             #[cfg(feature = "coff")]
122             $from::Coff(ref mut iter) => iter.next().map($to::Coff),
123             #[cfg(feature = "elf")]
124             $from::Elf32(ref mut iter) => iter.next().map($to::Elf32),
125             #[cfg(feature = "elf")]
126             $from::Elf64(ref mut iter) => iter.next().map($to::Elf64),
127             #[cfg(feature = "macho")]
128             $from::MachO32(ref mut iter) => iter.next().map($to::MachO32),
129             #[cfg(feature = "macho")]
130             $from::MachO64(ref mut iter) => iter.next().map($to::MachO64),
131             #[cfg(feature = "pe")]
132             $from::Pe32(ref mut iter) => iter.next().map($to::Pe32),
133             #[cfg(feature = "pe")]
134             $from::Pe64(ref mut iter) => iter.next().map($to::Pe64),
135             #[cfg(feature = "wasm")]
136             $from::Wasm(ref mut iter) => iter.next().map($to::Wasm),
137         }
138     };
139 }
140 
141 /// An object file.
142 ///
143 /// Most functionality is provided by the `Object` trait implementation.
144 #[derive(Debug)]
145 pub struct File<'data> {
146     inner: FileInternal<'data>,
147 }
148 
149 #[allow(clippy::large_enum_variant)]
150 #[derive(Debug)]
151 enum FileInternal<'data> {
152     #[cfg(feature = "coff")]
153     Coff(coff::CoffFile<'data>),
154     #[cfg(feature = "elf")]
155     Elf32(elf::ElfFile32<'data>),
156     #[cfg(feature = "elf")]
157     Elf64(elf::ElfFile64<'data>),
158     #[cfg(feature = "macho")]
159     MachO32(macho::MachOFile32<'data>),
160     #[cfg(feature = "macho")]
161     MachO64(macho::MachOFile64<'data>),
162     #[cfg(feature = "pe")]
163     Pe32(pe::PeFile32<'data>),
164     #[cfg(feature = "pe")]
165     Pe64(pe::PeFile64<'data>),
166     #[cfg(feature = "wasm")]
167     Wasm(wasm::WasmFile<'data>),
168 }
169 
170 impl<'data> File<'data> {
171     /// Parse the raw file data.
parse(data: &'data [u8]) -> Result<Self>172     pub fn parse(data: &'data [u8]) -> Result<Self> {
173         if data.len() < 16 {
174             return Err(Error("File too short"));
175         }
176 
177         let inner = match [data[0], data[1], data[2], data[3], data[4]] {
178             // 32-bit ELF
179             #[cfg(feature = "elf")]
180             [0x7f, b'E', b'L', b'F', 1] => FileInternal::Elf32(elf::ElfFile32::parse(data)?),
181             // 64-bit ELF
182             #[cfg(feature = "elf")]
183             [0x7f, b'E', b'L', b'F', 2] => FileInternal::Elf64(elf::ElfFile64::parse(data)?),
184             // 32-bit Mach-O
185             #[cfg(feature = "macho")]
186             [0xfe, 0xed, 0xfa, 0xce, _]
187             | [0xce, 0xfa, 0xed, 0xfe, _] => FileInternal::MachO32(macho::MachOFile32::parse(data)?),
188             // 64-bit Mach-O
189             #[cfg(feature = "macho")]
190             | [0xfe, 0xed, 0xfa, 0xcf, _]
191             | [0xcf, 0xfa, 0xed, 0xfe, _] => FileInternal::MachO64(macho::MachOFile64::parse(data)?),
192             // WASM
193             #[cfg(feature = "wasm")]
194             [0x00, b'a', b's', b'm', _] => FileInternal::Wasm(wasm::WasmFile::parse(data)?),
195             // MS-DOS, assume stub for Windows PE32 or PE32+
196             #[cfg(feature = "pe")]
197             [b'M', b'Z', _, _, _] => {
198                 // `optional_header_magic` doesn't care if it's `PeFile32` and `PeFile64`.
199                 match pe::PeFile64::optional_header_magic(data) {
200                     Ok(crate::pe::IMAGE_NT_OPTIONAL_HDR32_MAGIC) => {
201                         FileInternal::Pe32(pe::PeFile32::parse(data)?)
202                     }
203                     Ok(crate::pe::IMAGE_NT_OPTIONAL_HDR64_MAGIC) => {
204                         FileInternal::Pe64(pe::PeFile64::parse(data)?)
205                     }
206                     _ => return Err(Error("Unknown MS-DOS file")),
207                 }
208             }
209             // TODO: more COFF machines
210             #[cfg(feature = "coff")]
211             // COFF x86
212             [0x4c, 0x01, _, _, _]
213             // COFF x86-64
214             | [0x64, 0x86, _, _, _] => FileInternal::Coff(coff::CoffFile::parse(data)?),
215             _ => return Err(Error("Unknown file magic")),
216         };
217         Ok(File { inner })
218     }
219 
220     /// Return the file format.
format(&self) -> BinaryFormat221     pub fn format(&self) -> BinaryFormat {
222         match self.inner {
223             #[cfg(feature = "coff")]
224             FileInternal::Coff(_) => BinaryFormat::Coff,
225             #[cfg(feature = "elf")]
226             FileInternal::Elf32(_) | FileInternal::Elf64(_) => BinaryFormat::Elf,
227             #[cfg(feature = "macho")]
228             FileInternal::MachO32(_) | FileInternal::MachO64(_) => BinaryFormat::MachO,
229             #[cfg(feature = "pe")]
230             FileInternal::Pe32(_) | FileInternal::Pe64(_) => BinaryFormat::Pe,
231             #[cfg(feature = "wasm")]
232             FileInternal::Wasm(_) => BinaryFormat::Wasm,
233         }
234     }
235 }
236 
237 impl<'data> read::private::Sealed for File<'data> {}
238 
239 impl<'data, 'file> Object<'data, 'file> for File<'data>
240 where
241     'data: 'file,
242 {
243     type Segment = Segment<'data, 'file>;
244     type SegmentIterator = SegmentIterator<'data, 'file>;
245     type Section = Section<'data, 'file>;
246     type SectionIterator = SectionIterator<'data, 'file>;
247     type Comdat = Comdat<'data, 'file>;
248     type ComdatIterator = ComdatIterator<'data, 'file>;
249     type Symbol = Symbol<'data, 'file>;
250     type SymbolIterator = SymbolIterator<'data, 'file>;
251     type SymbolTable = SymbolTable<'data, 'file>;
252 
architecture(&self) -> Architecture253     fn architecture(&self) -> Architecture {
254         with_inner!(self.inner, FileInternal, |x| x.architecture())
255     }
256 
is_little_endian(&self) -> bool257     fn is_little_endian(&self) -> bool {
258         with_inner!(self.inner, FileInternal, |x| x.is_little_endian())
259     }
260 
is_64(&self) -> bool261     fn is_64(&self) -> bool {
262         with_inner!(self.inner, FileInternal, |x| x.is_64())
263     }
264 
segments(&'file self) -> SegmentIterator<'data, 'file>265     fn segments(&'file self) -> SegmentIterator<'data, 'file> {
266         SegmentIterator {
267             inner: map_inner!(self.inner, FileInternal, SegmentIteratorInternal, |x| x
268                 .segments()),
269         }
270     }
271 
section_by_name(&'file self, section_name: &str) -> Option<Section<'data, 'file>>272     fn section_by_name(&'file self, section_name: &str) -> Option<Section<'data, 'file>> {
273         map_inner_option!(self.inner, FileInternal, SectionInternal, |x| x
274             .section_by_name(section_name))
275         .map(|inner| Section { inner })
276     }
277 
section_by_index(&'file self, index: SectionIndex) -> Result<Section<'data, 'file>>278     fn section_by_index(&'file self, index: SectionIndex) -> Result<Section<'data, 'file>> {
279         map_inner_option!(self.inner, FileInternal, SectionInternal, |x| x
280             .section_by_index(index))
281         .map(|inner| Section { inner })
282     }
283 
sections(&'file self) -> SectionIterator<'data, 'file>284     fn sections(&'file self) -> SectionIterator<'data, 'file> {
285         SectionIterator {
286             inner: map_inner!(self.inner, FileInternal, SectionIteratorInternal, |x| x
287                 .sections()),
288         }
289     }
290 
comdats(&'file self) -> ComdatIterator<'data, 'file>291     fn comdats(&'file self) -> ComdatIterator<'data, 'file> {
292         ComdatIterator {
293             inner: map_inner!(self.inner, FileInternal, ComdatIteratorInternal, |x| x
294                 .comdats()),
295         }
296     }
297 
symbol_by_index(&'file self, index: SymbolIndex) -> Result<Symbol<'data, 'file>>298     fn symbol_by_index(&'file self, index: SymbolIndex) -> Result<Symbol<'data, 'file>> {
299         map_inner_option!(self.inner, FileInternal, SymbolInternal, |x| x
300             .symbol_by_index(index))
301         .map(|inner| Symbol { inner })
302     }
303 
symbols(&'file self) -> SymbolIterator<'data, 'file>304     fn symbols(&'file self) -> SymbolIterator<'data, 'file> {
305         SymbolIterator {
306             inner: map_inner!(self.inner, FileInternal, SymbolIteratorInternal, |x| x
307                 .symbols()),
308         }
309     }
310 
symbol_table(&'file self) -> Option<SymbolTable<'data, 'file>>311     fn symbol_table(&'file self) -> Option<SymbolTable<'data, 'file>> {
312         map_inner_option!(self.inner, FileInternal, SymbolTableInternal, |x| x
313             .symbol_table())
314         .map(|inner| SymbolTable { inner })
315     }
316 
dynamic_symbols(&'file self) -> SymbolIterator<'data, 'file>317     fn dynamic_symbols(&'file self) -> SymbolIterator<'data, 'file> {
318         SymbolIterator {
319             inner: map_inner!(self.inner, FileInternal, SymbolIteratorInternal, |x| x
320                 .dynamic_symbols()),
321         }
322     }
323 
dynamic_symbol_table(&'file self) -> Option<SymbolTable<'data, 'file>>324     fn dynamic_symbol_table(&'file self) -> Option<SymbolTable<'data, 'file>> {
325         map_inner_option!(self.inner, FileInternal, SymbolTableInternal, |x| x
326             .dynamic_symbol_table())
327         .map(|inner| SymbolTable { inner })
328     }
329 
symbol_map(&self) -> SymbolMap<SymbolMapName<'data>>330     fn symbol_map(&self) -> SymbolMap<SymbolMapName<'data>> {
331         with_inner!(self.inner, FileInternal, |x| x.symbol_map())
332     }
333 
object_map(&self) -> ObjectMap<'data>334     fn object_map(&self) -> ObjectMap<'data> {
335         with_inner!(self.inner, FileInternal, |x| x.object_map())
336     }
337 
has_debug_symbols(&self) -> bool338     fn has_debug_symbols(&self) -> bool {
339         with_inner!(self.inner, FileInternal, |x| x.has_debug_symbols())
340     }
341 
342     #[inline]
mach_uuid(&self) -> Result<Option<[u8; 16]>>343     fn mach_uuid(&self) -> Result<Option<[u8; 16]>> {
344         with_inner!(self.inner, FileInternal, |x| x.mach_uuid())
345     }
346 
347     #[inline]
build_id(&self) -> Result<Option<&'data [u8]>>348     fn build_id(&self) -> Result<Option<&'data [u8]>> {
349         with_inner!(self.inner, FileInternal, |x| x.build_id())
350     }
351 
352     #[inline]
gnu_debuglink(&self) -> Result<Option<(&'data [u8], u32)>>353     fn gnu_debuglink(&self) -> Result<Option<(&'data [u8], u32)>> {
354         with_inner!(self.inner, FileInternal, |x| x.gnu_debuglink())
355     }
356 
entry(&self) -> u64357     fn entry(&self) -> u64 {
358         with_inner!(self.inner, FileInternal, |x| x.entry())
359     }
360 
flags(&self) -> FileFlags361     fn flags(&self) -> FileFlags {
362         with_inner!(self.inner, FileInternal, |x| x.flags())
363     }
364 }
365 
366 /// An iterator over the segments of a `File`.
367 #[derive(Debug)]
368 pub struct SegmentIterator<'data, 'file>
369 where
370     'data: 'file,
371 {
372     inner: SegmentIteratorInternal<'data, 'file>,
373 }
374 
375 #[derive(Debug)]
376 enum SegmentIteratorInternal<'data, 'file>
377 where
378     'data: 'file,
379 {
380     #[cfg(feature = "coff")]
381     Coff(coff::CoffSegmentIterator<'data, 'file>),
382     #[cfg(feature = "elf")]
383     Elf32(elf::ElfSegmentIterator32<'data, 'file>),
384     #[cfg(feature = "elf")]
385     Elf64(elf::ElfSegmentIterator64<'data, 'file>),
386     #[cfg(feature = "macho")]
387     MachO32(macho::MachOSegmentIterator32<'data, 'file>),
388     #[cfg(feature = "macho")]
389     MachO64(macho::MachOSegmentIterator64<'data, 'file>),
390     #[cfg(feature = "pe")]
391     Pe32(pe::PeSegmentIterator32<'data, 'file>),
392     #[cfg(feature = "pe")]
393     Pe64(pe::PeSegmentIterator64<'data, 'file>),
394     #[cfg(feature = "wasm")]
395     Wasm(wasm::WasmSegmentIterator<'data, 'file>),
396 }
397 
398 impl<'data, 'file> Iterator for SegmentIterator<'data, 'file> {
399     type Item = Segment<'data, 'file>;
400 
next(&mut self) -> Option<Self::Item>401     fn next(&mut self) -> Option<Self::Item> {
402         next_inner!(self.inner, SegmentIteratorInternal, SegmentInternal)
403             .map(|inner| Segment { inner })
404     }
405 }
406 
407 /// A segment of a `File`.
408 pub struct Segment<'data, 'file>
409 where
410     'data: 'file,
411 {
412     inner: SegmentInternal<'data, 'file>,
413 }
414 
415 #[derive(Debug)]
416 enum SegmentInternal<'data, 'file>
417 where
418     'data: 'file,
419 {
420     #[cfg(feature = "coff")]
421     Coff(coff::CoffSegment<'data, 'file>),
422     #[cfg(feature = "elf")]
423     Elf32(elf::ElfSegment32<'data, 'file>),
424     #[cfg(feature = "elf")]
425     Elf64(elf::ElfSegment64<'data, 'file>),
426     #[cfg(feature = "macho")]
427     MachO32(macho::MachOSegment32<'data, 'file>),
428     #[cfg(feature = "macho")]
429     MachO64(macho::MachOSegment64<'data, 'file>),
430     #[cfg(feature = "pe")]
431     Pe32(pe::PeSegment32<'data, 'file>),
432     #[cfg(feature = "pe")]
433     Pe64(pe::PeSegment64<'data, 'file>),
434     #[cfg(feature = "wasm")]
435     Wasm(wasm::WasmSegment<'data, 'file>),
436 }
437 
438 impl<'data, 'file> fmt::Debug for Segment<'data, 'file> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result439     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
440         // It's painful to do much better than this
441         let mut s = f.debug_struct("Segment");
442         match self.name() {
443             Ok(Some(ref name)) => {
444                 s.field("name", name);
445             }
446             Ok(None) => {}
447             Err(_) => {
448                 s.field("name", &"<invalid>");
449             }
450         }
451         s.field("address", &self.address())
452             .field("size", &self.size())
453             .finish()
454     }
455 }
456 
457 impl<'data, 'file> read::private::Sealed for Segment<'data, 'file> {}
458 
459 impl<'data, 'file> ObjectSegment<'data> for Segment<'data, 'file> {
address(&self) -> u64460     fn address(&self) -> u64 {
461         with_inner!(self.inner, SegmentInternal, |x| x.address())
462     }
463 
size(&self) -> u64464     fn size(&self) -> u64 {
465         with_inner!(self.inner, SegmentInternal, |x| x.size())
466     }
467 
align(&self) -> u64468     fn align(&self) -> u64 {
469         with_inner!(self.inner, SegmentInternal, |x| x.align())
470     }
471 
file_range(&self) -> (u64, u64)472     fn file_range(&self) -> (u64, u64) {
473         with_inner!(self.inner, SegmentInternal, |x| x.file_range())
474     }
475 
data(&self) -> Result<&'data [u8]>476     fn data(&self) -> Result<&'data [u8]> {
477         with_inner!(self.inner, SegmentInternal, |x| x.data())
478     }
479 
data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>>480     fn data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>> {
481         with_inner!(self.inner, SegmentInternal, |x| x.data_range(address, size))
482     }
483 
name(&self) -> Result<Option<&str>>484     fn name(&self) -> Result<Option<&str>> {
485         with_inner!(self.inner, SegmentInternal, |x| x.name())
486     }
487 }
488 
489 /// An iterator of the sections of a `File`.
490 #[derive(Debug)]
491 pub struct SectionIterator<'data, 'file>
492 where
493     'data: 'file,
494 {
495     inner: SectionIteratorInternal<'data, 'file>,
496 }
497 
498 // we wrap our enums in a struct so that they are kept private.
499 #[derive(Debug)]
500 enum SectionIteratorInternal<'data, 'file>
501 where
502     'data: 'file,
503 {
504     #[cfg(feature = "coff")]
505     Coff(coff::CoffSectionIterator<'data, 'file>),
506     #[cfg(feature = "elf")]
507     Elf32(elf::ElfSectionIterator32<'data, 'file>),
508     #[cfg(feature = "elf")]
509     Elf64(elf::ElfSectionIterator64<'data, 'file>),
510     #[cfg(feature = "macho")]
511     MachO32(macho::MachOSectionIterator32<'data, 'file>),
512     #[cfg(feature = "macho")]
513     MachO64(macho::MachOSectionIterator64<'data, 'file>),
514     #[cfg(feature = "pe")]
515     Pe32(pe::PeSectionIterator32<'data, 'file>),
516     #[cfg(feature = "pe")]
517     Pe64(pe::PeSectionIterator64<'data, 'file>),
518     #[cfg(feature = "wasm")]
519     Wasm(wasm::WasmSectionIterator<'data, 'file>),
520 }
521 
522 impl<'data, 'file> Iterator for SectionIterator<'data, 'file> {
523     type Item = Section<'data, 'file>;
524 
next(&mut self) -> Option<Self::Item>525     fn next(&mut self) -> Option<Self::Item> {
526         next_inner!(self.inner, SectionIteratorInternal, SectionInternal)
527             .map(|inner| Section { inner })
528     }
529 }
530 
531 /// A Section of a File
532 pub struct Section<'data, 'file>
533 where
534     'data: 'file,
535 {
536     inner: SectionInternal<'data, 'file>,
537 }
538 
539 enum SectionInternal<'data, 'file>
540 where
541     'data: 'file,
542 {
543     #[cfg(feature = "coff")]
544     Coff(coff::CoffSection<'data, 'file>),
545     #[cfg(feature = "elf")]
546     Elf32(elf::ElfSection32<'data, 'file>),
547     #[cfg(feature = "elf")]
548     Elf64(elf::ElfSection64<'data, 'file>),
549     #[cfg(feature = "macho")]
550     MachO32(macho::MachOSection32<'data, 'file>),
551     #[cfg(feature = "macho")]
552     MachO64(macho::MachOSection64<'data, 'file>),
553     #[cfg(feature = "pe")]
554     Pe32(pe::PeSection32<'data, 'file>),
555     #[cfg(feature = "pe")]
556     Pe64(pe::PeSection64<'data, 'file>),
557     #[cfg(feature = "wasm")]
558     Wasm(wasm::WasmSection<'data, 'file>),
559 }
560 
561 impl<'data, 'file> fmt::Debug for Section<'data, 'file> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result562     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
563         // It's painful to do much better than this
564         let mut s = f.debug_struct("Section");
565         match self.segment_name() {
566             Ok(Some(ref name)) => {
567                 s.field("segment", name);
568             }
569             Ok(None) => {}
570             Err(_) => {
571                 s.field("segment", &"<invalid>");
572             }
573         }
574         s.field("name", &self.name().unwrap_or("<invalid>"))
575             .field("address", &self.address())
576             .field("size", &self.size())
577             .field("align", &self.align())
578             .field("kind", &self.kind())
579             .field("flags", &self.flags())
580             .finish()
581     }
582 }
583 
584 impl<'data, 'file> read::private::Sealed for Section<'data, 'file> {}
585 
586 impl<'data, 'file> ObjectSection<'data> for Section<'data, 'file> {
587     type RelocationIterator = RelocationIterator<'data, 'file>;
588 
index(&self) -> SectionIndex589     fn index(&self) -> SectionIndex {
590         with_inner!(self.inner, SectionInternal, |x| x.index())
591     }
592 
address(&self) -> u64593     fn address(&self) -> u64 {
594         with_inner!(self.inner, SectionInternal, |x| x.address())
595     }
596 
size(&self) -> u64597     fn size(&self) -> u64 {
598         with_inner!(self.inner, SectionInternal, |x| x.size())
599     }
600 
align(&self) -> u64601     fn align(&self) -> u64 {
602         with_inner!(self.inner, SectionInternal, |x| x.align())
603     }
604 
file_range(&self) -> Option<(u64, u64)>605     fn file_range(&self) -> Option<(u64, u64)> {
606         with_inner!(self.inner, SectionInternal, |x| x.file_range())
607     }
608 
data(&self) -> Result<&'data [u8]>609     fn data(&self) -> Result<&'data [u8]> {
610         with_inner!(self.inner, SectionInternal, |x| x.data())
611     }
612 
data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>>613     fn data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>> {
614         with_inner!(self.inner, SectionInternal, |x| x.data_range(address, size))
615     }
616 
compressed_data(&self) -> Result<CompressedData<'data>>617     fn compressed_data(&self) -> Result<CompressedData<'data>> {
618         with_inner!(self.inner, SectionInternal, |x| x.compressed_data())
619     }
620 
name(&self) -> Result<&str>621     fn name(&self) -> Result<&str> {
622         with_inner!(self.inner, SectionInternal, |x| x.name())
623     }
624 
segment_name(&self) -> Result<Option<&str>>625     fn segment_name(&self) -> Result<Option<&str>> {
626         with_inner!(self.inner, SectionInternal, |x| x.segment_name())
627     }
628 
kind(&self) -> SectionKind629     fn kind(&self) -> SectionKind {
630         with_inner!(self.inner, SectionInternal, |x| x.kind())
631     }
632 
relocations(&self) -> RelocationIterator<'data, 'file>633     fn relocations(&self) -> RelocationIterator<'data, 'file> {
634         RelocationIterator {
635             inner: map_inner!(
636                 self.inner,
637                 SectionInternal,
638                 RelocationIteratorInternal,
639                 |x| x.relocations()
640             ),
641         }
642     }
643 
flags(&self) -> SectionFlags644     fn flags(&self) -> SectionFlags {
645         with_inner!(self.inner, SectionInternal, |x| x.flags())
646     }
647 }
648 
649 /// An iterator of the COMDAT section groups of a `File`.
650 #[derive(Debug)]
651 pub struct ComdatIterator<'data, 'file>
652 where
653     'data: 'file,
654 {
655     inner: ComdatIteratorInternal<'data, 'file>,
656 }
657 
658 #[derive(Debug)]
659 enum ComdatIteratorInternal<'data, 'file>
660 where
661     'data: 'file,
662 {
663     #[cfg(feature = "coff")]
664     Coff(coff::CoffComdatIterator<'data, 'file>),
665     #[cfg(feature = "elf")]
666     Elf32(elf::ElfComdatIterator32<'data, 'file>),
667     #[cfg(feature = "elf")]
668     Elf64(elf::ElfComdatIterator64<'data, 'file>),
669     #[cfg(feature = "macho")]
670     MachO32(macho::MachOComdatIterator32<'data, 'file>),
671     #[cfg(feature = "macho")]
672     MachO64(macho::MachOComdatIterator64<'data, 'file>),
673     #[cfg(feature = "pe")]
674     Pe32(pe::PeComdatIterator32<'data, 'file>),
675     #[cfg(feature = "pe")]
676     Pe64(pe::PeComdatIterator64<'data, 'file>),
677     #[cfg(feature = "wasm")]
678     Wasm(wasm::WasmComdatIterator<'data, 'file>),
679 }
680 
681 impl<'data, 'file> Iterator for ComdatIterator<'data, 'file> {
682     type Item = Comdat<'data, 'file>;
683 
next(&mut self) -> Option<Self::Item>684     fn next(&mut self) -> Option<Self::Item> {
685         next_inner!(self.inner, ComdatIteratorInternal, ComdatInternal)
686             .map(|inner| Comdat { inner })
687     }
688 }
689 
690 /// A COMDAT section group of a `File`.
691 pub struct Comdat<'data, 'file>
692 where
693     'data: 'file,
694 {
695     inner: ComdatInternal<'data, 'file>,
696 }
697 
698 enum ComdatInternal<'data, 'file>
699 where
700     'data: 'file,
701 {
702     #[cfg(feature = "coff")]
703     Coff(coff::CoffComdat<'data, 'file>),
704     #[cfg(feature = "elf")]
705     Elf32(elf::ElfComdat32<'data, 'file>),
706     #[cfg(feature = "elf")]
707     Elf64(elf::ElfComdat64<'data, 'file>),
708     #[cfg(feature = "macho")]
709     MachO32(macho::MachOComdat32<'data, 'file>),
710     #[cfg(feature = "macho")]
711     MachO64(macho::MachOComdat64<'data, 'file>),
712     #[cfg(feature = "pe")]
713     Pe32(pe::PeComdat32<'data, 'file>),
714     #[cfg(feature = "pe")]
715     Pe64(pe::PeComdat64<'data, 'file>),
716     #[cfg(feature = "wasm")]
717     Wasm(wasm::WasmComdat<'data, 'file>),
718 }
719 
720 impl<'data, 'file> fmt::Debug for Comdat<'data, 'file> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result721     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
722         let mut s = f.debug_struct("Comdat");
723         s.field("symbol", &self.symbol())
724             .field("name", &self.name().unwrap_or("<invalid>"))
725             .field("kind", &self.kind())
726             .finish()
727     }
728 }
729 
730 impl<'data, 'file> read::private::Sealed for Comdat<'data, 'file> {}
731 
732 impl<'data, 'file> ObjectComdat<'data> for Comdat<'data, 'file> {
733     type SectionIterator = ComdatSectionIterator<'data, 'file>;
734 
kind(&self) -> ComdatKind735     fn kind(&self) -> ComdatKind {
736         with_inner!(self.inner, ComdatInternal, |x| x.kind())
737     }
738 
symbol(&self) -> SymbolIndex739     fn symbol(&self) -> SymbolIndex {
740         with_inner!(self.inner, ComdatInternal, |x| x.symbol())
741     }
742 
name(&self) -> Result<&str>743     fn name(&self) -> Result<&str> {
744         with_inner!(self.inner, ComdatInternal, |x| x.name())
745     }
746 
sections(&self) -> ComdatSectionIterator<'data, 'file>747     fn sections(&self) -> ComdatSectionIterator<'data, 'file> {
748         ComdatSectionIterator {
749             inner: map_inner!(
750                 self.inner,
751                 ComdatInternal,
752                 ComdatSectionIteratorInternal,
753                 |x| x.sections()
754             ),
755         }
756     }
757 }
758 
759 /// An iterator over COMDAT section entries.
760 #[derive(Debug)]
761 pub struct ComdatSectionIterator<'data, 'file>
762 where
763     'data: 'file,
764 {
765     inner: ComdatSectionIteratorInternal<'data, 'file>,
766 }
767 
768 #[derive(Debug)]
769 enum ComdatSectionIteratorInternal<'data, 'file>
770 where
771     'data: 'file,
772 {
773     #[cfg(feature = "coff")]
774     Coff(coff::CoffComdatSectionIterator<'data, 'file>),
775     #[cfg(feature = "elf")]
776     Elf32(elf::ElfComdatSectionIterator32<'data, 'file>),
777     #[cfg(feature = "elf")]
778     Elf64(elf::ElfComdatSectionIterator64<'data, 'file>),
779     #[cfg(feature = "macho")]
780     MachO32(macho::MachOComdatSectionIterator32<'data, 'file>),
781     #[cfg(feature = "macho")]
782     MachO64(macho::MachOComdatSectionIterator64<'data, 'file>),
783     #[cfg(feature = "pe")]
784     Pe32(pe::PeComdatSectionIterator32<'data, 'file>),
785     #[cfg(feature = "pe")]
786     Pe64(pe::PeComdatSectionIterator64<'data, 'file>),
787     #[cfg(feature = "wasm")]
788     Wasm(wasm::WasmComdatSectionIterator<'data, 'file>),
789 }
790 
791 impl<'data, 'file> Iterator for ComdatSectionIterator<'data, 'file> {
792     type Item = SectionIndex;
793 
next(&mut self) -> Option<Self::Item>794     fn next(&mut self) -> Option<Self::Item> {
795         with_inner_mut!(self.inner, ComdatSectionIteratorInternal, |x| x.next())
796     }
797 }
798 
799 /// A symbol table.
800 #[derive(Debug)]
801 pub struct SymbolTable<'data, 'file>
802 where
803     'data: 'file,
804 {
805     inner: SymbolTableInternal<'data, 'file>,
806 }
807 
808 #[derive(Debug)]
809 enum SymbolTableInternal<'data, 'file>
810 where
811     'data: 'file,
812 {
813     #[cfg(feature = "coff")]
814     Coff(coff::CoffSymbolTable<'data, 'file>),
815     #[cfg(feature = "elf")]
816     Elf32(elf::ElfSymbolTable32<'data, 'file>),
817     #[cfg(feature = "elf")]
818     Elf64(elf::ElfSymbolTable64<'data, 'file>),
819     #[cfg(feature = "macho")]
820     MachO32(macho::MachOSymbolTable32<'data, 'file>),
821     #[cfg(feature = "macho")]
822     MachO64(macho::MachOSymbolTable64<'data, 'file>),
823     #[cfg(feature = "pe")]
824     Pe32(coff::CoffSymbolTable<'data, 'file>),
825     #[cfg(feature = "pe")]
826     Pe64(coff::CoffSymbolTable<'data, 'file>),
827     #[cfg(feature = "wasm")]
828     Wasm(wasm::WasmSymbolTable<'data, 'file>),
829 }
830 
831 impl<'data, 'file> read::private::Sealed for SymbolTable<'data, 'file> {}
832 
833 impl<'data, 'file> ObjectSymbolTable<'data> for SymbolTable<'data, 'file> {
834     type Symbol = Symbol<'data, 'file>;
835     type SymbolIterator = SymbolIterator<'data, 'file>;
836 
symbols(&self) -> Self::SymbolIterator837     fn symbols(&self) -> Self::SymbolIterator {
838         SymbolIterator {
839             inner: map_inner!(
840                 self.inner,
841                 SymbolTableInternal,
842                 SymbolIteratorInternal,
843                 |x| x.symbols()
844             ),
845         }
846     }
847 
symbol_by_index(&self, index: SymbolIndex) -> Result<Self::Symbol>848     fn symbol_by_index(&self, index: SymbolIndex) -> Result<Self::Symbol> {
849         map_inner_option!(self.inner, SymbolTableInternal, SymbolInternal, |x| x
850             .symbol_by_index(index))
851         .map(|inner| Symbol { inner })
852     }
853 }
854 
855 /// An iterator over symbol table entries.
856 #[derive(Debug)]
857 pub struct SymbolIterator<'data, 'file>
858 where
859     'data: 'file,
860 {
861     inner: SymbolIteratorInternal<'data, 'file>,
862 }
863 
864 #[derive(Debug)]
865 enum SymbolIteratorInternal<'data, 'file>
866 where
867     'data: 'file,
868 {
869     #[cfg(feature = "coff")]
870     Coff(coff::CoffSymbolIterator<'data, 'file>),
871     #[cfg(feature = "elf")]
872     Elf32(elf::ElfSymbolIterator32<'data, 'file>),
873     #[cfg(feature = "elf")]
874     Elf64(elf::ElfSymbolIterator64<'data, 'file>),
875     #[cfg(feature = "macho")]
876     MachO32(macho::MachOSymbolIterator32<'data, 'file>),
877     #[cfg(feature = "macho")]
878     MachO64(macho::MachOSymbolIterator64<'data, 'file>),
879     #[cfg(feature = "pe")]
880     Pe32(coff::CoffSymbolIterator<'data, 'file>),
881     #[cfg(feature = "pe")]
882     Pe64(coff::CoffSymbolIterator<'data, 'file>),
883     #[cfg(feature = "wasm")]
884     Wasm(wasm::WasmSymbolIterator<'data, 'file>),
885 }
886 
887 impl<'data, 'file> Iterator for SymbolIterator<'data, 'file> {
888     type Item = Symbol<'data, 'file>;
889 
next(&mut self) -> Option<Self::Item>890     fn next(&mut self) -> Option<Self::Item> {
891         next_inner!(self.inner, SymbolIteratorInternal, SymbolInternal)
892             .map(|inner| Symbol { inner })
893     }
894 }
895 
896 /// A symbol table entry.
897 pub struct Symbol<'data, 'file>
898 where
899     'data: 'file,
900 {
901     inner: SymbolInternal<'data, 'file>,
902 }
903 
904 enum SymbolInternal<'data, 'file>
905 where
906     'data: 'file,
907 {
908     #[cfg(feature = "coff")]
909     Coff(coff::CoffSymbol<'data, 'file>),
910     #[cfg(feature = "elf")]
911     Elf32(elf::ElfSymbol32<'data, 'file>),
912     #[cfg(feature = "elf")]
913     Elf64(elf::ElfSymbol64<'data, 'file>),
914     #[cfg(feature = "macho")]
915     MachO32(macho::MachOSymbol32<'data, 'file>),
916     #[cfg(feature = "macho")]
917     MachO64(macho::MachOSymbol64<'data, 'file>),
918     #[cfg(feature = "pe")]
919     Pe32(coff::CoffSymbol<'data, 'file>),
920     #[cfg(feature = "pe")]
921     Pe64(coff::CoffSymbol<'data, 'file>),
922     #[cfg(feature = "wasm")]
923     Wasm(wasm::WasmSymbol<'data, 'file>),
924 }
925 
926 impl<'data, 'file> fmt::Debug for Symbol<'data, 'file> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result927     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
928         f.debug_struct("Symbol")
929             .field("name", &self.name().unwrap_or("<invalid>"))
930             .field("address", &self.address())
931             .field("size", &self.size())
932             .field("kind", &self.kind())
933             .field("section", &self.section())
934             .field("scope", &self.scope())
935             .field("weak", &self.is_weak())
936             .field("flags", &self.flags())
937             .finish()
938     }
939 }
940 
941 impl<'data, 'file> read::private::Sealed for Symbol<'data, 'file> {}
942 
943 impl<'data, 'file> ObjectSymbol<'data> for Symbol<'data, 'file> {
index(&self) -> SymbolIndex944     fn index(&self) -> SymbolIndex {
945         with_inner!(self.inner, SymbolInternal, |x| x.index())
946     }
947 
name(&self) -> Result<&'data str>948     fn name(&self) -> Result<&'data str> {
949         with_inner!(self.inner, SymbolInternal, |x| x.name())
950     }
951 
address(&self) -> u64952     fn address(&self) -> u64 {
953         with_inner!(self.inner, SymbolInternal, |x| x.address())
954     }
955 
size(&self) -> u64956     fn size(&self) -> u64 {
957         with_inner!(self.inner, SymbolInternal, |x| x.size())
958     }
959 
kind(&self) -> SymbolKind960     fn kind(&self) -> SymbolKind {
961         with_inner!(self.inner, SymbolInternal, |x| x.kind())
962     }
963 
section(&self) -> SymbolSection964     fn section(&self) -> SymbolSection {
965         with_inner!(self.inner, SymbolInternal, |x| x.section())
966     }
967 
is_undefined(&self) -> bool968     fn is_undefined(&self) -> bool {
969         with_inner!(self.inner, SymbolInternal, |x| x.is_undefined())
970     }
971 
is_definition(&self) -> bool972     fn is_definition(&self) -> bool {
973         with_inner!(self.inner, SymbolInternal, |x| x.is_definition())
974     }
975 
is_common(&self) -> bool976     fn is_common(&self) -> bool {
977         with_inner!(self.inner, SymbolInternal, |x| x.is_common())
978     }
979 
is_weak(&self) -> bool980     fn is_weak(&self) -> bool {
981         with_inner!(self.inner, SymbolInternal, |x| x.is_weak())
982     }
983 
scope(&self) -> SymbolScope984     fn scope(&self) -> SymbolScope {
985         with_inner!(self.inner, SymbolInternal, |x| x.scope())
986     }
987 
is_global(&self) -> bool988     fn is_global(&self) -> bool {
989         with_inner!(self.inner, SymbolInternal, |x| x.is_global())
990     }
991 
is_local(&self) -> bool992     fn is_local(&self) -> bool {
993         with_inner!(self.inner, SymbolInternal, |x| x.is_local())
994     }
995 
flags(&self) -> SymbolFlags<SectionIndex>996     fn flags(&self) -> SymbolFlags<SectionIndex> {
997         with_inner!(self.inner, SymbolInternal, |x| x.flags())
998     }
999 }
1000 
1001 /// An iterator over relocation entries
1002 #[derive(Debug)]
1003 pub struct RelocationIterator<'data, 'file>
1004 where
1005     'data: 'file,
1006 {
1007     inner: RelocationIteratorInternal<'data, 'file>,
1008 }
1009 
1010 #[derive(Debug)]
1011 enum RelocationIteratorInternal<'data, 'file>
1012 where
1013     'data: 'file,
1014 {
1015     #[cfg(feature = "coff")]
1016     Coff(coff::CoffRelocationIterator<'data, 'file>),
1017     #[cfg(feature = "elf")]
1018     Elf32(elf::ElfRelocationIterator32<'data, 'file>),
1019     #[cfg(feature = "elf")]
1020     Elf64(elf::ElfRelocationIterator64<'data, 'file>),
1021     #[cfg(feature = "macho")]
1022     MachO32(macho::MachORelocationIterator32<'data, 'file>),
1023     #[cfg(feature = "macho")]
1024     MachO64(macho::MachORelocationIterator64<'data, 'file>),
1025     #[cfg(feature = "pe")]
1026     Pe32(pe::PeRelocationIterator<'data, 'file>),
1027     #[cfg(feature = "pe")]
1028     Pe64(pe::PeRelocationIterator<'data, 'file>),
1029     #[cfg(feature = "wasm")]
1030     Wasm(wasm::WasmRelocationIterator<'data, 'file>),
1031 }
1032 
1033 impl<'data, 'file> Iterator for RelocationIterator<'data, 'file> {
1034     type Item = (u64, Relocation);
1035 
next(&mut self) -> Option<Self::Item>1036     fn next(&mut self) -> Option<Self::Item> {
1037         with_inner_mut!(self.inner, RelocationIteratorInternal, |x| x.next())
1038     }
1039 }
1040