LCOV - code coverage report
Current view: top level - src/pe - binary.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 52.1 % 326 170
Test Date: 2026-02-28:00:00:00 Functions: 52.8 % 89 47

            Line data    Source code
       1              : use lief_ffi as ffi;
       2              : 
       3              : use num_traits::{cast, Num};
       4              : use std::mem::size_of;
       5              : use std::pin::Pin;
       6              : use std::path::Path;
       7              : 
       8              : use super::builder::Config;
       9              : use super::parser_config::Config as ParserConfig;
      10              : use super::data_directory::{DataDirectories, DataDirectory};
      11              : use super::debug::{self, Entries, DebugEntry};
      12              : use super::delay_import::{DelayImport, DelayImports};
      13              : use super::export::Export;
      14              : use super::import::{Import, Imports};
      15              : use super::load_configuration::LoadConfiguration;
      16              : use super::relocation::Relocations;
      17              : use super::resources::{Manager as ResourcesManager, NodeBase};
      18              : use super::resources::Node as ResourceNode;
      19              : use super::rich_header::RichHeader;
      20              : use super::section::{Section, Sections};
      21              : use super::signature::Signatures;
      22              : use super::tls::TLS;
      23              : use super::{data_directory, signature};
      24              : use super::debug::CodeViewPDB;
      25              : use super::exception::RuntimeExceptionFunction;
      26              : use crate::coff;
      27              : use crate::coff::Symbol;
      28              : 
      29              : use crate::common::{into_optional, FromFFI, AsFFI};
      30              : use crate::declare_iterator;
      31              : use crate::generic;
      32              : use crate::to_conv_result;
      33              : use crate::to_slice;
      34              : use crate::Error;
      35              : 
      36              : use super::Algorithms;
      37              : use super::{DosHeader, Header, OptionalHeader};
      38              : 
      39              : /// This is the main interface to read and write PE binary attributes.
      40              : ///
      41              : /// Note that this structure implements the [`generic::Binary`] trait from which other generic
      42              : /// functions are exposed
      43              : ///
      44              : /// ```
      45              : /// fn use_trait(pe: &Binary) {
      46              : ///     let generic_binary = pe as &dyn generic::Binary;
      47              : ///     println!("{}", generic_binary.entrypoint());
      48              : /// }
      49              : ///
      50              : /// ```
      51              : pub struct Binary {
      52              :     ptr: cxx::UniquePtr<ffi::PE_Binary>,
      53              : }
      54              : 
      55              : impl FromFFI<ffi::PE_Binary> for Binary {
      56          300 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_Binary>) -> Self {
      57          300 :         Self { ptr }
      58          300 :     }
      59              : }
      60              : 
      61              : impl Binary {
      62              :     /// Parse from a filepath given as a string
      63            0 :     pub fn parse<P: AsRef<Path>>(path: P) -> Option<Self> {
      64            0 :         let ffi = ffi::PE_Binary::parse(path.as_ref().to_str().unwrap());
      65            0 :         if ffi.is_null() {
      66            0 :             return None;
      67            0 :         }
      68            0 :         Some(Binary::from_ffi(ffi))
      69            0 :     }
      70              : 
      71              :     /// Parse from a string file path and with a provided configuration
      72           12 :     pub fn parse_with_config<P: AsRef<Path>>(path: P, config: &ParserConfig) -> Option<Self> {
      73           12 :         let ffi_config = config.to_ffi();
      74           12 :         let ffi = ffi::PE_Binary::parse_with_config(path.as_ref().to_str().unwrap(), &ffi_config);
      75           12 :         if ffi.is_null() {
      76            0 :             return None;
      77           12 :         }
      78           12 :         Some(Binary::from_ffi(ffi))
      79           12 :     }
      80              : 
      81              :     /// DosHeader which starts the PE files
      82          156 :     pub fn dos_header(&self) -> DosHeader<'_> {
      83          156 :         DosHeader::from_ffi(self.ptr.dos_header())
      84          156 :     }
      85              : 
      86              :     /// Header that follows the [`Binary::header`]. It is named
      87              :     /// *optional* from the COFF specification but it is mandatory in a PE file.
      88          156 :     pub fn optional_header(&self) -> OptionalHeader<'_> {
      89          156 :         OptionalHeader::from_ffi(self.ptr.optional_header())
      90          156 :     }
      91              : 
      92              :     /// Re-compute the value of [`OptionalHeader::checksum`]
      93          156 :     pub fn compute_checksum(&self) -> u32 {
      94          156 :         self.ptr.compute_checksum()
      95          156 :     }
      96              : 
      97              :     /// Next header after the [`Binary::dos_header`]
      98          156 :     pub fn header(&self) -> Header<'_> {
      99          156 :         Header::from_ffi(self.ptr.header())
     100          156 :     }
     101              : 
     102              :     /// Return TLS information if present
     103          156 :     pub fn tls(&self) -> Option<TLS<'_>> {
     104          156 :         into_optional(self.ptr.tls())
     105          156 :     }
     106              : 
     107              :     /// Return rich header information if present.
     108          156 :     pub fn rich_header(&self) -> Option<RichHeader<'_>> {
     109          156 :         into_optional(self.ptr.rich_header())
     110          156 :     }
     111              : 
     112              :     /// Return export information
     113          156 :     pub fn export(&self) -> Option<Export<'_>> {
     114          156 :         into_optional(self.ptr.get_export())
     115          156 :     }
     116              : 
     117              :     /// Return the root of the PE's resource tree
     118          312 :     pub fn resources(&self) -> Option<ResourceNode<'_>> {
     119          312 :         into_optional(self.ptr.resources())
     120          312 :     }
     121              : 
     122              :     /// Return a manager interface to read and manipulate the resources tree with a user friendly
     123              :     /// interface.
     124          156 :     pub fn resources_manager(&self) -> Option<ResourcesManager<'_>> {
     125          156 :         into_optional(self.ptr.resources_manager())
     126          156 :     }
     127              : 
     128              :     /// Return the imports as an **iterator** over the [`Import`] structure
     129          156 :     pub fn imports(&self) -> Imports<'_> {
     130          156 :         Imports::new(self.ptr.imports())
     131          156 :     }
     132              : 
     133              :     /// Return the data directories as an iterator over the [`DataDirectory`] structure
     134          156 :     pub fn data_directories(&self) -> DataDirectories<'_> {
     135          156 :         DataDirectories::new(self.ptr.data_directories())
     136          156 :     }
     137              : 
     138              :     /// Return the sections as an iterator over the [`Section`] structure
     139          156 :     pub fn sections(&self) -> Sections<'_> {
     140          156 :         Sections::new(self.ptr.sections())
     141          156 :     }
     142              : 
     143              :     /// Return the relocations as an iterator over the [`super::Relocation`] structure
     144          156 :     pub fn relocations(&self) -> Relocations<'_> {
     145          156 :         Relocations::new(self.ptr.relocations())
     146          156 :     }
     147              : 
     148              :     /// Return the delayed imports as an iterator over the [`DelayImport`] structure
     149          156 :     pub fn delay_imports(&self) -> DelayImports<'_> {
     150          156 :         DelayImports::new(self.ptr.delay_imports())
     151          156 :     }
     152              : 
     153              :     /// Return an iterator over the [`signature::Signature`] if the current PE is authenticode-signed.
     154          168 :     pub fn signatures(&self) -> Signatures<'_> {
     155          168 :         Signatures::new(self.ptr.signatures())
     156          168 :     }
     157              : 
     158              :     /// Return an iterator over the [`debug::Entries`] of the binary.
     159          156 :     pub fn debug(&self) -> DebugEntries<'_> {
     160          156 :         DebugEntries::new(self.ptr.debug())
     161          156 :     }
     162              : 
     163              :     /// Compute the authentihash for the current PE with the given algorithms.
     164          156 :     pub fn authentihash(&self, algo: Algorithms) -> Vec<u8> {
     165          156 :         Vec::from(self.ptr.authentihash(algo.into()).as_slice())
     166          156 :     }
     167              : 
     168              :     /// Return load configuration info if present.
     169          156 :     pub fn load_configuration(&self) -> Option<LoadConfiguration<'_>> {
     170          156 :         into_optional(self.ptr.load_configuration())
     171          156 :     }
     172              : 
     173              :     /// Return the raw data between the [`Binary::dos_header`] and the regular [`Binary::header`]
     174          156 :     pub fn dos_stub(&self) -> &[u8] {
     175          156 :         to_slice!(self.ptr.dos_stub());
     176          156 :     }
     177              : 
     178              :     /// Return the original overlay data of the file
     179          156 :     pub fn overlay(&self) -> &[u8] {
     180          156 :         to_slice!(self.ptr.overlay());
     181          156 :     }
     182              : 
     183              :     /// Return the offset computed by LIEF to identify overlay data
     184          156 :     pub fn overlay_offset(&self) -> u64 {
     185          156 :         self.ptr.overlay_offset()
     186          156 :     }
     187              : 
     188              :     /// Convert a **relative** virtual address into an offset
     189           12 :     pub fn rva_to_offset(&self, rva: u64) -> u64 {
     190           12 :         self.ptr.rva_to_offset(rva)
     191           12 :     }
     192              : 
     193              :     /// Convert an **absolute** virtual address into an offset.
     194           12 :     pub fn va_to_offset(&self, va: u64) -> u64 {
     195           12 :         self.ptr.va_to_offset(va)
     196           12 :     }
     197              : 
     198              :     /// Return the size of the current binary when loaded in memory.
     199          156 :     pub fn virtual_size(&self) -> u64 {
     200          156 :         self.ptr.virtual_size()
     201          156 :     }
     202              : 
     203              :     /// Compute the size of all the headers.
     204          156 :     pub fn sizeof_headers(&self) -> u64 {
     205          156 :         self.ptr.sizeof_headers()
     206          156 :     }
     207              : 
     208              :     /// Find a section by its offset
     209           24 :     pub fn section_from_offset(&self, offset: u64) -> Option<Section<'_>> {
     210           24 :         into_optional(self.ptr.section_from_offset(offset))
     211           24 :     }
     212              : 
     213              :     /// Find a section by its **relative** virtual address
     214           24 :     pub fn section_from_rva(&self, rva: u64) -> Option<Section<'_>> {
     215           24 :         into_optional(self.ptr.section_from_rva(rva))
     216           24 :     }
     217              : 
     218              :     /// Find a section by its name
     219           24 :     pub fn section_by_name(&self, name: &str) -> Option<Section<'_>> {
     220           24 :         into_optional(self.ptr.section_by_name(name))
     221           24 :     }
     222              : 
     223              :     /// Find the data directory with the given type
     224          168 :     pub fn data_directory_by_type(&self, dir_type: data_directory::Type) -> Option<DataDirectory<'_>> {
     225          168 :         into_optional(self.ptr.data_directory_by_type(dir_type.into()))
     226          168 :     }
     227              : 
     228              :     /// Verify the binary against the embedded signature(s) (if any)
     229              :     ///
     230              :     /// First, it checks that the embedded signatures are correct (c.f. [`signature::Signature::check`])
     231              :     /// and then, it checks that the authentihash matches [`crate::pe::signature::content_info::ContentInfo::digest`]
     232           12 :     pub fn verify_signature(
     233           12 :         &self,
     234           12 :         checks: signature::VerificationChecks,
     235           12 :     ) -> signature::VerificationFlags {
     236           12 :         signature::VerificationFlags::from(self.ptr.verify_signature(checks.into()))
     237           12 :     }
     238              : 
     239              :     /// Verify the binary with the [`signature::Signature`] object provided in the first parameter.
     240              :     /// It can be used to verify a detached signature:
     241              :     ///
     242              :     /// ```
     243              :     /// if let Some(sig) = Signature::from_file(path_str.unwrap()) {
     244              :     ///     pe.verify_signature(&sig, signature::VerificationChecks::DEFAULT);
     245              :     /// }
     246              :     /// ```
     247           12 :     pub fn verify_with_signature(
     248           12 :         &self,
     249           12 :         sig: &signature::Signature,
     250           12 :         checks: signature::VerificationChecks,
     251           12 :     ) -> signature::VerificationFlags {
     252           12 :         signature::VerificationFlags::from(
     253           12 :             self.ptr.verify_with_signature(sig.into(), checks.into()),
     254           12 :         )
     255           12 :     }
     256              : 
     257              :     /// Find an import by its DLL name (case insensitive)
     258           24 :     pub fn import_by_name(&self, name: &str) -> Option<Import<'_>> {
     259           24 :         into_optional(self.ptr.import_by_name(name))
     260           24 :     }
     261              : 
     262              :     /// Find a delayed import by its name
     263           24 :     pub fn delay_import_by_name(&self, name: &str) -> Option<DelayImport<'_>> {
     264           24 :         into_optional(self.ptr.delay_import_by_name(name))
     265           24 :     }
     266              : 
     267              :     /// Return the sized content from the virtual address
     268           36 :     pub fn content_from_virtual_address(&self, address: u64, size: u64) -> &[u8] {
     269           36 :         to_slice!(self.ptr.get_content_from_virtual_address(address, size));
     270           36 :     }
     271              : 
     272          156 :     pub fn functions(&self) -> generic::Functions<'_> {
     273          156 :         generic::Functions::new(self.ptr.functions())
     274          156 :     }
     275              : 
     276              :     /// Return the data directory associated with the export table
     277            0 :     pub fn export_dir(&self) -> Option<DataDirectory<'_>> {
     278            0 :         into_optional(self.ptr.export_dir())
     279            0 :     }
     280              : 
     281              :     /// Return the data directory associated with the import table
     282            0 :     pub fn import_dir(&self) -> Option<DataDirectory<'_>> {
     283            0 :         into_optional(self.ptr.import_dir())
     284            0 :     }
     285              : 
     286              :     /// Return the data directory associated with the resources tree
     287            0 :     pub fn rsrc_dir(&self) -> Option<DataDirectory<'_>> {
     288            0 :         into_optional(self.ptr.rsrc_dir())
     289            0 :     }
     290              : 
     291              :     /// Return the data directory associated with the exceptions
     292            0 :     pub fn exceptions_dir(&self) -> Option<DataDirectory<'_>> {
     293            0 :         into_optional(self.ptr.exceptions_dir())
     294            0 :     }
     295              : 
     296              :     /// Return the data directory associated with the certificate table
     297              :     /// (authenticode)
     298            0 :     pub fn cert_dir(&self) -> Option<DataDirectory<'_>> {
     299            0 :         into_optional(self.ptr.cert_dir())
     300            0 :     }
     301              : 
     302              :     /// Return the data directory associated with the relocation table
     303            0 :     pub fn relocation_dir(&self) -> Option<DataDirectory<'_>> {
     304            0 :         into_optional(self.ptr.relocation_dir())
     305            0 :     }
     306              : 
     307              :     /// Return the data directory associated with the debug table
     308            0 :     pub fn debug_dir(&self) -> Option<DataDirectory<'_>> {
     309            0 :         into_optional(self.ptr.debug_dir())
     310            0 :     }
     311              : 
     312              :     /// Return the data directory associated with TLS
     313            0 :     pub fn tls_dir(&self) -> Option<DataDirectory<'_>> {
     314            0 :         into_optional(self.ptr.tls_dir())
     315            0 :     }
     316              : 
     317              :     /// Return the data directory associated with the load config
     318            0 :     pub fn load_config_dir(&self) -> Option<DataDirectory<'_>> {
     319            0 :         into_optional(self.ptr.load_config_dir())
     320            0 :     }
     321              : 
     322              :     /// Return the data directory associated with the IAT
     323            0 :     pub fn iat_dir(&self) -> Option<DataDirectory<'_>> {
     324            0 :         into_optional(self.ptr.iat_dir())
     325            0 :     }
     326              : 
     327              :     /// Return the data directory associated with delayed imports
     328            0 :     pub fn export_delay_dirdir(&self) -> Option<DataDirectory<'_>> {
     329            0 :         into_optional(self.ptr.delay_dir())
     330            0 :     }
     331              : 
     332              :     /// Get the integer value at the given virtual address
     333            0 :     pub fn get_int_from_virtual_address<T>(&self, addr: u64) -> Result<T, Error>
     334            0 :     where
     335            0 :         T: Num + cast::FromPrimitive + cast::ToPrimitive,
     336            0 :     {
     337            0 :         // Can't be in the generic trait because of:
     338            0 :         //   > for a trait to be "object safe" it needs to allow building a vtable to allow the call
     339            0 :         //   > to be resolvable dynamically; for more information visit
     340            0 :         //   > https://doc.rust-lang.org/reference/items/traits.html#object-safety
     341            0 :         if size_of::<T>() == size_of::<u8>() {
     342            0 :             to_conv_result!(
     343            0 :                 ffi::AbstractBinary::get_u8,
     344            0 :                 self.ptr.as_ref().unwrap().as_ref(),
     345            0 :                 |value| {
     346            0 :                     T::from_u8(value).unwrap_or_else(|| panic!("Can't cast value: {value}"))
     347            0 :                 },
     348            0 :                 addr
     349              :             );
     350            0 :         }
     351            0 : 
     352            0 :         if size_of::<T>() == size_of::<u16>() {
     353            0 :             to_conv_result!(
     354            0 :                 ffi::AbstractBinary::get_u16,
     355            0 :                 self.ptr.as_ref().unwrap().as_ref(),
     356            0 :                 |value| {
     357            0 :                     T::from_u16(value).unwrap_or_else(|| panic!("Can't cast value: {value}"))
     358            0 :                 },
     359            0 :                 addr
     360              :             );
     361            0 :         }
     362            0 : 
     363            0 :         if size_of::<T>() == size_of::<u32>() {
     364            0 :             to_conv_result!(
     365            0 :                 ffi::AbstractBinary::get_u32,
     366            0 :                 self.ptr.as_ref().unwrap().as_ref(),
     367            0 :                 |value| {
     368            0 :                     T::from_u32(value).unwrap_or_else(|| panic!("Can't cast value: {value}"))
     369            0 :                 },
     370            0 :                 addr
     371              :             );
     372            0 :         }
     373            0 : 
     374            0 :         if size_of::<T>() == size_of::<u64>() {
     375            0 :             to_conv_result!(
     376            0 :                 ffi::AbstractBinary::get_u64,
     377            0 :                 self.ptr.as_ref().unwrap().as_ref(),
     378            0 :                 |value| {
     379            0 :                     T::from_u64(value).unwrap_or_else(|| panic!("Can't cast value: {value}"))
     380            0 :                 },
     381            0 :                 addr
     382              :             );
     383            0 :         }
     384            0 : 
     385            0 :         Err(Error::NotSupported)
     386            0 :     }
     387              : 
     388              :     /// Add an imported library (i.e. `DLL`) to the binary
     389            0 :     pub fn add_import<'a>(&'a mut self, name: &str) -> Import<'a> {
     390            0 :         Import::from_ffi(self.ptr.pin_mut().add_import(name))
     391            0 :     }
     392              : 
     393              :     /// Add an imported library (i.e. `DLL`) to the binary.
     394              :     ///
     395              :     /// The second parameter `pos` defines where to insert the import.
     396            0 :     pub fn add_import_at_pos<'a>(&'a mut self, name: &str, pos: u32) -> Import<'a> {
     397            0 :         Import::from_ffi(self.ptr.pin_mut().add_import_pos(name, pos))
     398            0 :     }
     399              : 
     400              :     /// Remove the imported library with the given `name`
     401            0 :     pub fn remove_import(&mut self, name: &str) {
     402            0 :         self.ptr.pin_mut().remove_import(name);
     403            0 :     }
     404              : 
     405              :     /// Remove all libraries in the binary
     406            0 :     pub fn remove_all_imports(&mut self) {
     407            0 :         self.ptr.pin_mut().remove_all_imports();
     408            0 :     }
     409              : 
     410              :     /// Remove the TLS from the binary
     411            0 :     pub fn remove_tls(&mut self) {
     412            0 :         self.ptr.pin_mut().remove_tls();
     413            0 :     }
     414              : 
     415              :     /// Set or change the TLS information
     416            0 :     pub fn set_tls(&mut self, tls: &TLS) {
     417            0 :         self.ptr.pin_mut().set_tls(tls.as_ffi());
     418            0 :     }
     419              : 
     420              :     /// Change or set the resources tree to given node
     421            0 :     pub fn set_resources(&mut self, node: &dyn NodeBase) {
     422            0 :         self.ptr.pin_mut().set_resources(node.get_base());
     423            0 :     }
     424              : 
     425              :     /// Add a new debug entry
     426            0 :     pub fn add_debug_info<'a>(&'a mut self, entry: &dyn DebugEntry) -> Option<Entries<'a>> {
     427            0 :         into_optional(self.ptr.pin_mut().add_debug_info(entry.get_base()))
     428            0 :     }
     429              : 
     430              :     /// Remove a specific debug entry
     431            0 :     pub fn remove_debug(&mut self, entry: &dyn DebugEntry) -> bool {
     432            0 :         self.ptr.pin_mut().remove_debug(entry.get_base())
     433            0 :     }
     434              : 
     435              :     /// Remove all debug info
     436            0 :     pub fn clear_debug(&mut self) -> bool {
     437            0 :         self.ptr.pin_mut().clear_debug()
     438            0 :     }
     439              : 
     440              :     /// Return the [`CodeViewPDB`] object if present
     441            0 :     pub fn codeview_pdb(&self) -> Option<CodeViewPDB<'_>> {
     442            0 :         into_optional(self.ptr.codeview_pdb())
     443            0 :     }
     444              : 
     445              :     /// Write back the current PE binary into the file specified in parameter
     446            0 :     pub fn write<P: AsRef<Path>>(&mut self, output: P) {
     447            0 :         self.ptr.as_mut().unwrap().write(output.as_ref().to_str().unwrap());
     448            0 :     }
     449              : 
     450              :     /// Write back the current PE binary into the file specified in parameter with the
     451              :     /// configuration provided in the second parameter.
     452            0 :     pub fn write_with_config<P: AsRef<Path>>(&mut self, output: P, config: Config) {
     453            0 :         let ffi_config = config.to_ffi();
     454            0 :         self.ptr.as_mut().unwrap().write_with_config(output.as_ref().to_str().unwrap(),
     455            0 :             ffi_config.as_ref().unwrap());
     456            0 :     }
     457              : 
     458              :     /// Iterator over the strings located in the COFF string table
     459          156 :     pub fn coff_string_table(&self) -> COFFStrings<'_> {
     460          156 :         COFFStrings::new(self.ptr.coff_string_table())
     461          156 :     }
     462              : 
     463              :     /// Return an iterator over the binary (COFF) symbols (if any).
     464          156 :     pub fn symbols(&self) -> Symbols<'_> {
     465          156 :         Symbols::new(self.ptr.symbols())
     466          156 :     }
     467              : 
     468              :     /// Try to find the COFF string at the given offset in the COFF string table.
     469              :     ///
     470              :     /// <div class="warning">
     471              :     /// This offset must include the first 4 bytes holding the size of the table.
     472              :     /// Hence, the first string starts a the offset 4.
     473              :     /// </div>
     474            0 :     pub fn find_coff_string_at(&self, offset: u32) -> Option<coff::String<'_>> {
     475            0 :         into_optional(self.ptr.find_coff_string_at(offset))
     476            0 :     }
     477              : 
     478              :     /// Iterator over the exception (`_RUNTIME_FUNCTION`) functions
     479              :     ///
     480              :     /// This function requires that the option [`ParserConfig::parse_exceptions`] was turned on
     481              :     /// (default is `false`) when parsing the binary.
     482          156 :     pub fn exceptions(&self) -> Exceptions<'_> {
     483          156 :         Exceptions::new(self.ptr.exceptions())
     484          156 :     }
     485              : 
     486              :     /// Try to find the exception info at the given RVA
     487              :     ///
     488              :     /// This function requires that the option [`ParserConfig::parse_exceptions`] was turned on
     489              :     /// (default is `false`) when parsing the binary.
     490            0 :     pub fn find_exception_at(&self, rva: u32) -> Option<RuntimeExceptionFunction<'_>> {
     491            0 :         into_optional(self.ptr.find_exception_at(rva))
     492            0 :     }
     493              : 
     494              :     /// True if this binary is compiled in ARM64EC mode (emulation compatible)
     495            0 :     pub fn is_arm64ec(&self) -> bool {
     496            0 :         self.ptr.is_arm64ec()
     497            0 :     }
     498              : 
     499              :     /// True if this binary is compiled in ARM64X mode (contains both ARM64 and ARM64EC).
     500            0 :     pub fn is_arm64x(&self) -> bool {
     501            0 :         self.ptr.is_arm64x()
     502            0 :     }
     503              : 
     504              :     /// If the current binary contains dynamic relocations
     505              :     /// (e.g. LIEF::PE::DynamicFixupARM64X), this function returns the
     506              :     /// **relocated** view of the current PE.
     507              :     ///
     508              :     /// This can be used to get the alternative PE binary, targeting a different
     509              :     /// architectures.
     510              :     ///
     511              :     /// <div class="warning">
     512              :     /// This function is <b>moving</b> and taking the ownership of the nested
     513              :     /// PE binary. This means that subsequent calls to this function will return None.
     514              :     /// </div>
     515              :     ///
     516              :     /// This function requires that the option [`ParserConfig::parse_arm64x_binary`] was turned on
     517              :     /// (default is `false`) when parsing the binary.
     518          156 :     pub fn nested_pe_binary(&self) -> Option<Binary> {
     519          156 :         into_optional(self.ptr.nested_pe_binary())
     520          156 :     }
     521              : 
     522              :     /// Set or change the export table
     523            0 :     pub fn set_export(&mut self, export: &Export) {
     524            0 :         self.ptr.pin_mut().set_export(export.as_ffi());
     525            0 :     }
     526              : }
     527              : 
     528              : impl std::fmt::Debug for Binary {
     529          156 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     530          156 :         f.debug_struct("Binary").finish()
     531          156 :     }
     532              : }
     533              : 
     534              : impl generic::Binary for Binary {
     535          156 :     fn as_generic(&self) -> &ffi::AbstractBinary {
     536          156 :         self.ptr.as_ref().unwrap().as_ref()
     537          156 :     }
     538              : 
     539            0 :     fn as_pin_mut_generic(&mut self) -> Pin<&mut ffi::AbstractBinary> {
     540            0 :         unsafe {
     541            0 :             Pin::new_unchecked({
     542            0 :                 (self.ptr.as_ref().unwrap().as_ref()
     543            0 :                     as *const ffi::AbstractBinary
     544            0 :                     as *mut ffi::AbstractBinary).as_mut().unwrap()
     545            0 :             })
     546            0 :         }
     547            0 :     }
     548              : }
     549              : 
     550          372 : declare_iterator!(
     551          372 :     DebugEntries,
     552          372 :     debug::Entries<'a>,
     553          372 :     ffi::PE_Debug,
     554          372 :     ffi::PE_Binary,
     555          372 :     ffi::PE_Binary_it_debug
     556          372 : );
     557              : 
     558              : 
     559       295860 : declare_iterator!(
     560       295860 :     COFFStrings,
     561       295860 :     coff::String<'a>,
     562       295860 :     ffi::PE_COFFString,
     563       295860 :     ffi::PE_Binary,
     564       295860 :     ffi::PE_Binary_it_strings_table
     565       295860 : );
     566              : 
     567       366204 : declare_iterator!(
     568       366204 :     Symbols,
     569       366204 :     Symbol<'a>,
     570       366204 :     ffi::PE_Symbol,
     571       366204 :     ffi::PE_Binary,
     572       366204 :     ffi::PE_Binary_it_symbols
     573       366204 : );
     574              : 
     575       925308 : declare_iterator!(
     576       925308 :     Exceptions,
     577       925308 :     RuntimeExceptionFunction<'a>,
     578       925308 :     ffi::PE_ExceptionInfo,
     579       925308 :     ffi::PE_Binary,
     580       925308 :     ffi::PE_Binary_it_exceptions
     581       925308 : );
        

Generated by: LCOV version 2.1-1