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