1 use alloc::vec::Vec; 2 use core::convert::TryInto; 3 use core::fmt::Debug; 4 use core::{mem, str}; 5 6 use crate::read::{ 7 self, util, Architecture, ByteString, Bytes, Error, Export, FileFlags, Import, Object, 8 ReadError, ReadRef, SectionIndex, StringTable, SymbolIndex, 9 }; 10 use crate::{elf, endian, Endian, Endianness, Pod, U32}; 11 12 use super::{ 13 CompressionHeader, Dyn, ElfComdat, ElfComdatIterator, ElfDynamicRelocationIterator, ElfSection, 14 ElfSectionIterator, ElfSegment, ElfSegmentIterator, ElfSymbol, ElfSymbolIterator, 15 ElfSymbolTable, NoteHeader, ProgramHeader, Rel, Rela, RelocationSections, SectionHeader, 16 SectionTable, Sym, SymbolTable, 17 }; 18 19 /// A 32-bit ELF object file. 20 pub type ElfFile32<'data, Endian = Endianness, R = &'data [u8]> = 21 ElfFile<'data, elf::FileHeader32<Endian>, R>; 22 /// A 64-bit ELF object file. 23 pub type ElfFile64<'data, Endian = Endianness, R = &'data [u8]> = 24 ElfFile<'data, elf::FileHeader64<Endian>, R>; 25 26 /// A partially parsed ELF file. 27 /// 28 /// Most of the functionality of this type is provided by the `Object` trait implementation. 29 #[derive(Debug)] 30 pub struct ElfFile<'data, Elf, R = &'data [u8]> 31 where 32 Elf: FileHeader, 33 R: ReadRef<'data>, 34 { 35 pub(super) endian: Elf::Endian, 36 pub(super) data: R, 37 pub(super) header: &'data Elf, 38 pub(super) segments: &'data [Elf::ProgramHeader], 39 pub(super) sections: SectionTable<'data, Elf, R>, 40 pub(super) relocations: RelocationSections, 41 pub(super) symbols: SymbolTable<'data, Elf, R>, 42 pub(super) dynamic_symbols: SymbolTable<'data, Elf, R>, 43 } 44 45 impl<'data, Elf, R> ElfFile<'data, Elf, R> 46 where 47 Elf: FileHeader, 48 R: ReadRef<'data>, 49 { 50 /// Parse the raw ELF file data. parse(data: R) -> read::Result<Self>51 pub fn parse(data: R) -> read::Result<Self> { 52 let header = Elf::parse(data)?; 53 let endian = header.endian()?; 54 let segments = header.program_headers(endian, data)?; 55 let sections = header.sections(endian, data)?; 56 let symbols = sections.symbols(endian, data, elf::SHT_SYMTAB)?; 57 // TODO: get dynamic symbols from DT_SYMTAB if there are no sections 58 let dynamic_symbols = sections.symbols(endian, data, elf::SHT_DYNSYM)?; 59 // The API we provide requires a mapping from section to relocations, so build it now. 60 let relocations = sections.relocation_sections(endian, symbols.section())?; 61 62 Ok(ElfFile { 63 endian, 64 data, 65 header, 66 segments, 67 sections, 68 relocations, 69 symbols, 70 dynamic_symbols, 71 }) 72 } 73 74 /// Returns the endianness. endian(&self) -> Elf::Endian75 pub fn endian(&self) -> Elf::Endian { 76 self.endian 77 } 78 79 /// Returns the raw data. data(&self) -> R80 pub fn data(&self) -> R { 81 self.data 82 } 83 84 /// Returns the raw ELF file header. raw_header(&self) -> &'data Elf85 pub fn raw_header(&self) -> &'data Elf { 86 self.header 87 } 88 89 /// Returns the raw ELF segments. raw_segments(&self) -> &'data [Elf::ProgramHeader]90 pub fn raw_segments(&self) -> &'data [Elf::ProgramHeader] { 91 self.segments 92 } 93 raw_section_by_name<'file>( &'file self, section_name: &str, ) -> Option<ElfSection<'data, 'file, Elf, R>>94 fn raw_section_by_name<'file>( 95 &'file self, 96 section_name: &str, 97 ) -> Option<ElfSection<'data, 'file, Elf, R>> { 98 self.sections 99 .section_by_name(self.endian, section_name.as_bytes()) 100 .map(|(index, section)| ElfSection { 101 file: self, 102 index: SectionIndex(index), 103 section, 104 }) 105 } 106 107 #[cfg(feature = "compression")] zdebug_section_by_name<'file>( &'file self, section_name: &str, ) -> Option<ElfSection<'data, 'file, Elf, R>>108 fn zdebug_section_by_name<'file>( 109 &'file self, 110 section_name: &str, 111 ) -> Option<ElfSection<'data, 'file, Elf, R>> { 112 if !section_name.starts_with(".debug_") { 113 return None; 114 } 115 self.raw_section_by_name(&format!(".zdebug_{}", §ion_name[7..])) 116 } 117 118 #[cfg(not(feature = "compression"))] zdebug_section_by_name<'file>( &'file self, _section_name: &str, ) -> Option<ElfSection<'data, 'file, Elf, R>>119 fn zdebug_section_by_name<'file>( 120 &'file self, 121 _section_name: &str, 122 ) -> Option<ElfSection<'data, 'file, Elf, R>> { 123 None 124 } 125 } 126 127 impl<'data, Elf, R> read::private::Sealed for ElfFile<'data, Elf, R> 128 where 129 Elf: FileHeader, 130 R: ReadRef<'data>, 131 { 132 } 133 134 impl<'data, 'file, Elf, R> Object<'data, 'file> for ElfFile<'data, Elf, R> 135 where 136 'data: 'file, 137 Elf: FileHeader, 138 R: 'file + ReadRef<'data>, 139 { 140 type Segment = ElfSegment<'data, 'file, Elf, R>; 141 type SegmentIterator = ElfSegmentIterator<'data, 'file, Elf, R>; 142 type Section = ElfSection<'data, 'file, Elf, R>; 143 type SectionIterator = ElfSectionIterator<'data, 'file, Elf, R>; 144 type Comdat = ElfComdat<'data, 'file, Elf, R>; 145 type ComdatIterator = ElfComdatIterator<'data, 'file, Elf, R>; 146 type Symbol = ElfSymbol<'data, 'file, Elf, R>; 147 type SymbolIterator = ElfSymbolIterator<'data, 'file, Elf, R>; 148 type SymbolTable = ElfSymbolTable<'data, 'file, Elf, R>; 149 type DynamicRelocationIterator = ElfDynamicRelocationIterator<'data, 'file, Elf, R>; 150 architecture(&self) -> Architecture151 fn architecture(&self) -> Architecture { 152 match ( 153 self.header.e_machine(self.endian), 154 self.header.is_class_64(), 155 ) { 156 (elf::EM_AARCH64, _) => Architecture::Aarch64, 157 (elf::EM_ARM, _) => Architecture::Arm, 158 (elf::EM_AVR, _) => Architecture::Avr, 159 (elf::EM_BPF, _) => Architecture::Bpf, 160 (elf::EM_386, _) => Architecture::I386, 161 (elf::EM_X86_64, false) => Architecture::X86_64_X32, 162 (elf::EM_X86_64, true) => Architecture::X86_64, 163 (elf::EM_HEXAGON, _) => Architecture::Hexagon, 164 (elf::EM_MIPS, false) => Architecture::Mips, 165 (elf::EM_MIPS, true) => Architecture::Mips64, 166 (elf::EM_MSP430, _) => Architecture::Msp430, 167 (elf::EM_PPC, _) => Architecture::PowerPc, 168 (elf::EM_PPC64, _) => Architecture::PowerPc64, 169 (elf::EM_RISCV, false) => Architecture::Riscv32, 170 (elf::EM_RISCV, true) => Architecture::Riscv64, 171 // This is either s390 or s390x, depending on the ELF class. 172 // We only support the 64-bit variant s390x here. 173 (elf::EM_S390, true) => Architecture::S390x, 174 (elf::EM_SPARCV9, true) => Architecture::Sparc64, 175 _ => Architecture::Unknown, 176 } 177 } 178 179 #[inline] is_little_endian(&self) -> bool180 fn is_little_endian(&self) -> bool { 181 self.header.is_little_endian() 182 } 183 184 #[inline] is_64(&self) -> bool185 fn is_64(&self) -> bool { 186 self.header.is_class_64() 187 } 188 segments(&'file self) -> ElfSegmentIterator<'data, 'file, Elf, R>189 fn segments(&'file self) -> ElfSegmentIterator<'data, 'file, Elf, R> { 190 ElfSegmentIterator { 191 file: self, 192 iter: self.segments.iter(), 193 } 194 } 195 section_by_name( &'file self, section_name: &str, ) -> Option<ElfSection<'data, 'file, Elf, R>>196 fn section_by_name( 197 &'file self, 198 section_name: &str, 199 ) -> Option<ElfSection<'data, 'file, Elf, R>> { 200 self.raw_section_by_name(section_name) 201 .or_else(|| self.zdebug_section_by_name(section_name)) 202 } 203 section_by_index( &'file self, index: SectionIndex, ) -> read::Result<ElfSection<'data, 'file, Elf, R>>204 fn section_by_index( 205 &'file self, 206 index: SectionIndex, 207 ) -> read::Result<ElfSection<'data, 'file, Elf, R>> { 208 let section = self.sections.section(index.0)?; 209 Ok(ElfSection { 210 file: self, 211 index, 212 section, 213 }) 214 } 215 sections(&'file self) -> ElfSectionIterator<'data, 'file, Elf, R>216 fn sections(&'file self) -> ElfSectionIterator<'data, 'file, Elf, R> { 217 ElfSectionIterator { 218 file: self, 219 iter: self.sections.iter().enumerate(), 220 } 221 } 222 comdats(&'file self) -> ElfComdatIterator<'data, 'file, Elf, R>223 fn comdats(&'file self) -> ElfComdatIterator<'data, 'file, Elf, R> { 224 ElfComdatIterator { 225 file: self, 226 iter: self.sections.iter().enumerate(), 227 } 228 } 229 symbol_by_index( &'file self, index: SymbolIndex, ) -> read::Result<ElfSymbol<'data, 'file, Elf, R>>230 fn symbol_by_index( 231 &'file self, 232 index: SymbolIndex, 233 ) -> read::Result<ElfSymbol<'data, 'file, Elf, R>> { 234 let symbol = self.symbols.symbol(index.0)?; 235 Ok(ElfSymbol { 236 endian: self.endian, 237 symbols: &self.symbols, 238 index, 239 symbol, 240 }) 241 } 242 symbols(&'file self) -> ElfSymbolIterator<'data, 'file, Elf, R>243 fn symbols(&'file self) -> ElfSymbolIterator<'data, 'file, Elf, R> { 244 ElfSymbolIterator { 245 endian: self.endian, 246 symbols: &self.symbols, 247 index: 0, 248 } 249 } 250 symbol_table(&'file self) -> Option<ElfSymbolTable<'data, 'file, Elf, R>>251 fn symbol_table(&'file self) -> Option<ElfSymbolTable<'data, 'file, Elf, R>> { 252 Some(ElfSymbolTable { 253 endian: self.endian, 254 symbols: &self.symbols, 255 }) 256 } 257 dynamic_symbols(&'file self) -> ElfSymbolIterator<'data, 'file, Elf, R>258 fn dynamic_symbols(&'file self) -> ElfSymbolIterator<'data, 'file, Elf, R> { 259 ElfSymbolIterator { 260 endian: self.endian, 261 symbols: &self.dynamic_symbols, 262 index: 0, 263 } 264 } 265 dynamic_symbol_table(&'file self) -> Option<ElfSymbolTable<'data, 'file, Elf, R>>266 fn dynamic_symbol_table(&'file self) -> Option<ElfSymbolTable<'data, 'file, Elf, R>> { 267 Some(ElfSymbolTable { 268 endian: self.endian, 269 symbols: &self.dynamic_symbols, 270 }) 271 } 272 dynamic_relocations( &'file self, ) -> Option<ElfDynamicRelocationIterator<'data, 'file, Elf, R>>273 fn dynamic_relocations( 274 &'file self, 275 ) -> Option<ElfDynamicRelocationIterator<'data, 'file, Elf, R>> { 276 Some(ElfDynamicRelocationIterator { 277 section_index: 1, 278 file: self, 279 relocations: None, 280 }) 281 } 282 283 /// Get the imported symbols. imports(&self) -> read::Result<Vec<Import<'data>>>284 fn imports(&self) -> read::Result<Vec<Import<'data>>> { 285 let mut imports = Vec::new(); 286 for symbol in self.dynamic_symbols.iter() { 287 if symbol.is_undefined(self.endian) { 288 let name = symbol.name(self.endian, self.dynamic_symbols.strings())?; 289 if !name.is_empty() { 290 // TODO: use symbol versioning to determine library 291 imports.push(Import { 292 name: ByteString(name), 293 library: ByteString(&[]), 294 }); 295 } 296 } 297 } 298 Ok(imports) 299 } 300 301 /// Get the exported symbols. exports(&self) -> read::Result<Vec<Export<'data>>>302 fn exports(&self) -> read::Result<Vec<Export<'data>>> { 303 let mut exports = Vec::new(); 304 for symbol in self.dynamic_symbols.iter() { 305 if symbol.is_definition(self.endian) { 306 let name = symbol.name(self.endian, self.dynamic_symbols.strings())?; 307 let address = symbol.st_value(self.endian).into(); 308 exports.push(Export { 309 name: ByteString(name), 310 address, 311 }); 312 } 313 } 314 Ok(exports) 315 } 316 has_debug_symbols(&self) -> bool317 fn has_debug_symbols(&self) -> bool { 318 for section in self.sections.iter() { 319 if let Ok(name) = self.sections.section_name(self.endian, section) { 320 if name == b".debug_info" || name == b".zdebug_info" { 321 return true; 322 } 323 } 324 } 325 false 326 } 327 build_id(&self) -> read::Result<Option<&'data [u8]>>328 fn build_id(&self) -> read::Result<Option<&'data [u8]>> { 329 let endian = self.endian; 330 // Use section headers if present, otherwise use program headers. 331 if !self.sections.is_empty() { 332 for section in self.sections.iter() { 333 if let Some(mut notes) = section.notes(endian, self.data)? { 334 while let Some(note) = notes.next()? { 335 if note.name() == elf::ELF_NOTE_GNU 336 && note.n_type(endian) == elf::NT_GNU_BUILD_ID 337 { 338 return Ok(Some(note.desc())); 339 } 340 } 341 } 342 } 343 } else { 344 for segment in self.segments { 345 if let Some(mut notes) = segment.notes(endian, self.data)? { 346 while let Some(note) = notes.next()? { 347 if note.name() == elf::ELF_NOTE_GNU 348 && note.n_type(endian) == elf::NT_GNU_BUILD_ID 349 { 350 return Ok(Some(note.desc())); 351 } 352 } 353 } 354 } 355 } 356 Ok(None) 357 } 358 gnu_debuglink(&self) -> read::Result<Option<(&'data [u8], u32)>>359 fn gnu_debuglink(&self) -> read::Result<Option<(&'data [u8], u32)>> { 360 let section = match self.raw_section_by_name(".gnu_debuglink") { 361 Some(section) => section, 362 None => return Ok(None), 363 }; 364 let data = section 365 .section 366 .data(self.endian, self.data) 367 .read_error("Invalid ELF .gnu_debuglink section offset or size") 368 .map(Bytes)?; 369 let filename = data 370 .read_string_at(0) 371 .read_error("Missing ELF .gnu_debuglink filename")?; 372 let crc_offset = util::align(filename.len() + 1, 4); 373 let crc = data 374 .read_at::<U32<_>>(crc_offset) 375 .read_error("Missing ELF .gnu_debuglink crc")? 376 .get(self.endian); 377 Ok(Some((filename, crc))) 378 } 379 gnu_debugaltlink(&self) -> read::Result<Option<(&'data [u8], &'data [u8])>>380 fn gnu_debugaltlink(&self) -> read::Result<Option<(&'data [u8], &'data [u8])>> { 381 let section = match self.raw_section_by_name(".gnu_debugaltlink") { 382 Some(section) => section, 383 None => return Ok(None), 384 }; 385 let mut data = section 386 .section 387 .data(self.endian, self.data) 388 .read_error("Invalid ELF .gnu_debugaltlink section offset or size") 389 .map(Bytes)?; 390 let filename = data 391 .read_string() 392 .read_error("Missing ELF .gnu_debugaltlink filename")?; 393 let build_id = data.0; 394 Ok(Some((filename, build_id))) 395 } 396 relative_address_base(&self) -> u64397 fn relative_address_base(&self) -> u64 { 398 0 399 } 400 entry(&self) -> u64401 fn entry(&self) -> u64 { 402 self.header.e_entry(self.endian).into() 403 } 404 flags(&self) -> FileFlags405 fn flags(&self) -> FileFlags { 406 FileFlags::Elf { 407 e_flags: self.header.e_flags(self.endian), 408 } 409 } 410 } 411 412 /// A trait for generic access to `FileHeader32` and `FileHeader64`. 413 #[allow(missing_docs)] 414 pub trait FileHeader: Debug + Pod { 415 // Ideally this would be a `u64: From<Word>`, but can't express that. 416 type Word: Into<u64>; 417 type Sword: Into<i64>; 418 type Endian: endian::Endian; 419 type ProgramHeader: ProgramHeader<Elf = Self, Endian = Self::Endian, Word = Self::Word>; 420 type SectionHeader: SectionHeader<Elf = Self, Endian = Self::Endian, Word = Self::Word>; 421 type CompressionHeader: CompressionHeader<Endian = Self::Endian, Word = Self::Word>; 422 type NoteHeader: NoteHeader<Endian = Self::Endian>; 423 type Dyn: Dyn<Endian = Self::Endian, Word = Self::Word>; 424 type Sym: Sym<Endian = Self::Endian, Word = Self::Word>; 425 type Rel: Rel<Endian = Self::Endian, Word = Self::Word>; 426 type Rela: Rela<Endian = Self::Endian, Word = Self::Word> + From<Self::Rel>; 427 428 /// Return true if this type is a 64-bit header. 429 /// 430 /// This is a property of the type, not a value in the header data. is_type_64(&self) -> bool431 fn is_type_64(&self) -> bool; 432 e_ident(&self) -> &elf::Ident433 fn e_ident(&self) -> &elf::Ident; e_type(&self, endian: Self::Endian) -> u16434 fn e_type(&self, endian: Self::Endian) -> u16; e_machine(&self, endian: Self::Endian) -> u16435 fn e_machine(&self, endian: Self::Endian) -> u16; e_version(&self, endian: Self::Endian) -> u32436 fn e_version(&self, endian: Self::Endian) -> u32; e_entry(&self, endian: Self::Endian) -> Self::Word437 fn e_entry(&self, endian: Self::Endian) -> Self::Word; e_phoff(&self, endian: Self::Endian) -> Self::Word438 fn e_phoff(&self, endian: Self::Endian) -> Self::Word; e_shoff(&self, endian: Self::Endian) -> Self::Word439 fn e_shoff(&self, endian: Self::Endian) -> Self::Word; e_flags(&self, endian: Self::Endian) -> u32440 fn e_flags(&self, endian: Self::Endian) -> u32; e_ehsize(&self, endian: Self::Endian) -> u16441 fn e_ehsize(&self, endian: Self::Endian) -> u16; e_phentsize(&self, endian: Self::Endian) -> u16442 fn e_phentsize(&self, endian: Self::Endian) -> u16; e_phnum(&self, endian: Self::Endian) -> u16443 fn e_phnum(&self, endian: Self::Endian) -> u16; e_shentsize(&self, endian: Self::Endian) -> u16444 fn e_shentsize(&self, endian: Self::Endian) -> u16; e_shnum(&self, endian: Self::Endian) -> u16445 fn e_shnum(&self, endian: Self::Endian) -> u16; e_shstrndx(&self, endian: Self::Endian) -> u16446 fn e_shstrndx(&self, endian: Self::Endian) -> u16; 447 448 // Provided methods. 449 450 /// Read the file header. 451 /// 452 /// Also checks that the ident field in the file header is a supported format. parse<'data, R: ReadRef<'data>>(data: R) -> read::Result<&'data Self>453 fn parse<'data, R: ReadRef<'data>>(data: R) -> read::Result<&'data Self> { 454 let header = data 455 .read_at::<Self>(0) 456 .read_error("Invalid ELF header size or alignment")?; 457 if !header.is_supported() { 458 return Err(Error("Unsupported ELF header")); 459 } 460 // TODO: Check self.e_ehsize? 461 Ok(header) 462 } 463 464 /// Check that the ident field in the file header is a supported format. 465 /// 466 /// This checks the magic number, version, class, and endianness. is_supported(&self) -> bool467 fn is_supported(&self) -> bool { 468 let ident = self.e_ident(); 469 // TODO: Check self.e_version too? Requires endian though. 470 ident.magic == elf::ELFMAG 471 && (self.is_type_64() || self.is_class_32()) 472 && (!self.is_type_64() || self.is_class_64()) 473 && (self.is_little_endian() || self.is_big_endian()) 474 && ident.version == elf::EV_CURRENT 475 } 476 is_class_32(&self) -> bool477 fn is_class_32(&self) -> bool { 478 self.e_ident().class == elf::ELFCLASS32 479 } 480 is_class_64(&self) -> bool481 fn is_class_64(&self) -> bool { 482 self.e_ident().class == elf::ELFCLASS64 483 } 484 is_little_endian(&self) -> bool485 fn is_little_endian(&self) -> bool { 486 self.e_ident().data == elf::ELFDATA2LSB 487 } 488 is_big_endian(&self) -> bool489 fn is_big_endian(&self) -> bool { 490 self.e_ident().data == elf::ELFDATA2MSB 491 } 492 endian(&self) -> read::Result<Self::Endian>493 fn endian(&self) -> read::Result<Self::Endian> { 494 Self::Endian::from_big_endian(self.is_big_endian()).read_error("Unsupported ELF endian") 495 } 496 497 /// Return the first section header, if present. 498 /// 499 /// Section 0 is a special case because getting the section headers normally 500 /// requires `shnum`, but `shnum` may be in the first section header. section_0<'data, R: ReadRef<'data>>( &self, endian: Self::Endian, data: R, ) -> read::Result<Option<&'data Self::SectionHeader>>501 fn section_0<'data, R: ReadRef<'data>>( 502 &self, 503 endian: Self::Endian, 504 data: R, 505 ) -> read::Result<Option<&'data Self::SectionHeader>> { 506 let shoff: u64 = self.e_shoff(endian).into(); 507 if shoff == 0 { 508 // No section headers is ok. 509 return Ok(None); 510 } 511 let shentsize = usize::from(self.e_shentsize(endian)); 512 if shentsize != mem::size_of::<Self::SectionHeader>() { 513 // Section header size must match. 514 return Err(Error("Invalid ELF section header entry size")); 515 } 516 data.read_at(shoff) 517 .map(Some) 518 .read_error("Invalid ELF section header offset or size") 519 } 520 521 /// Return the `e_phnum` field of the header. Handles extended values. 522 /// 523 /// Returns `Err` for invalid values. phnum<'data, R: ReadRef<'data>>( &self, endian: Self::Endian, data: R, ) -> read::Result<usize>524 fn phnum<'data, R: ReadRef<'data>>( 525 &self, 526 endian: Self::Endian, 527 data: R, 528 ) -> read::Result<usize> { 529 let e_phnum = self.e_phnum(endian); 530 if e_phnum < elf::PN_XNUM { 531 Ok(e_phnum as usize) 532 } else if let Some(section_0) = self.section_0(endian, data)? { 533 Ok(section_0.sh_info(endian) as usize) 534 } else { 535 // Section 0 must exist if e_phnum overflows. 536 Err(Error("Missing ELF section headers for e_phnum overflow")) 537 } 538 } 539 540 /// Return the `e_shnum` field of the header. Handles extended values. 541 /// 542 /// Returns `Err` for invalid values. shnum<'data, R: ReadRef<'data>>( &self, endian: Self::Endian, data: R, ) -> read::Result<usize>543 fn shnum<'data, R: ReadRef<'data>>( 544 &self, 545 endian: Self::Endian, 546 data: R, 547 ) -> read::Result<usize> { 548 let e_shnum = self.e_shnum(endian); 549 if e_shnum > 0 { 550 Ok(e_shnum as usize) 551 } else if let Some(section_0) = self.section_0(endian, data)? { 552 section_0 553 .sh_size(endian) 554 .into() 555 .try_into() 556 .ok() 557 .read_error("Invalid ELF extended e_shnum") 558 } else { 559 // No section headers is ok. 560 Ok(0) 561 } 562 } 563 564 /// Return the `e_shstrndx` field of the header. Handles extended values. 565 /// 566 /// Returns `Err` for invalid values (including if the index is 0). shstrndx<'data, R: ReadRef<'data>>( &self, endian: Self::Endian, data: R, ) -> read::Result<u32>567 fn shstrndx<'data, R: ReadRef<'data>>( 568 &self, 569 endian: Self::Endian, 570 data: R, 571 ) -> read::Result<u32> { 572 let e_shstrndx = self.e_shstrndx(endian); 573 let index = if e_shstrndx != elf::SHN_XINDEX { 574 e_shstrndx.into() 575 } else if let Some(section_0) = self.section_0(endian, data)? { 576 section_0.sh_link(endian) 577 } else { 578 // Section 0 must exist if we're trying to read e_shstrndx. 579 return Err(Error("Missing ELF section headers for e_shstrndx overflow")); 580 }; 581 if index == 0 { 582 return Err(Error("Missing ELF e_shstrndx")); 583 } 584 Ok(index) 585 } 586 587 /// Return the slice of program headers. 588 /// 589 /// Returns `Ok(&[])` if there are no program headers. 590 /// Returns `Err` for invalid values. program_headers<'data, R: ReadRef<'data>>( &self, endian: Self::Endian, data: R, ) -> read::Result<&'data [Self::ProgramHeader]>591 fn program_headers<'data, R: ReadRef<'data>>( 592 &self, 593 endian: Self::Endian, 594 data: R, 595 ) -> read::Result<&'data [Self::ProgramHeader]> { 596 let phoff: u64 = self.e_phoff(endian).into(); 597 if phoff == 0 { 598 // No program headers is ok. 599 return Ok(&[]); 600 } 601 let phnum = self.phnum(endian, data)?; 602 if phnum == 0 { 603 // No program headers is ok. 604 return Ok(&[]); 605 } 606 let phentsize = self.e_phentsize(endian) as usize; 607 if phentsize != mem::size_of::<Self::ProgramHeader>() { 608 // Program header size must match. 609 return Err(Error("Invalid ELF program header entry size")); 610 } 611 data.read_slice_at(phoff, phnum) 612 .read_error("Invalid ELF program header size or alignment") 613 } 614 615 /// Return the slice of section headers. 616 /// 617 /// Returns `Ok(&[])` if there are no section headers. 618 /// Returns `Err` for invalid values. section_headers<'data, R: ReadRef<'data>>( &self, endian: Self::Endian, data: R, ) -> read::Result<&'data [Self::SectionHeader]>619 fn section_headers<'data, R: ReadRef<'data>>( 620 &self, 621 endian: Self::Endian, 622 data: R, 623 ) -> read::Result<&'data [Self::SectionHeader]> { 624 let shoff: u64 = self.e_shoff(endian).into(); 625 if shoff == 0 { 626 // No section headers is ok. 627 return Ok(&[]); 628 } 629 let shnum = self.shnum(endian, data)?; 630 if shnum == 0 { 631 // No section headers is ok. 632 return Ok(&[]); 633 } 634 let shentsize = usize::from(self.e_shentsize(endian)); 635 if shentsize != mem::size_of::<Self::SectionHeader>() { 636 // Section header size must match. 637 return Err(Error("Invalid ELF section header entry size")); 638 } 639 data.read_slice_at(shoff, shnum) 640 .read_error("Invalid ELF section header offset/size/alignment") 641 } 642 643 /// Return the string table for the section headers. section_strings<'data, R: ReadRef<'data>>( &self, endian: Self::Endian, data: R, sections: &[Self::SectionHeader], ) -> read::Result<StringTable<'data, R>>644 fn section_strings<'data, R: ReadRef<'data>>( 645 &self, 646 endian: Self::Endian, 647 data: R, 648 sections: &[Self::SectionHeader], 649 ) -> read::Result<StringTable<'data, R>> { 650 if sections.is_empty() { 651 return Ok(StringTable::default()); 652 } 653 let index = self.shstrndx(endian, data)? as usize; 654 let shstrtab = sections.get(index).read_error("Invalid ELF e_shstrndx")?; 655 let strings = if let Some((shstrtab_offset, shstrtab_size)) = shstrtab.file_range(endian) { 656 let shstrtab_end = shstrtab_offset 657 .checked_add(shstrtab_size) 658 .read_error("Invalid ELF shstrtab size")?; 659 StringTable::new(data, shstrtab_offset, shstrtab_end) 660 } else { 661 StringTable::default() 662 }; 663 Ok(strings) 664 } 665 666 /// Return the section table. sections<'data, R: ReadRef<'data>>( &self, endian: Self::Endian, data: R, ) -> read::Result<SectionTable<'data, Self, R>>667 fn sections<'data, R: ReadRef<'data>>( 668 &self, 669 endian: Self::Endian, 670 data: R, 671 ) -> read::Result<SectionTable<'data, Self, R>> { 672 let sections = self.section_headers(endian, data)?; 673 let strings = self.section_strings(endian, data, sections)?; 674 Ok(SectionTable::new(sections, strings)) 675 } 676 677 /// Returns whether this is a mips64el elf file. is_mips64el(&self, endian: Self::Endian) -> bool678 fn is_mips64el(&self, endian: Self::Endian) -> bool { 679 self.is_class_64() && self.is_little_endian() && self.e_machine(endian) == elf::EM_MIPS 680 } 681 } 682 683 impl<Endian: endian::Endian> FileHeader for elf::FileHeader32<Endian> { 684 type Word = u32; 685 type Sword = i32; 686 type Endian = Endian; 687 type ProgramHeader = elf::ProgramHeader32<Endian>; 688 type SectionHeader = elf::SectionHeader32<Endian>; 689 type CompressionHeader = elf::CompressionHeader32<Endian>; 690 type NoteHeader = elf::NoteHeader32<Endian>; 691 type Dyn = elf::Dyn32<Endian>; 692 type Sym = elf::Sym32<Endian>; 693 type Rel = elf::Rel32<Endian>; 694 type Rela = elf::Rela32<Endian>; 695 696 #[inline] is_type_64(&self) -> bool697 fn is_type_64(&self) -> bool { 698 false 699 } 700 701 #[inline] e_ident(&self) -> &elf::Ident702 fn e_ident(&self) -> &elf::Ident { 703 &self.e_ident 704 } 705 706 #[inline] e_type(&self, endian: Self::Endian) -> u16707 fn e_type(&self, endian: Self::Endian) -> u16 { 708 self.e_type.get(endian) 709 } 710 711 #[inline] e_machine(&self, endian: Self::Endian) -> u16712 fn e_machine(&self, endian: Self::Endian) -> u16 { 713 self.e_machine.get(endian) 714 } 715 716 #[inline] e_version(&self, endian: Self::Endian) -> u32717 fn e_version(&self, endian: Self::Endian) -> u32 { 718 self.e_version.get(endian) 719 } 720 721 #[inline] e_entry(&self, endian: Self::Endian) -> Self::Word722 fn e_entry(&self, endian: Self::Endian) -> Self::Word { 723 self.e_entry.get(endian) 724 } 725 726 #[inline] e_phoff(&self, endian: Self::Endian) -> Self::Word727 fn e_phoff(&self, endian: Self::Endian) -> Self::Word { 728 self.e_phoff.get(endian) 729 } 730 731 #[inline] e_shoff(&self, endian: Self::Endian) -> Self::Word732 fn e_shoff(&self, endian: Self::Endian) -> Self::Word { 733 self.e_shoff.get(endian) 734 } 735 736 #[inline] e_flags(&self, endian: Self::Endian) -> u32737 fn e_flags(&self, endian: Self::Endian) -> u32 { 738 self.e_flags.get(endian) 739 } 740 741 #[inline] e_ehsize(&self, endian: Self::Endian) -> u16742 fn e_ehsize(&self, endian: Self::Endian) -> u16 { 743 self.e_ehsize.get(endian) 744 } 745 746 #[inline] e_phentsize(&self, endian: Self::Endian) -> u16747 fn e_phentsize(&self, endian: Self::Endian) -> u16 { 748 self.e_phentsize.get(endian) 749 } 750 751 #[inline] e_phnum(&self, endian: Self::Endian) -> u16752 fn e_phnum(&self, endian: Self::Endian) -> u16 { 753 self.e_phnum.get(endian) 754 } 755 756 #[inline] e_shentsize(&self, endian: Self::Endian) -> u16757 fn e_shentsize(&self, endian: Self::Endian) -> u16 { 758 self.e_shentsize.get(endian) 759 } 760 761 #[inline] e_shnum(&self, endian: Self::Endian) -> u16762 fn e_shnum(&self, endian: Self::Endian) -> u16 { 763 self.e_shnum.get(endian) 764 } 765 766 #[inline] e_shstrndx(&self, endian: Self::Endian) -> u16767 fn e_shstrndx(&self, endian: Self::Endian) -> u16 { 768 self.e_shstrndx.get(endian) 769 } 770 } 771 772 impl<Endian: endian::Endian> FileHeader for elf::FileHeader64<Endian> { 773 type Word = u64; 774 type Sword = i64; 775 type Endian = Endian; 776 type ProgramHeader = elf::ProgramHeader64<Endian>; 777 type SectionHeader = elf::SectionHeader64<Endian>; 778 type CompressionHeader = elf::CompressionHeader64<Endian>; 779 type NoteHeader = elf::NoteHeader32<Endian>; 780 type Dyn = elf::Dyn64<Endian>; 781 type Sym = elf::Sym64<Endian>; 782 type Rel = elf::Rel64<Endian>; 783 type Rela = elf::Rela64<Endian>; 784 785 #[inline] is_type_64(&self) -> bool786 fn is_type_64(&self) -> bool { 787 true 788 } 789 790 #[inline] e_ident(&self) -> &elf::Ident791 fn e_ident(&self) -> &elf::Ident { 792 &self.e_ident 793 } 794 795 #[inline] e_type(&self, endian: Self::Endian) -> u16796 fn e_type(&self, endian: Self::Endian) -> u16 { 797 self.e_type.get(endian) 798 } 799 800 #[inline] e_machine(&self, endian: Self::Endian) -> u16801 fn e_machine(&self, endian: Self::Endian) -> u16 { 802 self.e_machine.get(endian) 803 } 804 805 #[inline] e_version(&self, endian: Self::Endian) -> u32806 fn e_version(&self, endian: Self::Endian) -> u32 { 807 self.e_version.get(endian) 808 } 809 810 #[inline] e_entry(&self, endian: Self::Endian) -> Self::Word811 fn e_entry(&self, endian: Self::Endian) -> Self::Word { 812 self.e_entry.get(endian) 813 } 814 815 #[inline] e_phoff(&self, endian: Self::Endian) -> Self::Word816 fn e_phoff(&self, endian: Self::Endian) -> Self::Word { 817 self.e_phoff.get(endian) 818 } 819 820 #[inline] e_shoff(&self, endian: Self::Endian) -> Self::Word821 fn e_shoff(&self, endian: Self::Endian) -> Self::Word { 822 self.e_shoff.get(endian) 823 } 824 825 #[inline] e_flags(&self, endian: Self::Endian) -> u32826 fn e_flags(&self, endian: Self::Endian) -> u32 { 827 self.e_flags.get(endian) 828 } 829 830 #[inline] e_ehsize(&self, endian: Self::Endian) -> u16831 fn e_ehsize(&self, endian: Self::Endian) -> u16 { 832 self.e_ehsize.get(endian) 833 } 834 835 #[inline] e_phentsize(&self, endian: Self::Endian) -> u16836 fn e_phentsize(&self, endian: Self::Endian) -> u16 { 837 self.e_phentsize.get(endian) 838 } 839 840 #[inline] e_phnum(&self, endian: Self::Endian) -> u16841 fn e_phnum(&self, endian: Self::Endian) -> u16 { 842 self.e_phnum.get(endian) 843 } 844 845 #[inline] e_shentsize(&self, endian: Self::Endian) -> u16846 fn e_shentsize(&self, endian: Self::Endian) -> u16 { 847 self.e_shentsize.get(endian) 848 } 849 850 #[inline] e_shnum(&self, endian: Self::Endian) -> u16851 fn e_shnum(&self, endian: Self::Endian) -> u16 { 852 self.e_shnum.get(endian) 853 } 854 855 #[inline] e_shstrndx(&self, endian: Self::Endian) -> u16856 fn e_shstrndx(&self, endian: Self::Endian) -> u16 { 857 self.e_shstrndx.get(endian) 858 } 859 } 860