LCOV - code coverage report
Current view: top level - src/pe - debug.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 39.6 % 541 214
Test Date: 2025-02-23:00:00:00 Functions: 42.9 % 189 81

            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 : );
        

Generated by: LCOV version 2.1-1