1use std::prelude::v1::*;
33
34use std::{cmp, fmt, iter, mem, slice};
35
36use crate::image::{IMAGE_BASE_RELOCATION, IMAGE_REL_BASED_ABSOLUTE};
37use crate::util::{extend_in_place, AlignTo};
38use crate::{Error, Result};
39
40#[derive(Copy, Clone)]
44pub struct BaseRelocs<'a> {
45 relocs: &'a [u8],
46}
47impl<'a> BaseRelocs<'a> {
48 pub(crate) unsafe fn new(relocs: &'a [u8]) -> BaseRelocs<'a> {
49 debug_assert!(relocs.as_ptr().aligned_to(4)); BaseRelocs { relocs }
51 }
52 pub fn parse(relocs: &'a [u8]) -> Result<BaseRelocs<'a>> {
56 if !(cfg!(feature = "unsafe_alignment") || relocs.as_ptr().aligned_to(4)) { return Err(Error::Misaligned);
58 }
59 Ok(BaseRelocs { relocs })
60 }
61 pub fn image(&self) -> &'a [u8] {
63 self.relocs
64 }
65 pub fn iter_blocks(&self) -> IterBlocks<'a> {
67 IterBlocks { data: self.relocs }
68 }
69 pub fn for_each<F: FnMut(u32, u8)>(&self, mut f: F) {
71 self.fold((), |(), rva, ty| f(rva, ty))
72 }
73 pub fn fold<T, F>(&self, init: T, mut f: F) -> T where F: FnMut(T, u32, u8) -> T {
75 let mut accum = init;
76 for block in self.iter_blocks() {
77 for word in block.words() {
78 let ty = block.type_of(word);
79 if ty != IMAGE_REL_BASED_ABSOLUTE {
80 let rva = block.rva_of(word);
81 accum = f(accum, rva, ty);
82 }
83 }
84 }
85 accum
86 }
87}
88impl<'a> fmt::Debug for BaseRelocs<'a> {
89 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
90 f.debug_struct("BaseRelocs").finish()
91 }
92}
93
94#[derive(Clone)]
98pub struct IterBlocks<'a> {
99 data: &'a [u8],
100}
101impl<'a> IterBlocks<'a> {
102 fn peek(&self) -> Option<Block<'a>> {
103 if mem::size_of_val(self.data) >= mem::size_of::<IMAGE_BASE_RELOCATION>() { Some(unsafe {
105 let image_p = self.data.as_ptr() as *const IMAGE_BASE_RELOCATION;
107 let image = &*image_p;
108 let len = cmp::min(image.SizeOfBlock as usize, self.data.len()).saturating_sub(mem::size_of::<IMAGE_BASE_RELOCATION>()) / 2;
110 let words = slice::from_raw_parts(image_p.offset(1) as *const u16, len);
111 Block { image, words }
112 })
113 }
114 else {
115 None
116 }
117 }
118}
119impl<'a> Iterator for IterBlocks<'a> {
120 type Item = Block<'a>;
121 fn next(&mut self) -> Option<Block<'a>> {
122 if let Some(block) = self.peek() {
123 let block_size = block.image.SizeOfBlock;
124 let block_size = cmp::max(block_size, mem::size_of::<IMAGE_BASE_RELOCATION>() as u32);
126 let block_size = block_size.align_to(4); let block_size = cmp::min(block_size as usize, self.data.len());
130 self.data = &self.data[block_size..];
131 Some(block)
132 }
133 else {
134 None
135 }
136 }
137}
138impl<'a> iter::FusedIterator for IterBlocks<'a> {}
139
140#[derive(Copy, Clone)]
144pub struct Block<'a> {
145 image: &'a IMAGE_BASE_RELOCATION,
146 words: &'a [u16],
147}
148impl<'a> Block<'a> {
149 pub fn image(&self) -> &'a IMAGE_BASE_RELOCATION {
151 self.image
152 }
153 pub fn words(&self) -> &'a [u16] {
155 self.words
156 }
157 pub fn rva_of(&self, word: &u16) -> u32 {
159 let offset = (word & 0x0fff) as u32;
160 self.image.VirtualAddress.wrapping_add(offset)
161 }
162 pub fn type_of(&self, word: &u16) -> u8 {
164 (word >> 12) as u8
165 }
166}
167impl<'a> fmt::Debug for Block<'a> {
168 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
169 f.debug_struct("Block")
170 .field("virtual_address", &format_args!("{:#x?}", self.image.VirtualAddress))
171 .field("words.len", &self.words().len())
172 .finish()
173 }
174}
175
176#[cfg(feature = "serde")]
186mod serde {
187 use crate::util::serde_helper::*;
188 use super::BaseRelocs;
189
190 impl<'a> Serialize for BaseRelocs<'a> {
191 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
192 let mut state = serializer.serialize_struct("BaseRelocs", 2)?;
193 let mut rvas = Vec::new();
194 let mut types = Vec::new();
195 self.for_each(|rva, ty| {
196 rvas.push(rva);
197 types.push(ty);
198 });
199 state.serialize_field("rvas", &*rvas)?;
200 state.serialize_field("types", &*types)?;
201 state.end()
202 }
203 }
204}
205
206fn encode_type_offset(base: u32, rva: u32, ty: u8) -> u16 {
209 (((rva - base) | (ty as u32) << 12) & 0xffff) as u16
210}
211
212pub fn build(mut rvas: &[u32], mut types: &[u8]) -> Vec<u8> {
216 assert_eq!(rvas.len(), types.len());
217
218 let mut result = Vec::<u8>::new();
219 while rvas.len() > 0 {
220 let start = rvas[0] & !0x0fff;
222 let end = start + 0x0fff;
223
224 let mut n = 0;
226 while n < rvas.len() && rvas[n] >= start && rvas[n] < end {
227 n += 1;
228 }
229
230 let size = (8 + 2 * n).align_to(4);
232
233 unsafe {
234 extend_in_place(&mut result, size, |bytes| {
235 let block_ptr = bytes.as_mut_ptr() as *mut IMAGE_BASE_RELOCATION;
237 (*block_ptr).VirtualAddress = start;
238 (*block_ptr).SizeOfBlock = size as u32;
239 let words = slice::from_raw_parts_mut(block_ptr.offset(1) as *mut u16, n.align_to(2));
241 for i in 0..n {
242 let rva = *rvas.get_unchecked(i);
243 let ty = *types.get_unchecked(i);
244 words[i] = encode_type_offset(start, rva, ty);
245 }
246 if n < words.len() {
248 words[n] = 0;
249 }
250 });
251 }
252
253 rvas = &rvas[n..];
254 types = &types[n..];
255 }
256 result
257}
258
259#[cfg(windows)]
260#[test]
261fn test_build_self() {
262 if crate::image::IMAGE_BASE_PANICS {
263 return;
264 }
265 use crate::pe::*;
266 let view = unsafe { PeView::new() };
267 if let Ok(base_relocs) = view.base_relocs() {
268 let mut rvas = Vec::new();
269 let mut types = Vec::new();
270 base_relocs.for_each(|rva, ty| {
271 rvas.push(rva);
272 types.push(ty);
273 });
274 let rebuild = build(&rvas, &types);
275 assert_eq!(rebuild, base_relocs.image());
276 }
277}