LCOV - code coverage report
Current view: top level - src/macho - binding_info.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 81.1 % 175 142
Test Date: 2024-11-30:00:00:00 Functions: 54.4 % 68 37

            Line data    Source code
       1              : use lief_ffi as ffi;
       2              : 
       3              : use super::commands::dylib::Dylib;
       4              : use super::commands::Segment;
       5              : use super::symbol::Symbol;
       6              : use std::{fmt, marker::PhantomData};
       7              : 
       8              : use crate::common::{into_optional, FromFFI};
       9              : 
      10       277650 : #[derive(Debug)]
      11              : /// This enum exposes all the different types of binding operations that
      12              : /// we can find in a Mach-O binary. [`BindingInfo::Dyld`] exposes the bindings info
      13              : /// wrapped in the `LC_DYLD_INFO` command while [`BindingInfo::Chained`] exposes the new
      14              : /// chained bindings implemented in the `DYLD_CHAINED_FIXUPS` command.
      15              : pub enum BindingInfo<'a> {
      16              :     /// Bindings defined in `LC_DYLD_INFO` command
      17              :     Dyld(Dyld<'a>),
      18              :     /// Bindings defined in `DYLD_CHAINED_FIXUPS` command
      19              :     Chained(Chained<'a>),
      20              :     /// Bindings infered from the indirect symbol table
      21              :     Indirect(Indirect<'a>),
      22              :     /// Fallback item
      23              :     Generic(Generic<'a>),
      24              : }
      25              : 
      26              : /// Generic trait shared by all [`BindingInfo`] items
      27              : pub trait AsGeneric {
      28              :     #[doc(hidden)]
      29              :     fn as_generic(&self) -> &ffi::MachO_BindingInfo;
      30              : 
      31              :     /// Library associated with the binding (if any)
      32        64450 :     fn library(&self) -> Option<Dylib> {
      33        64450 :         into_optional(self.as_generic().library())
      34        64450 :     }
      35              : 
      36              :     /// Symbol associated with the binding (if any)
      37        64450 :     fn symbol(&self) -> Option<Symbol> {
      38        64450 :         into_optional(self.as_generic().symbol())
      39        64450 :     }
      40              : 
      41              :     /// Segment associated with the binding (if any)
      42        64450 :     fn segment(&self) -> Option<Segment> {
      43        64450 :         into_optional(self.as_generic().segment())
      44        64450 :     }
      45              : 
      46              :     /// Address of the binding
      47       278150 :     fn address(&self) -> u64 {
      48       278150 :         self.as_generic().address()
      49       278150 :     }
      50              : 
      51              :     /// Value added to the segment's virtual address when bound
      52       278150 :     fn addend(&self) -> i64 {
      53       278150 :         self.as_generic().addend()
      54       278150 :     }
      55              : 
      56       278150 :     fn library_ordinal(&self) -> i32 {
      57       278150 :         self.as_generic().library_ordinal()
      58       278150 :     }
      59              : }
      60              : 
      61              : impl AsGeneric for BindingInfo<'_> {
      62              :     #[doc(hidden)]
      63            0 :     fn as_generic(&self) -> &ffi::MachO_BindingInfo {
      64            0 :         match &self {
      65            0 :             BindingInfo::Dyld(info) => {
      66            0 :                 info.as_generic()
      67              :             }
      68            0 :             BindingInfo::Chained(info) => {
      69            0 :                 info.as_generic()
      70              :             }
      71            0 :             BindingInfo::Indirect(info) => {
      72            0 :                 info.as_generic()
      73              :             }
      74            0 :             BindingInfo::Generic(info) => {
      75            0 :                 info.as_generic()
      76              :             }
      77              :         }
      78            0 :     }
      79              : }
      80              : 
      81              : impl std::fmt::Debug for &dyn AsGeneric {
      82       278150 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
      83       278150 :         f.debug_struct("AsGeneric")
      84       278150 :             .field("address", &self.address())
      85       278150 :             .field("addend", &self.addend())
      86       278150 :             .field("library_ordinal", &self.library_ordinal())
      87       278150 :             .finish()
      88       278150 :     }
      89              : }
      90              : 
      91              : impl<'a> FromFFI<ffi::MachO_BindingInfo> for BindingInfo<'a> {
      92       148750 :     fn from_ffi(ffi_entry: cxx::UniquePtr<ffi::MachO_BindingInfo>) -> Self {
      93       148750 :         unsafe {
      94       148750 :             let cmd_ref = ffi_entry.as_ref().unwrap();
      95       148750 : 
      96       148750 :             if ffi::MachO_ChainedBindingInfo::classof(cmd_ref) {
      97          990 :                 let raw = {
      98          990 :                     type From = cxx::UniquePtr<ffi::MachO_BindingInfo>;
      99          990 :                     type To = cxx::UniquePtr<ffi::MachO_ChainedBindingInfo>;
     100          990 :                     std::mem::transmute::<From, To>(ffi_entry)
     101          990 :                 };
     102          990 :                 BindingInfo::Chained(Chained::from_ffi(raw))
     103       147760 :             } else if ffi::MachO_DyldBindingInfo::classof(cmd_ref) {
     104       147020 :                 let raw = {
     105       147020 :                     type From = cxx::UniquePtr<ffi::MachO_BindingInfo>;
     106       147020 :                     type To = cxx::UniquePtr<ffi::MachO_DyldBindingInfo>;
     107       147020 :                     std::mem::transmute::<From, To>(ffi_entry)
     108       147020 :                 };
     109       147020 :                 BindingInfo::Dyld(Dyld::from_ffi(raw))
     110          740 :             } else if ffi::MachO_IndirectBindingInfo::classof(cmd_ref) {
     111          740 :                 let raw = {
     112          740 :                     type From = cxx::UniquePtr<ffi::MachO_BindingInfo>;
     113          740 :                     type To = cxx::UniquePtr<ffi::MachO_IndirectBindingInfo>;
     114          740 :                     std::mem::transmute::<From, To>(ffi_entry)
     115          740 :                 };
     116          740 :                 BindingInfo::Indirect(Indirect::from_ffi(raw))
     117              :             } else {
     118            0 :                 BindingInfo::Generic(Generic::from_ffi(ffi_entry))
     119              :             }
     120              :         }
     121       148750 :     }
     122              : }
     123              : 
     124              : pub struct Generic<'a> {
     125              :     ptr: cxx::UniquePtr<ffi::MachO_BindingInfo>,
     126              :     _owner: PhantomData<&'a ()>,
     127              : }
     128              : 
     129              : impl fmt::Debug for Generic<'_> {
     130            0 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     131            0 :         let base = self as &dyn AsGeneric;
     132            0 :         f.debug_struct("Generic").field("base", &base).finish()
     133            0 :     }
     134              : }
     135              : 
     136              : impl<'a> FromFFI<ffi::MachO_BindingInfo> for Generic<'a> {
     137            0 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_BindingInfo>) -> Self {
     138            0 :         Self {
     139            0 :             ptr,
     140            0 :             _owner: PhantomData,
     141            0 :         }
     142            0 :     }
     143              : }
     144              : 
     145              : impl AsGeneric for Generic<'_> {
     146            0 :     fn as_generic(&self) -> &ffi::MachO_BindingInfo {
     147            0 :         self.ptr.as_ref().unwrap()
     148            0 :     }
     149              : }
     150              : 
     151              : /// This structure represents a binding operation coming from binding bytecode
     152              : /// of `LC_DYLD_INFO`
     153              : pub struct Dyld<'a> {
     154              :     ptr: cxx::UniquePtr<ffi::MachO_DyldBindingInfo>,
     155              :     _owner: PhantomData<&'a ()>,
     156              : }
     157              : 
     158              : #[allow(non_camel_case_types)]
     159       275920 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
     160              : pub enum BINDING_CLASS {
     161              :     WEAK,
     162              :     LAZY,
     163              :     STANDARD,
     164              :     THREADED,
     165              :     UNKNOWN(u64),
     166              : }
     167              : 
     168              : impl BINDING_CLASS {
     169       275920 :     pub fn from_value(value: u64) -> Self {
     170       275920 :         match value {
     171         1380 :             0x00000001 => BINDING_CLASS::WEAK,
     172        71460 :             0x00000002 => BINDING_CLASS::LAZY,
     173       203080 :             0x00000003 => BINDING_CLASS::STANDARD,
     174            0 :             0x00000064 => BINDING_CLASS::THREADED,
     175            0 :             _ => BINDING_CLASS::UNKNOWN(value),
     176              :         }
     177       275920 :     }
     178              : }
     179              : 
     180              : #[allow(non_camel_case_types)]
     181       275920 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
     182              : pub enum BIND_TYPES {
     183              :     POINTER,
     184              :     TEXT_ABSOLUTE32,
     185              :     TEXT_PCREL32,
     186              :     UNKNOWN(u64),
     187              : }
     188              : 
     189              : impl BIND_TYPES {
     190       275920 :     pub fn from_value(value: u64) -> Self {
     191       275920 :         match value {
     192       275920 :             0x00000001 => BIND_TYPES::POINTER,
     193            0 :             0x00000002 => BIND_TYPES::TEXT_ABSOLUTE32,
     194            0 :             0x00000003 => BIND_TYPES::TEXT_PCREL32,
     195            0 :             _ => BIND_TYPES::UNKNOWN(value),
     196              :         }
     197       275920 :     }
     198              : }
     199              : 
     200              : impl Dyld<'_> {
     201              :     /// Class of the binding (weak, lazy, ...)
     202       275920 :     pub fn binding_class(&self) -> BINDING_CLASS {
     203       275920 :         BINDING_CLASS::from_value(self.ptr.binding_class())
     204       275920 :     }
     205              : 
     206              :     /// Type of the binding. Most of the times it should be [`BIND_TYPES::POINTER`]
     207       275920 :     pub fn binding_type(&self) -> BIND_TYPES {
     208       275920 :         BIND_TYPES::from_value(self.ptr.binding_type())
     209       275920 :     }
     210              : 
     211       275920 :     pub fn is_non_weak_definition(&self) -> bool {
     212       275920 :         self.ptr.is_non_weak_definition()
     213       275920 :     }
     214              : 
     215       275920 :     pub fn original_offset(&self) -> u64 {
     216       275920 :         self.ptr.original_offset()
     217       275920 :     }
     218              : }
     219              : 
     220              : impl fmt::Debug for Dyld<'_> {
     221       275920 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     222       275920 :         let base = self as &dyn AsGeneric;
     223       275920 :         f.debug_struct("Dyld")
     224       275920 :             .field("base", &base)
     225       275920 :             .field("binding_class", &self.binding_class())
     226       275920 :             .field("binding_type", &self.binding_type())
     227       275920 :             .field("is_non_weak_definition", &self.is_non_weak_definition())
     228       275920 :             .field("original_offset", &self.original_offset())
     229       275920 :             .finish()
     230       275920 :     }
     231              : }
     232              : 
     233              : impl FromFFI<ffi::MachO_DyldBindingInfo> for Dyld<'_> {
     234       211470 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_DyldBindingInfo>) -> Self {
     235       211470 :         Self {
     236       211470 :             ptr,
     237       211470 :             _owner: PhantomData,
     238       211470 :         }
     239       211470 :     }
     240              : }
     241              : 
     242              : impl AsGeneric for Dyld<'_> {
     243      1021110 :     fn as_generic(&self) -> &ffi::MachO_BindingInfo {
     244      1021110 :         self.ptr.as_ref().unwrap().as_ref()
     245      1021110 :     }
     246              : }
     247              : /// This structure represents a binding operation coming from chained binding command:
     248              : /// `LC_DYLD_CHAINED_FIXUPS`
     249              : pub struct Chained<'a> {
     250              :     ptr: cxx::UniquePtr<ffi::MachO_ChainedBindingInfo>,
     251              :     _owner: PhantomData<&'a ()>,
     252              : }
     253              : 
     254              : #[allow(non_camel_case_types)]
     255         1530 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
     256              : pub enum CHAINED_FORMAT {
     257              :     IMPORT,
     258              :     IMPORT_ADDEND,
     259              :     IMPORT_ADDEND64,
     260              :     UNKNOWN(u32),
     261              : }
     262              : 
     263              : impl CHAINED_FORMAT {
     264         1530 :     pub fn from_value(value: u32) -> Self {
     265         1530 :         match value {
     266         1530 :             0x00000001 => CHAINED_FORMAT::IMPORT,
     267            0 :             0x00000002 => CHAINED_FORMAT::IMPORT_ADDEND,
     268            0 :             0x00000003 => CHAINED_FORMAT::IMPORT_ADDEND64,
     269            0 :             _ => CHAINED_FORMAT::UNKNOWN(value),
     270              :         }
     271         1530 :     }
     272              : }
     273              : 
     274              : impl Chained<'_> {
     275              :     /// Format of the imports
     276         1490 :     pub fn format(&self) -> CHAINED_FORMAT {
     277         1490 :         CHAINED_FORMAT::from_value(self.ptr.format())
     278         1490 :     }
     279              : 
     280              :     /// Format of the pointer
     281         1490 :     pub fn ptr_format(&self) -> u32 {
     282         1490 :         self.ptr.ptr_format()
     283         1490 :     }
     284              : 
     285              :     /// Original offset in the chain of this binding
     286         1490 :     pub fn offset(&self) -> u32 {
     287         1490 :         self.ptr.offset()
     288         1490 :     }
     289              : }
     290              : 
     291              : impl fmt::Debug for Chained<'_> {
     292         1490 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     293         1490 :         let base = self as &dyn AsGeneric;
     294         1490 :         f.debug_struct("Chained")
     295         1490 :             .field("base", &base)
     296         1490 :             .field("format", &self.format())
     297         1490 :             .field("ptr_format", &self.ptr_format())
     298         1490 :             .field("offset", &self.offset())
     299         1490 :             .finish()
     300         1490 :     }
     301              : }
     302              : 
     303              : impl FromFFI<ffi::MachO_ChainedBindingInfo> for Chained<'_> {
     304         1490 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_ChainedBindingInfo>) -> Self {
     305         1490 :         Self {
     306         1490 :             ptr,
     307         1490 :             _owner: PhantomData,
     308         1490 :         }
     309         1490 :     }
     310              : }
     311              : 
     312              : impl AsGeneric for Chained<'_> {
     313         4470 :     fn as_generic(&self) -> &ffi::MachO_BindingInfo {
     314         4470 :         self.ptr.as_ref().unwrap().as_ref()
     315         4470 :     }
     316              : }
     317              : 
     318              : /// This structure represents a binding operation coming from the indirect symbol table
     319              : pub struct Indirect<'a> {
     320              :     ptr: cxx::UniquePtr<ffi::MachO_IndirectBindingInfo>,
     321              :     _owner: PhantomData<&'a ()>,
     322              : }
     323              : 
     324              : impl fmt::Debug for Indirect<'_> {
     325          740 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     326          740 :         let base = self as &dyn AsGeneric;
     327          740 :         f.debug_struct("Indirect")
     328          740 :             .field("base", &base)
     329          740 :             .finish()
     330          740 :     }
     331              : }
     332              : 
     333              : impl FromFFI<ffi::MachO_IndirectBindingInfo> for Indirect<'_> {
     334          740 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_IndirectBindingInfo>) -> Self {
     335          740 :         Self {
     336          740 :             ptr,
     337          740 :             _owner: PhantomData,
     338          740 :         }
     339          740 :     }
     340              : }
     341              : 
     342              : impl AsGeneric for Indirect<'_> {
     343         2220 :     fn as_generic(&self) -> &ffi::MachO_BindingInfo {
     344         2220 :         self.ptr.as_ref().unwrap().as_ref()
     345         2220 :     }
     346              : }
     347              : 
     348              : 
        

Generated by: LCOV version 2.1-1