LCOV - code coverage report
Current view: top level - src - generic.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 59.0 % 161 95
Test Date: 2025-02-23:00:00:00 Functions: 47.3 % 112 53

            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              :     /// Symbol's name
      15      1596570 :     fn name(&self) -> String {
      16      1596570 :         self.as_generic().name().to_string()
      17      1596570 :     }
      18              :     /// Symbol's value whose interpretation depends on the symbol's kind.
      19              :     /// Usually this is the address of the symbol though.
      20       830540 :     fn value(&self) -> u64 {
      21       830540 :         self.as_generic().value()
      22       830540 :     }
      23              :     /// Size of the symbol (can be 0)
      24       830540 :     fn size(&self) -> u64 {
      25       830540 :         self.as_generic().size()
      26       830540 :     }
      27              : }
      28              : 
      29              : impl std::fmt::Debug for &dyn Symbol {
      30       822770 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
      31       822770 :         f.debug_struct("Symbol")
      32       822770 :             .field("name", &self.name())
      33       822770 :             .field("value", &self.value())
      34       822770 :             .field("size", &self.size())
      35       822770 :             .finish()
      36       822770 :     }
      37              : }
      38              : 
      39              : /// Trait shared by all the sections in executable formats
      40              : pub trait Section {
      41              :     #[doc(hidden)]
      42              :     fn as_generic(&self) -> &ffi::AbstractSection;
      43              : 
      44              :     /// Name of the section
      45       232830 :     fn name(&self) -> String {
      46       232830 :         self.as_generic().name().to_string()
      47       232830 :     }
      48              : 
      49              :     /// Size of the section **in the file**
      50       230910 :     fn size(&self) -> u64 {
      51       230910 :         self.as_generic().size()
      52       230910 :     }
      53              : 
      54              :     /// Offset of the section **in the file**
      55       230840 :     fn offset(&self) -> u64 {
      56       230840 :         self.as_generic().offset()
      57       230840 :     }
      58              : 
      59              :     /// Address of the section **in memory**
      60       230840 :     fn virtual_address(&self) -> u64 {
      61       230840 :         self.as_generic().virtual_address()
      62       230840 :     }
      63              : 
      64              :     /// Content of the section
      65            0 :     fn content(&self) -> &[u8] {
      66            0 :         to_slice!(self.as_generic().content());
      67            0 :     }
      68              : }
      69              : 
      70              : impl std::fmt::Debug for &dyn Section {
      71       228850 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
      72       228850 :         f.debug_struct("Section")
      73       228850 :             .field("name", &self.name())
      74       228850 :             .field("size", &self.size())
      75       228850 :             .field("offset", &self.offset())
      76       228850 :             .field("virtual_address", &self.virtual_address())
      77       228850 :             .finish()
      78       228850 :     }
      79              : }
      80              : 
      81              : pub trait Relocation {
      82              :     #[doc(hidden)]
      83              :     fn as_generic(&self) -> &ffi::AbstractRelocation;
      84              : 
      85              :     /// Address where the relocation should take place
      86      2264100 :     fn address(&self) -> u64 {
      87      2264100 :         self.as_generic().address()
      88      2264100 :     }
      89              : 
      90              :     /// Size of the relocation
      91      2264100 :     fn size(&self) -> u64 {
      92      2264100 :         self.as_generic().size()
      93      2264100 :     }
      94              : }
      95              : 
      96              : impl std::fmt::Debug for &dyn Relocation {
      97      2264100 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
      98      2264100 :         f.debug_struct("Relocation")
      99      2264100 :             .field("address", &self.address())
     100      2264100 :             .field("size", &self.size())
     101      2264100 :             .finish()
     102      2264100 :     }
     103              : }
     104              : 
     105              : pub trait Binary {
     106              :     #[doc(hidden)]
     107              :     fn as_generic(&self) -> &ffi::AbstractBinary;
     108              : 
     109              :     #[doc(hidden)]
     110              :     fn as_pin_mut_generic(&mut self) -> Pin<&mut ffi::AbstractBinary>;
     111              : 
     112              :     /// Binary's entrypoint
     113           35 :     fn entrypoint(&self) -> u64 {
     114           35 :         self.as_generic().entrypoint()
     115           35 :     }
     116              : 
     117              :     /// Default base address where the binary should be mapped
     118            8 :     fn imagebase(&self) -> u64 {
     119            8 :         self.as_generic().imagebase()
     120            8 :     }
     121              : 
     122              :     /// Whether the current binary is **an executable** and **position independent**
     123            8 :     fn is_pie(&self) -> bool {
     124            8 :         self.as_generic().is_pie()
     125            8 :     }
     126              : 
     127              :     /// Whether the binary defines a non-executable stack
     128            8 :     fn has_nx(&self) -> bool {
     129            8 :         self.as_generic().has_nx()
     130            8 :     }
     131              : 
     132              :     /// Original file size of the binary
     133            8 :     fn original_size(&self) -> u64 {
     134            8 :         self.as_generic().original_size()
     135            8 :     }
     136              : 
     137              :     /// Return the debug info if present. It can be either a
     138              :     /// [`crate::pdb::DebugInfo`] or [`crate::dwarf::DebugInfo`].
     139              :     ///
     140              :     /// For ELF and Mach-O binaries, it returns the given DebugInfo object **only**
     141              :     /// if the binary embeds the DWARF debug info in the binary itself.
     142              :     ///
     143              :     /// For PE file, this function tries to find the **external** PDB using
     144              :     /// the [`crate::pe::debug::CodeViewPDB::filename`] output (if present). One can also
     145              :     /// use [`crate::pdb::load`] or [`crate::pdb::DebugInfo::from`] to get PDB debug
     146              :     /// info.
     147              :     ///
     148              :     /// <div class="warning">
     149              :     /// This function requires LIEF's extended version otherwise it always return `None`
     150              :     /// </div>
     151            0 :     fn debug_info(&self) -> Option<crate::DebugInfo> {
     152            0 :         into_optional(self.as_generic().debug_info())
     153            0 :     }
     154              : 
     155              :     /// Disassemble code starting a the given virtual address and with the given
     156              :     /// size.
     157              :     ///
     158              :     /// ```
     159              :     /// let insts = binary.disassemble(0xacde, 100);
     160              :     /// for inst in insts {
     161              :     ///     println!("{}", inst.to_string());
     162              :     /// }
     163              :     /// ```
     164              :     ///
     165              :     /// See also [`crate::assembly::Instruction`] and [`crate::assembly::Instructions`]
     166            0 :     fn disassemble(&self, address: u64, size: u64) -> InstructionsIt {
     167            0 :         InstructionsIt::new(self.as_generic().disassemble(address, size))
     168            0 :     }
     169              : 
     170              :     /// Disassemble code for the given symbol name
     171              :     ///
     172              :     /// ```
     173              :     /// let insts = binary.disassemble_symbol("__libc_start_main");
     174              :     /// for inst in insts {
     175              :     ///     println!("{}", inst.to_string());
     176              :     /// }
     177              :     /// ```
     178              :     ///
     179              :     /// See also [`crate::assembly::Instruction`] and [`crate::assembly::Instructions`]
     180            0 :     fn disassemble_symbol(&self, name: &str) -> InstructionsIt {
     181            0 :         InstructionsIt::new(self.as_generic().disassemble_function(name.to_string()))
     182            0 :     }
     183              : 
     184              :     /// Disassemble code at the given virtual address
     185              :     ///
     186              :     /// ```
     187              :     /// let insts = binary.disassemble_address(0xacde);
     188              :     /// for inst in insts {
     189              :     ///     println!("{}", inst.to_string());
     190              :     /// }
     191              :     /// ```
     192              :     ///
     193              :     /// See also [`crate::assembly::Instruction`] and [`crate::assembly::Instructions`]
     194            0 :     fn disassemble_address(&self, address: u64) -> InstructionsIt {
     195            0 :         InstructionsIt::new(self.as_generic().disassemble_address(address))
     196            0 :     }
     197              : 
     198              :     /// Disassemble code provided by the given slice at the specified `address` parameter.
     199              :     ///
     200              :     /// See also [`crate::assembly::Instruction`] and [`crate::assembly::Instructions`]
     201            0 :     fn disassemble_slice(&self, slice: &[u8], address: u64) -> InstructionsIt {
     202            0 :         unsafe {
     203            0 :             InstructionsIt::new(self.as_generic().disassemble_buffer(
     204            0 :                     slice.as_ptr(), slice.len().try_into().unwrap(),
     205            0 :                     address))
     206            0 :         }
     207            0 :     }
     208              : 
     209              :     /// Assemble **and patch** the provided assembly code at the specified address.
     210              :     ///
     211              :     /// The generated assembly is returned by the function
     212              :     ///
     213              :     /// ```
     214              :     /// let mut bin = get_binary();
     215              :     ///
     216              :     /// let Vec<u8> bytes = bin.assemble(0x12000440, r#"
     217              :     /// xor rax, rbx;
     218              :     /// mov rcx, rax;
     219              :     /// "#);
     220              :     /// ```
     221            0 :     fn assemble(&mut self, address: u64, asm: &str) -> Vec<u8> {
     222            0 :         Vec::from(self.as_pin_mut_generic().assemble(address, asm).as_slice())
     223            0 :     }
     224              : }
     225              : 
     226              : pub trait DebugInfo {
     227              :     #[doc(hidden)]
     228              :     fn as_generic(&self) -> &ffi::AbstracDebugInfo;
     229              : }
     230              : 
     231              : 
     232            0 : bitflags! {
     233            0 :     /// Flags used to characterize the semantics of the function
     234       723950 :     #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
     235            0 :     pub struct FunctionFlags: u32 {
     236            0 :         const NONE = 0x0;
     237            0 :         /// The function acts as constructor.
     238            0 :         ///
     239            0 :         /// Usually this flag is associated with functions
     240            0 :         /// that are located in the `.init_array`, `__mod_init_func` or `.tls` sections
     241            0 :         const CONSTRUCTOR = 0x1;
     242            0 : 
     243            0 :         /// The function acts as a destructor.
     244            0 :         ///
     245            0 :         /// Usually this flag is associated with functions
     246            0 :         /// that are located in the `.fini_array` or `__mod_term_func` sections
     247            0 :         const DESTRUCTOR = 0x2;
     248            0 : 
     249            0 :         /// The function is associated with Debug information
     250            0 :         const DEBUG_INFO = 0x4;
     251            0 : 
     252            0 :         /// The function is exported by the binary and the [`Function::address`]
     253            0 :         /// returns its virtual address in the binary
     254            0 :         const EXPORTED = 0x8;
     255            0 : 
     256            0 :         /// The function is **imported** by the binary and the [`Function::address`]
     257            0 :         /// should return 0
     258            0 :         const IMPORTED = 0x10;
     259            0 :     }
     260            0 : }
     261              : 
     262              : 
     263              : impl From<u32> for FunctionFlags {
     264       723950 :     fn from(value: u32) -> Self {
     265       723950 :         FunctionFlags::from_bits_truncate(value)
     266       723950 :     }
     267              : }
     268              : 
     269              : impl From<FunctionFlags> for u32 {
     270            0 :     fn from(value: FunctionFlags) -> Self {
     271            0 :         value.bits()
     272            0 :     }
     273              : }
     274              : 
     275              : impl std::fmt::Display for FunctionFlags {
     276            0 :     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
     277            0 :         bitflags::parser::to_writer(self, f)
     278            0 :     }
     279              : }
     280              : 
     281              : /// Structure that represents a binary's function
     282              : pub struct Function {
     283              :     ptr: cxx::UniquePtr<ffi::AbstractFunction>,
     284              : }
     285              : 
     286              : impl FromFFI<ffi::AbstractFunction> for Function {
     287       723950 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::AbstractFunction>) -> Self {
     288       723950 :         Self {
     289       723950 :             ptr,
     290       723950 :         }
     291       723950 :     }
     292              : }
     293              : 
     294              : impl Symbol for Function {
     295       723950 :     fn as_generic(&self) -> &lief_ffi::AbstractSymbol {
     296       723950 :         self.ptr.as_ref().unwrap().as_ref()
     297       723950 :     }
     298              : }
     299              : 
     300              : impl Function {
     301              :     /// Flags characterizing the semantics of the function
     302       723950 :     pub fn flags(&self) -> FunctionFlags {
     303       723950 :         FunctionFlags::from(self.ptr.flags())
     304       723950 :     }
     305              : 
     306              :     /// Address of the function (if not imported)
     307       723950 :     pub fn address(&self) -> u64 {
     308       723950 :         self.ptr.address()
     309       723950 :     }
     310              : }
     311              : 
     312              : impl std::fmt::Debug for Function {
     313       723950 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     314       723950 :         f.debug_struct("Function")
     315       723950 :             .field("name", &self.name())
     316       723950 :             .field("address", &self.address())
     317       723950 :             .field("flags", &self.flags())
     318       723950 :             .finish()
     319       723950 :     }
     320              : }
     321              : 
     322       723950 : declare_fwd_iterator!(
     323       723950 :     Functions,
     324       723950 :     Function,
     325       723950 :     ffi::AbstractFunction,
     326       723950 :     ffi::AbstractBinary,
     327       723950 :     ffi::AbstractBinary_it_functions
     328       723950 : );
     329              : 
     330            0 : declare_fwd_iterator!(
     331            0 :     InstructionsIt,
     332            0 :     Instructions,
     333            0 :     ffi::asm_Instruction,
     334            0 :     ffi::AbstractBinary,
     335            0 :     ffi::AbstractBinary_it_instructions
     336            0 : );
        

Generated by: LCOV version 2.1-1