| 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 | |