LCOV - code coverage report
Current view: top level - src - generic.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 48.2 % 197 95
Test Date: 2025-08-10:00:00:00 Functions: 38.3 % 154 59

            Line data    Source code
       1              : use lief_ffi as ffi;
       2              : use bitflags::bitflags;
       3              : use crate::{to_slice, declare_fwd_iterator, to_opt_trait};
       4              : use crate::common::{into_optional, FromFFI};
       5              : use crate::assembly::{Instructions, AssemblerConfig};
       6              : 
       7              : use std::pin::Pin;
       8              : 
       9              : /// Trait shared by all the symbols in executable formats
      10              : pub trait Symbol {
      11              :     #[doc(hidden)]
      12              :     fn as_generic(&self) -> &ffi::AbstractSymbol;
      13              : 
      14              :     #[doc(hidden)]
      15              :     fn as_pin_mut_generic(&mut self) -> Pin<&mut ffi::AbstractSymbol>;
      16              : 
      17              :     /// Symbol's name
      18      1949100 :     fn name(&self) -> String {
      19      1949100 :         self.as_generic().name().to_string()
      20      1949100 :     }
      21              :     /// Symbol's value whose interpretation depends on the symbol's kind.
      22              :     /// Usually this is the address of the symbol though.
      23      1018608 :     fn value(&self) -> u64 {
      24      1018608 :         self.as_generic().value()
      25      1018608 :     }
      26              :     /// Size of the symbol (can be 0)
      27      1018608 :     fn size(&self) -> u64 {
      28      1018608 :         self.as_generic().size()
      29      1018608 :     }
      30              : 
      31            0 :     fn set_name(&mut self, name: &str) {
      32            0 :         self.as_pin_mut_generic().set_name(name.to_string());
      33            0 :     }
      34              : 
      35            0 :     fn set_value(&mut self, value: u64) {
      36            0 :         self.as_pin_mut_generic().set_value(value);
      37            0 :     }
      38              : 
      39            0 :     fn set_size(&mut self, size: u64) {
      40            0 :         self.as_pin_mut_generic().set_size(size);
      41            0 :     }
      42              : }
      43              : 
      44              : impl std::fmt::Debug for &dyn Symbol {
      45      1009284 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
      46      1009284 :         f.debug_struct("Symbol")
      47      1009284 :             .field("name", &self.name())
      48      1009284 :             .field("value", &self.value())
      49      1009284 :             .field("size", &self.size())
      50      1009284 :             .finish()
      51      1009284 :     }
      52              : }
      53              : 
      54              : /// Trait shared by all the sections in executable formats
      55              : pub trait Section {
      56              :     #[doc(hidden)]
      57              :     fn as_generic(&self) -> &ffi::AbstractSection;
      58              : 
      59              :     /// Name of the section
      60       304608 :     fn name(&self) -> String {
      61       304608 :         self.as_generic().name().to_string()
      62       304608 :     }
      63              : 
      64              :     /// Size of the section **in the file**
      65       291120 :     fn size(&self) -> u64 {
      66       291120 :         self.as_generic().size()
      67       291120 :     }
      68              : 
      69              :     /// Offset of the section **in the file**
      70       291036 :     fn offset(&self) -> u64 {
      71       291036 :         self.as_generic().offset()
      72       291036 :     }
      73              : 
      74              :     /// Address of the section **in memory**
      75       291036 :     fn virtual_address(&self) -> u64 {
      76       291036 :         self.as_generic().virtual_address()
      77       291036 :     }
      78              : 
      79              :     /// Content of the section
      80            0 :     fn content(&self) -> &[u8] {
      81            0 :         to_slice!(self.as_generic().content());
      82            0 :     }
      83              : }
      84              : 
      85              : impl std::fmt::Debug for &dyn Section {
      86       288648 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
      87       288648 :         f.debug_struct("Section")
      88       288648 :             .field("name", &self.name())
      89       288648 :             .field("size", &self.size())
      90       288648 :             .field("offset", &self.offset())
      91       288648 :             .field("virtual_address", &self.virtual_address())
      92       288648 :             .finish()
      93       288648 :     }
      94              : }
      95              : 
      96              : pub trait Relocation {
      97              :     #[doc(hidden)]
      98              :     fn as_generic(&self) -> &ffi::AbstractRelocation;
      99              : 
     100              :     /// Address where the relocation should take place
     101      2728104 :     fn address(&self) -> u64 {
     102      2728104 :         self.as_generic().address()
     103      2728104 :     }
     104              : 
     105              :     /// Size of the relocation
     106      2728104 :     fn size(&self) -> u64 {
     107      2728104 :         self.as_generic().size()
     108      2728104 :     }
     109              : }
     110              : 
     111              : impl std::fmt::Debug for &dyn Relocation {
     112      2728104 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     113      2728104 :         f.debug_struct("Relocation")
     114      2728104 :             .field("address", &self.address())
     115      2728104 :             .field("size", &self.size())
     116      2728104 :             .finish()
     117      2728104 :     }
     118              : }
     119              : 
     120              : /// Generic interface representing a binary executable.
     121              : ///
     122              : /// This trait provides a unified interface across multiple binary formats
     123              : /// such as ELF, PE, Mach-O, and others. It enables users to access binary
     124              : /// components like headers, sections, symbols, relocations,
     125              : /// and functions in a format-agnostic way.
     126              : pub trait Binary {
     127              :     #[doc(hidden)]
     128              :     fn as_generic(&self) -> &ffi::AbstractBinary;
     129              : 
     130              :     #[doc(hidden)]
     131              :     fn as_pin_mut_generic(&mut self) -> Pin<&mut ffi::AbstractBinary>;
     132              : 
     133              :     /// Binary's entrypoint
     134           51 :     fn entrypoint(&self) -> u64 {
     135           51 :         self.as_generic().entrypoint()
     136           51 :     }
     137              : 
     138              :     /// Default base address where the binary should be mapped
     139            8 :     fn imagebase(&self) -> u64 {
     140            8 :         self.as_generic().imagebase()
     141            8 :     }
     142              : 
     143              :     /// Whether the current binary is **an executable** and **position independent**
     144            8 :     fn is_pie(&self) -> bool {
     145            8 :         self.as_generic().is_pie()
     146            8 :     }
     147              : 
     148              :     /// Whether the binary defines a non-executable stack
     149            8 :     fn has_nx(&self) -> bool {
     150            8 :         self.as_generic().has_nx()
     151            8 :     }
     152              : 
     153              :     /// Original file size of the binary
     154            8 :     fn original_size(&self) -> u64 {
     155            8 :         self.as_generic().original_size()
     156            8 :     }
     157              : 
     158              :     /// Return the debug info if present. It can be either a
     159              :     /// [`crate::pdb::DebugInfo`] or [`crate::dwarf::DebugInfo`].
     160              :     ///
     161              :     /// For ELF and Mach-O binaries, it returns the given DebugInfo object **only**
     162              :     /// if the binary embeds the DWARF debug info in the binary itself.
     163              :     ///
     164              :     /// For PE file, this function tries to find the **external** PDB using
     165              :     /// the [`crate::pe::debug::CodeViewPDB::filename`] output (if present). One can also
     166              :     /// use [`crate::pdb::load`] or [`crate::pdb::DebugInfo::from`] to get PDB debug
     167              :     /// info.
     168              :     ///
     169              :     /// <div class="warning">
     170              :     /// This function requires LIEF's extended version otherwise it always return `None`
     171              :     /// </div>
     172            0 :     fn debug_info(&self) -> Option<crate::DebugInfo> {
     173            0 :         into_optional(self.as_generic().debug_info())
     174            0 :     }
     175              : 
     176              :     /// Disassemble code starting at the given virtual address and with the given
     177              :     /// size.
     178              :     ///
     179              :     /// ```
     180              :     /// let insts = binary.disassemble(0xacde, 100);
     181              :     /// for inst in insts {
     182              :     ///     println!("{}", inst.to_string());
     183              :     /// }
     184              :     /// ```
     185              :     ///
     186              :     /// See also [`crate::assembly::Instruction`] and [`crate::assembly::Instructions`]
     187            0 :     fn disassemble(&self, address: u64, size: u64) -> InstructionsIt {
     188            0 :         InstructionsIt::new(self.as_generic().disassemble(address, size))
     189            0 :     }
     190              : 
     191              :     /// Disassemble code for the given symbol name
     192              :     ///
     193              :     /// ```
     194              :     /// let insts = binary.disassemble_symbol("__libc_start_main");
     195              :     /// for inst in insts {
     196              :     ///     println!("{}", inst.to_string());
     197              :     /// }
     198              :     /// ```
     199              :     ///
     200              :     /// See also [`crate::assembly::Instruction`] and [`crate::assembly::Instructions`]
     201            0 :     fn disassemble_symbol(&self, name: &str) -> InstructionsIt {
     202            0 :         InstructionsIt::new(self.as_generic().disassemble_function(name.to_string()))
     203            0 :     }
     204              : 
     205              :     /// Disassemble code at the given virtual address
     206              :     ///
     207              :     /// ```
     208              :     /// let insts = binary.disassemble_address(0xacde);
     209              :     /// for inst in insts {
     210              :     ///     println!("{}", inst.to_string());
     211              :     /// }
     212              :     /// ```
     213              :     ///
     214              :     /// See also [`crate::assembly::Instruction`] and [`crate::assembly::Instructions`]
     215            0 :     fn disassemble_address(&self, address: u64) -> InstructionsIt {
     216            0 :         InstructionsIt::new(self.as_generic().disassemble_address(address))
     217            0 :     }
     218              : 
     219              :     /// Disassemble code provided by the given slice at the specified `address` parameter.
     220              :     ///
     221              :     /// See also [`crate::assembly::Instruction`] and [`crate::assembly::Instructions`]
     222            0 :     fn disassemble_slice(&self, slice: &[u8], address: u64) -> InstructionsIt {
     223            0 :         unsafe {
     224            0 :             InstructionsIt::new(self.as_generic().disassemble_buffer(
     225            0 :                     slice.as_ptr(), slice.len().try_into().unwrap(),
     226            0 :                     address))
     227            0 :         }
     228            0 :     }
     229              : 
     230              :     /// Assemble **and patch** the provided assembly code at the specified address.
     231              :     ///
     232              :     /// The generated assembly is returned by the function
     233              :     ///
     234              :     /// ```
     235              :     /// let mut bin = get_binary();
     236              :     ///
     237              :     /// let Vec<u8> bytes = bin.assemble(0x12000440, r#"
     238              :     ///     xor rax, rbx;
     239              :     ///     mov rcx, rax;
     240              :     /// "#);
     241              :     /// ```
     242            0 :     fn assemble(&mut self, address: u64, asm: &str) -> Vec<u8> {
     243            0 :         Vec::from(self.as_pin_mut_generic().assemble(address, asm).as_slice())
     244            0 :     }
     245              : 
     246              :     /// Same as [`Binary::assemble`] but this function takes an extra [`AssemblerConfig`] that
     247              :     /// is used to configure the assembly engine: dialect, symbols definitions.
     248            0 :     fn assemble_with_config(&mut self, address: u64, asm: &str, config: &AssemblerConfig) -> Vec<u8> {
     249            0 :         let ffi_config = config.into_ffi();
     250            0 :         Vec::from(self.as_pin_mut_generic().assemble_with_config(address, asm, ffi_config.as_ref()).as_slice())
     251            0 :     }
     252              : 
     253              :     /// Get the default memory page size according to the architecture and the format of the
     254              :     /// current binary
     255            0 :     fn page_size(&self) -> u64 {
     256            0 :         self.as_generic().page_size()
     257            0 :     }
     258              : 
     259              :     /// Load and associate an external debug file (e.g., DWARF or PDB) with this binary.
     260              :     ///
     261              :     /// This method attempts to load the debug information from the file located at the given path,
     262              :     /// and binds it to the current binary instance. If successful, it returns the
     263              :     /// loaded [`crate::DebugInfo`] object.
     264              :     ///
     265              :     /// <div class="warning">
     266              :     /// It is the caller's responsibility to ensure that the debug file is
     267              :     /// compatible with the binary. Incorrect associations may lead to
     268              :     /// inconsistent or invalid results.
     269              :     /// </div>
     270              :     ///
     271              :     /// <div class="note">
     272              :     /// This function does not verify that the debug file matches the binary's unique
     273              :     /// identifier (e.g., build ID, GUID).
     274              :     /// </div>
     275            0 :     fn load_debug_info(&mut self, path: &std::path::Path) -> Option<crate::DebugInfo> {
     276            0 :         into_optional(self.as_pin_mut_generic().load_debug_info(path.to_str().unwrap()))
     277            0 :     }
     278              : }
     279              : 
     280              : /// This class provides a generic interface for accessing debug information
     281              : /// from different formats such as DWARF and PDB.
     282              : ///
     283              : /// Users can use this interface to access high-level debug features like
     284              : /// resolving function addresses.
     285              : ///
     286              : /// See: [`crate::pdb::DebugInfo`], [`crate::dwarf::DebugInfo`]
     287              : pub trait DebugInfo {
     288              :     #[doc(hidden)]
     289              :     fn as_generic(&self) -> &ffi::AbstracDebugInfo;
     290              : 
     291              :     /// Attempt to resolve the address of the function specified by `name`.
     292            0 :     fn find_function_address(&self, name: &str) -> Option<u64> {
     293            0 :         to_opt_trait!(
     294            0 :             &lief_ffi::AbstracDebugInfo::find_function_address,
     295            0 :             self.as_generic(),
     296            0 :             name
     297            0 :         );
     298            0 :     }
     299              : }
     300              : 
     301            0 : bitflags! {
     302            0 :     /// Flags used to characterize the semantics of the function
     303       868788 :     #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
     304            0 :     pub struct FunctionFlags: u32 {
     305            0 :         const NONE = 0x0;
     306            0 :         /// The function acts as constructor.
     307            0 :         ///
     308            0 :         /// Usually this flag is associated with functions
     309            0 :         /// that are located in the `.init_array`, `__mod_init_func` or `.tls` sections
     310            0 :         const CONSTRUCTOR = 0x1;
     311            0 : 
     312            0 :         /// The function acts as a destructor.
     313            0 :         ///
     314            0 :         /// Usually this flag is associated with functions
     315            0 :         /// that are located in the `.fini_array` or `__mod_term_func` sections
     316            0 :         const DESTRUCTOR = 0x2;
     317            0 : 
     318            0 :         /// The function is associated with Debug information
     319            0 :         const DEBUG_INFO = 0x4;
     320            0 : 
     321            0 :         /// The function is exported by the binary and the [`Function::address`]
     322            0 :         /// returns its virtual address in the binary
     323            0 :         const EXPORTED = 0x8;
     324            0 : 
     325            0 :         /// The function is **imported** by the binary and the [`Function::address`]
     326            0 :         /// should return 0
     327            0 :         const IMPORTED = 0x10;
     328            0 :     }
     329            0 : }
     330              : 
     331              : 
     332              : impl From<u32> for FunctionFlags {
     333       868788 :     fn from(value: u32) -> Self {
     334       868788 :         FunctionFlags::from_bits_truncate(value)
     335       868788 :     }
     336              : }
     337              : 
     338              : impl From<FunctionFlags> for u32 {
     339            0 :     fn from(value: FunctionFlags) -> Self {
     340            0 :         value.bits()
     341            0 :     }
     342              : }
     343              : 
     344              : impl std::fmt::Display for FunctionFlags {
     345            0 :     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
     346            0 :         bitflags::parser::to_writer(self, f)
     347            0 :     }
     348              : }
     349              : 
     350              : /// Structure that represents a binary's function
     351              : pub struct Function {
     352              :     ptr: cxx::UniquePtr<ffi::AbstractFunction>,
     353              : }
     354              : 
     355              : impl FromFFI<ffi::AbstractFunction> for Function {
     356       868788 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::AbstractFunction>) -> Self {
     357       868788 :         Self {
     358       868788 :             ptr,
     359       868788 :         }
     360       868788 :     }
     361              : }
     362              : 
     363              : impl Symbol for Function {
     364       868788 :     fn as_generic(&self) -> &lief_ffi::AbstractSymbol {
     365       868788 :         self.ptr.as_ref().unwrap().as_ref()
     366       868788 :     }
     367              : 
     368            0 :     fn as_pin_mut_generic(&mut self) -> Pin<&mut ffi::AbstractSymbol> {
     369            0 :         unsafe {
     370            0 :             Pin::new_unchecked({
     371            0 :                 (self.ptr.as_ref().unwrap().as_ref() as *const ffi::AbstractSymbol
     372            0 :                     as *mut ffi::AbstractSymbol)
     373            0 :                     .as_mut()
     374            0 :                     .unwrap()
     375            0 :             })
     376            0 :         }
     377            0 :     }
     378              : }
     379              : 
     380              : impl Function {
     381              :     /// Flags characterizing the semantics of the function
     382       868788 :     pub fn flags(&self) -> FunctionFlags {
     383       868788 :         FunctionFlags::from(self.ptr.flags())
     384       868788 :     }
     385              : 
     386              :     /// Address of the function (if not imported)
     387       868788 :     pub fn address(&self) -> u64 {
     388       868788 :         self.ptr.address()
     389       868788 :     }
     390              : }
     391              : 
     392              : impl std::fmt::Debug for Function {
     393       868788 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     394       868788 :         f.debug_struct("Function")
     395       868788 :             .field("name", &self.name())
     396       868788 :             .field("address", &self.address())
     397       868788 :             .field("flags", &self.flags())
     398       868788 :             .finish()
     399       868788 :     }
     400              : }
     401              : 
     402       868788 : declare_fwd_iterator!(
     403       868788 :     Functions,
     404       868788 :     Function,
     405       868788 :     ffi::AbstractFunction,
     406       868788 :     ffi::AbstractBinary,
     407       868788 :     ffi::AbstractBinary_it_functions
     408       868788 : );
     409              : 
     410            0 : declare_fwd_iterator!(
     411            0 :     InstructionsIt,
     412            0 :     Instructions,
     413            0 :     ffi::asm_Instruction,
     414            0 :     ffi::AbstractBinary,
     415            0 :     ffi::AbstractBinary_it_instructions
     416            0 : );
        

Generated by: LCOV version 2.1-1