Skip to main content

gimli/read/
relocate.rs

1#[cfg(feature = "read")]
2use alloc::borrow::Cow;
3use core::fmt;
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(Clone)]
23pub struct RelocateReader<R: Reader, 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,
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    /// Get a reference to the underlying section reader.
45    pub fn inner(&self) -> &R {
46        &self.reader
47    }
48}
49
50impl<R, T> fmt::Debug for RelocateReader<R, T>
51where
52    R: Reader,
53    T: Relocate<R::Offset>,
54{
55    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> core::result::Result<(), fmt::Error> {
56        fmt.debug_tuple("RelocationReader")
57            .field(&self.reader)
58            .finish()
59    }
60}
61
62impl<R, T> Reader for RelocateReader<R, T>
63where
64    R: Reader,
65    T: Relocate<R::Offset> + fmt::Debug + Clone,
66{
67    type Endian = R::Endian;
68    type Offset = R::Offset;
69
70    fn read_address(&mut self, address_size: u8) -> Result<u64> {
71        let offset = self.reader.offset_from(&self.section);
72        let value = self.reader.read_address(address_size)?;
73        self.relocate.relocate_address(offset, value)
74    }
75
76    fn read_offset(&mut self, format: Format) -> Result<R::Offset> {
77        let offset = self.reader.offset_from(&self.section);
78        let value = self.reader.read_offset(format)?;
79        self.relocate.relocate_offset(offset, value)
80    }
81
82    fn read_sized_offset(&mut self, size: u8) -> Result<R::Offset> {
83        let offset = self.reader.offset_from(&self.section);
84        let value = self.reader.read_sized_offset(size)?;
85        self.relocate.relocate_offset(offset, value)
86    }
87
88    #[inline]
89    fn split(&mut self, len: Self::Offset) -> Result<Self> {
90        let mut other = self.clone();
91        other.reader.truncate(len)?;
92        self.reader.skip(len)?;
93        Ok(other)
94    }
95
96    // All remaining methods simply delegate to `self.reader`.
97
98    #[inline]
99    fn endian(&self) -> Self::Endian {
100        self.reader.endian()
101    }
102
103    #[inline]
104    fn len(&self) -> Self::Offset {
105        self.reader.len()
106    }
107
108    #[inline]
109    fn empty(&mut self) {
110        self.reader.empty()
111    }
112
113    #[inline]
114    fn truncate(&mut self, len: Self::Offset) -> Result<()> {
115        self.reader.truncate(len)
116    }
117
118    #[inline]
119    fn offset_from(&self, base: &Self) -> Self::Offset {
120        self.reader.offset_from(&base.reader)
121    }
122
123    #[inline]
124    fn offset_id(&self) -> ReaderOffsetId {
125        self.reader.offset_id()
126    }
127
128    #[inline]
129    fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option<Self::Offset> {
130        self.reader.lookup_offset_id(id)
131    }
132
133    #[inline]
134    fn find(&self, byte: u8) -> Result<Self::Offset> {
135        self.reader.find(byte)
136    }
137
138    #[inline]
139    fn skip(&mut self, len: Self::Offset) -> Result<()> {
140        self.reader.skip(len)
141    }
142
143    #[cfg(not(feature = "read"))]
144    fn cannot_implement() -> super::reader::seal_if_no_alloc::Sealed {
145        super::reader::seal_if_no_alloc::Sealed
146    }
147
148    #[cfg(feature = "read")]
149    #[inline]
150    fn to_slice(&self) -> Result<Cow<'_, [u8]>> {
151        self.reader.to_slice()
152    }
153
154    #[cfg(feature = "read")]
155    #[inline]
156    fn to_string(&self) -> Result<Cow<'_, str>> {
157        self.reader.to_string()
158    }
159
160    #[cfg(feature = "read")]
161    #[inline]
162    fn to_string_lossy(&self) -> Result<Cow<'_, str>> {
163        self.reader.to_string_lossy()
164    }
165
166    #[inline]
167    fn read_slice(&mut self, buf: &mut [u8]) -> Result<()> {
168        self.reader.read_slice(buf)
169    }
170}