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