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. parse(data: &'data [u8]) -> Result<Self>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. format(&self) -> BinaryFormat221 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 architecture(&self) -> Architecture253 fn architecture(&self) -> Architecture { 254 with_inner!(self.inner, FileInternal, |x| x.architecture()) 255 } 256 is_little_endian(&self) -> bool257 fn is_little_endian(&self) -> bool { 258 with_inner!(self.inner, FileInternal, |x| x.is_little_endian()) 259 } 260 is_64(&self) -> bool261 fn is_64(&self) -> bool { 262 with_inner!(self.inner, FileInternal, |x| x.is_64()) 263 } 264 segments(&'file self) -> SegmentIterator<'data, 'file>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 section_by_name(&'file self, section_name: &str) -> Option<Section<'data, 'file>>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 section_by_index(&'file self, index: SectionIndex) -> Result<Section<'data, 'file>>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 sections(&'file self) -> SectionIterator<'data, 'file>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 comdats(&'file self) -> ComdatIterator<'data, 'file>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 symbol_by_index(&'file self, index: SymbolIndex) -> Result<Symbol<'data, 'file>>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 symbols(&'file self) -> SymbolIterator<'data, 'file>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 symbol_table(&'file self) -> Option<SymbolTable<'data, 'file>>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 dynamic_symbols(&'file self) -> SymbolIterator<'data, 'file>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 dynamic_symbol_table(&'file self) -> Option<SymbolTable<'data, 'file>>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 symbol_map(&self) -> SymbolMap<SymbolMapName<'data>>330 fn symbol_map(&self) -> SymbolMap<SymbolMapName<'data>> { 331 with_inner!(self.inner, FileInternal, |x| x.symbol_map()) 332 } 333 object_map(&self) -> ObjectMap<'data>334 fn object_map(&self) -> ObjectMap<'data> { 335 with_inner!(self.inner, FileInternal, |x| x.object_map()) 336 } 337 has_debug_symbols(&self) -> bool338 fn has_debug_symbols(&self) -> bool { 339 with_inner!(self.inner, FileInternal, |x| x.has_debug_symbols()) 340 } 341 342 #[inline] mach_uuid(&self) -> Result<Option<[u8; 16]>>343 fn mach_uuid(&self) -> Result<Option<[u8; 16]>> { 344 with_inner!(self.inner, FileInternal, |x| x.mach_uuid()) 345 } 346 347 #[inline] build_id(&self) -> Result<Option<&'data [u8]>>348 fn build_id(&self) -> Result<Option<&'data [u8]>> { 349 with_inner!(self.inner, FileInternal, |x| x.build_id()) 350 } 351 352 #[inline] gnu_debuglink(&self) -> Result<Option<(&'data [u8], u32)>>353 fn gnu_debuglink(&self) -> Result<Option<(&'data [u8], u32)>> { 354 with_inner!(self.inner, FileInternal, |x| x.gnu_debuglink()) 355 } 356 entry(&self) -> u64357 fn entry(&self) -> u64 { 358 with_inner!(self.inner, FileInternal, |x| x.entry()) 359 } 360 flags(&self) -> FileFlags361 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 next(&mut self) -> Option<Self::Item>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> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result439 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> { address(&self) -> u64460 fn address(&self) -> u64 { 461 with_inner!(self.inner, SegmentInternal, |x| x.address()) 462 } 463 size(&self) -> u64464 fn size(&self) -> u64 { 465 with_inner!(self.inner, SegmentInternal, |x| x.size()) 466 } 467 align(&self) -> u64468 fn align(&self) -> u64 { 469 with_inner!(self.inner, SegmentInternal, |x| x.align()) 470 } 471 file_range(&self) -> (u64, u64)472 fn file_range(&self) -> (u64, u64) { 473 with_inner!(self.inner, SegmentInternal, |x| x.file_range()) 474 } 475 data(&self) -> Result<&'data [u8]>476 fn data(&self) -> Result<&'data [u8]> { 477 with_inner!(self.inner, SegmentInternal, |x| x.data()) 478 } 479 data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>>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 name(&self) -> Result<Option<&str>>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 next(&mut self) -> Option<Self::Item>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> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result562 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 index(&self) -> SectionIndex589 fn index(&self) -> SectionIndex { 590 with_inner!(self.inner, SectionInternal, |x| x.index()) 591 } 592 address(&self) -> u64593 fn address(&self) -> u64 { 594 with_inner!(self.inner, SectionInternal, |x| x.address()) 595 } 596 size(&self) -> u64597 fn size(&self) -> u64 { 598 with_inner!(self.inner, SectionInternal, |x| x.size()) 599 } 600 align(&self) -> u64601 fn align(&self) -> u64 { 602 with_inner!(self.inner, SectionInternal, |x| x.align()) 603 } 604 file_range(&self) -> Option<(u64, u64)>605 fn file_range(&self) -> Option<(u64, u64)> { 606 with_inner!(self.inner, SectionInternal, |x| x.file_range()) 607 } 608 data(&self) -> Result<&'data [u8]>609 fn data(&self) -> Result<&'data [u8]> { 610 with_inner!(self.inner, SectionInternal, |x| x.data()) 611 } 612 data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>>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 compressed_data(&self) -> Result<CompressedData<'data>>617 fn compressed_data(&self) -> Result<CompressedData<'data>> { 618 with_inner!(self.inner, SectionInternal, |x| x.compressed_data()) 619 } 620 name(&self) -> Result<&str>621 fn name(&self) -> Result<&str> { 622 with_inner!(self.inner, SectionInternal, |x| x.name()) 623 } 624 segment_name(&self) -> Result<Option<&str>>625 fn segment_name(&self) -> Result<Option<&str>> { 626 with_inner!(self.inner, SectionInternal, |x| x.segment_name()) 627 } 628 kind(&self) -> SectionKind629 fn kind(&self) -> SectionKind { 630 with_inner!(self.inner, SectionInternal, |x| x.kind()) 631 } 632 relocations(&self) -> RelocationIterator<'data, 'file>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 flags(&self) -> SectionFlags644 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 next(&mut self) -> Option<Self::Item>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> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result721 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 kind(&self) -> ComdatKind735 fn kind(&self) -> ComdatKind { 736 with_inner!(self.inner, ComdatInternal, |x| x.kind()) 737 } 738 symbol(&self) -> SymbolIndex739 fn symbol(&self) -> SymbolIndex { 740 with_inner!(self.inner, ComdatInternal, |x| x.symbol()) 741 } 742 name(&self) -> Result<&str>743 fn name(&self) -> Result<&str> { 744 with_inner!(self.inner, ComdatInternal, |x| x.name()) 745 } 746 sections(&self) -> ComdatSectionIterator<'data, 'file>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 next(&mut self) -> Option<Self::Item>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 symbols(&self) -> Self::SymbolIterator837 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 symbol_by_index(&self, index: SymbolIndex) -> Result<Self::Symbol>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 next(&mut self) -> Option<Self::Item>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> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result927 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> { index(&self) -> SymbolIndex944 fn index(&self) -> SymbolIndex { 945 with_inner!(self.inner, SymbolInternal, |x| x.index()) 946 } 947 name(&self) -> Result<&'data str>948 fn name(&self) -> Result<&'data str> { 949 with_inner!(self.inner, SymbolInternal, |x| x.name()) 950 } 951 address(&self) -> u64952 fn address(&self) -> u64 { 953 with_inner!(self.inner, SymbolInternal, |x| x.address()) 954 } 955 size(&self) -> u64956 fn size(&self) -> u64 { 957 with_inner!(self.inner, SymbolInternal, |x| x.size()) 958 } 959 kind(&self) -> SymbolKind960 fn kind(&self) -> SymbolKind { 961 with_inner!(self.inner, SymbolInternal, |x| x.kind()) 962 } 963 section(&self) -> SymbolSection964 fn section(&self) -> SymbolSection { 965 with_inner!(self.inner, SymbolInternal, |x| x.section()) 966 } 967 is_undefined(&self) -> bool968 fn is_undefined(&self) -> bool { 969 with_inner!(self.inner, SymbolInternal, |x| x.is_undefined()) 970 } 971 is_definition(&self) -> bool972 fn is_definition(&self) -> bool { 973 with_inner!(self.inner, SymbolInternal, |x| x.is_definition()) 974 } 975 is_common(&self) -> bool976 fn is_common(&self) -> bool { 977 with_inner!(self.inner, SymbolInternal, |x| x.is_common()) 978 } 979 is_weak(&self) -> bool980 fn is_weak(&self) -> bool { 981 with_inner!(self.inner, SymbolInternal, |x| x.is_weak()) 982 } 983 scope(&self) -> SymbolScope984 fn scope(&self) -> SymbolScope { 985 with_inner!(self.inner, SymbolInternal, |x| x.scope()) 986 } 987 is_global(&self) -> bool988 fn is_global(&self) -> bool { 989 with_inner!(self.inner, SymbolInternal, |x| x.is_global()) 990 } 991 is_local(&self) -> bool992 fn is_local(&self) -> bool { 993 with_inner!(self.inner, SymbolInternal, |x| x.is_local()) 994 } 995 flags(&self) -> SymbolFlags<SectionIndex>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 next(&mut self) -> Option<Self::Item>1036 fn next(&mut self) -> Option<Self::Item> { 1037 with_inner_mut!(self.inner, RelocationIteratorInternal, |x| x.next()) 1038 } 1039 } 1040