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