LCOV - code coverage report
Current view: top level - src/pe - debug.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 37.9 % 570 216
Test Date: 2026-04-12:00:00:00 Functions: 38.0 % 213 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          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 : );
        

Generated by: LCOV version 2.1-1