LCOV - code coverage report
Current view: top level - src/pe - export.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 39.6 % 169 67
Test Date: 2025-02-23:00:00:00 Functions: 33.3 % 45 15

            Line data    Source code
       1              : //! PE export module
       2              : 
       3              : use lief_ffi as ffi;
       4              : 
       5              : use crate::common::into_optional;
       6              : use crate::common::{FromFFI, AsFFI};
       7              : use crate::declare_iterator;
       8              : use crate::generic;
       9              : 
      10              : use std::marker::PhantomData;
      11              : 
      12              : pub struct Export<'a> {
      13              :     ptr: cxx::UniquePtr<ffi::PE_Export>,
      14              :     _owner: PhantomData<&'a ffi::PE_Binary>,
      15              : }
      16              : 
      17              : impl Export<'_> {
      18              :     /// Create a new Export object
      19            0 :     pub fn new() -> Export<'static> {
      20            0 :         Export::from_ffi(ffi::PE_Export::create())
      21            0 :     }
      22              : 
      23              :     /// According to the PE specifications this value is reserved and should be set to 0
      24           80 :     pub fn export_flags(&self) -> u32 {
      25           80 :         self.ptr.export_flags()
      26           80 :     }
      27              : 
      28              :     /// The time and date that the export data was created
      29           80 :     pub fn timestamp(&self) -> u32 {
      30           80 :         self.ptr.timestamp()
      31           80 :     }
      32              : 
      33              :     /// The major version number (can be user-defined)
      34           80 :     pub fn major_version(&self) -> u16 {
      35           80 :         self.ptr.major_version()
      36           80 :     }
      37              : 
      38              :     /// The minor version number (can be user-defined)
      39           80 :     pub fn minor_version(&self) -> u16 {
      40           80 :         self.ptr.minor_version()
      41           80 :     }
      42              : 
      43              :     /// The starting number for the exports. Usually this value is set to 1
      44           80 :     pub fn ordinal_base(&self) -> u32 {
      45           80 :         self.ptr.ordinal_base()
      46           80 :     }
      47              : 
      48              :     /// The name of the library exported (e.g. `KERNEL32.dll`)
      49           80 :     pub fn name(&self) -> String {
      50           80 :         self.ptr.name().to_string()
      51           80 :     }
      52              : 
      53              :     /// Iterator over the different [`Entry`] exported by this table
      54           80 :     pub fn entries(&self) -> ExportEntries {
      55           80 :         ExportEntries::new(self.ptr.entries())
      56           80 :     }
      57              : 
      58              :     /// Address of the ASCII DLL's name (RVA)
      59            0 :     pub fn name_rva(&self) -> u32 {
      60            0 :         self.ptr.name_rva()
      61            0 :     }
      62              : 
      63              :     /// RVA to the list of exported names
      64            0 :     pub fn names_addr_table_rva(&self) -> u32 {
      65            0 :         self.ptr.names_addr_table_rva()
      66            0 :     }
      67              : 
      68              :     /// Number of exports by name
      69            0 :     pub fn names_addr_table_cnt(&self) -> u32 {
      70            0 :         self.ptr.names_addr_table_cnt()
      71            0 :     }
      72              : 
      73              :     /// RVA of the export address table
      74            0 :     pub fn export_addr_table_rva(&self) -> u32 {
      75            0 :         self.ptr.export_addr_table_rva()
      76            0 :     }
      77              : 
      78              :     /// Number of entries in the export address table
      79            0 :     pub fn export_addr_table_cnt(&self) -> u32 {
      80            0 :         self.ptr.export_addr_table_cnt()
      81            0 :     }
      82              : 
      83              :     /// RVA to the list of exported ordinals
      84            0 :     pub fn ord_addr_table_rva(&self) -> u32 {
      85            0 :         self.ptr.ord_addr_table_rva()
      86            0 :     }
      87              : 
      88              :     /// Change or set the export flags
      89            0 :     pub fn set_export_flags(&mut self, flags: u32) -> &mut Self {
      90            0 :         self.ptr.pin_mut().set_export_flags(flags);
      91            0 :         self
      92            0 :     }
      93              : 
      94              :     /// Change or set the timestamp
      95            0 :     pub fn set_timestamp(&mut self, timestamp: u32) -> &mut Self {
      96            0 :         self.ptr.pin_mut().set_export_flags(timestamp);
      97            0 :         self
      98            0 :     }
      99              : 
     100              :     /// Change or set the major version of the DLL
     101            0 :     pub fn set_major_version(&mut self, version: u32) -> &mut Self {
     102            0 :         self.ptr.pin_mut().set_major_version(version);
     103            0 :         self
     104            0 :     }
     105              : 
     106              :     /// Change or set the minor version of the DLL
     107            0 :     pub fn set_minor_version(&mut self, version: u32) -> &mut Self {
     108            0 :         self.ptr.pin_mut().set_minor_version(version);
     109            0 :         self
     110            0 :     }
     111              : 
     112              :     /// Change or set the name of the DLL
     113            0 :     pub fn set_name(&mut self, name: &str) -> &mut Self {
     114            0 :         self.ptr.pin_mut().set_name(name);
     115            0 :         self
     116            0 :     }
     117              : 
     118              :     /// Find the export entry with the given name
     119            0 :     pub fn entry_by_name(&self, name: &str) -> Option<Entry> {
     120            0 :         into_optional(self.ptr.entry_by_name(name))
     121            0 :     }
     122              : 
     123              :     /// Find the export entry with the given ordinal number
     124            0 :     pub fn entry_by_ordinal(&self, ordinal: u32) -> Option<Entry> {
     125            0 :         into_optional(self.ptr.entry_by_ordinal(ordinal))
     126            0 :     }
     127              : 
     128              :     /// Find the export entry at the provided RVA
     129            0 :     pub fn entry_at_rva(&self, rva: u32) -> Option<Entry> {
     130            0 :         into_optional(self.ptr.entry_at_rva(rva))
     131            0 :     }
     132              : 
     133              :     /// Add the given export and return the newly created and added export
     134            0 :     pub fn add_entry(&mut self, entry: &Entry) -> Entry {
     135            0 :         Entry::from_ffi(self.ptr.pin_mut().add_entry(entry.ptr.as_ref().unwrap()))
     136            0 :     }
     137              : 
     138              :     /// Add a new export entry given its name and its RVA
     139            0 :     pub fn add_entry_by_name(&mut self, name: &str, rva: u32) -> Entry {
     140            0 :         Entry::from_ffi(self.ptr.pin_mut().add_entry_by_name(name, rva))
     141            0 :     }
     142              : 
     143              :     /// Remove the given export entry
     144            0 :     pub fn remove_entry(&mut self, entry: Entry) -> bool {
     145            0 :         self.ptr.pin_mut().remove_entry(entry.ptr)
     146            0 :     }
     147              : 
     148              :     /// Remove the export entry with the given RVA
     149            0 :     pub fn remove_entry_at(&mut self, rva: u32) -> bool {
     150            0 :         self.ptr.pin_mut().remove_entry_at(rva)
     151            0 :     }
     152              : 
     153              :     /// Remove the export entry with the given RVA
     154            0 :     pub fn remove_entry_by_name(&mut self, name: &str) -> bool {
     155            0 :         self.ptr.pin_mut().remove_entry_by_name(name)
     156            0 :     }
     157              : 
     158              : }
     159              : 
     160              : impl std::fmt::Debug for Export<'_> {
     161           80 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     162           80 :         f.debug_struct("Export")
     163           80 :             .field("export_flags", &self.export_flags())
     164           80 :             .field("timestamp", &self.timestamp())
     165           80 :             .field("major_version", &self.major_version())
     166           80 :             .field("minor_version", &self.minor_version())
     167           80 :             .field("ordinal_base", &self.ordinal_base())
     168           80 :             .field("name", &self.name())
     169           80 :             .finish()
     170           80 :     }
     171              : }
     172              : 
     173              : impl<'a> FromFFI<ffi::PE_Export> for Export<'a> {
     174           80 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_Export>) -> Self {
     175           80 :         Export {
     176           80 :             ptr,
     177           80 :             _owner: PhantomData,
     178           80 :         }
     179           80 :     }
     180              : }
     181              : 
     182              : impl<'a> AsFFI<ffi::PE_Export> for Export<'a> {
     183            0 :     fn as_ffi(&self) -> &ffi::PE_Export {
     184            0 :         self.ptr.as_ref().unwrap()
     185            0 :     }
     186              : 
     187            0 :     fn as_mut_ffi(&mut self) -> std::pin::Pin<&mut ffi::PE_Export> {
     188            0 :         self.ptr.pin_mut()
     189            0 :     }
     190              : }
     191              : 
     192              : /// Structure which represents an entry in the export table.
     193              : ///
     194              : /// It implements the [`generic::Symbol`] trait that exposes [`generic::Symbol::name`] and
     195              : /// [`generic::Symbol::value`].
     196              : pub struct Entry<'a> {
     197              :     ptr: cxx::UniquePtr<ffi::PE_ExportEntry>,
     198              :     _owner: PhantomData<&'a ffi::PE_Export>,
     199              : }
     200              : 
     201              : impl Entry<'_> {
     202              :     /// Ordinal value associated with this exported entry.
     203              :     ///
     204              :     /// This value is computed as the index of this entry in the address table
     205              :     /// plus the ordinal base ([`Export::ordinal_base`])
     206       124260 :     pub fn ordinal(&self) -> u16 {
     207       124260 :         self.ptr.ordinal()
     208       124260 :     }
     209              : 
     210              :     /// Address of the current exported function in the DLL.
     211              :     ///
     212              :     /// If this entry is **external** to the DLL then it returns 0
     213              :     /// and the external address is returned by [`Entry::function_rva`]
     214       124260 :     pub fn address(&self) -> u32 {
     215       124260 :         self.ptr.address()
     216       124260 :     }
     217              : 
     218            0 :     pub fn function_rva(&self) -> u32 {
     219            0 :         self.ptr.function_rva()
     220            0 :     }
     221              : 
     222            0 :     pub fn is_extern(&self) -> bool {
     223            0 :         self.ptr.is_extern()
     224            0 :     }
     225              : 
     226            0 :     pub fn is_forwarded(&self) -> bool {
     227            0 :         self.ptr.is_forwarded()
     228            0 :     }
     229              : 
     230              :     /// Demangled representation of the symbol or an empty string if it can't
     231              :     /// be demangled
     232            0 :     pub fn demangled_name(&self) -> String {
     233            0 :         self.ptr.demangled_name().to_string()
     234            0 :     }
     235              : 
     236            0 :     pub fn forward_info(&self) -> Option<ForwardInfo> {
     237            0 :         if !self.ptr.is_forwarded() {
     238            0 :             return None;
     239            0 :         }
     240            0 :         Some(ForwardInfo::with_values(self.ptr.fwd_library().to_string(), self.ptr.fwd_function().to_string()))
     241            0 :     }
     242              : 
     243            0 :     pub fn set_ordinal(&mut self, ordinal: u16) -> &mut Self {
     244            0 :         self.ptr.pin_mut().set_ordinal(ordinal);
     245            0 :         self
     246            0 :     }
     247              : 
     248            0 :     pub fn set_address(&mut self, address: u32) -> &mut Self {
     249            0 :         self.ptr.pin_mut().set_address(address);
     250            0 :         self
     251            0 :     }
     252              : }
     253              : 
     254              : impl generic::Symbol for Entry<'_> {
     255       372780 :     fn as_generic(&self) -> &ffi::AbstractSymbol {
     256       372780 :         self.ptr.as_ref().unwrap().as_ref()
     257       372780 :     }
     258              : }
     259              : 
     260              : impl std::fmt::Debug for Entry<'_> {
     261       124260 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     262       124260 :         let base = self as &dyn generic::Symbol;
     263       124260 :         f.debug_struct("ExportEntry")
     264       124260 :             .field("base", &base)
     265       124260 :             .field("ordinal", &self.ordinal())
     266       124260 :             .field("address", &self.address())
     267       124260 :             .finish()
     268       124260 :     }
     269              : }
     270              : 
     271              : impl<'a> FromFFI<ffi::PE_ExportEntry> for Entry<'a> {
     272       124260 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ExportEntry>) -> Self {
     273       124260 :         Entry {
     274       124260 :             ptr,
     275       124260 :             _owner: PhantomData,
     276       124260 :         }
     277       124260 :     }
     278              : }
     279              : 
     280              : pub struct ForwardInfo {
     281              :     pub library: String,
     282              :     pub function: String,
     283              : }
     284              : 
     285              : impl ForwardInfo {
     286            0 :     pub fn with_values(library: String, function: String) -> Self {
     287            0 :         Self {
     288            0 :             library, function
     289            0 :         }
     290            0 :     }
     291              : }
     292              : 
     293       124260 : declare_iterator!(
     294       124260 :     ExportEntries,
     295       124260 :     Entry<'a>,
     296       124260 :     ffi::PE_ExportEntry,
     297       124260 :     ffi::PE_Export,
     298       124260 :     ffi::PE_Export_it_entries
     299       124260 : );
        

Generated by: LCOV version 2.1-1