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: 2026-04-12:00:00:00 Functions: 80.0 % 35 28

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

Generated by: LCOV version 2.1-1