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