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