Line data Source code
1 : use lief_ffi as ffi;
2 :
3 : use std::marker::PhantomData;
4 :
5 : use crate::to_slice;
6 : use crate::common::FromFFI;
7 : use crate::{generic, declare_iterator};
8 :
9 :
10 : #[allow(non_camel_case_types)]
11 305170 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
12 : pub enum StorageClass {
13 : INVALID,
14 : END_OF_FUNCTION,
15 : NONE,
16 : AUTOMATIC,
17 : EXTERNAL,
18 : STATIC,
19 : REGISTER,
20 : EXTERNAL_DEF,
21 : LABEL,
22 : UNDEFINED_LABEL,
23 : MEMBER_OF_STRUCT,
24 : ARGUMENT,
25 : STRUCT_TAG,
26 : MEMBER_OF_UNION,
27 : UNION_TAG,
28 : TYPE_DEFINITION,
29 : UNDEFINED_STATIC,
30 : ENUM_TAG,
31 : MEMBER_OF_ENUM,
32 : REGISTER_PARAM,
33 : BIT_FIELD,
34 : BLOCK,
35 : FUNCTION,
36 : END_OF_STRUCT,
37 : FILE,
38 : SECTION,
39 : WEAK_EXTERNAL,
40 : CLR_TOKEN,
41 : UNKNOWN(u32),
42 : }
43 :
44 : impl From<u32> for StorageClass {
45 305170 : fn from(value: u32) -> Self {
46 305170 : match value {
47 0 : 0x000000ff => StorageClass::INVALID,
48 0 : 0xffffffff => StorageClass::END_OF_FUNCTION,
49 0 : 0x00000000 => StorageClass::NONE,
50 0 : 0x00000001 => StorageClass::AUTOMATIC,
51 82890 : 0x00000002 => StorageClass::EXTERNAL,
52 219380 : 0x00000003 => StorageClass::STATIC,
53 0 : 0x00000004 => StorageClass::REGISTER,
54 0 : 0x00000005 => StorageClass::EXTERNAL_DEF,
55 80 : 0x00000006 => StorageClass::LABEL,
56 0 : 0x00000007 => StorageClass::UNDEFINED_LABEL,
57 0 : 0x00000008 => StorageClass::MEMBER_OF_STRUCT,
58 0 : 0x00000009 => StorageClass::ARGUMENT,
59 0 : 0x0000000a => StorageClass::STRUCT_TAG,
60 0 : 0x0000000b => StorageClass::MEMBER_OF_UNION,
61 0 : 0x0000000c => StorageClass::UNION_TAG,
62 0 : 0x0000000d => StorageClass::TYPE_DEFINITION,
63 0 : 0x0000000e => StorageClass::UNDEFINED_STATIC,
64 0 : 0x0000000f => StorageClass::ENUM_TAG,
65 0 : 0x00000010 => StorageClass::MEMBER_OF_ENUM,
66 0 : 0x00000011 => StorageClass::REGISTER_PARAM,
67 0 : 0x00000012 => StorageClass::BIT_FIELD,
68 0 : 0x00000064 => StorageClass::BLOCK,
69 0 : 0x00000065 => StorageClass::FUNCTION,
70 0 : 0x00000066 => StorageClass::END_OF_STRUCT,
71 2740 : 0x00000067 => StorageClass::FILE,
72 0 : 0x00000068 => StorageClass::SECTION,
73 80 : 0x00000069 => StorageClass::WEAK_EXTERNAL,
74 0 : 0x0000006b => StorageClass::CLR_TOKEN,
75 0 : _ => StorageClass::UNKNOWN(value),
76 :
77 : }
78 305170 : }
79 : }
80 : impl From<StorageClass> for u32 {
81 0 : fn from(value: StorageClass) -> u32 {
82 0 : match value {
83 0 : StorageClass::INVALID => 0x000000ff,
84 0 : StorageClass::END_OF_FUNCTION => 0xffffffff,
85 0 : StorageClass::NONE => 0x00000000,
86 0 : StorageClass::AUTOMATIC => 0x00000001,
87 0 : StorageClass::EXTERNAL => 0x00000002,
88 0 : StorageClass::STATIC => 0x00000003,
89 0 : StorageClass::REGISTER => 0x00000004,
90 0 : StorageClass::EXTERNAL_DEF => 0x00000005,
91 0 : StorageClass::LABEL => 0x00000006,
92 0 : StorageClass::UNDEFINED_LABEL => 0x00000007,
93 0 : StorageClass::MEMBER_OF_STRUCT => 0x00000008,
94 0 : StorageClass::ARGUMENT => 0x00000009,
95 0 : StorageClass::STRUCT_TAG => 0x0000000a,
96 0 : StorageClass::MEMBER_OF_UNION => 0x0000000b,
97 0 : StorageClass::UNION_TAG => 0x0000000c,
98 0 : StorageClass::TYPE_DEFINITION => 0x0000000d,
99 0 : StorageClass::UNDEFINED_STATIC => 0x0000000e,
100 0 : StorageClass::ENUM_TAG => 0x0000000f,
101 0 : StorageClass::MEMBER_OF_ENUM => 0x00000010,
102 0 : StorageClass::REGISTER_PARAM => 0x00000011,
103 0 : StorageClass::BIT_FIELD => 0x00000012,
104 0 : StorageClass::BLOCK => 0x00000064,
105 0 : StorageClass::FUNCTION => 0x00000065,
106 0 : StorageClass::END_OF_STRUCT => 0x00000066,
107 0 : StorageClass::FILE => 0x00000067,
108 0 : StorageClass::SECTION => 0x00000068,
109 0 : StorageClass::WEAK_EXTERNAL => 0x00000069,
110 0 : StorageClass::CLR_TOKEN => 0x0000006b,
111 0 : StorageClass::UNKNOWN(value) => value,
112 : }
113 0 : }
114 : }
115 :
116 :
117 : #[allow(non_camel_case_types)]
118 305170 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
119 : pub enum BaseType {
120 : TY_NULL,
121 : TY_VOID,
122 : TY_CHAR,
123 : TY_SHORT,
124 : TY_INT,
125 : TY_LONG,
126 : TY_FLOAT,
127 : TY_DOUBLE,
128 : TY_STRUCT,
129 : TY_UNION,
130 : TY_ENUM,
131 : TY_MOE,
132 : TY_BYTE,
133 : TY_WORD,
134 : TY_UINT,
135 : TY_DWORD,
136 : UNKNOWN(u32),
137 : }
138 :
139 : impl From<u32> for BaseType {
140 305170 : fn from(value: u32) -> Self {
141 305170 : match value {
142 305170 : 0x00000000 => BaseType::TY_NULL,
143 0 : 0x00000001 => BaseType::TY_VOID,
144 0 : 0x00000002 => BaseType::TY_CHAR,
145 0 : 0x00000003 => BaseType::TY_SHORT,
146 0 : 0x00000004 => BaseType::TY_INT,
147 0 : 0x00000005 => BaseType::TY_LONG,
148 0 : 0x00000006 => BaseType::TY_FLOAT,
149 0 : 0x00000007 => BaseType::TY_DOUBLE,
150 0 : 0x00000008 => BaseType::TY_STRUCT,
151 0 : 0x00000009 => BaseType::TY_UNION,
152 0 : 0x0000000a => BaseType::TY_ENUM,
153 0 : 0x0000000b => BaseType::TY_MOE,
154 0 : 0x0000000c => BaseType::TY_BYTE,
155 0 : 0x0000000d => BaseType::TY_WORD,
156 0 : 0x0000000e => BaseType::TY_UINT,
157 0 : 0x0000000f => BaseType::TY_DWORD,
158 0 : _ => BaseType::UNKNOWN(value),
159 :
160 : }
161 305170 : }
162 : }
163 : impl From<BaseType> for u32 {
164 0 : fn from(value: BaseType) -> u32 {
165 0 : match value {
166 0 : BaseType::TY_NULL => 0x00000000,
167 0 : BaseType::TY_VOID => 0x00000001,
168 0 : BaseType::TY_CHAR => 0x00000002,
169 0 : BaseType::TY_SHORT => 0x00000003,
170 0 : BaseType::TY_INT => 0x00000004,
171 0 : BaseType::TY_LONG => 0x00000005,
172 0 : BaseType::TY_FLOAT => 0x00000006,
173 0 : BaseType::TY_DOUBLE => 0x00000007,
174 0 : BaseType::TY_STRUCT => 0x00000008,
175 0 : BaseType::TY_UNION => 0x00000009,
176 0 : BaseType::TY_ENUM => 0x0000000a,
177 0 : BaseType::TY_MOE => 0x0000000b,
178 0 : BaseType::TY_BYTE => 0x0000000c,
179 0 : BaseType::TY_WORD => 0x0000000d,
180 0 : BaseType::TY_UINT => 0x0000000e,
181 0 : BaseType::TY_DWORD => 0x0000000f,
182 0 : BaseType::UNKNOWN(value) => value,
183 :
184 : }
185 0 : }
186 : }
187 :
188 :
189 :
190 : #[allow(non_camel_case_types)]
191 305170 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
192 : pub enum ComplexType {
193 : TY_NULL,
194 : TY_POINTER,
195 : TY_FUNCTION,
196 : TY_ARRAY,
197 : UNKNOWN(u32),
198 : }
199 :
200 : impl From<u32> for ComplexType {
201 305170 : fn from(value: u32) -> Self {
202 305170 : match value {
203 234340 : 0x00000000 => ComplexType::TY_NULL,
204 0 : 0x00000001 => ComplexType::TY_POINTER,
205 70830 : 0x00000002 => ComplexType::TY_FUNCTION,
206 0 : 0x00000003 => ComplexType::TY_ARRAY,
207 0 : _ => ComplexType::UNKNOWN(value),
208 :
209 : }
210 305170 : }
211 : }
212 : impl From<ComplexType> for u32 {
213 0 : fn from(value: ComplexType) -> u32 {
214 0 : match value {
215 0 : ComplexType::TY_NULL => 0x00000000,
216 0 : ComplexType::TY_POINTER => 0x00000001,
217 0 : ComplexType::TY_FUNCTION => 0x00000002,
218 0 : ComplexType::TY_ARRAY => 0x00000003,
219 0 : ComplexType::UNKNOWN(value) => value,
220 :
221 : }
222 0 : }
223 : }
224 :
225 : /// Structure that represents a PE-COFF symbol.
226 : ///
227 : /// Usually PE debug information (including symbols) are wrapped in a PDB file
228 : /// referenced by the CodeViewPDB object.
229 : ///
230 : /// The PE format allows to define (by COFF inheritance) a symbol table that is
231 : /// different from the regular PDB symbols. This table contains COFF(16) symbols
232 : /// which can reference auxiliary symbols.
233 : ///
234 : /// **Warning:** The [`crate::generic::Symbol::value`] should be interpreted in perspective of
235 : /// the [`Symbol::storage_class`].
236 : ///
237 : /// Reference: <https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#coff-symbol-table>
238 : pub struct Symbol<'a> {
239 : ptr: cxx::UniquePtr<ffi::PE_Symbol>,
240 : _owner: PhantomData<&'a ffi::PE_Binary>
241 : }
242 :
243 : impl FromFFI<ffi::PE_Symbol> for Symbol<'_> {
244 305170 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_Symbol>) -> Self {
245 305170 : Self {
246 305170 : ptr,
247 305170 : _owner: PhantomData
248 305170 : }
249 305170 : }
250 : }
251 :
252 : impl std::fmt::Debug for Symbol<'_> {
253 305170 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
254 305170 : let base = self as &dyn generic::Symbol;
255 305170 : f.debug_struct("Symbol")
256 305170 : .field("base", &base)
257 305170 : .field("storage_class", &self.storage_class())
258 305170 : .field("base_type", &self.base_type())
259 305170 : .field("complex_type", &self.complex_type())
260 305170 : .field("section_idx", &self.section_idx())
261 305170 : .finish()
262 305170 : }
263 : }
264 :
265 : impl Symbol<'_> {
266 : /// Auxiliary symbols associated with this symbol.
267 305170 : pub fn auxiliary_symbols(&self) -> ItAuxiliarySymbols {
268 305170 : ItAuxiliarySymbols::new(self.ptr.auxiliary_symbols())
269 305170 : }
270 :
271 : /// Storage class of the symbol which indicates what kind of definition a
272 : /// symbol represents.
273 305170 : pub fn storage_class(&self) -> StorageClass {
274 305170 : StorageClass::from(self.ptr.storage_class())
275 305170 : }
276 :
277 : /// The simple (base) data type
278 305170 : pub fn base_type(&self) -> BaseType {
279 305170 : BaseType::from(self.ptr.base_type())
280 305170 : }
281 :
282 : /// The complex type (if any)
283 305170 : pub fn complex_type(&self) -> ComplexType {
284 305170 : ComplexType::from(self.ptr.complex_type())
285 305170 : }
286 :
287 : /// The signed integer that identifies the section, using a one-based index
288 : /// into the section table. Some values have special meaning:
289 : ///
290 : /// * 0: The symbol record is not yet assigned a section. A value of zero
291 : /// indicates that a reference to an external symbol is defined elsewhere.
292 : /// A value of non-zero is a common symbol with a size that is specified
293 : /// by the value.
294 : /// * -1: The symbol has an absolute (non-relocatable) value and is not an
295 : /// address.
296 : /// * -2: The symbol provides general type or debugging information but does
297 : /// not correspond to a section. Microsoft tools use this setting along
298 : /// with `.file` records
299 305170 : pub fn section_idx(&self) -> i16 {
300 305170 : self.ptr.section_idx()
301 305170 : }
302 :
303 0 : pub fn is_external(&self) -> bool {
304 0 : self.ptr.is_external()
305 0 : }
306 :
307 0 : pub fn is_weak_external(&self) -> bool {
308 0 : self.ptr.is_weak_external()
309 0 : }
310 :
311 0 : pub fn is_undefined(&self) -> bool {
312 0 : self.ptr.is_undefined()
313 0 : }
314 :
315 0 : pub fn is_function_line_info(&self) -> bool {
316 0 : self.ptr.is_function_line_info()
317 0 : }
318 :
319 0 : pub fn is_file_record(&self) -> bool {
320 0 : self.ptr.is_file_record()
321 0 : }
322 : }
323 :
324 : impl generic::Symbol for Symbol<'_> {
325 915510 : fn as_generic(&self) -> &ffi::AbstractSymbol {
326 915510 : self.ptr.as_ref().unwrap().as_ref()
327 915510 : }
328 : }
329 :
330 : /// Class that represents an auxiliary symbols.
331 : ///
332 : /// An auxiliary symbol has the same size as a regular [`Symbol`] (18 bytes) but its content
333 : /// depends on the the parent symbol.
334 200700 : #[derive(Debug)]
335 : pub enum AuxiliarySymbols<'a> {
336 : /// Auxiliary Format 1 from the PE-COFF documentation
337 : FunctionDefinition(AuxiliaryFunctionDefinition<'a>),
338 : /// Auxiliary Format 2: .bf and .ef Symbols from the PE-COFF documentation
339 : BfAndEf(AuxiliaryBfAndEf<'a>),
340 : /// Auxiliary Format 3: Weak Externals from the PE-COFF documentation
341 : WeakExternal(AuxiliaryWeakExternal<'a>),
342 : /// Auxiliary Format 4: Files from the PE-COFF documentation
343 : File(AuxiliaryFile<'a>),
344 : /// Auxiliary Format 5: Section Definitions from the PE-COFF documentation
345 : SectionDefinition(AuxiliarySectionDefinition<'a>),
346 : CLRToken(AuxiliaryCLRToken<'a>),
347 : Unknown(AuxiliarySymbol<'a>),
348 : }
349 :
350 :
351 : impl<'a> FromFFI<ffi::PE_AuxiliarySymbol> for AuxiliarySymbols<'a> {
352 200700 : fn from_ffi(ffi_entry: cxx::UniquePtr<ffi::PE_AuxiliarySymbol>) -> Self {
353 200700 : unsafe {
354 200700 : let aux_ref = ffi_entry.as_ref().unwrap();
355 200700 : if ffi::PE_AuxiliaryFile::classof(aux_ref) {
356 2740 : let raw = {
357 2740 : type From = cxx::UniquePtr<ffi::PE_AuxiliarySymbol>;
358 2740 : type To = cxx::UniquePtr<ffi::PE_AuxiliaryFile>;
359 2740 : std::mem::transmute::<From, To>(ffi_entry)
360 2740 : };
361 2740 : AuxiliarySymbols::File(AuxiliaryFile::from_ffi(raw))
362 197960 : } else if ffi::PE_AuxiliarybfAndefSymbol::classof(aux_ref) {
363 0 : let raw = {
364 0 : type From = cxx::UniquePtr<ffi::PE_AuxiliarySymbol>;
365 0 : type To = cxx::UniquePtr<ffi::PE_AuxiliarybfAndefSymbol>;
366 0 : std::mem::transmute::<From, To>(ffi_entry)
367 0 : };
368 0 : AuxiliarySymbols::BfAndEf(AuxiliaryBfAndEf::from_ffi(raw))
369 197960 : } else if ffi::PE_AuxiliaryCLRToken::classof(aux_ref) {
370 0 : let raw = {
371 0 : type From = cxx::UniquePtr<ffi::PE_AuxiliarySymbol>;
372 0 : type To = cxx::UniquePtr<ffi::PE_AuxiliaryCLRToken>;
373 0 : std::mem::transmute::<From, To>(ffi_entry)
374 0 : };
375 0 : AuxiliarySymbols::CLRToken(AuxiliaryCLRToken::from_ffi(raw))
376 197960 : } else if ffi::PE_AuxiliaryFunctionDefinition::classof(aux_ref) {
377 1610 : let raw = {
378 1610 : type From = cxx::UniquePtr<ffi::PE_AuxiliarySymbol>;
379 1610 : type To = cxx::UniquePtr<ffi::PE_AuxiliaryFunctionDefinition>;
380 1610 : std::mem::transmute::<From, To>(ffi_entry)
381 1610 : };
382 1610 : AuxiliarySymbols::FunctionDefinition(AuxiliaryFunctionDefinition::from_ffi(raw))
383 196350 : } else if ffi::PE_AuxiliaryWeakExternal::classof(aux_ref) {
384 560 : let raw = {
385 560 : type From = cxx::UniquePtr<ffi::PE_AuxiliarySymbol>;
386 560 : type To = cxx::UniquePtr<ffi::PE_AuxiliaryWeakExternal>;
387 560 : std::mem::transmute::<From, To>(ffi_entry)
388 560 : };
389 560 : AuxiliarySymbols::WeakExternal(AuxiliaryWeakExternal::from_ffi(raw))
390 195790 : } else if ffi::PE_AuxiliarySectionDefinition::classof(aux_ref) {
391 195790 : let raw = {
392 195790 : type From = cxx::UniquePtr<ffi::PE_AuxiliarySymbol>;
393 195790 : type To = cxx::UniquePtr<ffi::PE_AuxiliarySectionDefinition>;
394 195790 : std::mem::transmute::<From, To>(ffi_entry)
395 195790 : };
396 195790 : AuxiliarySymbols::SectionDefinition(AuxiliarySectionDefinition::from_ffi(raw))
397 : } else {
398 0 : AuxiliarySymbols::Unknown(AuxiliarySymbol::from_ffi(ffi_entry))
399 : }
400 : }
401 200700 : }
402 : }
403 :
404 : /// This auxiliary symbol represents a filename (auxiliary format 4)
405 : ///
406 : /// The [`crate::generic::Symbol::name`] itself should start with `.file`, and this auxiliary record
407 : /// gives the name of a source-code file.
408 : ///
409 : /// Reference: <https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#auxiliary-format-4-files>
410 : pub struct AuxiliaryFile<'a> {
411 : ptr: cxx::UniquePtr<ffi::PE_AuxiliaryFile>,
412 : _owner: PhantomData<&'a ffi::PE_Symbol>,
413 : }
414 :
415 : impl std::fmt::Debug for AuxiliaryFile<'_> {
416 2740 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
417 2740 : f.debug_struct("AuxiliaryFile")
418 2740 : .field("filename", &self.filename())
419 2740 : .finish()
420 2740 : }
421 : }
422 :
423 : impl<'a> FromFFI<ffi::PE_AuxiliaryFile> for AuxiliaryFile<'a> {
424 2740 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_AuxiliaryFile>) -> Self {
425 2740 : Self {
426 2740 : ptr,
427 2740 : _owner: PhantomData,
428 2740 : }
429 2740 : }
430 : }
431 :
432 : impl AuxiliaryFile<'_> {
433 : /// The associated filename
434 2740 : pub fn filename(&self) -> String {
435 2740 : self.ptr.filename().to_string()
436 2740 : }
437 : }
438 :
439 : pub struct AuxiliaryBfAndEf<'a> {
440 : #[allow(dead_code)]
441 : ptr: cxx::UniquePtr<ffi::PE_AuxiliarybfAndefSymbol>,
442 : _owner: PhantomData<&'a ffi::PE_Symbol>,
443 : }
444 :
445 : impl std::fmt::Debug for AuxiliaryBfAndEf<'_> {
446 0 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
447 0 : f.debug_struct("AuxiliaryBfAndEf")
448 0 : .finish()
449 0 : }
450 : }
451 :
452 : impl<'a> FromFFI<ffi::PE_AuxiliarybfAndefSymbol> for AuxiliaryBfAndEf<'a> {
453 0 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_AuxiliarybfAndefSymbol>) -> Self {
454 0 : Self {
455 0 : ptr,
456 0 : _owner: PhantomData,
457 0 : }
458 0 : }
459 : }
460 :
461 : pub struct AuxiliaryCLRToken<'a> {
462 : #[allow(dead_code)]
463 : ptr: cxx::UniquePtr<ffi::PE_AuxiliaryCLRToken>,
464 : _owner: PhantomData<&'a ffi::PE_Symbol>,
465 : }
466 :
467 : impl std::fmt::Debug for AuxiliaryCLRToken<'_> {
468 0 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
469 0 : f.debug_struct("AuxiliaryCLRToken")
470 0 : .finish()
471 0 : }
472 : }
473 :
474 : impl<'a> FromFFI<ffi::PE_AuxiliaryCLRToken> for AuxiliaryCLRToken<'a> {
475 0 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_AuxiliaryCLRToken>) -> Self {
476 0 : Self {
477 0 : ptr,
478 0 : _owner: PhantomData,
479 0 : }
480 0 : }
481 : }
482 :
483 : /// This auxiliary symbols marks the beginning of a function definition.
484 : ///
485 : /// Reference: <https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#auxiliary-format-1-function-definitions>
486 : pub struct AuxiliaryFunctionDefinition<'a> {
487 : ptr: cxx::UniquePtr<ffi::PE_AuxiliaryFunctionDefinition>,
488 : _owner: PhantomData<&'a ffi::PE_Symbol>,
489 : }
490 :
491 : impl<'a> FromFFI<ffi::PE_AuxiliaryFunctionDefinition> for AuxiliaryFunctionDefinition<'a> {
492 1610 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_AuxiliaryFunctionDefinition>) -> Self {
493 1610 : Self {
494 1610 : ptr,
495 1610 : _owner: PhantomData,
496 1610 : }
497 1610 : }
498 : }
499 :
500 : impl std::fmt::Debug for AuxiliaryFunctionDefinition<'_> {
501 1610 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
502 1610 : f.debug_struct("AuxiliaryFunctionDefinition")
503 1610 : .field("tag_index", &self.tag_index())
504 1610 : .field("total_size", &self.total_size())
505 1610 : .field("ptr_to_line_number", &self.ptr_to_line_number())
506 1610 : .field("ptr_to_next_func", &self.ptr_to_next_func())
507 1610 : .field("padding", &self.padding())
508 1610 : .finish()
509 1610 : }
510 : }
511 :
512 : impl AuxiliaryFunctionDefinition<'_> {
513 : /// The symbol-table index of the corresponding `.bf` (begin function)
514 : /// symbol record.
515 1610 : pub fn tag_index(&self) -> u32 {
516 1610 : self.ptr.tag_index()
517 1610 : }
518 :
519 : /// The size of the executable code for the function itself.
520 : ///
521 : /// If the function is in its own section, the `SizeOfRawData` in the section
522 : /// header is greater or equal to this field, depending on alignment considerations.
523 1610 : pub fn total_size(&self) -> u32 {
524 1610 : self.ptr.total_size()
525 1610 : }
526 :
527 : /// The file offset of the first COFF line-number entry for the function,
528 : /// or zero if none exists (deprecated)
529 1610 : pub fn ptr_to_line_number(&self) -> u32 {
530 1610 : self.ptr.ptr_to_line_number()
531 1610 : }
532 :
533 : /// The symbol-table index of the record for the next function. If the function
534 : /// is the last in the symbol table, this field is set to zero.
535 1610 : pub fn ptr_to_next_func(&self) -> u32 {
536 1610 : self.ptr.ptr_to_next_func()
537 1610 : }
538 :
539 : /// Padding value (should be 0)
540 1610 : pub fn padding(&self) -> u16 {
541 1610 : self.ptr.padding()
542 1610 : }
543 :
544 : }
545 :
546 : /// This auxiliary symbol exposes information about the associated section.
547 : ///
548 : /// It **duplicates** some information that are provided in the section header
549 : pub struct AuxiliarySectionDefinition<'a> {
550 : ptr: cxx::UniquePtr<ffi::PE_AuxiliarySectionDefinition>,
551 : _owner: PhantomData<&'a ffi::PE_Symbol>,
552 : }
553 :
554 : impl<'a> FromFFI<ffi::PE_AuxiliarySectionDefinition> for AuxiliarySectionDefinition<'a> {
555 195790 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_AuxiliarySectionDefinition>) -> Self {
556 195790 : Self {
557 195790 : ptr,
558 195790 : _owner: PhantomData,
559 195790 : }
560 195790 : }
561 : }
562 :
563 : impl std::fmt::Debug for AuxiliarySectionDefinition<'_> {
564 195790 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
565 195790 : f.debug_struct("AuxiliarySectionDefinition")
566 195790 : .field("length", &self.length())
567 195790 : .field("nb_relocs", &self.nb_relocs())
568 195790 : .field("nb_line_numbers", &self.nb_line_numbers())
569 195790 : .field("checksum", &self.checksum())
570 195790 : .field("section_idx", &self.section_idx())
571 195790 : .field("selection", &self.selection())
572 195790 : .finish()
573 195790 : }
574 : }
575 :
576 : impl AuxiliarySectionDefinition<'_> {
577 : /// The size of section data. The same as `SizeOfRawData` in the section header.
578 195790 : pub fn length(&self) -> u32 {
579 195790 : self.ptr.length()
580 195790 : }
581 :
582 : /// The number of relocation entries for the section.
583 195790 : pub fn nb_relocs(&self) -> u16 {
584 195790 : self.ptr.nb_relocs()
585 195790 : }
586 :
587 : /// The number of line-number entries for the section.
588 195790 : pub fn nb_line_numbers(&self) -> u16 {
589 195790 : self.ptr.nb_line_numbers()
590 195790 : }
591 :
592 : /// The checksum for communal data. It is applicable if the `IMAGE_SCN_LNK_COMDAT` flag is set
593 : /// in the section header.
594 195790 : pub fn checksum(&self) -> u32 {
595 195790 : self.ptr.checksum()
596 195790 : }
597 :
598 : /// One-based index into the section table for the associated section.
599 : /// This is used when the COMDAT selection setting is 5.
600 195790 : pub fn section_idx(&self) -> u16 {
601 195790 : self.ptr.section_idx()
602 195790 : }
603 :
604 : /// The COMDAT selection number. This is applicable if the section is a
605 : /// COMDAT section.
606 195790 : pub fn selection(&self) -> u8 {
607 195790 : self.ptr.selection()
608 195790 : }
609 : }
610 :
611 :
612 : /// "Weak externals" are a mechanism for object files that allows flexibility at
613 : /// link time. A module can contain an unresolved external symbol (`sym1`), but
614 : /// it can also include an auxiliary record that indicates that if `sym1` is not
615 : /// present at link time, another external symbol (`sym2`) is used to resolve
616 : /// references instead.
617 : ///
618 : /// If a definition of `sym1` is linked, then an external reference to the
619 : /// symbol is resolved normally. If a definition of `sym1` is not linked, then all
620 : /// references to the weak external for `sym1` refer to `sym2` instead. The external
621 : /// symbol, `sym2`, must always be linked; typically, it is defined in the module
622 : /// that contains the weak reference to `sym1`.
623 : ///
624 : /// Reference: <https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#auxiliary-format-3-weak-externals>
625 : pub struct AuxiliaryWeakExternal<'a> {
626 : ptr: cxx::UniquePtr<ffi::PE_AuxiliaryWeakExternal>,
627 : _owner: PhantomData<&'a ffi::PE_Symbol>,
628 : }
629 :
630 :
631 : #[allow(non_camel_case_types)]
632 560 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
633 : pub enum Characteristics {
634 : SEARCH_NOLIBRARY,
635 : SEARCH_LIBRARY,
636 : SEARCH_ALIAS,
637 : ANTI_DEPENDENCY,
638 : UNKNOWN(u32),
639 : }
640 :
641 : impl From<u32> for Characteristics {
642 560 : fn from(value: u32) -> Self {
643 560 : match value {
644 90 : 0x00000001 => Characteristics::SEARCH_NOLIBRARY,
645 0 : 0x00000002 => Characteristics::SEARCH_LIBRARY,
646 0 : 0x00000003 => Characteristics::SEARCH_ALIAS,
647 0 : 0x00000004 => Characteristics::ANTI_DEPENDENCY,
648 470 : _ => Characteristics::UNKNOWN(value),
649 :
650 : }
651 560 : }
652 : }
653 : impl From<Characteristics> for u32 {
654 0 : fn from(value: Characteristics) -> u32 {
655 0 : match value {
656 0 : Characteristics::SEARCH_NOLIBRARY => 0x00000001,
657 0 : Characteristics::SEARCH_LIBRARY => 0x00000002,
658 0 : Characteristics::SEARCH_ALIAS => 0x00000003,
659 0 : Characteristics::ANTI_DEPENDENCY => 0x00000004,
660 0 : Characteristics::UNKNOWN(value) => value,
661 :
662 : }
663 0 : }
664 : }
665 :
666 : impl<'a> FromFFI<ffi::PE_AuxiliaryWeakExternal> for AuxiliaryWeakExternal<'a> {
667 560 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_AuxiliaryWeakExternal>) -> Self {
668 560 : Self {
669 560 : ptr,
670 560 : _owner: PhantomData,
671 560 : }
672 560 : }
673 : }
674 :
675 : impl std::fmt::Debug for AuxiliaryWeakExternal<'_> {
676 560 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
677 560 : f.debug_struct("AuxiliaryWeakExternal")
678 560 : .field("sym_idx", &self.sym_idx())
679 560 : .field("characteristics", &self.characteristics())
680 560 : .finish()
681 560 : }
682 : }
683 :
684 : impl AuxiliaryWeakExternal<'_> {
685 : /// The symbol-table index of `sym2`, the symbol to be linked if `sym1` is not
686 : /// found.
687 560 : pub fn sym_idx(&self) -> u32 {
688 560 : self.ptr.sym_idx()
689 560 : }
690 :
691 560 : pub fn characteristics(&self) -> Characteristics{
692 560 : Characteristics::from(self.ptr.characteristics())
693 560 : }
694 :
695 0 : pub fn padding(&self) -> &[u8] {
696 0 : to_slice!(self.ptr.padding());
697 0 : }
698 : }
699 :
700 :
701 : pub struct AuxiliarySymbol<'a> {
702 : ptr: cxx::UniquePtr<ffi::PE_AuxiliarySymbol>,
703 : _owner: PhantomData<&'a ffi::PE_Symbol>,
704 : }
705 :
706 : impl<'a> FromFFI<ffi::PE_AuxiliarySymbol> for AuxiliarySymbol<'a> {
707 0 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_AuxiliarySymbol>) -> Self {
708 0 : Self {
709 0 : ptr,
710 0 : _owner: PhantomData,
711 0 : }
712 0 : }
713 : }
714 :
715 : impl std::fmt::Debug for AuxiliarySymbol<'_> {
716 0 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
717 0 : f.debug_struct("AuxiliarySymbol")
718 0 : .finish()
719 0 : }
720 : }
721 :
722 : impl AuxiliarySymbol<'_> {
723 : /// Return the raw representation of this symbol
724 0 : pub fn payload(&self) -> &[u8] {
725 0 : to_slice!(self.ptr.payload());
726 0 : }
727 : }
728 :
729 200700 : declare_iterator!(
730 200700 : ItAuxiliarySymbols,
731 200700 : AuxiliarySymbols<'a>,
732 200700 : ffi::PE_AuxiliarySymbol,
733 200700 : ffi::PE_Symbol,
734 200700 : ffi::PE_Symbol_it_auxiliary_symbols
735 200700 : );
|