1 | use core::fmt::Debug; |
2 | use core::{iter, slice, str}; |
3 | |
4 | use crate::elf; |
5 | use crate::endian::{Endianness, U32Bytes}; |
6 | use crate::read::{self, ComdatKind, ObjectComdat, ReadError, ReadRef, SectionIndex, SymbolIndex}; |
7 | |
8 | use super::{ElfFile, FileHeader, SectionHeader, Sym}; |
9 | |
10 | /// An iterator for the COMDAT section groups in an [`ElfFile32`](super::ElfFile32). |
11 | pub type ElfComdatIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> = |
12 | ElfComdatIterator<'data, 'file, elf::FileHeader32<Endian>, R>; |
13 | /// An iterator for the COMDAT section groups in an [`ElfFile64`](super::ElfFile64). |
14 | pub type ElfComdatIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> = |
15 | ElfComdatIterator<'data, 'file, elf::FileHeader64<Endian>, R>; |
16 | |
17 | /// An iterator for the COMDAT section groups in an [`ElfFile`]. |
18 | #[derive (Debug)] |
19 | pub struct ElfComdatIterator<'data, 'file, Elf, R = &'data [u8]> |
20 | where |
21 | Elf: FileHeader, |
22 | R: ReadRef<'data>, |
23 | { |
24 | pub(super) file: &'file ElfFile<'data, Elf, R>, |
25 | pub(super) iter: iter::Enumerate<slice::Iter<'data, Elf::SectionHeader>>, |
26 | } |
27 | |
28 | impl<'data, 'file, Elf, R> Iterator for ElfComdatIterator<'data, 'file, Elf, R> |
29 | where |
30 | Elf: FileHeader, |
31 | R: ReadRef<'data>, |
32 | { |
33 | type Item = ElfComdat<'data, 'file, Elf, R>; |
34 | |
35 | fn next(&mut self) -> Option<Self::Item> { |
36 | for (_index: usize, section: &::SectionHeader) in self.iter.by_ref() { |
37 | if let Some(comdat: ElfComdat<'_, '_, Elf, R>) = ElfComdat::parse(self.file, section) { |
38 | return Some(comdat); |
39 | } |
40 | } |
41 | None |
42 | } |
43 | } |
44 | |
45 | /// A COMDAT section group in an [`ElfFile32`](super::ElfFile32). |
46 | pub type ElfComdat32<'data, 'file, Endian = Endianness, R = &'data [u8]> = |
47 | ElfComdat<'data, 'file, elf::FileHeader32<Endian>, R>; |
48 | /// A COMDAT section group in an [`ElfFile64`](super::ElfFile64). |
49 | pub type ElfComdat64<'data, 'file, Endian = Endianness, R = &'data [u8]> = |
50 | ElfComdat<'data, 'file, elf::FileHeader64<Endian>, R>; |
51 | |
52 | /// A COMDAT section group in an [`ElfFile`]. |
53 | /// |
54 | /// Most functionality is provided by the [`ObjectComdat`] trait implementation. |
55 | #[derive (Debug)] |
56 | pub struct ElfComdat<'data, 'file, Elf, R = &'data [u8]> |
57 | where |
58 | Elf: FileHeader, |
59 | R: ReadRef<'data>, |
60 | { |
61 | file: &'file ElfFile<'data, Elf, R>, |
62 | section: &'data Elf::SectionHeader, |
63 | sections: &'data [U32Bytes<Elf::Endian>], |
64 | } |
65 | |
66 | impl<'data, 'file, Elf, R> ElfComdat<'data, 'file, Elf, R> |
67 | where |
68 | Elf: FileHeader, |
69 | R: ReadRef<'data>, |
70 | { |
71 | fn parse( |
72 | file: &'file ElfFile<'data, Elf, R>, |
73 | section: &'data Elf::SectionHeader, |
74 | ) -> Option<ElfComdat<'data, 'file, Elf, R>> { |
75 | let (flag: u32, sections: &[U32Bytes<<::ProgramHeader as ProgramHeader>::Endian>]) = section.group(file.endian, file.data).ok()??; |
76 | if flag != elf::GRP_COMDAT { |
77 | return None; |
78 | } |
79 | Some(ElfComdat { |
80 | file, |
81 | section, |
82 | sections, |
83 | }) |
84 | } |
85 | } |
86 | |
87 | impl<'data, 'file, Elf, R> read::private::Sealed for ElfComdat<'data, 'file, Elf, R> |
88 | where |
89 | Elf: FileHeader, |
90 | R: ReadRef<'data>, |
91 | { |
92 | } |
93 | |
94 | impl<'data, 'file, Elf, R> ObjectComdat<'data> for ElfComdat<'data, 'file, Elf, R> |
95 | where |
96 | Elf: FileHeader, |
97 | R: ReadRef<'data>, |
98 | { |
99 | type SectionIterator = ElfComdatSectionIterator<'data, 'file, Elf, R>; |
100 | |
101 | #[inline ] |
102 | fn kind(&self) -> ComdatKind { |
103 | ComdatKind::Any |
104 | } |
105 | |
106 | #[inline ] |
107 | fn symbol(&self) -> SymbolIndex { |
108 | SymbolIndex(self.section.sh_info(self.file.endian) as usize) |
109 | } |
110 | |
111 | fn name_bytes(&self) -> read::Result<&[u8]> { |
112 | // FIXME: check sh_link |
113 | let index = self.section.sh_info(self.file.endian) as usize; |
114 | let symbol = self.file.symbols.symbol(index)?; |
115 | symbol.name(self.file.endian, self.file.symbols.strings()) |
116 | } |
117 | |
118 | fn name(&self) -> read::Result<&str> { |
119 | let name = self.name_bytes()?; |
120 | str::from_utf8(name) |
121 | .ok() |
122 | .read_error("Non UTF-8 ELF COMDAT name" ) |
123 | } |
124 | |
125 | fn sections(&self) -> Self::SectionIterator { |
126 | ElfComdatSectionIterator { |
127 | file: self.file, |
128 | sections: self.sections.iter(), |
129 | } |
130 | } |
131 | } |
132 | |
133 | /// An iterator for the sections in a COMDAT section group in an [`ElfFile32`](super::ElfFile32). |
134 | pub type ElfComdatSectionIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> = |
135 | ElfComdatSectionIterator<'data, 'file, elf::FileHeader32<Endian>, R>; |
136 | /// An iterator for the sections in a COMDAT section group in an [`ElfFile64`](super::ElfFile64). |
137 | pub type ElfComdatSectionIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> = |
138 | ElfComdatSectionIterator<'data, 'file, elf::FileHeader64<Endian>, R>; |
139 | |
140 | /// An iterator for the sections in a COMDAT section group in an [`ElfFile`]. |
141 | #[derive (Debug)] |
142 | pub struct ElfComdatSectionIterator<'data, 'file, Elf, R = &'data [u8]> |
143 | where |
144 | Elf: FileHeader, |
145 | R: ReadRef<'data>, |
146 | { |
147 | file: &'file ElfFile<'data, Elf, R>, |
148 | sections: slice::Iter<'data, U32Bytes<Elf::Endian>>, |
149 | } |
150 | |
151 | impl<'data, 'file, Elf, R> Iterator for ElfComdatSectionIterator<'data, 'file, Elf, R> |
152 | where |
153 | Elf: FileHeader, |
154 | R: ReadRef<'data>, |
155 | { |
156 | type Item = SectionIndex; |
157 | |
158 | fn next(&mut self) -> Option<Self::Item> { |
159 | let index: &U32Bytes<{unknown}> = self.sections.next()?; |
160 | Some(SectionIndex(index.get(self.file.endian) as usize)) |
161 | } |
162 | } |
163 | |