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 17020 : pub fn virtual_address(&self) -> u32 {
20 17020 : self.ptr.virtual_address()
21 17020 : }
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 17020 : pub fn block_size(&self) -> u32 {
26 17020 : self.ptr.block_size()
27 17020 : }
28 : /// Iterator over the Relocation [`Entry`]
29 17020 : pub fn entries(&self) -> RelocationEntries {
30 17020 : RelocationEntries::new(self.ptr.entries())
31 17020 : }
32 : }
33 :
34 : impl std::fmt::Debug for Relocation<'_> {
35 17020 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36 17020 : f.debug_struct("Relocation")
37 17020 : .field("virtual_address", &self.virtual_address())
38 17020 : .field("block_size", &self.block_size())
39 17020 : .finish()
40 17020 : }
41 : }
42 :
43 : impl<'a> FromFFI<ffi::PE_Relocation> for Relocation<'a> {
44 17020 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_Relocation>) -> Self {
45 17020 : Relocation {
46 17020 : ptr,
47 17020 : _owner: PhantomData,
48 17020 : }
49 17020 : }
50 : }
51 :
52 : #[allow(non_camel_case_types)]
53 1405280 : #[derive(Debug, Copy, Clone)]
54 : pub enum BaseType {
55 : ABS,
56 : HIGH,
57 : LOW,
58 : HIGHLOW,
59 : HIGHADJ,
60 : MIPS_JMPADDR,
61 : ARM_MOV32A,
62 : ARM_MOV32,
63 : RISCV_HI20,
64 : SECTION,
65 : REL,
66 : ARM_MOV32T,
67 : THUMB_MOV32,
68 : RISCV_LOW12I,
69 : RISCV_LOW12S,
70 : IA64_IMM64,
71 : MIPS_JMPADDR16,
72 : DIR64,
73 : HIGH3ADJ,
74 : UNKNOWN(u32),
75 : }
76 :
77 : impl BaseType {
78 1405280 : pub fn from_value(value: u32) -> Self {
79 1405280 : match value {
80 8550 : 0x00000000 => BaseType::ABS,
81 0 : 0x00000001 => BaseType::HIGH,
82 0 : 0x00000002 => BaseType::LOW,
83 1224240 : 0x00000003 => BaseType::HIGHLOW,
84 0 : 0x00000004 => BaseType::HIGHADJ,
85 0 : 0x00000005 => BaseType::MIPS_JMPADDR,
86 0 : 0x00000106 => BaseType::ARM_MOV32A,
87 0 : 0x00000107 => BaseType::ARM_MOV32,
88 0 : 0x00000108 => BaseType::RISCV_HI20,
89 0 : 0x00000006 => BaseType::SECTION,
90 0 : 0x00000007 => BaseType::REL,
91 0 : 0x00000208 => BaseType::ARM_MOV32T,
92 0 : 0x00000209 => BaseType::THUMB_MOV32,
93 0 : 0x0000020a => BaseType::RISCV_LOW12I,
94 0 : 0x00000008 => BaseType::RISCV_LOW12S,
95 0 : 0x00000009 => BaseType::IA64_IMM64,
96 0 : 0x00000309 => BaseType::MIPS_JMPADDR16,
97 172490 : 0x0000000a => BaseType::DIR64,
98 0 : 0x0000000b => BaseType::HIGH3ADJ,
99 0 : _ => BaseType::UNKNOWN(value),
100 : }
101 1405280 : }
102 : }
103 :
104 : /// Class which represents an entry in the relocation table
105 : ///
106 : /// It implements the [`generic::Relocation`] trait which provides additional functions
107 : pub struct Entry<'a> {
108 : ptr: cxx::UniquePtr<ffi::PE_RelocationEntry>,
109 : _owner: PhantomData<&'a ffi::PE_Relocation>,
110 : }
111 :
112 : impl generic::Relocation for Entry<'_> {
113 2810560 : fn as_generic(&self) -> &ffi::AbstractRelocation {
114 2810560 : self.ptr.as_ref().unwrap().as_ref()
115 2810560 : }
116 : }
117 :
118 : impl Entry<'_> {
119 : /// Offset relative to [`Relocation::virtual_address`] where the relocation occurs.
120 1405280 : pub fn position(&self) -> u64 {
121 1405280 : self.ptr.position()
122 1405280 : }
123 :
124 : /// Type of the relocation
125 1405280 : pub fn get_type(&self) -> BaseType {
126 1405280 : BaseType::from_value(self.ptr.get_type())
127 1405280 : }
128 :
129 : /// Raw data of the relocation:
130 : /// - The **high** 4 bits store the relocation type
131 : /// - The **low** 12 bits store the relocation offset
132 1405280 : pub fn data(&self) -> u16 {
133 1405280 : self.ptr.data()
134 1405280 : }
135 : }
136 :
137 : impl std::fmt::Debug for Entry<'_> {
138 1405280 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
139 1405280 : let base = self as &dyn generic::Relocation;
140 1405280 : f.debug_struct("RelocationEntry")
141 1405280 : .field("base", &base)
142 1405280 : .field("type", &self.get_type())
143 1405280 : .field("data", &self.data())
144 1405280 : .field("position", &self.position())
145 1405280 : .finish()
146 1405280 : }
147 : }
148 :
149 : impl<'a> FromFFI<ffi::PE_RelocationEntry> for Entry<'a> {
150 1405280 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_RelocationEntry>) -> Self {
151 1405280 : Entry {
152 1405280 : ptr,
153 1405280 : _owner: PhantomData,
154 1405280 : }
155 1405280 : }
156 : }
157 :
158 1405280 : declare_iterator!(
159 1405280 : RelocationEntries,
160 1405280 : Entry<'a>,
161 1405280 : ffi::PE_RelocationEntry,
162 1405280 : ffi::PE_Relocation,
163 1405280 : ffi::PE_Relocation_it_entries
164 1405280 : );
165 17020 : declare_iterator!(
166 17020 : Relocations,
167 17020 : Relocation<'a>,
168 17020 : ffi::PE_Relocation,
169 17020 : ffi::PE_Binary,
170 17020 : ffi::PE_Binary_it_relocations
171 17020 : );
|