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