LCOV - code coverage report
Current view: top level - src/pe - binary.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 52.6 % 323 170
Test Date: 2025-02-23:00:00:00 Functions: 57.3 % 82 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::symbol::Symbol;
      26              : use super::exception::RuntimeExceptionFunction;
      27              : use super::coff;
      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          250 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_Binary>) -> Self {
      57          250 :         Self { ptr }
      58          250 :     }
      59              : }
      60              : 
      61              : impl Binary {
      62              :     /// Parse from a file path given as a string
      63            0 :     pub fn parse(path: &str) -> Option<Self> {
      64            0 :         let ffi = ffi::PE_Binary::parse(path);
      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          120 :     pub fn parse_with_config(path: &str, config: ParserConfig) -> Option<Self> {
      73          120 :         let ffi_config = config.to_ffi();
      74          120 :         let ffi = ffi::PE_Binary::parse_with_config(path, &ffi_config);
      75          120 :         if ffi.is_null() {
      76            0 :             return None;
      77          120 :         }
      78          120 :         Some(Binary::from_ffi(ffi))
      79          120 :     }
      80              : 
      81              :     /// DosHeader which starts the PE files
      82          130 :     pub fn dos_header(&self) -> DosHeader {
      83          130 :         DosHeader::from_ffi(self.ptr.dos_header())
      84          130 :     }
      85              : 
      86              :     /// Header that follows the [`Binary::header`]. It is named
      87              :     /// *optional* from the COFF specfication but it is mandatory in a PE file.
      88          130 :     pub fn optional_header(&self) -> OptionalHeader {
      89          130 :         OptionalHeader::from_ffi(self.ptr.optional_header())
      90          130 :     }
      91              : 
      92              :     /// Re-compute the value of [`OptionalHeader::checksum`]
      93          130 :     pub fn compute_checksum(&self) -> u32 {
      94          130 :         self.ptr.compute_checksum()
      95          130 :     }
      96              : 
      97              :     /// Next header after the [`Binary::dos_header`]
      98          130 :     pub fn header(&self) -> Header {
      99          130 :         Header::from_ffi(self.ptr.header())
     100          130 :     }
     101              : 
     102              :     /// Return TLS information if present
     103          130 :     pub fn tls(&self) -> Option<TLS> {
     104          130 :         into_optional(self.ptr.tls())
     105          130 :     }
     106              : 
     107              :     /// Return rich header information if present.
     108          130 :     pub fn rich_header(&self) -> Option<RichHeader> {
     109          130 :         into_optional(self.ptr.rich_header())
     110          130 :     }
     111              : 
     112              :     /// Return export information
     113          130 :     pub fn export(&self) -> Option<Export> {
     114          130 :         into_optional(self.ptr.get_export())
     115          130 :     }
     116              : 
     117              :     /// Return the root of the PE's resource tree
     118          260 :     pub fn resources(&self) -> Option<ResourceNode> {
     119          260 :         into_optional(self.ptr.resources())
     120          260 :     }
     121              : 
     122              :     /// Return a manager interface to read and manipulate the resources tree with a user friendly
     123              :     /// interface.
     124          130 :     pub fn resources_manager(&self) -> Option<ResourcesManager> {
     125          130 :         into_optional(self.ptr.resources_manager())
     126          130 :     }
     127              : 
     128              :     /// Return the imports as an **iterator** over the [`Import`] structure
     129          130 :     pub fn imports(&self) -> Imports {
     130          130 :         Imports::new(self.ptr.imports())
     131          130 :     }
     132              : 
     133              :     /// Return the data directories as an iterator over the [`DataDirectory`] structure
     134          130 :     pub fn data_directories(&self) -> DataDirectories {
     135          130 :         DataDirectories::new(self.ptr.data_directories())
     136          130 :     }
     137              : 
     138              :     /// Return the sections as an iterator over the [`Section`] structure
     139          130 :     pub fn sections(&self) -> Sections {
     140          130 :         Sections::new(self.ptr.sections())
     141          130 :     }
     142              : 
     143              :     /// Return the relocations as an iterator over the [`super::Relocation`] structure
     144          130 :     pub fn relocations(&self) -> Relocations {
     145          130 :         Relocations::new(self.ptr.relocations())
     146          130 :     }
     147              : 
     148              :     /// Return the delayed imports as an iterator over the [`DelayImport`] structure
     149          130 :     pub fn delay_imports(&self) -> DelayImports {
     150          130 :         DelayImports::new(self.ptr.delay_imports())
     151          130 :     }
     152              : 
     153              :     /// Return an iterator over the [`signature::Signature`] if the current PE is authenticode-signed.
     154          140 :     pub fn signatures(&self) -> Signatures {
     155          140 :         Signatures::new(self.ptr.signatures())
     156          140 :     }
     157              : 
     158              :     /// Return an iterator over the [`debug::Entries`] of the binary.
     159          130 :     pub fn debug(&self) -> DebugEntries {
     160          130 :         DebugEntries::new(self.ptr.debug())
     161          130 :     }
     162              : 
     163              :     /// Compute the authentihash for the current PE with the given algorithms.
     164          130 :     pub fn authentihash(&self, algo: Algorithms) -> Vec<u8> {
     165          130 :         Vec::from(self.ptr.authentihash(algo.into()).as_slice())
     166          130 :     }
     167              : 
     168              :     /// Return load configuration info if present.
     169          130 :     pub fn load_configuration(&self) -> Option<LoadConfiguration> {
     170          130 :         into_optional(self.ptr.load_configuration())
     171          130 :     }
     172              : 
     173              :     /// Return the raw data between the [`Binary::dos_header`] and the regular [`Binary::header`]
     174          130 :     pub fn dos_stub(&self) -> &[u8] {
     175          130 :         to_slice!(self.ptr.dos_stub());
     176          130 :     }
     177              : 
     178              :     /// Return the original overlay data of the file
     179          130 :     pub fn overlay(&self) -> &[u8] {
     180          130 :         to_slice!(self.ptr.overlay());
     181          130 :     }
     182              : 
     183              :     /// Return the offset computed by LIEF to identify overlay data
     184          130 :     pub fn overlay_offset(&self) -> u64 {
     185          130 :         self.ptr.overlay_offset()
     186          130 :     }
     187              : 
     188              :     /// Convert a **relative** virtual address into an offset
     189           10 :     pub fn rva_to_offset(&self, rva: u64) -> u64 {
     190           10 :         self.ptr.rva_to_offset(rva)
     191           10 :     }
     192              : 
     193              :     /// Convert an **absolute** virtual address into an offset.
     194           10 :     pub fn va_to_offset(&self, va: u64) -> u64 {
     195           10 :         self.ptr.va_to_offset(va)
     196           10 :     }
     197              : 
     198              :     /// Return the size of the current binary when loaded in memory.
     199          130 :     pub fn virtual_size(&self) -> u64 {
     200          130 :         self.ptr.virtual_size()
     201          130 :     }
     202              : 
     203              :     /// Compute the size of all the headers.
     204          130 :     pub fn sizeof_headers(&self) -> u64 {
     205          130 :         self.ptr.sizeof_headers()
     206          130 :     }
     207              : 
     208              :     /// Find a section by its offset
     209           20 :     pub fn section_from_offset(&self, offset: u64) -> Option<Section> {
     210           20 :         into_optional(self.ptr.section_from_offset(offset))
     211           20 :     }
     212              : 
     213              :     /// Find a section by its **relative** virtual address
     214           20 :     pub fn section_from_rva(&self, rva: u64) -> Option<Section> {
     215           20 :         into_optional(self.ptr.section_from_rva(rva))
     216           20 :     }
     217              : 
     218              :     /// Find a section by its name
     219           20 :     pub fn section_by_name(&self, name: &str) -> Option<Section> {
     220           20 :         into_optional(self.ptr.section_by_name(name))
     221           20 :     }
     222              : 
     223              :     /// Find the data directory with the given type
     224          140 :     pub fn data_directory_by_type(&self, dir_type: data_directory::Type) -> Option<DataDirectory> {
     225          140 :         into_optional(self.ptr.data_directory_by_type(dir_type.into()))
     226          140 :     }
     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           10 :     pub fn verify_signature(
     233           10 :         &self,
     234           10 :         checks: signature::VerificationChecks,
     235           10 :     ) -> signature::VerificationFlags {
     236           10 :         signature::VerificationFlags::from(self.ptr.verify_signature(checks.into()))
     237           10 :     }
     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           10 :     pub fn verify_with_signature(
     248           10 :         &self,
     249           10 :         sig: &signature::Signature,
     250           10 :         checks: signature::VerificationChecks,
     251           10 :     ) -> signature::VerificationFlags {
     252           10 :         signature::VerificationFlags::from(
     253           10 :             self.ptr.verify_with_signature(sig.into(), checks.into()),
     254           10 :         )
     255           10 :     }
     256              : 
     257              :     /// Find an import by its DLL name (case insensitive)
     258           20 :     pub fn import_by_name(&self, name: &str) -> Option<Import> {
     259           20 :         into_optional(self.ptr.import_by_name(name))
     260           20 :     }
     261              : 
     262              :     /// Find a delayed import by its name
     263           20 :     pub fn delay_import_by_name(&self, name: &str) -> Option<DelayImport> {
     264           20 :         into_optional(self.ptr.delay_import_by_name(name))
     265           20 :     }
     266              : 
     267              :     /// Return the sized content from the virtual address
     268           30 :     pub fn content_from_virtual_address(&self, address: u64, size: u64) -> &[u8] {
     269           30 :         to_slice!(self.ptr.get_content_from_virtual_address(address, size));
     270           30 :     }
     271              : 
     272          130 :     pub fn functions(&self) -> generic::Functions {
     273          130 :         generic::Functions::new(self.ptr.functions())
     274          130 :     }
     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).expect(format!("Can't cast value: {}", value).as_str())
     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).expect(format!("Can't cast value: {}", value).as_str())
     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).expect(format!("Can't cast value: {}", value).as_str())
     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).expect(format!("Can't cast value: {}", value).as_str())
     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              :     /// Remove the imported library with the given `name`
     394            0 :     pub fn remove_import(&mut self, name: &str) {
     395            0 :         self.ptr.pin_mut().remove_import(name);
     396            0 :     }
     397              : 
     398              :     /// Remove all libraries in the binary
     399            0 :     pub fn remove_all_imports(&mut self) {
     400            0 :         self.ptr.pin_mut().remove_all_imports();
     401            0 :     }
     402              : 
     403              :     /// Remove the TLS from the binary
     404            0 :     pub fn remove_tls(&mut self) {
     405            0 :         self.ptr.pin_mut().remove_tls();
     406            0 :     }
     407              : 
     408              :     /// Set or change the TLS information
     409            0 :     pub fn set_tls(&mut self, tls: &TLS) {
     410            0 :         self.ptr.pin_mut().set_tls(tls.as_ffi());
     411            0 :     }
     412              : 
     413              :     /// Change or set the resources tree to given node
     414            0 :     pub fn set_resources(&mut self, node: &dyn NodeBase) {
     415            0 :         self.ptr.pin_mut().set_resources(node.get_base());
     416            0 :     }
     417              : 
     418              :     /// Add a new debug entry
     419            0 :     pub fn add_debug_info<'a>(&'a mut self, entry: &dyn DebugEntry) -> Option<Entries<'a>> {
     420            0 :         into_optional(self.ptr.pin_mut().add_debug_info(entry.get_base()))
     421            0 :     }
     422              : 
     423              :     /// Remove a specific debug entry
     424            0 :     pub fn remove_debug<'a>(&'a mut self, entry: &dyn DebugEntry) -> bool {
     425            0 :         self.ptr.pin_mut().remove_debug(entry.get_base())
     426            0 :     }
     427              : 
     428              :     /// Remove all debug info
     429            0 :     pub fn clear_debug<'a>(&'a mut self) -> bool {
     430            0 :         self.ptr.pin_mut().clear_debug()
     431            0 :     }
     432              : 
     433              :     /// Return the [`CodeViewPDB`] object if present
     434            0 :     pub fn codeview_pdb(&self) -> Option<CodeViewPDB> {
     435            0 :         into_optional(self.ptr.codeview_pdb())
     436            0 :     }
     437              : 
     438              :     /// Write back the current PE binary into the file specified in parameter
     439            0 :     pub fn write(&mut self, output: &Path) {
     440            0 :         self.ptr.as_mut().unwrap().write(output.to_str().unwrap());
     441            0 :     }
     442              : 
     443              :     /// Write back the current PE binary into the file specified in parameter with the
     444              :     /// configuration provided in the second parameter.
     445            0 :     pub fn write_with_config(&mut self, output: &Path, config: Config) {
     446            0 :         let ffi_config = config.to_ffi();
     447            0 :         self.ptr.as_mut().unwrap().write_with_config(output.to_str().unwrap(),
     448            0 :             &ffi_config.as_ref().unwrap());
     449            0 :     }
     450              : 
     451              :     /// Iterator over the strings located in the COFF string table
     452          130 :     pub fn coff_string_table(&self) -> COFFStrings {
     453          130 :         COFFStrings::new(self.ptr.coff_string_table())
     454          130 :     }
     455              : 
     456              :     /// Return an iterator over the binary (COFF) symbols (if any).
     457          130 :     pub fn symbols(&self) -> Symbols {
     458          130 :         Symbols::new(self.ptr.symbols())
     459          130 :     }
     460              : 
     461              :     /// Try to find the COFF string at the given offset in the COFF string table.
     462              :     ///
     463              :     /// <div class="warning">
     464              :     /// This offset must include the first 4 bytes holding the size of the table.
     465              :     /// Hence, the first string starts a the offset 4.
     466              :     /// </div>
     467            0 :     pub fn find_coff_string_at(&self, offset: u32) -> Option<coff::String> {
     468            0 :         into_optional(self.ptr.find_coff_string_at(offset))
     469            0 :     }
     470              : 
     471              :     /// Iterator over the exception (`_RUNTIME_FUNCTION`) functions
     472              :     ///
     473              :     /// This function requires that the option [`ParserConfig::parse_exceptions`] was turned on
     474              :     /// (default is `false`) when parsing the binary.
     475          130 :     pub fn exceptions(&self) -> Exceptions {
     476          130 :         Exceptions::new(self.ptr.exceptions())
     477          130 :     }
     478              : 
     479              :     /// Try to find the exception info at the given RVA
     480              :     ///
     481              :     /// This function requires that the option [`ParserConfig::parse_exceptions`] was turned on
     482              :     /// (default is `false`) when parsing the binary.
     483            0 :     pub fn find_exception_at(&self, rva: u32) -> Option<RuntimeExceptionFunction> {
     484            0 :         into_optional(self.ptr.find_exception_at(rva))
     485            0 :     }
     486              : 
     487              :     /// True if this binary is compiled in ARM64EC mode (emulation compatible)
     488            0 :     pub fn is_arm64ec(&self) -> bool {
     489            0 :         self.ptr.is_arm64ec()
     490            0 :     }
     491              : 
     492              :     /// True if this binary is compiled in ARM64X mode (contains both ARM64 and ARM64EC).
     493            0 :     pub fn is_arm64x(&self) -> bool {
     494            0 :         self.ptr.is_arm64x()
     495            0 :     }
     496              : 
     497              :     /// If the current binary contains dynamic relocations
     498              :     /// (e.g. LIEF::PE::DynamicFixupARM64X), this function returns the
     499              :     /// **relocated** view of the current PE.
     500              :     ///
     501              :     /// This can be used to get the alternative PE binary, targeting a different
     502              :     /// architectures.
     503              :     ///
     504              :     /// <div class="warning">
     505              :     /// This function is <b>moving</b> and taking the ownership of the nested
     506              :     /// PE binary. This means that subsequent calls to this function will return None.
     507              :     /// </div>
     508              :     ///
     509              :     /// This function requires that the option [`ParserConfig::parse_arm64x_binary`] was turned on
     510              :     /// (default is `false`) when parsing the binary.
     511          130 :     pub fn nested_pe_binary(&self) -> Option<Binary> {
     512          130 :         into_optional(self.ptr.nested_pe_binary())
     513          130 :     }
     514              : 
     515              :     /// Set or change the export table
     516            0 :     pub fn set_export(&mut self, export: &Export) {
     517            0 :         self.ptr.pin_mut().set_export(export.as_ffi());
     518            0 :     }
     519              : }
     520              : 
     521              : impl std::fmt::Debug for Binary {
     522          130 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     523          130 :         f.debug_struct("Binary").finish()
     524          130 :     }
     525              : }
     526              : 
     527              : impl generic::Binary for Binary {
     528          130 :     fn as_generic(&self) -> &ffi::AbstractBinary {
     529          130 :         self.ptr.as_ref().unwrap().as_ref()
     530          130 :     }
     531              : 
     532            0 :     fn as_pin_mut_generic(&mut self) -> Pin<&mut ffi::AbstractBinary> {
     533            0 :         unsafe {
     534            0 :             Pin::new_unchecked({
     535            0 :                 (self.ptr.as_ref().unwrap().as_ref()
     536            0 :                     as *const ffi::AbstractBinary
     537            0 :                     as *mut ffi::AbstractBinary).as_mut().unwrap()
     538            0 :             })
     539            0 :         }
     540            0 :     }
     541              : }
     542              : 
     543          310 : declare_iterator!(
     544          310 :     DebugEntries,
     545          310 :     debug::Entries<'a>,
     546          310 :     ffi::PE_Debug,
     547          310 :     ffi::PE_Binary,
     548          310 :     ffi::PE_Binary_it_debug
     549          310 : );
     550              : 
     551              : 
     552       246550 : declare_iterator!(
     553       246550 :     COFFStrings,
     554       246550 :     coff::String<'a>,
     555       246550 :     ffi::PE_COFFString,
     556       246550 :     ffi::PE_Binary,
     557       246550 :     ffi::PE_Binary_it_strings_table
     558       246550 : );
     559              : 
     560       305170 : declare_iterator!(
     561       305170 :     Symbols,
     562       305170 :     Symbol<'a>,
     563       305170 :     ffi::PE_Symbol,
     564       305170 :     ffi::PE_Binary,
     565       305170 :     ffi::PE_Binary_it_symbols
     566       305170 : );
     567              : 
     568       771090 : declare_iterator!(
     569       771090 :     Exceptions,
     570       771090 :     RuntimeExceptionFunction<'a>,
     571       771090 :     ffi::PE_ExceptionInfo,
     572       771090 :     ffi::PE_Binary,
     573       771090 :     ffi::PE_Binary_it_exceptions
     574       771090 : );
        

Generated by: LCOV version 2.1-1