LCOV - code coverage report
Current view: top level - src - generic.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 51.9 % 183 95
Test Date: 2025-06-24:00:00:00 Functions: 40.7 % 145 59

            Line data    Source code
       1              : use lief_ffi as ffi;
       2              : use bitflags::bitflags;
       3              : use crate::{to_slice, declare_fwd_iterator};
       4              : use crate::common::{into_optional, FromFFI};
       5              : use crate::assembly::Instructions;
       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      1948824 :     fn name(&self) -> String {
      19      1948824 :         self.as_generic().name().to_string()
      20      1948824 :     }
      21              :     /// Symbol's value whose interpretation depends on the symbol's kind.
      22              :     /// Usually this is the address of the symbol though.
      23      1018404 :     fn value(&self) -> u64 {
      24      1018404 :         self.as_generic().value()
      25      1018404 :     }
      26              :     /// Size of the symbol (can be 0)
      27      1018404 :     fn size(&self) -> u64 {
      28      1018404 :         self.as_generic().size()
      29      1018404 :     }
      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      1009080 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
      46      1009080 :         f.debug_struct("Symbol")
      47      1009080 :             .field("name", &self.name())
      48      1009080 :             .field("value", &self.value())
      49      1009080 :             .field("size", &self.size())
      50      1009080 :             .finish()
      51      1009080 :     }
      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       303000 :     fn name(&self) -> String {
      61       303000 :         self.as_generic().name().to_string()
      62       303000 :     }
      63              : 
      64              :     /// Size of the section **in the file**
      65       289512 :     fn size(&self) -> u64 {
      66       289512 :         self.as_generic().size()
      67       289512 :     }
      68              : 
      69              :     /// Offset of the section **in the file**
      70       289428 :     fn offset(&self) -> u64 {
      71       289428 :         self.as_generic().offset()
      72       289428 :     }
      73              : 
      74              :     /// Address of the section **in memory**
      75       289428 :     fn virtual_address(&self) -> u64 {
      76       289428 :         self.as_generic().virtual_address()
      77       289428 :     }
      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       287040 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
      87       287040 :         f.debug_struct("Section")
      88       287040 :             .field("name", &self.name())
      89       287040 :             .field("size", &self.size())
      90       287040 :             .field("offset", &self.offset())
      91       287040 :             .field("virtual_address", &self.virtual_address())
      92       287040 :             .finish()
      93       287040 :     }
      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              : pub trait Binary {
     121              :     #[doc(hidden)]
     122              :     fn as_generic(&self) -> &ffi::AbstractBinary;
     123              : 
     124              :     #[doc(hidden)]
     125              :     fn as_pin_mut_generic(&mut self) -> Pin<&mut ffi::AbstractBinary>;
     126              : 
     127              :     /// Binary's entrypoint
     128           35 :     fn entrypoint(&self) -> u64 {
     129           35 :         self.as_generic().entrypoint()
     130           35 :     }
     131              : 
     132              :     /// Default base address where the binary should be mapped
     133            8 :     fn imagebase(&self) -> u64 {
     134            8 :         self.as_generic().imagebase()
     135            8 :     }
     136              : 
     137              :     /// Whether the current binary is **an executable** and **position independent**
     138            8 :     fn is_pie(&self) -> bool {
     139            8 :         self.as_generic().is_pie()
     140            8 :     }
     141              : 
     142              :     /// Whether the binary defines a non-executable stack
     143            8 :     fn has_nx(&self) -> bool {
     144            8 :         self.as_generic().has_nx()
     145            8 :     }
     146              : 
     147              :     /// Original file size of the binary
     148            8 :     fn original_size(&self) -> u64 {
     149            8 :         self.as_generic().original_size()
     150            8 :     }
     151              : 
     152              :     /// Return the debug info if present. It can be either a
     153              :     /// [`crate::pdb::DebugInfo`] or [`crate::dwarf::DebugInfo`].
     154              :     ///
     155              :     /// For ELF and Mach-O binaries, it returns the given DebugInfo object **only**
     156              :     /// if the binary embeds the DWARF debug info in the binary itself.
     157              :     ///
     158              :     /// For PE file, this function tries to find the **external** PDB using
     159              :     /// the [`crate::pe::debug::CodeViewPDB::filename`] output (if present). One can also
     160              :     /// use [`crate::pdb::load`] or [`crate::pdb::DebugInfo::from`] to get PDB debug
     161              :     /// info.
     162              :     ///
     163              :     /// <div class="warning">
     164              :     /// This function requires LIEF's extended version otherwise it always return `None`
     165              :     /// </div>
     166            0 :     fn debug_info(&self) -> Option<crate::DebugInfo> {
     167            0 :         into_optional(self.as_generic().debug_info())
     168            0 :     }
     169              : 
     170              :     /// Disassemble code starting a the given virtual address and with the given
     171              :     /// size.
     172              :     ///
     173              :     /// ```
     174              :     /// let insts = binary.disassemble(0xacde, 100);
     175              :     /// for inst in insts {
     176              :     ///     println!("{}", inst.to_string());
     177              :     /// }
     178              :     /// ```
     179              :     ///
     180              :     /// See also [`crate::assembly::Instruction`] and [`crate::assembly::Instructions`]
     181            0 :     fn disassemble(&self, address: u64, size: u64) -> InstructionsIt {
     182            0 :         InstructionsIt::new(self.as_generic().disassemble(address, size))
     183            0 :     }
     184              : 
     185              :     /// Disassemble code for the given symbol name
     186              :     ///
     187              :     /// ```
     188              :     /// let insts = binary.disassemble_symbol("__libc_start_main");
     189              :     /// for inst in insts {
     190              :     ///     println!("{}", inst.to_string());
     191              :     /// }
     192              :     /// ```
     193              :     ///
     194              :     /// See also [`crate::assembly::Instruction`] and [`crate::assembly::Instructions`]
     195            0 :     fn disassemble_symbol(&self, name: &str) -> InstructionsIt {
     196            0 :         InstructionsIt::new(self.as_generic().disassemble_function(name.to_string()))
     197            0 :     }
     198              : 
     199              :     /// Disassemble code at the given virtual address
     200              :     ///
     201              :     /// ```
     202              :     /// let insts = binary.disassemble_address(0xacde);
     203              :     /// for inst in insts {
     204              :     ///     println!("{}", inst.to_string());
     205              :     /// }
     206              :     /// ```
     207              :     ///
     208              :     /// See also [`crate::assembly::Instruction`] and [`crate::assembly::Instructions`]
     209            0 :     fn disassemble_address(&self, address: u64) -> InstructionsIt {
     210            0 :         InstructionsIt::new(self.as_generic().disassemble_address(address))
     211            0 :     }
     212              : 
     213              :     /// Disassemble code provided by the given slice at the specified `address` parameter.
     214              :     ///
     215              :     /// See also [`crate::assembly::Instruction`] and [`crate::assembly::Instructions`]
     216            0 :     fn disassemble_slice(&self, slice: &[u8], address: u64) -> InstructionsIt {
     217            0 :         unsafe {
     218            0 :             InstructionsIt::new(self.as_generic().disassemble_buffer(
     219            0 :                     slice.as_ptr(), slice.len().try_into().unwrap(),
     220            0 :                     address))
     221            0 :         }
     222            0 :     }
     223              : 
     224              :     /// Assemble **and patch** the provided assembly code at the specified address.
     225              :     ///
     226              :     /// The generated assembly is returned by the function
     227              :     ///
     228              :     /// ```
     229              :     /// let mut bin = get_binary();
     230              :     ///
     231              :     /// let Vec<u8> bytes = bin.assemble(0x12000440, r#"
     232              :     /// xor rax, rbx;
     233              :     /// mov rcx, rax;
     234              :     /// "#);
     235              :     /// ```
     236            0 :     fn assemble(&mut self, address: u64, asm: &str) -> Vec<u8> {
     237            0 :         Vec::from(self.as_pin_mut_generic().assemble(address, asm).as_slice())
     238            0 :     }
     239              : 
     240              :     /// Get the default memory page size according to the architecture and the format of the
     241              :     /// current binary
     242            0 :     fn page_size(&self) -> u64 {
     243            0 :         self.as_generic().page_size()
     244            0 :     }
     245              : }
     246              : 
     247              : pub trait DebugInfo {
     248              :     #[doc(hidden)]
     249              :     fn as_generic(&self) -> &ffi::AbstracDebugInfo;
     250              : }
     251              : 
     252              : 
     253            0 : bitflags! {
     254            0 :     /// Flags used to characterize the semantics of the function
     255       868740 :     #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
     256            0 :     pub struct FunctionFlags: u32 {
     257            0 :         const NONE = 0x0;
     258            0 :         /// The function acts as constructor.
     259            0 :         ///
     260            0 :         /// Usually this flag is associated with functions
     261            0 :         /// that are located in the `.init_array`, `__mod_init_func` or `.tls` sections
     262            0 :         const CONSTRUCTOR = 0x1;
     263            0 : 
     264            0 :         /// The function acts as a destructor.
     265            0 :         ///
     266            0 :         /// Usually this flag is associated with functions
     267            0 :         /// that are located in the `.fini_array` or `__mod_term_func` sections
     268            0 :         const DESTRUCTOR = 0x2;
     269            0 : 
     270            0 :         /// The function is associated with Debug information
     271            0 :         const DEBUG_INFO = 0x4;
     272            0 : 
     273            0 :         /// The function is exported by the binary and the [`Function::address`]
     274            0 :         /// returns its virtual address in the binary
     275            0 :         const EXPORTED = 0x8;
     276            0 : 
     277            0 :         /// The function is **imported** by the binary and the [`Function::address`]
     278            0 :         /// should return 0
     279            0 :         const IMPORTED = 0x10;
     280            0 :     }
     281            0 : }
     282              : 
     283              : 
     284              : impl From<u32> for FunctionFlags {
     285       868740 :     fn from(value: u32) -> Self {
     286       868740 :         FunctionFlags::from_bits_truncate(value)
     287       868740 :     }
     288              : }
     289              : 
     290              : impl From<FunctionFlags> for u32 {
     291            0 :     fn from(value: FunctionFlags) -> Self {
     292            0 :         value.bits()
     293            0 :     }
     294              : }
     295              : 
     296              : impl std::fmt::Display for FunctionFlags {
     297            0 :     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
     298            0 :         bitflags::parser::to_writer(self, f)
     299            0 :     }
     300              : }
     301              : 
     302              : /// Structure that represents a binary's function
     303              : pub struct Function {
     304              :     ptr: cxx::UniquePtr<ffi::AbstractFunction>,
     305              : }
     306              : 
     307              : impl FromFFI<ffi::AbstractFunction> for Function {
     308       868740 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::AbstractFunction>) -> Self {
     309       868740 :         Self {
     310       868740 :             ptr,
     311       868740 :         }
     312       868740 :     }
     313              : }
     314              : 
     315              : impl Symbol for Function {
     316       868740 :     fn as_generic(&self) -> &lief_ffi::AbstractSymbol {
     317       868740 :         self.ptr.as_ref().unwrap().as_ref()
     318       868740 :     }
     319              : 
     320            0 :     fn as_pin_mut_generic(&mut self) -> Pin<&mut ffi::AbstractSymbol> {
     321            0 :         unsafe {
     322            0 :             Pin::new_unchecked({
     323            0 :                 (self.ptr.as_ref().unwrap().as_ref() as *const ffi::AbstractSymbol
     324            0 :                     as *mut ffi::AbstractSymbol)
     325            0 :                     .as_mut()
     326            0 :                     .unwrap()
     327            0 :             })
     328            0 :         }
     329            0 :     }
     330              : }
     331              : 
     332              : impl Function {
     333              :     /// Flags characterizing the semantics of the function
     334       868740 :     pub fn flags(&self) -> FunctionFlags {
     335       868740 :         FunctionFlags::from(self.ptr.flags())
     336       868740 :     }
     337              : 
     338              :     /// Address of the function (if not imported)
     339       868740 :     pub fn address(&self) -> u64 {
     340       868740 :         self.ptr.address()
     341       868740 :     }
     342              : }
     343              : 
     344              : impl std::fmt::Debug for Function {
     345       868740 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     346       868740 :         f.debug_struct("Function")
     347       868740 :             .field("name", &self.name())
     348       868740 :             .field("address", &self.address())
     349       868740 :             .field("flags", &self.flags())
     350       868740 :             .finish()
     351       868740 :     }
     352              : }
     353              : 
     354       868740 : declare_fwd_iterator!(
     355       868740 :     Functions,
     356       868740 :     Function,
     357       868740 :     ffi::AbstractFunction,
     358       868740 :     ffi::AbstractBinary,
     359       868740 :     ffi::AbstractBinary_it_functions
     360       868740 : );
     361              : 
     362            0 : declare_fwd_iterator!(
     363            0 :     InstructionsIt,
     364            0 :     Instructions,
     365            0 :     ffi::asm_Instruction,
     366            0 :     ffi::AbstractBinary,
     367            0 :     ffi::AbstractBinary_it_instructions
     368            0 : );
        

Generated by: LCOV version 2.1-1