Line data Source code
1 : //! Module that wraps the different debug information structure we can find in a PE binary.
2 :
3 : use bitflags::bitflags;
4 : use std::marker::PhantomData;
5 :
6 : use crate::common::into_optional;
7 : use crate::declare_iterator;
8 : use crate::{common::FromFFI, to_slice};
9 : use lief_ffi as ffi;
10 : use std::pin::Pin;
11 :
12 : use super::Section;
13 :
14 310 : #[derive(Debug)]
15 : /// This enum exposes the different debug entries that can be
16 : /// found in the debug DataDirectory.
17 : pub enum Entries<'a> {
18 : CodeView(CodeView<'a>),
19 : /// Entry associated with the `IMAGE_DEBUG_TYPE_CODEVIEW`
20 : CodeViewPDB(CodeViewPDB<'a>),
21 : /// Entry associated with `IMAGE_DEBUG_TYPE_REPRO`
22 : Repro(Repro<'a>),
23 : /// Entry associated with `IMAGE_DEBUG_TYPE_POGO`
24 : Pogo(Pogo<'a>),
25 : PDBChecksum(PDBChecksum<'a>),
26 : /// Entry associated with `IMAGE_DEBUG_TYPE_VC_FEATURE`
27 : VCFeature(VCFeature<'a>),
28 : /// Entry associated with `IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS`
29 : ExDllCharacteristics(ExDllCharacteristics<'a>),
30 : /// Entry associated with `IMAGE_DEBUG_TYPE_FPO`
31 : FPO(FPO<'a>),
32 : /// Generic entry for all the other `IMAGE_DEBUG_xxx`
33 : Generic(Generic<'a>),
34 : }
35 :
36 : #[allow(non_camel_case_types)]
37 310 : #[derive(Debug, Copy, Clone)]
38 : pub enum Type {
39 : COFF,
40 : CODEVIEW,
41 : FPO,
42 : MISC,
43 : EXCEPTION,
44 : FIXUP,
45 : OMAP_TO_SRC,
46 : OMAP_FROM_SRC,
47 : BORLAND,
48 : RESERVED10,
49 : CLSID,
50 : VC_FEATURE,
51 : POGO,
52 : ILTCG,
53 : MPX,
54 : REPRO,
55 : PDBCHECKSUM,
56 : EX_DLLCHARACTERISTICS,
57 : UNKNOWN(u32),
58 : }
59 :
60 : impl From<u32> for Type {
61 310 : fn from(value: u32) -> Self {
62 310 : match value {
63 0 : 0x00000001 => Type::COFF,
64 80 : 0x00000002 => Type::CODEVIEW,
65 0 : 0x00000003 => Type::FPO,
66 0 : 0x00000004 => Type::MISC,
67 0 : 0x00000005 => Type::EXCEPTION,
68 0 : 0x00000006 => Type::FIXUP,
69 0 : 0x00000007 => Type::OMAP_TO_SRC,
70 0 : 0x00000008 => Type::OMAP_FROM_SRC,
71 0 : 0x00000009 => Type::BORLAND,
72 10 : 0x0000000a => Type::RESERVED10,
73 0 : 0x0000000b => Type::CLSID,
74 30 : 0x0000000c => Type::VC_FEATURE,
75 90 : 0x0000000d => Type::POGO,
76 10 : 0x0000000e => Type::ILTCG,
77 0 : 0x0000000f => Type::MPX,
78 50 : 0x00000010 => Type::REPRO,
79 0 : 0x00000013 => Type::PDBCHECKSUM,
80 40 : 0x00000014 => Type::EX_DLLCHARACTERISTICS,
81 0 : _ => Type::UNKNOWN(value),
82 : }
83 310 : }
84 : }
85 :
86 : pub trait DebugEntry {
87 : #[doc(hidden)]
88 : fn get_base(&self) -> &ffi::PE_Debug;
89 :
90 : #[doc(hidden)]
91 : fn get_base_mut(&mut self) -> Pin<&mut ffi::PE_Debug>;
92 :
93 : /// Reserved should be 0
94 310 : fn characteristics(&self) -> u32 {
95 310 : self.get_base().characteristics()
96 310 : }
97 :
98 : /// The time and date when the debug data was created.
99 310 : fn timestamp(&self) -> u32 {
100 310 : self.get_base().timestamp()
101 310 : }
102 :
103 : /// The major version number of the debug data format.
104 310 : fn major_version(&self) -> u16 {
105 310 : self.get_base().major_version()
106 310 : }
107 :
108 : /// The minor version number of the debug data format.
109 310 : fn minor_version(&self) -> u16 {
110 310 : self.get_base().minor_version()
111 310 : }
112 :
113 : /// The format of the debugging information
114 310 : fn get_type(&self) -> Type {
115 310 : Type::from(self.get_base().get_type())
116 310 : }
117 :
118 : /// Size of the debug data
119 310 : fn sizeof_data(&self) -> u32 {
120 310 : self.get_base().sizeof_data()
121 310 : }
122 :
123 : /// Address of the debug data relative to the image base
124 310 : fn addressof_rawdata(&self) -> u32 {
125 310 : self.get_base().addressof_rawdata()
126 310 : }
127 :
128 : /// File offset of the debug data
129 310 : fn pointerto_rawdata(&self) -> u32 {
130 310 : self.get_base().pointerto_rawdata()
131 310 : }
132 :
133 : /// The section where debug data is located
134 0 : fn section(&self) -> Option<Section> {
135 0 : into_optional(self.get_base().section())
136 0 : }
137 :
138 : /// Debug data associated with this entry
139 0 : fn payload(&self) -> &[u8] {
140 0 : to_slice!(self.get_base().payload());
141 0 : }
142 : }
143 :
144 : impl DebugEntry for Entries<'_> {
145 0 : fn get_base(&self) -> &ffi::PE_Debug {
146 0 : match &self {
147 0 : Entries::CodeView(entry) => {
148 0 : entry.get_base()
149 : }
150 :
151 0 : Entries::CodeViewPDB(entry) => {
152 0 : entry.get_base()
153 : }
154 :
155 0 : Entries::Repro(entry) => {
156 0 : entry.get_base()
157 : }
158 :
159 0 : Entries::Pogo(entry) => {
160 0 : entry.get_base()
161 : }
162 :
163 0 : Entries::PDBChecksum(entry) => {
164 0 : entry.get_base()
165 : }
166 :
167 0 : Entries::VCFeature(entry) => {
168 0 : entry.get_base()
169 : }
170 :
171 0 : Entries::ExDllCharacteristics(entry) => {
172 0 : entry.get_base()
173 : }
174 :
175 0 : Entries::FPO(entry) => {
176 0 : entry.get_base()
177 : }
178 :
179 0 : Entries::Generic(entry) => {
180 0 : entry.get_base()
181 : }
182 : }
183 0 : }
184 :
185 0 : fn get_base_mut(&mut self) -> Pin<&mut ffi::PE_Debug> {
186 0 : match self {
187 0 : Entries::CodeView(entry) => {
188 0 : entry.get_base_mut()
189 : }
190 :
191 0 : Entries::CodeViewPDB(entry) => {
192 0 : entry.get_base_mut()
193 : }
194 :
195 0 : Entries::Repro(entry) => {
196 0 : entry.get_base_mut()
197 : }
198 :
199 0 : Entries::Pogo(entry) => {
200 0 : entry.get_base_mut()
201 : }
202 :
203 0 : Entries::PDBChecksum(entry) => {
204 0 : entry.get_base_mut()
205 : }
206 :
207 0 : Entries::VCFeature(entry) => {
208 0 : entry.get_base_mut()
209 : }
210 :
211 0 : Entries::ExDllCharacteristics(entry) => {
212 0 : entry.get_base_mut()
213 : }
214 :
215 0 : Entries::FPO(entry) => {
216 0 : entry.get_base_mut()
217 : }
218 :
219 0 : Entries::Generic(entry) => {
220 0 : entry.get_base_mut()
221 : }
222 : }
223 0 : }
224 : }
225 :
226 : impl std::fmt::Debug for &dyn DebugEntry {
227 310 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
228 310 : f.debug_struct("DebugEntry")
229 310 : .field("characteristics", &self.characteristics())
230 310 : .field("timestamp", &self.timestamp())
231 310 : .field("major_version", &self.major_version())
232 310 : .field("minor_version", &self.minor_version())
233 310 : .field("type", &self.get_type())
234 310 : .field("sizeof_data", &self.sizeof_data())
235 310 : .field("addressof_rawdata", &self.addressof_rawdata())
236 310 : .field("pointerto_rawdata", &self.pointerto_rawdata())
237 310 : .finish()
238 310 : }
239 : }
240 :
241 : impl<'a> FromFFI<ffi::PE_Debug> for Entries<'a> {
242 310 : fn from_ffi(ffi_entry: cxx::UniquePtr<ffi::PE_Debug>) -> Self {
243 310 : unsafe {
244 310 : let debug_ref = ffi_entry.as_ref().unwrap();
245 310 : if ffi::PE_Pogo::classof(debug_ref) {
246 90 : let raw = {
247 90 : type From = cxx::UniquePtr<ffi::PE_Debug>;
248 90 : type To = cxx::UniquePtr<ffi::PE_Pogo>;
249 90 : std::mem::transmute::<From, To>(ffi_entry)
250 90 : };
251 90 : Entries::Pogo(Pogo::from_ffi(raw))
252 220 : } else if ffi::PE_CodeViewPDB::classof(debug_ref) {
253 80 : let raw = {
254 80 : type From = cxx::UniquePtr<ffi::PE_Debug>;
255 80 : type To = cxx::UniquePtr<ffi::PE_CodeViewPDB>;
256 80 : std::mem::transmute::<From, To>(ffi_entry)
257 80 : };
258 80 : Entries::CodeViewPDB(CodeViewPDB::from_ffi(raw))
259 140 : } else if ffi::PE_Repro::classof(debug_ref) {
260 50 : let raw = {
261 50 : type From = cxx::UniquePtr<ffi::PE_Debug>;
262 50 : type To = cxx::UniquePtr<ffi::PE_Repro>;
263 50 : std::mem::transmute::<From, To>(ffi_entry)
264 50 : };
265 50 : Entries::Repro(Repro::from_ffi(raw))
266 90 : } else if ffi::PE_CodeView::classof(debug_ref) {
267 0 : let raw = {
268 0 : type From = cxx::UniquePtr<ffi::PE_Debug>;
269 0 : type To = cxx::UniquePtr<ffi::PE_CodeView>;
270 0 : std::mem::transmute::<From, To>(ffi_entry)
271 0 : };
272 0 : Entries::CodeView(CodeView::from_ffi(raw))
273 90 : } else if ffi::PE_PDBChecksum::classof(debug_ref) {
274 0 : let raw = {
275 0 : type From = cxx::UniquePtr<ffi::PE_Debug>;
276 0 : type To = cxx::UniquePtr<ffi::PE_PDBChecksum>;
277 0 : std::mem::transmute::<From, To>(ffi_entry)
278 0 : };
279 0 : Entries::PDBChecksum(PDBChecksum::from_ffi(raw))
280 90 : } else if ffi::PE_VCFeature::classof(debug_ref) {
281 30 : let raw = {
282 30 : type From = cxx::UniquePtr<ffi::PE_Debug>;
283 30 : type To = cxx::UniquePtr<ffi::PE_VCFeature>;
284 30 : std::mem::transmute::<From, To>(ffi_entry)
285 30 : };
286 30 : Entries::VCFeature(VCFeature::from_ffi(raw))
287 60 : } else if ffi::PE_ExDllCharacteristics::classof(debug_ref) {
288 40 : let raw = {
289 40 : type From = cxx::UniquePtr<ffi::PE_Debug>;
290 40 : type To = cxx::UniquePtr<ffi::PE_ExDllCharacteristics>;
291 40 : std::mem::transmute::<From, To>(ffi_entry)
292 40 : };
293 40 : Entries::ExDllCharacteristics(ExDllCharacteristics::from_ffi(raw))
294 20 : } else if ffi::PE_FPO::classof(debug_ref) {
295 0 : let raw = {
296 0 : type From = cxx::UniquePtr<ffi::PE_Debug>;
297 0 : type To = cxx::UniquePtr<ffi::PE_FPO>;
298 0 : std::mem::transmute::<From, To>(ffi_entry)
299 0 : };
300 0 : Entries::FPO(FPO::from_ffi(raw))
301 : } else {
302 20 : Entries::Generic(Generic::from_ffi(ffi_entry))
303 : }
304 : }
305 310 : }
306 : }
307 :
308 : pub struct Generic<'a> {
309 : ptr: cxx::UniquePtr<ffi::PE_Debug>,
310 : _owner: PhantomData<&'a ffi::PE_Binary>,
311 : }
312 :
313 : impl<'a> FromFFI<ffi::PE_Debug> for Generic<'a> {
314 20 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_Debug>) -> Self {
315 20 : Self {
316 20 : ptr,
317 20 : _owner: PhantomData,
318 20 : }
319 20 : }
320 : }
321 :
322 : impl DebugEntry for Generic<'_> {
323 160 : fn get_base(&self) -> &ffi::PE_Debug {
324 160 : self.ptr.as_ref().unwrap()
325 160 : }
326 :
327 0 : fn get_base_mut(&mut self) -> Pin<&mut ffi::PE_Debug> {
328 0 : unsafe {
329 0 : Pin::new_unchecked({
330 0 : (self.ptr.as_ref().unwrap()
331 0 : as *const ffi::PE_Debug
332 0 : as *mut ffi::PE_Debug).as_mut().unwrap()
333 0 : })
334 0 : }
335 0 : }
336 : }
337 :
338 : impl std::fmt::Debug for Generic<'_> {
339 20 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
340 20 : let base = self as &dyn DebugEntry;
341 20 : f.debug_struct("Generic").field("base", &base).finish()
342 20 : }
343 : }
344 :
345 : /// This structure represents a *Profile Guided Optimization* entry from the
346 : /// debug directory (`IMAGE_DEBUG_TYPE_POGO`).
347 : pub struct Pogo<'a> {
348 : ptr: cxx::UniquePtr<ffi::PE_Pogo>,
349 : _owner: PhantomData<&'a ffi::PE_Binary>,
350 : }
351 :
352 : impl Pogo<'_> {
353 : /// An iterator over the different POGO elements: [`PogoEntry`]
354 90 : pub fn entries(&self) -> PogoEntries {
355 90 : PogoEntries::new(self.ptr.entries())
356 90 : }
357 : }
358 :
359 : impl<'a> FromFFI<ffi::PE_Pogo> for Pogo<'a> {
360 90 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_Pogo>) -> Self {
361 90 : Self {
362 90 : ptr,
363 90 : _owner: PhantomData,
364 90 : }
365 90 : }
366 : }
367 :
368 : impl DebugEntry for Pogo<'_> {
369 720 : fn get_base(&self) -> &ffi::PE_Debug {
370 720 : self.ptr.as_ref().unwrap().as_ref()
371 720 : }
372 :
373 0 : fn get_base_mut(&mut self) -> Pin<&mut ffi::PE_Debug> {
374 0 : unsafe {
375 0 : Pin::new_unchecked({
376 0 : (self.ptr.as_ref().unwrap().as_ref()
377 0 : as *const ffi::PE_Debug
378 0 : as *mut ffi::PE_Debug).as_mut().unwrap()
379 0 : })
380 0 : }
381 0 : }
382 : }
383 :
384 : impl std::fmt::Debug for Pogo<'_> {
385 90 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
386 90 : let base = self as &dyn DebugEntry;
387 90 : f.debug_struct("Pogo").field("base", &base).finish()
388 90 : }
389 : }
390 :
391 : /// Structure which reprents an entry in the [`Pogo`] debug structure
392 : pub struct PogoEntry<'a> {
393 : ptr: cxx::UniquePtr<ffi::PE_PogoEntry>,
394 : _owner: PhantomData<&'a ffi::PE_Pogo>,
395 : }
396 :
397 : impl<'a> FromFFI<ffi::PE_PogoEntry> for PogoEntry<'a> {
398 6870 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_PogoEntry>) -> Self {
399 6870 : Self {
400 6870 : ptr,
401 6870 : _owner: PhantomData,
402 6870 : }
403 6870 : }
404 : }
405 :
406 : impl PogoEntry<'_> {
407 6870 : pub fn start_rva(&self) -> u32 {
408 6870 : self.ptr.start_rva()
409 6870 : }
410 6870 : pub fn size(&self) -> u32 {
411 6870 : self.ptr.size()
412 6870 : }
413 6870 : pub fn name(&self) -> String {
414 6870 : self.ptr.name().to_string()
415 6870 : }
416 : }
417 :
418 : impl std::fmt::Debug for PogoEntry<'_> {
419 6870 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
420 6870 : f.debug_struct("PogoEntry")
421 6870 : .field("name", &self.name())
422 6870 : .field("size", &self.size())
423 6870 : .field("start_rva", &self.start_rva())
424 6870 : .finish()
425 6870 : }
426 : }
427 :
428 : /// Structure that represents the (generic) Debug CodeView (`IMAGE_DEBUG_TYPE_CODEVIEW`).
429 : pub struct CodeView<'a> {
430 : ptr: cxx::UniquePtr<ffi::PE_CodeView>,
431 : _owner: PhantomData<&'a ffi::PE_Binary>,
432 : }
433 :
434 : impl<'a> FromFFI<ffi::PE_CodeView> for CodeView<'a> {
435 0 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_CodeView>) -> Self {
436 0 : Self {
437 0 : ptr,
438 0 : _owner: PhantomData,
439 0 : }
440 0 : }
441 : }
442 :
443 : impl DebugEntry for CodeView<'_> {
444 0 : fn get_base(&self) -> &ffi::PE_Debug {
445 0 : self.ptr.as_ref().unwrap().as_ref()
446 0 : }
447 :
448 0 : fn get_base_mut(&mut self) -> Pin<&mut ffi::PE_Debug> {
449 0 : unsafe {
450 0 : Pin::new_unchecked({
451 0 : (self.ptr.as_ref().unwrap().as_ref()
452 0 : as *const ffi::PE_Debug
453 0 : as *mut ffi::PE_Debug).as_mut().unwrap()
454 0 : })
455 0 : }
456 0 : }
457 : }
458 :
459 : impl std::fmt::Debug for CodeView<'_> {
460 0 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
461 0 : f.debug_struct("CodeView").finish()
462 0 : }
463 : }
464 :
465 : /// CodeView PDB specialization
466 : pub struct CodeViewPDB<'a> {
467 : ptr: cxx::UniquePtr<ffi::PE_CodeViewPDB>,
468 : _owner: PhantomData<&'a ffi::PE_Binary>,
469 : }
470 :
471 : impl<'a> FromFFI<ffi::PE_CodeViewPDB> for CodeViewPDB<'a> {
472 80 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_CodeViewPDB>) -> Self {
473 80 : Self {
474 80 : ptr,
475 80 : _owner: PhantomData,
476 80 : }
477 80 : }
478 : }
479 :
480 : /// CodeView PDB specialization
481 : impl CodeViewPDB<'_> {
482 0 : pub fn new() -> CodeViewPDB<'static> {
483 0 : CodeViewPDB::from_ffi(ffi::PE_CodeViewPDB::create())
484 0 : }
485 :
486 0 : pub fn with_filename(filename: &str) -> CodeViewPDB<'static> {
487 0 : CodeViewPDB::from_ffi(ffi::PE_CodeViewPDB::create_with_filename(filename))
488 0 : }
489 :
490 : /// Age value to verify. The age does not necessarily correspond to any known
491 : /// time value, it is used to determine if a .pdb file is out of sync with a corresponding
492 : /// `.exe` file.
493 80 : pub fn age(&self) -> u32 {
494 80 : self.ptr.age()
495 80 : }
496 :
497 : /// The path to the `.pdb` file
498 80 : pub fn filename(&self) -> String {
499 80 : self.ptr.filename().to_string()
500 80 : }
501 :
502 : /// The GUID signature to verify against the .pdb file signature.
503 : /// This attribute might be used to lookup remote PDB file on a symbol server.
504 0 : pub fn guid(&self) -> String {
505 0 : self.ptr.guid().to_string()
506 0 : }
507 :
508 : /// The 32-bit signature to verify against the .pdb file signature.
509 0 : pub fn signature(&self) -> [u8; 16] {
510 0 : let vector: Vec<u8> = self.ptr.signature().iter().map(|&e| e as u8).collect();
511 0 : vector.try_into().expect("Wrong size")
512 0 : }
513 :
514 : /// Change or set the PDB filename
515 0 : pub fn set_filename(&mut self, filename: &str) -> &mut Self {
516 0 : self.ptr.pin_mut().set_filename(filename);
517 0 : self
518 0 : }
519 :
520 0 : pub fn set_age(&mut self, age: u32) -> &mut Self {
521 0 : self.ptr.pin_mut().set_age(age);
522 0 : self
523 0 : }
524 :
525 0 : pub fn set_signature(&mut self, signature: &[u8; 16]) -> &mut Self {
526 0 : unsafe {
527 0 : self.ptr.pin_mut().set_signature(signature.as_ptr(), signature.len());
528 0 : }
529 0 : self
530 0 : }
531 : }
532 :
533 : impl DebugEntry for CodeViewPDB<'_> {
534 640 : fn get_base(&self) -> &ffi::PE_Debug {
535 640 : self.ptr.as_ref().unwrap().as_ref().as_ref()
536 640 : }
537 :
538 0 : fn get_base_mut(&mut self) -> Pin<&mut ffi::PE_Debug> {
539 0 : unsafe {
540 0 : Pin::new_unchecked({
541 0 : (self.ptr.as_ref().unwrap().as_ref().as_ref()
542 0 : as *const ffi::PE_Debug
543 0 : as *mut ffi::PE_Debug).as_mut().unwrap()
544 0 : })
545 0 : }
546 0 : }
547 : }
548 :
549 : impl std::fmt::Debug for CodeViewPDB<'_> {
550 80 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
551 80 : let base = self as &dyn DebugEntry;
552 80 : f.debug_struct("CodeViewPDB")
553 80 : .field("base", &base)
554 80 : .field("age", &self.age())
555 80 : .field("filename", &self.filename())
556 80 : .finish()
557 80 : }
558 : }
559 :
560 : /// This structure represents a reproducible build entry from the debug directory
561 : /// (`IMAGE_DEBUG_TYPE_REPRO`)
562 : ///
563 : /// This entry is usually generated with the undocumented `/Brepro` linker flag.
564 : /// See: <https://nikhilism.com/post/2020/windows-deterministic-builds/>
565 : pub struct Repro<'a> {
566 : ptr: cxx::UniquePtr<ffi::PE_Repro>,
567 : _owner: PhantomData<&'a ffi::PE_Binary>,
568 : }
569 :
570 : impl<'a> FromFFI<ffi::PE_Repro> for Repro<'a> {
571 50 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_Repro>) -> Self {
572 50 : Self {
573 50 : ptr,
574 50 : _owner: PhantomData,
575 50 : }
576 50 : }
577 : }
578 :
579 : impl Repro<'_> {
580 : /// The hash associated with the reproducible build
581 50 : pub fn hash(&self) -> &[u8] {
582 50 : to_slice!(self.ptr.hash());
583 50 : }
584 : }
585 :
586 : impl DebugEntry for Repro<'_> {
587 400 : fn get_base(&self) -> &ffi::PE_Debug {
588 400 : self.ptr.as_ref().unwrap().as_ref()
589 400 : }
590 :
591 0 : fn get_base_mut(&mut self) -> Pin<&mut ffi::PE_Debug> {
592 0 : unsafe {
593 0 : Pin::new_unchecked({
594 0 : (self.ptr.as_ref().unwrap().as_ref()
595 0 : as *const ffi::PE_Debug
596 0 : as *mut ffi::PE_Debug).as_mut().unwrap()
597 0 : })
598 0 : }
599 0 : }
600 : }
601 :
602 : impl std::fmt::Debug for Repro<'_> {
603 50 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
604 50 : let base = self as &dyn DebugEntry;
605 50 : f.debug_struct("Repro").field("base", &base).finish()
606 50 : }
607 : }
608 :
609 6870 : declare_iterator!(
610 6870 : PogoEntries,
611 6870 : PogoEntry<'a>,
612 6870 : ffi::PE_PogoEntry,
613 6870 : ffi::PE_Pogo,
614 6870 : ffi::PE_Pogo_it_entries
615 6870 : );
616 :
617 : /// This structure represents the PDB Checksum debug entry which is essentially
618 : /// an array of bytes representing the checksum of the PDB content.
619 : pub struct PDBChecksum<'a> {
620 : ptr: cxx::UniquePtr<ffi::PE_PDBChecksum>,
621 : _owner: PhantomData<&'a ffi::PE_Binary>,
622 : }
623 :
624 : impl<'a> FromFFI<ffi::PE_PDBChecksum> for PDBChecksum<'a> {
625 0 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_PDBChecksum>) -> Self {
626 0 : Self {
627 0 : ptr,
628 0 : _owner: PhantomData,
629 0 : }
630 0 : }
631 : }
632 :
633 : #[allow(non_camel_case_types)]
634 0 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
635 : pub enum ChecksumAlgorithm {
636 : SHA256,
637 : UNKNOWN(u32),
638 : }
639 :
640 : impl From<u32> for ChecksumAlgorithm {
641 0 : fn from(value: u32) -> Self {
642 0 : match value {
643 0 : 0x00000001 => ChecksumAlgorithm::SHA256,
644 0 : _ => ChecksumAlgorithm::UNKNOWN(value),
645 :
646 : }
647 0 : }
648 : }
649 : impl From<ChecksumAlgorithm> for u32 {
650 0 : fn from(value: ChecksumAlgorithm) -> u32 {
651 0 : match value {
652 0 : ChecksumAlgorithm::SHA256 => 0x00000001,
653 0 : ChecksumAlgorithm::UNKNOWN(value) => value,
654 :
655 : }
656 0 : }
657 : }
658 :
659 : impl PDBChecksum<'_> {
660 : /// Hash of the PDB content
661 0 : pub fn hash(&self) -> &[u8] {
662 0 : to_slice!(self.ptr.hash());
663 0 : }
664 :
665 : /// Algorithm used for hashing the PDB content
666 0 : pub fn algorithm(&self) -> ChecksumAlgorithm {
667 0 : ChecksumAlgorithm::from(self.ptr.algo())
668 0 : }
669 : }
670 :
671 : impl std::fmt::Debug for PDBChecksum<'_> {
672 0 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
673 0 : let base = self as &dyn DebugEntry;
674 0 : f.debug_struct("PDBChecksum").field("base", &base).finish()
675 0 : }
676 : }
677 :
678 : impl DebugEntry for PDBChecksum<'_> {
679 0 : fn get_base(&self) -> &ffi::PE_Debug {
680 0 : self.ptr.as_ref().unwrap().as_ref()
681 0 : }
682 :
683 0 : fn get_base_mut(&mut self) -> Pin<&mut ffi::PE_Debug> {
684 0 : unsafe {
685 0 : Pin::new_unchecked({
686 0 : (self.ptr.as_ref().unwrap().as_ref()
687 0 : as *const ffi::PE_Debug
688 0 : as *mut ffi::PE_Debug).as_mut().unwrap()
689 0 : })
690 0 : }
691 0 : }
692 : }
693 :
694 :
695 :
696 : /// This structure represents the `IMAGE_DEBUG_TYPE_VC_FEATURE` debug entry
697 : pub struct VCFeature<'a> {
698 : ptr: cxx::UniquePtr<ffi::PE_VCFeature>,
699 : _owner: PhantomData<&'a ffi::PE_Binary>,
700 : }
701 :
702 : impl<'a> FromFFI<ffi::PE_VCFeature> for VCFeature<'a> {
703 30 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_VCFeature>) -> Self {
704 30 : Self {
705 30 : ptr,
706 30 : _owner: PhantomData,
707 30 : }
708 30 : }
709 : }
710 :
711 : impl VCFeature<'_> {
712 : /// Count for `Pre-VC++ 11.00`
713 0 : pub fn pre_vcpp(&self) -> u32 {
714 0 : self.ptr.pre_vcpp()
715 0 : }
716 :
717 : /// Count for `C/C++`
718 0 : pub fn c_cpp(&self) -> u32 {
719 0 : self.ptr.c_cpp()
720 0 : }
721 :
722 : /// Count for `/GS` (number of guard stack)
723 0 : pub fn gs(&self) -> u32 {
724 0 : self.ptr.gs()
725 0 : }
726 :
727 : /// Whether `/sdl` was enabled for this binary.
728 : ///
729 : /// `sdl` stands for Security Development Lifecycle and provides enhanced
730 : /// security features like changing security-relevant warnings into errors or
731 : /// enforcing guard stack.
732 0 : pub fn sdl(&self) -> u32 {
733 0 : self.ptr.sdl()
734 0 : }
735 :
736 : /// Count for `/guardN`
737 0 : pub fn guards(&self) -> u32 {
738 0 : self.ptr.guards()
739 0 : }
740 : }
741 :
742 : impl DebugEntry for VCFeature<'_> {
743 240 : fn get_base(&self) -> &ffi::PE_Debug {
744 240 : self.ptr.as_ref().unwrap().as_ref()
745 240 : }
746 :
747 0 : fn get_base_mut(&mut self) -> Pin<&mut ffi::PE_Debug> {
748 0 : unsafe {
749 0 : Pin::new_unchecked({
750 0 : (self.ptr.as_ref().unwrap().as_ref()
751 0 : as *const ffi::PE_Debug
752 0 : as *mut ffi::PE_Debug).as_mut().unwrap()
753 0 : })
754 0 : }
755 0 : }
756 : }
757 :
758 : impl std::fmt::Debug for VCFeature<'_> {
759 30 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
760 30 : let base = self as &dyn DebugEntry;
761 30 : f.debug_struct("VCFeature").field("base", &base).finish()
762 30 : }
763 : }
764 :
765 : /// This structure represents the `IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS` debug entry
766 : pub struct ExDllCharacteristics<'a> {
767 : ptr: cxx::UniquePtr<ffi::PE_ExDllCharacteristics>,
768 : _owner: PhantomData<&'a ffi::PE_Binary>,
769 : }
770 :
771 : impl<'a> FromFFI<ffi::PE_ExDllCharacteristics> for ExDllCharacteristics<'a> {
772 40 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ExDllCharacteristics>) -> Self {
773 40 : Self {
774 40 : ptr,
775 40 : _owner: PhantomData,
776 40 : }
777 40 : }
778 : }
779 :
780 :
781 0 : bitflags! {
782 0 : #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
783 0 : pub struct ExtendedDLLCharacteristics: u32 {
784 0 : const CET_COMPAT = 0x1;
785 0 : const CET_COMPAT_STRICT_MODE = 0x2;
786 0 : const CET_SET_CONTEXT_IP_VALIDATION_RELAXED_MODE = 0x4;
787 0 : const CET_DYNAMIC_APIS_ALLOW_IN_PROC = 0x8;
788 0 : const CET_RESERVED_1 = 0x10;
789 0 : const CET_RESERVED_2 = 0x20;
790 0 : const FORWARD_CFI_COMPAT = 0x40;
791 0 : const HOTPATCH_COMPATIBLE = 0x80;
792 0 : }
793 0 : }
794 :
795 : impl From<u32> for ExtendedDLLCharacteristics {
796 0 : fn from(value: u32) -> Self {
797 0 : ExtendedDLLCharacteristics::from_bits_truncate(value)
798 0 : }
799 : }
800 :
801 : impl From<ExtendedDLLCharacteristics> for u32 {
802 0 : fn from(value: ExtendedDLLCharacteristics) -> Self {
803 0 : value.bits()
804 0 : }
805 : }
806 :
807 : impl std::fmt::Display for ExtendedDLLCharacteristics {
808 0 : fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
809 0 : bitflags::parser::to_writer(self, f)
810 0 : }
811 : }
812 :
813 : impl ExDllCharacteristics<'_> {
814 0 : pub fn characteristics(&self) -> ExtendedDLLCharacteristics {
815 0 : ExtendedDLLCharacteristics::from(self.ptr.characteristics())
816 0 : }
817 : }
818 :
819 : impl DebugEntry for ExDllCharacteristics<'_> {
820 320 : fn get_base(&self) -> &ffi::PE_Debug {
821 320 : self.ptr.as_ref().unwrap().as_ref()
822 320 : }
823 :
824 0 : fn get_base_mut(&mut self) -> Pin<&mut ffi::PE_Debug> {
825 0 : unsafe {
826 0 : Pin::new_unchecked({
827 0 : (self.ptr.as_ref().unwrap().as_ref()
828 0 : as *const ffi::PE_Debug
829 0 : as *mut ffi::PE_Debug).as_mut().unwrap()
830 0 : })
831 0 : }
832 0 : }
833 : }
834 :
835 : impl std::fmt::Debug for ExDllCharacteristics<'_> {
836 40 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
837 40 : let base = self as &dyn DebugEntry;
838 40 : f.debug_struct("ExDllCharacteristics").field("base", &base).finish()
839 40 : }
840 : }
841 :
842 : /// This structure represents the `IMAGE_DEBUG_TYPE_FPO` debug entry
843 : pub struct FPO<'a> {
844 : ptr: cxx::UniquePtr<ffi::PE_FPO>,
845 : _owner: PhantomData<&'a ffi::PE_Binary>,
846 : }
847 :
848 : impl FPO<'_> {
849 0 : pub fn entries(&self) -> FPOEntries {
850 0 : FPOEntries::new(self.ptr.entries())
851 0 : }
852 : }
853 :
854 : impl<'a> FromFFI<ffi::PE_FPO> for FPO<'a> {
855 0 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_FPO>) -> Self {
856 0 : Self {
857 0 : ptr,
858 0 : _owner: PhantomData,
859 0 : }
860 0 : }
861 : }
862 :
863 : impl DebugEntry for FPO<'_> {
864 0 : fn get_base(&self) -> &ffi::PE_Debug {
865 0 : self.ptr.as_ref().unwrap().as_ref()
866 0 : }
867 :
868 0 : fn get_base_mut(&mut self) -> Pin<&mut ffi::PE_Debug> {
869 0 : unsafe {
870 0 : Pin::new_unchecked({
871 0 : (self.ptr.as_ref().unwrap().as_ref()
872 0 : as *const ffi::PE_Debug
873 0 : as *mut ffi::PE_Debug).as_mut().unwrap()
874 0 : })
875 0 : }
876 0 : }
877 : }
878 :
879 : impl std::fmt::Debug for FPO<'_> {
880 0 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
881 0 : let base = self as &dyn DebugEntry;
882 0 : f.debug_struct("FPO").field("base", &base).finish()
883 0 : }
884 : }
885 :
886 : /// This structure represents the stack frame layout for a x86 function when frame pointer
887 : /// omission (FPO) optimization is used.
888 : pub struct FPOEntry<'a> {
889 : ptr: cxx::UniquePtr<ffi::PE_FPO_entry_t>,
890 : _owner: PhantomData<&'a ffi::PE_FPO>,
891 : }
892 :
893 : impl FPOEntry<'_> {
894 : /// The function RVA
895 0 : pub fn rva(&self) -> u32 {
896 0 : self.ptr.rva()
897 0 : }
898 :
899 : /// The number of bytes in the function.
900 0 : pub fn proc_size(&self) -> u32 {
901 0 : self.ptr.proc_size()
902 0 : }
903 :
904 : /// The number of local variables.
905 0 : pub fn nb_locals(&self) -> u32 {
906 0 : self.ptr.nb_locals()
907 0 : }
908 :
909 : /// The size of the parameters
910 0 : pub fn parameters_size(&self) -> u32 {
911 0 : self.ptr.parameters_size()
912 0 : }
913 :
914 : /// The number of bytes in the function prolog code.
915 0 : pub fn prolog_size(&self) -> u16 {
916 0 : self.ptr.prolog_size()
917 0 : }
918 :
919 : /// Number of registers saved
920 0 : pub fn nb_saved_regs(&self) -> u16 {
921 0 : self.ptr.nb_saved_regs()
922 0 : }
923 :
924 : /// Whether the function uses structured exception handling.
925 0 : pub fn use_seh(&self) -> bool {
926 0 : self.ptr.use_seh()
927 0 : }
928 :
929 : /// Whether the EBP register has been allocated.
930 0 : pub fn use_bp(&self) -> bool {
931 0 : self.ptr.use_bp()
932 0 : }
933 :
934 : /// Reserved for future use
935 0 : pub fn reserved(&self) -> u16 {
936 0 : self.ptr.reserved()
937 0 : }
938 :
939 : /// Variable that indicates the frame type.
940 0 : pub fn frame_type(&self) -> u32 {
941 0 : self.ptr.get_type()
942 0 : }
943 : }
944 :
945 : impl<'a> FromFFI<ffi::PE_FPO_entry_t> for FPOEntry<'a> {
946 0 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_FPO_entry_t>) -> Self {
947 0 : Self {
948 0 : ptr,
949 0 : _owner: PhantomData,
950 0 : }
951 0 : }
952 : }
953 :
954 0 : declare_iterator!(
955 0 : FPOEntries,
956 0 : FPOEntry<'a>,
957 0 : ffi::PE_FPO_entry_t,
958 0 : ffi::PE_FPO,
959 0 : ffi::PE_FPO_it_entries
960 0 : );
|