Skip to main content

object/read/
any.rs

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