LCOV - code coverage report
Current view: top level - src/pe - import.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 64.8 % 145 94
Test Date: 2026-04-12:00:00:00 Functions: 60.0 % 35 21

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

Generated by: LCOV version 2.1-1