LCOV - code coverage report
Current view: top level - src/elf - symbol.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 83.7 % 98 82
Test Date: 2025-06-24:00:00:00 Functions: 59.0 % 39 23

            Line data    Source code
       1              : use lief_ffi as ffi;
       2              : use std::fmt;
       3              : use std::pin::Pin;
       4              : use std::marker::PhantomData;
       5              : 
       6              : use crate::common::{FromFFI, into_optional};
       7              : use crate::declare_iterator;
       8              : use crate::generic;
       9              : use crate::elf::Section;
      10              : use super::SymbolVersion;
      11              : 
      12              : /// Structure which reprents an ELF symbol
      13              : pub struct Symbol<'a> {
      14              :     ptr: cxx::UniquePtr<ffi::ELF_Symbol>,
      15              :     _owner: PhantomData<&'a ffi::ELF_Binary>
      16              : }
      17              : 
      18              : #[allow(non_camel_case_types)]
      19        38748 : #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
      20              : pub enum Binding {
      21              :     /// Local symbol
      22              :     LOCAL,
      23              :     /// Global symbol
      24              :     GLOBAL,
      25              :     /// Weak symbol
      26              :     WEAK,
      27              :     /// Unique symbol
      28              :     GNU_UNIQUE,
      29              :     UNKNOWN(u32),
      30              : }
      31              : 
      32              : impl Binding {
      33        38748 :     pub fn from_value(value: u32) -> Self {
      34        38748 :         match value {
      35         4524 :             0x00000000 => Binding::LOCAL,
      36        28632 :             0x00000001 => Binding::GLOBAL,
      37         5472 :             0x00000002 => Binding::WEAK,
      38          120 :             0x0000000a => Binding::GNU_UNIQUE,
      39            0 :             _ => Binding::UNKNOWN(value),
      40              : 
      41              :         }
      42        38748 :     }
      43              : }
      44              : 
      45              : 
      46              : #[allow(non_camel_case_types)]
      47        38748 : #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
      48              : /// Type of the symbol. This enum matches the `STT_xxx` values of the ELF
      49              : /// specs
      50              : pub enum Type {
      51              :     /// Symbol's type is not specified
      52              :     NOTYPE,
      53              :     /// Symbol is a data object (variable, array, etc.)
      54              :     OBJECT,
      55              :     /// Symbol is executable code (function, etc.)
      56              :     FUNC,
      57              :     /// Symbol refers to a section
      58              :     SECTION,
      59              :     /// Local, absolute symbol that refers to a file
      60              :     FILE,
      61              :     /// An uninitialized common block
      62              :     COMMON,
      63              :     /// Thread local data object
      64              :     TLS,
      65              :     /// GNU indirect function
      66              :     GNU_IFUNC,
      67              :     UNKNOWN(u32),
      68              : }
      69              : 
      70              : impl Type {
      71        38748 :     pub fn from_value(value: u32) -> Self {
      72        38748 :         match value {
      73         4992 :             0x00000000 => Type::NOTYPE,
      74         9528 :             0x00000001 => Type::OBJECT,
      75        23412 :             0x00000002 => Type::FUNC,
      76          660 :             0x00000003 => Type::SECTION,
      77           84 :             0x00000004 => Type::FILE,
      78            0 :             0x00000005 => Type::COMMON,
      79           72 :             0x00000006 => Type::TLS,
      80            0 :             0x0000000a => Type::GNU_IFUNC,
      81            0 :             _ => Type::UNKNOWN(value),
      82              : 
      83              :         }
      84        38748 :     }
      85              : }
      86              : 
      87              : 
      88              : #[allow(non_camel_case_types)]
      89        38748 : #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
      90              : /// Visibility of the symbol. This enum matches the `STV_xxx` values of the
      91              : /// official ELF specs
      92              : pub enum Visibility {
      93              :     /// Visibility is specified by binding type
      94              :     DEFAULT,
      95              :     /// Defined by processor supplements
      96              :     INTERNAL,
      97              :     /// Not visible to other components
      98              :     HIDDEN,
      99              :     /// Visible in other components but not preemptable
     100              :     PROTECTED,
     101              :     UNKNOWN(u32),
     102              : }
     103              : 
     104              : impl Visibility {
     105        38748 :     pub fn from_value(value: u32) -> Self {
     106        38748 :         match value {
     107        38472 :             0x00000000 => Visibility::DEFAULT,
     108            0 :             0x00000001 => Visibility::INTERNAL,
     109          228 :             0x00000002 => Visibility::HIDDEN,
     110            0 :             0x00000003 => Visibility::PROTECTED,
     111           48 :             _ => Visibility::UNKNOWN(value),
     112              : 
     113              :         }
     114        38748 :     }
     115              : }
     116              : 
     117              : impl Symbol<'_> {
     118              :     /// The symbol's type provides a general classification for the associated entity
     119        38748 :     pub fn get_type(&self) -> Type {
     120        38748 :         Type::from_value(self.ptr.get_type())
     121        38748 :     }
     122              : 
     123              :     /// The symbol's binding determines the linkage visibility and behavior
     124        38748 :     pub fn binding(&self) -> Binding {
     125        38748 :         Binding::from_value(self.ptr.binding())
     126        38748 :     }
     127              : 
     128              :     /// This member specifies the symbol's type and binding attributes.
     129        38748 :     pub fn information(&self) -> u8 {
     130        38748 :         self.ptr.information()
     131        38748 :     }
     132              : 
     133              :     /// Alias for [`Symbol::visibility`]
     134        38748 :     pub fn other(&self) -> u8 {
     135        38748 :         self.ptr.other()
     136        38748 :     }
     137              : 
     138              :     /// ELF Section index associated with the symbol
     139        38748 :     pub fn section_idx(&self) -> u16 {
     140        38748 :         self.ptr.section_idx()
     141        38748 :     }
     142              : 
     143              :     /// Symbol visibility
     144        38748 :     pub fn visibility(&self) -> Visibility {
     145        38748 :         Visibility::from_value(self.ptr.visibility())
     146        38748 :     }
     147              : 
     148              :     /// Section associated with the symbol (if any)
     149        38748 :     pub fn section(&self) -> Option<Section> {
     150        38748 :         into_optional(self.ptr.section())
     151        38748 :     }
     152              : 
     153              :     /// Return the SymbolVersion associated with this symbol (if any)
     154        38748 :     pub fn symbol_version(&self) -> Option<SymbolVersion> {
     155        38748 :         into_optional(self.ptr.symbol_version())
     156        38748 :     }
     157              : 
     158              :     /// Try to demangle the symbol or return an empty string if it is not possible
     159         9324 :     pub fn demangled_name(&self) -> String {
     160         9324 :         self.ptr.demangled_name().to_string()
     161         9324 :     }
     162              : }
     163              : 
     164              : impl fmt::Debug for Symbol<'_> {
     165        38748 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     166        38748 :        let base = self as &dyn generic::Symbol;
     167        38748 :         f.debug_struct("Symbol")
     168        38748 :             .field("base", &base)
     169        38748 :             .field("type", &self.get_type())
     170        38748 :             .field("binding", &self.binding())
     171        38748 :             .field("information", &self.information())
     172        38748 :             .field("other", &self.other())
     173        38748 :             .field("section_idx", &self.section_idx())
     174        38748 :             .field("visibility", &self.visibility())
     175        38748 :             .field("section", &self.section())
     176        38748 :             .field("symbol_version", &self.symbol_version())
     177        38748 :             .finish()
     178        38748 :     }
     179              : }
     180              : 
     181              : impl FromFFI<ffi::ELF_Symbol> for Symbol<'_> {
     182        38772 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_Symbol>) -> Self {
     183        38772 :         Self {
     184        38772 :             ptr,
     185        38772 :             _owner: PhantomData
     186        38772 :         }
     187        38772 :     }
     188              : }
     189              : 
     190              : impl generic::Symbol for Symbol<'_> {
     191       144216 :     fn as_generic(&self) -> &ffi::AbstractSymbol {
     192       144216 :         self.ptr.as_ref().unwrap().as_ref()
     193       144216 :     }
     194              : 
     195            0 :     fn as_pin_mut_generic(&mut self) -> Pin<&mut ffi::AbstractSymbol> {
     196            0 :         unsafe {
     197            0 :             Pin::new_unchecked({
     198            0 :                 (self.ptr.as_ref().unwrap().as_ref() as *const ffi::AbstractSymbol
     199            0 :                     as *mut ffi::AbstractSymbol)
     200            0 :                     .as_mut()
     201            0 :                     .unwrap()
     202            0 :             })
     203            0 :         }
     204            0 :     }
     205              : }
     206              : 
     207              : impl fmt::Display for Symbol<'_> {
     208         9324 :     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     209         9324 :         write!(f, "{}", self.ptr.to_string())
     210         9324 :     }
     211              : }
     212              : 
     213         9324 : declare_iterator!(DynamicSymbols, Symbol<'a>, ffi::ELF_Symbol, ffi::ELF_Binary, ffi::ELF_Binary_it_dynamic_symbols);
     214         3096 : declare_iterator!(ExportedSymbols, Symbol<'a>, ffi::ELF_Symbol, ffi::ELF_Binary, ffi::ELF_Binary_it_exported_symbols);
     215         5832 : declare_iterator!(ImportedSymbols, Symbol<'a>, ffi::ELF_Symbol, ffi::ELF_Binary, ffi::ELF_Binary_it_imported_symbols);
     216         1056 : declare_iterator!(SymtabSymbols, Symbol<'a>, ffi::ELF_Symbol, ffi::ELF_Binary, ffi::ELF_Binary_it_symtab_symbols);
        

Generated by: LCOV version 2.1-1