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