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