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