| 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: &'static 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: &'static 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: &'static 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: &'static str = "Invalid ELF attribute string value" ; |
| 305 | self.data.read_string().read_error(err) |
| 306 | } |
| 307 | } |
| 308 | |