]> git.proxmox.com Git - rustc.git/blob - vendor/object-0.22.0/src/read/any.rs
New upstream version 1.55.0+dfsg1
[rustc.git] / vendor / object-0.22.0 / src / read / any.rs
1 use alloc::fmt;
2
3 #[cfg(feature = "coff")]
4 use crate::read::coff;
5 #[cfg(feature = "elf")]
6 use crate::read::elf;
7 #[cfg(feature = "macho")]
8 use crate::read::macho;
9 #[cfg(feature = "pe")]
10 use crate::read::pe;
11 #[cfg(feature = "wasm")]
12 use crate::read::wasm;
13 use crate::read::{
14 self, Architecture, BinaryFormat, ComdatKind, CompressedData, Error, FileFlags, Object,
15 ObjectComdat, ObjectMap, ObjectSection, ObjectSegment, ObjectSymbol, ObjectSymbolTable,
16 Relocation, Result, SectionFlags, SectionIndex, SectionKind, SymbolFlags, SymbolIndex,
17 SymbolKind, SymbolMap, SymbolMapName, SymbolScope, SymbolSection,
18 };
19
20 /// Evaluate an expression on the contents of a file format enum.
21 ///
22 /// This is a hack to avoid virtual calls.
23 macro_rules! with_inner {
24 ($inner:expr, $enum:ident, | $var:ident | $body:expr) => {
25 match $inner {
26 #[cfg(feature = "coff")]
27 $enum::Coff(ref $var) => $body,
28 #[cfg(feature = "elf")]
29 $enum::Elf32(ref $var) => $body,
30 #[cfg(feature = "elf")]
31 $enum::Elf64(ref $var) => $body,
32 #[cfg(feature = "macho")]
33 $enum::MachO32(ref $var) => $body,
34 #[cfg(feature = "macho")]
35 $enum::MachO64(ref $var) => $body,
36 #[cfg(feature = "pe")]
37 $enum::Pe32(ref $var) => $body,
38 #[cfg(feature = "pe")]
39 $enum::Pe64(ref $var) => $body,
40 #[cfg(feature = "wasm")]
41 $enum::Wasm(ref $var) => $body,
42 }
43 };
44 }
45
46 macro_rules! with_inner_mut {
47 ($inner:expr, $enum:ident, | $var:ident | $body:expr) => {
48 match $inner {
49 #[cfg(feature = "coff")]
50 $enum::Coff(ref mut $var) => $body,
51 #[cfg(feature = "elf")]
52 $enum::Elf32(ref mut $var) => $body,
53 #[cfg(feature = "elf")]
54 $enum::Elf64(ref mut $var) => $body,
55 #[cfg(feature = "macho")]
56 $enum::MachO32(ref mut $var) => $body,
57 #[cfg(feature = "macho")]
58 $enum::MachO64(ref mut $var) => $body,
59 #[cfg(feature = "pe")]
60 $enum::Pe32(ref mut $var) => $body,
61 #[cfg(feature = "pe")]
62 $enum::Pe64(ref mut $var) => $body,
63 #[cfg(feature = "wasm")]
64 $enum::Wasm(ref mut $var) => $body,
65 }
66 };
67 }
68
69 /// Like `with_inner!`, but wraps the result in another enum.
70 macro_rules! map_inner {
71 ($inner:expr, $from:ident, $to:ident, | $var:ident | $body:expr) => {
72 match $inner {
73 #[cfg(feature = "coff")]
74 $from::Coff(ref $var) => $to::Coff($body),
75 #[cfg(feature = "elf")]
76 $from::Elf32(ref $var) => $to::Elf32($body),
77 #[cfg(feature = "elf")]
78 $from::Elf64(ref $var) => $to::Elf64($body),
79 #[cfg(feature = "macho")]
80 $from::MachO32(ref $var) => $to::MachO32($body),
81 #[cfg(feature = "macho")]
82 $from::MachO64(ref $var) => $to::MachO64($body),
83 #[cfg(feature = "pe")]
84 $from::Pe32(ref $var) => $to::Pe32($body),
85 #[cfg(feature = "pe")]
86 $from::Pe64(ref $var) => $to::Pe64($body),
87 #[cfg(feature = "wasm")]
88 $from::Wasm(ref $var) => $to::Wasm($body),
89 }
90 };
91 }
92
93 /// Like `map_inner!`, but the result is a Result or Option.
94 macro_rules! map_inner_option {
95 ($inner:expr, $from:ident, $to:ident, | $var:ident | $body:expr) => {
96 match $inner {
97 #[cfg(feature = "coff")]
98 $from::Coff(ref $var) => $body.map($to::Coff),
99 #[cfg(feature = "elf")]
100 $from::Elf32(ref $var) => $body.map($to::Elf32),
101 #[cfg(feature = "elf")]
102 $from::Elf64(ref $var) => $body.map($to::Elf64),
103 #[cfg(feature = "macho")]
104 $from::MachO32(ref $var) => $body.map($to::MachO32),
105 #[cfg(feature = "macho")]
106 $from::MachO64(ref $var) => $body.map($to::MachO64),
107 #[cfg(feature = "pe")]
108 $from::Pe32(ref $var) => $body.map($to::Pe32),
109 #[cfg(feature = "pe")]
110 $from::Pe64(ref $var) => $body.map($to::Pe64),
111 #[cfg(feature = "wasm")]
112 $from::Wasm(ref $var) => $body.map($to::Wasm),
113 }
114 };
115 }
116
117 /// Call `next` for a file format iterator.
118 macro_rules! next_inner {
119 ($inner:expr, $from:ident, $to:ident) => {
120 match $inner {
121 #[cfg(feature = "coff")]
122 $from::Coff(ref mut iter) => iter.next().map($to::Coff),
123 #[cfg(feature = "elf")]
124 $from::Elf32(ref mut iter) => iter.next().map($to::Elf32),
125 #[cfg(feature = "elf")]
126 $from::Elf64(ref mut iter) => iter.next().map($to::Elf64),
127 #[cfg(feature = "macho")]
128 $from::MachO32(ref mut iter) => iter.next().map($to::MachO32),
129 #[cfg(feature = "macho")]
130 $from::MachO64(ref mut iter) => iter.next().map($to::MachO64),
131 #[cfg(feature = "pe")]
132 $from::Pe32(ref mut iter) => iter.next().map($to::Pe32),
133 #[cfg(feature = "pe")]
134 $from::Pe64(ref mut iter) => iter.next().map($to::Pe64),
135 #[cfg(feature = "wasm")]
136 $from::Wasm(ref mut iter) => iter.next().map($to::Wasm),
137 }
138 };
139 }
140
141 /// An object file.
142 ///
143 /// Most functionality is provided by the `Object` trait implementation.
144 #[derive(Debug)]
145 pub struct File<'data> {
146 inner: FileInternal<'data>,
147 }
148
149 #[allow(clippy::large_enum_variant)]
150 #[derive(Debug)]
151 enum FileInternal<'data> {
152 #[cfg(feature = "coff")]
153 Coff(coff::CoffFile<'data>),
154 #[cfg(feature = "elf")]
155 Elf32(elf::ElfFile32<'data>),
156 #[cfg(feature = "elf")]
157 Elf64(elf::ElfFile64<'data>),
158 #[cfg(feature = "macho")]
159 MachO32(macho::MachOFile32<'data>),
160 #[cfg(feature = "macho")]
161 MachO64(macho::MachOFile64<'data>),
162 #[cfg(feature = "pe")]
163 Pe32(pe::PeFile32<'data>),
164 #[cfg(feature = "pe")]
165 Pe64(pe::PeFile64<'data>),
166 #[cfg(feature = "wasm")]
167 Wasm(wasm::WasmFile<'data>),
168 }
169
170 impl<'data> File<'data> {
171 /// Parse the raw file data.
172 pub fn parse(data: &'data [u8]) -> Result<Self> {
173 if data.len() < 16 {
174 return Err(Error("File too short"));
175 }
176
177 let inner = match [data[0], data[1], data[2], data[3], data[4]] {
178 // 32-bit ELF
179 #[cfg(feature = "elf")]
180 [0x7f, b'E', b'L', b'F', 1] => FileInternal::Elf32(elf::ElfFile32::parse(data)?),
181 // 64-bit ELF
182 #[cfg(feature = "elf")]
183 [0x7f, b'E', b'L', b'F', 2] => FileInternal::Elf64(elf::ElfFile64::parse(data)?),
184 // 32-bit Mach-O
185 #[cfg(feature = "macho")]
186 [0xfe, 0xed, 0xfa, 0xce, _]
187 | [0xce, 0xfa, 0xed, 0xfe, _] => FileInternal::MachO32(macho::MachOFile32::parse(data)?),
188 // 64-bit Mach-O
189 #[cfg(feature = "macho")]
190 | [0xfe, 0xed, 0xfa, 0xcf, _]
191 | [0xcf, 0xfa, 0xed, 0xfe, _] => FileInternal::MachO64(macho::MachOFile64::parse(data)?),
192 // WASM
193 #[cfg(feature = "wasm")]
194 [0x00, b'a', b's', b'm', _] => FileInternal::Wasm(wasm::WasmFile::parse(data)?),
195 // MS-DOS, assume stub for Windows PE32 or PE32+
196 #[cfg(feature = "pe")]
197 [b'M', b'Z', _, _, _] => {
198 // `optional_header_magic` doesn't care if it's `PeFile32` and `PeFile64`.
199 match pe::PeFile64::optional_header_magic(data) {
200 Ok(crate::pe::IMAGE_NT_OPTIONAL_HDR32_MAGIC) => {
201 FileInternal::Pe32(pe::PeFile32::parse(data)?)
202 }
203 Ok(crate::pe::IMAGE_NT_OPTIONAL_HDR64_MAGIC) => {
204 FileInternal::Pe64(pe::PeFile64::parse(data)?)
205 }
206 _ => return Err(Error("Unknown MS-DOS file")),
207 }
208 }
209 // TODO: more COFF machines
210 #[cfg(feature = "coff")]
211 // COFF x86
212 [0x4c, 0x01, _, _, _]
213 // COFF x86-64
214 | [0x64, 0x86, _, _, _] => FileInternal::Coff(coff::CoffFile::parse(data)?),
215 _ => return Err(Error("Unknown file magic")),
216 };
217 Ok(File { inner })
218 }
219
220 /// Return the file format.
221 pub fn format(&self) -> BinaryFormat {
222 match self.inner {
223 #[cfg(feature = "coff")]
224 FileInternal::Coff(_) => BinaryFormat::Coff,
225 #[cfg(feature = "elf")]
226 FileInternal::Elf32(_) | FileInternal::Elf64(_) => BinaryFormat::Elf,
227 #[cfg(feature = "macho")]
228 FileInternal::MachO32(_) | FileInternal::MachO64(_) => BinaryFormat::MachO,
229 #[cfg(feature = "pe")]
230 FileInternal::Pe32(_) | FileInternal::Pe64(_) => BinaryFormat::Pe,
231 #[cfg(feature = "wasm")]
232 FileInternal::Wasm(_) => BinaryFormat::Wasm,
233 }
234 }
235 }
236
237 impl<'data> read::private::Sealed for File<'data> {}
238
239 impl<'data, 'file> Object<'data, 'file> for File<'data>
240 where
241 'data: 'file,
242 {
243 type Segment = Segment<'data, 'file>;
244 type SegmentIterator = SegmentIterator<'data, 'file>;
245 type Section = Section<'data, 'file>;
246 type SectionIterator = SectionIterator<'data, 'file>;
247 type Comdat = Comdat<'data, 'file>;
248 type ComdatIterator = ComdatIterator<'data, 'file>;
249 type Symbol = Symbol<'data, 'file>;
250 type SymbolIterator = SymbolIterator<'data, 'file>;
251 type SymbolTable = SymbolTable<'data, 'file>;
252
253 fn architecture(&self) -> Architecture {
254 with_inner!(self.inner, FileInternal, |x| x.architecture())
255 }
256
257 fn is_little_endian(&self) -> bool {
258 with_inner!(self.inner, FileInternal, |x| x.is_little_endian())
259 }
260
261 fn is_64(&self) -> bool {
262 with_inner!(self.inner, FileInternal, |x| x.is_64())
263 }
264
265 fn segments(&'file self) -> SegmentIterator<'data, 'file> {
266 SegmentIterator {
267 inner: map_inner!(self.inner, FileInternal, SegmentIteratorInternal, |x| x
268 .segments()),
269 }
270 }
271
272 fn section_by_name(&'file self, section_name: &str) -> Option<Section<'data, 'file>> {
273 map_inner_option!(self.inner, FileInternal, SectionInternal, |x| x
274 .section_by_name(section_name))
275 .map(|inner| Section { inner })
276 }
277
278 fn section_by_index(&'file self, index: SectionIndex) -> Result<Section<'data, 'file>> {
279 map_inner_option!(self.inner, FileInternal, SectionInternal, |x| x
280 .section_by_index(index))
281 .map(|inner| Section { inner })
282 }
283
284 fn sections(&'file self) -> SectionIterator<'data, 'file> {
285 SectionIterator {
286 inner: map_inner!(self.inner, FileInternal, SectionIteratorInternal, |x| x
287 .sections()),
288 }
289 }
290
291 fn comdats(&'file self) -> ComdatIterator<'data, 'file> {
292 ComdatIterator {
293 inner: map_inner!(self.inner, FileInternal, ComdatIteratorInternal, |x| x
294 .comdats()),
295 }
296 }
297
298 fn symbol_by_index(&'file self, index: SymbolIndex) -> Result<Symbol<'data, 'file>> {
299 map_inner_option!(self.inner, FileInternal, SymbolInternal, |x| x
300 .symbol_by_index(index))
301 .map(|inner| Symbol { inner })
302 }
303
304 fn symbols(&'file self) -> SymbolIterator<'data, 'file> {
305 SymbolIterator {
306 inner: map_inner!(self.inner, FileInternal, SymbolIteratorInternal, |x| x
307 .symbols()),
308 }
309 }
310
311 fn symbol_table(&'file self) -> Option<SymbolTable<'data, 'file>> {
312 map_inner_option!(self.inner, FileInternal, SymbolTableInternal, |x| x
313 .symbol_table())
314 .map(|inner| SymbolTable { inner })
315 }
316
317 fn dynamic_symbols(&'file self) -> SymbolIterator<'data, 'file> {
318 SymbolIterator {
319 inner: map_inner!(self.inner, FileInternal, SymbolIteratorInternal, |x| x
320 .dynamic_symbols()),
321 }
322 }
323
324 fn dynamic_symbol_table(&'file self) -> Option<SymbolTable<'data, 'file>> {
325 map_inner_option!(self.inner, FileInternal, SymbolTableInternal, |x| x
326 .dynamic_symbol_table())
327 .map(|inner| SymbolTable { inner })
328 }
329
330 fn symbol_map(&self) -> SymbolMap<SymbolMapName<'data>> {
331 with_inner!(self.inner, FileInternal, |x| x.symbol_map())
332 }
333
334 fn object_map(&self) -> ObjectMap<'data> {
335 with_inner!(self.inner, FileInternal, |x| x.object_map())
336 }
337
338 fn has_debug_symbols(&self) -> bool {
339 with_inner!(self.inner, FileInternal, |x| x.has_debug_symbols())
340 }
341
342 #[inline]
343 fn mach_uuid(&self) -> Result<Option<[u8; 16]>> {
344 with_inner!(self.inner, FileInternal, |x| x.mach_uuid())
345 }
346
347 #[inline]
348 fn build_id(&self) -> Result<Option<&'data [u8]>> {
349 with_inner!(self.inner, FileInternal, |x| x.build_id())
350 }
351
352 #[inline]
353 fn gnu_debuglink(&self) -> Result<Option<(&'data [u8], u32)>> {
354 with_inner!(self.inner, FileInternal, |x| x.gnu_debuglink())
355 }
356
357 fn entry(&self) -> u64 {
358 with_inner!(self.inner, FileInternal, |x| x.entry())
359 }
360
361 fn flags(&self) -> FileFlags {
362 with_inner!(self.inner, FileInternal, |x| x.flags())
363 }
364 }
365
366 /// An iterator over the segments of a `File`.
367 #[derive(Debug)]
368 pub struct SegmentIterator<'data, 'file>
369 where
370 'data: 'file,
371 {
372 inner: SegmentIteratorInternal<'data, 'file>,
373 }
374
375 #[derive(Debug)]
376 enum SegmentIteratorInternal<'data, 'file>
377 where
378 'data: 'file,
379 {
380 #[cfg(feature = "coff")]
381 Coff(coff::CoffSegmentIterator<'data, 'file>),
382 #[cfg(feature = "elf")]
383 Elf32(elf::ElfSegmentIterator32<'data, 'file>),
384 #[cfg(feature = "elf")]
385 Elf64(elf::ElfSegmentIterator64<'data, 'file>),
386 #[cfg(feature = "macho")]
387 MachO32(macho::MachOSegmentIterator32<'data, 'file>),
388 #[cfg(feature = "macho")]
389 MachO64(macho::MachOSegmentIterator64<'data, 'file>),
390 #[cfg(feature = "pe")]
391 Pe32(pe::PeSegmentIterator32<'data, 'file>),
392 #[cfg(feature = "pe")]
393 Pe64(pe::PeSegmentIterator64<'data, 'file>),
394 #[cfg(feature = "wasm")]
395 Wasm(wasm::WasmSegmentIterator<'data, 'file>),
396 }
397
398 impl<'data, 'file> Iterator for SegmentIterator<'data, 'file> {
399 type Item = Segment<'data, 'file>;
400
401 fn next(&mut self) -> Option<Self::Item> {
402 next_inner!(self.inner, SegmentIteratorInternal, SegmentInternal)
403 .map(|inner| Segment { inner })
404 }
405 }
406
407 /// A segment of a `File`.
408 pub struct Segment<'data, 'file>
409 where
410 'data: 'file,
411 {
412 inner: SegmentInternal<'data, 'file>,
413 }
414
415 #[derive(Debug)]
416 enum SegmentInternal<'data, 'file>
417 where
418 'data: 'file,
419 {
420 #[cfg(feature = "coff")]
421 Coff(coff::CoffSegment<'data, 'file>),
422 #[cfg(feature = "elf")]
423 Elf32(elf::ElfSegment32<'data, 'file>),
424 #[cfg(feature = "elf")]
425 Elf64(elf::ElfSegment64<'data, 'file>),
426 #[cfg(feature = "macho")]
427 MachO32(macho::MachOSegment32<'data, 'file>),
428 #[cfg(feature = "macho")]
429 MachO64(macho::MachOSegment64<'data, 'file>),
430 #[cfg(feature = "pe")]
431 Pe32(pe::PeSegment32<'data, 'file>),
432 #[cfg(feature = "pe")]
433 Pe64(pe::PeSegment64<'data, 'file>),
434 #[cfg(feature = "wasm")]
435 Wasm(wasm::WasmSegment<'data, 'file>),
436 }
437
438 impl<'data, 'file> fmt::Debug for Segment<'data, 'file> {
439 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
440 // It's painful to do much better than this
441 let mut s = f.debug_struct("Segment");
442 match self.name() {
443 Ok(Some(ref name)) => {
444 s.field("name", name);
445 }
446 Ok(None) => {}
447 Err(_) => {
448 s.field("name", &"<invalid>");
449 }
450 }
451 s.field("address", &self.address())
452 .field("size", &self.size())
453 .finish()
454 }
455 }
456
457 impl<'data, 'file> read::private::Sealed for Segment<'data, 'file> {}
458
459 impl<'data, 'file> ObjectSegment<'data> for Segment<'data, 'file> {
460 fn address(&self) -> u64 {
461 with_inner!(self.inner, SegmentInternal, |x| x.address())
462 }
463
464 fn size(&self) -> u64 {
465 with_inner!(self.inner, SegmentInternal, |x| x.size())
466 }
467
468 fn align(&self) -> u64 {
469 with_inner!(self.inner, SegmentInternal, |x| x.align())
470 }
471
472 fn file_range(&self) -> (u64, u64) {
473 with_inner!(self.inner, SegmentInternal, |x| x.file_range())
474 }
475
476 fn data(&self) -> Result<&'data [u8]> {
477 with_inner!(self.inner, SegmentInternal, |x| x.data())
478 }
479
480 fn data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>> {
481 with_inner!(self.inner, SegmentInternal, |x| x.data_range(address, size))
482 }
483
484 fn name(&self) -> Result<Option<&str>> {
485 with_inner!(self.inner, SegmentInternal, |x| x.name())
486 }
487 }
488
489 /// An iterator of the sections of a `File`.
490 #[derive(Debug)]
491 pub struct SectionIterator<'data, 'file>
492 where
493 'data: 'file,
494 {
495 inner: SectionIteratorInternal<'data, 'file>,
496 }
497
498 // we wrap our enums in a struct so that they are kept private.
499 #[derive(Debug)]
500 enum SectionIteratorInternal<'data, 'file>
501 where
502 'data: 'file,
503 {
504 #[cfg(feature = "coff")]
505 Coff(coff::CoffSectionIterator<'data, 'file>),
506 #[cfg(feature = "elf")]
507 Elf32(elf::ElfSectionIterator32<'data, 'file>),
508 #[cfg(feature = "elf")]
509 Elf64(elf::ElfSectionIterator64<'data, 'file>),
510 #[cfg(feature = "macho")]
511 MachO32(macho::MachOSectionIterator32<'data, 'file>),
512 #[cfg(feature = "macho")]
513 MachO64(macho::MachOSectionIterator64<'data, 'file>),
514 #[cfg(feature = "pe")]
515 Pe32(pe::PeSectionIterator32<'data, 'file>),
516 #[cfg(feature = "pe")]
517 Pe64(pe::PeSectionIterator64<'data, 'file>),
518 #[cfg(feature = "wasm")]
519 Wasm(wasm::WasmSectionIterator<'data, 'file>),
520 }
521
522 impl<'data, 'file> Iterator for SectionIterator<'data, 'file> {
523 type Item = Section<'data, 'file>;
524
525 fn next(&mut self) -> Option<Self::Item> {
526 next_inner!(self.inner, SectionIteratorInternal, SectionInternal)
527 .map(|inner| Section { inner })
528 }
529 }
530
531 /// A Section of a File
532 pub struct Section<'data, 'file>
533 where
534 'data: 'file,
535 {
536 inner: SectionInternal<'data, 'file>,
537 }
538
539 enum SectionInternal<'data, 'file>
540 where
541 'data: 'file,
542 {
543 #[cfg(feature = "coff")]
544 Coff(coff::CoffSection<'data, 'file>),
545 #[cfg(feature = "elf")]
546 Elf32(elf::ElfSection32<'data, 'file>),
547 #[cfg(feature = "elf")]
548 Elf64(elf::ElfSection64<'data, 'file>),
549 #[cfg(feature = "macho")]
550 MachO32(macho::MachOSection32<'data, 'file>),
551 #[cfg(feature = "macho")]
552 MachO64(macho::MachOSection64<'data, 'file>),
553 #[cfg(feature = "pe")]
554 Pe32(pe::PeSection32<'data, 'file>),
555 #[cfg(feature = "pe")]
556 Pe64(pe::PeSection64<'data, 'file>),
557 #[cfg(feature = "wasm")]
558 Wasm(wasm::WasmSection<'data, 'file>),
559 }
560
561 impl<'data, 'file> fmt::Debug for Section<'data, 'file> {
562 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
563 // It's painful to do much better than this
564 let mut s = f.debug_struct("Section");
565 match self.segment_name() {
566 Ok(Some(ref name)) => {
567 s.field("segment", name);
568 }
569 Ok(None) => {}
570 Err(_) => {
571 s.field("segment", &"<invalid>");
572 }
573 }
574 s.field("name", &self.name().unwrap_or("<invalid>"))
575 .field("address", &self.address())
576 .field("size", &self.size())
577 .field("align", &self.align())
578 .field("kind", &self.kind())
579 .field("flags", &self.flags())
580 .finish()
581 }
582 }
583
584 impl<'data, 'file> read::private::Sealed for Section<'data, 'file> {}
585
586 impl<'data, 'file> ObjectSection<'data> for Section<'data, 'file> {
587 type RelocationIterator = RelocationIterator<'data, 'file>;
588
589 fn index(&self) -> SectionIndex {
590 with_inner!(self.inner, SectionInternal, |x| x.index())
591 }
592
593 fn address(&self) -> u64 {
594 with_inner!(self.inner, SectionInternal, |x| x.address())
595 }
596
597 fn size(&self) -> u64 {
598 with_inner!(self.inner, SectionInternal, |x| x.size())
599 }
600
601 fn align(&self) -> u64 {
602 with_inner!(self.inner, SectionInternal, |x| x.align())
603 }
604
605 fn file_range(&self) -> Option<(u64, u64)> {
606 with_inner!(self.inner, SectionInternal, |x| x.file_range())
607 }
608
609 fn data(&self) -> Result<&'data [u8]> {
610 with_inner!(self.inner, SectionInternal, |x| x.data())
611 }
612
613 fn data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>> {
614 with_inner!(self.inner, SectionInternal, |x| x.data_range(address, size))
615 }
616
617 fn compressed_data(&self) -> Result<CompressedData<'data>> {
618 with_inner!(self.inner, SectionInternal, |x| x.compressed_data())
619 }
620
621 fn name(&self) -> Result<&str> {
622 with_inner!(self.inner, SectionInternal, |x| x.name())
623 }
624
625 fn segment_name(&self) -> Result<Option<&str>> {
626 with_inner!(self.inner, SectionInternal, |x| x.segment_name())
627 }
628
629 fn kind(&self) -> SectionKind {
630 with_inner!(self.inner, SectionInternal, |x| x.kind())
631 }
632
633 fn relocations(&self) -> RelocationIterator<'data, 'file> {
634 RelocationIterator {
635 inner: map_inner!(
636 self.inner,
637 SectionInternal,
638 RelocationIteratorInternal,
639 |x| x.relocations()
640 ),
641 }
642 }
643
644 fn flags(&self) -> SectionFlags {
645 with_inner!(self.inner, SectionInternal, |x| x.flags())
646 }
647 }
648
649 /// An iterator of the COMDAT section groups of a `File`.
650 #[derive(Debug)]
651 pub struct ComdatIterator<'data, 'file>
652 where
653 'data: 'file,
654 {
655 inner: ComdatIteratorInternal<'data, 'file>,
656 }
657
658 #[derive(Debug)]
659 enum ComdatIteratorInternal<'data, 'file>
660 where
661 'data: 'file,
662 {
663 #[cfg(feature = "coff")]
664 Coff(coff::CoffComdatIterator<'data, 'file>),
665 #[cfg(feature = "elf")]
666 Elf32(elf::ElfComdatIterator32<'data, 'file>),
667 #[cfg(feature = "elf")]
668 Elf64(elf::ElfComdatIterator64<'data, 'file>),
669 #[cfg(feature = "macho")]
670 MachO32(macho::MachOComdatIterator32<'data, 'file>),
671 #[cfg(feature = "macho")]
672 MachO64(macho::MachOComdatIterator64<'data, 'file>),
673 #[cfg(feature = "pe")]
674 Pe32(pe::PeComdatIterator32<'data, 'file>),
675 #[cfg(feature = "pe")]
676 Pe64(pe::PeComdatIterator64<'data, 'file>),
677 #[cfg(feature = "wasm")]
678 Wasm(wasm::WasmComdatIterator<'data, 'file>),
679 }
680
681 impl<'data, 'file> Iterator for ComdatIterator<'data, 'file> {
682 type Item = Comdat<'data, 'file>;
683
684 fn next(&mut self) -> Option<Self::Item> {
685 next_inner!(self.inner, ComdatIteratorInternal, ComdatInternal)
686 .map(|inner| Comdat { inner })
687 }
688 }
689
690 /// A COMDAT section group of a `File`.
691 pub struct Comdat<'data, 'file>
692 where
693 'data: 'file,
694 {
695 inner: ComdatInternal<'data, 'file>,
696 }
697
698 enum ComdatInternal<'data, 'file>
699 where
700 'data: 'file,
701 {
702 #[cfg(feature = "coff")]
703 Coff(coff::CoffComdat<'data, 'file>),
704 #[cfg(feature = "elf")]
705 Elf32(elf::ElfComdat32<'data, 'file>),
706 #[cfg(feature = "elf")]
707 Elf64(elf::ElfComdat64<'data, 'file>),
708 #[cfg(feature = "macho")]
709 MachO32(macho::MachOComdat32<'data, 'file>),
710 #[cfg(feature = "macho")]
711 MachO64(macho::MachOComdat64<'data, 'file>),
712 #[cfg(feature = "pe")]
713 Pe32(pe::PeComdat32<'data, 'file>),
714 #[cfg(feature = "pe")]
715 Pe64(pe::PeComdat64<'data, 'file>),
716 #[cfg(feature = "wasm")]
717 Wasm(wasm::WasmComdat<'data, 'file>),
718 }
719
720 impl<'data, 'file> fmt::Debug for Comdat<'data, 'file> {
721 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
722 let mut s = f.debug_struct("Comdat");
723 s.field("symbol", &self.symbol())
724 .field("name", &self.name().unwrap_or("<invalid>"))
725 .field("kind", &self.kind())
726 .finish()
727 }
728 }
729
730 impl<'data, 'file> read::private::Sealed for Comdat<'data, 'file> {}
731
732 impl<'data, 'file> ObjectComdat<'data> for Comdat<'data, 'file> {
733 type SectionIterator = ComdatSectionIterator<'data, 'file>;
734
735 fn kind(&self) -> ComdatKind {
736 with_inner!(self.inner, ComdatInternal, |x| x.kind())
737 }
738
739 fn symbol(&self) -> SymbolIndex {
740 with_inner!(self.inner, ComdatInternal, |x| x.symbol())
741 }
742
743 fn name(&self) -> Result<&str> {
744 with_inner!(self.inner, ComdatInternal, |x| x.name())
745 }
746
747 fn sections(&self) -> ComdatSectionIterator<'data, 'file> {
748 ComdatSectionIterator {
749 inner: map_inner!(
750 self.inner,
751 ComdatInternal,
752 ComdatSectionIteratorInternal,
753 |x| x.sections()
754 ),
755 }
756 }
757 }
758
759 /// An iterator over COMDAT section entries.
760 #[derive(Debug)]
761 pub struct ComdatSectionIterator<'data, 'file>
762 where
763 'data: 'file,
764 {
765 inner: ComdatSectionIteratorInternal<'data, 'file>,
766 }
767
768 #[derive(Debug)]
769 enum ComdatSectionIteratorInternal<'data, 'file>
770 where
771 'data: 'file,
772 {
773 #[cfg(feature = "coff")]
774 Coff(coff::CoffComdatSectionIterator<'data, 'file>),
775 #[cfg(feature = "elf")]
776 Elf32(elf::ElfComdatSectionIterator32<'data, 'file>),
777 #[cfg(feature = "elf")]
778 Elf64(elf::ElfComdatSectionIterator64<'data, 'file>),
779 #[cfg(feature = "macho")]
780 MachO32(macho::MachOComdatSectionIterator32<'data, 'file>),
781 #[cfg(feature = "macho")]
782 MachO64(macho::MachOComdatSectionIterator64<'data, 'file>),
783 #[cfg(feature = "pe")]
784 Pe32(pe::PeComdatSectionIterator32<'data, 'file>),
785 #[cfg(feature = "pe")]
786 Pe64(pe::PeComdatSectionIterator64<'data, 'file>),
787 #[cfg(feature = "wasm")]
788 Wasm(wasm::WasmComdatSectionIterator<'data, 'file>),
789 }
790
791 impl<'data, 'file> Iterator for ComdatSectionIterator<'data, 'file> {
792 type Item = SectionIndex;
793
794 fn next(&mut self) -> Option<Self::Item> {
795 with_inner_mut!(self.inner, ComdatSectionIteratorInternal, |x| x.next())
796 }
797 }
798
799 /// A symbol table.
800 #[derive(Debug)]
801 pub struct SymbolTable<'data, 'file>
802 where
803 'data: 'file,
804 {
805 inner: SymbolTableInternal<'data, 'file>,
806 }
807
808 #[derive(Debug)]
809 enum SymbolTableInternal<'data, 'file>
810 where
811 'data: 'file,
812 {
813 #[cfg(feature = "coff")]
814 Coff(coff::CoffSymbolTable<'data, 'file>),
815 #[cfg(feature = "elf")]
816 Elf32(elf::ElfSymbolTable32<'data, 'file>),
817 #[cfg(feature = "elf")]
818 Elf64(elf::ElfSymbolTable64<'data, 'file>),
819 #[cfg(feature = "macho")]
820 MachO32(macho::MachOSymbolTable32<'data, 'file>),
821 #[cfg(feature = "macho")]
822 MachO64(macho::MachOSymbolTable64<'data, 'file>),
823 #[cfg(feature = "pe")]
824 Pe32(coff::CoffSymbolTable<'data, 'file>),
825 #[cfg(feature = "pe")]
826 Pe64(coff::CoffSymbolTable<'data, 'file>),
827 #[cfg(feature = "wasm")]
828 Wasm(wasm::WasmSymbolTable<'data, 'file>),
829 }
830
831 impl<'data, 'file> read::private::Sealed for SymbolTable<'data, 'file> {}
832
833 impl<'data, 'file> ObjectSymbolTable<'data> for SymbolTable<'data, 'file> {
834 type Symbol = Symbol<'data, 'file>;
835 type SymbolIterator = SymbolIterator<'data, 'file>;
836
837 fn symbols(&self) -> Self::SymbolIterator {
838 SymbolIterator {
839 inner: map_inner!(
840 self.inner,
841 SymbolTableInternal,
842 SymbolIteratorInternal,
843 |x| x.symbols()
844 ),
845 }
846 }
847
848 fn symbol_by_index(&self, index: SymbolIndex) -> Result<Self::Symbol> {
849 map_inner_option!(self.inner, SymbolTableInternal, SymbolInternal, |x| x
850 .symbol_by_index(index))
851 .map(|inner| Symbol { inner })
852 }
853 }
854
855 /// An iterator over symbol table entries.
856 #[derive(Debug)]
857 pub struct SymbolIterator<'data, 'file>
858 where
859 'data: 'file,
860 {
861 inner: SymbolIteratorInternal<'data, 'file>,
862 }
863
864 #[derive(Debug)]
865 enum SymbolIteratorInternal<'data, 'file>
866 where
867 'data: 'file,
868 {
869 #[cfg(feature = "coff")]
870 Coff(coff::CoffSymbolIterator<'data, 'file>),
871 #[cfg(feature = "elf")]
872 Elf32(elf::ElfSymbolIterator32<'data, 'file>),
873 #[cfg(feature = "elf")]
874 Elf64(elf::ElfSymbolIterator64<'data, 'file>),
875 #[cfg(feature = "macho")]
876 MachO32(macho::MachOSymbolIterator32<'data, 'file>),
877 #[cfg(feature = "macho")]
878 MachO64(macho::MachOSymbolIterator64<'data, 'file>),
879 #[cfg(feature = "pe")]
880 Pe32(coff::CoffSymbolIterator<'data, 'file>),
881 #[cfg(feature = "pe")]
882 Pe64(coff::CoffSymbolIterator<'data, 'file>),
883 #[cfg(feature = "wasm")]
884 Wasm(wasm::WasmSymbolIterator<'data, 'file>),
885 }
886
887 impl<'data, 'file> Iterator for SymbolIterator<'data, 'file> {
888 type Item = Symbol<'data, 'file>;
889
890 fn next(&mut self) -> Option<Self::Item> {
891 next_inner!(self.inner, SymbolIteratorInternal, SymbolInternal)
892 .map(|inner| Symbol { inner })
893 }
894 }
895
896 /// A symbol table entry.
897 pub struct Symbol<'data, 'file>
898 where
899 'data: 'file,
900 {
901 inner: SymbolInternal<'data, 'file>,
902 }
903
904 enum SymbolInternal<'data, 'file>
905 where
906 'data: 'file,
907 {
908 #[cfg(feature = "coff")]
909 Coff(coff::CoffSymbol<'data, 'file>),
910 #[cfg(feature = "elf")]
911 Elf32(elf::ElfSymbol32<'data, 'file>),
912 #[cfg(feature = "elf")]
913 Elf64(elf::ElfSymbol64<'data, 'file>),
914 #[cfg(feature = "macho")]
915 MachO32(macho::MachOSymbol32<'data, 'file>),
916 #[cfg(feature = "macho")]
917 MachO64(macho::MachOSymbol64<'data, 'file>),
918 #[cfg(feature = "pe")]
919 Pe32(coff::CoffSymbol<'data, 'file>),
920 #[cfg(feature = "pe")]
921 Pe64(coff::CoffSymbol<'data, 'file>),
922 #[cfg(feature = "wasm")]
923 Wasm(wasm::WasmSymbol<'data, 'file>),
924 }
925
926 impl<'data, 'file> fmt::Debug for Symbol<'data, 'file> {
927 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
928 f.debug_struct("Symbol")
929 .field("name", &self.name().unwrap_or("<invalid>"))
930 .field("address", &self.address())
931 .field("size", &self.size())
932 .field("kind", &self.kind())
933 .field("section", &self.section())
934 .field("scope", &self.scope())
935 .field("weak", &self.is_weak())
936 .field("flags", &self.flags())
937 .finish()
938 }
939 }
940
941 impl<'data, 'file> read::private::Sealed for Symbol<'data, 'file> {}
942
943 impl<'data, 'file> ObjectSymbol<'data> for Symbol<'data, 'file> {
944 fn index(&self) -> SymbolIndex {
945 with_inner!(self.inner, SymbolInternal, |x| x.index())
946 }
947
948 fn name(&self) -> Result<&'data str> {
949 with_inner!(self.inner, SymbolInternal, |x| x.name())
950 }
951
952 fn address(&self) -> u64 {
953 with_inner!(self.inner, SymbolInternal, |x| x.address())
954 }
955
956 fn size(&self) -> u64 {
957 with_inner!(self.inner, SymbolInternal, |x| x.size())
958 }
959
960 fn kind(&self) -> SymbolKind {
961 with_inner!(self.inner, SymbolInternal, |x| x.kind())
962 }
963
964 fn section(&self) -> SymbolSection {
965 with_inner!(self.inner, SymbolInternal, |x| x.section())
966 }
967
968 fn is_undefined(&self) -> bool {
969 with_inner!(self.inner, SymbolInternal, |x| x.is_undefined())
970 }
971
972 fn is_definition(&self) -> bool {
973 with_inner!(self.inner, SymbolInternal, |x| x.is_definition())
974 }
975
976 fn is_common(&self) -> bool {
977 with_inner!(self.inner, SymbolInternal, |x| x.is_common())
978 }
979
980 fn is_weak(&self) -> bool {
981 with_inner!(self.inner, SymbolInternal, |x| x.is_weak())
982 }
983
984 fn scope(&self) -> SymbolScope {
985 with_inner!(self.inner, SymbolInternal, |x| x.scope())
986 }
987
988 fn is_global(&self) -> bool {
989 with_inner!(self.inner, SymbolInternal, |x| x.is_global())
990 }
991
992 fn is_local(&self) -> bool {
993 with_inner!(self.inner, SymbolInternal, |x| x.is_local())
994 }
995
996 fn flags(&self) -> SymbolFlags<SectionIndex> {
997 with_inner!(self.inner, SymbolInternal, |x| x.flags())
998 }
999 }
1000
1001 /// An iterator over relocation entries
1002 #[derive(Debug)]
1003 pub struct RelocationIterator<'data, 'file>
1004 where
1005 'data: 'file,
1006 {
1007 inner: RelocationIteratorInternal<'data, 'file>,
1008 }
1009
1010 #[derive(Debug)]
1011 enum RelocationIteratorInternal<'data, 'file>
1012 where
1013 'data: 'file,
1014 {
1015 #[cfg(feature = "coff")]
1016 Coff(coff::CoffRelocationIterator<'data, 'file>),
1017 #[cfg(feature = "elf")]
1018 Elf32(elf::ElfRelocationIterator32<'data, 'file>),
1019 #[cfg(feature = "elf")]
1020 Elf64(elf::ElfRelocationIterator64<'data, 'file>),
1021 #[cfg(feature = "macho")]
1022 MachO32(macho::MachORelocationIterator32<'data, 'file>),
1023 #[cfg(feature = "macho")]
1024 MachO64(macho::MachORelocationIterator64<'data, 'file>),
1025 #[cfg(feature = "pe")]
1026 Pe32(pe::PeRelocationIterator<'data, 'file>),
1027 #[cfg(feature = "pe")]
1028 Pe64(pe::PeRelocationIterator<'data, 'file>),
1029 #[cfg(feature = "wasm")]
1030 Wasm(wasm::WasmRelocationIterator<'data, 'file>),
1031 }
1032
1033 impl<'data, 'file> Iterator for RelocationIterator<'data, 'file> {
1034 type Item = (u64, Relocation);
1035
1036 fn next(&mut self) -> Option<Self::Item> {
1037 with_inner_mut!(self.inner, RelocationIteratorInternal, |x| x.next())
1038 }
1039 }