LCOV - code coverage report
Current view: top level - src/elf - binary.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 39.0 % 538 210
Test Date: 2026-04-12:00:00:00 Functions: 30.5 % 174 53

            Line data    Source code
       1              : use std::mem::size_of;
       2              : use std::path::Path;
       3              : use std::pin::Pin;
       4              : 
       5              : use num_traits::{cast, Num};
       6              : 
       7              : use lief_ffi as ffi;
       8              : 
       9              : use super::builder::Config;
      10              : use super::dynamic::{self, DynamicEntries, Library};
      11              : use super::hash::{Gnu, Sysv};
      12              : use super::header::Header;
      13              : use super::note::ItNotes;
      14              : use super::parser_config::Config as ParserConfig;
      15              : use super::relocation::{
      16              :     DynamicRelocations, ObjectRelocations, PltGotRelocations, Relocation, Relocations,
      17              : };
      18              : use super::section::{Section, Sections};
      19              : use super::segment::{self, Segments};
      20              : use super::symbol::{DynamicSymbols, ExportedSymbols, ImportedSymbols, SymtabSymbols};
      21              : use super::symbol_versioning::{SymbolVersion, SymbolVersionDefinition, SymbolVersionRequirement};
      22              : use super::{Segment, Symbol};
      23              : use crate::elf::dynamic::DynamicEntry;
      24              : use crate::Error;
      25              : 
      26              : use crate::common::{into_optional, AsFFI, FromFFI};
      27              : use crate::generic;
      28              : use crate::{declare_iterator, to_conv_result, to_result, to_slice};
      29              : 
      30            0 : #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
      31              : pub enum ElfClass {
      32              :     Elf32,
      33              :     Elf64,
      34              :     Unknown,
      35              : }
      36              : 
      37              : impl ElfClass {
      38              :     const ELF_CLASS32: u32 = 1;
      39              :     const ELF_CLASS64: u32 = 2;
      40              : 
      41            0 :     pub fn from_value(value: u32) -> Self {
      42            0 :         match value {
      43            0 :             Self::ELF_CLASS32 => ElfClass::Elf32,
      44            0 :             Self::ELF_CLASS64 => ElfClass::Elf64,
      45            0 :             _ => ElfClass::Unknown,
      46              :         }
      47            0 :     }
      48              : }
      49              : 
      50              : /// Strategy used for relocating the PHDR table
      51              : #[allow(non_camel_case_types)]
      52            0 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
      53              : pub enum PhdrReloc {
      54              :     /// Let LIEF choose the best strategy
      55              :     AUTO,
      56              :     /// Shift content after the PHDR table (PIE binaries only)
      57              :     PIE_SHIFT,
      58              :     /// Relocate the PHDR after the first BSS-like segment
      59              :     BSS_END,
      60              :     /// Relocate at the end of the binary
      61              :     BINARY_END,
      62              :     /// Relocate between two LOAD segments
      63              :     SEGMENT_GAP,
      64              :     UNKNOWN(u32),
      65              : }
      66              : 
      67              : impl From<u32> for PhdrReloc {
      68            0 :     fn from(value: u32) -> Self {
      69            0 :         match value {
      70            0 :             0 => PhdrReloc::AUTO,
      71            0 :             1 => PhdrReloc::PIE_SHIFT,
      72            0 :             2 => PhdrReloc::BSS_END,
      73            0 :             3 => PhdrReloc::BINARY_END,
      74            0 :             4 => PhdrReloc::SEGMENT_GAP,
      75            0 :             _ => PhdrReloc::UNKNOWN(value),
      76              :         }
      77            0 :     }
      78              : }
      79              : 
      80              : impl From<PhdrReloc> for u32 {
      81            0 :     fn from(value: PhdrReloc) -> u32 {
      82            0 :         match value {
      83            0 :             PhdrReloc::AUTO => 0,
      84            0 :             PhdrReloc::PIE_SHIFT => 1,
      85            0 :             PhdrReloc::BSS_END => 2,
      86            0 :             PhdrReloc::BINARY_END => 3,
      87            0 :             PhdrReloc::SEGMENT_GAP => 4,
      88            0 :             PhdrReloc::UNKNOWN(v) => v,
      89              :         }
      90            0 :     }
      91              : }
      92              : 
      93              : /// Strategy for inserting a new section
      94              : #[allow(non_camel_case_types)]
      95            0 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
      96              : pub enum SecInsertPos {
      97              :     /// Let LIEF choose the best strategy
      98              :     AUTO,
      99              :     /// Insert after the last segment offset, before debug info
     100              :     POST_SEGMENT,
     101              :     /// Insert after the last section offset, at binary end
     102              :     POST_SECTION,
     103              :     UNKNOWN(u32),
     104              : }
     105              : 
     106              : impl From<u32> for SecInsertPos {
     107            0 :     fn from(value: u32) -> Self {
     108            0 :         match value {
     109            0 :             0 => SecInsertPos::AUTO,
     110            0 :             1 => SecInsertPos::POST_SEGMENT,
     111            0 :             2 => SecInsertPos::POST_SECTION,
     112            0 :             _ => SecInsertPos::UNKNOWN(value),
     113              :         }
     114            0 :     }
     115              : }
     116              : 
     117              : impl From<SecInsertPos> for u32 {
     118            0 :     fn from(value: SecInsertPos) -> u32 {
     119            0 :         match value {
     120            0 :             SecInsertPos::AUTO => 0,
     121            0 :             SecInsertPos::POST_SEGMENT => 1,
     122            0 :             SecInsertPos::POST_SECTION => 2,
     123            0 :             SecInsertPos::UNKNOWN(v) => v,
     124              :         }
     125            0 :     }
     126              : }
     127              : 
     128              : /// This is the main interface to read and write ELF binary attributes.
     129              : ///
     130              : /// Note that this structure implements the [`generic::Binary`] trait from which other generic
     131              : /// functions are exposed
     132              : pub struct Binary {
     133              :     ptr: cxx::UniquePtr<ffi::ELF_Binary>,
     134              : }
     135              : 
     136              : impl std::fmt::Debug for Binary {
     137          130 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     138          130 :         f.debug_struct("Binary")
     139          130 :             .field("header", &self.header())
     140          130 :             .finish()
     141          130 :     }
     142              : }
     143              : 
     144              : impl FromFFI<ffi::ELF_Binary> for Binary {
     145          546 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_Binary>) -> Self {
     146          546 :         Self { ptr }
     147          546 :     }
     148              : }
     149              : 
     150              : impl Binary {
     151              :     /// Create a [`Binary`] from the given file path
     152           32 :     pub fn parse<P: AsRef<Path>>(path: P) -> Option<Self> {
     153           32 :         let bin = ffi::ELF_Binary::parse(path.as_ref().to_str().unwrap());
     154           32 :         if bin.is_null() {
     155            0 :             return None;
     156           32 :         }
     157           32 :         Some(Binary::from_ffi(bin))
     158           32 :     }
     159              : 
     160              :     /// Parse from a string file path and with a provided configuration
     161            0 :     pub fn parse_with_config<P: AsRef<Path>>(path: P, config: &ParserConfig) -> Option<Self> {
     162            0 :         let ffi_config = config.to_ffi();
     163            0 :         let ffi = ffi::ELF_Binary::parse_with_config(path.as_ref().to_str().unwrap(), &ffi_config);
     164            0 :         if ffi.is_null() {
     165            0 :             return None;
     166            0 :         }
     167            0 :         Some(Binary::from_ffi(ffi))
     168            0 :     }
     169              : 
     170              :     /// Return the main ELF header
     171          130 :     pub fn header(&self) -> Header<'_> {
     172          130 :         Header::from_ffi(self.ptr.header())
     173          130 :     }
     174              : 
     175              :     /// Return the size taken by the binary when loaded (virtual size)
     176          130 :     pub fn virtual_size(&self) -> u64 {
     177          130 :         self.ptr.virtual_size()
     178          130 :     }
     179              : 
     180              :     /// Return the path to the ELF interpreter that is used to process the ELF information
     181              :     /// once loaded by the kernel
     182          130 :     pub fn interpreter(&self) -> String {
     183          130 :         self.ptr.interpreter().to_string()
     184          130 :     }
     185              : 
     186              :     /// Return sysv-hash information (if present)
     187          130 :     pub fn sysv_hash(&self) -> Option<Sysv<'_>> {
     188          130 :         into_optional(self.ptr.sysv_hash())
     189          130 :     }
     190              : 
     191              :     /// Return GNU Hash info (if present)
     192          130 :     pub fn gnu_hash(&self) -> Option<Gnu<'_>> {
     193          130 :         into_optional(self.ptr.gnu_hash())
     194          130 :     }
     195              : 
     196              :     /// Return an iterator over the [`crate::elf::Section`] of the binary
     197          130 :     pub fn sections(&self) -> Sections<'_> {
     198          130 :         Sections::new(self.ptr.sections())
     199          130 :     }
     200              : 
     201              :     /// Return an iterator over the [`crate::elf::Segment`] of the binary
     202          130 :     pub fn segments(&self) -> Segments<'_> {
     203          130 :         Segments::new(self.ptr.segments())
     204          130 :     }
     205              : 
     206              :     /// Return an iterator over the [`crate::elf::DynamicEntries`] of the binary
     207          130 :     pub fn dynamic_entries(&self) -> DynamicEntries<'_> {
     208          130 :         DynamicEntries::new(self.ptr.dynamic_entries())
     209          130 :     }
     210              : 
     211              :     /// Remove **all** dynamic entries with the given tag
     212            0 :     pub fn remove_dynamic_entries_by_tag(&mut self, tag: dynamic::Tag) {
     213            0 :         self.ptr
     214            0 :             .as_mut()
     215            0 :             .unwrap()
     216            0 :             .remove_dynamic_entries_by_tag(tag.into())
     217            0 :     }
     218              : 
     219              :     /// Add the given dynamic entry and return the new entry
     220            0 :     pub fn add_dynamic_entry(&mut self, entry: &dyn dynamic::DynamicEntry) -> dynamic::Entries<'_> {
     221            0 :         dynamic::Entries::from_ffi(
     222            0 :             self.ptr
     223            0 :                 .as_mut()
     224            0 :                 .unwrap()
     225            0 :                 .add_dynamic_entry(entry.as_base()),
     226            0 :         )
     227            0 :     }
     228              : 
     229              :     /// Return an iterator over the dynamic [`crate::elf::Symbol`] of the binary
     230          130 :     pub fn dynamic_symbols(&self) -> DynamicSymbols<'_> {
     231          130 :         DynamicSymbols::new(self.ptr.dynamic_symbols())
     232          130 :     }
     233              : 
     234              :     /// Return an iterator over the **exported** [`crate::elf::Symbol`] of the binary
     235          130 :     pub fn exported_symbols(&self) -> ExportedSymbols<'_> {
     236          130 :         ExportedSymbols::new(self.ptr.exported_symbols())
     237          130 :     }
     238              : 
     239              :     /// Return an iterator over the **imported** [`crate::elf::Symbol`] of the binary
     240          130 :     pub fn imported_symbols(&self) -> ImportedSymbols<'_> {
     241          130 :         ImportedSymbols::new(self.ptr.imported_symbols())
     242          130 :     }
     243              : 
     244              :     /// Return an iterator over the symtab-debug [`crate::elf::Symbol`] of the binary
     245          130 :     pub fn symtab_symbols(&self) -> SymtabSymbols<'_> {
     246          130 :         SymtabSymbols::new(self.ptr.symtab_symbols())
     247          130 :     }
     248              : 
     249              :     /// Return an iterator over the  [`crate::elf::SymbolVersion`] of the binary
     250          260 :     pub fn symbols_version(&self) -> SymbolsVersion<'_> {
     251          260 :         SymbolsVersion::new(self.ptr.symbols_version())
     252          260 :     }
     253              : 
     254              :     /// Return an iterator over the  [`crate::elf::SymbolVersionRequirement`] of the binary
     255          130 :     pub fn symbols_version_requirement(&self) -> SymbolsVersionRequirement<'_> {
     256          130 :         SymbolsVersionRequirement::new(self.ptr.symbols_version_requirement())
     257          130 :     }
     258              : 
     259              :     /// Return an iterator over the  [`crate::elf::SymbolVersionDefinition`] of the binary
     260          130 :     pub fn symbols_version_definition(&self) -> SymbolsVersionDefinition<'_> {
     261          130 :         SymbolsVersionDefinition::new(self.ptr.symbols_version_definition())
     262          130 :     }
     263              : 
     264              :     /// Return an iterator over the  [`crate::elf::Notes`] of the binary
     265          390 :     pub fn notes(&self) -> ItNotes<'_> {
     266          390 :         ItNotes::new(self.ptr.notes())
     267          390 :     }
     268              : 
     269              :     /// Return an iterator over the `.plt.got` [`crate::elf::Relocation`] of the binary
     270          130 :     pub fn pltgot_relocations(&self) -> PltGotRelocations<'_> {
     271          130 :         PltGotRelocations::new(self.ptr.pltgot_relocations())
     272          130 :     }
     273              : 
     274              :     /// Return an iterator over the regular [`crate::elf::Relocation`] of the binary
     275          130 :     pub fn dynamic_relocations(&self) -> DynamicRelocations<'_> {
     276          130 :         DynamicRelocations::new(self.ptr.dynamic_relocations())
     277          130 :     }
     278              : 
     279              :     /// Return an iterator over the object-file (`.o`) [`crate::elf::Relocation`]
     280          130 :     pub fn object_relocations(&self) -> ObjectRelocations<'_> {
     281          130 :         ObjectRelocations::new(self.ptr.object_relocations())
     282          130 :     }
     283              : 
     284              :     /// Return an iterator over **all** [`crate::elf::Relocation`] of the binary
     285          130 :     pub fn relocations(&self) -> Relocations<'_> {
     286          130 :         Relocations::new(self.ptr.relocations())
     287          130 :     }
     288              : 
     289              :     /// Try to find the ELF section with the given name
     290          130 :     pub fn section_by_name(&self, name: &str) -> Option<Section<'_>> {
     291          130 :         into_optional(self.ptr.section_by_name(name))
     292          130 :     }
     293              : 
     294              :     /// Try to find the ELF relocation that takes place at the given address
     295           26 :     pub fn relocation_by_addr(&self, address: u64) -> Option<Relocation<'_>> {
     296           26 :         into_optional(self.ptr.relocation_by_addr(address))
     297           26 :     }
     298              : 
     299              :     /// Try to find the `.plt.got` relocation for the given symbol name
     300           26 :     pub fn relocation_for_symbol(&self, sym_name: &str) -> Option<Relocation<'_>> {
     301           26 :         into_optional(self.ptr.relocation_for_symbol(sym_name))
     302           26 :     }
     303              : 
     304              :     /// Try to find the symbol with the given name in the dynamic `.dynsym` table
     305           13 :     pub fn dynamic_symbol_by_name(&self, sym_name: &str) -> Option<Symbol<'_>> {
     306           13 :         into_optional(self.ptr.get_dynamic_symbol(sym_name))
     307           13 :     }
     308              : 
     309              :     /// Try to find the symbol with the given name in the debug `.symtab` table
     310           13 :     pub fn symtab_symbol_by_name(&self, sym_name: &str) -> Option<Symbol<'_>> {
     311           13 :         into_optional(self.ptr.get_symtab_symbol(sym_name))
     312           13 :     }
     313              : 
     314              :     /// Try to find the library (`DT_NEEDED`) with the given name
     315           26 :     pub fn get_library(&self, name: &str) -> Option<dynamic::Library<'_>> {
     316           26 :         into_optional(self.ptr.get_library(name))
     317           26 :     }
     318              : 
     319              :     /// Try to find the section that encompasses the given offset. `skip_nobits` can be used
     320              :     /// to include (or not) the `SHT_NOTBIT` sections
     321           26 :     pub fn section_from_offset(&self, offset: u64, skip_nobits: bool) -> Option<Section<'_>> {
     322           26 :         into_optional(self.ptr.section_from_offset(offset, skip_nobits))
     323           26 :     }
     324              : 
     325              :     /// Try to find the section that encompasses the given virtual address. `skip_nobits` can be used
     326              :     /// to include (or not) the `SHT_NOTBIT` sections
     327           26 :     pub fn section_from_virtual_address(
     328           26 :         &self,
     329           26 :         address: u64,
     330           26 :         skip_nobits: bool,
     331           26 :     ) -> Option<Section<'_>> {
     332           26 :         into_optional(self.ptr.section_from_virtual_address(address, skip_nobits))
     333           26 :     }
     334              : 
     335              :     /// Try to find the segment that encompasses the given virtual address
     336           26 :     pub fn segment_from_virtual_address(&self, address: u64) -> Option<Segment<'_>> {
     337           26 :         into_optional(self.ptr.segment_from_virtual_address(address))
     338           26 :     }
     339              : 
     340              :     /// Try to find the segment that encompasses the given offset
     341           26 :     pub fn segment_from_offset(&self, offset: u64) -> Option<Segment<'_>> {
     342           26 :         into_optional(self.ptr.segment_from_offset(offset))
     343           26 :     }
     344              : 
     345              :     /// Get a slice of the content at the given address.
     346           13 :     pub fn content_from_virtual_address(&self, address: u64, size: u64) -> &[u8] {
     347           13 :         to_slice!(self.ptr.get_content_from_virtual_address(address, size));
     348           13 :     }
     349              : 
     350              :     /// Convert the given virtual address into an offset
     351           26 :     pub fn virtual_address_to_offset(&self, address: u64) -> Result<u64, Error> {
     352           26 :         to_result!(ffi::ELF_Binary::virtual_address_to_offset, &self, address);
     353           26 :     }
     354              : 
     355              :     /// Return the array defined by the given tag (e.g.
     356              :     /// [`dynamic::Tag::INIT_ARRAY`]) with relocations applied (if any)
     357          390 :     pub fn get_relocated_dynamic_array(&self, tag: dynamic::Tag) -> Vec<u64> {
     358          390 :         Vec::from(
     359          390 :             self.ptr
     360          390 :                 .get_relocated_dynamic_array(u64::from(tag))
     361          390 :                 .as_slice(),
     362          390 :         )
     363          390 :     }
     364              : 
     365              :     /// True if the current binary is targeting Android
     366            0 :     pub fn is_targeting_android(&self) -> bool {
     367            0 :         self.ptr.is_targeting_android()
     368            0 :     }
     369              : 
     370              :     /// Get the integer value at the given virtual address
     371            4 :     pub fn get_int_from_virtual_address<T>(&self, addr: u64) -> Result<T, Error>
     372            4 :     where
     373            4 :         T: Num + cast::FromPrimitive + cast::ToPrimitive,
     374            4 :     {
     375            4 :         // Can't be in the generic trait because of:
     376            4 :         //   > for a trait to be "object safe" it needs to allow building a vtable to allow the call
     377            4 :         //   > to be resolvable dynamically; for more information visit
     378            4 :         //   > https://doc.rust-lang.org/reference/items/traits.html#object-safety
     379            4 :         if size_of::<T>() == size_of::<u8>() {
     380            1 :             to_conv_result!(
     381            1 :                 ffi::AbstractBinary::get_u8,
     382            1 :                 self.ptr.as_ref().unwrap().as_ref(),
     383            1 :                 |value| {
     384            1 :                     T::from_u8(value).unwrap_or_else(|| panic!("Can't cast value: {value}"))
     385            1 :                 },
     386            1 :                 addr
     387              :             );
     388            3 :         }
     389            3 : 
     390            3 :         if size_of::<T>() == size_of::<u16>() {
     391            1 :             to_conv_result!(
     392            1 :                 ffi::AbstractBinary::get_u16,
     393            1 :                 self.ptr.as_ref().unwrap().as_ref(),
     394            1 :                 |value| {
     395            1 :                     T::from_u16(value).unwrap_or_else(|| panic!("Can't cast value: {value}"))
     396            1 :                 },
     397            1 :                 addr
     398              :             );
     399            2 :         }
     400            2 : 
     401            2 :         if size_of::<T>() == size_of::<u32>() {
     402            1 :             to_conv_result!(
     403            1 :                 ffi::AbstractBinary::get_u32,
     404            1 :                 self.ptr.as_ref().unwrap().as_ref(),
     405            1 :                 |value| {
     406            1 :                     T::from_u32(value).unwrap_or_else(|| panic!("Can't cast value: {value}"))
     407            1 :                 },
     408            1 :                 addr
     409              :             );
     410            1 :         }
     411            1 : 
     412            1 :         if size_of::<T>() == size_of::<u64>() {
     413            1 :             to_conv_result!(
     414            1 :                 ffi::AbstractBinary::get_u64,
     415            1 :                 self.ptr.as_ref().unwrap().as_ref(),
     416            1 :                 |value| {
     417            1 :                     T::from_u64(value).unwrap_or_else(|| panic!("Can't cast value: {value}"))
     418            1 :                 },
     419            1 :                 addr
     420              :             );
     421            0 :         }
     422            0 : 
     423            0 :         Err(Error::NotSupported)
     424            4 :     }
     425              : 
     426              :     /// Write back the current ELF binary into the file specified in parameter
     427            1 :     pub fn write<P: AsRef<Path>>(&mut self, output: P) {
     428            1 :         self.ptr
     429            1 :             .as_mut()
     430            1 :             .unwrap()
     431            1 :             .write(output.as_ref().to_str().unwrap());
     432            1 :     }
     433              : 
     434              :     /// Write back the current ELF binary into the file specified in parameter with the
     435              :     /// configuration provided in the second parameter.
     436            1 :     pub fn write_with_config<P: AsRef<Path>>(&mut self, output: P, config: Config) {
     437            1 :         self.ptr
     438            1 :             .as_mut()
     439            1 :             .unwrap()
     440            1 :             .write_with_config(output.as_ref().to_str().unwrap(), config.to_ffi());
     441            1 :     }
     442              : 
     443              :     /// Add a library as dependency
     444           13 :     pub fn add_library<'a>(&'a mut self, library: &str) -> Library<'a> {
     445           13 :         Library::from_ffi(self.ptr.as_mut().unwrap().add_library(library))
     446           13 :     }
     447              : 
     448              :     /// Iterator over the functions found in this binary
     449          130 :     pub fn functions(&self) -> generic::Functions<'_> {
     450          130 :         generic::Functions::new(self.ptr.functions())
     451          130 :     }
     452              : 
     453              :     /// Try to find the dynamic entry associated with the given tag
     454            0 :     pub fn dynamic_entry_by_tag(&self, tag: dynamic::Tag) -> Option<dynamic::Entries<'_>> {
     455            0 :         into_optional(self.ptr.dynamic_entry_by_tag(tag.into()))
     456            0 :     }
     457              : 
     458              :     /// Look for the segment with the given type. If there are multiple segment
     459              :     /// with the same type, it returns the first one.
     460            0 :     pub fn segment_by_type(&self, seg_type: segment::Type) -> Option<Segment<'_>> {
     461            0 :         into_optional(self.ptr.segment_by_type(seg_type.into()))
     462            0 :     }
     463              : 
     464              :     /// Remove the given dynamic entry
     465            0 :     pub fn remove_dynamic_entry(&mut self, entry: impl dynamic::DynamicEntry) {
     466            0 :         self.ptr.pin_mut().remove_dynamic_entry(entry.as_base());
     467            0 :     }
     468              : 
     469              :     /// Remove the dynamic entries matching the given predicate.
     470              :     ///
     471              :     /// The function returns the number of entries that have been deleted.
     472            0 :     pub fn remove_dynamic_entry_if<P>(&mut self, predicate: P) -> usize
     473            0 :     where
     474            0 :         P: Fn(&dynamic::Entries) -> bool,
     475            0 :     {
     476            0 :         let entries = self
     477            0 :             .dynamic_entries()
     478            0 :             .filter(predicate)
     479            0 :             .map(|e| e.as_base().raw_ptr())
     480            0 :             .collect::<Vec<_>>();
     481            0 : 
     482            0 :         let cnt = entries.len();
     483              : 
     484            0 :         for ffi_entry in entries {
     485            0 :             unsafe {
     486            0 :                 self.ptr.pin_mut().remove_dynamic_entry_from_ptr(ffi_entry);
     487            0 :             }
     488              :         }
     489            0 :         cnt
     490            0 :     }
     491              : 
     492              :     /// Remove the `DT_NEEDED` dependency with the given name
     493            0 :     pub fn remove_library(&mut self, name: &str) {
     494            0 :         self.ptr.pin_mut().remove_library(name.to_string());
     495            0 :     }
     496              : 
     497              :     /// Add the provided segment to the binary. This function returns the
     498              :     /// newly added segment which could define additional attributes like the virtual address.
     499            0 :     pub fn add_segment(&mut self, segment: &Segment) -> Option<Segment<'_>> {
     500            0 :         into_optional(
     501            0 :             self.ptr
     502            0 :                 .pin_mut()
     503            0 :                 .add_segment(segment.ptr.as_ref().unwrap()),
     504            0 :         )
     505            0 :     }
     506              : 
     507              :     /// Change the path to the interpreter
     508            0 :     pub fn set_interpreter<P: AsRef<Path>>(&mut self, interpreter: P) {
     509            0 :         self.ptr
     510            0 :             .pin_mut()
     511            0 :             .set_interpreter(interpreter.as_ref().to_str().unwrap());
     512            0 :     }
     513              : 
     514              :     /// Try to find the SymbolVersionRequirement associated with the given library
     515              :     /// name (e.g. `libc.so.6`)
     516            0 :     pub fn find_version_requirement(&self, libname: &str) -> Option<SymbolVersionRequirement<'_>> {
     517            0 :         into_optional(self.ptr.find_version_requirement(libname.to_string()))
     518            0 :     }
     519              : 
     520              :     /// Deletes all required symbol versions linked to the specified library name.
     521              :     /// The function returns true if the operation succeed, false otherwise.
     522              :     ///
     523              :     /// <div class='warning'>
     524              :     /// To maintain consistency, this function also removes versions
     525              :     /// associated with dynamic symbols that are linked to the specified
     526              :     /// library name.
     527              :     /// </div>
     528            0 :     pub fn remove_version_requirement(&mut self, libname: &str) -> bool {
     529            0 :         self.ptr
     530            0 :             .pin_mut()
     531            0 :             .remove_version_requirement(libname.to_string())
     532            0 :     }
     533              : 
     534              :     /// Remove the given segment. If `clear` is set, the original content of the
     535              :     /// segment will be filled with zeros before removal.
     536            0 :     pub fn remove_segment(&mut self, segment: Segment, clear: bool) {
     537            0 :         self.ptr
     538            0 :             .pin_mut()
     539            0 :             .remove_segment(segment.ptr.as_ref().unwrap(), clear)
     540            0 :     }
     541              : 
     542              :     /// Remove all segments associated with the given type.
     543              :     ///
     544              :     /// If `clear` is set, the original content of the segments will be filled
     545              :     /// with zeros before removal.
     546            0 :     pub fn remove_segments_by_type(&mut self, ty: segment::Type, clear: bool) {
     547            0 :         self.ptr.pin_mut().remove_segments_by_type(ty.into(), clear)
     548            0 :     }
     549              : 
     550              :     /// Return an iterator over all symbols (combined dynamic + symtab)
     551            0 :     pub fn symbols(&self) -> AllSymbols<'_> {
     552            0 :         AllSymbols::new(self.ptr.symbols())
     553            0 :     }
     554              : 
     555              :     /// Return all printable strings from the binary with a minimum length
     556            0 :     pub fn strings(&self, min_size: u64) -> Vec<String> {
     557            0 :         self.ptr
     558            0 :             .strings(min_size)
     559            0 :             .iter()
     560            0 :             .map(|s| s.to_string())
     561            0 :             .collect()
     562            0 :     }
     563              : 
     564              :     /// Return the last offset used in binary according to sections table
     565            0 :     pub fn last_offset_section(&self) -> u64 {
     566            0 :         self.ptr.last_offset_section()
     567            0 :     }
     568              : 
     569              :     /// Return the last offset used in binary according to segments table
     570            0 :     pub fn last_offset_segment(&self) -> u64 {
     571            0 :         self.ptr.last_offset_segment()
     572            0 :     }
     573              : 
     574              :     /// Return the next virtual address available
     575            0 :     pub fn next_virtual_address(&self) -> u64 {
     576            0 :         self.ptr.next_virtual_address()
     577            0 :     }
     578              : 
     579              :     /// Return the offset of the end of the binary on disk
     580            0 :     pub fn eof_offset(&self) -> u64 {
     581            0 :         self.ptr.eof_offset()
     582            0 :     }
     583              : 
     584              :     /// Return the destructor functions (from `.fini_array`, `.dtors`, etc.)
     585            0 :     pub fn dtor_functions(&self) -> generic::Functions<'_> {
     586            0 :         generic::Functions::new(self.ptr.dtor_functions())
     587            0 :     }
     588              : 
     589              :     /// Return the overlay data
     590            0 :     pub fn overlay(&self) -> &[u8] {
     591            0 :         to_slice!(self.ptr.get_overlay());
     592            0 :     }
     593              : 
     594              :     /// Set the overlay data
     595            0 :     pub fn set_overlay(&mut self, data: &[u8]) {
     596            0 :         unsafe {
     597            0 :             self.ptr
     598            0 :                 .pin_mut()
     599            0 :                 .set_overlay(data.as_ptr(), data.len() as u64);
     600            0 :         }
     601            0 :     }
     602              : 
     603              :     /// Check if the binary has a dynamic entry with the given tag
     604            0 :     pub fn has_dynamic_entry_tag(&self, tag: dynamic::Tag) -> bool {
     605            0 :         self.ptr.has_dynamic_entry_tag(tag.into())
     606            0 :     }
     607              : 
     608              :     /// Check if the binary has a segment with the given type
     609            0 :     pub fn has_segment_type(&self, ty: segment::Type) -> bool {
     610            0 :         self.ptr.has_segment_type(ty.into())
     611            0 :     }
     612              : 
     613              :     /// Check if the binary has a note with the given type
     614            0 :     pub fn has_note_type(&self, ty: super::note::Type) -> bool {
     615            0 :         self.ptr.has_note_type(ty.into())
     616            0 :     }
     617              : 
     618              :     /// Check if the binary has a section with the given type
     619            0 :     pub fn has_section_type(&self, ty: super::section::Type) -> bool {
     620            0 :         self.ptr.has_section_type(ty.into())
     621            0 :     }
     622              : 
     623              :     /// Try to find a note by its type
     624            0 :     pub fn note_by_type(&self, ty: super::note::Type) -> Option<super::note::Notes<'_>> {
     625            0 :         into_optional(self.ptr.get_note_by_type(ty.into()))
     626            0 :     }
     627              : 
     628              :     /// Try to find a section by its type
     629            0 :     pub fn section_by_type(&self, ty: super::section::Type) -> Option<Section<'_>> {
     630            0 :         into_optional(self.ptr.get_section_by_type(ty.into()))
     631            0 :     }
     632              : 
     633              :     /// Check if the binary has a section with the given name
     634            0 :     pub fn has_section(&self, name: &str) -> bool {
     635            0 :         self.ptr.has_section(name.to_string())
     636            0 :     }
     637              : 
     638              :     /// Check if the binary has a section that spans the given offset
     639            0 :     pub fn has_section_with_offset(&self, offset: u64) -> bool {
     640            0 :         self.ptr.has_section_with_offset(offset)
     641            0 :     }
     642              : 
     643              :     /// Check if the binary has a section that spans the given virtual address
     644            0 :     pub fn has_section_with_va(&self, va: u64) -> bool {
     645            0 :         self.ptr.has_section_with_va(va)
     646            0 :     }
     647              : 
     648              :     /// Check if the binary has a library dependency with the given name
     649            0 :     pub fn has_library(&self, name: &str) -> bool {
     650            0 :         self.ptr.has_library(name.to_string())
     651            0 :     }
     652              : 
     653              :     /// Check if the binary has a dynamic symbol with the given name
     654            0 :     pub fn has_dynamic_symbol(&self, name: &str) -> bool {
     655            0 :         self.ptr.has_dynamic_symbol(name.to_string())
     656            0 :     }
     657              : 
     658              :     /// Check if the binary has a symtab symbol with the given name
     659            0 :     pub fn has_symtab_symbol(&self, name: &str) -> bool {
     660            0 :         self.ptr.has_symtab_symbol(name.to_string())
     661            0 :     }
     662              : 
     663              :     /// Return the index of the given name in the dynamic symbol table
     664            0 :     pub fn dynsym_idx(&self, name: &str) -> Option<u64> {
     665            0 :         let idx = self.ptr.dynsym_idx(name.to_string());
     666            0 :         if idx < 0 {
     667            0 :             return None;
     668            0 :         }
     669            0 :         Some(idx as u64)
     670            0 :     }
     671              : 
     672              :     /// Return the index of the given name in the symtab symbol table, or -1
     673            0 :     pub fn symtab_idx(&self, name: &str) -> Option<u64> {
     674            0 :         let idx = self.ptr.symtab_idx(name.to_string());
     675            0 :         if idx < 0 {
     676            0 :             return None;
     677            0 :         }
     678            0 :         Some(idx as u64)
     679            0 :     }
     680              : 
     681              :     /// Patch the GOT/PLT entry for the given symbol name
     682            0 :     pub fn patch_pltgot(&mut self, symbol_name: &str, address: u64) {
     683            0 :         self.ptr
     684            0 :             .pin_mut()
     685            0 :             .patch_pltgot_by_name(symbol_name.to_string(), address);
     686            0 :     }
     687              : 
     688              :     /// Add a section to the binary. If `loaded` is true, the section will be
     689              :     /// added in a way that it is loaded in memory. `pos` controls where the
     690              :     /// section is inserted.
     691            0 :     pub fn add_section(
     692            0 :         &mut self,
     693            0 :         section: &Section,
     694            0 :         loaded: bool,
     695            0 :         pos: SecInsertPos,
     696            0 :     ) -> Option<Section<'_>> {
     697            0 :         into_optional(
     698            0 :             self.ptr
     699            0 :                 .pin_mut()
     700            0 :                 .add_section(section.as_ffi(), loaded, pos.into()),
     701            0 :         )
     702            0 :     }
     703              : 
     704              :     /// Add a note to the binary
     705            0 :     pub fn add_note(&mut self, note: &super::note::Notes) -> super::note::Notes<'_> {
     706            0 :         super::note::Notes::from_ffi(self.ptr.pin_mut().add_note(note.as_ffi()))
     707            0 :     }
     708              : 
     709              :     /// Add a dynamic relocation
     710            0 :     pub fn add_dynamic_relocation(&mut self, reloc: &Relocation) -> Relocation<'_> {
     711            0 :         Relocation::from_ffi(self.ptr.pin_mut().add_dynamic_relocation(reloc.as_ffi()))
     712            0 :     }
     713              : 
     714              :     /// Add a `.plt.got` relocation
     715            0 :     pub fn add_pltgot_relocation(&mut self, reloc: &Relocation) -> Relocation<'_> {
     716            0 :         Relocation::from_ffi(self.ptr.pin_mut().add_pltgot_relocation(reloc.as_ffi()))
     717            0 :     }
     718              : 
     719              :     /// Add a symbol to the `.symtab` table
     720            0 :     pub fn add_symtab_symbol(&mut self, symbol: &Symbol) -> Symbol<'_> {
     721            0 :         Symbol::from_ffi(self.ptr.pin_mut().add_symtab_symbol(symbol.as_ffi()))
     722            0 :     }
     723              : 
     724              :     /// Add a symbol to the dynamic symbol table (`.dynsym`)
     725            0 :     pub fn add_dynamic_symbol(&mut self, symbol: &Symbol) -> Symbol<'_> {
     726            0 :         Symbol::from_ffi(self.ptr.pin_mut().add_dynamic_symbol(symbol.as_ffi()))
     727            0 :     }
     728              : 
     729              :     /// Add an exported function with the given address and name
     730            0 :     pub fn add_exported_function(&mut self, address: u64, name: &str) -> Symbol<'_> {
     731            0 :         Symbol::from_ffi(
     732            0 :             self.ptr
     733            0 :                 .pin_mut()
     734            0 :                 .add_exported_function(address, name.to_string()),
     735            0 :         )
     736            0 :     }
     737              : 
     738              :     /// Export the symbol with the given name, optionally setting its value (can be 0)
     739            0 :     pub fn export_symbol_by_name(&mut self, symbol_name: &str, value: u64) -> Symbol<'_> {
     740            0 :         Symbol::from_ffi(
     741            0 :             self.ptr
     742            0 :                 .pin_mut()
     743            0 :                 .export_symbol_by_name(symbol_name.to_string(), value),
     744            0 :         )
     745            0 :     }
     746              : 
     747              :     /// Export an existing symbol
     748            0 :     pub fn export_symbol(&mut self, symbol: &Symbol) -> Symbol<'_> {
     749            0 :         Symbol::from_ffi(self.ptr.pin_mut().export_symbol_obj(symbol.as_ffi()))
     750            0 :     }
     751              : 
     752              :     /// Remove the symtab symbol with the given name
     753            0 :     pub fn remove_symtab_symbol(&mut self, name: &str) {
     754            0 :         self.ptr
     755            0 :             .pin_mut()
     756            0 :             .remove_symtab_symbol_by_name(name.to_string());
     757            0 :     }
     758              : 
     759              :     /// Remove the dynamic symbol with the given name
     760            0 :     pub fn remove_dynamic_symbol(&mut self, name: &str) {
     761            0 :         self.ptr
     762            0 :             .pin_mut()
     763            0 :             .remove_dynamic_symbol_by_name(name.to_string());
     764            0 :     }
     765              : 
     766              :     /// Remove the given section. If `clear` is set, the section content will be
     767              :     /// filled with zeros before removal.
     768            0 :     pub fn remove_section(&mut self, section: &Section, clear: bool) {
     769            0 :         self.ptr.pin_mut().remove_section(section.as_ffi(), clear);
     770            0 :     }
     771              : 
     772              :     /// Remove the given note
     773            0 :     pub fn remove_note(&mut self, note: &super::note::Notes) {
     774            0 :         self.ptr.pin_mut().remove_note(note.as_ffi());
     775            0 :     }
     776              : 
     777              :     /// Extend the given segment by `size` bytes
     778            0 :     pub fn extend_segment(&mut self, segment: &Segment, size: u64) -> Option<Segment<'_>> {
     779            0 :         into_optional(
     780            0 :             self.ptr
     781            0 :                 .pin_mut()
     782            0 :                 .extend_segment(segment.ptr.as_ref().unwrap(), size),
     783            0 :         )
     784            0 :     }
     785              : 
     786              :     /// Extend the given section by `size` bytes
     787            0 :     pub fn extend_section(&mut self, section: &Section, size: u64) -> Option<Section<'_>> {
     788            0 :         into_optional(self.ptr.pin_mut().extend_section(section.as_ffi(), size))
     789            0 :     }
     790              : 
     791              :     /// Strip all debug symbols from the binary
     792            0 :     pub fn strip(&mut self) {
     793            0 :         self.ptr.pin_mut().strip();
     794            0 :     }
     795              : 
     796              :     /// Get the index of a section by its name. Returns `None` if not found.
     797            0 :     pub fn section_idx_by_name(&self, name: &str) -> Option<usize> {
     798            0 :         let idx = self.ptr.get_section_idx_by_name(name.to_string());
     799            0 :         if idx < 0 {
     800            0 :             None
     801              :         } else {
     802            0 :             Some(idx as usize)
     803              :         }
     804            0 :     }
     805              : 
     806              :     /// Get the index of the given section. Returns `None` if not found.
     807            0 :     pub fn section_idx(&self, section: &Section) -> Option<usize> {
     808            0 :         let idx = self.ptr.get_section_idx_by_section(section.as_ffi());
     809            0 :         if idx < 0 {
     810            0 :             None
     811              :         } else {
     812            0 :             Some(idx as usize)
     813              :         }
     814            0 :     }
     815              : 
     816              :     /// Relocate the PHDR table using the given strategy.
     817              :     /// Returns the new offset of the PHDR table.
     818            0 :     pub fn relocate_phdr_table(&mut self, reloc_type: PhdrReloc) -> u64 {
     819            0 :         self.ptr.pin_mut().relocate_phdr_table(reloc_type.into())
     820            0 :     }
     821              : }
     822              : 
     823              : impl AsFFI<ffi::ELF_Binary> for Binary {
     824            0 :     fn as_ffi(&self) -> &ffi::ELF_Binary {
     825            0 :         self.ptr.as_ref().unwrap()
     826            0 :     }
     827              : 
     828            0 :     fn as_mut_ffi(&mut self) -> std::pin::Pin<&mut ffi::ELF_Binary> {
     829            0 :         self.ptr.pin_mut()
     830            0 :     }
     831              : }
     832              : 
     833              : impl generic::Binary for Binary {
     834          650 :     fn as_generic(&self) -> &ffi::AbstractBinary {
     835          650 :         self.ptr.as_ref().unwrap().as_ref()
     836          650 :     }
     837              : 
     838            0 :     fn as_pin_mut_generic(&mut self) -> Pin<&mut ffi::AbstractBinary> {
     839            0 :         unsafe {
     840            0 :             Pin::new_unchecked({
     841            0 :                 (self.ptr.as_ref().unwrap().as_ref() as *const ffi::AbstractBinary
     842            0 :                     as *mut ffi::AbstractBinary)
     843            0 :                     .as_mut()
     844            0 :                     .unwrap()
     845            0 :             })
     846            0 :         }
     847            0 :     }
     848              : }
     849              : 
     850        20826 : declare_iterator!(
     851        20826 :     SymbolsVersion,
     852        20826 :     SymbolVersion<'a>,
     853        20826 :     ffi::ELF_SymbolVersion,
     854        20826 :     ffi::ELF_Binary,
     855        20826 :     ffi::ELF_Binary_it_symbols_version
     856        20826 : );
     857          221 : declare_iterator!(
     858          221 :     SymbolsVersionRequirement,
     859          221 :     SymbolVersionRequirement<'a>,
     860          221 :     ffi::ELF_SymbolVersionRequirement,
     861          221 :     ffi::ELF_Binary,
     862          221 :     ffi::ELF_Binary_it_symbols_version_requirement
     863          221 : );
     864           39 : declare_iterator!(
     865           39 :     SymbolsVersionDefinition,
     866           39 :     SymbolVersionDefinition<'a>,
     867           39 :     ffi::ELF_SymbolVersionDefinition,
     868           39 :     ffi::ELF_Binary,
     869           39 :     ffi::ELF_Binary_it_symbols_version_definition
     870           39 : );
     871            0 : declare_iterator!(
     872            0 :     AllSymbols,
     873            0 :     Symbol<'a>,
     874            0 :     ffi::ELF_Symbol,
     875            0 :     ffi::ELF_Binary,
     876            0 :     ffi::ELF_Binary_it_symbols
     877            0 : );
        

Generated by: LCOV version 2.1-1