LCOV - code coverage report
Current view: top level - src/macho - symbol.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 61.0 % 118 72
Test Date: 2026-04-12:00:00:00 Functions: 50.0 % 34 17

            Line data    Source code
       1              : use std::marker::PhantomData;
       2              : use std::pin::Pin;
       3              : 
       4              : use crate::common::{into_optional, AsFFI, FromFFI};
       5              : use crate::declare_iterator;
       6              : use crate::generic;
       7              : use lief_ffi as ffi;
       8              : 
       9              : use super::commands::Dylib;
      10              : use super::{BindingInfo, ExportInfo};
      11              : 
      12              : /// Structure that represents a Symbol in a Mach-O file.
      13              : ///
      14              : /// A Mach-O symbol can come from:
      15              : /// 1. The symbols command (LC_SYMTAB / SymbolCommand)
      16              : /// 2. The Dyld Export trie
      17              : /// 3. The Dyld Symbol bindings
      18              : pub struct Symbol<'a> {
      19              :     ptr: cxx::UniquePtr<ffi::MachO_Symbol>,
      20              :     _owner: PhantomData<&'a ()>,
      21              : }
      22              : 
      23              : #[allow(non_camel_case_types)]
      24       463034 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
      25              : pub enum Category {
      26              :     NONE,
      27              :     LOCAL,
      28              :     EXTERNAL,
      29              :     UNDEFINED,
      30              :     INDIRECT_ABS,
      31              :     INDIRECT_LOCAL,
      32              :     INDIRECT_ABS_LOCAL,
      33              :     UNKNOWN(u32),
      34              : }
      35              : 
      36              : impl From<u32> for Category {
      37       463034 :     fn from(value: u32) -> Self {
      38       463034 :         match value {
      39       113451 :             0x00000000 => Category::NONE,
      40       196963 :             0x00000001 => Category::LOCAL,
      41        90974 :             0x00000002 => Category::EXTERNAL,
      42        61646 :             0x00000003 => Category::UNDEFINED,
      43            0 :             0x00000004 => Category::INDIRECT_ABS,
      44            0 :             0x00000005 => Category::INDIRECT_LOCAL,
      45            0 :             0x00000006 => Category::INDIRECT_ABS_LOCAL,
      46            0 :             _ => Category::UNKNOWN(value),
      47              :         }
      48       463034 :     }
      49              : }
      50              : 
      51              : #[allow(non_camel_case_types)]
      52       463034 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
      53              : pub enum Origin {
      54              :     DYLD_EXPORT,
      55              :     DYLD_BIND,
      56              :     LC_SYMTAB,
      57              :     UNKNOWN(u32),
      58              : }
      59              : 
      60              : impl From<u32> for Origin {
      61       463034 :     fn from(value: u32) -> Self {
      62       463034 :         match value {
      63        53820 :             0x00000001 => Origin::DYLD_EXPORT,
      64        59631 :             0x00000002 => Origin::DYLD_BIND,
      65       349583 :             0x00000003 => Origin::LC_SYMTAB,
      66            0 :             _ => Origin::UNKNOWN(value),
      67              :         }
      68       463034 :     }
      69              : }
      70              : 
      71              : /// Symbol type as defined by `nlist_xx.n_type & N_TYPE`
      72              : #[allow(non_camel_case_types)]
      73            0 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
      74              : pub enum Type {
      75              :     /// The symbol is undefined
      76              :     UNDEFINED,
      77              :     /// The symbol is absolute
      78              :     ABSOLUTE_SYM,
      79              :     /// The symbol is defined in a specific section
      80              :     SECTION,
      81              :     /// The symbol is undefined and the image is using a prebound value
      82              :     PREBOUND,
      83              :     /// The symbol is defined to be the same as another symbol
      84              :     INDIRECT,
      85              :     UNKNOWN(u32),
      86              : }
      87              : 
      88              : impl From<u32> for Type {
      89            0 :     fn from(value: u32) -> Self {
      90            0 :         match value {
      91            0 :             0x0 => Type::UNDEFINED,
      92            0 :             0x2 => Type::ABSOLUTE_SYM,
      93            0 :             0xe => Type::SECTION,
      94            0 :             0xc => Type::PREBOUND,
      95            0 :             0xa => Type::INDIRECT,
      96            0 :             _ => Type::UNKNOWN(value),
      97              :         }
      98            0 :     }
      99              : }
     100              : 
     101              : impl From<Type> for u32 {
     102            0 :     fn from(value: Type) -> u32 {
     103            0 :         match value {
     104            0 :             Type::UNDEFINED => 0x0,
     105            0 :             Type::ABSOLUTE_SYM => 0x2,
     106            0 :             Type::SECTION => 0xe,
     107            0 :             Type::PREBOUND => 0xc,
     108            0 :             Type::INDIRECT => 0xa,
     109            0 :             Type::UNKNOWN(v) => v,
     110              :         }
     111            0 :     }
     112              : }
     113              : 
     114              : impl Symbol<'_> {
     115       463034 :     pub fn get_type(&self) -> u8 {
     116       463034 :         self.ptr.get_type()
     117       463034 :     }
     118              : 
     119              :     /// It returns the number of sections in which this symbol can be found.
     120              :     /// If the symbol can't be found in any section, it returns 0 (`NO_SECT`)
     121       463034 :     pub fn numberof_sections(&self) -> u8 {
     122       463034 :         self.ptr.numberof_sections()
     123       463034 :     }
     124              : 
     125              :     /// Return information about the symbol
     126       463034 :     pub fn description(&self) -> u16 {
     127       463034 :         self.ptr.description()
     128       463034 :     }
     129              : 
     130              :     /// Return the origin of the symbol: from `LC_SYMTAB` from the Dyld information, ...
     131       463034 :     pub fn origin(&self) -> Origin {
     132       463034 :         Origin::from(self.ptr.origin())
     133       463034 :     }
     134              : 
     135              :     /// Category of the symbol according to the `LC_DYSYMTAB` command
     136       463034 :     pub fn category(&self) -> Category {
     137       463034 :         Category::from(self.ptr.category())
     138       463034 :     }
     139              : 
     140              :     /// Export info associated with this symbol (if any)
     141       463034 :     pub fn export_info(&self) -> Option<ExportInfo<'_>> {
     142       463034 :         into_optional(self.ptr.export_info())
     143       463034 :     }
     144              : 
     145              :     /// Binding info associated with this symbol (if any)
     146       463034 :     pub fn binding_info(&self) -> Option<BindingInfo<'_>> {
     147       463034 :         into_optional(self.ptr.binding_info())
     148       463034 :     }
     149              : 
     150              :     /// Return the library in which this symbol is defined (if any)
     151       463034 :     pub fn library(&self) -> Option<Dylib<'_>> {
     152       463034 :         into_optional(self.ptr.library())
     153       463034 :     }
     154              : 
     155              :     /// Whether this symbol is external
     156            0 :     pub fn is_external(&self) -> bool {
     157            0 :         self.ptr.is_external()
     158            0 :     }
     159              : 
     160              :     /// Return the library ordinal for this symbol. A negative ordinal indicates
     161              :     /// a special value (e.g., -1 for `SELF_LIBRARY`, -2 for `MAIN_EXECUTABLE`)
     162            0 :     pub fn library_ordinal(&self) -> i32 {
     163            0 :         self.ptr.library_ordinal()
     164            0 :     }
     165              : 
     166              :     /// Try to demangle the symbol or return an empty string if it is not possible
     167       335296 :     pub fn demangled_name(&self) -> String {
     168       335296 :         self.ptr.demangled_name().to_string()
     169       335296 :     }
     170              : }
     171              : 
     172              : impl std::fmt::Debug for Symbol<'_> {
     173       463034 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     174       463034 :         let base = self as &dyn generic::Symbol;
     175       463034 :         f.debug_struct("Symbol")
     176       463034 :             .field("base", &base)
     177       463034 :             .field("type", &self.get_type())
     178       463034 :             .field("numberof_sections", &self.numberof_sections())
     179       463034 :             .field("description", &self.description())
     180       463034 :             .field("origin", &self.origin())
     181       463034 :             .field("category", &self.category())
     182       463034 :             .field("export_info", &self.export_info())
     183       463034 :             .field("binding_info", &self.binding_info())
     184       463034 :             .field("library", &self.library())
     185       463034 :             .finish()
     186       463034 :     }
     187              : }
     188              : 
     189              : impl<'a> FromFFI<ffi::MachO_Symbol> for Symbol<'a> {
     190       525304 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_Symbol>) -> Self {
     191       525304 :         Self {
     192       525304 :             ptr,
     193       525304 :             _owner: PhantomData,
     194       525304 :         }
     195       525304 :     }
     196              : }
     197              : 
     198              : impl AsFFI<ffi::MachO_Symbol> for Symbol<'_> {
     199            0 :     fn as_ffi(&self) -> &ffi::MachO_Symbol {
     200            0 :         self.ptr.as_ref().unwrap()
     201            0 :     }
     202              : 
     203            0 :     fn as_mut_ffi(&mut self) -> Pin<&mut ffi::MachO_Symbol> {
     204            0 :         self.ptr.pin_mut()
     205            0 :     }
     206              : }
     207              : 
     208              : impl generic::Symbol for Symbol<'_> {
     209      1451372 :     fn as_generic(&self) -> &ffi::AbstractSymbol {
     210      1451372 :         self.ptr.as_ref().unwrap().as_ref()
     211      1451372 :     }
     212              : 
     213            0 :     fn as_pin_mut_generic(&mut self) -> Pin<&mut ffi::AbstractSymbol> {
     214            0 :         unsafe {
     215            0 :             Pin::new_unchecked({
     216            0 :                 (self.ptr.as_ref().unwrap().as_ref() as *const ffi::AbstractSymbol
     217            0 :                     as *mut ffi::AbstractSymbol)
     218            0 :                     .as_mut()
     219            0 :                     .unwrap()
     220            0 :             })
     221            0 :         }
     222            0 :     }
     223              : }
     224              : 
     225       335296 : declare_iterator!(
     226       335296 :     Symbols,
     227       335296 :     Symbol<'a>,
     228       335296 :     ffi::MachO_Symbol,
     229       335296 :     ffi::MachO_Binary,
     230       335296 :     ffi::MachO_Binary_it_symbols
     231       335296 : );
        

Generated by: LCOV version 2.1-1