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 | /// A trait for addresses within a DWARF section. |
191 | /// |
192 | /// Currently this is a simple extension trait for `u64`, but it may be expanded |
193 | /// in the future to support user-defined address types. |
194 | pub(crate) trait ReaderAddress: Sized { |
195 | /// Add a length to an address of the given size. |
196 | /// |
197 | /// Returns an error for overflow. |
198 | fn add_sized(self, length: u64, size: u8) -> Result<Self>; |
199 | |
200 | /// Add a length to an address of the given size. |
201 | /// |
202 | /// Wraps the result to the size of the address to allow for the possibility |
203 | /// that the length is a negative value. |
204 | fn wrapping_add_sized(self, length: u64, size: u8) -> Self; |
205 | |
206 | /// The all-ones value of an address of the given size. |
207 | fn ones_sized(size: u8) -> Self; |
208 | } |
209 | |
210 | impl ReaderAddress for u64 { |
211 | #[inline ] |
212 | fn add_sized(self, length: u64, size: u8) -> Result<Self> { |
213 | let address: u64 = self.checked_add(length).ok_or(err:Error::AddressOverflow)?; |
214 | let mask: u64 = Self::ones_sized(size); |
215 | if address & !mask != 0 { |
216 | return Err(Error::AddressOverflow); |
217 | } |
218 | Ok(address) |
219 | } |
220 | |
221 | #[inline ] |
222 | fn wrapping_add_sized(self, length: u64, size: u8) -> Self { |
223 | let mask: u64 = Self::ones_sized(size); |
224 | self.wrapping_add(length) & mask |
225 | } |
226 | |
227 | #[inline ] |
228 | fn ones_sized(size: u8) -> Self { |
229 | !0 >> (64 - size * 8) |
230 | } |
231 | } |
232 | |
233 | #[cfg (not(feature = "read" ))] |
234 | pub(crate) mod seal_if_no_alloc { |
235 | #[derive (Debug)] |
236 | pub struct Sealed; |
237 | } |
238 | |
239 | /// A trait for reading the data from a DWARF section. |
240 | /// |
241 | /// All read operations advance the section offset of the reader |
242 | /// unless specified otherwise. |
243 | /// |
244 | /// ## Choosing a `Reader` Implementation |
245 | /// |
246 | /// `gimli` comes with a few different `Reader` implementations and lets you |
247 | /// choose the one that is right for your use case. A `Reader` is essentially a |
248 | /// view into the raw bytes that make up some DWARF, but this view might borrow |
249 | /// the underlying data or use reference counting ownership, and it might be |
250 | /// thread safe or not. |
251 | /// |
252 | /// | Implementation | Ownership | Thread Safe | Notes | |
253 | /// |:------------------|:------------------|:------------|:------| |
254 | /// | [`EndianSlice`](./struct.EndianSlice.html) | Borrowed | Yes | Fastest, but requires that all of your code work with borrows. | |
255 | /// | [`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. | |
256 | /// | [`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. | |
257 | /// | [`EndianReader<T>`](./struct.EndianReader.html) | Same as `T` | Same as `T` | Escape hatch for easily defining your own type of `Reader`. | |
258 | pub trait Reader: Debug + Clone { |
259 | /// The endianity of bytes that are read. |
260 | type Endian: Endianity; |
261 | |
262 | /// The type used for offsets and lengths. |
263 | type Offset: ReaderOffset; |
264 | |
265 | /// Return the endianity of bytes that are read. |
266 | fn endian(&self) -> Self::Endian; |
267 | |
268 | /// Return the number of bytes remaining. |
269 | fn len(&self) -> Self::Offset; |
270 | |
271 | /// Set the number of bytes remaining to zero. |
272 | fn empty(&mut self); |
273 | |
274 | /// Set the number of bytes remaining to the specified length. |
275 | fn truncate(&mut self, len: Self::Offset) -> Result<()>; |
276 | |
277 | /// Return the offset of this reader's data relative to the start of |
278 | /// the given base reader's data. |
279 | /// |
280 | /// May panic if this reader's data is not contained within the given |
281 | /// base reader's data. |
282 | fn offset_from(&self, base: &Self) -> Self::Offset; |
283 | |
284 | /// Return an identifier for the current reader offset. |
285 | fn offset_id(&self) -> ReaderOffsetId; |
286 | |
287 | /// Return the offset corresponding to the given `id` if |
288 | /// it is associated with this reader. |
289 | fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option<Self::Offset>; |
290 | |
291 | /// Find the index of the first occurrence of the given byte. |
292 | /// The offset of the reader is not changed. |
293 | fn find(&self, byte: u8) -> Result<Self::Offset>; |
294 | |
295 | /// Discard the specified number of bytes. |
296 | fn skip(&mut self, len: Self::Offset) -> Result<()>; |
297 | |
298 | /// Split a reader in two. |
299 | /// |
300 | /// A new reader is returned that can be used to read the next |
301 | /// `len` bytes, and `self` is advanced so that it reads the remainder. |
302 | fn split(&mut self, len: Self::Offset) -> Result<Self>; |
303 | |
304 | /// This trait cannot be implemented if "read" feature is not enabled. |
305 | /// |
306 | /// `Reader` trait has a few methods that depend on `alloc` crate. |
307 | /// Disallowing `Reader` trait implementation prevents a crate that only depends on |
308 | /// "read-core" from being broken if another crate depending on `gimli` enables |
309 | /// "read" feature. |
310 | #[cfg (not(feature = "read" ))] |
311 | fn cannot_implement() -> seal_if_no_alloc::Sealed; |
312 | |
313 | /// Return all remaining data as a clone-on-write slice. |
314 | /// |
315 | /// The slice will be borrowed where possible, but some readers may |
316 | /// always return an owned vector. |
317 | /// |
318 | /// Does not advance the reader. |
319 | #[cfg (feature = "read" )] |
320 | fn to_slice(&self) -> Result<Cow<'_, [u8]>>; |
321 | |
322 | /// Convert all remaining data to a clone-on-write string. |
323 | /// |
324 | /// The string will be borrowed where possible, but some readers may |
325 | /// always return an owned string. |
326 | /// |
327 | /// Does not advance the reader. |
328 | /// |
329 | /// Returns an error if the data contains invalid characters. |
330 | #[cfg (feature = "read" )] |
331 | fn to_string(&self) -> Result<Cow<'_, str>>; |
332 | |
333 | /// Convert all remaining data to a clone-on-write string, including invalid characters. |
334 | /// |
335 | /// The string will be borrowed where possible, but some readers may |
336 | /// always return an owned string. |
337 | /// |
338 | /// Does not advance the reader. |
339 | #[cfg (feature = "read" )] |
340 | fn to_string_lossy(&self) -> Result<Cow<'_, str>>; |
341 | |
342 | /// Read exactly `buf.len()` bytes into `buf`. |
343 | fn read_slice(&mut self, buf: &mut [u8]) -> Result<()>; |
344 | |
345 | /// Read a u8 array. |
346 | #[inline ] |
347 | fn read_u8_array<A>(&mut self) -> Result<A> |
348 | where |
349 | A: Sized + Default + AsMut<[u8]>, |
350 | { |
351 | let mut val = Default::default(); |
352 | self.read_slice(<A as AsMut<[u8]>>::as_mut(&mut val))?; |
353 | Ok(val) |
354 | } |
355 | |
356 | /// Return true if the number of bytes remaining is zero. |
357 | #[inline ] |
358 | fn is_empty(&self) -> bool { |
359 | self.len() == Self::Offset::from_u8(0) |
360 | } |
361 | |
362 | /// Read a u8. |
363 | #[inline ] |
364 | fn read_u8(&mut self) -> Result<u8> { |
365 | let a: [u8; 1] = self.read_u8_array()?; |
366 | Ok(a[0]) |
367 | } |
368 | |
369 | /// Read an i8. |
370 | #[inline ] |
371 | fn read_i8(&mut self) -> Result<i8> { |
372 | let a: [u8; 1] = self.read_u8_array()?; |
373 | Ok(a[0] as i8) |
374 | } |
375 | |
376 | /// Read a u16. |
377 | #[inline ] |
378 | fn read_u16(&mut self) -> Result<u16> { |
379 | let a: [u8; 2] = self.read_u8_array()?; |
380 | Ok(self.endian().read_u16(&a)) |
381 | } |
382 | |
383 | /// Read an i16. |
384 | #[inline ] |
385 | fn read_i16(&mut self) -> Result<i16> { |
386 | let a: [u8; 2] = self.read_u8_array()?; |
387 | Ok(self.endian().read_i16(&a)) |
388 | } |
389 | |
390 | /// Read a u32. |
391 | #[inline ] |
392 | fn read_u32(&mut self) -> Result<u32> { |
393 | let a: [u8; 4] = self.read_u8_array()?; |
394 | Ok(self.endian().read_u32(&a)) |
395 | } |
396 | |
397 | /// Read an i32. |
398 | #[inline ] |
399 | fn read_i32(&mut self) -> Result<i32> { |
400 | let a: [u8; 4] = self.read_u8_array()?; |
401 | Ok(self.endian().read_i32(&a)) |
402 | } |
403 | |
404 | /// Read a u64. |
405 | #[inline ] |
406 | fn read_u64(&mut self) -> Result<u64> { |
407 | let a: [u8; 8] = self.read_u8_array()?; |
408 | Ok(self.endian().read_u64(&a)) |
409 | } |
410 | |
411 | /// Read an i64. |
412 | #[inline ] |
413 | fn read_i64(&mut self) -> Result<i64> { |
414 | let a: [u8; 8] = self.read_u8_array()?; |
415 | Ok(self.endian().read_i64(&a)) |
416 | } |
417 | |
418 | /// Read a f32. |
419 | #[inline ] |
420 | fn read_f32(&mut self) -> Result<f32> { |
421 | let a: [u8; 4] = self.read_u8_array()?; |
422 | Ok(self.endian().read_f32(&a)) |
423 | } |
424 | |
425 | /// Read a f64. |
426 | #[inline ] |
427 | fn read_f64(&mut self) -> Result<f64> { |
428 | let a: [u8; 8] = self.read_u8_array()?; |
429 | Ok(self.endian().read_f64(&a)) |
430 | } |
431 | |
432 | /// Read an unsigned n-bytes integer u64. |
433 | /// |
434 | /// # Panics |
435 | /// |
436 | /// Panics when nbytes < 1 or nbytes > 8 |
437 | #[inline ] |
438 | fn read_uint(&mut self, n: usize) -> Result<u64> { |
439 | let mut buf = [0; 8]; |
440 | self.read_slice(&mut buf[..n])?; |
441 | Ok(self.endian().read_uint(&buf[..n])) |
442 | } |
443 | |
444 | /// Read a null-terminated slice, and return it (excluding the null). |
445 | fn read_null_terminated_slice(&mut self) -> Result<Self> { |
446 | let idx = self.find(0)?; |
447 | let val = self.split(idx)?; |
448 | self.skip(Self::Offset::from_u8(1))?; |
449 | Ok(val) |
450 | } |
451 | |
452 | /// Skip a LEB128 encoded integer. |
453 | fn skip_leb128(&mut self) -> Result<()> { |
454 | leb128::read::skip(self) |
455 | } |
456 | |
457 | /// Read an unsigned LEB128 encoded integer. |
458 | fn read_uleb128(&mut self) -> Result<u64> { |
459 | leb128::read::unsigned(self) |
460 | } |
461 | |
462 | /// Read an unsigned LEB128 encoded u32. |
463 | fn read_uleb128_u32(&mut self) -> Result<u32> { |
464 | leb128::read::unsigned(self)? |
465 | .try_into() |
466 | .map_err(|_| Error::BadUnsignedLeb128) |
467 | } |
468 | |
469 | /// Read an unsigned LEB128 encoded u16. |
470 | fn read_uleb128_u16(&mut self) -> Result<u16> { |
471 | leb128::read::u16(self) |
472 | } |
473 | |
474 | /// Read a signed LEB128 encoded integer. |
475 | fn read_sleb128(&mut self) -> Result<i64> { |
476 | leb128::read::signed(self) |
477 | } |
478 | |
479 | /// Read an initial length field. |
480 | /// |
481 | /// This field is encoded as either a 32-bit length or |
482 | /// a 64-bit length, and the returned `Format` indicates which. |
483 | fn read_initial_length(&mut self) -> Result<(Self::Offset, Format)> { |
484 | const MAX_DWARF_32_UNIT_LENGTH: u32 = 0xffff_fff0; |
485 | const DWARF_64_INITIAL_UNIT_LENGTH: u32 = 0xffff_ffff; |
486 | |
487 | let val = self.read_u32()?; |
488 | if val < MAX_DWARF_32_UNIT_LENGTH { |
489 | Ok((Self::Offset::from_u32(val), Format::Dwarf32)) |
490 | } else if val == DWARF_64_INITIAL_UNIT_LENGTH { |
491 | let val = self.read_u64().and_then(Self::Offset::from_u64)?; |
492 | Ok((val, Format::Dwarf64)) |
493 | } else { |
494 | Err(Error::UnknownReservedLength) |
495 | } |
496 | } |
497 | |
498 | /// Read a byte and validate it as an address size. |
499 | fn read_address_size(&mut self) -> Result<u8> { |
500 | let size = self.read_u8()?; |
501 | match size { |
502 | 1 | 2 | 4 | 8 => Ok(size), |
503 | _ => Err(Error::UnsupportedAddressSize(size)), |
504 | } |
505 | } |
506 | |
507 | /// Read an address-sized integer, and return it as a `u64`. |
508 | fn read_address(&mut self, address_size: u8) -> Result<u64> { |
509 | match address_size { |
510 | 1 => self.read_u8().map(u64::from), |
511 | 2 => self.read_u16().map(u64::from), |
512 | 4 => self.read_u32().map(u64::from), |
513 | 8 => self.read_u64(), |
514 | otherwise => Err(Error::UnsupportedAddressSize(otherwise)), |
515 | } |
516 | } |
517 | |
518 | /// Parse a word-sized integer according to the DWARF format. |
519 | /// |
520 | /// These are always used to encode section offsets or lengths, |
521 | /// and so have a type of `Self::Offset`. |
522 | fn read_word(&mut self, format: Format) -> Result<Self::Offset> { |
523 | match format { |
524 | Format::Dwarf32 => self.read_u32().map(Self::Offset::from_u32), |
525 | Format::Dwarf64 => self.read_u64().and_then(Self::Offset::from_u64), |
526 | } |
527 | } |
528 | |
529 | /// Parse a word-sized section length according to the DWARF format. |
530 | #[inline ] |
531 | fn read_length(&mut self, format: Format) -> Result<Self::Offset> { |
532 | self.read_word(format) |
533 | } |
534 | |
535 | /// Parse a word-sized section offset according to the DWARF format. |
536 | #[inline ] |
537 | fn read_offset(&mut self, format: Format) -> Result<Self::Offset> { |
538 | self.read_word(format) |
539 | } |
540 | |
541 | /// Parse a section offset of the given size. |
542 | /// |
543 | /// This is used for `DW_FORM_ref_addr` values in DWARF version 2. |
544 | fn read_sized_offset(&mut self, size: u8) -> Result<Self::Offset> { |
545 | match size { |
546 | 1 => self.read_u8().map(u64::from), |
547 | 2 => self.read_u16().map(u64::from), |
548 | 4 => self.read_u32().map(u64::from), |
549 | 8 => self.read_u64(), |
550 | otherwise => Err(Error::UnsupportedOffsetSize(otherwise)), |
551 | } |
552 | .and_then(Self::Offset::from_u64) |
553 | } |
554 | } |
555 | |