1 | use core::convert::TryInto; |
2 | |
3 | use crate::elf; |
4 | use crate::endian; |
5 | use crate::read::{Bytes, Error, ReadError, Result}; |
6 | |
7 | use super::FileHeader; |
8 | |
9 | /// An ELF attributes section. |
10 | /// |
11 | /// This may be a GNU attributes section, or an architecture specific attributes section. |
12 | /// |
13 | /// An attributes section contains a series of [`AttributesSubsection`]. |
14 | /// |
15 | /// Returned by [`SectionHeader::attributes`](super::SectionHeader::attributes) |
16 | /// and [`SectionHeader::gnu_attributes`](super::SectionHeader::gnu_attributes). |
17 | #[derive (Debug, Clone)] |
18 | pub struct AttributesSection<'data, Elf: FileHeader> { |
19 | endian: Elf::Endian, |
20 | version: u8, |
21 | data: Bytes<'data>, |
22 | } |
23 | |
24 | impl<'data, Elf: FileHeader> AttributesSection<'data, Elf> { |
25 | /// Parse an ELF attributes section given the section data. |
26 | pub fn new(endian: Elf::Endian, data: &'data [u8]) -> Result<Self> { |
27 | let mut data = Bytes(data); |
28 | |
29 | // Skip the version field that is one byte long. |
30 | // If the section is empty then the version doesn't matter. |
31 | let version = data.read::<u8>().cloned().unwrap_or(b'A' ); |
32 | |
33 | Ok(AttributesSection { |
34 | endian, |
35 | version, |
36 | data, |
37 | }) |
38 | } |
39 | |
40 | /// Return the version of the attributes section. |
41 | pub fn version(&self) -> u8 { |
42 | self.version |
43 | } |
44 | |
45 | /// Return an iterator over the subsections. |
46 | pub fn subsections(&self) -> Result<AttributesSubsectionIterator<'data, Elf>> { |
47 | // There is currently only one format version. |
48 | if self.version != b'A' { |
49 | return Err(Error("Unsupported ELF attributes section version" )); |
50 | } |
51 | |
52 | Ok(AttributesSubsectionIterator { |
53 | endian: self.endian, |
54 | data: self.data, |
55 | }) |
56 | } |
57 | } |
58 | |
59 | /// An iterator for the subsections in an [`AttributesSection`]. |
60 | #[derive (Debug, Clone)] |
61 | pub struct AttributesSubsectionIterator<'data, Elf: FileHeader> { |
62 | endian: Elf::Endian, |
63 | data: Bytes<'data>, |
64 | } |
65 | |
66 | impl<'data, Elf: FileHeader> AttributesSubsectionIterator<'data, Elf> { |
67 | /// Return the next subsection. |
68 | pub fn next(&mut self) -> Result<Option<AttributesSubsection<'data, Elf>>> { |
69 | if self.data.is_empty() { |
70 | return Ok(None); |
71 | } |
72 | |
73 | let result = self.parse().map(Some); |
74 | if result.is_err() { |
75 | self.data = Bytes(&[]); |
76 | } |
77 | result |
78 | } |
79 | |
80 | fn parse(&mut self) -> Result<AttributesSubsection<'data, Elf>> { |
81 | // First read the subsection length. |
82 | let mut data = self.data; |
83 | let length = data |
84 | .read::<endian::U32Bytes<Elf::Endian>>() |
85 | .read_error("ELF attributes section is too short" )? |
86 | .get(self.endian); |
87 | |
88 | // Now read the entire subsection, updating self.data. |
89 | let mut data = self |
90 | .data |
91 | .read_bytes(length as usize) |
92 | .read_error("Invalid ELF attributes subsection length" )?; |
93 | // Skip the subsection length field. |
94 | data.skip(4) |
95 | .read_error("Invalid ELF attributes subsection length" )?; |
96 | |
97 | // TODO: errors here should not prevent reading the next subsection. |
98 | let vendor = data |
99 | .read_string() |
100 | .read_error("Invalid ELF attributes vendor" )?; |
101 | |
102 | Ok(AttributesSubsection { |
103 | endian: self.endian, |
104 | length, |
105 | vendor, |
106 | data, |
107 | }) |
108 | } |
109 | } |
110 | |
111 | impl<'data, Elf: FileHeader> Iterator for AttributesSubsectionIterator<'data, Elf> { |
112 | type Item = Result<AttributesSubsection<'data, Elf>>; |
113 | |
114 | fn next(&mut self) -> Option<Self::Item> { |
115 | self.next().transpose() |
116 | } |
117 | } |
118 | |
119 | /// A subsection in an [`AttributesSection`]. |
120 | /// |
121 | /// A subsection is identified by a vendor name. It contains a series of |
122 | /// [`AttributesSubsubsection`]. |
123 | #[derive (Debug, Clone)] |
124 | pub struct AttributesSubsection<'data, Elf: FileHeader> { |
125 | endian: Elf::Endian, |
126 | length: u32, |
127 | vendor: &'data [u8], |
128 | data: Bytes<'data>, |
129 | } |
130 | |
131 | impl<'data, Elf: FileHeader> AttributesSubsection<'data, Elf> { |
132 | /// Return the length of the attributes subsection. |
133 | pub fn length(&self) -> u32 { |
134 | self.length |
135 | } |
136 | |
137 | /// Return the vendor name of the attributes subsection. |
138 | pub fn vendor(&self) -> &'data [u8] { |
139 | self.vendor |
140 | } |
141 | |
142 | /// Return an iterator over the sub-subsections. |
143 | pub fn subsubsections(&self) -> AttributesSubsubsectionIterator<'data, Elf> { |
144 | AttributesSubsubsectionIterator { |
145 | endian: self.endian, |
146 | data: self.data, |
147 | } |
148 | } |
149 | } |
150 | |
151 | /// An iterator for the sub-subsections in an [`AttributesSubsection`]. |
152 | #[derive (Debug, Clone)] |
153 | pub struct AttributesSubsubsectionIterator<'data, Elf: FileHeader> { |
154 | endian: Elf::Endian, |
155 | data: Bytes<'data>, |
156 | } |
157 | |
158 | impl<'data, Elf: FileHeader> AttributesSubsubsectionIterator<'data, Elf> { |
159 | /// Return the next sub-subsection. |
160 | pub fn next(&mut self) -> Result<Option<AttributesSubsubsection<'data>>> { |
161 | if self.data.is_empty() { |
162 | return Ok(None); |
163 | } |
164 | |
165 | let result = self.parse().map(Some); |
166 | if result.is_err() { |
167 | self.data = Bytes(&[]); |
168 | } |
169 | result |
170 | } |
171 | |
172 | fn parse(&mut self) -> Result<AttributesSubsubsection<'data>> { |
173 | // The format of a sub-section looks like this: |
174 | // |
175 | // <file-tag> <size> <attribute>* |
176 | // | <section-tag> <size> <section-number>* 0 <attribute>* |
177 | // | <symbol-tag> <size> <symbol-number>* 0 <attribute>* |
178 | let mut data = self.data; |
179 | let tag = *data |
180 | .read::<u8>() |
181 | .read_error("ELF attributes subsection is too short" )?; |
182 | let length = data |
183 | .read::<endian::U32Bytes<Elf::Endian>>() |
184 | .read_error("ELF attributes subsection is too short" )? |
185 | .get(self.endian); |
186 | |
187 | // Now read the entire sub-subsection, updating self.data. |
188 | let mut data = self |
189 | .data |
190 | .read_bytes(length as usize) |
191 | .read_error("Invalid ELF attributes sub-subsection length" )?; |
192 | // Skip the tag and sub-subsection size field. |
193 | data.skip(1 + 4) |
194 | .read_error("Invalid ELF attributes sub-subsection length" )?; |
195 | |
196 | // TODO: errors here should not prevent reading the next sub-subsection. |
197 | let indices = if tag == elf::Tag_Section || tag == elf::Tag_Symbol { |
198 | data.read_string() |
199 | .map(Bytes) |
200 | .read_error("Missing ELF attributes sub-subsection indices" )? |
201 | } else if tag == elf::Tag_File { |
202 | Bytes(&[]) |
203 | } else { |
204 | return Err(Error("Unimplemented ELF attributes sub-subsection tag" )); |
205 | }; |
206 | |
207 | Ok(AttributesSubsubsection { |
208 | tag, |
209 | length, |
210 | indices, |
211 | data, |
212 | }) |
213 | } |
214 | } |
215 | |
216 | impl<'data, Elf: FileHeader> Iterator for AttributesSubsubsectionIterator<'data, Elf> { |
217 | type Item = Result<AttributesSubsubsection<'data>>; |
218 | |
219 | fn next(&mut self) -> Option<Self::Item> { |
220 | self.next().transpose() |
221 | } |
222 | } |
223 | |
224 | /// A sub-subsection in an [`AttributesSubsection`]. |
225 | /// |
226 | /// A sub-subsection is identified by a tag. It contains an optional series of indices, |
227 | /// followed by a series of attributes. |
228 | #[derive (Debug, Clone)] |
229 | pub struct AttributesSubsubsection<'data> { |
230 | tag: u8, |
231 | length: u32, |
232 | indices: Bytes<'data>, |
233 | data: Bytes<'data>, |
234 | } |
235 | |
236 | impl<'data> AttributesSubsubsection<'data> { |
237 | /// Return the tag of the attributes sub-subsection. |
238 | pub fn tag(&self) -> u8 { |
239 | self.tag |
240 | } |
241 | |
242 | /// Return the length of the attributes sub-subsection. |
243 | pub fn length(&self) -> u32 { |
244 | self.length |
245 | } |
246 | |
247 | /// Return the data containing the indices. |
248 | pub fn indices_data(&self) -> &'data [u8] { |
249 | self.indices.0 |
250 | } |
251 | |
252 | /// Return the indices. |
253 | /// |
254 | /// This will be section indices if the tag is `Tag_Section`, |
255 | /// or symbol indices if the tag is `Tag_Symbol`, |
256 | /// and otherwise it will be empty. |
257 | pub fn indices(&self) -> AttributeIndexIterator<'data> { |
258 | AttributeIndexIterator { data: self.indices } |
259 | } |
260 | |
261 | /// Return the data containing the attributes. |
262 | pub fn attributes_data(&self) -> &'data [u8] { |
263 | self.data.0 |
264 | } |
265 | |
266 | /// Return a parser for the data containing the attributes. |
267 | pub fn attributes(&self) -> AttributeReader<'data> { |
268 | AttributeReader { data: self.data } |
269 | } |
270 | } |
271 | |
272 | /// An iterator over the indices in an [`AttributesSubsubsection`]. |
273 | #[derive (Debug, Clone)] |
274 | pub struct AttributeIndexIterator<'data> { |
275 | data: Bytes<'data>, |
276 | } |
277 | |
278 | impl<'data> AttributeIndexIterator<'data> { |
279 | /// Parse the next index. |
280 | pub fn next(&mut self) -> Result<Option<u32>> { |
281 | if self.data.is_empty() { |
282 | return Ok(None); |
283 | } |
284 | |
285 | let result: Result = self.parse().map(op:Some); |
286 | if result.is_err() { |
287 | self.data = Bytes(&[]); |
288 | } |
289 | result |
290 | } |
291 | |
292 | fn parse(&mut self) -> Result<u32> { |
293 | let err: &'static str = "Invalid ELF attribute index" ; |
294 | self.data |
295 | .read_uleb128() |
296 | .read_error(err)? |
297 | .try_into() |
298 | .map_err(|_| ()) |
299 | .read_error(err) |
300 | } |
301 | } |
302 | |
303 | impl<'data> Iterator for AttributeIndexIterator<'data> { |
304 | type Item = Result<u32>; |
305 | |
306 | fn next(&mut self) -> Option<Self::Item> { |
307 | self.next().transpose() |
308 | } |
309 | } |
310 | |
311 | /// A parser for the attributes in an [`AttributesSubsubsection`]. |
312 | /// |
313 | /// The parser relies on the caller to know the format of the data for each attribute tag. |
314 | #[derive (Debug, Clone)] |
315 | pub struct AttributeReader<'data> { |
316 | data: Bytes<'data>, |
317 | } |
318 | |
319 | impl<'data> AttributeReader<'data> { |
320 | /// Parse a tag. |
321 | pub fn read_tag(&mut self) -> Result<Option<u64>> { |
322 | if self.data.is_empty() { |
323 | return Ok(None); |
324 | } |
325 | let err: &'static str = "Invalid ELF attribute tag" ; |
326 | self.data.read_uleb128().read_error(err).map(op:Some) |
327 | } |
328 | |
329 | /// Parse an integer value. |
330 | pub fn read_integer(&mut self) -> Result<u64> { |
331 | let err: &'static str = "Invalid ELF attribute integer value" ; |
332 | self.data.read_uleb128().read_error(err) |
333 | } |
334 | |
335 | /// Parse a string value. |
336 | pub fn read_string(&mut self) -> Result<&'data [u8]> { |
337 | let err: &'static str = "Invalid ELF attribute string value" ; |
338 | self.data.read_string().read_error(err) |
339 | } |
340 | } |
341 | |