1use alloc::vec::Vec;
2use core::convert::TryInto;
3use core::fmt::Debug;
4use core::mem;
5
6use crate::endian::{self, Endian, Endianness, NativeEndian, U32};
7use crate::pod::Pod;
8use crate::read::{
9 self, util, Architecture, ByteString, Bytes, Error, Export, FileFlags, Import, Object,
10 ObjectKind, ReadError, ReadRef, SectionIndex, StringTable, SymbolIndex,
11};
12use crate::{elf, SkipDebugList};
13
14use super::{
15 CompressionHeader, Dyn, DynamicTable, ElfComdat, ElfComdatIterator,
16 ElfDynamicRelocationIterator, ElfSection, ElfSectionIterator, ElfSegment, ElfSegmentIterator,
17 ElfSymbol, ElfSymbolIterator, ElfSymbolTable, NoteHeader, ProgramHeader, Rel, Rela,
18 RelocationSections, Relr, SectionHeader, SectionTable, Sym, SymbolTable,
19};
20
21pub type ElfFile32<'data, Endian = Endianness, R = &'data [u8]> =
26 ElfFile<'data, elf::FileHeader32<Endian>, R>;
27
28pub type ElfFile64<'data, Endian = Endianness, R = &'data [u8]> =
33 ElfFile<'data, elf::FileHeader64<Endian>, R>;
34
35#[cfg(target_pointer_width = "32")]
37pub type NativeElfFile<'data, R = &'data [u8]> = ElfFile32<'data, NativeEndian, R>;
38
39#[cfg(target_pointer_width = "64")]
41pub type NativeElfFile<'data, R = &'data [u8]> = ElfFile64<'data, NativeEndian, R>;
42
43#[derive(Debug)]
47pub struct ElfFile<'data, Elf, R = &'data [u8]>
48where
49 Elf: FileHeader,
50 R: ReadRef<'data>,
51{
52 pub(super) endian: Elf::Endian,
53 pub(super) data: SkipDebugList<R>,
54 pub(super) header: &'data Elf,
55 pub(super) segments: &'data [Elf::ProgramHeader],
56 pub(super) sections: SectionTable<'data, Elf, R>,
57 pub(super) relocations: RelocationSections,
58 pub(super) symbols: SymbolTable<'data, Elf, R>,
59 pub(super) dynamic_symbols: SymbolTable<'data, Elf, R>,
60}
61
62impl<'data, Elf, R> ElfFile<'data, Elf, R>
63where
64 Elf: FileHeader,
65 R: ReadRef<'data>,
66{
67 pub fn parse(data: R) -> read::Result<Self> {
69 let header = Elf::parse(data)?;
70 let endian = header.endian()?;
71 let segments = header.program_headers(endian, data)?;
72 let sections = header.sections(endian, data)?;
73 let symbols = sections.symbols(endian, data, elf::SHT_SYMTAB)?;
74 let dynamic_symbols = sections.symbols(endian, data, elf::SHT_DYNSYM)?;
76 let relocations = sections.relocation_sections(endian, symbols.section())?;
78
79 Ok(ElfFile {
80 endian,
81 data: SkipDebugList(data),
82 header,
83 segments,
84 sections,
85 relocations,
86 symbols,
87 dynamic_symbols,
88 })
89 }
90
91 pub fn endian(&self) -> Elf::Endian {
93 self.endian
94 }
95
96 pub fn data(&self) -> R {
98 self.data.0
99 }
100
101 #[deprecated(note = "Use `elf_header` instead")]
103 pub fn raw_header(&self) -> &'data Elf {
104 self.header
105 }
106
107 #[deprecated(note = "Use `elf_program_headers` instead")]
109 pub fn raw_segments(&self) -> &'data [Elf::ProgramHeader] {
110 self.segments
111 }
112
113 pub fn elf_header(&self) -> &'data Elf {
115 self.header
116 }
117
118 pub fn elf_program_headers(&self) -> &'data [Elf::ProgramHeader] {
122 self.segments
123 }
124
125 pub fn elf_section_table(&self) -> &SectionTable<'data, Elf, R> {
129 &self.sections
130 }
131
132 pub fn elf_symbol_table(&self) -> &SymbolTable<'data, Elf, R> {
136 &self.symbols
137 }
138
139 pub fn elf_dynamic_symbol_table(&self) -> &SymbolTable<'data, Elf, R> {
143 &self.dynamic_symbols
144 }
145
146 pub fn elf_relocation_sections(&self) -> &RelocationSections {
148 &self.relocations
149 }
150
151 pub fn elf_dynamic_table(&self) -> read::Result<DynamicTable<'data, Elf, R>> {
155 self.sections.dynamic_table(self.endian, self.data.0)
156 }
157
158 fn raw_section_by_name<'file>(
159 &'file self,
160 section_name: &[u8],
161 ) -> Option<ElfSection<'data, 'file, Elf, R>> {
162 self.sections
163 .section_by_name(self.endian, section_name)
164 .map(|(index, section)| ElfSection {
165 file: self,
166 index,
167 section,
168 })
169 }
170
171 #[cfg(feature = "compression")]
172 fn zdebug_section_by_name<'file>(
173 &'file self,
174 section_name: &[u8],
175 ) -> Option<ElfSection<'data, 'file, Elf, R>> {
176 if !section_name.starts_with(b".debug_") {
177 return None;
178 }
179 let mut name = Vec::with_capacity(section_name.len() + 1);
180 name.extend_from_slice(b".zdebug_");
181 name.extend_from_slice(§ion_name[7..]);
182 self.raw_section_by_name(&name)
183 }
184
185 #[cfg(not(feature = "compression"))]
186 fn zdebug_section_by_name<'file>(
187 &'file self,
188 _section_name: &[u8],
189 ) -> Option<ElfSection<'data, 'file, Elf, R>> {
190 None
191 }
192}
193
194impl<'data, Elf, R> read::private::Sealed for ElfFile<'data, Elf, R>
195where
196 Elf: FileHeader,
197 R: ReadRef<'data>,
198{
199}
200
201impl<'data, Elf, R> Object<'data> for ElfFile<'data, Elf, R>
202where
203 Elf: FileHeader,
204 R: ReadRef<'data>,
205{
206 type Segment<'file>
207 = ElfSegment<'data, 'file, Elf, R>
208 where
209 Self: 'file,
210 'data: 'file;
211 type SegmentIterator<'file>
212 = ElfSegmentIterator<'data, 'file, Elf, R>
213 where
214 Self: 'file,
215 'data: 'file;
216 type Section<'file>
217 = ElfSection<'data, 'file, Elf, R>
218 where
219 Self: 'file,
220 'data: 'file;
221 type SectionIterator<'file>
222 = ElfSectionIterator<'data, 'file, Elf, R>
223 where
224 Self: 'file,
225 'data: 'file;
226 type Comdat<'file>
227 = ElfComdat<'data, 'file, Elf, R>
228 where
229 Self: 'file,
230 'data: 'file;
231 type ComdatIterator<'file>
232 = ElfComdatIterator<'data, 'file, Elf, R>
233 where
234 Self: 'file,
235 'data: 'file;
236 type Symbol<'file>
237 = ElfSymbol<'data, 'file, Elf, R>
238 where
239 Self: 'file,
240 'data: 'file;
241 type SymbolIterator<'file>
242 = ElfSymbolIterator<'data, 'file, Elf, R>
243 where
244 Self: 'file,
245 'data: 'file;
246 type SymbolTable<'file>
247 = ElfSymbolTable<'data, 'file, Elf, R>
248 where
249 Self: 'file,
250 'data: 'file;
251 type DynamicRelocationIterator<'file>
252 = ElfDynamicRelocationIterator<'data, 'file, Elf, R>
253 where
254 Self: 'file,
255 'data: 'file;
256
257 fn architecture(&self) -> Architecture {
258 match (
259 self.header.e_machine(self.endian),
260 self.header.is_class_64(),
261 ) {
262 (elf::EM_AARCH64, true) => Architecture::Aarch64,
263 (elf::EM_AARCH64, false) => Architecture::Aarch64_Ilp32,
264 (elf::EM_ALPHA, true) => Architecture::Alpha,
265 (elf::EM_ARM, _) => Architecture::Arm,
266 (elf::EM_AVR, _) => Architecture::Avr,
267 (elf::EM_BPF, _) => Architecture::Bpf,
268 (elf::EM_CSKY, _) => Architecture::Csky,
269 (elf::EM_MCST_ELBRUS, false) => Architecture::E2K32,
270 (elf::EM_MCST_ELBRUS, true) => Architecture::E2K64,
271 (elf::EM_386, _) => Architecture::I386,
272 (elf::EM_X86_64, false) => Architecture::X86_64_X32,
273 (elf::EM_X86_64, true) => Architecture::X86_64,
274 (elf::EM_HEXAGON, _) => Architecture::Hexagon,
275 (elf::EM_LOONGARCH, false) => Architecture::LoongArch32,
276 (elf::EM_LOONGARCH, true) => Architecture::LoongArch64,
277 (elf::EM_68K, false) => Architecture::M68k,
278 (elf::EM_MIPS, false) => {
279 if (self.header.e_flags(self.endian) & elf::EF_MIPS_ABI2) != 0 {
280 Architecture::Mips64_N32
281 } else {
282 Architecture::Mips
283 }
284 }
285 (elf::EM_MIPS, true) => Architecture::Mips64,
286 (elf::EM_MSP430, _) => Architecture::Msp430,
287 (elf::EM_PARISC, _) => Architecture::Hppa,
288 (elf::EM_PPC, _) => Architecture::PowerPc,
289 (elf::EM_PPC64, _) => Architecture::PowerPc64,
290 (elf::EM_RISCV, false) => Architecture::Riscv32,
291 (elf::EM_RISCV, true) => Architecture::Riscv64,
292 (elf::EM_S390, true) => Architecture::S390x,
295 (elf::EM_SBF, _) => Architecture::Sbf,
296 (elf::EM_SHARC, false) => Architecture::Sharc,
297 (elf::EM_SPARC, false) => Architecture::Sparc,
298 (elf::EM_SPARC32PLUS, false) => Architecture::Sparc32Plus,
299 (elf::EM_SPARCV9, true) => Architecture::Sparc64,
300 (elf::EM_XTENSA, false) => Architecture::Xtensa,
301 (elf::EM_SH, false) => Architecture::SuperH,
302 _ => Architecture::Unknown,
303 }
304 }
305
306 #[inline]
307 fn is_little_endian(&self) -> bool {
308 self.header.is_little_endian()
309 }
310
311 #[inline]
312 fn is_64(&self) -> bool {
313 self.header.is_class_64()
314 }
315
316 fn kind(&self) -> ObjectKind {
317 match self.header.e_type(self.endian) {
318 elf::ET_REL => ObjectKind::Relocatable,
319 elf::ET_EXEC => ObjectKind::Executable,
320 elf::ET_DYN => ObjectKind::Dynamic,
322 elf::ET_CORE => ObjectKind::Core,
323 _ => ObjectKind::Unknown,
324 }
325 }
326
327 fn segments(&self) -> ElfSegmentIterator<'data, '_, Elf, R> {
328 ElfSegmentIterator {
329 file: self,
330 iter: self.segments.iter(),
331 }
332 }
333
334 fn section_by_name_bytes<'file>(
335 &'file self,
336 section_name: &[u8],
337 ) -> Option<ElfSection<'data, 'file, Elf, R>> {
338 self.raw_section_by_name(section_name)
339 .or_else(|| self.zdebug_section_by_name(section_name))
340 }
341
342 fn section_by_index(&self, index: SectionIndex) -> read::Result<ElfSection<'data, '_, Elf, R>> {
343 let section = self.sections.section(index)?;
344 Ok(ElfSection {
345 file: self,
346 index,
347 section,
348 })
349 }
350
351 fn sections(&self) -> ElfSectionIterator<'data, '_, Elf, R> {
352 ElfSectionIterator::new(self)
353 }
354
355 fn comdats(&self) -> ElfComdatIterator<'data, '_, Elf, R> {
356 ElfComdatIterator::new(self)
357 }
358
359 fn symbol_by_index(&self, index: SymbolIndex) -> read::Result<ElfSymbol<'data, '_, Elf, R>> {
360 let symbol = self.symbols.symbol(index)?;
361 Ok(ElfSymbol {
362 endian: self.endian,
363 symbols: &self.symbols,
364 index,
365 symbol,
366 })
367 }
368
369 fn symbols(&self) -> ElfSymbolIterator<'data, '_, Elf, R> {
370 ElfSymbolIterator::new(self.endian, &self.symbols)
371 }
372
373 fn symbol_table(&self) -> Option<ElfSymbolTable<'data, '_, Elf, R>> {
374 if self.symbols.is_empty() {
375 return None;
376 }
377 Some(ElfSymbolTable {
378 endian: self.endian,
379 symbols: &self.symbols,
380 })
381 }
382
383 fn dynamic_symbols(&self) -> ElfSymbolIterator<'data, '_, Elf, R> {
384 ElfSymbolIterator::new(self.endian, &self.dynamic_symbols)
385 }
386
387 fn dynamic_symbol_table(&self) -> Option<ElfSymbolTable<'data, '_, Elf, R>> {
388 if self.dynamic_symbols.is_empty() {
389 return None;
390 }
391 Some(ElfSymbolTable {
392 endian: self.endian,
393 symbols: &self.dynamic_symbols,
394 })
395 }
396
397 fn dynamic_relocations<'file>(
398 &'file self,
399 ) -> Option<ElfDynamicRelocationIterator<'data, 'file, Elf, R>> {
400 Some(ElfDynamicRelocationIterator {
401 section_index: SectionIndex(1),
402 file: self,
403 relocations: None,
404 })
405 }
406
407 fn imports(&self) -> read::Result<Vec<Import<'data>>> {
408 let versions = self.sections.versions(self.endian, self.data.0)?;
409
410 let mut imports = Vec::new();
411 for (index, symbol) in self.dynamic_symbols.enumerate() {
412 if symbol.is_undefined(self.endian) {
413 let name = symbol.name(self.endian, self.dynamic_symbols.strings())?;
414 if !name.is_empty() {
415 let library = if let Some(svt) = versions.as_ref() {
416 let vi = svt.version_index(self.endian, index);
417 svt.version(vi)?.and_then(|v| v.file())
418 } else {
419 None
420 }
421 .unwrap_or(&[]);
422 imports.push(Import {
423 name: ByteString(name),
424 library: ByteString(library),
425 });
426 }
427 }
428 }
429 Ok(imports)
430 }
431
432 fn exports(&self) -> read::Result<Vec<Export<'data>>> {
433 let mut exports = Vec::new();
434 for symbol in self.dynamic_symbols.iter() {
435 if symbol.is_definition(self.endian, self.dynamic_symbols.strings()) {
436 let name = symbol.name(self.endian, self.dynamic_symbols.strings())?;
437 let address = symbol.st_value(self.endian).into();
438 exports.push(Export {
439 name: ByteString(name),
440 address,
441 });
442 }
443 }
444 Ok(exports)
445 }
446
447 fn has_debug_symbols(&self) -> bool {
448 for section in self.sections.iter() {
449 if let Ok(name) = self.sections.section_name(self.endian, section) {
450 if name == b".debug_info" || name == b".zdebug_info" {
451 return true;
452 }
453 }
454 }
455 false
456 }
457
458 fn build_id(&self) -> read::Result<Option<&'data [u8]>> {
459 let endian = self.endian;
460 if !self.sections.is_empty() {
462 for section in self.sections.iter() {
463 if let Some(mut notes) = section.notes(endian, self.data.0)? {
464 while let Some(note) = notes.next()? {
465 if note.name() == elf::ELF_NOTE_GNU
466 && note.n_type(endian) == elf::NT_GNU_BUILD_ID
467 {
468 return Ok(Some(note.desc()));
469 }
470 }
471 }
472 }
473 } else {
474 for segment in self.segments {
475 if let Some(mut notes) = segment.notes(endian, self.data.0)? {
476 while let Some(note) = notes.next()? {
477 if note.name() == elf::ELF_NOTE_GNU
478 && note.n_type(endian) == elf::NT_GNU_BUILD_ID
479 {
480 return Ok(Some(note.desc()));
481 }
482 }
483 }
484 }
485 }
486 Ok(None)
487 }
488
489 fn gnu_debuglink(&self) -> read::Result<Option<(&'data [u8], u32)>> {
490 let section = match self.raw_section_by_name(b".gnu_debuglink") {
491 Some(section) => section,
492 None => return Ok(None),
493 };
494 let data = section
495 .section
496 .data(self.endian, self.data.0)
497 .read_error("Invalid ELF .gnu_debuglink section offset or size")
498 .map(Bytes)?;
499 let filename = data
500 .read_string_at(0)
501 .read_error("Missing ELF .gnu_debuglink filename")?;
502 let crc_offset = util::align(filename.len() + 1, 4);
503 let crc = data
504 .read_at::<U32<_>>(crc_offset)
505 .read_error("Missing ELF .gnu_debuglink crc")?
506 .get(self.endian);
507 Ok(Some((filename, crc)))
508 }
509
510 fn gnu_debugaltlink(&self) -> read::Result<Option<(&'data [u8], &'data [u8])>> {
511 let section = match self.raw_section_by_name(b".gnu_debugaltlink") {
512 Some(section) => section,
513 None => return Ok(None),
514 };
515 let mut data = section
516 .section
517 .data(self.endian, self.data.0)
518 .read_error("Invalid ELF .gnu_debugaltlink section offset or size")
519 .map(Bytes)?;
520 let filename = data
521 .read_string()
522 .read_error("Missing ELF .gnu_debugaltlink filename")?;
523 let build_id = data.0;
524 Ok(Some((filename, build_id)))
525 }
526
527 fn relative_address_base(&self) -> u64 {
528 0
529 }
530
531 fn entry(&self) -> u64 {
532 self.header.e_entry(self.endian).into()
533 }
534
535 fn flags(&self) -> FileFlags {
536 FileFlags::Elf {
537 os_abi: self.header.e_ident().os_abi,
538 abi_version: self.header.e_ident().abi_version,
539 e_flags: self.header.e_flags(self.endian),
540 }
541 }
542}
543
544#[allow(missing_docs)]
546pub trait FileHeader: Debug + Pod {
547 type Word: Into<u64> + Default + Copy;
549 type Sword: Into<i64>;
550 type Endian: endian::Endian;
551 type ProgramHeader: ProgramHeader<Elf = Self, Endian = Self::Endian, Word = Self::Word>;
552 type SectionHeader: SectionHeader<Elf = Self, Endian = Self::Endian, Word = Self::Word>;
553 type CompressionHeader: CompressionHeader<Endian = Self::Endian, Word = Self::Word>;
554 type NoteHeader: NoteHeader<Endian = Self::Endian>;
555 type Dyn: Dyn<Endian = Self::Endian, Word = Self::Word>;
556 type Sym: Sym<Endian = Self::Endian, Word = Self::Word>;
557 type Rel: Rel<Endian = Self::Endian, Word = Self::Word>;
558 type Rela: Rela<Endian = Self::Endian, Word = Self::Word> + From<Self::Rel>;
559 type Relr: Relr<Endian = Self::Endian, Word = Self::Word>;
560
561 fn is_type_64(&self) -> bool;
565
566 fn is_type_64_sized() -> bool
572 where
573 Self: Sized;
574
575 fn e_ident(&self) -> &elf::Ident;
576 fn e_type(&self, endian: Self::Endian) -> u16;
577 fn e_machine(&self, endian: Self::Endian) -> u16;
578 fn e_version(&self, endian: Self::Endian) -> u32;
579 fn e_entry(&self, endian: Self::Endian) -> Self::Word;
580 fn e_phoff(&self, endian: Self::Endian) -> Self::Word;
581 fn e_shoff(&self, endian: Self::Endian) -> Self::Word;
582 fn e_flags(&self, endian: Self::Endian) -> u32;
583 fn e_ehsize(&self, endian: Self::Endian) -> u16;
584 fn e_phentsize(&self, endian: Self::Endian) -> u16;
585 fn e_phnum(&self, endian: Self::Endian) -> u16;
586 fn e_shentsize(&self, endian: Self::Endian) -> u16;
587 fn e_shnum(&self, endian: Self::Endian) -> u16;
588 fn e_shstrndx(&self, endian: Self::Endian) -> u16;
589
590 fn parse<'data, R: ReadRef<'data>>(data: R) -> read::Result<&'data Self> {
596 let header = data
597 .read_at::<Self>(0)
598 .read_error("Invalid ELF header size or alignment")?;
599 if !header.is_supported() {
600 return Err(Error("Unsupported ELF header"));
601 }
602 Ok(header)
604 }
605
606 fn is_supported(&self) -> bool {
610 let ident = self.e_ident();
611 ident.magic == elf::ELFMAG
613 && (self.is_type_64() || self.is_class_32())
614 && (!self.is_type_64() || self.is_class_64())
615 && (self.is_little_endian() || self.is_big_endian())
616 && ident.version == elf::EV_CURRENT
617 }
618
619 fn is_class_32(&self) -> bool {
620 self.e_ident().class == elf::ELFCLASS32
621 }
622
623 fn is_class_64(&self) -> bool {
624 self.e_ident().class == elf::ELFCLASS64
625 }
626
627 fn is_little_endian(&self) -> bool {
628 self.e_ident().data == elf::ELFDATA2LSB
629 }
630
631 fn is_big_endian(&self) -> bool {
632 self.e_ident().data == elf::ELFDATA2MSB
633 }
634
635 fn endian(&self) -> read::Result<Self::Endian> {
636 Self::Endian::from_big_endian(self.is_big_endian()).read_error("Unsupported ELF endian")
637 }
638
639 fn section_0<'data, R: ReadRef<'data>>(
644 &self,
645 endian: Self::Endian,
646 data: R,
647 ) -> read::Result<Option<&'data Self::SectionHeader>> {
648 let shoff: u64 = self.e_shoff(endian).into();
649 if shoff == 0 {
650 return Ok(None);
652 }
653 let shentsize = usize::from(self.e_shentsize(endian));
654 if shentsize != mem::size_of::<Self::SectionHeader>() {
655 return Err(Error("Invalid ELF section header entry size"));
657 }
658 data.read_at(shoff)
659 .map(Some)
660 .read_error("Invalid ELF section header offset or size")
661 }
662
663 fn phnum<'data, R: ReadRef<'data>>(
667 &self,
668 endian: Self::Endian,
669 data: R,
670 ) -> read::Result<usize> {
671 let e_phnum = self.e_phnum(endian);
672 if e_phnum < elf::PN_XNUM {
673 Ok(e_phnum as usize)
674 } else if let Some(section_0) = self.section_0(endian, data)? {
675 Ok(section_0.sh_info(endian) as usize)
676 } else {
677 Err(Error("Missing ELF section headers for e_phnum overflow"))
679 }
680 }
681
682 fn shnum<'data, R: ReadRef<'data>>(
686 &self,
687 endian: Self::Endian,
688 data: R,
689 ) -> read::Result<usize> {
690 let e_shnum = self.e_shnum(endian);
691 if e_shnum > 0 {
692 Ok(e_shnum as usize)
693 } else if let Some(section_0) = self.section_0(endian, data)? {
694 section_0
695 .sh_size(endian)
696 .into()
697 .try_into()
698 .ok()
699 .read_error("Invalid ELF extended e_shnum")
700 } else {
701 Ok(0)
703 }
704 }
705
706 fn shstrndx<'data, R: ReadRef<'data>>(
710 &self,
711 endian: Self::Endian,
712 data: R,
713 ) -> read::Result<u32> {
714 let e_shstrndx = self.e_shstrndx(endian);
715 let index = if e_shstrndx != elf::SHN_XINDEX {
716 e_shstrndx.into()
717 } else if let Some(section_0) = self.section_0(endian, data)? {
718 section_0.sh_link(endian)
719 } else {
720 return Err(Error("Missing ELF section headers for e_shstrndx overflow"));
722 };
723 if index == 0 {
724 return Err(Error("Missing ELF e_shstrndx"));
725 }
726 Ok(index)
727 }
728
729 fn program_headers<'data, R: ReadRef<'data>>(
734 &self,
735 endian: Self::Endian,
736 data: R,
737 ) -> read::Result<&'data [Self::ProgramHeader]> {
738 let phoff: u64 = self.e_phoff(endian).into();
739 if phoff == 0 {
740 return Ok(&[]);
742 }
743 let phnum = self.phnum(endian, data)?;
744 if phnum == 0 {
745 return Ok(&[]);
747 }
748 let phentsize = self.e_phentsize(endian) as usize;
749 if phentsize != mem::size_of::<Self::ProgramHeader>() {
750 return Err(Error("Invalid ELF program header entry size"));
752 }
753 data.read_slice_at(phoff, phnum)
754 .read_error("Invalid ELF program header size or alignment")
755 }
756
757 fn section_headers<'data, R: ReadRef<'data>>(
762 &self,
763 endian: Self::Endian,
764 data: R,
765 ) -> read::Result<&'data [Self::SectionHeader]> {
766 let shoff: u64 = self.e_shoff(endian).into();
767 if shoff == 0 {
768 return Ok(&[]);
770 }
771 let shnum = self.shnum(endian, data)?;
772 if shnum == 0 {
773 return Ok(&[]);
775 }
776 let shentsize = usize::from(self.e_shentsize(endian));
777 if shentsize != mem::size_of::<Self::SectionHeader>() {
778 return Err(Error("Invalid ELF section header entry size"));
780 }
781 data.read_slice_at(shoff, shnum)
782 .read_error("Invalid ELF section header offset/size/alignment")
783 }
784
785 fn section_strings_index<'data, R: ReadRef<'data>>(
789 &self,
790 endian: Self::Endian,
791 data: R,
792 ) -> read::Result<SectionIndex> {
793 self.shstrndx(endian, data)
794 .map(|index| SectionIndex(index as usize))
795 }
796
797 fn section_strings<'data, R: ReadRef<'data>>(
799 &self,
800 endian: Self::Endian,
801 data: R,
802 sections: &[Self::SectionHeader],
803 ) -> read::Result<StringTable<'data, R>> {
804 if sections.is_empty() {
805 return Ok(StringTable::default());
806 }
807 let index = self.section_strings_index(endian, data)?;
808 let shstrtab = sections.get(index.0).read_error("Invalid ELF e_shstrndx")?;
809 let strings = if let Some((shstrtab_offset, shstrtab_size)) = shstrtab.file_range(endian) {
810 let shstrtab_end = shstrtab_offset
811 .checked_add(shstrtab_size)
812 .read_error("Invalid ELF shstrtab size")?;
813 StringTable::new(data, shstrtab_offset, shstrtab_end)
814 } else {
815 StringTable::default()
816 };
817 Ok(strings)
818 }
819
820 fn sections<'data, R: ReadRef<'data>>(
822 &self,
823 endian: Self::Endian,
824 data: R,
825 ) -> read::Result<SectionTable<'data, Self, R>> {
826 let sections = self.section_headers(endian, data)?;
827 let strings = self.section_strings(endian, data, sections)?;
828 Ok(SectionTable::new(sections, strings))
829 }
830
831 fn is_mips64el(&self, endian: Self::Endian) -> bool {
833 self.is_class_64() && self.is_little_endian() && self.e_machine(endian) == elf::EM_MIPS
834 }
835}
836
837impl<Endian: endian::Endian> FileHeader for elf::FileHeader32<Endian> {
838 type Word = u32;
839 type Sword = i32;
840 type Endian = Endian;
841 type ProgramHeader = elf::ProgramHeader32<Endian>;
842 type SectionHeader = elf::SectionHeader32<Endian>;
843 type CompressionHeader = elf::CompressionHeader32<Endian>;
844 type NoteHeader = elf::NoteHeader32<Endian>;
845 type Dyn = elf::Dyn32<Endian>;
846 type Sym = elf::Sym32<Endian>;
847 type Rel = elf::Rel32<Endian>;
848 type Rela = elf::Rela32<Endian>;
849 type Relr = elf::Relr32<Endian>;
850
851 #[inline]
852 fn is_type_64(&self) -> bool {
853 false
854 }
855
856 #[inline]
857 fn is_type_64_sized() -> bool
858 where
859 Self: Sized,
860 {
861 false
862 }
863
864 #[inline]
865 fn e_ident(&self) -> &elf::Ident {
866 &self.e_ident
867 }
868
869 #[inline]
870 fn e_type(&self, endian: Self::Endian) -> u16 {
871 self.e_type.get(endian)
872 }
873
874 #[inline]
875 fn e_machine(&self, endian: Self::Endian) -> u16 {
876 self.e_machine.get(endian)
877 }
878
879 #[inline]
880 fn e_version(&self, endian: Self::Endian) -> u32 {
881 self.e_version.get(endian)
882 }
883
884 #[inline]
885 fn e_entry(&self, endian: Self::Endian) -> Self::Word {
886 self.e_entry.get(endian)
887 }
888
889 #[inline]
890 fn e_phoff(&self, endian: Self::Endian) -> Self::Word {
891 self.e_phoff.get(endian)
892 }
893
894 #[inline]
895 fn e_shoff(&self, endian: Self::Endian) -> Self::Word {
896 self.e_shoff.get(endian)
897 }
898
899 #[inline]
900 fn e_flags(&self, endian: Self::Endian) -> u32 {
901 self.e_flags.get(endian)
902 }
903
904 #[inline]
905 fn e_ehsize(&self, endian: Self::Endian) -> u16 {
906 self.e_ehsize.get(endian)
907 }
908
909 #[inline]
910 fn e_phentsize(&self, endian: Self::Endian) -> u16 {
911 self.e_phentsize.get(endian)
912 }
913
914 #[inline]
915 fn e_phnum(&self, endian: Self::Endian) -> u16 {
916 self.e_phnum.get(endian)
917 }
918
919 #[inline]
920 fn e_shentsize(&self, endian: Self::Endian) -> u16 {
921 self.e_shentsize.get(endian)
922 }
923
924 #[inline]
925 fn e_shnum(&self, endian: Self::Endian) -> u16 {
926 self.e_shnum.get(endian)
927 }
928
929 #[inline]
930 fn e_shstrndx(&self, endian: Self::Endian) -> u16 {
931 self.e_shstrndx.get(endian)
932 }
933}
934
935impl<Endian: endian::Endian> FileHeader for elf::FileHeader64<Endian> {
936 type Word = u64;
937 type Sword = i64;
938 type Endian = Endian;
939 type ProgramHeader = elf::ProgramHeader64<Endian>;
940 type SectionHeader = elf::SectionHeader64<Endian>;
941 type CompressionHeader = elf::CompressionHeader64<Endian>;
942 type NoteHeader = elf::NoteHeader32<Endian>;
943 type Dyn = elf::Dyn64<Endian>;
944 type Sym = elf::Sym64<Endian>;
945 type Rel = elf::Rel64<Endian>;
946 type Rela = elf::Rela64<Endian>;
947 type Relr = elf::Relr64<Endian>;
948
949 #[inline]
950 fn is_type_64(&self) -> bool {
951 true
952 }
953
954 #[inline]
955 fn is_type_64_sized() -> bool
956 where
957 Self: Sized,
958 {
959 true
960 }
961
962 #[inline]
963 fn e_ident(&self) -> &elf::Ident {
964 &self.e_ident
965 }
966
967 #[inline]
968 fn e_type(&self, endian: Self::Endian) -> u16 {
969 self.e_type.get(endian)
970 }
971
972 #[inline]
973 fn e_machine(&self, endian: Self::Endian) -> u16 {
974 self.e_machine.get(endian)
975 }
976
977 #[inline]
978 fn e_version(&self, endian: Self::Endian) -> u32 {
979 self.e_version.get(endian)
980 }
981
982 #[inline]
983 fn e_entry(&self, endian: Self::Endian) -> Self::Word {
984 self.e_entry.get(endian)
985 }
986
987 #[inline]
988 fn e_phoff(&self, endian: Self::Endian) -> Self::Word {
989 self.e_phoff.get(endian)
990 }
991
992 #[inline]
993 fn e_shoff(&self, endian: Self::Endian) -> Self::Word {
994 self.e_shoff.get(endian)
995 }
996
997 #[inline]
998 fn e_flags(&self, endian: Self::Endian) -> u32 {
999 self.e_flags.get(endian)
1000 }
1001
1002 #[inline]
1003 fn e_ehsize(&self, endian: Self::Endian) -> u16 {
1004 self.e_ehsize.get(endian)
1005 }
1006
1007 #[inline]
1008 fn e_phentsize(&self, endian: Self::Endian) -> u16 {
1009 self.e_phentsize.get(endian)
1010 }
1011
1012 #[inline]
1013 fn e_phnum(&self, endian: Self::Endian) -> u16 {
1014 self.e_phnum.get(endian)
1015 }
1016
1017 #[inline]
1018 fn e_shentsize(&self, endian: Self::Endian) -> u16 {
1019 self.e_shentsize.get(endian)
1020 }
1021
1022 #[inline]
1023 fn e_shnum(&self, endian: Self::Endian) -> u16 {
1024 self.e_shnum.get(endian)
1025 }
1026
1027 #[inline]
1028 fn e_shstrndx(&self, endian: Self::Endian) -> u16 {
1029 self.e_shstrndx.get(endian)
1030 }
1031}