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