1 use alloc::borrow::Cow; 2 use core::convert::TryInto; 3 use core::fmt::Debug; 4 use core::hash::Hash; 5 use core::ops::{Add, AddAssign, Sub}; 6 7 use crate::common::Format; 8 use crate::endianity::Endianity; 9 use crate::leb128; 10 use crate::read::{Error, Result}; 11 12 /// An identifier for an offset within a section reader. 13 /// 14 /// This is used for error reporting. The meaning of this value is specific to 15 /// each reader implementation. The values should be chosen to be unique amongst 16 /// all readers. If values are not unique then errors may point to the wrong reader. 17 #[derive(Debug, Clone, Copy, PartialEq, Eq)] 18 pub struct ReaderOffsetId(pub u64); 19 20 /// A trait for offsets with a DWARF section. 21 /// 22 /// This allows consumers to choose a size that is appropriate for their address space. 23 pub trait ReaderOffset: 24 Debug + Copy + Eq + Ord + Hash + Add<Output = Self> + AddAssign + Sub<Output = Self> 25 { 26 /// Convert a u8 to an offset. from_u8(offset: u8) -> Self27 fn from_u8(offset: u8) -> Self; 28 29 /// Convert a u16 to an offset. from_u16(offset: u16) -> Self30 fn from_u16(offset: u16) -> Self; 31 32 /// Convert an i16 to an offset. from_i16(offset: i16) -> Self33 fn from_i16(offset: i16) -> Self; 34 35 /// Convert a u32 to an offset. from_u32(offset: u32) -> Self36 fn from_u32(offset: u32) -> Self; 37 38 /// Convert a u64 to an offset. 39 /// 40 /// Returns `Error::UnsupportedOffset` if the value is too large. from_u64(offset: u64) -> Result<Self>41 fn from_u64(offset: u64) -> Result<Self>; 42 43 /// Convert an offset to a u64. into_u64(self) -> u6444 fn into_u64(self) -> u64; 45 46 /// Wrapping (modular) addition. Computes `self + other`. wrapping_add(self, other: Self) -> Self47 fn wrapping_add(self, other: Self) -> Self; 48 49 /// Checked subtraction. Computes `self - other`. checked_sub(self, other: Self) -> Option<Self>50 fn checked_sub(self, other: Self) -> Option<Self>; 51 } 52 53 impl ReaderOffset for u64 { 54 #[inline] from_u8(offset: u8) -> Self55 fn from_u8(offset: u8) -> Self { 56 u64::from(offset) 57 } 58 59 #[inline] from_u16(offset: u16) -> Self60 fn from_u16(offset: u16) -> Self { 61 u64::from(offset) 62 } 63 64 #[inline] from_i16(offset: i16) -> Self65 fn from_i16(offset: i16) -> Self { 66 offset as u64 67 } 68 69 #[inline] from_u32(offset: u32) -> Self70 fn from_u32(offset: u32) -> Self { 71 u64::from(offset) 72 } 73 74 #[inline] from_u64(offset: u64) -> Result<Self>75 fn from_u64(offset: u64) -> Result<Self> { 76 Ok(offset) 77 } 78 79 #[inline] into_u64(self) -> u6480 fn into_u64(self) -> u64 { 81 self 82 } 83 84 #[inline] wrapping_add(self, other: Self) -> Self85 fn wrapping_add(self, other: Self) -> Self { 86 self.wrapping_add(other) 87 } 88 89 #[inline] checked_sub(self, other: Self) -> Option<Self>90 fn checked_sub(self, other: Self) -> Option<Self> { 91 self.checked_sub(other) 92 } 93 } 94 95 impl ReaderOffset for u32 { 96 #[inline] from_u8(offset: u8) -> Self97 fn from_u8(offset: u8) -> Self { 98 u32::from(offset) 99 } 100 101 #[inline] from_u16(offset: u16) -> Self102 fn from_u16(offset: u16) -> Self { 103 u32::from(offset) 104 } 105 106 #[inline] from_i16(offset: i16) -> Self107 fn from_i16(offset: i16) -> Self { 108 offset as u32 109 } 110 111 #[inline] from_u32(offset: u32) -> Self112 fn from_u32(offset: u32) -> Self { 113 offset 114 } 115 116 #[inline] from_u64(offset64: u64) -> Result<Self>117 fn from_u64(offset64: u64) -> Result<Self> { 118 let offset = offset64 as u32; 119 if u64::from(offset) == offset64 { 120 Ok(offset) 121 } else { 122 Err(Error::UnsupportedOffset) 123 } 124 } 125 126 #[inline] into_u64(self) -> u64127 fn into_u64(self) -> u64 { 128 u64::from(self) 129 } 130 131 #[inline] wrapping_add(self, other: Self) -> Self132 fn wrapping_add(self, other: Self) -> Self { 133 self.wrapping_add(other) 134 } 135 136 #[inline] checked_sub(self, other: Self) -> Option<Self>137 fn checked_sub(self, other: Self) -> Option<Self> { 138 self.checked_sub(other) 139 } 140 } 141 142 impl ReaderOffset for usize { 143 #[inline] from_u8(offset: u8) -> Self144 fn from_u8(offset: u8) -> Self { 145 offset as usize 146 } 147 148 #[inline] from_u16(offset: u16) -> Self149 fn from_u16(offset: u16) -> Self { 150 offset as usize 151 } 152 153 #[inline] from_i16(offset: i16) -> Self154 fn from_i16(offset: i16) -> Self { 155 offset as usize 156 } 157 158 #[inline] from_u32(offset: u32) -> Self159 fn from_u32(offset: u32) -> Self { 160 offset as usize 161 } 162 163 #[inline] from_u64(offset64: u64) -> Result<Self>164 fn from_u64(offset64: u64) -> Result<Self> { 165 let offset = offset64 as usize; 166 if offset as u64 == offset64 { 167 Ok(offset) 168 } else { 169 Err(Error::UnsupportedOffset) 170 } 171 } 172 173 #[inline] into_u64(self) -> u64174 fn into_u64(self) -> u64 { 175 self as u64 176 } 177 178 #[inline] wrapping_add(self, other: Self) -> Self179 fn wrapping_add(self, other: Self) -> Self { 180 self.wrapping_add(other) 181 } 182 183 #[inline] checked_sub(self, other: Self) -> Option<Self>184 fn checked_sub(self, other: Self) -> Option<Self> { 185 self.checked_sub(other) 186 } 187 } 188 189 /// A trait for reading the data from a DWARF section. 190 /// 191 /// All read operations advance the section offset of the reader 192 /// unless specified otherwise. 193 /// 194 /// ## Choosing a `Reader` Implementation 195 /// 196 /// `gimli` comes with a few different `Reader` implementations and lets you 197 /// choose the one that is right for your use case. A `Reader` is essentially a 198 /// view into the raw bytes that make up some DWARF, but this view might borrow 199 /// the underlying data or use reference counting ownership, and it might be 200 /// thread safe or not. 201 /// 202 /// | Implementation | Ownership | Thread Safe | Notes | 203 /// |:------------------|:------------------|:------------|:------| 204 /// | [`EndianSlice`](./struct.EndianSlice.html) | Borrowed | Yes | Fastest, but requires that all of your code work with borrows. | 205 /// | [`EndianRcSlice`](./struct.EndianRcSlice.html) | Reference counted | No | Shared ownership via reference counting, which alleviates the borrow restrictions of `EndianSlice` but imposes reference counting increments and decrements. Cannot be sent across threads, because the reference count is not atomic. | 206 /// | [`EndianArcSlice`](./struct.EndianArcSlice.html) | Reference counted | Yes | The same as `EndianRcSlice`, but uses atomic reference counting, and therefore reference counting operations are slower but `EndianArcSlice`s may be sent across threads. | 207 /// | [`EndianReader<T>`](./struct.EndianReader.html) | Same as `T` | Same as `T` | Escape hatch for easily defining your own type of `Reader`. | 208 pub trait Reader: Debug + Clone { 209 /// The endianity of bytes that are read. 210 type Endian: Endianity; 211 212 /// The type used for offsets and lengths. 213 type Offset: ReaderOffset; 214 215 /// Return the endianity of bytes that are read. endian(&self) -> Self::Endian216 fn endian(&self) -> Self::Endian; 217 218 /// Return the number of bytes remaining. len(&self) -> Self::Offset219 fn len(&self) -> Self::Offset; 220 221 /// Set the number of bytes remaining to zero. empty(&mut self)222 fn empty(&mut self); 223 224 /// Set the number of bytes remaining to the specified length. truncate(&mut self, len: Self::Offset) -> Result<()>225 fn truncate(&mut self, len: Self::Offset) -> Result<()>; 226 227 /// Return the offset of this reader's data relative to the start of 228 /// the given base reader's data. 229 /// 230 /// May panic if this reader's data is not contained within the given 231 /// base reader's data. offset_from(&self, base: &Self) -> Self::Offset232 fn offset_from(&self, base: &Self) -> Self::Offset; 233 234 /// Return an identifier for the current reader offset. offset_id(&self) -> ReaderOffsetId235 fn offset_id(&self) -> ReaderOffsetId; 236 237 /// Return the offset corresponding to the given `id` if 238 /// it is associated with this reader. lookup_offset_id(&self, id: ReaderOffsetId) -> Option<Self::Offset>239 fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option<Self::Offset>; 240 241 /// Find the index of the first occurence of the given byte. 242 /// The offset of the reader is not changed. find(&self, byte: u8) -> Result<Self::Offset>243 fn find(&self, byte: u8) -> Result<Self::Offset>; 244 245 /// Discard the specified number of bytes. skip(&mut self, len: Self::Offset) -> Result<()>246 fn skip(&mut self, len: Self::Offset) -> Result<()>; 247 248 /// Split a reader in two. 249 /// 250 /// A new reader is returned that can be used to read the next 251 /// `len` bytes, and `self` is advanced so that it reads the remainder. split(&mut self, len: Self::Offset) -> Result<Self>252 fn split(&mut self, len: Self::Offset) -> Result<Self>; 253 254 /// Return all remaining data as a clone-on-write slice. 255 /// 256 /// The slice will be borrowed where possible, but some readers may 257 /// always return an owned vector. 258 /// 259 /// Does not advance the reader. to_slice(&self) -> Result<Cow<[u8]>>260 fn to_slice(&self) -> Result<Cow<[u8]>>; 261 262 /// Convert all remaining data to a clone-on-write string. 263 /// 264 /// The string will be borrowed where possible, but some readers may 265 /// always return an owned string. 266 /// 267 /// Does not advance the reader. 268 /// 269 /// Returns an error if the data contains invalid characters. to_string(&self) -> Result<Cow<str>>270 fn to_string(&self) -> Result<Cow<str>>; 271 272 /// Convert all remaining data to a clone-on-write string, including invalid characters. 273 /// 274 /// The string will be borrowed where possible, but some readers may 275 /// always return an owned string. 276 /// 277 /// Does not advance the reader. to_string_lossy(&self) -> Result<Cow<str>>278 fn to_string_lossy(&self) -> Result<Cow<str>>; 279 280 /// Read exactly `buf.len()` bytes into `buf`. read_slice(&mut self, buf: &mut [u8]) -> Result<()>281 fn read_slice(&mut self, buf: &mut [u8]) -> Result<()>; 282 283 /// Read a u8 array. 284 #[inline] read_u8_array<A>(&mut self) -> Result<A> where A: Sized + Default + AsMut<[u8]>,285 fn read_u8_array<A>(&mut self) -> Result<A> 286 where 287 A: Sized + Default + AsMut<[u8]>, 288 { 289 let mut val = Default::default(); 290 self.read_slice(<A as AsMut<[u8]>>::as_mut(&mut val))?; 291 Ok(val) 292 } 293 294 /// Return true if the number of bytes remaining is zero. 295 #[inline] is_empty(&self) -> bool296 fn is_empty(&self) -> bool { 297 self.len() == Self::Offset::from_u8(0) 298 } 299 300 /// Read a u8. 301 #[inline] read_u8(&mut self) -> Result<u8>302 fn read_u8(&mut self) -> Result<u8> { 303 let a: [u8; 1] = self.read_u8_array()?; 304 Ok(a[0]) 305 } 306 307 /// Read an i8. 308 #[inline] read_i8(&mut self) -> Result<i8>309 fn read_i8(&mut self) -> Result<i8> { 310 let a: [u8; 1] = self.read_u8_array()?; 311 Ok(a[0] as i8) 312 } 313 314 /// Read a u16. 315 #[inline] read_u16(&mut self) -> Result<u16>316 fn read_u16(&mut self) -> Result<u16> { 317 let a: [u8; 2] = self.read_u8_array()?; 318 Ok(self.endian().read_u16(&a)) 319 } 320 321 /// Read an i16. 322 #[inline] read_i16(&mut self) -> Result<i16>323 fn read_i16(&mut self) -> Result<i16> { 324 let a: [u8; 2] = self.read_u8_array()?; 325 Ok(self.endian().read_i16(&a)) 326 } 327 328 /// Read a u32. 329 #[inline] read_u32(&mut self) -> Result<u32>330 fn read_u32(&mut self) -> Result<u32> { 331 let a: [u8; 4] = self.read_u8_array()?; 332 Ok(self.endian().read_u32(&a)) 333 } 334 335 /// Read an i32. 336 #[inline] read_i32(&mut self) -> Result<i32>337 fn read_i32(&mut self) -> Result<i32> { 338 let a: [u8; 4] = self.read_u8_array()?; 339 Ok(self.endian().read_i32(&a)) 340 } 341 342 /// Read a u64. 343 #[inline] read_u64(&mut self) -> Result<u64>344 fn read_u64(&mut self) -> Result<u64> { 345 let a: [u8; 8] = self.read_u8_array()?; 346 Ok(self.endian().read_u64(&a)) 347 } 348 349 /// Read an i64. 350 #[inline] read_i64(&mut self) -> Result<i64>351 fn read_i64(&mut self) -> Result<i64> { 352 let a: [u8; 8] = self.read_u8_array()?; 353 Ok(self.endian().read_i64(&a)) 354 } 355 356 /// Read a f32. 357 #[inline] read_f32(&mut self) -> Result<f32>358 fn read_f32(&mut self) -> Result<f32> { 359 let a: [u8; 4] = self.read_u8_array()?; 360 Ok(self.endian().read_f32(&a)) 361 } 362 363 /// Read a f64. 364 #[inline] read_f64(&mut self) -> Result<f64>365 fn read_f64(&mut self) -> Result<f64> { 366 let a: [u8; 8] = self.read_u8_array()?; 367 Ok(self.endian().read_f64(&a)) 368 } 369 370 /// Read an unsigned n-bytes integer u64. 371 /// 372 /// # Panics 373 /// 374 /// Panics when nbytes < 1 or nbytes > 8 375 #[inline] read_uint(&mut self, n: usize) -> Result<u64>376 fn read_uint(&mut self, n: usize) -> Result<u64> { 377 let mut buf = [0; 8]; 378 self.read_slice(&mut buf[..n])?; 379 Ok(self.endian().read_uint(&buf[..n])) 380 } 381 382 /// Read a null-terminated slice, and return it (excluding the null). read_null_terminated_slice(&mut self) -> Result<Self>383 fn read_null_terminated_slice(&mut self) -> Result<Self> { 384 let idx = self.find(0)?; 385 let val = self.split(idx)?; 386 self.skip(Self::Offset::from_u8(1))?; 387 Ok(val) 388 } 389 390 /// Read an unsigned LEB128 encoded integer. read_uleb128(&mut self) -> Result<u64>391 fn read_uleb128(&mut self) -> Result<u64> { 392 leb128::read::unsigned(self) 393 } 394 395 /// Read an unsigned LEB128 encoded u32. read_uleb128_u32(&mut self) -> Result<u32>396 fn read_uleb128_u32(&mut self) -> Result<u32> { 397 leb128::read::unsigned(self)? 398 .try_into() 399 .map_err(|_| Error::BadUnsignedLeb128) 400 } 401 402 /// Read an unsigned LEB128 encoded u16. read_uleb128_u16(&mut self) -> Result<u16>403 fn read_uleb128_u16(&mut self) -> Result<u16> { 404 leb128::read::u16(self) 405 } 406 407 /// Read a signed LEB128 encoded integer. read_sleb128(&mut self) -> Result<i64>408 fn read_sleb128(&mut self) -> Result<i64> { 409 leb128::read::signed(self) 410 } 411 412 /// Read an initial length field. 413 /// 414 /// This field is encoded as either a 32-bit length or 415 /// a 64-bit length, and the returned `Format` indicates which. read_initial_length(&mut self) -> Result<(Self::Offset, Format)>416 fn read_initial_length(&mut self) -> Result<(Self::Offset, Format)> { 417 const MAX_DWARF_32_UNIT_LENGTH: u32 = 0xffff_fff0; 418 const DWARF_64_INITIAL_UNIT_LENGTH: u32 = 0xffff_ffff; 419 420 let val = self.read_u32()?; 421 if val < MAX_DWARF_32_UNIT_LENGTH { 422 Ok((Self::Offset::from_u32(val), Format::Dwarf32)) 423 } else if val == DWARF_64_INITIAL_UNIT_LENGTH { 424 let val = self.read_u64().and_then(Self::Offset::from_u64)?; 425 Ok((val, Format::Dwarf64)) 426 } else { 427 Err(Error::UnknownReservedLength) 428 } 429 } 430 431 /// Read an address-sized integer, and return it as a `u64`. read_address(&mut self, address_size: u8) -> Result<u64>432 fn read_address(&mut self, address_size: u8) -> Result<u64> { 433 match address_size { 434 1 => self.read_u8().map(u64::from), 435 2 => self.read_u16().map(u64::from), 436 4 => self.read_u32().map(u64::from), 437 8 => self.read_u64(), 438 otherwise => Err(Error::UnsupportedAddressSize(otherwise)), 439 } 440 } 441 442 /// Parse a word-sized integer according to the DWARF format. 443 /// 444 /// These are always used to encode section offsets or lengths, 445 /// and so have a type of `Self::Offset`. read_word(&mut self, format: Format) -> Result<Self::Offset>446 fn read_word(&mut self, format: Format) -> Result<Self::Offset> { 447 match format { 448 Format::Dwarf32 => self.read_u32().map(Self::Offset::from_u32), 449 Format::Dwarf64 => self.read_u64().and_then(Self::Offset::from_u64), 450 } 451 } 452 453 /// Parse a word-sized section length according to the DWARF format. 454 #[inline] read_length(&mut self, format: Format) -> Result<Self::Offset>455 fn read_length(&mut self, format: Format) -> Result<Self::Offset> { 456 self.read_word(format) 457 } 458 459 /// Parse a word-sized section offset according to the DWARF format. 460 #[inline] read_offset(&mut self, format: Format) -> Result<Self::Offset>461 fn read_offset(&mut self, format: Format) -> Result<Self::Offset> { 462 self.read_word(format) 463 } 464 465 /// Parse a section offset of the given size. 466 /// 467 /// This is used for `DW_FORM_ref_addr` values in DWARF version 2. read_sized_offset(&mut self, size: u8) -> Result<Self::Offset>468 fn read_sized_offset(&mut self, size: u8) -> Result<Self::Offset> { 469 match size { 470 1 => self.read_u8().map(u64::from), 471 2 => self.read_u16().map(u64::from), 472 4 => self.read_u32().map(u64::from), 473 8 => self.read_u64(), 474 otherwise => Err(Error::UnsupportedOffsetSize(otherwise)), 475 } 476 .and_then(Self::Offset::from_u64) 477 } 478 } 479