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, CompressedData, Error, FileFlags, Object, ObjectSection,
15     ObjectSegment, Relocation, Result, SectionFlags, SectionIndex, SectionKind, Symbol,
16     SymbolIndex, SymbolMap,
17 };
18 
19 /// Evaluate an expression on the contents of a file format enum.
20 ///
21 /// This is a hack to avoid virtual calls.
22 macro_rules! with_inner {
23     ($inner:expr, $enum:ident, | $var:ident | $body:expr) => {
24         match $inner {
25             #[cfg(feature = "coff")]
26             $enum::Coff(ref $var) => $body,
27             #[cfg(feature = "elf")]
28             $enum::Elf32(ref $var) => $body,
29             #[cfg(feature = "elf")]
30             $enum::Elf64(ref $var) => $body,
31             #[cfg(feature = "macho")]
32             $enum::MachO32(ref $var) => $body,
33             #[cfg(feature = "macho")]
34             $enum::MachO64(ref $var) => $body,
35             #[cfg(feature = "pe")]
36             $enum::Pe32(ref $var) => $body,
37             #[cfg(feature = "pe")]
38             $enum::Pe64(ref $var) => $body,
39             #[cfg(feature = "wasm")]
40             $enum::Wasm(ref $var) => $body,
41         }
42     };
43 }
44 
45 macro_rules! with_inner_mut {
46     ($inner:expr, $enum:ident, | $var:ident | $body:expr) => {
47         match $inner {
48             #[cfg(feature = "coff")]
49             $enum::Coff(ref mut $var) => $body,
50             #[cfg(feature = "elf")]
51             $enum::Elf32(ref mut $var) => $body,
52             #[cfg(feature = "elf")]
53             $enum::Elf64(ref mut $var) => $body,
54             #[cfg(feature = "macho")]
55             $enum::MachO32(ref mut $var) => $body,
56             #[cfg(feature = "macho")]
57             $enum::MachO64(ref mut $var) => $body,
58             #[cfg(feature = "pe")]
59             $enum::Pe32(ref mut $var) => $body,
60             #[cfg(feature = "pe")]
61             $enum::Pe64(ref mut $var) => $body,
62             #[cfg(feature = "wasm")]
63             $enum::Wasm(ref mut $var) => $body,
64         }
65     };
66 }
67 
68 /// Like `with_inner!`, but wraps the result in another enum.
69 macro_rules! map_inner {
70     ($inner:expr, $from:ident, $to:ident, | $var:ident | $body:expr) => {
71         match $inner {
72             #[cfg(feature = "coff")]
73             $from::Coff(ref $var) => $to::Coff($body),
74             #[cfg(feature = "elf")]
75             $from::Elf32(ref $var) => $to::Elf32($body),
76             #[cfg(feature = "elf")]
77             $from::Elf64(ref $var) => $to::Elf64($body),
78             #[cfg(feature = "macho")]
79             $from::MachO32(ref $var) => $to::MachO32($body),
80             #[cfg(feature = "macho")]
81             $from::MachO64(ref $var) => $to::MachO64($body),
82             #[cfg(feature = "pe")]
83             $from::Pe32(ref $var) => $to::Pe32($body),
84             #[cfg(feature = "pe")]
85             $from::Pe64(ref $var) => $to::Pe64($body),
86             #[cfg(feature = "wasm")]
87             $from::Wasm(ref $var) => $to::Wasm($body),
88         }
89     };
90 }
91 
92 /// Like `map_inner!`, but the result is a Result or Option.
93 macro_rules! map_inner_option {
94     ($inner:expr, $from:ident, $to:ident, | $var:ident | $body:expr) => {
95         match $inner {
96             #[cfg(feature = "coff")]
97             $from::Coff(ref $var) => $body.map($to::Coff),
98             #[cfg(feature = "elf")]
99             $from::Elf32(ref $var) => $body.map($to::Elf32),
100             #[cfg(feature = "elf")]
101             $from::Elf64(ref $var) => $body.map($to::Elf64),
102             #[cfg(feature = "macho")]
103             $from::MachO32(ref $var) => $body.map($to::MachO32),
104             #[cfg(feature = "macho")]
105             $from::MachO64(ref $var) => $body.map($to::MachO64),
106             #[cfg(feature = "pe")]
107             $from::Pe32(ref $var) => $body.map($to::Pe32),
108             #[cfg(feature = "pe")]
109             $from::Pe64(ref $var) => $body.map($to::Pe64),
110             #[cfg(feature = "wasm")]
111             $from::Wasm(ref $var) => $body.map($to::Wasm),
112         }
113     };
114 }
115 
116 /// Call `next` for a file format iterator.
117 macro_rules! next_inner {
118     ($inner:expr, $from:ident, $to:ident) => {
119         match $inner {
120             #[cfg(feature = "coff")]
121             $from::Coff(ref mut iter) => iter.next().map($to::Coff),
122             #[cfg(feature = "elf")]
123             $from::Elf32(ref mut iter) => iter.next().map($to::Elf32),
124             #[cfg(feature = "elf")]
125             $from::Elf64(ref mut iter) => iter.next().map($to::Elf64),
126             #[cfg(feature = "macho")]
127             $from::MachO32(ref mut iter) => iter.next().map($to::MachO32),
128             #[cfg(feature = "macho")]
129             $from::MachO64(ref mut iter) => iter.next().map($to::MachO64),
130             #[cfg(feature = "pe")]
131             $from::Pe32(ref mut iter) => iter.next().map($to::Pe32),
132             #[cfg(feature = "pe")]
133             $from::Pe64(ref mut iter) => iter.next().map($to::Pe64),
134             #[cfg(feature = "wasm")]
135             $from::Wasm(ref mut iter) => iter.next().map($to::Wasm),
136         }
137     };
138 }
139 
140 /// An object file.
141 ///
142 /// Most functionality is provided by the `Object` trait implementation.
143 #[derive(Debug)]
144 pub struct File<'data> {
145     inner: FileInternal<'data>,
146 }
147 
148 #[allow(clippy::large_enum_variant)]
149 #[derive(Debug)]
150 enum FileInternal<'data> {
151     #[cfg(feature = "coff")]
152     Coff(coff::CoffFile<'data>),
153     #[cfg(feature = "elf")]
154     Elf32(elf::ElfFile32<'data>),
155     #[cfg(feature = "elf")]
156     Elf64(elf::ElfFile64<'data>),
157     #[cfg(feature = "macho")]
158     MachO32(macho::MachOFile32<'data>),
159     #[cfg(feature = "macho")]
160     MachO64(macho::MachOFile64<'data>),
161     #[cfg(feature = "pe")]
162     Pe32(pe::PeFile32<'data>),
163     #[cfg(feature = "pe")]
164     Pe64(pe::PeFile64<'data>),
165     #[cfg(feature = "wasm")]
166     Wasm(wasm::WasmFile<'data>),
167 }
168 
169 impl<'data> File<'data> {
170     /// Parse the raw file data.
parse(data: &'data [u8]) -> Result<Self>171     pub fn parse(data: &'data [u8]) -> Result<Self> {
172         if data.len() < 16 {
173             return Err(Error("File too short"));
174         }
175 
176         let inner = match [data[0], data[1], data[2], data[3], data[4]] {
177             // 32-bit ELF
178             #[cfg(feature = "elf")]
179             [0x7f, b'E', b'L', b'F', 1] => FileInternal::Elf32(elf::ElfFile32::parse(data)?),
180             // 64-bit ELF
181             #[cfg(feature = "elf")]
182             [0x7f, b'E', b'L', b'F', 2] => FileInternal::Elf64(elf::ElfFile64::parse(data)?),
183             // 32-bit Mach-O
184             #[cfg(feature = "macho")]
185             [0xfe, 0xed, 0xfa, 0xce, _]
186             | [0xce, 0xfa, 0xed, 0xfe, _] => FileInternal::MachO32(macho::MachOFile32::parse(data)?),
187             // 64-bit Mach-O
188             #[cfg(feature = "macho")]
189             | [0xfe, 0xed, 0xfa, 0xcf, _]
190             | [0xcf, 0xfa, 0xed, 0xfe, _] => FileInternal::MachO64(macho::MachOFile64::parse(data)?),
191             // WASM
192             #[cfg(feature = "wasm")]
193             [0x00, b'a', b's', b'm', _] => FileInternal::Wasm(wasm::WasmFile::parse(data)?),
194             // MS-DOS, assume stub for Windows PE32 or PE32+
195             #[cfg(feature = "pe")]
196             [b'M', b'Z', _, _, _] => {
197                 // `optional_header_magic` doesn't care if it's `PeFile32` and `PeFile64`.
198                 match pe::PeFile64::optional_header_magic(data) {
199                     Ok(crate::pe::IMAGE_NT_OPTIONAL_HDR32_MAGIC) => {
200                         FileInternal::Pe32(pe::PeFile32::parse(data)?)
201                     }
202                     Ok(crate::pe::IMAGE_NT_OPTIONAL_HDR64_MAGIC) => {
203                         FileInternal::Pe64(pe::PeFile64::parse(data)?)
204                     }
205                     _ => return Err(Error("Unknown MS-DOS file")),
206                 }
207             }
208             // TODO: more COFF machines
209             #[cfg(feature = "coff")]
210             // COFF x86
211             [0x4c, 0x01, _, _, _]
212             // COFF x86-64
213             | [0x64, 0x86, _, _, _] => FileInternal::Coff(coff::CoffFile::parse(data)?),
214             _ => return Err(Error("Unknown file magic")),
215         };
216         Ok(File { inner })
217     }
218 
219     /// Return the file format.
format(&self) -> BinaryFormat220     pub fn format(&self) -> BinaryFormat {
221         match self.inner {
222             #[cfg(feature = "coff")]
223             FileInternal::Coff(_) => BinaryFormat::Coff,
224             #[cfg(feature = "elf")]
225             FileInternal::Elf32(_) | FileInternal::Elf64(_) => BinaryFormat::Elf,
226             #[cfg(feature = "macho")]
227             FileInternal::MachO32(_) | FileInternal::MachO64(_) => BinaryFormat::MachO,
228             #[cfg(feature = "pe")]
229             FileInternal::Pe32(_) | FileInternal::Pe64(_) => BinaryFormat::Pe,
230             #[cfg(feature = "wasm")]
231             FileInternal::Wasm(_) => BinaryFormat::Wasm,
232         }
233     }
234 }
235 
236 impl<'data> read::private::Sealed for File<'data> {}
237 
238 impl<'data, 'file> Object<'data, 'file> for File<'data>
239 where
240     'data: 'file,
241 {
242     type Segment = Segment<'data, 'file>;
243     type SegmentIterator = SegmentIterator<'data, 'file>;
244     type Section = Section<'data, 'file>;
245     type SectionIterator = SectionIterator<'data, 'file>;
246     type SymbolIterator = SymbolIterator<'data, 'file>;
247 
architecture(&self) -> Architecture248     fn architecture(&self) -> Architecture {
249         with_inner!(self.inner, FileInternal, |x| x.architecture())
250     }
251 
is_little_endian(&self) -> bool252     fn is_little_endian(&self) -> bool {
253         with_inner!(self.inner, FileInternal, |x| x.is_little_endian())
254     }
255 
is_64(&self) -> bool256     fn is_64(&self) -> bool {
257         with_inner!(self.inner, FileInternal, |x| x.is_64())
258     }
259 
segments(&'file self) -> SegmentIterator<'data, 'file>260     fn segments(&'file self) -> SegmentIterator<'data, 'file> {
261         SegmentIterator {
262             inner: map_inner!(self.inner, FileInternal, SegmentIteratorInternal, |x| x
263                 .segments()),
264         }
265     }
266 
section_by_name(&'file self, section_name: &str) -> Option<Section<'data, 'file>>267     fn section_by_name(&'file self, section_name: &str) -> Option<Section<'data, 'file>> {
268         map_inner_option!(self.inner, FileInternal, SectionInternal, |x| x
269             .section_by_name(section_name))
270         .map(|inner| Section { inner })
271     }
272 
section_by_index(&'file self, index: SectionIndex) -> Result<Section<'data, 'file>>273     fn section_by_index(&'file self, index: SectionIndex) -> Result<Section<'data, 'file>> {
274         map_inner_option!(self.inner, FileInternal, SectionInternal, |x| x
275             .section_by_index(index))
276         .map(|inner| Section { inner })
277     }
278 
sections(&'file self) -> SectionIterator<'data, 'file>279     fn sections(&'file self) -> SectionIterator<'data, 'file> {
280         SectionIterator {
281             inner: map_inner!(self.inner, FileInternal, SectionIteratorInternal, |x| x
282                 .sections()),
283         }
284     }
285 
symbol_by_index(&self, index: SymbolIndex) -> Result<Symbol<'data>>286     fn symbol_by_index(&self, index: SymbolIndex) -> Result<Symbol<'data>> {
287         with_inner!(self.inner, FileInternal, |x| x.symbol_by_index(index))
288     }
289 
symbols(&'file self) -> SymbolIterator<'data, 'file>290     fn symbols(&'file self) -> SymbolIterator<'data, 'file> {
291         SymbolIterator {
292             inner: map_inner!(self.inner, FileInternal, SymbolIteratorInternal, |x| x
293                 .symbols()),
294         }
295     }
296 
dynamic_symbols(&'file self) -> SymbolIterator<'data, 'file>297     fn dynamic_symbols(&'file self) -> SymbolIterator<'data, 'file> {
298         SymbolIterator {
299             inner: map_inner!(self.inner, FileInternal, SymbolIteratorInternal, |x| x
300                 .dynamic_symbols()),
301         }
302     }
303 
symbol_map(&self) -> SymbolMap<'data>304     fn symbol_map(&self) -> SymbolMap<'data> {
305         with_inner!(self.inner, FileInternal, |x| x.symbol_map())
306     }
307 
has_debug_symbols(&self) -> bool308     fn has_debug_symbols(&self) -> bool {
309         with_inner!(self.inner, FileInternal, |x| x.has_debug_symbols())
310     }
311 
312     #[inline]
mach_uuid(&self) -> Result<Option<[u8; 16]>>313     fn mach_uuid(&self) -> Result<Option<[u8; 16]>> {
314         with_inner!(self.inner, FileInternal, |x| x.mach_uuid())
315     }
316 
317     #[inline]
build_id(&self) -> Result<Option<&'data [u8]>>318     fn build_id(&self) -> Result<Option<&'data [u8]>> {
319         with_inner!(self.inner, FileInternal, |x| x.build_id())
320     }
321 
322     #[inline]
gnu_debuglink(&self) -> Result<Option<(&'data [u8], u32)>>323     fn gnu_debuglink(&self) -> Result<Option<(&'data [u8], u32)>> {
324         with_inner!(self.inner, FileInternal, |x| x.gnu_debuglink())
325     }
326 
entry(&self) -> u64327     fn entry(&self) -> u64 {
328         with_inner!(self.inner, FileInternal, |x| x.entry())
329     }
330 
flags(&self) -> FileFlags331     fn flags(&self) -> FileFlags {
332         with_inner!(self.inner, FileInternal, |x| x.flags())
333     }
334 }
335 
336 /// An iterator over the segments of a `File`.
337 #[derive(Debug)]
338 pub struct SegmentIterator<'data, 'file>
339 where
340     'data: 'file,
341 {
342     inner: SegmentIteratorInternal<'data, 'file>,
343 }
344 
345 #[derive(Debug)]
346 enum SegmentIteratorInternal<'data, 'file>
347 where
348     'data: 'file,
349 {
350     #[cfg(feature = "coff")]
351     Coff(coff::CoffSegmentIterator<'data, 'file>),
352     #[cfg(feature = "elf")]
353     Elf32(elf::ElfSegmentIterator32<'data, 'file>),
354     #[cfg(feature = "elf")]
355     Elf64(elf::ElfSegmentIterator64<'data, 'file>),
356     #[cfg(feature = "macho")]
357     MachO32(macho::MachOSegmentIterator32<'data, 'file>),
358     #[cfg(feature = "macho")]
359     MachO64(macho::MachOSegmentIterator64<'data, 'file>),
360     #[cfg(feature = "pe")]
361     Pe32(pe::PeSegmentIterator32<'data, 'file>),
362     #[cfg(feature = "pe")]
363     Pe64(pe::PeSegmentIterator64<'data, 'file>),
364     #[cfg(feature = "wasm")]
365     Wasm(wasm::WasmSegmentIterator<'data, 'file>),
366 }
367 
368 impl<'data, 'file> Iterator for SegmentIterator<'data, 'file> {
369     type Item = Segment<'data, 'file>;
370 
next(&mut self) -> Option<Self::Item>371     fn next(&mut self) -> Option<Self::Item> {
372         next_inner!(self.inner, SegmentIteratorInternal, SegmentInternal)
373             .map(|inner| Segment { inner })
374     }
375 }
376 
377 /// A segment of a `File`.
378 pub struct Segment<'data, 'file>
379 where
380     'data: 'file,
381 {
382     inner: SegmentInternal<'data, 'file>,
383 }
384 
385 #[derive(Debug)]
386 enum SegmentInternal<'data, 'file>
387 where
388     'data: 'file,
389 {
390     #[cfg(feature = "coff")]
391     Coff(coff::CoffSegment<'data, 'file>),
392     #[cfg(feature = "elf")]
393     Elf32(elf::ElfSegment32<'data, 'file>),
394     #[cfg(feature = "elf")]
395     Elf64(elf::ElfSegment64<'data, 'file>),
396     #[cfg(feature = "macho")]
397     MachO32(macho::MachOSegment32<'data, 'file>),
398     #[cfg(feature = "macho")]
399     MachO64(macho::MachOSegment64<'data, 'file>),
400     #[cfg(feature = "pe")]
401     Pe32(pe::PeSegment32<'data, 'file>),
402     #[cfg(feature = "pe")]
403     Pe64(pe::PeSegment64<'data, 'file>),
404     #[cfg(feature = "wasm")]
405     Wasm(wasm::WasmSegment<'data, 'file>),
406 }
407 
408 impl<'data, 'file> fmt::Debug for Segment<'data, 'file> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result409     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
410         // It's painful to do much better than this
411         let mut s = f.debug_struct("Segment");
412         match self.name() {
413             Ok(Some(ref name)) => {
414                 s.field("name", name);
415             }
416             Ok(None) => {}
417             Err(_) => {
418                 s.field("name", &"<invalid>");
419             }
420         }
421         s.field("address", &self.address())
422             .field("size", &self.size())
423             .finish()
424     }
425 }
426 
427 impl<'data, 'file> read::private::Sealed for Segment<'data, 'file> {}
428 
429 impl<'data, 'file> ObjectSegment<'data> for Segment<'data, 'file> {
address(&self) -> u64430     fn address(&self) -> u64 {
431         with_inner!(self.inner, SegmentInternal, |x| x.address())
432     }
433 
size(&self) -> u64434     fn size(&self) -> u64 {
435         with_inner!(self.inner, SegmentInternal, |x| x.size())
436     }
437 
align(&self) -> u64438     fn align(&self) -> u64 {
439         with_inner!(self.inner, SegmentInternal, |x| x.align())
440     }
441 
file_range(&self) -> (u64, u64)442     fn file_range(&self) -> (u64, u64) {
443         with_inner!(self.inner, SegmentInternal, |x| x.file_range())
444     }
445 
data(&self) -> Result<&'data [u8]>446     fn data(&self) -> Result<&'data [u8]> {
447         with_inner!(self.inner, SegmentInternal, |x| x.data())
448     }
449 
data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>>450     fn data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>> {
451         with_inner!(self.inner, SegmentInternal, |x| x.data_range(address, size))
452     }
453 
name(&self) -> Result<Option<&str>>454     fn name(&self) -> Result<Option<&str>> {
455         with_inner!(self.inner, SegmentInternal, |x| x.name())
456     }
457 }
458 
459 /// An iterator of the sections of a `File`.
460 #[derive(Debug)]
461 pub struct SectionIterator<'data, 'file>
462 where
463     'data: 'file,
464 {
465     inner: SectionIteratorInternal<'data, 'file>,
466 }
467 
468 // we wrap our enums in a struct so that they are kept private.
469 #[derive(Debug)]
470 enum SectionIteratorInternal<'data, 'file>
471 where
472     'data: 'file,
473 {
474     #[cfg(feature = "coff")]
475     Coff(coff::CoffSectionIterator<'data, 'file>),
476     #[cfg(feature = "elf")]
477     Elf32(elf::ElfSectionIterator32<'data, 'file>),
478     #[cfg(feature = "elf")]
479     Elf64(elf::ElfSectionIterator64<'data, 'file>),
480     #[cfg(feature = "macho")]
481     MachO32(macho::MachOSectionIterator32<'data, 'file>),
482     #[cfg(feature = "macho")]
483     MachO64(macho::MachOSectionIterator64<'data, 'file>),
484     #[cfg(feature = "pe")]
485     Pe32(pe::PeSectionIterator32<'data, 'file>),
486     #[cfg(feature = "pe")]
487     Pe64(pe::PeSectionIterator64<'data, 'file>),
488     #[cfg(feature = "wasm")]
489     Wasm(wasm::WasmSectionIterator<'data, 'file>),
490 }
491 
492 impl<'data, 'file> Iterator for SectionIterator<'data, 'file> {
493     type Item = Section<'data, 'file>;
494 
next(&mut self) -> Option<Self::Item>495     fn next(&mut self) -> Option<Self::Item> {
496         next_inner!(self.inner, SectionIteratorInternal, SectionInternal)
497             .map(|inner| Section { inner })
498     }
499 }
500 
501 /// A Section of a File
502 pub struct Section<'data, 'file>
503 where
504     'data: 'file,
505 {
506     inner: SectionInternal<'data, 'file>,
507 }
508 
509 enum SectionInternal<'data, 'file>
510 where
511     'data: 'file,
512 {
513     #[cfg(feature = "coff")]
514     Coff(coff::CoffSection<'data, 'file>),
515     #[cfg(feature = "elf")]
516     Elf32(elf::ElfSection32<'data, 'file>),
517     #[cfg(feature = "elf")]
518     Elf64(elf::ElfSection64<'data, 'file>),
519     #[cfg(feature = "macho")]
520     MachO32(macho::MachOSection32<'data, 'file>),
521     #[cfg(feature = "macho")]
522     MachO64(macho::MachOSection64<'data, 'file>),
523     #[cfg(feature = "pe")]
524     Pe32(pe::PeSection32<'data, 'file>),
525     #[cfg(feature = "pe")]
526     Pe64(pe::PeSection64<'data, 'file>),
527     #[cfg(feature = "wasm")]
528     Wasm(wasm::WasmSection<'data, 'file>),
529 }
530 
531 impl<'data, 'file> fmt::Debug for Section<'data, 'file> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result532     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
533         // It's painful to do much better than this
534         let mut s = f.debug_struct("Section");
535         match self.segment_name() {
536             Ok(Some(ref name)) => {
537                 s.field("segment", name);
538             }
539             Ok(None) => {}
540             Err(_) => {
541                 s.field("segment", &"<invalid>");
542             }
543         }
544         s.field("name", &self.name().unwrap_or("<invalid>"))
545             .field("address", &self.address())
546             .field("size", &self.size())
547             .field("kind", &self.kind())
548             .finish()
549     }
550 }
551 
552 impl<'data, 'file> read::private::Sealed for Section<'data, 'file> {}
553 
554 impl<'data, 'file> ObjectSection<'data> for Section<'data, 'file> {
555     type RelocationIterator = RelocationIterator<'data, 'file>;
556 
index(&self) -> SectionIndex557     fn index(&self) -> SectionIndex {
558         with_inner!(self.inner, SectionInternal, |x| x.index())
559     }
560 
address(&self) -> u64561     fn address(&self) -> u64 {
562         with_inner!(self.inner, SectionInternal, |x| x.address())
563     }
564 
size(&self) -> u64565     fn size(&self) -> u64 {
566         with_inner!(self.inner, SectionInternal, |x| x.size())
567     }
568 
align(&self) -> u64569     fn align(&self) -> u64 {
570         with_inner!(self.inner, SectionInternal, |x| x.align())
571     }
572 
file_range(&self) -> Option<(u64, u64)>573     fn file_range(&self) -> Option<(u64, u64)> {
574         with_inner!(self.inner, SectionInternal, |x| x.file_range())
575     }
576 
data(&self) -> Result<&'data [u8]>577     fn data(&self) -> Result<&'data [u8]> {
578         with_inner!(self.inner, SectionInternal, |x| x.data())
579     }
580 
data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>>581     fn data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>> {
582         with_inner!(self.inner, SectionInternal, |x| x.data_range(address, size))
583     }
584 
compressed_data(&self) -> Result<CompressedData<'data>>585     fn compressed_data(&self) -> Result<CompressedData<'data>> {
586         with_inner!(self.inner, SectionInternal, |x| x.compressed_data())
587     }
588 
name(&self) -> Result<&str>589     fn name(&self) -> Result<&str> {
590         with_inner!(self.inner, SectionInternal, |x| x.name())
591     }
592 
segment_name(&self) -> Result<Option<&str>>593     fn segment_name(&self) -> Result<Option<&str>> {
594         with_inner!(self.inner, SectionInternal, |x| x.segment_name())
595     }
596 
kind(&self) -> SectionKind597     fn kind(&self) -> SectionKind {
598         with_inner!(self.inner, SectionInternal, |x| x.kind())
599     }
600 
relocations(&self) -> RelocationIterator<'data, 'file>601     fn relocations(&self) -> RelocationIterator<'data, 'file> {
602         RelocationIterator {
603             inner: map_inner!(
604                 self.inner,
605                 SectionInternal,
606                 RelocationIteratorInternal,
607                 |x| x.relocations()
608             ),
609         }
610     }
611 
flags(&self) -> SectionFlags612     fn flags(&self) -> SectionFlags {
613         with_inner!(self.inner, SectionInternal, |x| x.flags())
614     }
615 }
616 
617 /// An iterator over symbol table entries.
618 #[derive(Debug)]
619 pub struct SymbolIterator<'data, 'file>
620 where
621     'data: 'file,
622 {
623     inner: SymbolIteratorInternal<'data, 'file>,
624 }
625 
626 #[derive(Debug)]
627 enum SymbolIteratorInternal<'data, 'file>
628 where
629     'data: 'file,
630 {
631     #[cfg(feature = "coff")]
632     Coff(coff::CoffSymbolIterator<'data, 'file>),
633     #[cfg(feature = "elf")]
634     Elf32(elf::ElfSymbolIterator32<'data, 'file>),
635     #[cfg(feature = "elf")]
636     Elf64(elf::ElfSymbolIterator64<'data, 'file>),
637     #[cfg(feature = "macho")]
638     MachO32(macho::MachOSymbolIterator32<'data, 'file>),
639     #[cfg(feature = "macho")]
640     MachO64(macho::MachOSymbolIterator64<'data, 'file>),
641     #[cfg(feature = "pe")]
642     Pe32(coff::CoffSymbolIterator<'data, 'file>),
643     #[cfg(feature = "pe")]
644     Pe64(coff::CoffSymbolIterator<'data, 'file>),
645     #[cfg(feature = "wasm")]
646     Wasm(wasm::WasmSymbolIterator<'data, 'file>),
647 }
648 
649 impl<'data, 'file> Iterator for SymbolIterator<'data, 'file> {
650     type Item = (SymbolIndex, Symbol<'data>);
651 
next(&mut self) -> Option<Self::Item>652     fn next(&mut self) -> Option<Self::Item> {
653         with_inner_mut!(self.inner, SymbolIteratorInternal, |x| x.next())
654     }
655 }
656 
657 /// An iterator over relocation entries
658 #[derive(Debug)]
659 pub struct RelocationIterator<'data, 'file>
660 where
661     'data: 'file,
662 {
663     inner: RelocationIteratorInternal<'data, 'file>,
664 }
665 
666 #[derive(Debug)]
667 enum RelocationIteratorInternal<'data, 'file>
668 where
669     'data: 'file,
670 {
671     #[cfg(feature = "coff")]
672     Coff(coff::CoffRelocationIterator<'data, 'file>),
673     #[cfg(feature = "elf")]
674     Elf32(elf::ElfRelocationIterator32<'data, 'file>),
675     #[cfg(feature = "elf")]
676     Elf64(elf::ElfRelocationIterator64<'data, 'file>),
677     #[cfg(feature = "macho")]
678     MachO32(macho::MachORelocationIterator32<'data, 'file>),
679     #[cfg(feature = "macho")]
680     MachO64(macho::MachORelocationIterator64<'data, 'file>),
681     #[cfg(feature = "pe")]
682     Pe32(pe::PeRelocationIterator<'data, 'file>),
683     #[cfg(feature = "pe")]
684     Pe64(pe::PeRelocationIterator<'data, 'file>),
685     #[cfg(feature = "wasm")]
686     Wasm(wasm::WasmRelocationIterator<'data, 'file>),
687 }
688 
689 impl<'data, 'file> Iterator for RelocationIterator<'data, 'file> {
690     type Item = (u64, Relocation);
691 
next(&mut self) -> Option<Self::Item>692     fn next(&mut self) -> Option<Self::Item> {
693         with_inner_mut!(self.inner, RelocationIteratorInternal, |x| x.next())
694     }
695 }
696