LCOV - code coverage report
Current view: top level - src/pe - import.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 79.7 % 118 94
Test Date: 2025-02-23:00:00:00 Functions: 72.4 % 29 21

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

Generated by: LCOV version 2.1-1