LCOV - code coverage report
Current view: top level - src/pe - headers.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 55.7 % 515 287
Test Date: 2025-02-23:00:00:00 Functions: 67.6 % 105 71

            Line data    Source code
       1              : //! This module exposes the different headers that we can find in a PE binary.
       2              : //! It includes:
       3              : //! - [`DosHeader`]
       4              : //! - [`Header`]
       5              : //! - [`OptionalHeader`]
       6              : 
       7              : use bitflags::bitflags;
       8              : use std::marker::PhantomData;
       9              : 
      10              : use crate::common::FromFFI;
      11              : use lief_ffi as ffi;
      12              : 
      13              : /// Structure which represents the DosHeader, the **first** structure presents at the beginning of
      14              : /// a PE file.
      15              : ///
      16              : /// Most of the attributes of this structures are no longer relevant
      17              : pub struct DosHeader<'a> {
      18              :     ptr: cxx::UniquePtr<ffi::PE_DosHeader>,
      19              :     _owner: PhantomData<&'a ffi::PE_Binary>,
      20              : }
      21              : 
      22              : impl FromFFI<ffi::PE_DosHeader> for DosHeader<'_> {
      23          130 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_DosHeader>) -> Self {
      24          130 :         Self {
      25          130 :             ptr,
      26          130 :             _owner: PhantomData,
      27          130 :         }
      28          130 :     }
      29              : }
      30              : 
      31              : impl<'a> DosHeader<'a> {
      32              :     /// Magic bytes identifying a DOS/PE binary
      33          130 :     pub fn magic(&self) -> u16 {
      34          130 :         self.ptr.magic()
      35          130 :     }
      36              : 
      37          130 :     pub fn used_bytes_in_last_page(&self) -> u16 {
      38          130 :         self.ptr.used_bytes_in_last_page()
      39          130 :     }
      40              : 
      41          130 :     pub fn file_size_in_pages(&self) -> u16 {
      42          130 :         self.ptr.file_size_in_pages()
      43          130 :     }
      44              : 
      45          130 :     pub fn numberof_relocation(&self) -> u16 {
      46          130 :         self.ptr.numberof_relocation()
      47          130 :     }
      48              : 
      49          130 :     pub fn header_size_in_paragraphs(&self) -> u16 {
      50          130 :         self.ptr.header_size_in_paragraphs()
      51          130 :     }
      52              : 
      53          130 :     pub fn minimum_extra_paragraphs(&self) -> u16 {
      54          130 :         self.ptr.minimum_extra_paragraphs()
      55          130 :     }
      56              : 
      57          130 :     pub fn maximum_extra_paragraphs(&self) -> u16 {
      58          130 :         self.ptr.maximum_extra_paragraphs()
      59          130 :     }
      60              : 
      61          130 :     pub fn initial_relative_ss(&self) -> u16 {
      62          130 :         self.ptr.initial_relative_ss()
      63          130 :     }
      64              : 
      65          130 :     pub fn initial_sp(&self) -> u16 {
      66          130 :         self.ptr.initial_sp()
      67          130 :     }
      68              : 
      69          130 :     pub fn checksum(&self) -> u16 {
      70          130 :         self.ptr.checksum()
      71          130 :     }
      72              : 
      73          130 :     pub fn initial_ip(&self) -> u16 {
      74          130 :         self.ptr.initial_ip()
      75          130 :     }
      76              : 
      77          130 :     pub fn initial_relative_cs(&self) -> u16 {
      78          130 :         self.ptr.initial_relative_cs()
      79          130 :     }
      80              : 
      81          130 :     pub fn addressof_relocation_table(&self) -> u16 {
      82          130 :         self.ptr.addressof_relocation_table()
      83          130 :     }
      84              : 
      85          130 :     pub fn overlay_number(&self) -> u16 {
      86          130 :         self.ptr.overlay_number()
      87          130 :     }
      88              : 
      89          130 :     pub fn reserved(&self) -> Vec<u16> {
      90          520 :         Vec::from_iter(self.ptr.reserved().iter().map(|x| *x as u16))
      91          130 :     }
      92              : 
      93          130 :     pub fn oem_id(&self) -> u16 {
      94          130 :         self.ptr.oem_id()
      95          130 :     }
      96              : 
      97          130 :     pub fn oem_info(&self) -> u16 {
      98          130 :         self.ptr.oem_info()
      99          130 :     }
     100              : 
     101          130 :     pub fn reserved2(&self) -> Vec<u16> {
     102          520 :         Vec::from_iter(self.ptr.reserved().iter().map(|x| *x as u16))
     103          130 :     }
     104              : 
     105              :     /// Return the offset to the [`Header`] structure.
     106          130 :     pub fn addressof_new_exeheader(&self) -> u32 {
     107          130 :         self.ptr.addressof_new_exeheader()
     108          130 :     }
     109              : }
     110              : 
     111              : impl std::fmt::Debug for DosHeader<'_> {
     112          130 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     113          130 :         f.debug_struct("DosHeader")
     114          130 :             .field("magic", &self.magic())
     115          130 :             .field("used_bytes_in_last_page", &self.used_bytes_in_last_page())
     116          130 :             .field("file_size_in_pages", &self.file_size_in_pages())
     117          130 :             .field("numberof_relocation", &self.numberof_relocation())
     118          130 :             .field(
     119          130 :                 "header_size_in_paragraphs",
     120          130 :                 &self.header_size_in_paragraphs(),
     121          130 :             )
     122          130 :             .field("minimum_extra_paragraphs", &self.minimum_extra_paragraphs())
     123          130 :             .field("maximum_extra_paragraphs", &self.maximum_extra_paragraphs())
     124          130 :             .field("initial_relative_ss", &self.initial_relative_ss())
     125          130 :             .field("initial_sp", &self.initial_sp())
     126          130 :             .field("checksum", &self.checksum())
     127          130 :             .field("initial_ip", &self.initial_ip())
     128          130 :             .field("initial_relative_cs", &self.initial_relative_cs())
     129          130 :             .field(
     130          130 :                 "addressof_relocation_table",
     131          130 :                 &self.addressof_relocation_table(),
     132          130 :             )
     133          130 :             .field("overlay_number", &self.overlay_number())
     134          130 :             .field("reserved", &self.reserved())
     135          130 :             .field("oem_info", &self.oem_info())
     136          130 :             .field("oem_id", &self.oem_id())
     137          130 :             .field("reserved2", &self.reserved2())
     138          130 :             .field("addressof_new_exeheader", &self.addressof_new_exeheader())
     139          130 :             .finish()
     140          130 :     }
     141              : }
     142              : 
     143              : /// Structure that represents the PE header (which follows the [`DosHeader`])
     144              : pub struct Header<'a> {
     145              :     ptr: cxx::UniquePtr<ffi::PE_Header>,
     146              :     _owner: PhantomData<&'a ffi::PE_Binary>,
     147              : }
     148              : 
     149              : impl FromFFI<ffi::PE_Header> for Header<'_> {
     150          130 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_Header>) -> Self {
     151          130 :         Self {
     152          130 :             ptr,
     153          130 :             _owner: PhantomData,
     154          130 :         }
     155          130 :     }
     156              : }
     157              : 
     158              : 
     159              : #[allow(non_camel_case_types)]
     160          130 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
     161              : pub enum MachineType {
     162              :     /// Alpha AXP, 32-bit address space
     163              :     ALPHA,
     164              :     /// Alpha AXP, 64-bit address space
     165              :     ALPHA64,
     166              :     /// Matsushita AM33
     167              :     AM33,
     168              :     /// AMD x64
     169              :     AMD64,
     170              :     /// ARM little endian
     171              :     ARM,
     172              :     /// ARMv7 Thumb mode only
     173              :     ARMNT,
     174              :     /// ARMv8 in 64-bits mode
     175              :     ARM64,
     176              :     /// EFI byte code
     177              :     EBC,
     178              :     /// Intel 386 or later
     179              :     I386,
     180              :     /// Intel Itanium processor family
     181              :     IA64,
     182              :     /// LoongArch 32-bit processor family
     183              :     LOONGARCH32,
     184              :     /// LoongArch 64-bit processor family
     185              :     LOONGARCH64,
     186              :     /// Mitsubishi M32R little endian
     187              :     M32R,
     188              :     /// MIPS16
     189              :     MIPS16,
     190              :     /// MIPS with FPU
     191              :     MIPSFPU,
     192              :     /// MIPS16 with FPU
     193              :     MIPSFPU16,
     194              :     /// Power PC little endian
     195              :     POWERPC,
     196              :     /// Power PC with floating point
     197              :     POWERPCFP,
     198              :     /// Power PC big endian
     199              :     POWERPCBE,
     200              :     /// MIPS with little endian
     201              :     R4000,
     202              :     /// RISC-V 32-bit address space
     203              :     RISCV32,
     204              :     /// RISC-V 64-bit address space
     205              :     RISCV64,
     206              :     /// RISC-V 128-bit address space
     207              :     RISCV128,
     208              :     /// Hitachi SH3
     209              :     SH3,
     210              :     /// Hitachi SH3 DSP
     211              :     SH3DSP,
     212              :     /// Hitachi SH4
     213              :     SH4,
     214              :     /// Hitachi SH5
     215              :     SH5,
     216              :     /// ARM or Thumb
     217              :     THUMB,
     218              :     /// MIPS little-endian WCE v2
     219              :     WCEMIPSV2,
     220              :     ARM64EC,
     221              :     ARM64X,
     222              :     CHPE_X86,
     223              :     UNKNOWN(u32),
     224              : }
     225              : 
     226              : impl From<u32> for MachineType {
     227          130 :     fn from(value: u32) -> Self {
     228          130 :         match value {
     229            0 :             0x00000184 => MachineType::ALPHA,
     230            0 :             0x00000284 => MachineType::ALPHA64,
     231            0 :             0x000001d3 => MachineType::AM33,
     232           70 :             0x00008664 => MachineType::AMD64,
     233            0 :             0x000001c0 => MachineType::ARM,
     234            0 :             0x000001c4 => MachineType::ARMNT,
     235           20 :             0x0000aa64 => MachineType::ARM64,
     236            0 :             0x00000ebc => MachineType::EBC,
     237           40 :             0x0000014c => MachineType::I386,
     238            0 :             0x00000200 => MachineType::IA64,
     239            0 :             0x00006232 => MachineType::LOONGARCH32,
     240            0 :             0x00006264 => MachineType::LOONGARCH64,
     241            0 :             0x00009041 => MachineType::M32R,
     242            0 :             0x00000266 => MachineType::MIPS16,
     243            0 :             0x00000366 => MachineType::MIPSFPU,
     244            0 :             0x00000466 => MachineType::MIPSFPU16,
     245            0 :             0x000001f0 => MachineType::POWERPC,
     246            0 :             0x000001f1 => MachineType::POWERPCFP,
     247            0 :             0x000001f2 => MachineType::POWERPCBE,
     248            0 :             0x00000166 => MachineType::R4000,
     249            0 :             0x00005032 => MachineType::RISCV32,
     250            0 :             0x00005064 => MachineType::RISCV64,
     251            0 :             0x00005128 => MachineType::RISCV128,
     252            0 :             0x000001a2 => MachineType::SH3,
     253            0 :             0x000001a3 => MachineType::SH3DSP,
     254            0 :             0x000001a6 => MachineType::SH4,
     255            0 :             0x000001a8 => MachineType::SH5,
     256            0 :             0x000001c2 => MachineType::THUMB,
     257            0 :             0x00000169 => MachineType::WCEMIPSV2,
     258            0 :             0x0000a641 => MachineType::ARM64EC,
     259            0 :             0x0000a64e => MachineType::ARM64X,
     260            0 :             0x00003a64 => MachineType::CHPE_X86,
     261            0 :             _ => MachineType::UNKNOWN(value),
     262              : 
     263              :         }
     264          130 :     }
     265              : }
     266              : impl From<MachineType> for u32 {
     267            0 :     fn from(value: MachineType) -> u32 {
     268            0 :         match value {
     269            0 :             MachineType::ALPHA => 0x184,
     270            0 :             MachineType::ALPHA64 => 0x284,
     271            0 :             MachineType::AM33 => 0x000001d3,
     272            0 :             MachineType::AMD64 => 0x00008664,
     273            0 :             MachineType::ARM => 0x000001c0,
     274            0 :             MachineType::ARMNT => 0x000001c4,
     275            0 :             MachineType::ARM64 => 0x0000aa64,
     276            0 :             MachineType::EBC => 0x00000ebc,
     277            0 :             MachineType::I386 => 0x0000014c,
     278            0 :             MachineType::IA64 => 0x00000200,
     279            0 :             MachineType::LOONGARCH32 => 0x6232,
     280            0 :             MachineType::LOONGARCH64 => 0x6264,
     281            0 :             MachineType::M32R => 0x00009041,
     282            0 :             MachineType::MIPS16 => 0x00000266,
     283            0 :             MachineType::MIPSFPU => 0x00000366,
     284            0 :             MachineType::MIPSFPU16 => 0x00000466,
     285            0 :             MachineType::POWERPC => 0x000001f0,
     286            0 :             MachineType::POWERPCFP => 0x000001f1,
     287            0 :             MachineType::POWERPCBE => 0x000001f2,
     288            0 :             MachineType::R4000 => 0x00000166,
     289            0 :             MachineType::RISCV32 => 0x00005032,
     290            0 :             MachineType::RISCV64 => 0x00005064,
     291            0 :             MachineType::RISCV128 => 0x00005128,
     292            0 :             MachineType::SH3 => 0x000001a2,
     293            0 :             MachineType::SH3DSP => 0x000001a3,
     294            0 :             MachineType::SH4 => 0x000001a6,
     295            0 :             MachineType::SH5 => 0x000001a8,
     296            0 :             MachineType::THUMB => 0x000001c2,
     297            0 :             MachineType::WCEMIPSV2 => 0x00000169,
     298            0 :             MachineType::ARM64EC => 0x0000a641,
     299            0 :             MachineType::ARM64X => 0x0000a64e,
     300            0 :             MachineType::CHPE_X86 => 0x00003a64,
     301            0 :             MachineType::UNKNOWN(_) => 0,
     302              : 
     303              :         }
     304            0 :     }
     305              : }
     306              : 
     307              : 
     308            0 : bitflags! {
     309          130 :     #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
     310            0 :     pub struct Characteristics: u32 {
     311            0 :         const NONE = 0x0;
     312            0 : 
     313            0 :         /// The file does not contain base relocations and must be loaded at its preferred base.
     314            0 :         /// If this cannot be done, the loader will error.
     315            0 :         const RELOCS_STRIPPED = 0x1;
     316            0 : 
     317            0 :         /// File is executable (i.e. no unresolved externel references).
     318            0 :         const EXECUTABLE_IMAGE = 0x2;
     319            0 : 
     320            0 :         /// COFF line numbers have been stripped. This is deprecated and should be 0
     321            0 :         const LINE_NUMS_STRIPPED = 0x4;
     322            0 : 
     323            0 :         /// COFF symbol table entries for local symbols have been removed.
     324            0 :         /// This is deprecated and should be 0.
     325            0 :         const LOCAL_SYMS_STRIPPED = 0x8;
     326            0 : 
     327            0 :         /// Aggressively trim working set. This is deprecated and must be 0.
     328            0 :         const AGGRESSIVE_WS_TRIM = 0x10;
     329            0 : 
     330            0 :         /// App can handle >2gb addresses
     331            0 :         const LARGE_ADDRESS_AWARE = 0x20;
     332            0 : 
     333            0 :         /// Little endian: the LSB precedes the MSB in memory. This is deprecated and should be 0.
     334            0 :         const BYTES_REVERSED_LO = 0x80;
     335            0 : 
     336            0 :         /// Machine is based on a 32bit word architecture.
     337            0 :         const NEED_32BIT_MACHINE = 0x100;
     338            0 : 
     339            0 :         /// Debugging info has been removed.
     340            0 :         const DEBUG_STRIPPED = 0x200;
     341            0 : 
     342            0 :         /// If the image is on removable media, fully load it and copy it to swap.
     343            0 :         const REMOVABLE_RUN_FROM_SWAP = 0x400;
     344            0 : 
     345            0 :         /// If the image is on network media, fully load it and copy it to swap.
     346            0 :         const NET_RUN_FROM_SWAP = 0x800;
     347            0 : 
     348            0 :         /// The image file is a system file, not a user program.
     349            0 :         const SYSTEM = 0x1000;
     350            0 : 
     351            0 :         /// The image file is a DLL.
     352            0 :         const DLL = 0x2000;
     353            0 : 
     354            0 :         /// This file should only be run on a uniprocessor machine.
     355            0 :         const UP_SYSTEM_ONLY = 0x4000;
     356            0 : 
     357            0 :         /// Big endian: the MSB precedes the LSB in memory. This is deprecated
     358            0 :         const BYTES_REVERSED_HI = 0x8000;
     359            0 :     }
     360            0 : }
     361              : 
     362              : impl std::fmt::Display for Characteristics {
     363            0 :     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
     364            0 :         bitflags::parser::to_writer(self, f)
     365            0 :     }
     366              : }
     367              : 
     368              : 
     369              : impl From<u32> for Characteristics {
     370          130 :     fn from(value: u32) -> Self {
     371          130 :         Characteristics::from_bits_truncate(value)
     372          130 :     }
     373              : }
     374              : impl From<Characteristics> for u32 {
     375            0 :     fn from(value: Characteristics) -> Self {
     376            0 :         value.bits()
     377            0 :     }
     378              : }
     379              : 
     380              : impl Header<'_> {
     381              :     /// The targeted machine architecture like ARM, x86, AMD64, ...
     382          130 :     pub fn machine(&self) -> MachineType {
     383          130 :         MachineType::from(self.ptr.machine())
     384          130 :     }
     385              : 
     386              :     /// The number of sections in the binary.
     387          130 :     pub fn nb_sections(&self) -> u16 {
     388          130 :         self.ptr.numberof_sections()
     389          130 :     }
     390              : 
     391              :     /// The low 32 bits of the number of seconds since January 1, 1970.
     392              :     /// It **indicates** when the file was created.
     393          130 :     pub fn time_date_stamp(&self) -> u32 {
     394          130 :         self.ptr.time_date_stamp()
     395          130 :     }
     396              : 
     397              :     /// The offset of the **COFF** symbol table.
     398              :     /// This value should be zero for an image because COFF debugging information is deprecated on
     399              :     /// in PE binary
     400          130 :     pub fn pointerto_symbol_table(&self) -> u32 {
     401          130 :         self.ptr.pointerto_symbol_table()
     402          130 :     }
     403              : 
     404              : 
     405              :     /// The number of entries in the symbol table. This data can be used to locate the string table
     406              :     /// which immediately follows the symbol table.
     407              :     ///
     408              :     /// This value should be zero for an image because COFF debugging information is deprecated in
     409              :     /// PE binary
     410          130 :     pub fn numberof_symbols(&self) -> u32 {
     411          130 :         self.ptr.numberof_symbols()
     412          130 :     }
     413              : 
     414              :     /// Size of the OptionalHeader **AND** the data directories which follows this header.
     415              :     ///
     416              :     /// This value is equivalent to:
     417              :     /// `sizeof(pe_optional_header) + NB_DATA_DIR * sizeof(data_directory)`
     418              :     ///
     419              :     /// This size **should** be either:
     420              :     /// * 0xE0 (224) for a PE32  (32 bits)
     421              :     /// * 0xF0 (240) for a PE32+ (64 bits)
     422          130 :     pub fn sizeof_optional_header(&self) -> u16 {
     423          130 :         self.ptr.sizeof_optional_header()
     424          130 :     }
     425              : 
     426              :     /// Characteristics of the binary like whether it is a DLL or an executable
     427          130 :     pub fn characteristics(&self) -> Characteristics {
     428          130 :         Characteristics::from(self.ptr.characteristics())
     429          130 :     }
     430              : 
     431            0 :     pub fn set_machine(&mut self, machine: MachineType) {
     432            0 :         self.ptr.pin_mut().set_machine(u32::from(machine));
     433            0 :     }
     434              : 
     435            0 :     pub fn set_numberof_sections(&mut self, value: u16) {
     436            0 :         self.ptr.pin_mut().set_numberof_sections(value);
     437            0 :     }
     438              : 
     439            0 :     pub fn set_time_date_stamp(&mut self, value: u32) {
     440            0 :         self.ptr.pin_mut().set_time_date_stamp(value);
     441            0 :     }
     442              : 
     443            0 :     pub fn set_pointerto_symbol_table(&mut self, value: u32) {
     444            0 :         self.ptr.pin_mut().set_pointerto_symbol_table(value);
     445            0 :     }
     446              : 
     447            0 :     pub fn set_numberof_symbols(&mut self, value: u32) {
     448            0 :         self.ptr.pin_mut().set_numberof_symbols(value);
     449            0 :     }
     450              : 
     451            0 :     pub fn set_sizeof_optional_header(&mut self, value: u16) {
     452            0 :         self.ptr.pin_mut().set_sizeof_optional_header(value);
     453            0 :     }
     454              : 
     455            0 :     pub fn set_characteristics(&mut self, characteristics: Characteristics) {
     456            0 :         self.ptr.pin_mut().set_characteristics(characteristics.bits());
     457            0 :     }
     458              : 
     459            0 :     pub fn add_characteristic(&mut self, characteristics: Characteristics) {
     460            0 :         self.ptr.pin_mut().add_characteristic(characteristics.bits());
     461            0 :     }
     462              : 
     463            0 :     pub fn remove_characteristic(&mut self, characteristics: Characteristics) {
     464            0 :         self.ptr.pin_mut().remove_characteristic(characteristics.bits());
     465            0 :     }
     466              : }
     467              : 
     468              : impl std::fmt::Debug for Header<'_> {
     469          130 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     470          130 :         f.debug_struct("Header")
     471          130 :             .field("machine", &self.machine())
     472          130 :             .field("nb_sections", &self.nb_sections())
     473          130 :             .field("time_date_stamp", &self.time_date_stamp())
     474          130 :             .field("pointerto_symbol_table", &self.pointerto_symbol_table())
     475          130 :             .field("numberof_symbols", &self.numberof_symbols())
     476          130 :             .field("sizeof_optional_header", &self.sizeof_optional_header())
     477          130 :             .field("characteristics", &self.characteristics())
     478          130 :             .finish()
     479          130 :     }
     480              : }
     481              : 
     482              : 
     483              : /// Structure which represents the PE OptionalHeader (after [`Header`]).
     484              : ///
     485              : /// Note that the term *optional* comes from the COFF specifications but this header is
     486              : /// **mandatory** for a PE binary.
     487              : pub struct OptionalHeader<'a> {
     488              :     ptr: cxx::UniquePtr<ffi::PE_OptionalHeader>,
     489              :     _owner: PhantomData<&'a ffi::PE_Binary>,
     490              : }
     491              : 
     492              : impl FromFFI<ffi::PE_OptionalHeader> for OptionalHeader<'_> {
     493          130 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_OptionalHeader>) -> Self {
     494          130 :         Self {
     495          130 :             ptr,
     496          130 :             _owner: PhantomData,
     497          130 :         }
     498          130 :     }
     499              : }
     500              : 
     501            0 : bitflags! {
     502          130 :     #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
     503            0 :     pub struct DllCharacteristics: u32 {
     504            0 :         /// ASLR with 64 bit address space.
     505            0 :         const HIGH_ENTROPY_VA = 0x20;
     506            0 : 
     507            0 :         /// DLL can be relocated at load time.
     508            0 :         const DYNAMIC_BASE = 0x40;
     509            0 : 
     510            0 :         /// Code integrity checks are enforced.
     511            0 :         const FORCE_INTEGRITY = 0x80;
     512            0 : 
     513            0 :         /// Image is NX compatible.
     514            0 :         const NX_COMPAT = 0x100;
     515            0 : 
     516            0 :         /// Isolation aware, but do not isolate the image.
     517            0 :         const NO_ISOLATION = 0x200;
     518            0 : 
     519            0 :         /// Does not use structured exception handling (SEH).
     520            0 :         /// No SEH handler may be called in this image.
     521            0 :         const NO_SEH = 0x400;
     522            0 : 
     523            0 :         /// Do not bind the image.
     524            0 :         const NO_BIND = 0x800;
     525            0 : 
     526            0 :         /// Image should execute in an AppContainer.
     527            0 :         const APPCONTAINER = 0x1000;
     528            0 : 
     529            0 :         /// A WDM driver.
     530            0 :         const WDM_DRIVER = 0x2000;
     531            0 : 
     532            0 :         /// Image supports Control Flow Guard.
     533            0 :         const GUARD_CF = 0x4000;
     534            0 : 
     535            0 :         /// Terminal Server aware.
     536            0 :         const TERMINAL_SERVER_AWARE = 0x8000;
     537            0 :     }
     538            0 : }
     539              : 
     540              : 
     541              : impl From<u32> for DllCharacteristics {
     542          130 :     fn from(value: u32) -> Self {
     543          130 :         DllCharacteristics::from_bits_truncate(value)
     544          130 :     }
     545              : }
     546              : impl From<DllCharacteristics> for u32 {
     547            0 :     fn from(value: DllCharacteristics) -> Self {
     548            0 :         value.bits()
     549            0 :     }
     550              : }
     551              : impl std::fmt::Display for DllCharacteristics {
     552            0 :     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
     553            0 :         bitflags::parser::to_writer(self, f)
     554            0 :     }
     555              : }
     556              : 
     557              : 
     558              : #[allow(non_camel_case_types)]
     559          130 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
     560              : pub enum Subsystem {
     561              :     /// Device drivers and native Windows processes
     562              :     NATIVE,
     563              : 
     564              :     /// The Windows GUI subsystem.
     565              :     WINDOWS_GUI,
     566              : 
     567              :     /// The Windows character subsystem.
     568              :     WINDOWS_CUI,
     569              : 
     570              :     /// The OS/2 character subsytem.
     571              :     OS2_CUI,
     572              : 
     573              :     /// The POSIX character subsystem.
     574              :     POSIX_CUI,
     575              : 
     576              :     /// Native Windows 9x driver.
     577              :     NATIVE_WINDOWS,
     578              : 
     579              :     /// Windows CE.
     580              :     WINDOWS_CE_GUI,
     581              : 
     582              :     /// An EFI application.
     583              :     EFI_APPLICATION,
     584              : 
     585              :     /// An EFI driver with boot services.
     586              :     EFI_BOOT_SERVICE_DRIVER,
     587              : 
     588              :     /// An EFI driver with run-time services.
     589              :     EFI_RUNTIME_DRIVER,
     590              : 
     591              :     /// An EFI ROM image.
     592              :     EFI_ROM,
     593              : 
     594              :     /// XBOX
     595              :     XBOX,
     596              : 
     597              :     /// A BCD application.
     598              :     WINDOWS_BOOT_APPLICATION,
     599              : 
     600              :     /// An unknown subsystem.
     601              :     UNKNOWN(u64),
     602              : }
     603              : 
     604              : impl From<u64> for Subsystem {
     605          130 :     fn from(value: u64) -> Self {
     606          130 :         match value {
     607           10 :             0x00000001 => Subsystem::NATIVE,
     608           70 :             0x00000002 => Subsystem::WINDOWS_GUI,
     609           50 :             0x00000003 => Subsystem::WINDOWS_CUI,
     610            0 :             0x00000005 => Subsystem::OS2_CUI,
     611            0 :             0x00000007 => Subsystem::POSIX_CUI,
     612            0 :             0x00000008 => Subsystem::NATIVE_WINDOWS,
     613            0 :             0x00000009 => Subsystem::WINDOWS_CE_GUI,
     614            0 :             0x0000000a => Subsystem::EFI_APPLICATION,
     615            0 :             0x0000000b => Subsystem::EFI_BOOT_SERVICE_DRIVER,
     616            0 :             0x0000000c => Subsystem::EFI_RUNTIME_DRIVER,
     617            0 :             0x0000000d => Subsystem::EFI_ROM,
     618            0 :             0x0000000e => Subsystem::XBOX,
     619            0 :             0x00000010 => Subsystem::WINDOWS_BOOT_APPLICATION,
     620            0 :             _ => Subsystem::UNKNOWN(value),
     621              : 
     622              :         }
     623          130 :     }
     624              : }
     625              : impl From<Subsystem> for u64 {
     626            0 :     fn from(value: Subsystem) -> u64 {
     627            0 :         match value {
     628            0 :             Subsystem::NATIVE => 0x00000001,
     629            0 :             Subsystem::WINDOWS_GUI => 0x00000002,
     630            0 :             Subsystem::WINDOWS_CUI => 0x00000003,
     631            0 :             Subsystem::OS2_CUI => 0x00000005,
     632            0 :             Subsystem::POSIX_CUI => 0x00000007,
     633            0 :             Subsystem::NATIVE_WINDOWS => 0x00000008,
     634            0 :             Subsystem::WINDOWS_CE_GUI => 0x00000009,
     635            0 :             Subsystem::EFI_APPLICATION => 0x0000000a,
     636            0 :             Subsystem::EFI_BOOT_SERVICE_DRIVER => 0x0000000b,
     637            0 :             Subsystem::EFI_RUNTIME_DRIVER => 0x0000000c,
     638            0 :             Subsystem::EFI_ROM => 0x0000000d,
     639            0 :             Subsystem::XBOX => 0x0000000e,
     640            0 :             Subsystem::WINDOWS_BOOT_APPLICATION => 0x00000010,
     641            0 :             Subsystem::UNKNOWN(_) => 0,
     642              : 
     643              :         }
     644            0 :     }
     645              : }
     646              : 
     647              : impl OptionalHeader<'_> {
     648              :     /// The linker major version
     649          130 :     pub fn major_linker_version(&self) -> u8 {
     650          130 :         self.ptr.major_linker_version()
     651          130 :     }
     652              : 
     653              :     /// The linker minor version
     654          130 :     pub fn minor_linker_version(&self) -> u8 {
     655          130 :         self.ptr.minor_linker_version()
     656          130 :     }
     657              : 
     658              :     /// The size of the code `.text` section or the sum of
     659              :     /// all the sections that contain code (i.e. sections with `CNT_CODE` flag)
     660          130 :     pub fn sizeof_code(&self) -> u32 {
     661          130 :         self.ptr.sizeof_code()
     662          130 :     }
     663              : 
     664              :     /// The size of the initialized data which are usually located in the `.data` section.
     665              :     /// If the initialized data are split across multiple sections, it is the sum of the sections.
     666          130 :     pub fn sizeof_initialized_data(&self) -> u32 {
     667          130 :         self.ptr.sizeof_initialized_data()
     668          130 :     }
     669              : 
     670              :     /// The size of the uninitialized data which are usually located in the `.bss` section.
     671              :     /// If the uninitialized data are split across multiple sections, it is the sum of the sections.
     672          130 :     pub fn sizeof_uninitialized_data(&self) -> u32 {
     673          130 :         self.ptr.sizeof_uninitialized_data()
     674          130 :     }
     675              : 
     676              :     /// The address of the entry point relative to the image base when the executable file is
     677              :     /// loaded into memory. For program images, this is the starting address. For device
     678              :     /// drivers, this is the address of the initialization function.
     679              :     ///
     680              :     /// An entry point is optional for DLLs. When no entry point is present, this field must be zero.
     681          130 :     pub fn addressof_entrypoint(&self) -> u32 {
     682          130 :         self.ptr.addressof_entrypoint()
     683          130 :     }
     684              : 
     685              :     /// Address relative to the imagebase where the binary's code starts.
     686          130 :     pub fn baseof_code(&self) -> u32 {
     687          130 :         self.ptr.baseof_code()
     688          130 :     }
     689              : 
     690              :     /// Address relative to the imagebase where the binary's data starts.
     691              :     ///
     692              :     /// <div class="warning">This value is not present for PE64 files</div>
     693          130 :     pub fn baseof_data(&self) -> u32 {
     694          130 :         self.ptr.baseof_data()
     695          130 :     }
     696              : 
     697              :     /// The preferred base address when mapping the binary in memory
     698          130 :     pub fn imagebase(&self) -> u64 {
     699          130 :         self.ptr.imagebase()
     700          130 :     }
     701              : 
     702              :     /// The alignment (in bytes) of sections when they are loaded into memory.
     703              :     ///
     704              :     /// It must be greater than or equal to file_alignment and
     705              :     /// the default is the page size for the architecture.
     706          130 :     pub fn section_alignment(&self) -> u32 {
     707          130 :         self.ptr.section_alignment()
     708          130 :     }
     709              : 
     710              :     /// The section's file alignment. This value must be a power of 2 between 512 and 64K.
     711              :     /// The default value is usually 512
     712          130 :     pub fn file_alignment(&self) -> u32 {
     713          130 :         self.ptr.file_alignment()
     714          130 :     }
     715              : 
     716              :     /// The **major** version number of the required operating system
     717          130 :     pub fn major_operating_system_version(&self) -> u16 {
     718          130 :         self.ptr.major_operating_system_version()
     719          130 :     }
     720              : 
     721              :     /// The **minor** version number of the required operating system
     722          130 :     pub fn minor_operating_system_version(&self) -> u16 {
     723          130 :         self.ptr.minor_operating_system_version()
     724          130 :     }
     725              : 
     726              :     /// The major version number of the image
     727          130 :     pub fn major_image_version(&self) -> u16 {
     728          130 :         self.ptr.major_image_version()
     729          130 :     }
     730              : 
     731              :     /// The minor version number of the image
     732          130 :     pub fn minor_image_version(&self) -> u16 {
     733          130 :         self.ptr.minor_image_version()
     734          130 :     }
     735              : 
     736              :     /// The major version number of the subsystem
     737          130 :     pub fn major_subsystem_version(&self) -> u16 {
     738          130 :         self.ptr.major_subsystem_version()
     739          130 :     }
     740              : 
     741              :     /// The minor version number of the subsystem
     742          130 :     pub fn minor_subsystem_version(&self) -> u16 {
     743          130 :         self.ptr.minor_subsystem_version()
     744          130 :     }
     745              : 
     746              :     /// According to the official PE specifications, this value
     747              :     /// is reserved and **should** be 0.
     748          130 :     pub fn win32_version_value(&self) -> u32 {
     749          130 :         self.ptr.win32_version_value()
     750          130 :     }
     751              : 
     752              :     /// The size (in bytes) of the image, including all headers, as the image is loaded in memory.
     753              :     ///
     754              :     /// It must be a multiple of section_alignment and should match [`crate::pe::Binary::virtual_size`]
     755          130 :     pub fn sizeof_image(&self) -> u32 {
     756          130 :         self.ptr.sizeof_image()
     757          130 :     }
     758              : 
     759              :     /// Size of the DosHeader + PE Header + Section headers rounded up to a multiple of the file_alignment
     760          130 :     pub fn sizeof_headers(&self) -> u32 {
     761          130 :         self.ptr.sizeof_headers()
     762          130 :     }
     763              : 
     764              :     /// The image file checksum. The algorithm for computing the checksum is incorporated into `IMAGHELP.DLL`.
     765              :     ///
     766              :     /// The following are checked for validation at load time all **drivers**, any **DLL loaded at boot**
     767              :     /// time, and any **DLL** that is loaded into a **critical** Windows process.
     768          260 :     pub fn checksum(&self) -> u32 {
     769          260 :         self.ptr.checksum()
     770          260 :     }
     771              : 
     772              :     /// Target subsystem like Driver, XBox, Windows GUI, ...
     773          130 :     pub fn subsystem(&self) -> Subsystem {
     774          130 :         Subsystem::from(self.ptr.subsystem())
     775          130 :     }
     776              : 
     777              :     /// Some characteristics of the underlying binary like the support of the PIE.
     778              :     /// The prefix ``dll`` comes from the official PE specifications but these characteristics
     779              :     /// are also used for **executables**
     780          130 :     pub fn dll_characteristics(&self) -> DllCharacteristics {
     781          130 :         DllCharacteristics::from(self.ptr.dll_characteristics())
     782          130 :     }
     783              : 
     784              : 
     785              :     /// Size of the stack to reserve when loading the PE binary
     786              :     ///
     787              :     /// Only [`OptionalHeader::sizeof_stack_commit`] is committed, the rest
     788              :     /// available one page at a time until the reserve size is reached.
     789          130 :     pub fn sizeof_stack_reserve(&self) -> u64 {
     790          130 :         self.ptr.sizeof_stack_reserve()
     791          130 :     }
     792              : 
     793              :     /// Size of the stack to commit
     794          130 :     pub fn sizeof_stack_commit(&self) -> u64 {
     795          130 :         self.ptr.sizeof_stack_commit()
     796          130 :     }
     797              : 
     798              :     /// Size of the heap to reserve when loading the PE binary
     799          130 :     pub fn sizeof_heap_reserve(&self) -> u64 {
     800          130 :         self.ptr.sizeof_heap_reserve()
     801          130 :     }
     802              : 
     803              :     /// Size of the stack to commit
     804          130 :     pub fn sizeof_heap_commit(&self) -> u64 {
     805          130 :         self.ptr.sizeof_heap_commit()
     806          130 :     }
     807              : 
     808              :     /// According to the PE specifications, this value is *reserved* and **should** be 0.
     809          130 :     pub fn loader_flags(&self) -> u32 {
     810          130 :         self.ptr.loader_flags()
     811          130 :     }
     812              : 
     813              :     /// The number of DataDirectory that follow this header.
     814          130 :     pub fn numberof_rva_and_size(&self) -> u32 {
     815          130 :         self.ptr.numberof_rva_and_size()
     816          130 :     }
     817              : 
     818            0 :     pub fn set_addressof_entrypoint(&mut self, value: u32) {
     819            0 :         self.ptr.pin_mut().set_addressof_entrypoint(value)
     820            0 :     }
     821              : 
     822            0 :     pub fn set_imagebase(&mut self, value: u64) {
     823            0 :         self.ptr.pin_mut().set_imagebase(value)
     824            0 :     }
     825              : }
     826              : 
     827              : impl std::fmt::Debug for OptionalHeader<'_> {
     828          130 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     829          130 :         f.debug_struct("OptionalHeader")
     830          130 :             .field("major_linker_version", &self.major_linker_version())
     831          130 :             .field("minor_linker_version", &self.minor_linker_version())
     832          130 :             .field("sizeof_code", &self.sizeof_code())
     833          130 :             .field("sizeof_initialized_data", &self.sizeof_initialized_data())
     834          130 :             .field(
     835          130 :                 "sizeof_uninitialized_data",
     836          130 :                 &self.sizeof_uninitialized_data(),
     837          130 :             )
     838          130 :             .field("addressof_entrypoint", &self.addressof_entrypoint())
     839          130 :             .field("baseof_code", &self.baseof_code())
     840          130 :             .field("baseof_data", &self.baseof_data())
     841          130 :             .field("imagebase", &self.imagebase())
     842          130 :             .field("section_alignment", &self.section_alignment())
     843          130 :             .field("file_alignment", &self.file_alignment())
     844          130 :             .field(
     845          130 :                 "major_operating_system_version",
     846          130 :                 &self.major_operating_system_version(),
     847          130 :             )
     848          130 :             .field(
     849          130 :                 "minor_operating_system_version",
     850          130 :                 &self.minor_operating_system_version(),
     851          130 :             )
     852          130 :             .field("major_image_version", &self.major_image_version())
     853          130 :             .field("minor_image_version", &self.minor_image_version())
     854          130 :             .field("major_subsystem_version", &self.major_subsystem_version())
     855          130 :             .field("minor_subsystem_version", &self.minor_subsystem_version())
     856          130 :             .field("win32_version_value", &self.win32_version_value())
     857          130 :             .field("sizeof_image", &self.sizeof_image())
     858          130 :             .field("sizeof_headers", &self.sizeof_headers())
     859          130 :             .field("checksum", &self.checksum())
     860          130 :             .field("subsystem", &self.subsystem())
     861          130 :             .field("dll_characteristics", &self.dll_characteristics())
     862          130 :             .field("sizeof_stack_reserve", &self.sizeof_stack_reserve())
     863          130 :             .field("sizeof_stack_commit", &self.sizeof_stack_commit())
     864          130 :             .field("sizeof_heap_reserve", &self.sizeof_heap_reserve())
     865          130 :             .field("sizeof_heap_commit", &self.sizeof_heap_commit())
     866          130 :             .field("loader_flags", &self.loader_flags())
     867          130 :             .field("numberof_rva_and_size", &self.numberof_rva_and_size())
     868          130 :             .finish()
     869          130 :     }
     870              : }
        

Generated by: LCOV version 2.1-1