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