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-10-27: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       222120 : #[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        51560 :     fn library(&self) -> Option<Dylib> {
      33        51560 :         into_optional(self.as_generic().library())
      34        51560 :     }
      35              : 
      36              :     /// Symbol associated with the binding (if any)
      37        51560 :     fn symbol(&self) -> Option<Symbol> {
      38        51560 :         into_optional(self.as_generic().symbol())
      39        51560 :     }
      40              : 
      41              :     /// Segment associated with the binding (if any)
      42        51560 :     fn segment(&self) -> Option<Segment> {
      43        51560 :         into_optional(self.as_generic().segment())
      44        51560 :     }
      45              : 
      46              :     /// Address of the binding
      47       222520 :     fn address(&self) -> u64 {
      48       222520 :         self.as_generic().address()
      49       222520 :     }
      50              : 
      51              :     /// Value added to the segment's virtual address when bound
      52       222520 :     fn addend(&self) -> i64 {
      53       222520 :         self.as_generic().addend()
      54       222520 :     }
      55              : 
      56       222520 :     fn library_ordinal(&self) -> i32 {
      57       222520 :         self.as_generic().library_ordinal()
      58       222520 :     }
      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       222520 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
      83       222520 :         f.debug_struct("AsGeneric")
      84       222520 :             .field("address", &self.address())
      85       222520 :             .field("addend", &self.addend())
      86       222520 :             .field("library_ordinal", &self.library_ordinal())
      87       222520 :             .finish()
      88       222520 :     }
      89              : }
      90              : 
      91              : impl<'a> FromFFI<ffi::MachO_BindingInfo> for BindingInfo<'a> {
      92       119000 :     fn from_ffi(ffi_entry: cxx::UniquePtr<ffi::MachO_BindingInfo>) -> Self {
      93       119000 :         unsafe {
      94       119000 :             let cmd_ref = ffi_entry.as_ref().unwrap();
      95       119000 : 
      96       119000 :             if ffi::MachO_ChainedBindingInfo::classof(cmd_ref) {
      97          792 :                 let raw = {
      98          792 :                     type From = cxx::UniquePtr<ffi::MachO_BindingInfo>;
      99          792 :                     type To = cxx::UniquePtr<ffi::MachO_ChainedBindingInfo>;
     100          792 :                     std::mem::transmute::<From, To>(ffi_entry)
     101          792 :                 };
     102          792 :                 BindingInfo::Chained(Chained::from_ffi(raw))
     103       118208 :             } else if ffi::MachO_DyldBindingInfo::classof(cmd_ref) {
     104       117616 :                 let raw = {
     105       117616 :                     type From = cxx::UniquePtr<ffi::MachO_BindingInfo>;
     106       117616 :                     type To = cxx::UniquePtr<ffi::MachO_DyldBindingInfo>;
     107       117616 :                     std::mem::transmute::<From, To>(ffi_entry)
     108       117616 :                 };
     109       117616 :                 BindingInfo::Dyld(Dyld::from_ffi(raw))
     110          592 :             } else if ffi::MachO_IndirectBindingInfo::classof(cmd_ref) {
     111          592 :                 let raw = {
     112          592 :                     type From = cxx::UniquePtr<ffi::MachO_BindingInfo>;
     113          592 :                     type To = cxx::UniquePtr<ffi::MachO_IndirectBindingInfo>;
     114          592 :                     std::mem::transmute::<From, To>(ffi_entry)
     115          592 :                 };
     116          592 :                 BindingInfo::Indirect(Indirect::from_ffi(raw))
     117              :             } else {
     118            0 :                 BindingInfo::Generic(Generic::from_ffi(ffi_entry))
     119              :             }
     120              :         }
     121       119000 :     }
     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       220736 : #[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       220736 :     pub fn from_value(value: u64) -> Self {
     170       220736 :         match value {
     171         1104 :             0x00000001 => BINDING_CLASS::WEAK,
     172        57168 :             0x00000002 => BINDING_CLASS::LAZY,
     173       162464 :             0x00000003 => BINDING_CLASS::STANDARD,
     174            0 :             0x00000064 => BINDING_CLASS::THREADED,
     175            0 :             _ => BINDING_CLASS::UNKNOWN(value),
     176              :         }
     177       220736 :     }
     178              : }
     179              : 
     180              : #[allow(non_camel_case_types)]
     181       220736 : #[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       220736 :     pub fn from_value(value: u64) -> Self {
     191       220736 :         match value {
     192       220736 :             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       220736 :     }
     198              : }
     199              : 
     200              : impl Dyld<'_> {
     201              :     /// Class of the binding (weak, lazy, ...)
     202       220736 :     pub fn binding_class(&self) -> BINDING_CLASS {
     203       220736 :         BINDING_CLASS::from_value(self.ptr.binding_class())
     204       220736 :     }
     205              : 
     206              :     /// Type of the binding. Most of the times it should be [`BIND_TYPES::POINTER`]
     207       220736 :     pub fn binding_type(&self) -> BIND_TYPES {
     208       220736 :         BIND_TYPES::from_value(self.ptr.binding_type())
     209       220736 :     }
     210              : 
     211       220736 :     pub fn is_non_weak_definition(&self) -> bool {
     212       220736 :         self.ptr.is_non_weak_definition()
     213       220736 :     }
     214              : 
     215       220736 :     pub fn original_offset(&self) -> u64 {
     216       220736 :         self.ptr.original_offset()
     217       220736 :     }
     218              : }
     219              : 
     220              : impl fmt::Debug for Dyld<'_> {
     221       220736 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     222       220736 :         let base = self as &dyn AsGeneric;
     223       220736 :         f.debug_struct("Dyld")
     224       220736 :             .field("base", &base)
     225       220736 :             .field("binding_class", &self.binding_class())
     226       220736 :             .field("binding_type", &self.binding_type())
     227       220736 :             .field("is_non_weak_definition", &self.is_non_weak_definition())
     228       220736 :             .field("original_offset", &self.original_offset())
     229       220736 :             .finish()
     230       220736 :     }
     231              : }
     232              : 
     233              : impl FromFFI<ffi::MachO_DyldBindingInfo> for Dyld<'_> {
     234       169176 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_DyldBindingInfo>) -> Self {
     235       169176 :         Self {
     236       169176 :             ptr,
     237       169176 :             _owner: PhantomData,
     238       169176 :         }
     239       169176 :     }
     240              : }
     241              : 
     242              : impl AsGeneric for Dyld<'_> {
     243       816888 :     fn as_generic(&self) -> &ffi::MachO_BindingInfo {
     244       816888 :         self.ptr.as_ref().unwrap().as_ref()
     245       816888 :     }
     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         1224 : #[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         1224 :     pub fn from_value(value: u32) -> Self {
     265         1224 :         match value {
     266         1224 :             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         1224 :     }
     272              : }
     273              : 
     274              : impl Chained<'_> {
     275              :     /// Format of the imports
     276         1192 :     pub fn format(&self) -> CHAINED_FORMAT {
     277         1192 :         CHAINED_FORMAT::from_value(self.ptr.format())
     278         1192 :     }
     279              : 
     280              :     /// Format of the pointer
     281         1192 :     pub fn ptr_format(&self) -> u32 {
     282         1192 :         self.ptr.ptr_format()
     283         1192 :     }
     284              : 
     285              :     /// Original offset in the chain of this binding
     286         1192 :     pub fn offset(&self) -> u32 {
     287         1192 :         self.ptr.offset()
     288         1192 :     }
     289              : }
     290              : 
     291              : impl fmt::Debug for Chained<'_> {
     292         1192 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     293         1192 :         let base = self as &dyn AsGeneric;
     294         1192 :         f.debug_struct("Chained")
     295         1192 :             .field("base", &base)
     296         1192 :             .field("format", &self.format())
     297         1192 :             .field("ptr_format", &self.ptr_format())
     298         1192 :             .field("offset", &self.offset())
     299         1192 :             .finish()
     300         1192 :     }
     301              : }
     302              : 
     303              : impl FromFFI<ffi::MachO_ChainedBindingInfo> for Chained<'_> {
     304         1192 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_ChainedBindingInfo>) -> Self {
     305         1192 :         Self {
     306         1192 :             ptr,
     307         1192 :             _owner: PhantomData,
     308         1192 :         }
     309         1192 :     }
     310              : }
     311              : 
     312              : impl AsGeneric for Chained<'_> {
     313         3576 :     fn as_generic(&self) -> &ffi::MachO_BindingInfo {
     314         3576 :         self.ptr.as_ref().unwrap().as_ref()
     315         3576 :     }
     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          592 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     326          592 :         let base = self as &dyn AsGeneric;
     327          592 :         f.debug_struct("Indirect")
     328          592 :             .field("base", &base)
     329          592 :             .finish()
     330          592 :     }
     331              : }
     332              : 
     333              : impl FromFFI<ffi::MachO_IndirectBindingInfo> for Indirect<'_> {
     334          592 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_IndirectBindingInfo>) -> Self {
     335          592 :         Self {
     336          592 :             ptr,
     337          592 :             _owner: PhantomData,
     338          592 :         }
     339          592 :     }
     340              : }
     341              : 
     342              : impl AsGeneric for Indirect<'_> {
     343         1776 :     fn as_generic(&self) -> &ffi::MachO_BindingInfo {
     344         1776 :         self.ptr.as_ref().unwrap().as_ref()
     345         1776 :     }
     346              : }
     347              : 
     348              : 
        

Generated by: LCOV version 2.1-1