1use core::convert::TryInto;
2
3use crate::elf;
4use crate::endian;
5use crate::read::{Bytes, Error, ReadError, Result};
6
7use 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)]
18pub struct AttributesSection<'data, Elf: FileHeader> {
19 endian: Elf::Endian,
20 version: u8,
21 data: Bytes<'data>,
22}
23
24impl<'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)]
61pub struct AttributesSubsectionIterator<'data, Elf: FileHeader> {
62 endian: Elf::Endian,
63 data: Bytes<'data>,
64}
65
66impl<'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
111impl<'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)]
124pub struct AttributesSubsection<'data, Elf: FileHeader> {
125 endian: Elf::Endian,
126 length: u32,
127 vendor: &'data [u8],
128 data: Bytes<'data>,
129}
130
131impl<'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)]
153pub struct AttributesSubsubsectionIterator<'data, Elf: FileHeader> {
154 endian: Elf::Endian,
155 data: Bytes<'data>,
156}
157
158impl<'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
216impl<'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)]
229pub struct AttributesSubsubsection<'data> {
230 tag: u8,
231 length: u32,
232 indices: Bytes<'data>,
233 data: Bytes<'data>,
234}
235
236impl<'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)]
274pub struct AttributeIndexIterator<'data> {
275 data: Bytes<'data>,
276}
277
278impl<'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, Error> = 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
303impl<'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)]
315pub struct AttributeReader<'data> {
316 data: Bytes<'data>,
317}
318
319impl<'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