LCOV - code coverage report
Current view: top level - src/macho - symbol.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 82.8 % 87 72
Test Date: 2025-08-10:00:00:00 Functions: 70.8 % 24 17

            Line data    Source code
       1              : use std::marker::PhantomData;
       2              : use std::pin::Pin;
       3              : 
       4              : use crate::common::{into_optional, 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       404268 : #[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       404268 :     fn from(value: u32) -> Self {
      38       404268 :         match value {
      39       104724 :             0x00000000 => Category::NONE,
      40       166680 :             0x00000001 => Category::LOCAL,
      41        83952 :             0x00000002 => Category::EXTERNAL,
      42        48912 :             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       404268 :     }
      49              : }
      50              : 
      51              : #[allow(non_camel_case_types)]
      52       404268 : #[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       404268 :     fn from(value: u32) -> Self {
      62       404268 :         match value {
      63        49680 :             0x00000001 => Origin::DYLD_EXPORT,
      64        55044 :             0x00000002 => Origin::DYLD_BIND,
      65       299544 :             0x00000003 => Origin::LC_SYMTAB,
      66            0 :             _ => Origin::UNKNOWN(value),
      67              :         }
      68       404268 :     }
      69              : }
      70              : 
      71              : impl Symbol<'_> {
      72       404268 :     pub fn get_type(&self) -> u8 {
      73       404268 :         self.ptr.get_type()
      74       404268 :     }
      75              : 
      76              :     /// It returns the number of sections in which this symbol can be found.
      77              :     /// If the symbol can't be found in any section, it returns 0 (`NO_SECT`)
      78       404268 :     pub fn numberof_sections(&self) -> u8 {
      79       404268 :         self.ptr.numberof_sections()
      80       404268 :     }
      81              : 
      82              :     /// Return information about the symbol
      83       404268 :     pub fn description(&self) -> u16 {
      84       404268 :         self.ptr.description()
      85       404268 :     }
      86              : 
      87              :     /// Return the origin of the symbol: from `LC_SYMTAB` from the Dyld information, ...
      88       404268 :     pub fn origin(&self) -> Origin {
      89       404268 :         Origin::from(self.ptr.origin())
      90       404268 :     }
      91              : 
      92              :     /// Category of the symbol according to the `LC_DYSYMTAB` command
      93       404268 :     pub fn category(&self) -> Category {
      94       404268 :         Category::from(self.ptr.category())
      95       404268 :     }
      96              : 
      97              :     /// Export info associated with this symbol (if any)
      98       404268 :     pub fn export_info(&self) -> Option<ExportInfo> {
      99       404268 :         into_optional(self.ptr.export_info())
     100       404268 :     }
     101              : 
     102              :     /// Binding info associated with this symbol (if any)
     103       404268 :     pub fn binding_info(&self) -> Option<BindingInfo> {
     104       404268 :         into_optional(self.ptr.binding_info())
     105       404268 :     }
     106              : 
     107              :     /// Return the library in which this symbol is defined (if any)
     108       404268 :     pub fn library(&self) -> Option<Dylib> {
     109       404268 :         into_optional(self.ptr.library())
     110       404268 :     }
     111              : 
     112              :     /// Try to demangle the symbol or return an empty string if it is not possible
     113       290832 :     pub fn demangled_name(&self) -> String {
     114       290832 :         self.ptr.demangled_name().to_string()
     115       290832 :     }
     116              : }
     117              : 
     118              : impl std::fmt::Debug for Symbol<'_> {
     119       404268 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     120       404268 :         let base = self as &dyn generic::Symbol;
     121       404268 :         f.debug_struct("Symbol")
     122       404268 :             .field("base", &base)
     123       404268 :             .field("type", &self.get_type())
     124       404268 :             .field("numberof_sections", &self.numberof_sections())
     125       404268 :             .field("description", &self.description())
     126       404268 :             .field("origin", &self.origin())
     127       404268 :             .field("category", &self.category())
     128       404268 :             .field("export_info", &self.export_info())
     129       404268 :             .field("binding_info", &self.binding_info())
     130       404268 :             .field("library", &self.library())
     131       404268 :             .finish()
     132       404268 :     }
     133              : }
     134              : 
     135              : impl<'a> FromFFI<ffi::MachO_Symbol> for Symbol<'a> {
     136       454788 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_Symbol>) -> Self {
     137       454788 :         Self {
     138       454788 :             ptr,
     139       454788 :             _owner: PhantomData,
     140       454788 :         }
     141       454788 :     }
     142              : }
     143              : 
     144              : impl generic::Symbol for Symbol<'_> {
     145      1263324 :     fn as_generic(&self) -> &ffi::AbstractSymbol {
     146      1263324 :         self.ptr.as_ref().unwrap().as_ref()
     147      1263324 :     }
     148              : 
     149            0 :     fn as_pin_mut_generic(&mut self) -> Pin<&mut ffi::AbstractSymbol> {
     150            0 :         unsafe {
     151            0 :             Pin::new_unchecked({
     152            0 :                 (self.ptr.as_ref().unwrap().as_ref() as *const ffi::AbstractSymbol
     153            0 :                     as *mut ffi::AbstractSymbol)
     154            0 :                     .as_mut()
     155            0 :                     .unwrap()
     156            0 :             })
     157            0 :         }
     158            0 :     }
     159              : }
     160              : 
     161       290832 : declare_iterator!(
     162       290832 :     Symbols,
     163       290832 :     Symbol<'a>,
     164       290832 :     ffi::MachO_Symbol,
     165       290832 :     ffi::MachO_Binary,
     166       290832 :     ffi::MachO_Binary_it_symbols
     167       290832 : );
        

Generated by: LCOV version 2.1-1