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#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub struct ReaderOffsetId(pub u64);
20
21pub trait ReaderOffset:
25 Debug + Copy + Eq + Ord + Hash + Add<Output = Self> + AddAssign + Sub<Output = Self>
26{
27 fn from_u8(offset: u8) -> Self;
29
30 fn from_u16(offset: u16) -> Self;
32
33 fn from_i16(offset: i16) -> Self;
35
36 fn from_u32(offset: u32) -> Self;
38
39 fn from_u64(offset: u64) -> Result<Self>;
43
44 fn into_u64(self) -> u64;
46
47 fn wrapping_add(self, other: Self) -> Self;
49
50 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
190pub(crate) trait ReaderAddress: Sized {
195 fn add_sized(self, length: u64, size: u8) -> Result<Self>;
199
200 fn wrapping_add_sized(self, length: u64, size: u8) -> Self;
205
206 fn zeros() -> Self;
208
209 fn ones_sized(size: u8) -> Self;
211
212 fn min_tombstone(size: u8) -> Self {
228 Self::zeros().wrapping_add_sized(-2i64 as u64, size)
229 }
230}
231
232impl ReaderAddress for u64 {
233 #[inline]
234 fn add_sized(self, length: u64, size: u8) -> Result<Self> {
235 let address = self.checked_add(length).ok_or(Error::AddressOverflow)?;
236 let mask = Self::ones_sized(size);
237 if address & !mask != 0 {
238 return Err(Error::AddressOverflow);
239 }
240 Ok(address)
241 }
242
243 #[inline]
244 fn wrapping_add_sized(self, length: u64, size: u8) -> Self {
245 let mask = Self::ones_sized(size);
246 self.wrapping_add(length) & mask
247 }
248
249 #[inline]
250 fn zeros() -> Self {
251 0
252 }
253
254 #[inline]
255 fn ones_sized(size: u8) -> Self {
256 !0 >> (64 - size * 8)
257 }
258}
259
260#[cfg(not(feature = "read"))]
261pub(crate) mod seal_if_no_alloc {
262 #[derive(Debug)]
263 pub struct Sealed;
264}
265
266pub trait Reader: Debug + Clone {
286 type Endian: Endianity;
288
289 type Offset: ReaderOffset;
291
292 fn endian(&self) -> Self::Endian;
294
295 fn len(&self) -> Self::Offset;
297
298 fn empty(&mut self);
300
301 fn truncate(&mut self, len: Self::Offset) -> Result<()>;
303
304 fn offset_from(&self, base: &Self) -> Self::Offset;
310
311 fn offset_id(&self) -> ReaderOffsetId;
313
314 fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option<Self::Offset>;
317
318 fn find(&self, byte: u8) -> Result<Self::Offset>;
321
322 fn skip(&mut self, len: Self::Offset) -> Result<()>;
324
325 fn split(&mut self, len: Self::Offset) -> Result<Self>;
330
331 #[cfg(not(feature = "read"))]
338 fn cannot_implement() -> seal_if_no_alloc::Sealed;
339
340 #[cfg(feature = "read")]
347 fn to_slice(&self) -> Result<Cow<'_, [u8]>>;
348
349 #[cfg(feature = "read")]
358 fn to_string(&self) -> Result<Cow<'_, str>>;
359
360 #[cfg(feature = "read")]
367 fn to_string_lossy(&self) -> Result<Cow<'_, str>>;
368
369 fn read_slice(&mut self, buf: &mut [u8]) -> Result<()>;
371
372 #[inline]
374 fn read_u8_array<A>(&mut self) -> Result<A>
375 where
376 A: Sized + Default + AsMut<[u8]>,
377 {
378 let mut val = Default::default();
379 self.read_slice(<A as AsMut<[u8]>>::as_mut(&mut val))?;
380 Ok(val)
381 }
382
383 #[inline]
385 fn is_empty(&self) -> bool {
386 self.len() == Self::Offset::from_u8(0)
387 }
388
389 #[inline]
391 fn read_u8(&mut self) -> Result<u8> {
392 let a: [u8; 1] = self.read_u8_array()?;
393 Ok(a[0])
394 }
395
396 #[inline]
398 fn read_i8(&mut self) -> Result<i8> {
399 let a: [u8; 1] = self.read_u8_array()?;
400 Ok(a[0] as i8)
401 }
402
403 #[inline]
405 fn read_u16(&mut self) -> Result<u16> {
406 let a: [u8; 2] = self.read_u8_array()?;
407 Ok(self.endian().read_u16(&a))
408 }
409
410 #[inline]
412 fn read_i16(&mut self) -> Result<i16> {
413 let a: [u8; 2] = self.read_u8_array()?;
414 Ok(self.endian().read_i16(&a))
415 }
416
417 #[inline]
419 fn read_u32(&mut self) -> Result<u32> {
420 let a: [u8; 4] = self.read_u8_array()?;
421 Ok(self.endian().read_u32(&a))
422 }
423
424 #[inline]
426 fn read_i32(&mut self) -> Result<i32> {
427 let a: [u8; 4] = self.read_u8_array()?;
428 Ok(self.endian().read_i32(&a))
429 }
430
431 #[inline]
433 fn read_u64(&mut self) -> Result<u64> {
434 let a: [u8; 8] = self.read_u8_array()?;
435 Ok(self.endian().read_u64(&a))
436 }
437
438 #[inline]
440 fn read_i64(&mut self) -> Result<i64> {
441 let a: [u8; 8] = self.read_u8_array()?;
442 Ok(self.endian().read_i64(&a))
443 }
444
445 #[inline]
447 fn read_f32(&mut self) -> Result<f32> {
448 let a: [u8; 4] = self.read_u8_array()?;
449 Ok(self.endian().read_f32(&a))
450 }
451
452 #[inline]
454 fn read_f64(&mut self) -> Result<f64> {
455 let a: [u8; 8] = self.read_u8_array()?;
456 Ok(self.endian().read_f64(&a))
457 }
458
459 #[inline]
465 fn read_uint(&mut self, n: usize) -> Result<u64> {
466 let mut buf = [0; 8];
467 self.read_slice(&mut buf[..n])?;
468 Ok(self.endian().read_uint(&buf[..n]))
469 }
470
471 fn read_null_terminated_slice(&mut self) -> Result<Self> {
473 let idx = self.find(0)?;
474 let val = self.split(idx)?;
475 self.skip(Self::Offset::from_u8(1))?;
476 Ok(val)
477 }
478
479 fn skip_leb128(&mut self) -> Result<()> {
481 leb128::read::skip(self)
482 }
483
484 fn read_uleb128(&mut self) -> Result<u64> {
486 leb128::read::unsigned(self)
487 }
488
489 fn read_uleb128_u32(&mut self) -> Result<u32> {
491 leb128::read::unsigned(self)?
492 .try_into()
493 .map_err(|_| Error::BadUnsignedLeb128)
494 }
495
496 fn read_uleb128_u16(&mut self) -> Result<u16> {
498 leb128::read::u16(self)
499 }
500
501 fn read_sleb128(&mut self) -> Result<i64> {
503 leb128::read::signed(self)
504 }
505
506 fn read_initial_length(&mut self) -> Result<(Self::Offset, Format)> {
511 const MAX_DWARF_32_UNIT_LENGTH: u32 = 0xffff_fff0;
512 const DWARF_64_INITIAL_UNIT_LENGTH: u32 = 0xffff_ffff;
513
514 let val = self.read_u32()?;
515 if val < MAX_DWARF_32_UNIT_LENGTH {
516 Ok((Self::Offset::from_u32(val), Format::Dwarf32))
517 } else if val == DWARF_64_INITIAL_UNIT_LENGTH {
518 let val = self.read_u64().and_then(Self::Offset::from_u64)?;
519 Ok((val, Format::Dwarf64))
520 } else {
521 Err(Error::UnknownReservedLength)
522 }
523 }
524
525 fn read_address_size(&mut self) -> Result<u8> {
527 let size = self.read_u8()?;
528 match size {
529 1 | 2 | 4 | 8 => Ok(size),
530 _ => Err(Error::UnsupportedAddressSize(size)),
531 }
532 }
533
534 fn read_address(&mut self, address_size: u8) -> Result<u64> {
536 match address_size {
537 1 => self.read_u8().map(u64::from),
538 2 => self.read_u16().map(u64::from),
539 4 => self.read_u32().map(u64::from),
540 8 => self.read_u64(),
541 otherwise => Err(Error::UnsupportedAddressSize(otherwise)),
542 }
543 }
544
545 fn read_word(&mut self, format: Format) -> Result<Self::Offset> {
550 match format {
551 Format::Dwarf32 => self.read_u32().map(Self::Offset::from_u32),
552 Format::Dwarf64 => self.read_u64().and_then(Self::Offset::from_u64),
553 }
554 }
555
556 #[inline]
558 fn read_length(&mut self, format: Format) -> Result<Self::Offset> {
559 self.read_word(format)
560 }
561
562 #[inline]
564 fn read_offset(&mut self, format: Format) -> Result<Self::Offset> {
565 self.read_word(format)
566 }
567
568 fn read_sized_offset(&mut self, size: u8) -> Result<Self::Offset> {
572 match size {
573 1 => self.read_u8().map(u64::from),
574 2 => self.read_u16().map(u64::from),
575 4 => self.read_u32().map(u64::from),
576 8 => self.read_u64(),
577 otherwise => Err(Error::UnsupportedOffsetSize(otherwise)),
578 }
579 .and_then(Self::Offset::from_u64)
580 }
581}
582
583#[cfg(test)]
584mod test {
585 use super::*;
586
587 #[test]
588 fn test_min_tombstone() {
589 assert_eq!(u64::min_tombstone(1), 0xfe);
590 assert_eq!(u64::min_tombstone(2), 0xfffe);
591 assert_eq!(u64::min_tombstone(4), 0xffff_fffe);
592 assert_eq!(u64::min_tombstone(8), 0xffff_ffff_ffff_fffe);
593 }
594}