1use core::fmt::Debug;
2use core::{iter, slice, str};
3
4use crate::elf;
5use crate::endian::{self, Endianness, U32Bytes};
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, ElfFile, ElfSectionRelocationIterator,
15 FileHeader, GnuHashTable, HashTable, NoteIterator, RelocationSections, RelrIterator,
16 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(
187 &self,
188 endian: Elf::Endian,
189 data: R,
190 ) -> read::Result<Option<(&'data [Elf::Dyn], SectionIndex)>> {
191 for section in self.sections {
192 if let Some(dynamic) = section.dynamic(endian, data)? {
193 return Ok(Some(dynamic));
194 }
195 }
196 Ok(None)
197 }
198
199 pub fn hash_header(
204 &self,
205 endian: Elf::Endian,
206 data: R,
207 ) -> read::Result<Option<&'data elf::HashHeader<Elf::Endian>>> {
208 for section in self.sections {
209 if let Some(hash) = section.hash_header(endian, data)? {
210 return Ok(Some(hash));
211 }
212 }
213 Ok(None)
214 }
215
216 pub fn hash(
223 &self,
224 endian: Elf::Endian,
225 data: R,
226 ) -> read::Result<Option<(HashTable<'data, Elf>, SectionIndex)>> {
227 for section in self.sections {
228 if let Some(hash) = section.hash(endian, data)? {
229 return Ok(Some(hash));
230 }
231 }
232 Ok(None)
233 }
234
235 pub fn gnu_hash_header(
240 &self,
241 endian: Elf::Endian,
242 data: R,
243 ) -> read::Result<Option<&'data elf::GnuHashHeader<Elf::Endian>>> {
244 for section in self.sections {
245 if let Some(hash) = section.gnu_hash_header(endian, data)? {
246 return Ok(Some(hash));
247 }
248 }
249 Ok(None)
250 }
251
252 pub fn gnu_hash(
259 &self,
260 endian: Elf::Endian,
261 data: R,
262 ) -> read::Result<Option<(GnuHashTable<'data, Elf>, SectionIndex)>> {
263 for section in self.sections {
264 if let Some(hash) = section.gnu_hash(endian, data)? {
265 return Ok(Some(hash));
266 }
267 }
268 Ok(None)
269 }
270
271 pub fn gnu_versym(
278 &self,
279 endian: Elf::Endian,
280 data: R,
281 ) -> read::Result<Option<(&'data [elf::Versym<Elf::Endian>], SectionIndex)>> {
282 for section in self.sections {
283 if let Some(syms) = section.gnu_versym(endian, data)? {
284 return Ok(Some(syms));
285 }
286 }
287 Ok(None)
288 }
289
290 pub fn gnu_verdef(
297 &self,
298 endian: Elf::Endian,
299 data: R,
300 ) -> read::Result<Option<(VerdefIterator<'data, Elf>, SectionIndex)>> {
301 for section in self.sections {
302 if let Some(defs) = section.gnu_verdef(endian, data)? {
303 return Ok(Some(defs));
304 }
305 }
306 Ok(None)
307 }
308
309 pub fn gnu_verneed(
316 &self,
317 endian: Elf::Endian,
318 data: R,
319 ) -> read::Result<Option<(VerneedIterator<'data, Elf>, SectionIndex)>> {
320 for section in self.sections {
321 if let Some(needs) = section.gnu_verneed(endian, data)? {
322 return Ok(Some(needs));
323 }
324 }
325 Ok(None)
326 }
327
328 pub fn versions(
333 &self,
334 endian: Elf::Endian,
335 data: R,
336 ) -> read::Result<Option<VersionTable<'data, Elf>>> {
337 let (versyms, link) = match self.gnu_versym(endian, data)? {
338 Some(val) => val,
339 None => return Ok(None),
340 };
341 let strings = self.symbol_table_by_index(endian, data, link)?.strings();
342 let verdefs = self.gnu_verdef(endian, data)?.map(|x| x.0);
344 let verneeds = self.gnu_verneed(endian, data)?.map(|x| x.0);
345 VersionTable::parse(endian, versyms, verdefs, verneeds, strings).map(Some)
346 }
347}
348
349pub type ElfSectionIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
351 ElfSectionIterator<'data, 'file, elf::FileHeader32<Endian>, R>;
352pub type ElfSectionIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
354 ElfSectionIterator<'data, 'file, elf::FileHeader64<Endian>, R>;
355
356#[derive(Debug)]
358pub struct ElfSectionIterator<'data, 'file, Elf, R = &'data [u8]>
359where
360 Elf: FileHeader,
361 R: ReadRef<'data>,
362{
363 file: &'file ElfFile<'data, Elf, R>,
364 iter: iter::Enumerate<slice::Iter<'data, Elf::SectionHeader>>,
365}
366
367impl<'data, 'file, Elf, R> ElfSectionIterator<'data, 'file, Elf, R>
368where
369 Elf: FileHeader,
370 R: ReadRef<'data>,
371{
372 pub(super) fn new(file: &'file ElfFile<'data, Elf, R>) -> Self {
373 let mut iter = file.sections.iter().enumerate();
374 iter.next(); ElfSectionIterator { file, iter }
376 }
377}
378
379impl<'data, 'file, Elf, R> Iterator for ElfSectionIterator<'data, 'file, Elf, R>
380where
381 Elf: FileHeader,
382 R: ReadRef<'data>,
383{
384 type Item = ElfSection<'data, 'file, Elf, R>;
385
386 fn next(&mut self) -> Option<Self::Item> {
387 self.iter.next().map(|(index, section)| ElfSection {
388 index: SectionIndex(index),
389 file: self.file,
390 section,
391 })
392 }
393}
394
395pub type ElfSection32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
397 ElfSection<'data, 'file, elf::FileHeader32<Endian>, R>;
398pub type ElfSection64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
400 ElfSection<'data, 'file, elf::FileHeader64<Endian>, R>;
401
402#[derive(Debug)]
406pub struct ElfSection<'data, 'file, Elf, R = &'data [u8]>
407where
408 Elf: FileHeader,
409 R: ReadRef<'data>,
410{
411 pub(super) file: &'file ElfFile<'data, Elf, R>,
412 pub(super) index: SectionIndex,
413 pub(super) section: &'data Elf::SectionHeader,
414}
415
416impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> ElfSection<'data, 'file, Elf, R> {
417 pub fn elf_file(&self) -> &'file ElfFile<'data, Elf, R> {
419 self.file
420 }
421
422 pub fn elf_section_header(&self) -> &'data Elf::SectionHeader {
424 self.section
425 }
426
427 pub fn elf_relocation_section_index(&self) -> read::Result<Option<SectionIndex>> {
432 let Some(relocation_index) = self.file.relocations.get(self.index) else {
433 return Ok(None);
434 };
435 if self.file.relocations.get(relocation_index).is_some() {
436 return Err(Error(
437 "Unsupported ELF section with multiple relocation sections",
438 ));
439 }
440 Ok(Some(relocation_index))
441 }
442
443 pub fn elf_relocation_section(&self) -> read::Result<Option<&'data Elf::SectionHeader>> {
448 let Some(relocation_index) = self.elf_relocation_section_index()? else {
449 return Ok(None);
450 };
451 self.file.sections.section(relocation_index).map(Some)
452 }
453
454 pub fn elf_linked_rel(&self) -> read::Result<&'data [Elf::Rel]> {
459 let Some(relocation_section) = self.elf_relocation_section()? else {
460 return Ok(&[]);
461 };
462 let Some((rel, _)) = relocation_section.rel(self.file.endian, self.file.data)? else {
464 return Ok(&[]);
465 };
466 Ok(rel)
467 }
468
469 pub fn elf_linked_rela(&self) -> read::Result<&'data [Elf::Rela]> {
474 let Some(relocation_section) = self.elf_relocation_section()? else {
475 return Ok(&[]);
476 };
477 let Some((rela, _)) = relocation_section.rela(self.file.endian, self.file.data)? else {
479 return Ok(&[]);
480 };
481 Ok(rela)
482 }
483
484 fn bytes(&self) -> read::Result<&'data [u8]> {
485 self.section
486 .data(self.file.endian, self.file.data)
487 .read_error("Invalid ELF section size or offset")
488 }
489
490 fn maybe_compressed(&self) -> read::Result<Option<CompressedFileRange>> {
491 let endian = self.file.endian;
492 if let Some((header, offset, compressed_size)) =
493 self.section.compression(endian, self.file.data)?
494 {
495 let format = match header.ch_type(endian) {
496 elf::ELFCOMPRESS_ZLIB => CompressionFormat::Zlib,
497 elf::ELFCOMPRESS_ZSTD => CompressionFormat::Zstandard,
498 _ => return Err(Error("Unsupported ELF compression type")),
499 };
500 let uncompressed_size = header.ch_size(endian).into();
501 Ok(Some(CompressedFileRange {
502 format,
503 offset,
504 compressed_size,
505 uncompressed_size,
506 }))
507 } else {
508 Ok(None)
509 }
510 }
511
512 fn maybe_compressed_gnu(&self) -> read::Result<Option<CompressedFileRange>> {
514 if !self
515 .name()
516 .map_or(false, |name| name.starts_with(".zdebug_"))
517 {
518 return Ok(None);
519 }
520 let (section_offset, section_size) = self
521 .file_range()
522 .read_error("Invalid ELF GNU compressed section type")?;
523 gnu_compression::compressed_file_range(self.file.data, section_offset, section_size)
524 .map(Some)
525 }
526}
527
528impl<'data, 'file, Elf, R> read::private::Sealed for ElfSection<'data, 'file, Elf, R>
529where
530 Elf: FileHeader,
531 R: ReadRef<'data>,
532{
533}
534
535impl<'data, 'file, Elf, R> ObjectSection<'data> for ElfSection<'data, 'file, Elf, R>
536where
537 Elf: FileHeader,
538 R: ReadRef<'data>,
539{
540 type RelocationIterator = ElfSectionRelocationIterator<'data, 'file, Elf, R>;
541
542 #[inline]
543 fn index(&self) -> SectionIndex {
544 self.index
545 }
546
547 #[inline]
548 fn address(&self) -> u64 {
549 self.section.sh_addr(self.file.endian).into()
550 }
551
552 #[inline]
553 fn size(&self) -> u64 {
554 self.section.sh_size(self.file.endian).into()
555 }
556
557 #[inline]
558 fn align(&self) -> u64 {
559 self.section.sh_addralign(self.file.endian).into()
560 }
561
562 #[inline]
563 fn file_range(&self) -> Option<(u64, u64)> {
564 self.section.file_range(self.file.endian)
565 }
566
567 #[inline]
568 fn data(&self) -> read::Result<&'data [u8]> {
569 self.bytes()
570 }
571
572 fn data_range(&self, address: u64, size: u64) -> read::Result<Option<&'data [u8]>> {
573 Ok(read::util::data_range(
574 self.bytes()?,
575 self.address(),
576 address,
577 size,
578 ))
579 }
580
581 fn compressed_file_range(&self) -> read::Result<CompressedFileRange> {
582 Ok(if let Some(data) = self.maybe_compressed()? {
583 data
584 } else if let Some(data) = self.maybe_compressed_gnu()? {
585 data
586 } else {
587 CompressedFileRange::none(self.file_range())
588 })
589 }
590
591 fn compressed_data(&self) -> read::Result<CompressedData<'data>> {
592 self.compressed_file_range()?.data(self.file.data)
593 }
594
595 fn name_bytes(&self) -> read::Result<&'data [u8]> {
596 self.file
597 .sections
598 .section_name(self.file.endian, self.section)
599 }
600
601 fn name(&self) -> read::Result<&'data str> {
602 let name = self.name_bytes()?;
603 str::from_utf8(name)
604 .ok()
605 .read_error("Non UTF-8 ELF section name")
606 }
607
608 #[inline]
609 fn segment_name_bytes(&self) -> read::Result<Option<&[u8]>> {
610 Ok(None)
611 }
612
613 #[inline]
614 fn segment_name(&self) -> read::Result<Option<&str>> {
615 Ok(None)
616 }
617
618 fn kind(&self) -> SectionKind {
619 let flags = self.section.sh_flags(self.file.endian).into();
620 let sh_type = self.section.sh_type(self.file.endian);
621 match sh_type {
622 elf::SHT_PROGBITS => {
623 if flags & u64::from(elf::SHF_ALLOC) != 0 {
624 if flags & u64::from(elf::SHF_EXECINSTR) != 0 {
625 SectionKind::Text
626 } else if flags & u64::from(elf::SHF_TLS) != 0 {
627 SectionKind::Tls
628 } else if flags & u64::from(elf::SHF_WRITE) != 0 {
629 SectionKind::Data
630 } else if flags & u64::from(elf::SHF_STRINGS) != 0 {
631 SectionKind::ReadOnlyString
632 } else {
633 SectionKind::ReadOnlyData
634 }
635 } else if flags & u64::from(elf::SHF_STRINGS) != 0 {
636 SectionKind::OtherString
637 } else {
638 SectionKind::Other
639 }
640 }
641 elf::SHT_NOBITS => {
642 if flags & u64::from(elf::SHF_TLS) != 0 {
643 SectionKind::UninitializedTls
644 } else {
645 SectionKind::UninitializedData
646 }
647 }
648 elf::SHT_NOTE => SectionKind::Note,
649 elf::SHT_NULL
650 | elf::SHT_SYMTAB
651 | elf::SHT_STRTAB
652 | elf::SHT_RELA
653 | elf::SHT_HASH
654 | elf::SHT_DYNAMIC
655 | elf::SHT_REL
656 | elf::SHT_DYNSYM
657 | elf::SHT_GROUP
658 | elf::SHT_SYMTAB_SHNDX
659 | elf::SHT_RELR
660 | elf::SHT_CREL => SectionKind::Metadata,
661 _ => SectionKind::Elf(sh_type),
662 }
663 }
664
665 fn relocations(&self) -> ElfSectionRelocationIterator<'data, 'file, Elf, R> {
666 ElfSectionRelocationIterator {
667 section_index: self.index,
668 file: self.file,
669 relocations: None,
670 }
671 }
672
673 fn relocation_map(&self) -> read::Result<RelocationMap> {
674 RelocationMap::new(self.file, self)
675 }
676
677 fn flags(&self) -> SectionFlags {
678 SectionFlags::Elf {
679 sh_flags: self.section.sh_flags(self.file.endian).into(),
680 }
681 }
682}
683
684#[allow(missing_docs)]
686pub trait SectionHeader: Debug + Pod {
687 type Elf: FileHeader<SectionHeader = Self, Endian = Self::Endian, Word = Self::Word>;
688 type Word: Into<u64>;
689 type Endian: endian::Endian;
690
691 fn sh_name(&self, endian: Self::Endian) -> u32;
692 fn sh_type(&self, endian: Self::Endian) -> u32;
693 fn sh_flags(&self, endian: Self::Endian) -> Self::Word;
694 fn sh_addr(&self, endian: Self::Endian) -> Self::Word;
695 fn sh_offset(&self, endian: Self::Endian) -> Self::Word;
696 fn sh_size(&self, endian: Self::Endian) -> Self::Word;
697 fn sh_link(&self, endian: Self::Endian) -> u32;
698 fn sh_info(&self, endian: Self::Endian) -> u32;
699 fn sh_addralign(&self, endian: Self::Endian) -> Self::Word;
700 fn sh_entsize(&self, endian: Self::Endian) -> Self::Word;
701
702 fn name<'data, R: ReadRef<'data>>(
704 &self,
705 endian: Self::Endian,
706 strings: StringTable<'data, R>,
707 ) -> read::Result<&'data [u8]> {
708 strings
709 .get(self.sh_name(endian))
710 .read_error("Invalid ELF section name offset")
711 }
712
713 fn link(&self, endian: Self::Endian) -> SectionIndex {
717 SectionIndex(self.sh_link(endian) as usize)
718 }
719
720 fn has_info_link(&self, endian: Self::Endian) -> bool {
722 self.sh_flags(endian).into() & u64::from(elf::SHF_INFO_LINK) != 0
723 }
724
725 fn info_link(&self, endian: Self::Endian) -> SectionIndex {
730 SectionIndex(self.sh_info(endian) as usize)
731 }
732
733 fn file_range(&self, endian: Self::Endian) -> Option<(u64, u64)> {
737 if self.sh_type(endian) == elf::SHT_NOBITS {
738 None
739 } else {
740 Some((self.sh_offset(endian).into(), self.sh_size(endian).into()))
741 }
742 }
743
744 fn data<'data, R: ReadRef<'data>>(
749 &self,
750 endian: Self::Endian,
751 data: R,
752 ) -> read::Result<&'data [u8]> {
753 if let Some((offset, size)) = self.file_range(endian) {
754 data.read_bytes_at(offset, size)
755 .read_error("Invalid ELF section size or offset")
756 } else {
757 Ok(&[])
758 }
759 }
760
761 fn data_as_array<'data, T: Pod, R: ReadRef<'data>>(
767 &self,
768 endian: Self::Endian,
769 data: R,
770 ) -> read::Result<&'data [T]> {
771 pod::slice_from_all_bytes(self.data(endian, data)?)
772 .read_error("Invalid ELF section size or offset")
773 }
774
775 fn strings<'data, R: ReadRef<'data>>(
780 &self,
781 endian: Self::Endian,
782 data: R,
783 ) -> read::Result<Option<StringTable<'data, R>>> {
784 if self.sh_type(endian) != elf::SHT_STRTAB {
785 return Ok(None);
786 }
787 let str_offset = self.sh_offset(endian).into();
788 let str_size = self.sh_size(endian).into();
789 let str_end = str_offset
790 .checked_add(str_size)
791 .read_error("Invalid ELF string section offset or size")?;
792 Ok(Some(StringTable::new(data, str_offset, str_end)))
793 }
794
795 fn symbols<'data, R: ReadRef<'data>>(
805 &self,
806 endian: Self::Endian,
807 data: R,
808 sections: &SectionTable<'data, Self::Elf, R>,
809 section_index: SectionIndex,
810 ) -> read::Result<Option<SymbolTable<'data, Self::Elf, R>>> {
811 let sh_type = self.sh_type(endian);
812 if sh_type != elf::SHT_SYMTAB && sh_type != elf::SHT_DYNSYM {
813 return Ok(None);
814 }
815 SymbolTable::parse(endian, data, sections, section_index, self).map(Some)
816 }
817
818 fn rel<'data, R: ReadRef<'data>>(
825 &self,
826 endian: Self::Endian,
827 data: R,
828 ) -> read::Result<Option<(&'data [<Self::Elf as FileHeader>::Rel], SectionIndex)>> {
829 if self.sh_type(endian) != elf::SHT_REL {
830 return Ok(None);
831 }
832 let rel = self
833 .data_as_array(endian, data)
834 .read_error("Invalid ELF relocation section offset or size")?;
835 Ok(Some((rel, self.link(endian))))
836 }
837
838 fn rela<'data, R: ReadRef<'data>>(
845 &self,
846 endian: Self::Endian,
847 data: R,
848 ) -> read::Result<Option<(&'data [<Self::Elf as FileHeader>::Rela], SectionIndex)>> {
849 if self.sh_type(endian) != elf::SHT_RELA {
850 return Ok(None);
851 }
852 let rela = self
853 .data_as_array(endian, data)
854 .read_error("Invalid ELF relocation section offset or size")?;
855 Ok(Some((rela, self.link(endian))))
856 }
857
858 fn relr<'data, R: ReadRef<'data>>(
863 &self,
864 endian: Self::Endian,
865 data: R,
866 ) -> read::Result<Option<RelrIterator<'data, Self::Elf>>> {
867 if self.sh_type(endian) != elf::SHT_RELR {
868 return Ok(None);
869 }
870 let data = self
871 .data_as_array(endian, data)
872 .read_error("Invalid ELF relocation section offset or size")?;
873 let relrs = RelrIterator::new(endian, data);
874 Ok(Some(relrs))
875 }
876
877 fn crel<'data, R: ReadRef<'data>>(
882 &self,
883 endian: Self::Endian,
884 data: R,
885 ) -> read::Result<Option<(CrelIterator<'data>, SectionIndex)>> {
886 if self.sh_type(endian) != elf::SHT_CREL {
887 return Ok(None);
888 }
889 let data = self
890 .data(endian, data)
891 .read_error("Invalid ELF relocation section offset or size")?;
892 let relrs = CrelIterator::new(data);
893 Ok(Some((relrs?, self.link(endian))))
894 }
895
896 fn dynamic<'data, R: ReadRef<'data>>(
903 &self,
904 endian: Self::Endian,
905 data: R,
906 ) -> read::Result<Option<(&'data [<Self::Elf as FileHeader>::Dyn], SectionIndex)>> {
907 if self.sh_type(endian) != elf::SHT_DYNAMIC {
908 return Ok(None);
909 }
910 let dynamic = self
911 .data_as_array(endian, data)
912 .read_error("Invalid ELF dynamic section offset or size")?;
913 Ok(Some((dynamic, self.link(endian))))
914 }
915
916 fn notes<'data, R: ReadRef<'data>>(
921 &self,
922 endian: Self::Endian,
923 data: R,
924 ) -> read::Result<Option<NoteIterator<'data, Self::Elf>>> {
925 if self.sh_type(endian) != elf::SHT_NOTE {
926 return Ok(None);
927 }
928 let data = self
929 .data(endian, data)
930 .read_error("Invalid ELF note section offset or size")?;
931 let notes = NoteIterator::new(endian, self.sh_addralign(endian), data)?;
932 Ok(Some(notes))
933 }
934
935 fn group<'data, R: ReadRef<'data>>(
943 &self,
944 endian: Self::Endian,
945 data: R,
946 ) -> read::Result<Option<(u32, &'data [U32Bytes<Self::Endian>])>> {
947 if self.sh_type(endian) != elf::SHT_GROUP {
948 return Ok(None);
949 }
950 let msg = "Invalid ELF group section offset or size";
951 let data = self.data(endian, data).read_error(msg)?;
952 let (flag, data) = pod::from_bytes::<U32Bytes<_>>(data).read_error(msg)?;
953 let sections = pod::slice_from_all_bytes(data).read_error(msg)?;
954 Ok(Some((flag.get(endian), sections)))
955 }
956
957 fn hash_header<'data, R: ReadRef<'data>>(
962 &self,
963 endian: Self::Endian,
964 data: R,
965 ) -> read::Result<Option<&'data elf::HashHeader<Self::Endian>>> {
966 if self.sh_type(endian) != elf::SHT_HASH {
967 return Ok(None);
968 }
969 let data = self
970 .data(endian, data)
971 .read_error("Invalid ELF hash section offset or size")?;
972 let header = data
973 .read_at::<elf::HashHeader<Self::Endian>>(0)
974 .read_error("Invalid hash header")?;
975 Ok(Some(header))
976 }
977
978 fn hash<'data, R: ReadRef<'data>>(
985 &self,
986 endian: Self::Endian,
987 data: R,
988 ) -> read::Result<Option<(HashTable<'data, Self::Elf>, SectionIndex)>> {
989 if self.sh_type(endian) != elf::SHT_HASH {
990 return Ok(None);
991 }
992 let data = self
993 .data(endian, data)
994 .read_error("Invalid ELF hash section offset or size")?;
995 let hash = HashTable::parse(endian, data)?;
996 Ok(Some((hash, self.link(endian))))
997 }
998
999 fn gnu_hash_header<'data, R: ReadRef<'data>>(
1004 &self,
1005 endian: Self::Endian,
1006 data: R,
1007 ) -> read::Result<Option<&'data elf::GnuHashHeader<Self::Endian>>> {
1008 if self.sh_type(endian) != elf::SHT_GNU_HASH {
1009 return Ok(None);
1010 }
1011 let data = self
1012 .data(endian, data)
1013 .read_error("Invalid ELF GNU hash section offset or size")?;
1014 let header = data
1015 .read_at::<elf::GnuHashHeader<Self::Endian>>(0)
1016 .read_error("Invalid GNU hash header")?;
1017 Ok(Some(header))
1018 }
1019
1020 fn gnu_hash<'data, R: ReadRef<'data>>(
1027 &self,
1028 endian: Self::Endian,
1029 data: R,
1030 ) -> read::Result<Option<(GnuHashTable<'data, Self::Elf>, SectionIndex)>> {
1031 if self.sh_type(endian) != elf::SHT_GNU_HASH {
1032 return Ok(None);
1033 }
1034 let data = self
1035 .data(endian, data)
1036 .read_error("Invalid ELF GNU hash section offset or size")?;
1037 let hash = GnuHashTable::parse(endian, data)?;
1038 Ok(Some((hash, self.link(endian))))
1039 }
1040
1041 fn gnu_versym<'data, R: ReadRef<'data>>(
1048 &self,
1049 endian: Self::Endian,
1050 data: R,
1051 ) -> read::Result<Option<(&'data [elf::Versym<Self::Endian>], SectionIndex)>> {
1052 if self.sh_type(endian) != elf::SHT_GNU_VERSYM {
1053 return Ok(None);
1054 }
1055 let versym = self
1056 .data_as_array(endian, data)
1057 .read_error("Invalid ELF GNU versym section offset or size")?;
1058 Ok(Some((versym, self.link(endian))))
1059 }
1060
1061 fn gnu_verdef<'data, R: ReadRef<'data>>(
1068 &self,
1069 endian: Self::Endian,
1070 data: R,
1071 ) -> read::Result<Option<(VerdefIterator<'data, Self::Elf>, SectionIndex)>> {
1072 if self.sh_type(endian) != elf::SHT_GNU_VERDEF {
1073 return Ok(None);
1074 }
1075 let verdef = self
1076 .data(endian, data)
1077 .read_error("Invalid ELF GNU verdef section offset or size")?;
1078 Ok(Some((
1079 VerdefIterator::new(endian, verdef),
1080 self.link(endian),
1081 )))
1082 }
1083
1084 fn gnu_verneed<'data, R: ReadRef<'data>>(
1091 &self,
1092 endian: Self::Endian,
1093 data: R,
1094 ) -> read::Result<Option<(VerneedIterator<'data, Self::Elf>, SectionIndex)>> {
1095 if self.sh_type(endian) != elf::SHT_GNU_VERNEED {
1096 return Ok(None);
1097 }
1098 let verneed = self
1099 .data(endian, data)
1100 .read_error("Invalid ELF GNU verneed section offset or size")?;
1101 Ok(Some((
1102 VerneedIterator::new(endian, verneed),
1103 self.link(endian),
1104 )))
1105 }
1106
1107 fn gnu_attributes<'data, R: ReadRef<'data>>(
1112 &self,
1113 endian: Self::Endian,
1114 data: R,
1115 ) -> read::Result<Option<AttributesSection<'data, Self::Elf>>> {
1116 if self.sh_type(endian) != elf::SHT_GNU_ATTRIBUTES {
1117 return Ok(None);
1118 }
1119 self.attributes(endian, data).map(Some)
1120 }
1121
1122 fn attributes<'data, R: ReadRef<'data>>(
1129 &self,
1130 endian: Self::Endian,
1131 data: R,
1132 ) -> read::Result<AttributesSection<'data, Self::Elf>> {
1133 let data = self.data(endian, data)?;
1134 AttributesSection::new(endian, data)
1135 }
1136
1137 fn compression<'data, R: ReadRef<'data>>(
1145 &self,
1146 endian: Self::Endian,
1147 data: R,
1148 ) -> read::Result<
1149 Option<(
1150 &'data <Self::Elf as FileHeader>::CompressionHeader,
1151 u64,
1152 u64,
1153 )>,
1154 > {
1155 if (self.sh_flags(endian).into() & u64::from(elf::SHF_COMPRESSED)) == 0 {
1156 return Ok(None);
1157 }
1158 let (section_offset, section_size) = self
1159 .file_range(endian)
1160 .read_error("Invalid ELF compressed section type")?;
1161 let mut offset = section_offset;
1162 let header = data
1163 .read::<<Self::Elf as FileHeader>::CompressionHeader>(&mut offset)
1164 .read_error("Invalid ELF compressed section offset")?;
1165 let compressed_size = section_size
1166 .checked_sub(offset - section_offset)
1167 .read_error("Invalid ELF compressed section size")?;
1168 Ok(Some((header, offset, compressed_size)))
1169 }
1170}
1171
1172impl<Endian: endian::Endian> SectionHeader for elf::SectionHeader32<Endian> {
1173 type Elf = elf::FileHeader32<Endian>;
1174 type Word = u32;
1175 type Endian = Endian;
1176
1177 #[inline]
1178 fn sh_name(&self, endian: Self::Endian) -> u32 {
1179 self.sh_name.get(endian)
1180 }
1181
1182 #[inline]
1183 fn sh_type(&self, endian: Self::Endian) -> u32 {
1184 self.sh_type.get(endian)
1185 }
1186
1187 #[inline]
1188 fn sh_flags(&self, endian: Self::Endian) -> Self::Word {
1189 self.sh_flags.get(endian)
1190 }
1191
1192 #[inline]
1193 fn sh_addr(&self, endian: Self::Endian) -> Self::Word {
1194 self.sh_addr.get(endian)
1195 }
1196
1197 #[inline]
1198 fn sh_offset(&self, endian: Self::Endian) -> Self::Word {
1199 self.sh_offset.get(endian)
1200 }
1201
1202 #[inline]
1203 fn sh_size(&self, endian: Self::Endian) -> Self::Word {
1204 self.sh_size.get(endian)
1205 }
1206
1207 #[inline]
1208 fn sh_link(&self, endian: Self::Endian) -> u32 {
1209 self.sh_link.get(endian)
1210 }
1211
1212 #[inline]
1213 fn sh_info(&self, endian: Self::Endian) -> u32 {
1214 self.sh_info.get(endian)
1215 }
1216
1217 #[inline]
1218 fn sh_addralign(&self, endian: Self::Endian) -> Self::Word {
1219 self.sh_addralign.get(endian)
1220 }
1221
1222 #[inline]
1223 fn sh_entsize(&self, endian: Self::Endian) -> Self::Word {
1224 self.sh_entsize.get(endian)
1225 }
1226}
1227
1228impl<Endian: endian::Endian> SectionHeader for elf::SectionHeader64<Endian> {
1229 type Word = u64;
1230 type Endian = Endian;
1231 type Elf = elf::FileHeader64<Endian>;
1232
1233 #[inline]
1234 fn sh_name(&self, endian: Self::Endian) -> u32 {
1235 self.sh_name.get(endian)
1236 }
1237
1238 #[inline]
1239 fn sh_type(&self, endian: Self::Endian) -> u32 {
1240 self.sh_type.get(endian)
1241 }
1242
1243 #[inline]
1244 fn sh_flags(&self, endian: Self::Endian) -> Self::Word {
1245 self.sh_flags.get(endian)
1246 }
1247
1248 #[inline]
1249 fn sh_addr(&self, endian: Self::Endian) -> Self::Word {
1250 self.sh_addr.get(endian)
1251 }
1252
1253 #[inline]
1254 fn sh_offset(&self, endian: Self::Endian) -> Self::Word {
1255 self.sh_offset.get(endian)
1256 }
1257
1258 #[inline]
1259 fn sh_size(&self, endian: Self::Endian) -> Self::Word {
1260 self.sh_size.get(endian)
1261 }
1262
1263 #[inline]
1264 fn sh_link(&self, endian: Self::Endian) -> u32 {
1265 self.sh_link.get(endian)
1266 }
1267
1268 #[inline]
1269 fn sh_info(&self, endian: Self::Endian) -> u32 {
1270 self.sh_info.get(endian)
1271 }
1272
1273 #[inline]
1274 fn sh_addralign(&self, endian: Self::Endian) -> Self::Word {
1275 self.sh_addralign.get(endian)
1276 }
1277
1278 #[inline]
1279 fn sh_entsize(&self, endian: Self::Endian) -> Self::Word {
1280 self.sh_entsize.get(endian)
1281 }
1282}