1use core::fmt::Debug;
2use core::{iter, slice, str};
3
4use crate::elf;
5use crate::endian::{self, Endianness, U32};
6use crate::pod::{self, Pod};
7use crate::read::{
8 self, gnu_compression, CompressedData, CompressedFileRange, CompressionFormat, Error,
9 ObjectSection, ReadError, ReadRef, RelocationMap, SectionFlags, SectionIndex, SectionKind,
10 StringTable,
11};
12
13use super::{
14 AttributesSection, CompressionHeader, CrelIterator, DynamicTable, ElfFile,
15 ElfSectionRelocationIterator, FileHeader, GnuHashTable, HashTable, NoteIterator,
16 RelocationSections, RelrIterator, SymbolTable, VerdefIterator, VerneedIterator, VersionTable,
17};
18
19#[derive(Debug, Clone, Copy)]
25pub struct SectionTable<'data, Elf: FileHeader, R = &'data [u8]>
26where
27 R: ReadRef<'data>,
28{
29 sections: &'data [Elf::SectionHeader],
30 strings: StringTable<'data, R>,
31}
32
33impl<'data, Elf: FileHeader, R: ReadRef<'data>> Default for SectionTable<'data, Elf, R> {
34 fn default() -> Self {
35 SectionTable {
36 sections: &[],
37 strings: StringTable::default(),
38 }
39 }
40}
41
42impl<'data, Elf: FileHeader, R: ReadRef<'data>> SectionTable<'data, Elf, R> {
43 #[inline]
45 pub fn new(sections: &'data [Elf::SectionHeader], strings: StringTable<'data, R>) -> Self {
46 SectionTable { sections, strings }
47 }
48
49 #[inline]
53 pub fn iter(&self) -> slice::Iter<'data, Elf::SectionHeader> {
54 self.sections.iter()
55 }
56
57 #[inline]
61 pub fn enumerate(&self) -> impl Iterator<Item = (SectionIndex, &'data Elf::SectionHeader)> {
62 self.sections
63 .iter()
64 .enumerate()
65 .map(|(i, section)| (SectionIndex(i), section))
66 }
67
68 #[inline]
70 pub fn is_empty(&self) -> bool {
71 self.sections.is_empty()
72 }
73
74 #[inline]
76 pub fn len(&self) -> usize {
77 self.sections.len()
78 }
79
80 pub fn section(&self, index: SectionIndex) -> read::Result<&'data Elf::SectionHeader> {
84 if index == SectionIndex(0) {
85 return Err(read::Error("Invalid ELF section index"));
86 }
87 self.sections
88 .get(index.0)
89 .read_error("Invalid ELF section index")
90 }
91
92 pub fn section_by_name(
96 &self,
97 endian: Elf::Endian,
98 name: &[u8],
99 ) -> Option<(SectionIndex, &'data Elf::SectionHeader)> {
100 self.enumerate()
101 .find(|(_, section)| self.section_name(endian, section) == Ok(name))
102 }
103
104 pub fn section_name(
106 &self,
107 endian: Elf::Endian,
108 section: &Elf::SectionHeader,
109 ) -> read::Result<&'data [u8]> {
110 section.name(endian, self.strings)
111 }
112
113 #[inline]
118 pub fn strings(
119 &self,
120 endian: Elf::Endian,
121 data: R,
122 index: SectionIndex,
123 ) -> read::Result<StringTable<'data, R>> {
124 if index == SectionIndex(0) {
125 return Ok(StringTable::default());
126 }
127 self.section(index)?
128 .strings(endian, data)?
129 .read_error("Invalid ELF string section type")
130 }
131
132 #[inline]
136 pub fn symbols(
137 &self,
138 endian: Elf::Endian,
139 data: R,
140 sh_type: u32,
141 ) -> read::Result<SymbolTable<'data, Elf, R>> {
142 debug_assert!(sh_type == elf::SHT_DYNSYM || sh_type == elf::SHT_SYMTAB);
143
144 let (index, section) = match self.enumerate().find(|s| s.1.sh_type(endian) == sh_type) {
145 Some(s) => s,
146 None => return Ok(SymbolTable::default()),
147 };
148
149 SymbolTable::parse(endian, data, self, index, section)
150 }
151
152 #[inline]
156 pub fn symbol_table_by_index(
157 &self,
158 endian: Elf::Endian,
159 data: R,
160 index: SectionIndex,
161 ) -> read::Result<SymbolTable<'data, Elf, R>> {
162 let section = self.section(index)?;
163 match section.sh_type(endian) {
164 elf::SHT_DYNSYM | elf::SHT_SYMTAB => {}
165 _ => return Err(Error("Invalid ELF symbol table section type")),
166 }
167 SymbolTable::parse(endian, data, self, index, section)
168 }
169
170 #[inline]
172 pub fn relocation_sections(
173 &self,
174 endian: Elf::Endian,
175 symbol_section: SectionIndex,
176 ) -> read::Result<RelocationSections> {
177 RelocationSections::parse(endian, self, symbol_section)
178 }
179
180 pub fn dynamic_table(
184 &self,
185 endian: Elf::Endian,
186 data: R,
187 ) -> read::Result<DynamicTable<'data, Elf, R>> {
188 let section = match self.iter().find(|s| s.sh_type(endian) == elf::SHT_DYNAMIC) {
189 Some(s) => s,
190 None => return Ok(DynamicTable::default()),
191 };
192 DynamicTable::parse(endian, data, self, section)
193 }
194
195 pub fn dynamic(
202 &self,
203 endian: Elf::Endian,
204 data: R,
205 ) -> read::Result<Option<(&'data [Elf::Dyn], SectionIndex)>> {
206 for section in self.sections {
207 if let Some(dynamic) = section.dynamic(endian, data)? {
208 return Ok(Some(dynamic));
209 }
210 }
211 Ok(None)
212 }
213
214 pub fn hash_header(
219 &self,
220 endian: Elf::Endian,
221 data: R,
222 ) -> read::Result<Option<&'data elf::HashHeader<Elf::Endian>>> {
223 for section in self.sections {
224 if let Some(hash) = section.hash_header(endian, data)? {
225 return Ok(Some(hash));
226 }
227 }
228 Ok(None)
229 }
230
231 pub fn hash(
238 &self,
239 endian: Elf::Endian,
240 data: R,
241 ) -> read::Result<Option<(HashTable<'data, Elf>, SectionIndex)>> {
242 for section in self.sections {
243 if let Some(hash) = section.hash(endian, data)? {
244 return Ok(Some(hash));
245 }
246 }
247 Ok(None)
248 }
249
250 pub fn gnu_hash_header(
255 &self,
256 endian: Elf::Endian,
257 data: R,
258 ) -> read::Result<Option<&'data elf::GnuHashHeader<Elf::Endian>>> {
259 for section in self.sections {
260 if let Some(hash) = section.gnu_hash_header(endian, data)? {
261 return Ok(Some(hash));
262 }
263 }
264 Ok(None)
265 }
266
267 pub fn gnu_hash(
274 &self,
275 endian: Elf::Endian,
276 data: R,
277 ) -> read::Result<Option<(GnuHashTable<'data, Elf>, SectionIndex)>> {
278 for section in self.sections {
279 if let Some(hash) = section.gnu_hash(endian, data)? {
280 return Ok(Some(hash));
281 }
282 }
283 Ok(None)
284 }
285
286 pub fn gnu_versym(
293 &self,
294 endian: Elf::Endian,
295 data: R,
296 ) -> read::Result<Option<(&'data [elf::Versym<Elf::Endian>], SectionIndex)>> {
297 for section in self.sections {
298 if let Some(syms) = section.gnu_versym(endian, data)? {
299 return Ok(Some(syms));
300 }
301 }
302 Ok(None)
303 }
304
305 pub fn gnu_verdef(
312 &self,
313 endian: Elf::Endian,
314 data: R,
315 ) -> read::Result<Option<(VerdefIterator<'data, Elf>, SectionIndex)>> {
316 for section in self.sections {
317 if let Some(defs) = section.gnu_verdef(endian, data)? {
318 return Ok(Some(defs));
319 }
320 }
321 Ok(None)
322 }
323
324 pub fn gnu_verneed(
331 &self,
332 endian: Elf::Endian,
333 data: R,
334 ) -> read::Result<Option<(VerneedIterator<'data, Elf>, SectionIndex)>> {
335 for section in self.sections {
336 if let Some(needs) = section.gnu_verneed(endian, data)? {
337 return Ok(Some(needs));
338 }
339 }
340 Ok(None)
341 }
342
343 pub fn versions(
348 &self,
349 endian: Elf::Endian,
350 data: R,
351 ) -> read::Result<Option<VersionTable<'data, Elf>>> {
352 let (versyms, link) = match self.gnu_versym(endian, data)? {
353 Some(val) => val,
354 None => return Ok(None),
355 };
356 let strings = self.symbol_table_by_index(endian, data, link)?.strings();
357 let verdefs = self.gnu_verdef(endian, data)?.map(|x| x.0);
359 let verneeds = self.gnu_verneed(endian, data)?.map(|x| x.0);
360 VersionTable::parse(endian, versyms, verdefs, verneeds, strings).map(Some)
361 }
362}
363
364pub type ElfSectionIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
366 ElfSectionIterator<'data, 'file, elf::FileHeader32<Endian>, R>;
367pub type ElfSectionIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
369 ElfSectionIterator<'data, 'file, elf::FileHeader64<Endian>, R>;
370
371#[derive(Debug)]
373pub struct ElfSectionIterator<'data, 'file, Elf, R = &'data [u8]>
374where
375 Elf: FileHeader,
376 R: ReadRef<'data>,
377{
378 file: &'file ElfFile<'data, Elf, R>,
379 iter: iter::Enumerate<slice::Iter<'data, Elf::SectionHeader>>,
380}
381
382impl<'data, 'file, Elf, R> ElfSectionIterator<'data, 'file, Elf, R>
383where
384 Elf: FileHeader,
385 R: ReadRef<'data>,
386{
387 pub(super) fn new(file: &'file ElfFile<'data, Elf, R>) -> Self {
388 let mut iter = file.sections.iter().enumerate();
389 iter.next(); ElfSectionIterator { file, iter }
391 }
392}
393
394impl<'data, 'file, Elf, R> Iterator for ElfSectionIterator<'data, 'file, Elf, R>
395where
396 Elf: FileHeader,
397 R: ReadRef<'data>,
398{
399 type Item = ElfSection<'data, 'file, Elf, R>;
400
401 fn next(&mut self) -> Option<Self::Item> {
402 self.iter.next().map(|(index, section)| ElfSection {
403 index: SectionIndex(index),
404 file: self.file,
405 section,
406 })
407 }
408}
409
410pub type ElfSection32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
412 ElfSection<'data, 'file, elf::FileHeader32<Endian>, R>;
413pub type ElfSection64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
415 ElfSection<'data, 'file, elf::FileHeader64<Endian>, R>;
416
417#[derive(Debug)]
421pub struct ElfSection<'data, 'file, Elf, R = &'data [u8]>
422where
423 Elf: FileHeader,
424 R: ReadRef<'data>,
425{
426 pub(super) file: &'file ElfFile<'data, Elf, R>,
427 pub(super) index: SectionIndex,
428 pub(super) section: &'data Elf::SectionHeader,
429}
430
431impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> ElfSection<'data, 'file, Elf, R> {
432 pub fn elf_file(&self) -> &'file ElfFile<'data, Elf, R> {
434 self.file
435 }
436
437 pub fn elf_section_header(&self) -> &'data Elf::SectionHeader {
439 self.section
440 }
441
442 pub fn elf_relocation_section_index(&self) -> read::Result<Option<SectionIndex>> {
447 let Some(relocation_index) = self.file.relocations.get(self.index) else {
448 return Ok(None);
449 };
450 if self.file.relocations.get(relocation_index).is_some() {
451 return Err(Error(
452 "Unsupported ELF section with multiple relocation sections",
453 ));
454 }
455 Ok(Some(relocation_index))
456 }
457
458 pub fn elf_relocation_section(&self) -> read::Result<Option<&'data Elf::SectionHeader>> {
463 let Some(relocation_index) = self.elf_relocation_section_index()? else {
464 return Ok(None);
465 };
466 self.file.sections.section(relocation_index).map(Some)
467 }
468
469 pub fn elf_linked_rel(&self) -> read::Result<&'data [Elf::Rel]> {
474 let Some(relocation_section) = self.elf_relocation_section()? else {
475 return Ok(&[]);
476 };
477 let Some((rel, _)) = relocation_section.rel(self.file.endian, self.file.data.0)? else {
479 return Ok(&[]);
480 };
481 Ok(rel)
482 }
483
484 pub fn elf_linked_rela(&self) -> read::Result<&'data [Elf::Rela]> {
489 let Some(relocation_section) = self.elf_relocation_section()? else {
490 return Ok(&[]);
491 };
492 let Some((rela, _)) = relocation_section.rela(self.file.endian, self.file.data.0)? else {
494 return Ok(&[]);
495 };
496 Ok(rela)
497 }
498
499 fn bytes(&self) -> read::Result<&'data [u8]> {
500 self.section
501 .data(self.file.endian, self.file.data.0)
502 .read_error("Invalid ELF section size or offset")
503 }
504
505 fn maybe_compressed(&self) -> read::Result<Option<CompressedFileRange>> {
506 let endian = self.file.endian;
507 if let Some((header, offset, compressed_size)) =
508 self.section.compression(endian, self.file.data.0)?
509 {
510 let format = match header.ch_type(endian) {
511 elf::ELFCOMPRESS_ZLIB => CompressionFormat::Zlib,
512 elf::ELFCOMPRESS_ZSTD => CompressionFormat::Zstandard,
513 _ => return Err(Error("Unsupported ELF compression type")),
514 };
515 let uncompressed_size = header.ch_size(endian).into();
516 Ok(Some(CompressedFileRange {
517 format,
518 offset,
519 compressed_size,
520 uncompressed_size,
521 }))
522 } else {
523 Ok(None)
524 }
525 }
526
527 fn maybe_compressed_gnu(&self) -> read::Result<Option<CompressedFileRange>> {
529 if !self
530 .name()
531 .map_or(false, |name| name.starts_with(".zdebug_"))
532 {
533 return Ok(None);
534 }
535 let (section_offset, section_size) = self
536 .file_range()
537 .read_error("Invalid ELF GNU compressed section type")?;
538 gnu_compression::compressed_file_range(self.file.data.0, section_offset, section_size)
539 .map(Some)
540 }
541}
542
543impl<'data, 'file, Elf, R> read::private::Sealed for ElfSection<'data, 'file, Elf, R>
544where
545 Elf: FileHeader,
546 R: ReadRef<'data>,
547{
548}
549
550impl<'data, 'file, Elf, R> ObjectSection<'data> for ElfSection<'data, 'file, Elf, R>
551where
552 Elf: FileHeader,
553 R: ReadRef<'data>,
554{
555 type RelocationIterator = ElfSectionRelocationIterator<'data, 'file, Elf, R>;
556
557 #[inline]
558 fn index(&self) -> SectionIndex {
559 self.index
560 }
561
562 #[inline]
563 fn address(&self) -> u64 {
564 self.section.sh_addr(self.file.endian).into()
565 }
566
567 #[inline]
568 fn size(&self) -> u64 {
569 self.section.sh_size(self.file.endian).into()
570 }
571
572 #[inline]
573 fn align(&self) -> u64 {
574 self.section.sh_addralign(self.file.endian).into()
575 }
576
577 #[inline]
578 fn file_range(&self) -> Option<(u64, u64)> {
579 self.section.file_range(self.file.endian)
580 }
581
582 #[inline]
583 fn data(&self) -> read::Result<&'data [u8]> {
584 self.bytes()
585 }
586
587 fn data_range(&self, address: u64, size: u64) -> read::Result<Option<&'data [u8]>> {
588 Ok(read::util::data_range(
589 self.bytes()?,
590 self.address(),
591 address,
592 size,
593 ))
594 }
595
596 fn compressed_file_range(&self) -> read::Result<CompressedFileRange> {
597 Ok(if let Some(data) = self.maybe_compressed()? {
598 data
599 } else if let Some(data) = self.maybe_compressed_gnu()? {
600 data
601 } else {
602 CompressedFileRange::none(self.file_range())
603 })
604 }
605
606 fn compressed_data(&self) -> read::Result<CompressedData<'data>> {
607 self.compressed_file_range()?.data(self.file.data.0)
608 }
609
610 fn name_bytes(&self) -> read::Result<&'data [u8]> {
611 self.file
612 .sections
613 .section_name(self.file.endian, self.section)
614 }
615
616 fn name(&self) -> read::Result<&'data str> {
617 let name = self.name_bytes()?;
618 str::from_utf8(name)
619 .ok()
620 .read_error("Non UTF-8 ELF section name")
621 }
622
623 #[inline]
624 fn segment_name_bytes(&self) -> read::Result<Option<&[u8]>> {
625 Ok(None)
626 }
627
628 #[inline]
629 fn segment_name(&self) -> read::Result<Option<&str>> {
630 Ok(None)
631 }
632
633 fn kind(&self) -> SectionKind {
634 let flags = self.section.sh_flags(self.file.endian).into();
635 let sh_type = self.section.sh_type(self.file.endian);
636 match sh_type {
637 elf::SHT_PROGBITS => {
638 if flags & u64::from(elf::SHF_ALLOC) != 0 {
639 if flags & u64::from(elf::SHF_EXECINSTR) != 0 {
640 SectionKind::Text
641 } else if flags & u64::from(elf::SHF_TLS) != 0 {
642 SectionKind::Tls
643 } else if flags & u64::from(elf::SHF_WRITE) != 0 {
644 SectionKind::Data
645 } else if flags & u64::from(elf::SHF_STRINGS) != 0 {
646 SectionKind::ReadOnlyString
647 } else {
648 SectionKind::ReadOnlyData
649 }
650 } else if flags & u64::from(elf::SHF_STRINGS) != 0 {
651 SectionKind::OtherString
652 } else {
653 SectionKind::Other
654 }
655 }
656 elf::SHT_NOBITS => {
657 if flags & u64::from(elf::SHF_TLS) != 0 {
658 SectionKind::UninitializedTls
659 } else {
660 SectionKind::UninitializedData
661 }
662 }
663 elf::SHT_NOTE => SectionKind::Note,
664 elf::SHT_NULL
665 | elf::SHT_SYMTAB
666 | elf::SHT_STRTAB
667 | elf::SHT_RELA
668 | elf::SHT_HASH
669 | elf::SHT_DYNAMIC
670 | elf::SHT_REL
671 | elf::SHT_DYNSYM
672 | elf::SHT_GROUP
673 | elf::SHT_SYMTAB_SHNDX
674 | elf::SHT_RELR
675 | elf::SHT_CREL => SectionKind::Metadata,
676 _ => SectionKind::Elf(sh_type),
677 }
678 }
679
680 fn relocations(&self) -> ElfSectionRelocationIterator<'data, 'file, Elf, R> {
681 ElfSectionRelocationIterator {
682 section_index: self.index,
683 file: self.file,
684 relocations: None,
685 }
686 }
687
688 fn relocation_map(&self) -> read::Result<RelocationMap> {
689 RelocationMap::new(self.file, self)
690 }
691
692 fn flags(&self) -> SectionFlags {
693 SectionFlags::Elf {
694 sh_flags: self.section.sh_flags(self.file.endian).into(),
695 }
696 }
697}
698
699#[allow(missing_docs)]
701pub trait SectionHeader: Debug + Pod {
702 type Elf: FileHeader<SectionHeader = Self, Endian = Self::Endian, Word = Self::Word>;
703 type Word: Into<u64>;
704 type Endian: endian::Endian;
705
706 fn sh_name(&self, endian: Self::Endian) -> u32;
707 fn sh_type(&self, endian: Self::Endian) -> u32;
708 fn sh_flags(&self, endian: Self::Endian) -> Self::Word;
709 fn sh_addr(&self, endian: Self::Endian) -> Self::Word;
710 fn sh_offset(&self, endian: Self::Endian) -> Self::Word;
711 fn sh_size(&self, endian: Self::Endian) -> Self::Word;
712 fn sh_link(&self, endian: Self::Endian) -> u32;
713 fn sh_info(&self, endian: Self::Endian) -> u32;
714 fn sh_addralign(&self, endian: Self::Endian) -> Self::Word;
715 fn sh_entsize(&self, endian: Self::Endian) -> Self::Word;
716
717 fn name<'data, R: ReadRef<'data>>(
719 &self,
720 endian: Self::Endian,
721 strings: StringTable<'data, R>,
722 ) -> read::Result<&'data [u8]> {
723 strings
724 .get(self.sh_name(endian))
725 .read_error("Invalid ELF section name offset")
726 }
727
728 fn link(&self, endian: Self::Endian) -> SectionIndex {
732 SectionIndex(self.sh_link(endian) as usize)
733 }
734
735 fn has_info_link(&self, endian: Self::Endian) -> bool {
737 self.sh_flags(endian).into() & u64::from(elf::SHF_INFO_LINK) != 0
738 }
739
740 fn info_link(&self, endian: Self::Endian) -> SectionIndex {
745 SectionIndex(self.sh_info(endian) as usize)
746 }
747
748 fn file_range(&self, endian: Self::Endian) -> Option<(u64, u64)> {
752 if self.sh_type(endian) == elf::SHT_NOBITS {
753 None
754 } else {
755 Some((self.sh_offset(endian).into(), self.sh_size(endian).into()))
756 }
757 }
758
759 fn data<'data, R: ReadRef<'data>>(
764 &self,
765 endian: Self::Endian,
766 data: R,
767 ) -> read::Result<&'data [u8]> {
768 if let Some((offset, size)) = self.file_range(endian) {
769 data.read_bytes_at(offset, size)
770 .read_error("Invalid ELF section size or offset")
771 } else {
772 Ok(&[])
773 }
774 }
775
776 fn data_as_array<'data, T: Pod, R: ReadRef<'data>>(
782 &self,
783 endian: Self::Endian,
784 data: R,
785 ) -> read::Result<&'data [T]> {
786 pod::slice_from_all_bytes(self.data(endian, data)?)
787 .read_error("Invalid ELF section size or offset")
788 }
789
790 fn strings<'data, R: ReadRef<'data>>(
795 &self,
796 endian: Self::Endian,
797 data: R,
798 ) -> read::Result<Option<StringTable<'data, R>>> {
799 if self.sh_type(endian) != elf::SHT_STRTAB {
800 return Ok(None);
801 }
802 let str_offset = self.sh_offset(endian).into();
803 let str_size = self.sh_size(endian).into();
804 let str_end = str_offset
805 .checked_add(str_size)
806 .read_error("Invalid ELF string section offset or size")?;
807 Ok(Some(StringTable::new(data, str_offset, str_end)))
808 }
809
810 fn symbols<'data, R: ReadRef<'data>>(
820 &self,
821 endian: Self::Endian,
822 data: R,
823 sections: &SectionTable<'data, Self::Elf, R>,
824 section_index: SectionIndex,
825 ) -> read::Result<Option<SymbolTable<'data, Self::Elf, R>>> {
826 let sh_type = self.sh_type(endian);
827 if sh_type != elf::SHT_SYMTAB && sh_type != elf::SHT_DYNSYM {
828 return Ok(None);
829 }
830 SymbolTable::parse(endian, data, sections, section_index, self).map(Some)
831 }
832
833 fn rel<'data, R: ReadRef<'data>>(
840 &self,
841 endian: Self::Endian,
842 data: R,
843 ) -> read::Result<Option<(&'data [<Self::Elf as FileHeader>::Rel], SectionIndex)>> {
844 if self.sh_type(endian) != elf::SHT_REL {
845 return Ok(None);
846 }
847 let rel = self
848 .data_as_array(endian, data)
849 .read_error("Invalid ELF relocation section offset or size")?;
850 Ok(Some((rel, self.link(endian))))
851 }
852
853 fn rela<'data, R: ReadRef<'data>>(
860 &self,
861 endian: Self::Endian,
862 data: R,
863 ) -> read::Result<Option<(&'data [<Self::Elf as FileHeader>::Rela], SectionIndex)>> {
864 if self.sh_type(endian) != elf::SHT_RELA {
865 return Ok(None);
866 }
867 let rela = self
868 .data_as_array(endian, data)
869 .read_error("Invalid ELF relocation section offset or size")?;
870 Ok(Some((rela, self.link(endian))))
871 }
872
873 fn relr<'data, R: ReadRef<'data>>(
878 &self,
879 endian: Self::Endian,
880 data: R,
881 ) -> read::Result<Option<RelrIterator<'data, Self::Elf>>> {
882 if self.sh_type(endian) != elf::SHT_RELR {
883 return Ok(None);
884 }
885 let data = self
886 .data_as_array(endian, data)
887 .read_error("Invalid ELF relocation section offset or size")?;
888 let relrs = RelrIterator::new(endian, data);
889 Ok(Some(relrs))
890 }
891
892 fn crel<'data, R: ReadRef<'data>>(
897 &self,
898 endian: Self::Endian,
899 data: R,
900 ) -> read::Result<Option<(CrelIterator<'data>, SectionIndex)>> {
901 if self.sh_type(endian) != elf::SHT_CREL {
902 return Ok(None);
903 }
904 let data = self
905 .data(endian, data)
906 .read_error("Invalid ELF relocation section offset or size")?;
907 let relrs = CrelIterator::new(data);
908 Ok(Some((relrs?, self.link(endian))))
909 }
910
911 fn dynamic_table<'data, R: ReadRef<'data>>(
918 &self,
919 endian: Self::Endian,
920 data: R,
921 sections: &SectionTable<'data, Self::Elf, R>,
922 ) -> read::Result<Option<DynamicTable<'data, Self::Elf, R>>> {
923 if self.sh_type(endian) != elf::SHT_DYNAMIC {
924 return Ok(None);
925 }
926 DynamicTable::parse(endian, data, sections, self).map(Some)
927 }
928
929 fn dynamic<'data, R: ReadRef<'data>>(
936 &self,
937 endian: Self::Endian,
938 data: R,
939 ) -> read::Result<Option<(&'data [<Self::Elf as FileHeader>::Dyn], SectionIndex)>> {
940 if self.sh_type(endian) != elf::SHT_DYNAMIC {
941 return Ok(None);
942 }
943 let dynamic = self
944 .data_as_array(endian, data)
945 .read_error("Invalid ELF dynamic section offset or size")?;
946 Ok(Some((dynamic, self.link(endian))))
947 }
948
949 fn notes<'data, R: ReadRef<'data>>(
954 &self,
955 endian: Self::Endian,
956 data: R,
957 ) -> read::Result<Option<NoteIterator<'data, Self::Elf>>> {
958 if self.sh_type(endian) != elf::SHT_NOTE {
959 return Ok(None);
960 }
961 let data = self
962 .data(endian, data)
963 .read_error("Invalid ELF note section offset or size")?;
964 let notes = NoteIterator::new(endian, self.sh_addralign(endian), data)?;
965 Ok(Some(notes))
966 }
967
968 fn group<'data, R: ReadRef<'data>>(
976 &self,
977 endian: Self::Endian,
978 data: R,
979 ) -> read::Result<Option<(u32, &'data [U32<Self::Endian>])>> {
980 if self.sh_type(endian) != elf::SHT_GROUP {
981 return Ok(None);
982 }
983 let msg = "Invalid ELF group section offset or size";
984 let data = self.data(endian, data).read_error(msg)?;
985 let (flag, data) = pod::from_bytes::<U32<_>>(data).read_error(msg)?;
986 let sections = pod::slice_from_all_bytes(data).read_error(msg)?;
987 Ok(Some((flag.get(endian), sections)))
988 }
989
990 fn hash_header<'data, R: ReadRef<'data>>(
995 &self,
996 endian: Self::Endian,
997 data: R,
998 ) -> read::Result<Option<&'data elf::HashHeader<Self::Endian>>> {
999 if self.sh_type(endian) != elf::SHT_HASH {
1000 return Ok(None);
1001 }
1002 let data = self
1003 .data(endian, data)
1004 .read_error("Invalid ELF hash section offset or size")?;
1005 let header = data
1006 .read_at::<elf::HashHeader<Self::Endian>>(0)
1007 .read_error("Invalid hash header")?;
1008 Ok(Some(header))
1009 }
1010
1011 fn hash<'data, R: ReadRef<'data>>(
1018 &self,
1019 endian: Self::Endian,
1020 data: R,
1021 ) -> read::Result<Option<(HashTable<'data, Self::Elf>, SectionIndex)>> {
1022 if self.sh_type(endian) != elf::SHT_HASH {
1023 return Ok(None);
1024 }
1025 let data = self
1026 .data(endian, data)
1027 .read_error("Invalid ELF hash section offset or size")?;
1028 let hash = HashTable::parse(endian, data)?;
1029 Ok(Some((hash, self.link(endian))))
1030 }
1031
1032 fn gnu_hash_header<'data, R: ReadRef<'data>>(
1037 &self,
1038 endian: Self::Endian,
1039 data: R,
1040 ) -> read::Result<Option<&'data elf::GnuHashHeader<Self::Endian>>> {
1041 if self.sh_type(endian) != elf::SHT_GNU_HASH {
1042 return Ok(None);
1043 }
1044 let data = self
1045 .data(endian, data)
1046 .read_error("Invalid ELF GNU hash section offset or size")?;
1047 let header = data
1048 .read_at::<elf::GnuHashHeader<Self::Endian>>(0)
1049 .read_error("Invalid GNU hash header")?;
1050 Ok(Some(header))
1051 }
1052
1053 fn gnu_hash<'data, R: ReadRef<'data>>(
1060 &self,
1061 endian: Self::Endian,
1062 data: R,
1063 ) -> read::Result<Option<(GnuHashTable<'data, Self::Elf>, SectionIndex)>> {
1064 if self.sh_type(endian) != elf::SHT_GNU_HASH {
1065 return Ok(None);
1066 }
1067 let data = self
1068 .data(endian, data)
1069 .read_error("Invalid ELF GNU hash section offset or size")?;
1070 let hash = GnuHashTable::parse(endian, data)?;
1071 Ok(Some((hash, self.link(endian))))
1072 }
1073
1074 fn gnu_versym<'data, R: ReadRef<'data>>(
1081 &self,
1082 endian: Self::Endian,
1083 data: R,
1084 ) -> read::Result<Option<(&'data [elf::Versym<Self::Endian>], SectionIndex)>> {
1085 if self.sh_type(endian) != elf::SHT_GNU_VERSYM {
1086 return Ok(None);
1087 }
1088 let versym = self
1089 .data_as_array(endian, data)
1090 .read_error("Invalid ELF GNU versym section offset or size")?;
1091 Ok(Some((versym, self.link(endian))))
1092 }
1093
1094 fn gnu_verdef<'data, R: ReadRef<'data>>(
1101 &self,
1102 endian: Self::Endian,
1103 data: R,
1104 ) -> read::Result<Option<(VerdefIterator<'data, Self::Elf>, SectionIndex)>> {
1105 if self.sh_type(endian) != elf::SHT_GNU_VERDEF {
1106 return Ok(None);
1107 }
1108 let verdef = self
1109 .data(endian, data)
1110 .read_error("Invalid ELF GNU verdef section offset or size")?;
1111 Ok(Some((
1112 VerdefIterator::new(endian, verdef),
1113 self.link(endian),
1114 )))
1115 }
1116
1117 fn gnu_verneed<'data, R: ReadRef<'data>>(
1124 &self,
1125 endian: Self::Endian,
1126 data: R,
1127 ) -> read::Result<Option<(VerneedIterator<'data, Self::Elf>, SectionIndex)>> {
1128 if self.sh_type(endian) != elf::SHT_GNU_VERNEED {
1129 return Ok(None);
1130 }
1131 let verneed = self
1132 .data(endian, data)
1133 .read_error("Invalid ELF GNU verneed section offset or size")?;
1134 Ok(Some((
1135 VerneedIterator::new(endian, verneed),
1136 self.link(endian),
1137 )))
1138 }
1139
1140 fn gnu_attributes<'data, R: ReadRef<'data>>(
1145 &self,
1146 endian: Self::Endian,
1147 data: R,
1148 ) -> read::Result<Option<AttributesSection<'data, Self::Elf>>> {
1149 if self.sh_type(endian) != elf::SHT_GNU_ATTRIBUTES {
1150 return Ok(None);
1151 }
1152 self.attributes(endian, data).map(Some)
1153 }
1154
1155 fn attributes<'data, R: ReadRef<'data>>(
1162 &self,
1163 endian: Self::Endian,
1164 data: R,
1165 ) -> read::Result<AttributesSection<'data, Self::Elf>> {
1166 let data = self.data(endian, data)?;
1167 AttributesSection::new(endian, data)
1168 }
1169
1170 fn compression<'data, R: ReadRef<'data>>(
1178 &self,
1179 endian: Self::Endian,
1180 data: R,
1181 ) -> read::Result<
1182 Option<(
1183 &'data <Self::Elf as FileHeader>::CompressionHeader,
1184 u64,
1185 u64,
1186 )>,
1187 > {
1188 if (self.sh_flags(endian).into() & u64::from(elf::SHF_COMPRESSED)) == 0 {
1189 return Ok(None);
1190 }
1191 let (section_offset, section_size) = self
1192 .file_range(endian)
1193 .read_error("Invalid ELF compressed section type")?;
1194 let mut offset = section_offset;
1195 let header = data
1196 .read::<<Self::Elf as FileHeader>::CompressionHeader>(&mut offset)
1197 .read_error("Invalid ELF compressed section offset")?;
1198 let compressed_size = section_size
1199 .checked_sub(offset - section_offset)
1200 .read_error("Invalid ELF compressed section size")?;
1201 Ok(Some((header, offset, compressed_size)))
1202 }
1203}
1204
1205impl<Endian: endian::Endian> SectionHeader for elf::SectionHeader32<Endian> {
1206 type Elf = elf::FileHeader32<Endian>;
1207 type Word = u32;
1208 type Endian = Endian;
1209
1210 #[inline]
1211 fn sh_name(&self, endian: Self::Endian) -> u32 {
1212 self.sh_name.get(endian)
1213 }
1214
1215 #[inline]
1216 fn sh_type(&self, endian: Self::Endian) -> u32 {
1217 self.sh_type.get(endian)
1218 }
1219
1220 #[inline]
1221 fn sh_flags(&self, endian: Self::Endian) -> Self::Word {
1222 self.sh_flags.get(endian)
1223 }
1224
1225 #[inline]
1226 fn sh_addr(&self, endian: Self::Endian) -> Self::Word {
1227 self.sh_addr.get(endian)
1228 }
1229
1230 #[inline]
1231 fn sh_offset(&self, endian: Self::Endian) -> Self::Word {
1232 self.sh_offset.get(endian)
1233 }
1234
1235 #[inline]
1236 fn sh_size(&self, endian: Self::Endian) -> Self::Word {
1237 self.sh_size.get(endian)
1238 }
1239
1240 #[inline]
1241 fn sh_link(&self, endian: Self::Endian) -> u32 {
1242 self.sh_link.get(endian)
1243 }
1244
1245 #[inline]
1246 fn sh_info(&self, endian: Self::Endian) -> u32 {
1247 self.sh_info.get(endian)
1248 }
1249
1250 #[inline]
1251 fn sh_addralign(&self, endian: Self::Endian) -> Self::Word {
1252 self.sh_addralign.get(endian)
1253 }
1254
1255 #[inline]
1256 fn sh_entsize(&self, endian: Self::Endian) -> Self::Word {
1257 self.sh_entsize.get(endian)
1258 }
1259}
1260
1261impl<Endian: endian::Endian> SectionHeader for elf::SectionHeader64<Endian> {
1262 type Word = u64;
1263 type Endian = Endian;
1264 type Elf = elf::FileHeader64<Endian>;
1265
1266 #[inline]
1267 fn sh_name(&self, endian: Self::Endian) -> u32 {
1268 self.sh_name.get(endian)
1269 }
1270
1271 #[inline]
1272 fn sh_type(&self, endian: Self::Endian) -> u32 {
1273 self.sh_type.get(endian)
1274 }
1275
1276 #[inline]
1277 fn sh_flags(&self, endian: Self::Endian) -> Self::Word {
1278 self.sh_flags.get(endian)
1279 }
1280
1281 #[inline]
1282 fn sh_addr(&self, endian: Self::Endian) -> Self::Word {
1283 self.sh_addr.get(endian)
1284 }
1285
1286 #[inline]
1287 fn sh_offset(&self, endian: Self::Endian) -> Self::Word {
1288 self.sh_offset.get(endian)
1289 }
1290
1291 #[inline]
1292 fn sh_size(&self, endian: Self::Endian) -> Self::Word {
1293 self.sh_size.get(endian)
1294 }
1295
1296 #[inline]
1297 fn sh_link(&self, endian: Self::Endian) -> u32 {
1298 self.sh_link.get(endian)
1299 }
1300
1301 #[inline]
1302 fn sh_info(&self, endian: Self::Endian) -> u32 {
1303 self.sh_info.get(endian)
1304 }
1305
1306 #[inline]
1307 fn sh_addralign(&self, endian: Self::Endian) -> Self::Word {
1308 self.sh_addralign.get(endian)
1309 }
1310
1311 #[inline]
1312 fn sh_entsize(&self, endian: Self::Endian) -> Self::Word {
1313 self.sh_entsize.get(endian)
1314 }
1315}