LCOV - code coverage report
Current view: top level - src/pe - export.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 37.4 % 179 67
Test Date: 2025-06-24:00:00:00 Functions: 32.6 % 46 15

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

Generated by: LCOV version 2.1-1