Coverage Report

Created: 2025-10-29 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/object-0.36.7/src/read/any.rs
Line
Count
Source
1
use alloc::fmt;
2
use alloc::vec::Vec;
3
use core::marker::PhantomData;
4
5
#[allow(unused_imports)] // Unused for Wasm
6
use crate::endian::Endianness;
7
#[cfg(feature = "coff")]
8
use crate::read::coff;
9
#[cfg(feature = "elf")]
10
use crate::read::elf;
11
#[cfg(feature = "macho")]
12
use crate::read::macho;
13
#[cfg(feature = "pe")]
14
use crate::read::pe;
15
#[cfg(feature = "wasm")]
16
use crate::read::wasm;
17
#[cfg(feature = "xcoff")]
18
use crate::read::xcoff;
19
use 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.
30
macro_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
59
macro_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.
89
macro_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.
119
macro_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
148
macro_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.
178
macro_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)]
213
pub 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
238
impl<'data, R: ReadRef<'data>> File<'data, R> {
239
    /// Parse the raw file data.
240
0
    pub fn parse(data: R) -> Result<Self> {
241
0
        Ok(match FileKind::parse(data)? {
242
            #[cfg(feature = "elf")]
243
0
            FileKind::Elf32 => File::Elf32(elf::ElfFile32::parse(data)?),
244
            #[cfg(feature = "elf")]
245
0
            FileKind::Elf64 => File::Elf64(elf::ElfFile64::parse(data)?),
246
            #[cfg(feature = "macho")]
247
0
            FileKind::MachO32 => File::MachO32(macho::MachOFile32::parse(data)?),
248
            #[cfg(feature = "macho")]
249
0
            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
0
            FileKind::Pe32 => File::Pe32(pe::PeFile32::parse(data)?),
254
            #[cfg(feature = "pe")]
255
0
            FileKind::Pe64 => File::Pe64(pe::PeFile64::parse(data)?),
256
            #[cfg(feature = "coff")]
257
0
            FileKind::Coff => File::Coff(coff::CoffFile::parse(data)?),
258
            #[cfg(feature = "coff")]
259
0
            FileKind::CoffBig => File::CoffBig(coff::CoffBigFile::parse(data)?),
260
            #[cfg(feature = "xcoff")]
261
0
            FileKind::Xcoff32 => File::Xcoff32(xcoff::XcoffFile32::parse(data)?),
262
            #[cfg(feature = "xcoff")]
263
0
            FileKind::Xcoff64 => File::Xcoff64(xcoff::XcoffFile64::parse(data)?),
264
            #[allow(unreachable_patterns)]
265
0
            _ => return Err(Error("Unsupported file format")),
266
        })
267
0
    }
268
269
    /// Parse a Mach-O image from the dyld shared cache.
270
    #[cfg(feature = "macho")]
271
0
    pub fn parse_dyld_cache_image<'cache, E: crate::Endian>(
272
0
        image: &macho::DyldCacheImage<'data, 'cache, E, R>,
273
0
    ) -> Result<Self> {
274
0
        Ok(match image.cache.architecture().address_size() {
275
            Some(read::AddressSize::U64) => {
276
0
                File::MachO64(macho::MachOFile64::parse_dyld_cache_image(image)?)
277
            }
278
            Some(read::AddressSize::U32) => {
279
0
                File::MachO32(macho::MachOFile32::parse_dyld_cache_image(image)?)
280
            }
281
0
            _ => return Err(Error("Unsupported file format")),
282
        })
283
0
    }
284
285
    /// Return the file format.
286
0
    pub fn format(&self) -> BinaryFormat {
287
0
        match self {
288
            #[cfg(feature = "coff")]
289
0
            File::Coff(_) | File::CoffBig(_) => BinaryFormat::Coff,
290
            #[cfg(feature = "elf")]
291
0
            File::Elf32(_) | File::Elf64(_) => BinaryFormat::Elf,
292
            #[cfg(feature = "macho")]
293
0
            File::MachO32(_) | File::MachO64(_) => BinaryFormat::MachO,
294
            #[cfg(feature = "pe")]
295
0
            File::Pe32(_) | File::Pe64(_) => BinaryFormat::Pe,
296
            #[cfg(feature = "wasm")]
297
            File::Wasm(_) => BinaryFormat::Wasm,
298
            #[cfg(feature = "xcoff")]
299
0
            File::Xcoff32(_) | File::Xcoff64(_) => BinaryFormat::Xcoff,
300
        }
301
0
    }
302
}
303
304
impl<'data, R: ReadRef<'data>> read::private::Sealed for File<'data, R> {}
305
306
impl<'data, R> Object<'data> for File<'data, R>
307
where
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
0
    fn architecture(&self) -> Architecture {
362
0
        with_inner!(self, File, |x| x.architecture())
363
0
    }
364
365
0
    fn sub_architecture(&self) -> Option<SubArchitecture> {
366
0
        with_inner!(self, File, |x| x.sub_architecture())
367
0
    }
368
369
0
    fn is_little_endian(&self) -> bool {
370
0
        with_inner!(self, File, |x| x.is_little_endian())
371
0
    }
372
373
0
    fn is_64(&self) -> bool {
374
0
        with_inner!(self, File, |x| x.is_64())
375
0
    }
376
377
0
    fn kind(&self) -> ObjectKind {
378
0
        with_inner!(self, File, |x| x.kind())
379
0
    }
380
381
0
    fn segments(&self) -> SegmentIterator<'data, '_, R> {
382
        SegmentIterator {
383
0
            inner: map_inner!(self, File, SegmentIteratorInternal, |x| x.segments()),
384
        }
385
0
    }
386
387
0
    fn section_by_name_bytes<'file>(
388
0
        &'file self,
389
0
        section_name: &[u8],
390
0
    ) -> Option<Section<'data, 'file, R>> {
391
0
        map_inner_option!(self, File, SectionInternal, |x| x
392
0
            .section_by_name_bytes(section_name))
393
0
        .map(|inner| Section { inner })
394
0
    }
395
396
0
    fn section_by_index(&self, index: SectionIndex) -> Result<Section<'data, '_, R>> {
397
0
        map_inner_option!(self, File, SectionInternal, |x| x.section_by_index(index))
398
0
            .map(|inner| Section { inner })
399
0
    }
400
401
0
    fn sections(&self) -> SectionIterator<'data, '_, R> {
402
        SectionIterator {
403
0
            inner: map_inner!(self, File, SectionIteratorInternal, |x| x.sections()),
404
        }
405
0
    }
406
407
0
    fn comdats(&self) -> ComdatIterator<'data, '_, R> {
408
        ComdatIterator {
409
0
            inner: map_inner!(self, File, ComdatIteratorInternal, |x| x.comdats()),
410
        }
411
0
    }
412
413
0
    fn symbol_by_index(&self, index: SymbolIndex) -> Result<Symbol<'data, '_, R>> {
414
0
        map_inner_option!(self, File, SymbolInternal, |x| x
415
0
            .symbol_by_index(index)
416
0
            .map(|x| (x, PhantomData)))
Unexecuted instantiation: <object::read::any::File<_> as object::read::traits::Object>::symbol_by_index::{closure#2}
Unexecuted instantiation: <object::read::any::File<_> as object::read::traits::Object>::symbol_by_index::{closure#3}
Unexecuted instantiation: <object::read::any::File<_> as object::read::traits::Object>::symbol_by_index::{closure#4}
Unexecuted instantiation: <object::read::any::File<_> as object::read::traits::Object>::symbol_by_index::{closure#5}
Unexecuted instantiation: <object::read::any::File<_> as object::read::traits::Object>::symbol_by_index::{closure#6}
Unexecuted instantiation: <object::read::any::File<_> as object::read::traits::Object>::symbol_by_index::{closure#7}
Unexecuted instantiation: <object::read::any::File<_> as object::read::traits::Object>::symbol_by_index::{closure#8}
Unexecuted instantiation: <object::read::any::File<_> as object::read::traits::Object>::symbol_by_index::{closure#9}
Unexecuted instantiation: <object::read::any::File<_> as object::read::traits::Object>::symbol_by_index::{closure#10}
Unexecuted instantiation: <object::read::any::File<_> as object::read::traits::Object>::symbol_by_index::{closure#1}
417
0
        .map(|inner| Symbol { inner })
418
0
    }
419
420
0
    fn symbols(&self) -> SymbolIterator<'data, '_, R> {
421
        SymbolIterator {
422
0
            inner: map_inner!(self, File, SymbolIteratorInternal, |x| (
423
0
                x.symbols(),
424
0
                PhantomData
425
0
            )),
426
        }
427
0
    }
428
429
0
    fn symbol_table(&self) -> Option<SymbolTable<'data, '_, R>> {
430
0
        map_inner_option!(self, File, SymbolTableInternal, |x| x
431
0
            .symbol_table()
432
0
            .map(|x| (x, PhantomData)))
Unexecuted instantiation: <object::read::any::File<_> as object::read::traits::Object>::symbol_table::{closure#2}
Unexecuted instantiation: <object::read::any::File<_> as object::read::traits::Object>::symbol_table::{closure#3}
Unexecuted instantiation: <object::read::any::File<_> as object::read::traits::Object>::symbol_table::{closure#4}
Unexecuted instantiation: <object::read::any::File<_> as object::read::traits::Object>::symbol_table::{closure#5}
Unexecuted instantiation: <object::read::any::File<_> as object::read::traits::Object>::symbol_table::{closure#6}
Unexecuted instantiation: <object::read::any::File<_> as object::read::traits::Object>::symbol_table::{closure#7}
Unexecuted instantiation: <object::read::any::File<_> as object::read::traits::Object>::symbol_table::{closure#8}
Unexecuted instantiation: <object::read::any::File<_> as object::read::traits::Object>::symbol_table::{closure#9}
Unexecuted instantiation: <object::read::any::File<_> as object::read::traits::Object>::symbol_table::{closure#10}
Unexecuted instantiation: <object::read::any::File<_> as object::read::traits::Object>::symbol_table::{closure#1}
433
0
        .map(|inner| SymbolTable { inner })
434
0
    }
435
436
0
    fn dynamic_symbols(&self) -> SymbolIterator<'data, '_, R> {
437
        SymbolIterator {
438
0
            inner: map_inner!(self, File, SymbolIteratorInternal, |x| (
439
0
                x.dynamic_symbols(),
440
0
                PhantomData
441
0
            )),
442
        }
443
0
    }
444
445
0
    fn dynamic_symbol_table(&self) -> Option<SymbolTable<'data, '_, R>> {
446
0
        map_inner_option!(self, File, SymbolTableInternal, |x| x
447
0
            .dynamic_symbol_table()
448
0
            .map(|x| (x, PhantomData)))
Unexecuted instantiation: <object::read::any::File<_> as object::read::traits::Object>::dynamic_symbol_table::{closure#2}
Unexecuted instantiation: <object::read::any::File<_> as object::read::traits::Object>::dynamic_symbol_table::{closure#3}
Unexecuted instantiation: <object::read::any::File<_> as object::read::traits::Object>::dynamic_symbol_table::{closure#4}
Unexecuted instantiation: <object::read::any::File<_> as object::read::traits::Object>::dynamic_symbol_table::{closure#5}
Unexecuted instantiation: <object::read::any::File<_> as object::read::traits::Object>::dynamic_symbol_table::{closure#6}
Unexecuted instantiation: <object::read::any::File<_> as object::read::traits::Object>::dynamic_symbol_table::{closure#7}
Unexecuted instantiation: <object::read::any::File<_> as object::read::traits::Object>::dynamic_symbol_table::{closure#8}
Unexecuted instantiation: <object::read::any::File<_> as object::read::traits::Object>::dynamic_symbol_table::{closure#9}
Unexecuted instantiation: <object::read::any::File<_> as object::read::traits::Object>::dynamic_symbol_table::{closure#10}
Unexecuted instantiation: <object::read::any::File<_> as object::read::traits::Object>::dynamic_symbol_table::{closure#1}
449
0
        .map(|inner| SymbolTable { inner })
450
0
    }
451
452
    #[cfg(feature = "elf")]
453
0
    fn dynamic_relocations(&self) -> Option<DynamicRelocationIterator<'data, '_, R>> {
454
0
        let inner = match self {
455
0
            File::Elf32(ref elf) => {
456
0
                DynamicRelocationIteratorInternal::Elf32(elf.dynamic_relocations()?)
457
            }
458
0
            File::Elf64(ref elf) => {
459
0
                DynamicRelocationIteratorInternal::Elf64(elf.dynamic_relocations()?)
460
            }
461
            #[allow(unreachable_patterns)]
462
0
            _ => return None,
463
        };
464
0
        Some(DynamicRelocationIterator { inner })
465
0
    }
466
467
    #[cfg(not(feature = "elf"))]
468
    fn dynamic_relocations(&self) -> Option<DynamicRelocationIterator<'data, '_, R>> {
469
        None
470
    }
471
472
0
    fn symbol_map(&self) -> SymbolMap<SymbolMapName<'data>> {
473
0
        with_inner!(self, File, |x| x.symbol_map())
474
0
    }
475
476
0
    fn object_map(&self) -> ObjectMap<'data> {
477
0
        with_inner!(self, File, |x| x.object_map())
478
0
    }
479
480
0
    fn imports(&self) -> Result<Vec<Import<'data>>> {
481
0
        with_inner!(self, File, |x| x.imports())
482
0
    }
483
484
0
    fn exports(&self) -> Result<Vec<Export<'data>>> {
485
0
        with_inner!(self, File, |x| x.exports())
486
0
    }
487
488
0
    fn has_debug_symbols(&self) -> bool {
489
0
        with_inner!(self, File, |x| x.has_debug_symbols())
490
0
    }
491
492
    #[inline]
493
0
    fn mach_uuid(&self) -> Result<Option<[u8; 16]>> {
494
0
        with_inner!(self, File, |x| x.mach_uuid())
495
0
    }
496
497
    #[inline]
498
0
    fn build_id(&self) -> Result<Option<&'data [u8]>> {
499
0
        with_inner!(self, File, |x| x.build_id())
500
0
    }
501
502
    #[inline]
503
0
    fn gnu_debuglink(&self) -> Result<Option<(&'data [u8], u32)>> {
504
0
        with_inner!(self, File, |x| x.gnu_debuglink())
505
0
    }
506
507
    #[inline]
508
0
    fn gnu_debugaltlink(&self) -> Result<Option<(&'data [u8], &'data [u8])>> {
509
0
        with_inner!(self, File, |x| x.gnu_debugaltlink())
510
0
    }
511
512
    #[inline]
513
0
    fn pdb_info(&self) -> Result<Option<CodeView<'_>>> {
514
0
        with_inner!(self, File, |x| x.pdb_info())
515
0
    }
516
517
0
    fn relative_address_base(&self) -> u64 {
518
0
        with_inner!(self, File, |x| x.relative_address_base())
519
0
    }
520
521
0
    fn entry(&self) -> u64 {
522
0
        with_inner!(self, File, |x| x.entry())
523
0
    }
524
525
0
    fn flags(&self) -> FileFlags {
526
0
        with_inner!(self, File, |x| x.flags())
527
0
    }
528
}
529
530
/// An iterator for the loadable segments in a [`File`].
531
#[derive(Debug)]
532
pub struct SegmentIterator<'data, 'file, R: ReadRef<'data> = &'data [u8]> {
533
    inner: SegmentIteratorInternal<'data, 'file, R>,
534
}
535
536
#[derive(Debug)]
537
enum 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
562
impl<'data, 'file, R: ReadRef<'data>> Iterator for SegmentIterator<'data, 'file, R> {
563
    type Item = Segment<'data, 'file, R>;
564
565
0
    fn next(&mut self) -> Option<Self::Item> {
566
0
        next_inner!(self.inner, SegmentIteratorInternal, SegmentInternal)
567
0
            .map(|inner| Segment { inner })
568
0
    }
569
}
570
571
/// A loadable segment in a [`File`].
572
///
573
/// Most functionality is provided by the [`ObjectSegment`] trait implementation.
574
pub struct Segment<'data, 'file, R: ReadRef<'data> = &'data [u8]> {
575
    inner: SegmentInternal<'data, 'file, R>,
576
}
577
578
#[derive(Debug)]
579
enum 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
604
impl<'data, 'file, R: ReadRef<'data>> fmt::Debug for Segment<'data, 'file, R> {
605
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
606
        // It's painful to do much better than this
607
0
        let mut s = f.debug_struct("Segment");
608
0
        match self.name() {
609
0
            Ok(Some(ref name)) => {
610
0
                s.field("name", name);
611
0
            }
612
0
            Ok(None) => {}
613
0
            Err(_) => {
614
0
                s.field("name", &"<invalid>");
615
0
            }
616
        }
617
0
        s.field("address", &self.address())
618
0
            .field("size", &self.size())
619
0
            .finish()
620
0
    }
621
}
622
623
impl<'data, 'file, R: ReadRef<'data>> read::private::Sealed for Segment<'data, 'file, R> {}
624
625
impl<'data, 'file, R: ReadRef<'data>> ObjectSegment<'data> for Segment<'data, 'file, R> {
626
0
    fn address(&self) -> u64 {
627
0
        with_inner!(self.inner, SegmentInternal, |x| x.address())
628
0
    }
629
630
0
    fn size(&self) -> u64 {
631
0
        with_inner!(self.inner, SegmentInternal, |x| x.size())
632
0
    }
633
634
0
    fn align(&self) -> u64 {
635
0
        with_inner!(self.inner, SegmentInternal, |x| x.align())
636
0
    }
637
638
0
    fn file_range(&self) -> (u64, u64) {
639
0
        with_inner!(self.inner, SegmentInternal, |x| x.file_range())
640
0
    }
641
642
0
    fn data(&self) -> Result<&'data [u8]> {
643
0
        with_inner!(self.inner, SegmentInternal, |x| x.data())
644
0
    }
645
646
0
    fn data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>> {
647
0
        with_inner!(self.inner, SegmentInternal, |x| x.data_range(address, size))
648
0
    }
649
650
0
    fn name_bytes(&self) -> Result<Option<&[u8]>> {
651
0
        with_inner!(self.inner, SegmentInternal, |x| x.name_bytes())
652
0
    }
653
654
0
    fn name(&self) -> Result<Option<&str>> {
655
0
        with_inner!(self.inner, SegmentInternal, |x| x.name())
656
0
    }
657
658
0
    fn flags(&self) -> SegmentFlags {
659
0
        with_inner!(self.inner, SegmentInternal, |x| x.flags())
660
0
    }
661
}
662
663
/// An iterator for the sections in a [`File`].
664
#[derive(Debug)]
665
pub 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)]
671
enum 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
696
impl<'data, 'file, R: ReadRef<'data>> Iterator for SectionIterator<'data, 'file, R> {
697
    type Item = Section<'data, 'file, R>;
698
699
0
    fn next(&mut self) -> Option<Self::Item> {
700
0
        next_inner!(self.inner, SectionIteratorInternal, SectionInternal)
701
0
            .map(|inner| Section { inner })
702
0
    }
703
}
704
705
/// A section in a [`File`].
706
///
707
/// Most functionality is provided by the [`ObjectSection`] trait implementation.
708
pub struct Section<'data, 'file, R: ReadRef<'data> = &'data [u8]> {
709
    inner: SectionInternal<'data, 'file, R>,
710
}
711
712
enum 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
737
impl<'data, 'file, R: ReadRef<'data>> fmt::Debug for Section<'data, 'file, R> {
738
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
739
        // It's painful to do much better than this
740
0
        let mut s = f.debug_struct("Section");
741
0
        match self.segment_name() {
742
0
            Ok(Some(ref name)) => {
743
0
                s.field("segment", name);
744
0
            }
745
0
            Ok(None) => {}
746
0
            Err(_) => {
747
0
                s.field("segment", &"<invalid>");
748
0
            }
749
        }
750
0
        s.field("name", &self.name().unwrap_or("<invalid>"))
751
0
            .field("address", &self.address())
752
0
            .field("size", &self.size())
753
0
            .field("align", &self.align())
754
0
            .field("kind", &self.kind())
755
0
            .field("flags", &self.flags())
756
0
            .finish()
757
0
    }
758
}
759
760
impl<'data, 'file, R: ReadRef<'data>> read::private::Sealed for Section<'data, 'file, R> {}
761
762
impl<'data, 'file, R: ReadRef<'data>> ObjectSection<'data> for Section<'data, 'file, R> {
763
    type RelocationIterator = SectionRelocationIterator<'data, 'file, R>;
764
765
0
    fn index(&self) -> SectionIndex {
766
0
        with_inner!(self.inner, SectionInternal, |x| x.index())
767
0
    }
768
769
0
    fn address(&self) -> u64 {
770
0
        with_inner!(self.inner, SectionInternal, |x| x.address())
771
0
    }
772
773
0
    fn size(&self) -> u64 {
774
0
        with_inner!(self.inner, SectionInternal, |x| x.size())
775
0
    }
776
777
0
    fn align(&self) -> u64 {
778
0
        with_inner!(self.inner, SectionInternal, |x| x.align())
779
0
    }
780
781
0
    fn file_range(&self) -> Option<(u64, u64)> {
782
0
        with_inner!(self.inner, SectionInternal, |x| x.file_range())
783
0
    }
784
785
0
    fn data(&self) -> Result<&'data [u8]> {
786
0
        with_inner!(self.inner, SectionInternal, |x| x.data())
787
0
    }
788
789
0
    fn data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>> {
790
0
        with_inner!(self.inner, SectionInternal, |x| x.data_range(address, size))
791
0
    }
792
793
0
    fn compressed_file_range(&self) -> Result<CompressedFileRange> {
794
0
        with_inner!(self.inner, SectionInternal, |x| x.compressed_file_range())
795
0
    }
796
797
0
    fn compressed_data(&self) -> Result<CompressedData<'data>> {
798
0
        with_inner!(self.inner, SectionInternal, |x| x.compressed_data())
799
0
    }
800
801
0
    fn name_bytes(&self) -> Result<&'data [u8]> {
802
0
        with_inner!(self.inner, SectionInternal, |x| x.name_bytes())
803
0
    }
804
805
0
    fn name(&self) -> Result<&'data str> {
806
0
        with_inner!(self.inner, SectionInternal, |x| x.name())
807
0
    }
808
809
0
    fn segment_name_bytes(&self) -> Result<Option<&[u8]>> {
810
0
        with_inner!(self.inner, SectionInternal, |x| x.segment_name_bytes())
811
0
    }
812
813
0
    fn segment_name(&self) -> Result<Option<&str>> {
814
0
        with_inner!(self.inner, SectionInternal, |x| x.segment_name())
815
0
    }
816
817
0
    fn kind(&self) -> SectionKind {
818
0
        with_inner!(self.inner, SectionInternal, |x| x.kind())
819
0
    }
820
821
0
    fn relocations(&self) -> SectionRelocationIterator<'data, 'file, R> {
822
        SectionRelocationIterator {
823
0
            inner: map_inner!(
824
0
                self.inner,
825
                SectionInternal,
826
                SectionRelocationIteratorInternal,
827
0
                |x| x.relocations()
828
            ),
829
        }
830
0
    }
831
832
0
    fn relocation_map(&self) -> Result<RelocationMap> {
833
0
        with_inner!(self.inner, SectionInternal, |x| x.relocation_map())
834
0
    }
835
836
0
    fn flags(&self) -> SectionFlags {
837
0
        with_inner!(self.inner, SectionInternal, |x| x.flags())
838
0
    }
839
}
840
841
/// An iterator for the COMDAT section groups in a [`File`].
842
#[derive(Debug)]
843
pub struct ComdatIterator<'data, 'file, R: ReadRef<'data> = &'data [u8]> {
844
    inner: ComdatIteratorInternal<'data, 'file, R>,
845
}
846
847
#[derive(Debug)]
848
enum 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
873
impl<'data, 'file, R: ReadRef<'data>> Iterator for ComdatIterator<'data, 'file, R> {
874
    type Item = Comdat<'data, 'file, R>;
875
876
0
    fn next(&mut self) -> Option<Self::Item> {
877
0
        next_inner!(self.inner, ComdatIteratorInternal, ComdatInternal)
878
0
            .map(|inner| Comdat { inner })
879
0
    }
880
}
881
882
/// A COMDAT section group in a [`File`].
883
///
884
/// Most functionality is provided by the [`ObjectComdat`] trait implementation.
885
pub struct Comdat<'data, 'file, R: ReadRef<'data> = &'data [u8]> {
886
    inner: ComdatInternal<'data, 'file, R>,
887
}
888
889
enum 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
914
impl<'data, 'file, R: ReadRef<'data>> fmt::Debug for Comdat<'data, 'file, R> {
915
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
916
0
        let mut s = f.debug_struct("Comdat");
917
0
        s.field("symbol", &self.symbol())
918
0
            .field("name", &self.name().unwrap_or("<invalid>"))
919
0
            .field("kind", &self.kind())
920
0
            .finish()
921
0
    }
922
}
923
924
impl<'data, 'file, R: ReadRef<'data>> read::private::Sealed for Comdat<'data, 'file, R> {}
925
926
impl<'data, 'file, R: ReadRef<'data>> ObjectComdat<'data> for Comdat<'data, 'file, R> {
927
    type SectionIterator = ComdatSectionIterator<'data, 'file, R>;
928
929
0
    fn kind(&self) -> ComdatKind {
930
0
        with_inner!(self.inner, ComdatInternal, |x| x.kind())
931
0
    }
932
933
0
    fn symbol(&self) -> SymbolIndex {
934
0
        with_inner!(self.inner, ComdatInternal, |x| x.symbol())
935
0
    }
936
937
0
    fn name_bytes(&self) -> Result<&'data [u8]> {
938
0
        with_inner!(self.inner, ComdatInternal, |x| x.name_bytes())
939
0
    }
940
941
0
    fn name(&self) -> Result<&'data str> {
942
0
        with_inner!(self.inner, ComdatInternal, |x| x.name())
943
0
    }
944
945
0
    fn sections(&self) -> ComdatSectionIterator<'data, 'file, R> {
946
        ComdatSectionIterator {
947
0
            inner: map_inner!(
948
0
                self.inner,
949
                ComdatInternal,
950
                ComdatSectionIteratorInternal,
951
0
                |x| x.sections()
952
            ),
953
        }
954
0
    }
955
}
956
957
/// An iterator for the sections in a [`Comdat`].
958
#[derive(Debug)]
959
pub struct ComdatSectionIterator<'data, 'file, R: ReadRef<'data> = &'data [u8]> {
960
    inner: ComdatSectionIteratorInternal<'data, 'file, R>,
961
}
962
963
#[derive(Debug)]
964
enum 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
989
impl<'data, 'file, R: ReadRef<'data>> Iterator for ComdatSectionIterator<'data, 'file, R> {
990
    type Item = SectionIndex;
991
992
0
    fn next(&mut self) -> Option<Self::Item> {
993
0
        with_inner_mut!(self.inner, ComdatSectionIteratorInternal, |x| x.next())
994
0
    }
995
}
996
997
/// A symbol table in a [`File`].
998
///
999
/// Most functionality is provided by the [`ObjectSymbolTable`] trait implementation.
1000
#[derive(Debug)]
1001
pub struct SymbolTable<'data, 'file, R = &'data [u8]>
1002
where
1003
    R: ReadRef<'data>,
1004
{
1005
    inner: SymbolTableInternal<'data, 'file, R>,
1006
}
1007
1008
#[derive(Debug)]
1009
enum SymbolTableInternal<'data, 'file, R>
1010
where
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
1057
impl<'data, 'file, R: ReadRef<'data>> read::private::Sealed for SymbolTable<'data, 'file, R> {}
1058
1059
impl<'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
0
    fn symbols(&self) -> Self::SymbolIterator {
1064
        SymbolIterator {
1065
0
            inner: map_inner!(
1066
0
                self.inner,
1067
                SymbolTableInternal,
1068
                SymbolIteratorInternal,
1069
0
                |x| (x.0.symbols(), PhantomData)
1070
            ),
1071
        }
1072
0
    }
1073
1074
0
    fn symbol_by_index(&self, index: SymbolIndex) -> Result<Self::Symbol> {
1075
0
        map_inner_option!(self.inner, SymbolTableInternal, SymbolInternal, |x| x
1076
0
            .0
1077
0
            .symbol_by_index(index)
1078
0
            .map(|x| (x, PhantomData)))
Unexecuted instantiation: <object::read::any::SymbolTable<_> as object::read::traits::ObjectSymbolTable>::symbol_by_index::{closure#2}
Unexecuted instantiation: <object::read::any::SymbolTable<_> as object::read::traits::ObjectSymbolTable>::symbol_by_index::{closure#3}
Unexecuted instantiation: <object::read::any::SymbolTable<_> as object::read::traits::ObjectSymbolTable>::symbol_by_index::{closure#4}
Unexecuted instantiation: <object::read::any::SymbolTable<_> as object::read::traits::ObjectSymbolTable>::symbol_by_index::{closure#5}
Unexecuted instantiation: <object::read::any::SymbolTable<_> as object::read::traits::ObjectSymbolTable>::symbol_by_index::{closure#6}
Unexecuted instantiation: <object::read::any::SymbolTable<_> as object::read::traits::ObjectSymbolTable>::symbol_by_index::{closure#7}
Unexecuted instantiation: <object::read::any::SymbolTable<_> as object::read::traits::ObjectSymbolTable>::symbol_by_index::{closure#8}
Unexecuted instantiation: <object::read::any::SymbolTable<_> as object::read::traits::ObjectSymbolTable>::symbol_by_index::{closure#9}
Unexecuted instantiation: <object::read::any::SymbolTable<_> as object::read::traits::ObjectSymbolTable>::symbol_by_index::{closure#10}
Unexecuted instantiation: <object::read::any::SymbolTable<_> as object::read::traits::ObjectSymbolTable>::symbol_by_index::{closure#1}
1079
0
        .map(|inner| Symbol { inner })
1080
0
    }
1081
}
1082
1083
/// An iterator for the symbols in a [`SymbolTable`].
1084
#[derive(Debug)]
1085
pub struct SymbolIterator<'data, 'file, R = &'data [u8]>
1086
where
1087
    R: ReadRef<'data>,
1088
{
1089
    inner: SymbolIteratorInternal<'data, 'file, R>,
1090
}
1091
1092
#[derive(Debug)]
1093
enum SymbolIteratorInternal<'data, 'file, R>
1094
where
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
1151
impl<'data, 'file, R: ReadRef<'data>> Iterator for SymbolIterator<'data, 'file, R> {
1152
    type Item = Symbol<'data, 'file, R>;
1153
1154
0
    fn next(&mut self) -> Option<Self::Item> {
1155
0
        map_inner_option_mut!(self.inner, SymbolIteratorInternal, SymbolInternal, |iter| {
1156
0
            iter.0.next().map(|x| (x, PhantomData))
Unexecuted instantiation: <object::read::any::SymbolIterator<_> as core::iter::traits::iterator::Iterator>::next::{closure#2}
Unexecuted instantiation: <object::read::any::SymbolIterator<_> as core::iter::traits::iterator::Iterator>::next::{closure#3}
Unexecuted instantiation: <object::read::any::SymbolIterator<_> as core::iter::traits::iterator::Iterator>::next::{closure#4}
Unexecuted instantiation: <object::read::any::SymbolIterator<_> as core::iter::traits::iterator::Iterator>::next::{closure#5}
Unexecuted instantiation: <object::read::any::SymbolIterator<_> as core::iter::traits::iterator::Iterator>::next::{closure#6}
Unexecuted instantiation: <object::read::any::SymbolIterator<_> as core::iter::traits::iterator::Iterator>::next::{closure#7}
Unexecuted instantiation: <object::read::any::SymbolIterator<_> as core::iter::traits::iterator::Iterator>::next::{closure#8}
Unexecuted instantiation: <object::read::any::SymbolIterator<_> as core::iter::traits::iterator::Iterator>::next::{closure#9}
Unexecuted instantiation: <object::read::any::SymbolIterator<_> as core::iter::traits::iterator::Iterator>::next::{closure#10}
Unexecuted instantiation: <object::read::any::SymbolIterator<_> as core::iter::traits::iterator::Iterator>::next::{closure#1}
1157
        })
1158
0
        .map(|inner| Symbol { inner })
1159
0
    }
1160
}
1161
1162
/// An symbol in a [`SymbolTable`].
1163
///
1164
/// Most functionality is provided by the [`ObjectSymbol`] trait implementation.
1165
pub struct Symbol<'data, 'file, R = &'data [u8]>
1166
where
1167
    R: ReadRef<'data>,
1168
{
1169
    inner: SymbolInternal<'data, 'file, R>,
1170
}
1171
1172
enum SymbolInternal<'data, 'file, R>
1173
where
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
1220
impl<'data, 'file, R: ReadRef<'data>> fmt::Debug for Symbol<'data, 'file, R> {
1221
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1222
0
        f.debug_struct("Symbol")
1223
0
            .field("name", &self.name().unwrap_or("<invalid>"))
1224
0
            .field("address", &self.address())
1225
0
            .field("size", &self.size())
1226
0
            .field("kind", &self.kind())
1227
0
            .field("section", &self.section())
1228
0
            .field("scope", &self.scope())
1229
0
            .field("weak", &self.is_weak())
1230
0
            .field("flags", &self.flags())
1231
0
            .finish()
1232
0
    }
1233
}
1234
1235
impl<'data, 'file, R: ReadRef<'data>> read::private::Sealed for Symbol<'data, 'file, R> {}
1236
1237
impl<'data, 'file, R: ReadRef<'data>> ObjectSymbol<'data> for Symbol<'data, 'file, R> {
1238
0
    fn index(&self) -> SymbolIndex {
1239
0
        with_inner!(self.inner, SymbolInternal, |x| x.0.index())
1240
0
    }
1241
1242
0
    fn name_bytes(&self) -> Result<&'data [u8]> {
1243
0
        with_inner!(self.inner, SymbolInternal, |x| x.0.name_bytes())
1244
0
    }
1245
1246
0
    fn name(&self) -> Result<&'data str> {
1247
0
        with_inner!(self.inner, SymbolInternal, |x| x.0.name())
1248
0
    }
1249
1250
0
    fn address(&self) -> u64 {
1251
0
        with_inner!(self.inner, SymbolInternal, |x| x.0.address())
1252
0
    }
1253
1254
0
    fn size(&self) -> u64 {
1255
0
        with_inner!(self.inner, SymbolInternal, |x| x.0.size())
1256
0
    }
1257
1258
0
    fn kind(&self) -> SymbolKind {
1259
0
        with_inner!(self.inner, SymbolInternal, |x| x.0.kind())
1260
0
    }
1261
1262
0
    fn section(&self) -> SymbolSection {
1263
0
        with_inner!(self.inner, SymbolInternal, |x| x.0.section())
1264
0
    }
1265
1266
0
    fn is_undefined(&self) -> bool {
1267
0
        with_inner!(self.inner, SymbolInternal, |x| x.0.is_undefined())
1268
0
    }
1269
1270
0
    fn is_definition(&self) -> bool {
1271
0
        with_inner!(self.inner, SymbolInternal, |x| x.0.is_definition())
1272
0
    }
1273
1274
0
    fn is_common(&self) -> bool {
1275
0
        with_inner!(self.inner, SymbolInternal, |x| x.0.is_common())
1276
0
    }
1277
1278
0
    fn is_weak(&self) -> bool {
1279
0
        with_inner!(self.inner, SymbolInternal, |x| x.0.is_weak())
1280
0
    }
1281
1282
0
    fn scope(&self) -> SymbolScope {
1283
0
        with_inner!(self.inner, SymbolInternal, |x| x.0.scope())
1284
0
    }
1285
1286
0
    fn is_global(&self) -> bool {
1287
0
        with_inner!(self.inner, SymbolInternal, |x| x.0.is_global())
1288
0
    }
1289
1290
0
    fn is_local(&self) -> bool {
1291
0
        with_inner!(self.inner, SymbolInternal, |x| x.0.is_local())
1292
0
    }
1293
1294
0
    fn flags(&self) -> SymbolFlags<SectionIndex, SymbolIndex> {
1295
0
        with_inner!(self.inner, SymbolInternal, |x| x.0.flags())
1296
0
    }
1297
}
1298
1299
/// An iterator for the dynamic relocation entries in a [`File`].
1300
#[derive(Debug)]
1301
pub struct DynamicRelocationIterator<'data, 'file, R = &'data [u8]>
1302
where
1303
    R: ReadRef<'data>,
1304
{
1305
    inner: DynamicRelocationIteratorInternal<'data, 'file, R>,
1306
}
1307
1308
#[derive(Debug)]
1309
enum DynamicRelocationIteratorInternal<'data, 'file, R>
1310
where
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
1322
impl<'data, 'file, R: ReadRef<'data>> Iterator for DynamicRelocationIterator<'data, 'file, R> {
1323
    type Item = (u64, Relocation);
1324
1325
0
    fn next(&mut self) -> Option<Self::Item> {
1326
0
        match self.inner {
1327
            #[cfg(feature = "elf")]
1328
0
            DynamicRelocationIteratorInternal::Elf32(ref mut elf) => elf.next(),
1329
            #[cfg(feature = "elf")]
1330
0
            DynamicRelocationIteratorInternal::Elf64(ref mut elf) => elf.next(),
1331
0
            DynamicRelocationIteratorInternal::None(_) => None,
1332
        }
1333
0
    }
1334
}
1335
1336
/// An iterator for the relocation entries in a [`Section`].
1337
#[derive(Debug)]
1338
pub struct SectionRelocationIterator<'data, 'file, R: ReadRef<'data> = &'data [u8]> {
1339
    inner: SectionRelocationIteratorInternal<'data, 'file, R>,
1340
}
1341
1342
#[derive(Debug)]
1343
enum 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
1368
impl<'data, 'file, R: ReadRef<'data>> Iterator for SectionRelocationIterator<'data, 'file, R> {
1369
    type Item = (u64, Relocation);
1370
1371
0
    fn next(&mut self) -> Option<Self::Item> {
1372
0
        with_inner_mut!(self.inner, SectionRelocationIteratorInternal, |x| x.next())
1373
0
    }
1374
}