Line data Source code
1 : use super::load_configuration::AsCHPEMetadata;
2 : use crate::common::FromFFI;
3 : use crate::declare_iterator;
4 : use lief_ffi as ffi;
5 : use std::marker::PhantomData;
6 :
7 : /// This structure represents hybrid metadata for ARM64EC or ARM64X.
8 : pub struct CHPEMetadata<'a> {
9 : ptr: cxx::UniquePtr<ffi::PE_CHPEMetadataARM64>,
10 : _owner: PhantomData<&'a ffi::PE_LoadConfiguration>,
11 : }
12 :
13 : impl<'a> FromFFI<ffi::PE_CHPEMetadataARM64> for CHPEMetadata<'a> {
14 0 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_CHPEMetadataARM64>) -> Self {
15 0 : Self {
16 0 : ptr,
17 0 : _owner: PhantomData,
18 0 : }
19 0 : }
20 : }
21 :
22 : impl CHPEMetadata<'_> {
23 : /// RVA to the array that describes architecture-specific ranges
24 0 : pub fn code_map(&self) -> u32 {
25 0 : self.ptr.code_map()
26 0 : }
27 :
28 : /// Number of entries in the code map
29 0 : pub fn code_map_count(&self) -> u32 {
30 0 : self.ptr.code_map_count()
31 0 : }
32 :
33 0 : pub fn redirection_metadata(&self) -> u32 {
34 0 : self.ptr.redirection_metadata()
35 0 : }
36 :
37 0 : pub fn os_arm64x_dispatch_call_no_redirect(&self) -> u32 {
38 0 : self.ptr.os_arm64x_dispatch_call_no_redirect()
39 0 : }
40 :
41 0 : pub fn os_arm64x_dispatch_ret(&self) -> u32 {
42 0 : self.ptr.os_arm64x_dispatch_ret()
43 0 : }
44 :
45 0 : pub fn os_arm64x_dispatch_call(&self) -> u32 {
46 0 : self.ptr.os_arm64x_dispatch_call()
47 0 : }
48 :
49 0 : pub fn os_arm64x_dispatch_icall(&self) -> u32 {
50 0 : self.ptr.os_arm64x_dispatch_icall()
51 0 : }
52 :
53 0 : pub fn os_arm64x_dispatch_icall_cfg(&self) -> u32 {
54 0 : self.ptr.os_arm64x_dispatch_icall_cfg()
55 0 : }
56 :
57 0 : pub fn alternate_entry_point(&self) -> u32 {
58 0 : self.ptr.alternate_entry_point()
59 0 : }
60 :
61 0 : pub fn auxiliary_iat(&self) -> u32 {
62 0 : self.ptr.auxiliary_iat()
63 0 : }
64 :
65 0 : pub fn code_ranges_to_entry_points_count(&self) -> u32 {
66 0 : self.ptr.code_ranges_to_entry_points_count()
67 0 : }
68 :
69 0 : pub fn redirection_metadata_count(&self) -> u32 {
70 0 : self.ptr.redirection_metadata_count()
71 0 : }
72 :
73 0 : pub fn get_x64_information_function_pointer(&self) -> u32 {
74 0 : self.ptr.get_x64_information_function_pointer()
75 0 : }
76 :
77 0 : pub fn set_x64_information_function_pointer(&self) -> u32 {
78 0 : self.ptr.set_x64_information_function_pointer()
79 0 : }
80 :
81 : /// RVA to this architecture-specific exception table
82 0 : pub fn extra_rfe_table(&self) -> u32 {
83 0 : self.ptr.extra_rfe_table()
84 0 : }
85 :
86 : /// Architecture-specific exception table size
87 0 : pub fn extra_rfe_table_size(&self) -> u32 {
88 0 : self.ptr.extra_rfe_table_size()
89 0 : }
90 :
91 0 : pub fn auxiliary_iat_copy(&self) -> u32 {
92 0 : self.ptr.auxiliary_iat_copy()
93 0 : }
94 :
95 0 : pub fn auxiliary_delay_import(&self) -> u32 {
96 0 : self.ptr.auxiliary_delay_import()
97 0 : }
98 :
99 0 : pub fn auxiliary_delay_import_copy(&self) -> u32 {
100 0 : self.ptr.auxiliary_delay_import_copy()
101 0 : }
102 :
103 0 : pub fn bitfield_info(&self) -> u32 {
104 0 : self.ptr.bitfield_info()
105 0 : }
106 :
107 0 : pub fn code_ranges(&self) -> CodeRanges {
108 0 : CodeRanges::new(self.ptr.code_ranges())
109 0 : }
110 :
111 0 : pub fn redirections(&self) -> Redirections {
112 0 : Redirections::new(self.ptr.redirections())
113 0 : }
114 : }
115 :
116 : impl AsCHPEMetadata for CHPEMetadata<'_> {
117 0 : fn as_generic(&self) -> &ffi::PE_CHPEMetadata {
118 0 : self.ptr.as_ref().unwrap().as_ref()
119 0 : }
120 : }
121 :
122 : impl std::fmt::Debug for CHPEMetadata<'_> {
123 0 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
124 0 : f.debug_struct("CHPEMetadataARM64")
125 0 : .field("code_map", &self.code_map())
126 0 : .field("code_map_count", &self.code_map_count())
127 0 : .field("redirection_metadata", &self.redirection_metadata())
128 0 : .field(
129 0 : "os_arm64x_dispatch_call_no_redirect",
130 0 : &self.os_arm64x_dispatch_call_no_redirect(),
131 0 : )
132 0 : .field("os_arm64x_dispatch_ret", &self.os_arm64x_dispatch_ret())
133 0 : .field("os_arm64x_dispatch_call", &self.os_arm64x_dispatch_call())
134 0 : .field("os_arm64x_dispatch_icall", &self.os_arm64x_dispatch_icall())
135 0 : .field(
136 0 : "os_arm64x_dispatch_icall_cfg",
137 0 : &self.os_arm64x_dispatch_icall_cfg(),
138 0 : )
139 0 : .field("alternate_entry_point", &self.alternate_entry_point())
140 0 : .field("auxiliary_iat", &self.auxiliary_iat())
141 0 : .field(
142 0 : "code_ranges_to_entry_points_count",
143 0 : &self.code_ranges_to_entry_points_count(),
144 0 : )
145 0 : .field(
146 0 : "redirection_metadata_count",
147 0 : &self.redirection_metadata_count(),
148 0 : )
149 0 : .field(
150 0 : "get_x64_information_function_pointer",
151 0 : &self.get_x64_information_function_pointer(),
152 0 : )
153 0 : .field(
154 0 : "set_x64_information_function_pointer",
155 0 : &self.set_x64_information_function_pointer(),
156 0 : )
157 0 : .field("extra_rfe_table", &self.extra_rfe_table())
158 0 : .field("extra_rfe_table_size", &self.extra_rfe_table_size())
159 0 : .field("auxiliary_iat_copy", &self.auxiliary_iat_copy())
160 0 : .field("auxiliary_delay_import", &self.auxiliary_delay_import())
161 0 : .field(
162 0 : "auxiliary_delay_import_copy",
163 0 : &self.auxiliary_delay_import_copy(),
164 0 : )
165 0 : .field("bitfield_info", &self.bitfield_info())
166 0 : .finish()
167 0 : }
168 : }
169 :
170 : /// Structure that describes architecture-specific ranges
171 : pub struct RangeEntry<'a> {
172 : ptr: cxx::UniquePtr<ffi::PE_CHPEMetadataARM64_range_entry_t>,
173 : _owner: PhantomData<&'a ffi::PE_LoadConfiguration>,
174 : }
175 :
176 : impl<'a> FromFFI<ffi::PE_CHPEMetadataARM64_range_entry_t> for RangeEntry<'a> {
177 0 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_CHPEMetadataARM64_range_entry_t>) -> Self {
178 0 : Self {
179 0 : ptr,
180 0 : _owner: PhantomData,
181 0 : }
182 0 : }
183 : }
184 :
185 : #[allow(non_camel_case_types)]
186 0 : #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
187 : pub enum RangeType {
188 : ARM64,
189 : ARM64EC,
190 : AMD64,
191 : UNKNOWN(u32),
192 : }
193 :
194 : impl From<u32> for RangeType {
195 0 : fn from(value: u32) -> Self {
196 0 : match value {
197 0 : 0x000000000 => RangeType::ARM64,
198 0 : 0x000000001 => RangeType::ARM64EC,
199 0 : 0x000000002 => RangeType::AMD64,
200 0 : _ => RangeType::UNKNOWN(value),
201 : }
202 0 : }
203 : }
204 :
205 : impl RangeEntry<'_> {
206 : /// Raw data (include start RVA and type)
207 0 : pub fn start_offset(&self) -> u32 {
208 0 : self.ptr.start_offset()
209 0 : }
210 :
211 : /// Range's length
212 0 : pub fn length(&self) -> u32 {
213 0 : self.ptr.length()
214 0 : }
215 :
216 : /// Start of the range (RVA)
217 0 : pub fn start(&self) -> u32 {
218 0 : self.ptr.start()
219 0 : }
220 :
221 : /// End of the range (RVA)
222 0 : pub fn end(&self) -> u32 {
223 0 : self.ptr.end()
224 0 : }
225 :
226 : /// Architecture for this range
227 0 : pub fn range_type(&self) -> RangeType {
228 0 : RangeType::from(self.ptr.get_type())
229 0 : }
230 : }
231 :
232 : impl std::fmt::Debug for RangeEntry<'_> {
233 0 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
234 0 : f.debug_struct("RangeEntry")
235 0 : .field("start_offset", &self.start_offset())
236 0 : .field("length", &self.length())
237 0 : .field("start", &self.start())
238 0 : .field("end", &self.end())
239 0 : .field("range_type", &self.range_type())
240 0 : .finish()
241 0 : }
242 : }
243 :
244 : /// Structure that describes a redirection
245 : pub struct RedirectionEntry<'a> {
246 : ptr: cxx::UniquePtr<ffi::PE_CHPEMetadataARM64_redirection_entry_t>,
247 : _owner: PhantomData<&'a ffi::PE_LoadConfiguration>,
248 : }
249 :
250 : impl<'a> FromFFI<ffi::PE_CHPEMetadataARM64_redirection_entry_t> for RedirectionEntry<'a> {
251 0 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_CHPEMetadataARM64_redirection_entry_t>) -> Self {
252 0 : Self {
253 0 : ptr,
254 0 : _owner: PhantomData,
255 0 : }
256 0 : }
257 : }
258 :
259 : impl RedirectionEntry<'_> {
260 0 : pub fn src(&self) -> u32 {
261 0 : self.ptr.src()
262 0 : }
263 :
264 0 : pub fn dst(&self) -> u32 {
265 0 : self.ptr.dst()
266 0 : }
267 : }
268 :
269 : impl std::fmt::Debug for RedirectionEntry<'_> {
270 0 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
271 0 : f.debug_struct("RedirectionEntry")
272 0 : .field("src", &self.src())
273 0 : .field("dst", &self.dst())
274 0 : .finish()
275 0 : }
276 : }
277 :
278 0 : declare_iterator!(
279 0 : CodeRanges,
280 0 : RangeEntry<'a>,
281 0 : ffi::PE_CHPEMetadataARM64_range_entry_t,
282 0 : ffi::PE_CHPEMetadataARM64,
283 0 : ffi::PE_CHPEMetadataARM64_it_const_range_entries
284 0 : );
285 :
286 0 : declare_iterator!(
287 0 : Redirections,
288 0 : RedirectionEntry<'a>,
289 0 : ffi::PE_CHPEMetadataARM64_redirection_entry_t,
290 0 : ffi::PE_CHPEMetadataARM64,
291 0 : ffi::PE_CHPEMetadataARM64_it_const_redirection_entries
292 0 : );
|