/src/gimli/src/read/relocate.rs
Line | Count | Source (jump to first uncovered line) |
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 | 0 | pub fn new(section: R, relocate: T) -> Self { |
36 | 0 | let reader = section.clone(); |
37 | 0 | Self { |
38 | 0 | section, |
39 | 0 | reader, |
40 | 0 | relocate, |
41 | 0 | } |
42 | 0 | } |
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 | 0 | fn read_address(&mut self, address_size: u8) -> Result<u64> { |
54 | 0 | let offset = self.reader.offset_from(&self.section); |
55 | 0 | let value = self.reader.read_address(address_size)?; |
56 | 0 | self.relocate.relocate_address(offset, value) |
57 | 0 | } |
58 | | |
59 | 0 | fn read_offset(&mut self, format: Format) -> Result<R::Offset> { |
60 | 0 | let offset = self.reader.offset_from(&self.section); |
61 | 0 | let value = self.reader.read_offset(format)?; |
62 | 0 | self.relocate.relocate_offset(offset, value) |
63 | 0 | } |
64 | | |
65 | 0 | fn read_sized_offset(&mut self, size: u8) -> Result<R::Offset> { |
66 | 0 | let offset = self.reader.offset_from(&self.section); |
67 | 0 | let value = self.reader.read_sized_offset(size)?; |
68 | 0 | self.relocate.relocate_offset(offset, value) |
69 | 0 | } |
70 | | |
71 | | #[inline] |
72 | 0 | fn split(&mut self, len: Self::Offset) -> Result<Self> { |
73 | 0 | let mut other = self.clone(); |
74 | 0 | other.reader.truncate(len)?; |
75 | 0 | self.reader.skip(len)?; |
76 | 0 | Ok(other) |
77 | 0 | } |
78 | | |
79 | | // All remaining methods simply delegate to `self.reader`. |
80 | | |
81 | | #[inline] |
82 | 0 | fn endian(&self) -> Self::Endian { |
83 | 0 | self.reader.endian() |
84 | 0 | } |
85 | | |
86 | | #[inline] |
87 | 0 | fn len(&self) -> Self::Offset { |
88 | 0 | self.reader.len() |
89 | 0 | } |
90 | | |
91 | | #[inline] |
92 | 0 | fn empty(&mut self) { |
93 | 0 | self.reader.empty() |
94 | 0 | } |
95 | | |
96 | | #[inline] |
97 | 0 | fn truncate(&mut self, len: Self::Offset) -> Result<()> { |
98 | 0 | self.reader.truncate(len) |
99 | 0 | } |
100 | | |
101 | | #[inline] |
102 | 0 | fn offset_from(&self, base: &Self) -> Self::Offset { |
103 | 0 | self.reader.offset_from(&base.reader) |
104 | 0 | } |
105 | | |
106 | | #[inline] |
107 | 0 | fn offset_id(&self) -> ReaderOffsetId { |
108 | 0 | self.reader.offset_id() |
109 | 0 | } |
110 | | |
111 | | #[inline] |
112 | 0 | fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option<Self::Offset> { |
113 | 0 | self.reader.lookup_offset_id(id) |
114 | 0 | } |
115 | | |
116 | | #[inline] |
117 | 0 | fn find(&self, byte: u8) -> Result<Self::Offset> { |
118 | 0 | self.reader.find(byte) |
119 | 0 | } |
120 | | |
121 | | #[inline] |
122 | 0 | fn skip(&mut self, len: Self::Offset) -> Result<()> { |
123 | 0 | self.reader.skip(len) |
124 | 0 | } |
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 | 0 | fn to_slice(&self) -> Result<Cow<'_, [u8]>> { |
134 | 0 | self.reader.to_slice() |
135 | 0 | } |
136 | | |
137 | | #[cfg(feature = "read")] |
138 | | #[inline] |
139 | 0 | fn to_string(&self) -> Result<Cow<'_, str>> { |
140 | 0 | self.reader.to_string() |
141 | 0 | } |
142 | | |
143 | | #[cfg(feature = "read")] |
144 | | #[inline] |
145 | 0 | fn to_string_lossy(&self) -> Result<Cow<'_, str>> { |
146 | 0 | self.reader.to_string_lossy() |
147 | 0 | } |
148 | | |
149 | | #[inline] |
150 | 0 | fn read_slice(&mut self, buf: &mut [u8]) -> Result<()> { |
151 | 0 | self.reader.read_slice(buf) |
152 | 0 | } |
153 | | } |