1#[cfg(feature = "read")]
2use alloc::borrow::Cow;
3use core::convert::TryInto;
4use core::fmt::Debug;
5use core::hash::Hash;
6use core::ops::{Add, AddAssign, Sub};
7
8use crate::common::Format;
9use crate::endianity::Endianity;
10use crate::leb128;
11use 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)]
19pub 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.
24pub 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
54impl 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
96impl 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
143impl 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"))]
191pub(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`. |
215pub 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