1 #[cfg(feature = "read")]
2 use alloc
::borrow
::Cow
;
3 use core
::convert
::TryInto
;
6 use core
::ops
::{Add, AddAssign, Sub}
;
8 use crate::common
::Format
;
9 use crate::endianity
::Endianity
;
11 use crate::read
::{Error, Result}
;
13 /// An identifier for an offset within a section reader.
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);
21 /// A trait for offsets with a DWARF section.
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>
27 /// Convert a u8 to an offset.
28 fn from_u8(offset
: u8) -> Self;
30 /// Convert a u16 to an offset.
31 fn from_u16(offset
: u16) -> Self;
33 /// Convert an i16 to an offset.
34 fn from_i16(offset
: i16) -> Self;
36 /// Convert a u32 to an offset.
37 fn from_u32(offset
: u32) -> Self;
39 /// Convert a u64 to an offset.
41 /// Returns `Error::UnsupportedOffset` if the value is too large.
42 fn from_u64(offset
: u64) -> Result
<Self>;
44 /// Convert an offset to a u64.
45 fn into_u64(self) -> u64;
47 /// Wrapping (modular) addition. Computes `self + other`.
48 fn wrapping_add(self, other
: Self) -> Self;
50 /// Checked subtraction. Computes `self - other`.
51 fn checked_sub(self, other
: Self) -> Option
<Self>;
54 impl ReaderOffset
for u64 {
56 fn from_u8(offset
: u8) -> Self {
61 fn from_u16(offset
: u16) -> Self {
66 fn from_i16(offset
: i16) -> Self {
71 fn from_u32(offset
: u32) -> Self {
76 fn from_u64(offset
: u64) -> Result
<Self> {
81 fn into_u64(self) -> u64 {
86 fn wrapping_add(self, other
: Self) -> Self {
87 self.wrapping_add(other
)
91 fn checked_sub(self, other
: Self) -> Option
<Self> {
92 self.checked_sub(other
)
96 impl ReaderOffset
for u32 {
98 fn from_u8(offset
: u8) -> Self {
103 fn from_u16(offset
: u16) -> Self {
108 fn from_i16(offset
: i16) -> Self {
113 fn from_u32(offset
: u32) -> Self {
118 fn from_u64(offset64
: u64) -> Result
<Self> {
119 let offset
= offset64
as u32;
120 if u64::from(offset
) == offset64
{
123 Err(Error
::UnsupportedOffset
)
128 fn into_u64(self) -> u64 {
133 fn wrapping_add(self, other
: Self) -> Self {
134 self.wrapping_add(other
)
138 fn checked_sub(self, other
: Self) -> Option
<Self> {
139 self.checked_sub(other
)
143 impl ReaderOffset
for usize {
145 fn from_u8(offset
: u8) -> Self {
150 fn from_u16(offset
: u16) -> Self {
155 fn from_i16(offset
: i16) -> Self {
160 fn from_u32(offset
: u32) -> Self {
165 fn from_u64(offset64
: u64) -> Result
<Self> {
166 let offset
= offset64
as usize;
167 if offset
as u64 == offset64
{
170 Err(Error
::UnsupportedOffset
)
175 fn into_u64(self) -> u64 {
180 fn wrapping_add(self, other
: Self) -> Self {
181 self.wrapping_add(other
)
185 fn checked_sub(self, other
: Self) -> Option
<Self> {
186 self.checked_sub(other
)
190 #[cfg(not(feature = "read"))]
191 pub(crate) mod seal_if_no_alloc
{
196 /// A trait for reading the data from a DWARF section.
198 /// All read operations advance the section offset of the reader
199 /// unless specified otherwise.
201 /// ## Choosing a `Reader` Implementation
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.
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
;
219 /// The type used for offsets and lengths.
220 type Offset
: ReaderOffset
;
222 /// Return the endianity of bytes that are read.
223 fn endian(&self) -> Self::Endian
;
225 /// Return the number of bytes remaining.
226 fn len(&self) -> Self::Offset
;
228 /// Set the number of bytes remaining to zero.
231 /// Set the number of bytes remaining to the specified length.
232 fn truncate(&mut self, len
: Self::Offset
) -> Result
<()>;
234 /// Return the offset of this reader's data relative to the start of
235 /// the given base reader's data.
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
;
241 /// Return an identifier for the current reader offset.
242 fn offset_id(&self) -> ReaderOffsetId
;
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
>;
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
>;
252 /// Discard the specified number of bytes.
253 fn skip(&mut self, len
: Self::Offset
) -> Result
<()>;
255 /// Split a reader in two.
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>;
261 /// This trait cannot be implemented if "read" feature is not enabled.
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
267 #[cfg(not(feature = "read"))]
268 fn cannot_implement() -> seal_if_no_alloc
::Sealed
;
270 /// Return all remaining data as a clone-on-write slice.
272 /// The slice will be borrowed where possible, but some readers may
273 /// always return an owned vector.
275 /// Does not advance the reader.
276 #[cfg(feature = "read")]
277 fn to_slice(&self) -> Result
<Cow
<[u8]>>;
279 /// Convert all remaining data to a clone-on-write string.
281 /// The string will be borrowed where possible, but some readers may
282 /// always return an owned string.
284 /// Does not advance the reader.
286 /// Returns an error if the data contains invalid characters.
287 #[cfg(feature = "read")]
288 fn to_string(&self) -> Result
<Cow
<str>>;
290 /// Convert all remaining data to a clone-on-write string, including invalid characters.
292 /// The string will be borrowed where possible, but some readers may
293 /// always return an owned string.
295 /// Does not advance the reader.
296 #[cfg(feature = "read")]
297 fn to_string_lossy(&self) -> Result
<Cow
<str>>;
299 /// Read exactly `buf.len()` bytes into `buf`.
300 fn read_slice(&mut self, buf
: &mut [u8]) -> Result
<()>;
304 fn read_u8_array
<A
>(&mut self) -> Result
<A
>
306 A
: Sized
+ Default
+ AsMut
<[u8]>,
308 let mut val
= Default
::default();
309 self.read_slice(<A
as AsMut
<[u8]>>::as_mut(&mut val
))?
;
313 /// Return true if the number of bytes remaining is zero.
315 fn is_empty(&self) -> bool
{
316 self.len() == Self::Offset
::from_u8(0)
321 fn read_u8(&mut self) -> Result
<u8> {
322 let a
: [u8; 1] = self.read_u8_array()?
;
328 fn read_i8(&mut self) -> Result
<i8> {
329 let a
: [u8; 1] = self.read_u8_array()?
;
335 fn read_u16(&mut self) -> Result
<u16> {
336 let a
: [u8; 2] = self.read_u8_array()?
;
337 Ok(self.endian().read_u16(&a
))
342 fn read_i16(&mut self) -> Result
<i16> {
343 let a
: [u8; 2] = self.read_u8_array()?
;
344 Ok(self.endian().read_i16(&a
))
349 fn read_u32(&mut self) -> Result
<u32> {
350 let a
: [u8; 4] = self.read_u8_array()?
;
351 Ok(self.endian().read_u32(&a
))
356 fn read_i32(&mut self) -> Result
<i32> {
357 let a
: [u8; 4] = self.read_u8_array()?
;
358 Ok(self.endian().read_i32(&a
))
363 fn read_u64(&mut self) -> Result
<u64> {
364 let a
: [u8; 8] = self.read_u8_array()?
;
365 Ok(self.endian().read_u64(&a
))
370 fn read_i64(&mut self) -> Result
<i64> {
371 let a
: [u8; 8] = self.read_u8_array()?
;
372 Ok(self.endian().read_i64(&a
))
377 fn read_f32(&mut self) -> Result
<f32> {
378 let a
: [u8; 4] = self.read_u8_array()?
;
379 Ok(self.endian().read_f32(&a
))
384 fn read_f64(&mut self) -> Result
<f64> {
385 let a
: [u8; 8] = self.read_u8_array()?
;
386 Ok(self.endian().read_f64(&a
))
389 /// Read an unsigned n-bytes integer u64.
393 /// Panics when nbytes < 1 or nbytes > 8
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
]))
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))?
;
409 /// Skip a LEB128 encoded integer.
410 fn skip_leb128(&mut self) -> Result
<()> {
411 leb128
::read
::skip(self)
414 /// Read an unsigned LEB128 encoded integer.
415 fn read_uleb128(&mut self) -> Result
<u64> {
416 leb128
::read
::unsigned(self)
419 /// Read an unsigned LEB128 encoded u32.
420 fn read_uleb128_u32(&mut self) -> Result
<u32> {
421 leb128
::read
::unsigned(self)?
423 .map_err(|_
| Error
::BadUnsignedLeb128
)
426 /// Read an unsigned LEB128 encoded u16.
427 fn read_uleb128_u16(&mut self) -> Result
<u16> {
428 leb128
::read
::u16(self)
431 /// Read a signed LEB128 encoded integer.
432 fn read_sleb128(&mut self) -> Result
<i64> {
433 leb128
::read
::signed(self)
436 /// Read an initial length field.
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;
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
))
451 Err(Error
::UnknownReservedLength
)
455 /// Read an address-sized integer, and return it as a `u64`.
456 fn read_address(&mut self, address_size
: u8) -> Result
<u64> {
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
)),
466 /// Parse a word-sized integer according to the DWARF format.
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
> {
472 Format
::Dwarf32
=> self.read_u32().map(Self::Offset
::from_u32
),
473 Format
::Dwarf64
=> self.read_u64().and_then(Self::Offset
::from_u64
),
477 /// Parse a word-sized section length according to the DWARF format.
479 fn read_length(&mut self, format
: Format
) -> Result
<Self::Offset
> {
480 self.read_word(format
)
483 /// Parse a word-sized section offset according to the DWARF format.
485 fn read_offset(&mut self, format
: Format
) -> Result
<Self::Offset
> {
486 self.read_word(format
)
489 /// Parse a section offset of the given size.
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
> {
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
)),
500 .and_then(Self::Offset
::from_u64
)