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