gimli/read/
relocate.rs

1#[cfg(feature = "read")]
2use alloc::borrow::Cow;
3use core::fmt::Debug;
4
5use crate::common::Format;
6use crate::read::{Reader, ReaderOffset, ReaderOffsetId, Result};
7
8/// Trait for relocating addresses and offsets while reading a section.
9pub trait Relocate<T: ReaderOffset = usize> {
10    /// Relocate an address which was read from the given section offset.
11    fn relocate_address(&self, offset: T, value: u64) -> Result<u64>;
12
13    /// Relocate a value which was read from the given section offset.
14    fn relocate_offset(&self, offset: T, value: T) -> Result<T>;
15}
16
17/// A `Reader` which applies relocations to addresses and offsets.
18///
19/// This is useful for reading sections which contain relocations,
20/// such as those in a relocatable object file.
21/// It is generally not used for reading sections in an executable file.
22#[derive(Debug, Clone)]
23pub struct RelocateReader<R: Reader<Offset = usize>, T: Relocate<R::Offset>> {
24    section: R,
25    reader: R,
26    relocate: T,
27}
28
29impl<R, T> RelocateReader<R, T>
30where
31    R: Reader<Offset = usize>,
32    T: Relocate<R::Offset>,
33{
34    /// Create a new `RelocateReader` which applies relocations to the given section reader.
35    pub fn new(section: R, relocate: T) -> Self {
36        let reader = section.clone();
37        Self {
38            section,
39            reader,
40            relocate,
41        }
42    }
43}
44
45impl<R, T> Reader for RelocateReader<R, T>
46where
47    R: Reader<Offset = usize>,
48    T: Relocate<R::Offset> + Debug + Clone,
49{
50    type Endian = R::Endian;
51    type Offset = R::Offset;
52
53    fn read_address(&mut self, address_size: u8) -> Result<u64> {
54        let offset = self.reader.offset_from(&self.section);
55        let value = self.reader.read_address(address_size)?;
56        self.relocate.relocate_address(offset, value)
57    }
58
59    fn read_offset(&mut self, format: Format) -> Result<R::Offset> {
60        let offset = self.reader.offset_from(&self.section);
61        let value = self.reader.read_offset(format)?;
62        self.relocate.relocate_offset(offset, value)
63    }
64
65    fn read_sized_offset(&mut self, size: u8) -> Result<R::Offset> {
66        let offset = self.reader.offset_from(&self.section);
67        let value = self.reader.read_sized_offset(size)?;
68        self.relocate.relocate_offset(offset, value)
69    }
70
71    #[inline]
72    fn split(&mut self, len: Self::Offset) -> Result<Self> {
73        let mut other = self.clone();
74        other.reader.truncate(len)?;
75        self.reader.skip(len)?;
76        Ok(other)
77    }
78
79    // All remaining methods simply delegate to `self.reader`.
80
81    #[inline]
82    fn endian(&self) -> Self::Endian {
83        self.reader.endian()
84    }
85
86    #[inline]
87    fn len(&self) -> Self::Offset {
88        self.reader.len()
89    }
90
91    #[inline]
92    fn empty(&mut self) {
93        self.reader.empty()
94    }
95
96    #[inline]
97    fn truncate(&mut self, len: Self::Offset) -> Result<()> {
98        self.reader.truncate(len)
99    }
100
101    #[inline]
102    fn offset_from(&self, base: &Self) -> Self::Offset {
103        self.reader.offset_from(&base.reader)
104    }
105
106    #[inline]
107    fn offset_id(&self) -> ReaderOffsetId {
108        self.reader.offset_id()
109    }
110
111    #[inline]
112    fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option<Self::Offset> {
113        self.reader.lookup_offset_id(id)
114    }
115
116    #[inline]
117    fn find(&self, byte: u8) -> Result<Self::Offset> {
118        self.reader.find(byte)
119    }
120
121    #[inline]
122    fn skip(&mut self, len: Self::Offset) -> Result<()> {
123        self.reader.skip(len)
124    }
125
126    #[cfg(not(feature = "read"))]
127    fn cannot_implement() -> super::reader::seal_if_no_alloc::Sealed {
128        super::reader::seal_if_no_alloc::Sealed
129    }
130
131    #[cfg(feature = "read")]
132    #[inline]
133    fn to_slice(&self) -> Result<Cow<'_, [u8]>> {
134        self.reader.to_slice()
135    }
136
137    #[cfg(feature = "read")]
138    #[inline]
139    fn to_string(&self) -> Result<Cow<'_, str>> {
140        self.reader.to_string()
141    }
142
143    #[cfg(feature = "read")]
144    #[inline]
145    fn to_string_lossy(&self) -> Result<Cow<'_, str>> {
146        self.reader.to_string_lossy()
147    }
148
149    #[inline]
150    fn read_slice(&mut self, buf: &mut [u8]) -> Result<()> {
151        self.reader.read_slice(buf)
152    }
153}