Line data Source code
1 : //! Module related to dynamic relocations (DVRT)
2 :
3 : use lief_ffi as ffi;
4 :
5 : use crate::common::{FromFFI, into_optional};
6 : use std::marker::PhantomData;
7 : use super::dynamic_fixups::DynamicFixup;
8 :
9 : pub const IMAGE_DYNAMIC_RELOCATION_GUARD_RF_PROLOGUE: u32 = 1u32;
10 :
11 : pub const IMAGE_DYNAMIC_RELOCATION_GUARD_RF_EPILOGUE: u32 = 2u32;
12 :
13 : pub const IMAGE_DYNAMIC_RELOCATION_GUARD_IMPORT_CONTROL_TRANSFER: u32 = 3u32;
14 :
15 : pub const IMAGE_DYNAMIC_RELOCATION_GUARD_INDIR_CONTROL_TRANSFER: u32 = 4u32;
16 :
17 : pub const IMAGE_DYNAMIC_RELOCATION_GUARD_SWITCHTABLE_BRANCH: u32 = 5u32;
18 :
19 : pub const IMAGE_DYNAMIC_RELOCATION_ARM64X: u32 = 6u32;
20 :
21 : pub const IMAGE_DYNAMIC_RELOCATION_FUNCTION_OVERRIDE: u32 = 7u32;
22 :
23 : pub const IMAGE_DYNAMIC_RELOCATION_ARM64_KERNEL_IMPORT_CALL_TRANSFER: u32 = 8u32;
24 :
25 :
26 : /// This enum wraps the different versions of dynamic relocations:
27 : ///
28 : /// - `IMAGE_DYNAMIC_RELOCATION32`
29 : /// - `IMAGE_DYNAMIC_RELOCATION32_V2`
30 : /// - `IMAGE_DYNAMIC_RELOCATION64`
31 : /// - `IMAGE_DYNAMIC_RELOCATION64_V2`
32 0 : #[derive(Debug)]
33 : pub enum DynamicRelocation<'a> {
34 : /// Either `IMAGE_DYNAMIC_RELOCATION32` or `IMAGE_DYNAMIC_RELOCATION64`
35 : V1(DynamicRelocationV1<'a>),
36 :
37 : /// Either `IMAGE_DYNAMIC_RELOCATION32` or `IMAGE_DYNAMIC_RELOCATION64_V2`
38 : V2(DynamicRelocationV2<'a>),
39 : }
40 :
41 : impl std::fmt::Display for DynamicRelocation<'_> {
42 0 : fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
43 0 : match self {
44 0 : DynamicRelocation::V1(v1) => {
45 0 : write!(f, "{}", v1.as_generic().to_string())
46 : }
47 0 : DynamicRelocation::V2(v2) => {
48 0 : write!(f, "{}", v2.as_generic().to_string())
49 : }
50 : }
51 0 : }
52 : }
53 :
54 : impl<'a> FromFFI<ffi::PE_DynamicRelocation> for DynamicRelocation<'a> {
55 0 : fn from_ffi(ffi_entry: cxx::UniquePtr<ffi::PE_DynamicRelocation>) -> Self {
56 0 : unsafe {
57 0 : let obj_ref = ffi_entry.as_ref().unwrap();
58 0 : if ffi::PE_DynamicRelocationV1::classof(obj_ref) {
59 0 : let raw = {
60 0 : type From = cxx::UniquePtr<ffi::PE_DynamicRelocation>;
61 0 : type To = cxx::UniquePtr<ffi::PE_DynamicRelocationV1>;
62 0 : std::mem::transmute::<From, To>(ffi_entry)
63 0 : };
64 0 : DynamicRelocation::V1(DynamicRelocationV1::from_ffi(raw))
65 0 : } else if ffi::PE_DynamicRelocationV2::classof(obj_ref) {
66 0 : let raw = {
67 0 : type From = cxx::UniquePtr<ffi::PE_DynamicRelocation>;
68 0 : type To = cxx::UniquePtr<ffi::PE_DynamicRelocationV2>;
69 0 : std::mem::transmute::<From, To>(ffi_entry)
70 0 : };
71 0 : DynamicRelocation::V2(DynamicRelocationV2::from_ffi(raw))
72 : } else {
73 0 : panic!("unsupported version");
74 : }
75 : }
76 0 : }
77 : }
78 :
79 : /// Trait shared by all dynamic relocations
80 : pub trait AsDynamicRelocation {
81 : #[doc(hidden)]
82 : fn as_generic(&self) -> &ffi::PE_DynamicRelocation;
83 :
84 : /// Version of the structure
85 0 : fn version(&self) -> u32 {
86 0 : self.as_generic().version()
87 0 : }
88 :
89 : /// Symbol address. Some values have a special meaning and define how fixups are encoded
90 0 : fn symbol(&self) -> u64 {
91 0 : self.as_generic().symbol()
92 0 : }
93 :
94 : /// Return fixups information, where the interpretation may depend on the
95 : /// [`AsDynamicRelocation::symbol`]
96 0 : fn fixups(&self) -> Option<DynamicFixup> {
97 0 : into_optional(self.as_generic().fixups())
98 0 : }
99 : }
100 :
101 : /// This structure represents a dynamic relocation (`IMAGE_DYNAMIC_RELOCATION32` or
102 : /// `IMAGE_DYNAMIC_RELOCATION64`)
103 : pub struct DynamicRelocationV1<'a> {
104 : ptr: cxx::UniquePtr<ffi::PE_DynamicRelocationV1>,
105 : _owner: PhantomData<&'a ffi::PE_LoadConfiguration>,
106 : }
107 :
108 : impl<'a> FromFFI<ffi::PE_DynamicRelocationV1> for DynamicRelocationV1<'a> {
109 0 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_DynamicRelocationV1>) -> Self {
110 0 : Self {
111 0 : ptr,
112 0 : _owner: PhantomData,
113 0 : }
114 0 : }
115 : }
116 :
117 : impl AsDynamicRelocation for DynamicRelocationV1<'_> {
118 0 : fn as_generic(&self) -> &ffi::PE_DynamicRelocation {
119 0 : self.ptr.as_ref().unwrap().as_ref()
120 0 : }
121 : }
122 :
123 : impl std::fmt::Debug for DynamicRelocationV1<'_> {
124 0 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
125 0 : f.debug_struct("DynamicRelocationV1")
126 0 : .field("version", &self.version())
127 0 : .field("symbol", &self.symbol())
128 0 : .finish()
129 0 : }
130 : }
131 :
132 : impl std::fmt::Display for DynamicRelocationV1<'_> {
133 0 : fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
134 0 : write!(f, "{}", self.as_generic().to_string())
135 0 : }
136 : }
137 :
138 : /// This class represents a dynamic relocation (`IMAGE_DYNAMIC_RELOCATION64_V2` or
139 : /// `IMAGE_DYNAMIC_RELOCATION32_V2`)
140 : pub struct DynamicRelocationV2<'a> {
141 : ptr: cxx::UniquePtr<ffi::PE_DynamicRelocationV2>,
142 : _owner: PhantomData<&'a ffi::PE_LoadConfiguration>,
143 : }
144 :
145 : impl<'a> FromFFI<ffi::PE_DynamicRelocationV2> for DynamicRelocationV2<'a> {
146 0 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_DynamicRelocationV2>) -> Self {
147 0 : Self {
148 0 : ptr,
149 0 : _owner: PhantomData,
150 0 : }
151 0 : }
152 : }
153 :
154 : impl AsDynamicRelocation for DynamicRelocationV2<'_> {
155 0 : fn as_generic(&self) -> &ffi::PE_DynamicRelocation {
156 0 : self.ptr.as_ref().unwrap().as_ref()
157 0 : }
158 : }
159 :
160 :
161 : impl std::fmt::Debug for DynamicRelocationV2<'_> {
162 0 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
163 0 : f.debug_struct("DynamicRelocationV1")
164 0 : .field("version", &self.version())
165 0 : .field("symbol", &self.symbol())
166 0 : .finish()
167 0 : }
168 : }
169 :
170 : impl std::fmt::Display for DynamicRelocationV2<'_> {
171 0 : fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
172 0 : write!(f, "{}", self.as_generic().to_string())
173 0 : }
174 : }
175 :
176 : impl AsDynamicRelocation for DynamicRelocation<'_> {
177 0 : fn as_generic(&self) -> &ffi::PE_DynamicRelocation {
178 0 : match &self {
179 0 : DynamicRelocation::V1(entry) => {
180 0 : entry.as_generic()
181 : }
182 :
183 0 : DynamicRelocation::V2(entry) => {
184 0 : entry.as_generic()
185 : }
186 : }
187 0 : }
188 : }
189 :
190 : impl std::fmt::Display for &dyn AsDynamicRelocation {
191 0 : fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
192 0 : write!(f, "{}", self.as_generic().to_string())
193 0 : }
194 : }
|