LCOV - code coverage report
Current view: top level - src/pe - import.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 73.4 % 128 94
Test Date: 2025-06-24:00:00:00 Functions: 70.0 % 30 21

            Line data    Source code
       1              : //! This module represents PE's Imports
       2              : 
       3              : use std::pin::Pin;
       4              : use std::marker::PhantomData;
       5              : 
       6              : use crate::common::into_optional;
       7              : use crate::declare_iterator;
       8              : use crate::pe::DataDirectory;
       9              : use crate::{common::FromFFI, generic};
      10              : use lief_ffi as ffi;
      11              : 
      12              : pub struct Import<'a> {
      13              :     ptr: cxx::UniquePtr<ffi::PE_Import>,
      14              :     _owner: PhantomData<&'a ffi::PE_Binary>,
      15              : }
      16              : 
      17              : impl std::fmt::Debug for Import<'_> {
      18         2256 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
      19         2256 :         f.debug_struct("Import")
      20         2256 :             .field("name", &self.name())
      21         2256 :             .field("forwarder_chain", &self.forwarder_chain())
      22         2256 :             .field("timedatestamp", &self.timedatestamp())
      23         2256 :             .field("import_address_table_rva", &self.import_address_table_rva())
      24         2256 :             .field("import_lookup_table_rva", &self.import_lookup_table_rva())
      25         2256 :             .field("directory", &self.directory())
      26         2256 :             .field("iat_directory", &self.iat_directory())
      27         2256 :             .finish()
      28         2256 :     }
      29              : }
      30              : 
      31              : impl<'a> FromFFI<ffi::PE_Import> for Import<'a> {
      32         2268 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_Import>) -> Self {
      33         2268 :         Import {
      34         2268 :             ptr,
      35         2268 :             _owner: PhantomData,
      36         2268 :         }
      37         2268 :     }
      38              : }
      39              : 
      40              : impl Import<'_> {
      41              :     /// Iterator over the [`ImportEntry`]
      42         2256 :     pub fn entries(&self) -> ImportEntries {
      43         2256 :         ImportEntries::new(self.ptr.entries())
      44         2256 :     }
      45              : 
      46              :     /// The index of the first forwarder reference
      47         2256 :     pub fn forwarder_chain(&self) -> u32 {
      48         2256 :         self.ptr.forwarder_chain()
      49         2256 :     }
      50              : 
      51              :     /// The stamp that is set to zero until the image is bound.
      52              :     /// After the image is bound, this field is set to the time/data stamp of the DLL
      53         2256 :     pub fn timedatestamp(&self) -> u32 {
      54         2256 :         self.ptr.timedatestamp()
      55         2256 :     }
      56              : 
      57              :     /// The RVA of the import address table (`IAT`). The content of this table is
      58              :     /// **identical** to the content of the Import Lookup Table (`ILT`) until the image is bound.
      59              :     ///
      60              :     /// <div class="warning">This address could change when re-building the binary</div>
      61         2256 :     pub fn import_address_table_rva(&self) -> u32 {
      62         2256 :         self.ptr.import_address_table_rva()
      63         2256 :     }
      64              : 
      65              :     /// Return the relative virtual address of the import lookup table
      66              :     ///
      67              :     /// <div class="warning">This address could change when re-building the binary</div>
      68         2256 :     pub fn import_lookup_table_rva(&self) -> u32 {
      69         2256 :         self.ptr.import_lookup_table_rva()
      70         2256 :     }
      71              : 
      72              :     /// Return the library's name (e.g. `kernel32.dll`)
      73         2256 :     pub fn name(&self) -> String {
      74         2256 :         self.ptr.name().to_string()
      75         2256 :     }
      76              : 
      77              :     /// Return the [`DataDirectory`] associated with this import.
      78         2256 :     pub fn directory(&self) -> Option<DataDirectory> {
      79         2256 :         into_optional(self.ptr.directory())
      80         2256 :     }
      81              : 
      82              :     /// Return the [`DataDirectory`] associated with the IAT (import address table).
      83         2256 :     pub fn iat_directory(&self) -> Option<DataDirectory> {
      84         2256 :         into_optional(self.ptr.iat_directory())
      85         2256 :     }
      86              : 
      87              :     /// Try to find an [`ImportEntry`] by its name
      88            0 :     pub fn entry_by_name(&self, name: &str) -> Option<ImportEntry> {
      89            0 :         into_optional(self.ptr.entry_by_name(name))
      90            0 :     }
      91              : 
      92              :     /// The original name rva
      93            0 :     pub fn name_rva(&self) -> u32 {
      94            0 :         self.ptr.name_rva()
      95            0 :     }
      96              : 
      97              :     /// Remove the import entry with the given name.
      98              :     ///
      99              :     /// Return true if the deletion succeed, false otherwise
     100            0 :     pub fn remove_entry_by_name(&mut self, name: &str) -> bool {
     101            0 :         self.ptr.pin_mut().remove_entry_by_name(name)
     102            0 :     }
     103              : 
     104              :     /// Remove the import entry with the given ordinal number
     105              :     ///
     106              :     /// Return true if the deletion succeed, false otherwise
     107            0 :     pub fn remove_entry_by_ordinal(&mut self, ord: u32) -> bool {
     108            0 :         self.ptr.pin_mut().remove_entry_by_ordinal(ord)
     109            0 :     }
     110              : 
     111              :     /// Add a new entry with the given name
     112            0 :     pub fn add_entry_by_name<'a>(&'a mut self, name: &str) -> ImportEntry<'a> {
     113            0 :         ImportEntry::from_ffi(self.ptr.pin_mut().add_entry_by_name(name))
     114            0 :     }
     115              : }
     116              : 
     117              : /// Structure that represents an entry (i.e. an import) in the regular import table.
     118              : ///
     119              : /// It implements the [`generic::Symbol`] trait that exposes [`generic::Symbol::name`] and
     120              : /// [`generic::Symbol::value`].
     121              : pub struct ImportEntry<'a> {
     122              :     ptr: cxx::UniquePtr<ffi::PE_ImportEntry>,
     123              :     _owner: PhantomData<&'a ffi::PE_Import>,
     124              : }
     125              : 
     126              : impl ImportEntry<'_> {
     127              :     /// `True` if it is an import by ordinal
     128            0 :     pub fn is_ordinal(&self) -> bool {
     129            0 :         self.ptr.is_ordinal()
     130            0 :     }
     131              : 
     132              :     /// The ordinal value
     133        28428 :     pub fn ordinal(&self) -> u16 {
     134        28428 :         self.ptr.ordinal()
     135        28428 :     }
     136        28428 :     pub fn hint_name_rva(&self) -> u64 {
     137        28428 :         self.ptr.hint_name_rva()
     138        28428 :     }
     139              : 
     140              :     /// Index into the export table that is used to speed-up the resolution
     141        28428 :     pub fn hint(&self) -> u16 {
     142        28428 :         self.ptr.hint()
     143        28428 :     }
     144              : 
     145              :     /// Value of the current entry in the Import Address Table.
     146              :     /// It should match the lookup table value
     147        28428 :     pub fn iat_value(&self) -> u64 {
     148        28428 :         self.ptr.iat_value()
     149        28428 :     }
     150              : 
     151              :     /// Original value in the import lookup table.
     152              :     ///
     153              :     /// This value should match the [`ImportEntry::iat_value`].
     154            0 :     pub fn ilt_value(&self) -> u64 {
     155            0 :         self.ptr.ilt_value()
     156            0 :     }
     157              : 
     158              :     /// Raw value
     159        28428 :     pub fn data(&self) -> u64 {
     160        28428 :         self.ptr.data()
     161        28428 :     }
     162              : 
     163              :     /// **Original** address of the entry in the Import Address Table
     164        28428 :     pub fn iat_address(&self) -> u64 {
     165        28428 :         self.ptr.iat_address()
     166        28428 :     }
     167              : 
     168              :     /// Demangled representation of the symbol or an empty string if it can't
     169              :     /// be demangled
     170            0 :     pub fn demangled_name(&self) -> String {
     171            0 :         self.ptr.demangled_name().to_string()
     172            0 :     }
     173              : }
     174              : 
     175              : impl<'a> FromFFI<ffi::PE_ImportEntry> for ImportEntry<'a> {
     176        28428 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ImportEntry>) -> Self {
     177        28428 :         ImportEntry {
     178        28428 :             ptr,
     179        28428 :             _owner: PhantomData,
     180        28428 :         }
     181        28428 :     }
     182              : }
     183              : 
     184              : impl generic::Symbol for ImportEntry<'_> {
     185        85284 :     fn as_generic(&self) -> &ffi::AbstractSymbol {
     186        85284 :         self.ptr.as_ref().unwrap().as_ref()
     187        85284 :     }
     188              : 
     189            0 :     fn as_pin_mut_generic(&mut self) -> Pin<&mut ffi::AbstractSymbol> {
     190            0 :         unsafe {
     191            0 :             Pin::new_unchecked({
     192            0 :                 (self.ptr.as_ref().unwrap().as_ref() as *const ffi::AbstractSymbol
     193            0 :                     as *mut ffi::AbstractSymbol)
     194            0 :                     .as_mut()
     195            0 :                     .unwrap()
     196            0 :             })
     197            0 :         }
     198            0 :     }
     199              : }
     200              : 
     201              : impl std::fmt::Debug for ImportEntry<'_> {
     202        28428 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     203        28428 :         let base = self as &dyn generic::Symbol;
     204        28428 :         f.debug_struct("ImportEntry")
     205        28428 :             .field("base", &base)
     206        28428 :             .field("ordinal", &self.ordinal())
     207        28428 :             .field("hint_name_rva", &self.hint_name_rva())
     208        28428 :             .field("hint", &self.hint())
     209        28428 :             .field("iat_value", &self.iat_value())
     210        28428 :             .field("data", &self.data())
     211        28428 :             .field("iat_address", &self.iat_address())
     212        28428 :             .finish()
     213        28428 :     }
     214              : }
     215              : 
     216        28428 : declare_iterator!(
     217        28428 :     ImportEntries,
     218        28428 :     ImportEntry<'a>,
     219        28428 :     ffi::PE_ImportEntry,
     220        28428 :     ffi::PE_Import,
     221        28428 :     ffi::PE_Import_it_entries
     222        28428 : );
     223         2256 : declare_iterator!(
     224         2256 :     Imports,
     225         2256 :     Import<'a>,
     226         2256 :     ffi::PE_Import,
     227         2256 :     ffi::PE_Binary,
     228         2256 :     ffi::PE_Binary_it_imports
     229         2256 : );
        

Generated by: LCOV version 2.1-1