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 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)]
62pub struct AttributesSubsectionIterator<'data, Elf: FileHeader> {
63 endian: Elf::Endian,
64 data: Bytes<'data>,
65}
66
67impl<'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)]
116pub struct AttributesSubsection<'data, Elf: FileHeader> {
117 endian: Elf::Endian,
118 length: u32,
119 vendor: &'data [u8],
120 data: Bytes<'data>,
121}
122
123impl<'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)]
145pub struct AttributesSubsubsectionIterator<'data, Elf: FileHeader> {
146 endian: Elf::Endian,
147 data: Bytes<'data>,
148}
149
150impl<'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)]
212pub struct AttributesSubsubsection<'data> {
213 tag: u8,
214 length: u32,
215 indices: Bytes<'data>,
216 data: Bytes<'data>,
217}
218
219impl<'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)]
257pub struct AttributeIndexIterator<'data> {
258 data: Bytes<'data>,
259}
260
261impl<'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)]
282pub struct AttributeReader<'data> {
283 data: Bytes<'data>,
284}
285
286impl<'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