1 | #[cfg (feature = "read" )] |
2 | use alloc::borrow::Cow; |
3 | use core::fmt::Debug; |
4 | |
5 | use crate::common::Format; |
6 | use crate::read::{Reader, ReaderOffset, ReaderOffsetId, Result}; |
7 | |
8 | /// Trait for relocating addresses and offsets while reading a section. |
9 | pub 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)] |
23 | pub struct RelocateReader<R: Reader<Offset = usize>, T: Relocate<R::Offset>> { |
24 | section: R, |
25 | reader: R, |
26 | relocate: T, |
27 | } |
28 | |
29 | impl<R, T> RelocateReader<R, T> |
30 | where |
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: R = section.clone(); |
37 | Self { |
38 | section, |
39 | reader, |
40 | relocate, |
41 | } |
42 | } |
43 | } |
44 | |
45 | impl<R, T> Reader for RelocateReader<R, T> |
46 | where |
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 | } |
154 | |