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