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, 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> = ElfSegment<'data, 'file, Elf, R> where Self: 'file, 'data: 'file;
191 type SegmentIterator<'file> = ElfSegmentIterator<'data, 'file, Elf, R> where Self: 'file, 'data: 'file;
192 type Section<'file> = ElfSection<'data, 'file, Elf, R> where Self: 'file, 'data: 'file;
193 type SectionIterator<'file> = ElfSectionIterator<'data, 'file, Elf, R> where Self: 'file, 'data: 'file;
194 type Comdat<'file> = ElfComdat<'data, 'file, Elf, R> where Self: 'file, 'data: 'file;
195 type ComdatIterator<'file> = ElfComdatIterator<'data, 'file, Elf, R> where Self: 'file, 'data: 'file;
196 type Symbol<'file> = ElfSymbol<'data, 'file, Elf, R> where Self: 'file, 'data: 'file;
197 type SymbolIterator<'file> = ElfSymbolIterator<'data, 'file, Elf, R> where Self: 'file, 'data: 'file;
198 type SymbolTable<'file> = ElfSymbolTable<'data, 'file, Elf, R> where Self: 'file, 'data: 'file;
199 type DynamicRelocationIterator<'file> = ElfDynamicRelocationIterator<'data, 'file, Elf, R> where Self: 'file, 'data: 'file;
200
201 fn architecture(&self) -> Architecture {
202 match (
203 self.header.e_machine(self.endian),
204 self.header.is_class_64(),
205 ) {
206 (elf::EM_AARCH64, true) => Architecture::Aarch64,
207 (elf::EM_AARCH64, false) => Architecture::Aarch64_Ilp32,
208 (elf::EM_ARM, _) => Architecture::Arm,
209 (elf::EM_AVR, _) => Architecture::Avr,
210 (elf::EM_BPF, _) => Architecture::Bpf,
211 (elf::EM_CSKY, _) => Architecture::Csky,
212 (elf::EM_MCST_ELBRUS, false) => Architecture::E2K32,
213 (elf::EM_MCST_ELBRUS, true) => Architecture::E2K64,
214 (elf::EM_386, _) => Architecture::I386,
215 (elf::EM_X86_64, false) => Architecture::X86_64_X32,
216 (elf::EM_X86_64, true) => Architecture::X86_64,
217 (elf::EM_HEXAGON, _) => Architecture::Hexagon,
218 (elf::EM_LOONGARCH, true) => Architecture::LoongArch64,
219 (elf::EM_MIPS, false) => Architecture::Mips,
220 (elf::EM_MIPS, true) => Architecture::Mips64,
221 (elf::EM_MSP430, _) => Architecture::Msp430,
222 (elf::EM_PPC, _) => Architecture::PowerPc,
223 (elf::EM_PPC64, _) => Architecture::PowerPc64,
224 (elf::EM_RISCV, false) => Architecture::Riscv32,
225 (elf::EM_RISCV, true) => Architecture::Riscv64,
226 (elf::EM_S390, true) => Architecture::S390x,
229 (elf::EM_SBF, _) => Architecture::Sbf,
230 (elf::EM_SHARC, false) => Architecture::Sharc,
231 (elf::EM_SPARC, false) => Architecture::Sparc,
232 (elf::EM_SPARC32PLUS, false) => Architecture::Sparc32Plus,
233 (elf::EM_SPARCV9, true) => Architecture::Sparc64,
234 (elf::EM_XTENSA, false) => Architecture::Xtensa,
235 _ => Architecture::Unknown,
236 }
237 }
238
239 #[inline]
240 fn is_little_endian(&self) -> bool {
241 self.header.is_little_endian()
242 }
243
244 #[inline]
245 fn is_64(&self) -> bool {
246 self.header.is_class_64()
247 }
248
249 fn kind(&self) -> ObjectKind {
250 match self.header.e_type(self.endian) {
251 elf::ET_REL => ObjectKind::Relocatable,
252 elf::ET_EXEC => ObjectKind::Executable,
253 elf::ET_DYN => ObjectKind::Dynamic,
255 elf::ET_CORE => ObjectKind::Core,
256 _ => ObjectKind::Unknown,
257 }
258 }
259
260 fn segments(&self) -> ElfSegmentIterator<'data, '_, Elf, R> {
261 ElfSegmentIterator {
262 file: self,
263 iter: self.segments.iter(),
264 }
265 }
266
267 fn section_by_name_bytes<'file>(
268 &'file self,
269 section_name: &[u8],
270 ) -> Option<ElfSection<'data, 'file, Elf, R>> {
271 self.raw_section_by_name(section_name)
272 .or_else(|| self.zdebug_section_by_name(section_name))
273 }
274
275 fn section_by_index(&self, index: SectionIndex) -> read::Result<ElfSection<'data, '_, Elf, R>> {
276 let section = self.sections.section(index)?;
277 Ok(ElfSection {
278 file: self,
279 index,
280 section,
281 })
282 }
283
284 fn sections(&self) -> ElfSectionIterator<'data, '_, Elf, R> {
285 ElfSectionIterator::new(self)
286 }
287
288 fn comdats(&self) -> ElfComdatIterator<'data, '_, Elf, R> {
289 ElfComdatIterator::new(self)
290 }
291
292 fn symbol_by_index(&self, index: SymbolIndex) -> read::Result<ElfSymbol<'data, '_, Elf, R>> {
293 let symbol = self.symbols.symbol(index)?;
294 Ok(ElfSymbol {
295 endian: self.endian,
296 symbols: &self.symbols,
297 index,
298 symbol,
299 })
300 }
301
302 fn symbols(&self) -> ElfSymbolIterator<'data, '_, Elf, R> {
303 ElfSymbolIterator::new(self.endian, &self.symbols)
304 }
305
306 fn symbol_table(&self) -> Option<ElfSymbolTable<'data, '_, Elf, R>> {
307 if self.symbols.is_empty() {
308 return None;
309 }
310 Some(ElfSymbolTable {
311 endian: self.endian,
312 symbols: &self.symbols,
313 })
314 }
315
316 fn dynamic_symbols(&self) -> ElfSymbolIterator<'data, '_, Elf, R> {
317 ElfSymbolIterator::new(self.endian, &self.dynamic_symbols)
318 }
319
320 fn dynamic_symbol_table(&self) -> Option<ElfSymbolTable<'data, '_, Elf, R>> {
321 if self.dynamic_symbols.is_empty() {
322 return None;
323 }
324 Some(ElfSymbolTable {
325 endian: self.endian,
326 symbols: &self.dynamic_symbols,
327 })
328 }
329
330 fn dynamic_relocations<'file>(
331 &'file self,
332 ) -> Option<ElfDynamicRelocationIterator<'data, 'file, Elf, R>> {
333 Some(ElfDynamicRelocationIterator {
334 section_index: SectionIndex(1),
335 file: self,
336 relocations: None,
337 })
338 }
339
340 fn imports(&self) -> read::Result<Vec<Import<'data>>> {
341 let versions = self.sections.versions(self.endian, self.data)?;
342
343 let mut imports = Vec::new();
344 for (index, symbol) in self.dynamic_symbols.enumerate() {
345 if symbol.is_undefined(self.endian) {
346 let name = symbol.name(self.endian, self.dynamic_symbols.strings())?;
347 if !name.is_empty() {
348 let library = if let Some(svt) = versions.as_ref() {
349 let vi = svt.version_index(self.endian, index);
350 svt.version(vi)?.and_then(|v| v.file())
351 } else {
352 None
353 }
354 .unwrap_or(&[]);
355 imports.push(Import {
356 name: ByteString(name),
357 library: ByteString(library),
358 });
359 }
360 }
361 }
362 Ok(imports)
363 }
364
365 fn exports(&self) -> read::Result<Vec<Export<'data>>> {
366 let mut exports = Vec::new();
367 for symbol in self.dynamic_symbols.iter() {
368 if symbol.is_definition(self.endian) {
369 let name = symbol.name(self.endian, self.dynamic_symbols.strings())?;
370 let address = symbol.st_value(self.endian).into();
371 exports.push(Export {
372 name: ByteString(name),
373 address,
374 });
375 }
376 }
377 Ok(exports)
378 }
379
380 fn has_debug_symbols(&self) -> bool {
381 for section in self.sections.iter() {
382 if let Ok(name) = self.sections.section_name(self.endian, section) {
383 if name == b".debug_info" || name == b".zdebug_info" {
384 return true;
385 }
386 }
387 }
388 false
389 }
390
391 fn build_id(&self) -> read::Result<Option<&'data [u8]>> {
392 let endian = self.endian;
393 if !self.sections.is_empty() {
395 for section in self.sections.iter() {
396 if let Some(mut notes) = section.notes(endian, self.data)? {
397 while let Some(note) = notes.next()? {
398 if note.name() == elf::ELF_NOTE_GNU
399 && note.n_type(endian) == elf::NT_GNU_BUILD_ID
400 {
401 return Ok(Some(note.desc()));
402 }
403 }
404 }
405 }
406 } else {
407 for segment in self.segments {
408 if let Some(mut notes) = segment.notes(endian, self.data)? {
409 while let Some(note) = notes.next()? {
410 if note.name() == elf::ELF_NOTE_GNU
411 && note.n_type(endian) == elf::NT_GNU_BUILD_ID
412 {
413 return Ok(Some(note.desc()));
414 }
415 }
416 }
417 }
418 }
419 Ok(None)
420 }
421
422 fn gnu_debuglink(&self) -> read::Result<Option<(&'data [u8], u32)>> {
423 let section = match self.raw_section_by_name(b".gnu_debuglink") {
424 Some(section) => section,
425 None => return Ok(None),
426 };
427 let data = section
428 .section
429 .data(self.endian, self.data)
430 .read_error("Invalid ELF .gnu_debuglink section offset or size")
431 .map(Bytes)?;
432 let filename = data
433 .read_string_at(0)
434 .read_error("Missing ELF .gnu_debuglink filename")?;
435 let crc_offset = util::align(filename.len() + 1, 4);
436 let crc = data
437 .read_at::<U32<_>>(crc_offset)
438 .read_error("Missing ELF .gnu_debuglink crc")?
439 .get(self.endian);
440 Ok(Some((filename, crc)))
441 }
442
443 fn gnu_debugaltlink(&self) -> read::Result<Option<(&'data [u8], &'data [u8])>> {
444 let section = match self.raw_section_by_name(b".gnu_debugaltlink") {
445 Some(section) => section,
446 None => return Ok(None),
447 };
448 let mut data = section
449 .section
450 .data(self.endian, self.data)
451 .read_error("Invalid ELF .gnu_debugaltlink section offset or size")
452 .map(Bytes)?;
453 let filename = data
454 .read_string()
455 .read_error("Missing ELF .gnu_debugaltlink filename")?;
456 let build_id = data.0;
457 Ok(Some((filename, build_id)))
458 }
459
460 fn relative_address_base(&self) -> u64 {
461 0
462 }
463
464 fn entry(&self) -> u64 {
465 self.header.e_entry(self.endian).into()
466 }
467
468 fn flags(&self) -> FileFlags {
469 FileFlags::Elf {
470 os_abi: self.header.e_ident().os_abi,
471 abi_version: self.header.e_ident().abi_version,
472 e_flags: self.header.e_flags(self.endian),
473 }
474 }
475}
476
477#[allow(missing_docs)]
479pub trait FileHeader: Debug + Pod {
480 type Word: Into<u64>;
482 type Sword: Into<i64>;
483 type Endian: endian::Endian;
484 type ProgramHeader: ProgramHeader<Elf = Self, Endian = Self::Endian, Word = Self::Word>;
485 type SectionHeader: SectionHeader<Elf = Self, Endian = Self::Endian, Word = Self::Word>;
486 type CompressionHeader: CompressionHeader<Endian = Self::Endian, Word = Self::Word>;
487 type NoteHeader: NoteHeader<Endian = Self::Endian>;
488 type Dyn: Dyn<Endian = Self::Endian, Word = Self::Word>;
489 type Sym: Sym<Endian = Self::Endian, Word = Self::Word>;
490 type Rel: Rel<Endian = Self::Endian, Word = Self::Word>;
491 type Rela: Rela<Endian = Self::Endian, Word = Self::Word> + From<Self::Rel>;
492
493 fn is_type_64(&self) -> bool;
497
498 fn is_type_64_sized() -> bool
504 where
505 Self: Sized;
506
507 fn e_ident(&self) -> &elf::Ident;
508 fn e_type(&self, endian: Self::Endian) -> u16;
509 fn e_machine(&self, endian: Self::Endian) -> u16;
510 fn e_version(&self, endian: Self::Endian) -> u32;
511 fn e_entry(&self, endian: Self::Endian) -> Self::Word;
512 fn e_phoff(&self, endian: Self::Endian) -> Self::Word;
513 fn e_shoff(&self, endian: Self::Endian) -> Self::Word;
514 fn e_flags(&self, endian: Self::Endian) -> u32;
515 fn e_ehsize(&self, endian: Self::Endian) -> u16;
516 fn e_phentsize(&self, endian: Self::Endian) -> u16;
517 fn e_phnum(&self, endian: Self::Endian) -> u16;
518 fn e_shentsize(&self, endian: Self::Endian) -> u16;
519 fn e_shnum(&self, endian: Self::Endian) -> u16;
520 fn e_shstrndx(&self, endian: Self::Endian) -> u16;
521
522 fn parse<'data, R: ReadRef<'data>>(data: R) -> read::Result<&'data Self> {
528 let header = data
529 .read_at::<Self>(0)
530 .read_error("Invalid ELF header size or alignment")?;
531 if !header.is_supported() {
532 return Err(Error("Unsupported ELF header"));
533 }
534 Ok(header)
536 }
537
538 fn is_supported(&self) -> bool {
542 let ident = self.e_ident();
543 ident.magic == elf::ELFMAG
545 && (self.is_type_64() || self.is_class_32())
546 && (!self.is_type_64() || self.is_class_64())
547 && (self.is_little_endian() || self.is_big_endian())
548 && ident.version == elf::EV_CURRENT
549 }
550
551 fn is_class_32(&self) -> bool {
552 self.e_ident().class == elf::ELFCLASS32
553 }
554
555 fn is_class_64(&self) -> bool {
556 self.e_ident().class == elf::ELFCLASS64
557 }
558
559 fn is_little_endian(&self) -> bool {
560 self.e_ident().data == elf::ELFDATA2LSB
561 }
562
563 fn is_big_endian(&self) -> bool {
564 self.e_ident().data == elf::ELFDATA2MSB
565 }
566
567 fn endian(&self) -> read::Result<Self::Endian> {
568 Self::Endian::from_big_endian(self.is_big_endian()).read_error("Unsupported ELF endian")
569 }
570
571 fn section_0<'data, R: ReadRef<'data>>(
576 &self,
577 endian: Self::Endian,
578 data: R,
579 ) -> read::Result<Option<&'data Self::SectionHeader>> {
580 let shoff: u64 = self.e_shoff(endian).into();
581 if shoff == 0 {
582 return Ok(None);
584 }
585 let shentsize = usize::from(self.e_shentsize(endian));
586 if shentsize != mem::size_of::<Self::SectionHeader>() {
587 return Err(Error("Invalid ELF section header entry size"));
589 }
590 data.read_at(shoff)
591 .map(Some)
592 .read_error("Invalid ELF section header offset or size")
593 }
594
595 fn phnum<'data, R: ReadRef<'data>>(
599 &self,
600 endian: Self::Endian,
601 data: R,
602 ) -> read::Result<usize> {
603 let e_phnum = self.e_phnum(endian);
604 if e_phnum < elf::PN_XNUM {
605 Ok(e_phnum as usize)
606 } else if let Some(section_0) = self.section_0(endian, data)? {
607 Ok(section_0.sh_info(endian) as usize)
608 } else {
609 Err(Error("Missing ELF section headers for e_phnum overflow"))
611 }
612 }
613
614 fn shnum<'data, R: ReadRef<'data>>(
618 &self,
619 endian: Self::Endian,
620 data: R,
621 ) -> read::Result<usize> {
622 let e_shnum = self.e_shnum(endian);
623 if e_shnum > 0 {
624 Ok(e_shnum as usize)
625 } else if let Some(section_0) = self.section_0(endian, data)? {
626 section_0
627 .sh_size(endian)
628 .into()
629 .try_into()
630 .ok()
631 .read_error("Invalid ELF extended e_shnum")
632 } else {
633 Ok(0)
635 }
636 }
637
638 fn shstrndx<'data, R: ReadRef<'data>>(
642 &self,
643 endian: Self::Endian,
644 data: R,
645 ) -> read::Result<u32> {
646 let e_shstrndx = self.e_shstrndx(endian);
647 let index = if e_shstrndx != elf::SHN_XINDEX {
648 e_shstrndx.into()
649 } else if let Some(section_0) = self.section_0(endian, data)? {
650 section_0.sh_link(endian)
651 } else {
652 return Err(Error("Missing ELF section headers for e_shstrndx overflow"));
654 };
655 if index == 0 {
656 return Err(Error("Missing ELF e_shstrndx"));
657 }
658 Ok(index)
659 }
660
661 fn program_headers<'data, R: ReadRef<'data>>(
666 &self,
667 endian: Self::Endian,
668 data: R,
669 ) -> read::Result<&'data [Self::ProgramHeader]> {
670 let phoff: u64 = self.e_phoff(endian).into();
671 if phoff == 0 {
672 return Ok(&[]);
674 }
675 let phnum = self.phnum(endian, data)?;
676 if phnum == 0 {
677 return Ok(&[]);
679 }
680 let phentsize = self.e_phentsize(endian) as usize;
681 if phentsize != mem::size_of::<Self::ProgramHeader>() {
682 return Err(Error("Invalid ELF program header entry size"));
684 }
685 data.read_slice_at(phoff, phnum)
686 .read_error("Invalid ELF program header size or alignment")
687 }
688
689 fn section_headers<'data, R: ReadRef<'data>>(
694 &self,
695 endian: Self::Endian,
696 data: R,
697 ) -> read::Result<&'data [Self::SectionHeader]> {
698 let shoff: u64 = self.e_shoff(endian).into();
699 if shoff == 0 {
700 return Ok(&[]);
702 }
703 let shnum = self.shnum(endian, data)?;
704 if shnum == 0 {
705 return Ok(&[]);
707 }
708 let shentsize = usize::from(self.e_shentsize(endian));
709 if shentsize != mem::size_of::<Self::SectionHeader>() {
710 return Err(Error("Invalid ELF section header entry size"));
712 }
713 data.read_slice_at(shoff, shnum)
714 .read_error("Invalid ELF section header offset/size/alignment")
715 }
716
717 fn section_strings_index<'data, R: ReadRef<'data>>(
721 &self,
722 endian: Self::Endian,
723 data: R,
724 ) -> read::Result<SectionIndex> {
725 self.shstrndx(endian, data)
726 .map(|index| SectionIndex(index as usize))
727 }
728
729 fn section_strings<'data, R: ReadRef<'data>>(
731 &self,
732 endian: Self::Endian,
733 data: R,
734 sections: &[Self::SectionHeader],
735 ) -> read::Result<StringTable<'data, R>> {
736 if sections.is_empty() {
737 return Ok(StringTable::default());
738 }
739 let index = self.section_strings_index(endian, data)?;
740 let shstrtab = sections.get(index.0).read_error("Invalid ELF e_shstrndx")?;
741 let strings = if let Some((shstrtab_offset, shstrtab_size)) = shstrtab.file_range(endian) {
742 let shstrtab_end = shstrtab_offset
743 .checked_add(shstrtab_size)
744 .read_error("Invalid ELF shstrtab size")?;
745 StringTable::new(data, shstrtab_offset, shstrtab_end)
746 } else {
747 StringTable::default()
748 };
749 Ok(strings)
750 }
751
752 fn sections<'data, R: ReadRef<'data>>(
754 &self,
755 endian: Self::Endian,
756 data: R,
757 ) -> read::Result<SectionTable<'data, Self, R>> {
758 let sections = self.section_headers(endian, data)?;
759 let strings = self.section_strings(endian, data, sections)?;
760 Ok(SectionTable::new(sections, strings))
761 }
762
763 fn is_mips64el(&self, endian: Self::Endian) -> bool {
765 self.is_class_64() && self.is_little_endian() && self.e_machine(endian) == elf::EM_MIPS
766 }
767}
768
769impl<Endian: endian::Endian> FileHeader for elf::FileHeader32<Endian> {
770 type Word = u32;
771 type Sword = i32;
772 type Endian = Endian;
773 type ProgramHeader = elf::ProgramHeader32<Endian>;
774 type SectionHeader = elf::SectionHeader32<Endian>;
775 type CompressionHeader = elf::CompressionHeader32<Endian>;
776 type NoteHeader = elf::NoteHeader32<Endian>;
777 type Dyn = elf::Dyn32<Endian>;
778 type Sym = elf::Sym32<Endian>;
779 type Rel = elf::Rel32<Endian>;
780 type Rela = elf::Rela32<Endian>;
781
782 #[inline]
783 fn is_type_64(&self) -> bool {
784 false
785 }
786
787 #[inline]
788 fn is_type_64_sized() -> bool
789 where
790 Self: Sized,
791 {
792 false
793 }
794
795 #[inline]
796 fn e_ident(&self) -> &elf::Ident {
797 &self.e_ident
798 }
799
800 #[inline]
801 fn e_type(&self, endian: Self::Endian) -> u16 {
802 self.e_type.get(endian)
803 }
804
805 #[inline]
806 fn e_machine(&self, endian: Self::Endian) -> u16 {
807 self.e_machine.get(endian)
808 }
809
810 #[inline]
811 fn e_version(&self, endian: Self::Endian) -> u32 {
812 self.e_version.get(endian)
813 }
814
815 #[inline]
816 fn e_entry(&self, endian: Self::Endian) -> Self::Word {
817 self.e_entry.get(endian)
818 }
819
820 #[inline]
821 fn e_phoff(&self, endian: Self::Endian) -> Self::Word {
822 self.e_phoff.get(endian)
823 }
824
825 #[inline]
826 fn e_shoff(&self, endian: Self::Endian) -> Self::Word {
827 self.e_shoff.get(endian)
828 }
829
830 #[inline]
831 fn e_flags(&self, endian: Self::Endian) -> u32 {
832 self.e_flags.get(endian)
833 }
834
835 #[inline]
836 fn e_ehsize(&self, endian: Self::Endian) -> u16 {
837 self.e_ehsize.get(endian)
838 }
839
840 #[inline]
841 fn e_phentsize(&self, endian: Self::Endian) -> u16 {
842 self.e_phentsize.get(endian)
843 }
844
845 #[inline]
846 fn e_phnum(&self, endian: Self::Endian) -> u16 {
847 self.e_phnum.get(endian)
848 }
849
850 #[inline]
851 fn e_shentsize(&self, endian: Self::Endian) -> u16 {
852 self.e_shentsize.get(endian)
853 }
854
855 #[inline]
856 fn e_shnum(&self, endian: Self::Endian) -> u16 {
857 self.e_shnum.get(endian)
858 }
859
860 #[inline]
861 fn e_shstrndx(&self, endian: Self::Endian) -> u16 {
862 self.e_shstrndx.get(endian)
863 }
864}
865
866impl<Endian: endian::Endian> FileHeader for elf::FileHeader64<Endian> {
867 type Word = u64;
868 type Sword = i64;
869 type Endian = Endian;
870 type ProgramHeader = elf::ProgramHeader64<Endian>;
871 type SectionHeader = elf::SectionHeader64<Endian>;
872 type CompressionHeader = elf::CompressionHeader64<Endian>;
873 type NoteHeader = elf::NoteHeader32<Endian>;
874 type Dyn = elf::Dyn64<Endian>;
875 type Sym = elf::Sym64<Endian>;
876 type Rel = elf::Rel64<Endian>;
877 type Rela = elf::Rela64<Endian>;
878
879 #[inline]
880 fn is_type_64(&self) -> bool {
881 true
882 }
883
884 #[inline]
885 fn is_type_64_sized() -> bool
886 where
887 Self: Sized,
888 {
889 true
890 }
891
892 #[inline]
893 fn e_ident(&self) -> &elf::Ident {
894 &self.e_ident
895 }
896
897 #[inline]
898 fn e_type(&self, endian: Self::Endian) -> u16 {
899 self.e_type.get(endian)
900 }
901
902 #[inline]
903 fn e_machine(&self, endian: Self::Endian) -> u16 {
904 self.e_machine.get(endian)
905 }
906
907 #[inline]
908 fn e_version(&self, endian: Self::Endian) -> u32 {
909 self.e_version.get(endian)
910 }
911
912 #[inline]
913 fn e_entry(&self, endian: Self::Endian) -> Self::Word {
914 self.e_entry.get(endian)
915 }
916
917 #[inline]
918 fn e_phoff(&self, endian: Self::Endian) -> Self::Word {
919 self.e_phoff.get(endian)
920 }
921
922 #[inline]
923 fn e_shoff(&self, endian: Self::Endian) -> Self::Word {
924 self.e_shoff.get(endian)
925 }
926
927 #[inline]
928 fn e_flags(&self, endian: Self::Endian) -> u32 {
929 self.e_flags.get(endian)
930 }
931
932 #[inline]
933 fn e_ehsize(&self, endian: Self::Endian) -> u16 {
934 self.e_ehsize.get(endian)
935 }
936
937 #[inline]
938 fn e_phentsize(&self, endian: Self::Endian) -> u16 {
939 self.e_phentsize.get(endian)
940 }
941
942 #[inline]
943 fn e_phnum(&self, endian: Self::Endian) -> u16 {
944 self.e_phnum.get(endian)
945 }
946
947 #[inline]
948 fn e_shentsize(&self, endian: Self::Endian) -> u16 {
949 self.e_shentsize.get(endian)
950 }
951
952 #[inline]
953 fn e_shnum(&self, endian: Self::Endian) -> u16 {
954 self.e_shnum.get(endian)
955 }
956
957 #[inline]
958 fn e_shstrndx(&self, endian: Self::Endian) -> u16 {
959 self.e_shstrndx.get(endian)
960 }
961}