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