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