Line data Source code
1 : //! This module includes the different structures related to the relocation process in a PE binary
2 :
3 : use std::marker::PhantomData;
4 :
5 : use lief_ffi as ffi;
6 :
7 : use crate::common::FromFFI;
8 : use crate::{declare_iterator, generic};
9 :
10 : /// Class which represents the *Base Relocation Block*
11 : /// We usually find this structure in the `.reloc` section
12 : pub struct Relocation<'a> {
13 : ptr: cxx::UniquePtr<ffi::PE_Relocation>,
14 : _owner: PhantomData<&'a ffi::PE_Binary>,
15 : }
16 :
17 : impl Relocation<'_> {
18 : /// The RVA for which the offset of the relocation entries is added
19 28379 : pub fn virtual_address(&self) -> u32 {
20 28379 : self.ptr.virtual_address()
21 28379 : }
22 :
23 : /// The total number of bytes in the base relocation block.
24 : /// `block_size = sizeof(BaseRelocationBlock) + nb_of_relocs * sizeof(uint16_t = RelocationEntry)`
25 28379 : pub fn block_size(&self) -> u32 {
26 28379 : self.ptr.block_size()
27 28379 : }
28 : /// Iterator over the Relocation [`Entry`]
29 28379 : pub fn entries(&self) -> RelocationEntries<'_> {
30 28379 : RelocationEntries::new(self.ptr.entries())
31 28379 : }
32 : }
33 :
34 : impl std::fmt::Debug for Relocation<'_> {
35 28379 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36 28379 : f.debug_struct("Relocation")
37 28379 : .field("virtual_address", &self.virtual_address())
38 28379 : .field("block_size", &self.block_size())
39 28379 : .finish()
40 28379 : }
41 : }
42 :
43 : impl<'a> FromFFI<ffi::PE_Relocation> for Relocation<'a> {
44 28379 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_Relocation>) -> Self {
45 28379 : Relocation {
46 28379 : ptr,
47 28379 : _owner: PhantomData,
48 28379 : }
49 28379 : }
50 : }
51 :
52 : #[allow(non_camel_case_types)]
53 2922270 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
54 : pub enum BaseType {
55 : ABS,
56 : HIGH,
57 : LOW,
58 : HIGHLOW,
59 : HIGHADJ,
60 : MIPS_JMPADDR,
61 : ARM_MOV32,
62 : RISCV_HI20,
63 : SECTION,
64 : THUMB_MOV32,
65 : RISCV_LOW12I,
66 : RISCV_LOW12S,
67 : LOONARCH_MARK_LA,
68 : MIPS_JMPADDR16,
69 : DIR64,
70 : HIGH3ADJ,
71 : UNKNOWN(u32),
72 : }
73 :
74 : impl From<u32> for BaseType {
75 2922270 : fn from(value: u32) -> Self {
76 2922270 : match value {
77 14105 : 0x00000000 => BaseType::ABS,
78 0 : 0x00000001 => BaseType::HIGH,
79 0 : 0x00000002 => BaseType::LOW,
80 1591512 : 0x00000003 => BaseType::HIGHLOW,
81 0 : 0x00000004 => BaseType::HIGHADJ,
82 0 : 0x00000105 => BaseType::MIPS_JMPADDR,
83 0 : 0x00000205 => BaseType::ARM_MOV32,
84 0 : 0x00000405 => BaseType::RISCV_HI20,
85 0 : 0x00000006 => BaseType::SECTION,
86 0 : 0x00000807 => BaseType::THUMB_MOV32,
87 0 : 0x00001007 => BaseType::RISCV_LOW12I,
88 0 : 0x00002008 => BaseType::RISCV_LOW12S,
89 0 : 0x00004008 => BaseType::LOONARCH_MARK_LA,
90 0 : 0x00000009 => BaseType::MIPS_JMPADDR16,
91 1316653 : 0x0000000a => BaseType::DIR64,
92 0 : 0x0000000b => BaseType::HIGH3ADJ,
93 0 : _ => BaseType::UNKNOWN(value),
94 : }
95 2922270 : }
96 : }
97 : impl From<BaseType> for u32 {
98 0 : fn from(value: BaseType) -> u32 {
99 0 : match value {
100 0 : BaseType::ABS => 0x00000000,
101 0 : BaseType::HIGH => 0x00000001,
102 0 : BaseType::LOW => 0x00000002,
103 0 : BaseType::HIGHLOW => 0x00000003,
104 0 : BaseType::HIGHADJ => 0x00000004,
105 0 : BaseType::MIPS_JMPADDR => 0x00000105,
106 0 : BaseType::ARM_MOV32 => 0x00000205,
107 0 : BaseType::RISCV_HI20 => 0x00000405,
108 0 : BaseType::SECTION => 0x00000006,
109 0 : BaseType::THUMB_MOV32 => 0x00000807,
110 0 : BaseType::RISCV_LOW12I => 0x00001007,
111 0 : BaseType::RISCV_LOW12S => 0x00002008,
112 0 : BaseType::LOONARCH_MARK_LA => 0x00004008,
113 0 : BaseType::MIPS_JMPADDR16 => 0x00000009,
114 0 : BaseType::DIR64 => 0x0000000a,
115 0 : BaseType::HIGH3ADJ => 0x0000000b,
116 0 : BaseType::UNKNOWN(value) => value,
117 : }
118 0 : }
119 : }
120 :
121 : /// Class which represents an entry in the relocation table
122 : ///
123 : /// It implements the [`generic::Relocation`] trait which provides additional functions
124 : pub struct Entry<'a> {
125 : ptr: cxx::UniquePtr<ffi::PE_RelocationEntry>,
126 : _owner: PhantomData<&'a ffi::PE_Relocation>,
127 : }
128 :
129 : impl generic::Relocation for Entry<'_> {
130 5844540 : fn as_generic(&self) -> &ffi::AbstractRelocation {
131 5844540 : self.ptr.as_ref().unwrap().as_ref()
132 5844540 : }
133 : }
134 :
135 : impl Entry<'_> {
136 : /// Offset relative to [`Relocation::virtual_address`] where the relocation occurs.
137 2922270 : pub fn position(&self) -> u64 {
138 2922270 : self.ptr.position()
139 2922270 : }
140 :
141 : /// Type of the relocation
142 2922270 : pub fn get_type(&self) -> BaseType {
143 2922270 : BaseType::from(self.ptr.get_type())
144 2922270 : }
145 :
146 : /// Raw data of the relocation:
147 : /// - The **high** 4 bits store the relocation type
148 : /// - The **low** 12 bits store the relocation offset
149 2922270 : pub fn data(&self) -> u16 {
150 2922270 : self.ptr.data()
151 2922270 : }
152 : }
153 :
154 : impl std::fmt::Debug for Entry<'_> {
155 2922270 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
156 2922270 : let base = self as &dyn generic::Relocation;
157 2922270 : f.debug_struct("RelocationEntry")
158 2922270 : .field("base", &base)
159 2922270 : .field("type", &self.get_type())
160 2922270 : .field("data", &self.data())
161 2922270 : .field("position", &self.position())
162 2922270 : .finish()
163 2922270 : }
164 : }
165 :
166 : impl<'a> FromFFI<ffi::PE_RelocationEntry> for Entry<'a> {
167 2922270 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_RelocationEntry>) -> Self {
168 2922270 : Entry {
169 2922270 : ptr,
170 2922270 : _owner: PhantomData,
171 2922270 : }
172 2922270 : }
173 : }
174 :
175 2922270 : declare_iterator!(
176 2922270 : RelocationEntries,
177 2922270 : Entry<'a>,
178 2922270 : ffi::PE_RelocationEntry,
179 2922270 : ffi::PE_Relocation,
180 2922270 : ffi::PE_Relocation_it_entries
181 2922270 : );
182 28379 : declare_iterator!(
183 28379 : Relocations,
184 28379 : Relocation<'a>,
185 28379 : ffi::PE_Relocation,
186 28379 : ffi::PE_Binary,
187 28379 : ffi::PE_Binary_it_relocations
188 28379 : );
|