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