object/read/pe/
relocation.rs
1use core::slice;
2
3use crate::endian::{LittleEndian as LE, U16};
4use crate::pe;
5use crate::read::{Bytes, Error, ReadError, Result};
6
7#[derive(Debug, Default, Clone, Copy)]
11pub struct RelocationBlockIterator<'data> {
12 data: Bytes<'data>,
13}
14
15impl<'data> RelocationBlockIterator<'data> {
16 pub fn new(data: &'data [u8]) -> Self {
18 RelocationBlockIterator { data: Bytes(data) }
19 }
20
21 pub fn next(&mut self) -> Result<Option<RelocationIterator<'data>>> {
23 if self.data.is_empty() {
24 return Ok(None);
25 }
26
27 let result = self.parse().map(Some);
28 if result.is_err() {
29 self.data = Bytes(&[]);
30 }
31 result
32 }
33
34 fn parse(&mut self) -> Result<RelocationIterator<'data>> {
35 let header = self
36 .data
37 .read::<pe::ImageBaseRelocation>()
38 .read_error("Invalid PE reloc section size")?;
39 let virtual_address = header.virtual_address.get(LE);
40 let size = header.size_of_block.get(LE);
41 if size <= 8 || size & 3 != 0 {
42 return Err(Error("Invalid PE reloc block size"));
43 }
44 let count = (size - 8) / 2;
45 let relocs = self
46 .data
47 .read_slice::<U16<LE>>(count as usize)
48 .read_error("Invalid PE reloc block size")?
49 .iter();
50 Ok(RelocationIterator {
51 virtual_address,
52 size,
53 relocs,
54 })
55 }
56}
57
58impl<'data> Iterator for RelocationBlockIterator<'data> {
59 type Item = Result<RelocationIterator<'data>>;
60
61 fn next(&mut self) -> Option<Self::Item> {
62 self.next().transpose()
63 }
64}
65
66#[derive(Debug, Clone)]
68pub struct RelocationIterator<'data> {
69 virtual_address: u32,
70 size: u32,
71 relocs: slice::Iter<'data, U16<LE>>,
72}
73
74impl<'data> RelocationIterator<'data> {
75 pub fn virtual_address(&self) -> u32 {
77 self.virtual_address
78 }
79
80 pub fn size(&self) -> u32 {
82 self.size
83 }
84}
85
86impl<'data> Iterator for RelocationIterator<'data> {
87 type Item = Relocation;
88
89 fn next(&mut self) -> Option<Relocation> {
90 loop {
91 let reloc = self.relocs.next()?.get(LE);
92 if reloc != 0 {
93 return Some(Relocation {
94 virtual_address: self.virtual_address.wrapping_add((reloc & 0xfff) as u32),
95 typ: reloc >> 12,
96 });
97 }
98 }
99 }
100}
101
102#[derive(Debug, Default, Clone, Copy)]
104pub struct Relocation {
105 pub virtual_address: u32,
107 pub typ: u16,
109}