LCOV - code coverage report
Current view: top level - src/coff - header.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 92.4 % 119 110
Test Date: 2025-06-24:00:00:00 Functions: 80.0 % 35 28

            Line data    Source code
       1              : 
       2              : //! COFF section module
       3              : 
       4              : use std::marker::PhantomData;
       5              : 
       6              : use lief_ffi as ffi;
       7              : 
       8              : use crate::common::FromFFI;
       9              : use crate::pe;
      10              : use crate::to_slice;
      11              : 
      12              : 
      13              : /// This enum represents the different types of COFF header.
      14              : pub enum Header<'a> {
      15              :     /// Regular (default) header
      16              :     Regular(RegularHeader<'a>),
      17              : 
      18              :     /// Header for COFF files that contain more than 65536 sections (compiled with `/bigobj`)
      19              :     BigObj(BigObjHeader<'a>),
      20              : }
      21              : 
      22              : impl FromFFI<ffi::COFF_Header> for Header<'_> {
      23           84 :     fn from_ffi(ffi_entry: cxx::UniquePtr<ffi::COFF_Header>) -> Self {
      24           84 :         unsafe {
      25           84 :             let obj_ref = ffi_entry.as_ref().unwrap();
      26           84 :             if ffi::COFF_RegularHeader::classof(obj_ref) {
      27           60 :                 let raw = {
      28           60 :                     type From = cxx::UniquePtr<ffi::COFF_Header>;
      29           60 :                     type To = cxx::UniquePtr<ffi::COFF_RegularHeader>;
      30           60 :                     std::mem::transmute::<From, To>(ffi_entry)
      31           60 :                 };
      32           60 :                 Header::Regular(RegularHeader::from_ffi(raw))
      33           24 :             } else if ffi::COFF_BigObjHeader::classof(obj_ref) {
      34           24 :                 let raw = {
      35           24 :                     type From = cxx::UniquePtr<ffi::COFF_Header>;
      36           24 :                     type To = cxx::UniquePtr<ffi::COFF_BigObjHeader>;
      37           24 :                     std::mem::transmute::<From, To>(ffi_entry)
      38           24 :                 };
      39           24 :                 Header::BigObj(BigObjHeader::from_ffi(raw))
      40              :             } else {
      41            0 :                 panic!("unsupported header");
      42              :             }
      43              :         }
      44           84 :     }
      45              : }
      46              : 
      47              : /// Trait shared by the different COFF headers
      48              : pub trait GenericHeader {
      49              :     #[doc(hidden)]
      50              :     fn as_generic(&self) -> &ffi::COFF_Header;
      51              : 
      52              :     /// The machine type targeted by this COFF
      53           84 :     fn machine(&self) -> pe::headers::MachineType {
      54           84 :         pe::headers::MachineType::from(self.as_generic().machine())
      55           84 :     }
      56              : 
      57              :     /// The number of sections
      58           84 :     fn nb_sections(&self) -> u32 {
      59           84 :         self.as_generic().nb_sections()
      60           84 :     }
      61              : 
      62              :     /// Offset of the symbols table
      63           84 :     fn pointerto_symbol_table(&self) -> u32 {
      64           84 :         self.as_generic().pointerto_symbol_table()
      65           84 :     }
      66              : 
      67              :     /// Number of symbols (including auxiliary symbols)
      68           84 :     fn nb_symbols(&self) -> u32 {
      69           84 :         self.as_generic().nb_symbols()
      70           84 :     }
      71              : 
      72              :     /// Timestamp when the COFF has been generated
      73           84 :     fn timedatestamp(&self) -> u32 {
      74           84 :         self.as_generic().timedatestamp()
      75           84 :     }
      76              : }
      77              : 
      78              : impl GenericHeader for Header<'_> {
      79            0 :     fn as_generic(&self) -> &ffi::COFF_Header {
      80            0 :         match &self {
      81            0 :             Header::Regular(h) => h.as_generic(),
      82            0 :             Header::BigObj(h) => h.as_generic(),
      83              :         }
      84            0 :     }
      85              : }
      86              : 
      87              : 
      88              : impl std::fmt::Debug for &dyn GenericHeader {
      89           84 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
      90           84 :         f.debug_struct("GenericHeader")
      91           84 :             .field("machine", &self.machine())
      92           84 :             .field("nb_sections", &self.nb_sections())
      93           84 :             .field("pointerto_symbol_table", &self.pointerto_symbol_table())
      94           84 :             .field("nb_symbols", &self.nb_symbols())
      95           84 :             .field("timedatestamp", &self.timedatestamp())
      96           84 :             .finish()
      97           84 :     }
      98              : }
      99              : 
     100              : impl std::fmt::Display for &dyn GenericHeader {
     101            0 :     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
     102            0 :         write!(f, "{}", self.as_generic().to_string())
     103            0 :     }
     104              : }
     105              : 
     106              : 
     107              : /// Regular (default) header
     108              : pub struct RegularHeader<'a> {
     109              :     ptr: cxx::UniquePtr<ffi::COFF_RegularHeader>,
     110              :     _owner: PhantomData<&'a ffi::COFF_Binary>,
     111              : }
     112              : 
     113              : impl FromFFI<ffi::COFF_RegularHeader> for RegularHeader<'_> {
     114           60 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::COFF_RegularHeader>) -> Self {
     115           60 :         Self {
     116           60 :             ptr,
     117           60 :             _owner: PhantomData,
     118           60 :         }
     119           60 :     }
     120              : }
     121              : 
     122              : impl RegularHeader<'_> {
     123              :     /// The size of the optional header that follows this header (should be 0)
     124           60 :     pub fn sizeof_optionalheader(&self) -> u16 {
     125           60 :         self.ptr.sizeof_optionalheader()
     126           60 :     }
     127              : 
     128              :     /// Characteristics
     129           60 :     pub fn characteristics(&self) -> u16 {
     130           60 :         self.ptr.characteristics()
     131           60 :     }
     132              : }
     133              : 
     134              : impl GenericHeader for RegularHeader<'_> {
     135          360 :     fn as_generic(&self) -> &ffi::COFF_Header {
     136          360 :         self.ptr.as_ref().unwrap().as_ref()
     137          360 :     }
     138              : }
     139              : 
     140              : impl std::fmt::Debug for RegularHeader<'_> {
     141           60 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     142           60 :         let base = self as &dyn GenericHeader;
     143           60 :         f.debug_struct("RegularHeader")
     144           60 :             .field("base", &base)
     145           60 :             .field("sizeof_optionalheader", &self.sizeof_optionalheader())
     146           60 :             .field("characteristics", &self.characteristics())
     147           60 :             .finish()
     148           60 :     }
     149              : }
     150              : 
     151              : impl std::fmt::Display for RegularHeader<'_> {
     152           60 :     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
     153           60 :         write!(f, "{}", self.as_generic().to_string())
     154           60 :     }
     155              : }
     156              : 
     157              : /// Header for COFF files that contain more than 65536 sections (compiled with `/bigobj`)
     158              : pub struct BigObjHeader<'a> {
     159              :     ptr: cxx::UniquePtr<ffi::COFF_BigObjHeader>,
     160              :     _owner: PhantomData<&'a ffi::COFF_Binary>,
     161              : }
     162              : 
     163              : impl FromFFI<ffi::COFF_BigObjHeader> for BigObjHeader<'_> {
     164           24 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::COFF_BigObjHeader>) -> Self {
     165           24 :         Self {
     166           24 :             ptr,
     167           24 :             _owner: PhantomData,
     168           24 :         }
     169           24 :     }
     170              : }
     171              : 
     172              : impl BigObjHeader<'_> {
     173              :     /// The version of this header which must be >= 2
     174           24 :     pub fn version(&self) -> u16 {
     175           24 :         self.ptr.version()
     176           24 :     }
     177              : 
     178              :     /// Originally named `ClassID`, this uuid should match: `{D1BAA1C7-BAEE-4ba9-AF20-FAF66AA4DCB8}`
     179           24 :     pub fn uuid(&self) -> &[u8] {
     180           24 :         to_slice!(self.ptr.uuid());
     181           24 :     }
     182              : 
     183              :     /// Size of data that follows the header
     184           24 :     pub fn sizeof_data(&self) -> u32 {
     185           24 :         self.ptr.sizeof_data()
     186           24 :     }
     187              : 
     188              :     /// 1 means that it contains metadata
     189           24 :     pub fn flags(&self) -> u32 {
     190           24 :         self.ptr.flags()
     191           24 :     }
     192              : 
     193              :     /// Size of CLR metadata
     194           24 :     pub fn metadata_size(&self) -> u32 {
     195           24 :         self.ptr.metadata_size()
     196           24 :     }
     197              : 
     198              :     /// Offset of CLR metadata
     199           24 :     pub fn metadata_offset(&self) -> u32 {
     200           24 :         self.ptr.metadata_offset()
     201           24 :     }
     202              : }
     203              : 
     204              : impl std::fmt::Debug for BigObjHeader<'_> {
     205           24 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     206           24 :         let base = self as &dyn GenericHeader;
     207           24 :         f.debug_struct("BigObjHeader")
     208           24 :             .field("base", &base)
     209           24 :             .field("version", &self.version())
     210           24 :             .field("uuid", &self.uuid())
     211           24 :             .field("sizeof_data", &self.sizeof_data())
     212           24 :             .field("flags", &self.flags())
     213           24 :             .field("metadata_size", &self.metadata_size())
     214           24 :             .field("metadata_offset", &self.metadata_offset())
     215           24 :             .finish()
     216           24 :     }
     217              : }
     218              : 
     219              : 
     220              : impl GenericHeader for BigObjHeader<'_> {
     221          144 :     fn as_generic(&self) -> &ffi::COFF_Header {
     222          144 :         self.ptr.as_ref().unwrap().as_ref()
     223          144 :     }
     224              : }
     225              : 
     226              : impl std::fmt::Display for BigObjHeader<'_> {
     227           24 :     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
     228           24 :         write!(f, "{}", self.as_generic().to_string())
     229           24 :     }
     230              : }
        

Generated by: LCOV version 2.1-1