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