LCOV - code coverage report
Current view: top level - src/macho - relocation.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 79.7 % 138 110
Test Date: 2024-10-27:00:00:00 Functions: 69.0 % 42 29

            Line data    Source code
       1              : use std::marker::PhantomData;
       2              : 
       3              : use super::commands::segment::Segment;
       4              : use super::section::Section;
       5              : use super::symbol::Symbol;
       6              : use crate::common::{into_optional, FromFFI};
       7              : use crate::declare_iterator;
       8              : use crate::generic;
       9              : use lief_ffi as ffi;
      10              : 
      11       166128 : #[derive(Debug)]
      12              : /// Enum that represents the different to encode/represent a relocation
      13              : /// in a Mach-O file
      14              : pub enum Relocation<'a> {
      15              :     /// Relocation encoded in the rebase bytecode of `LC_DYLD_INFO`
      16              :     Dyld(Dyld<'a>),
      17              : 
      18              :     /// Relocation encoded in chained fixup `LC_DYLD_CHAINED_FIXUPS`
      19              :     Fixup(Fixup<'a>),
      20              : 
      21              :     /// Relocation of Mach-O object files (`.o`) wrapped by the sections
      22              :     Object(Object<'a>),
      23              : 
      24              :     /// Fallback structure
      25              :     Generic(Generic<'a>),
      26              : }
      27              : 
      28              : impl<'a> FromFFI<ffi::MachO_Relocation> for Relocation<'a> {
      29       166128 :     fn from_ffi(ffi_entry: cxx::UniquePtr<ffi::MachO_Relocation>) -> Self {
      30       166128 :         unsafe {
      31       166128 :             let cmd_ref = ffi_entry.as_ref().unwrap();
      32       166128 : 
      33       166128 :             if ffi::MachO_RelocationDyld::classof(cmd_ref) {
      34       129696 :                 let raw = {
      35       129696 :                     type From = cxx::UniquePtr<ffi::MachO_Relocation>;
      36       129696 :                     type To = cxx::UniquePtr<ffi::MachO_RelocationDyld>;
      37       129696 :                     std::mem::transmute::<From, To>(ffi_entry)
      38       129696 :                 };
      39       129696 :                 Relocation::Dyld(Dyld::from_ffi(raw))
      40        36432 :             } else if ffi::MachO_RelocationFixup::classof(cmd_ref) {
      41        20192 :                 let raw = {
      42        20192 :                     type From = cxx::UniquePtr<ffi::MachO_Relocation>;
      43        20192 :                     type To = cxx::UniquePtr<ffi::MachO_RelocationFixup>;
      44        20192 :                     std::mem::transmute::<From, To>(ffi_entry)
      45        20192 :                 };
      46        20192 :                 Relocation::Fixup(Fixup::from_ffi(raw))
      47        16240 :             } else if ffi::MachO_RelocationObject::classof(cmd_ref) {
      48        16240 :                 let raw = {
      49        16240 :                     type From = cxx::UniquePtr<ffi::MachO_Relocation>;
      50        16240 :                     type To = cxx::UniquePtr<ffi::MachO_RelocationObject>;
      51        16240 :                     std::mem::transmute::<From, To>(ffi_entry)
      52        16240 :                 };
      53        16240 :                 Relocation::Object(Object::from_ffi(raw))
      54              :             } else {
      55            0 :                 Relocation::Generic(Generic::from_ffi(ffi_entry))
      56              :             }
      57              :         }
      58       166128 :     }
      59              : }
      60              : 
      61              : /// Trait shared by **all** the relocations defined in [`Relocation`]
      62              : pub trait RelocationBase {
      63              :     #[doc(hidden)]
      64              :     fn get_base(&self) -> &ffi::MachO_Relocation;
      65              : 
      66              :     /// Indicates whether the item containing the address to be
      67              :     /// relocated is part of a CPU instruction that uses PC-relative addressing.
      68              :     ///
      69              :     /// For addresses contained in PC-relative instructions, the CPU adds the address of
      70              :     /// the instruction to the address contained in the instruction.
      71       166128 :     fn is_pc_relative(&self) -> bool {
      72       166128 :         self.get_base().is_pc_relative()
      73       166128 :     }
      74              : 
      75              :     /// Symbol associated with the relocation (if any)
      76       166128 :     fn symbol(&self) -> Option<Symbol> {
      77       166128 :         into_optional(self.get_base().symbol())
      78       166128 :     }
      79              : 
      80              :     /// Section associated with the section (if any)
      81       166128 :     fn section(&self) -> Option<Section> {
      82       166128 :         into_optional(self.get_base().section())
      83       166128 :     }
      84              : 
      85              :     /// Segment command associated with the relocation (if any)
      86       166128 :     fn segment(&self) -> Option<Segment> {
      87       166128 :         into_optional(self.get_base().segment())
      88       166128 :     }
      89              : }
      90              : 
      91              : impl RelocationBase for Relocation<'_> {
      92            0 :     fn get_base(&self) -> &ffi::MachO_Relocation {
      93            0 :         match &self {
      94            0 :             Relocation::Dyld(reloc) => {
      95            0 :                 reloc.get_base()
      96              :             }
      97              : 
      98            0 :             Relocation::Fixup(reloc) => {
      99            0 :                 reloc.get_base()
     100              :             }
     101              : 
     102            0 :             Relocation::Object(reloc) => {
     103            0 :                 reloc.get_base()
     104              :             }
     105              : 
     106            0 :             Relocation::Generic(reloc) => {
     107            0 :                 reloc.get_base()
     108              :             }
     109              :         }
     110            0 :     }
     111              : }
     112              : 
     113              : impl std::fmt::Debug for &dyn RelocationBase {
     114       166128 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     115       166128 :         f.debug_struct("Section")
     116       166128 :             .field("is_pc_relative", &self.is_pc_relative())
     117       166128 :             .field("symbol", &self.symbol())
     118       166128 :             .field("section", &self.section())
     119       166128 :             .field("segment", &self.segment())
     120       166128 :             .finish()
     121       166128 :     }
     122              : }
     123              : 
     124              : pub struct Generic<'a> {
     125              :     ptr: cxx::UniquePtr<ffi::MachO_Relocation>,
     126              :     _owner: PhantomData<&'a ()>,
     127              : }
     128              : 
     129              : impl RelocationBase for Generic<'_> {
     130            0 :     fn get_base(&self) -> &ffi::MachO_Relocation {
     131            0 :         self.ptr.as_ref().unwrap()
     132            0 :     }
     133              : }
     134              : 
     135              : impl generic::Relocation for Generic<'_> {
     136            0 :     fn as_generic(&self) -> &ffi::AbstractRelocation {
     137            0 :         self.ptr.as_ref().unwrap().as_ref()
     138            0 :     }
     139              : }
     140              : 
     141              : impl std::fmt::Debug for Generic<'_> {
     142            0 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     143            0 :         let base = self as &dyn RelocationBase;
     144            0 :         f.debug_struct("Generic").field("base", &base).finish()
     145            0 :     }
     146              : }
     147              : 
     148              : impl FromFFI<ffi::MachO_Relocation> for Generic<'_> {
     149            0 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_Relocation>) -> Self {
     150            0 :         Self {
     151            0 :             ptr,
     152            0 :             _owner: PhantomData,
     153            0 :         }
     154            0 :     }
     155              : }
     156              : 
     157              : /// Structure that represents a bytecode rebase operation (from `LC_DYLD_INFO`)
     158              : pub struct Dyld<'a> {
     159              :     ptr: cxx::UniquePtr<ffi::MachO_RelocationDyld>,
     160              :     _owner: PhantomData<&'a ()>,
     161              : }
     162              : 
     163              : impl FromFFI<ffi::MachO_RelocationDyld> for Dyld<'_> {
     164       129696 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_RelocationDyld>) -> Self {
     165       129696 :         Self {
     166       129696 :             ptr,
     167       129696 :             _owner: PhantomData,
     168       129696 :         }
     169       129696 :     }
     170              : }
     171              : 
     172              : impl RelocationBase for Dyld<'_> {
     173       518784 :     fn get_base(&self) -> &ffi::MachO_Relocation {
     174       518784 :         self.ptr.as_ref().unwrap().as_ref()
     175       518784 :     }
     176              : }
     177              : 
     178              : impl std::fmt::Debug for Dyld<'_> {
     179       129696 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     180       129696 :         let base = self as &dyn RelocationBase;
     181       129696 :         f.debug_struct("Dyld").field("base", &base).finish()
     182       129696 :     }
     183              : }
     184              : 
     185              : /// Structure that represents a fixup (i.e. relocation) from  the recent from `LC_DYLD_CHAINED_FIXUPS`
     186              : /// command
     187              : pub struct Fixup<'a> {
     188              :     ptr: cxx::UniquePtr<ffi::MachO_RelocationFixup>,
     189              :     _owner: PhantomData<&'a ()>,
     190              : }
     191              : 
     192              : impl Fixup<'_> {
     193              :     /// The value that should be set at the address pointed by [`crate::Relocation::address`]
     194              :     /// if the imagebase chosen by the loader is [`crate::generic::Binary::imagebase`].
     195              :     /// Otherwise: [`Fixup::target`] - [`crate::generic::Binary::imagebase`] + new_imagebase.
     196        20192 :     pub fn target(&self) -> u64 {
     197        20192 :         self.ptr.target()
     198        20192 :     }
     199        20192 :     pub fn ptr_format(&self) -> u32 {
     200        20192 :         self.ptr.ptr_format()
     201        20192 :     }
     202              : 
     203              :     /// The address of this relocation is bound to its offset
     204        20192 :     pub fn offset(&self) -> u32 {
     205        20192 :         self.ptr.offset()
     206        20192 :     }
     207              : 
     208              :     /// Return the (unscaled) next offset in the chain
     209        10096 :     pub fn next(&self) -> u32 {
     210        10096 :         self.ptr.next()
     211        10096 :     }
     212              : }
     213              : 
     214              : impl FromFFI<ffi::MachO_RelocationFixup> for Fixup<'_> {
     215        20192 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_RelocationFixup>) -> Self {
     216        20192 :         Self {
     217        20192 :             ptr,
     218        20192 :             _owner: PhantomData,
     219        20192 :         }
     220        20192 :     }
     221              : }
     222              : 
     223              : impl RelocationBase for Fixup<'_> {
     224        80768 :     fn get_base(&self) -> &ffi::MachO_Relocation {
     225        80768 :         self.ptr.as_ref().unwrap().as_ref()
     226        80768 :     }
     227              : }
     228              : 
     229              : impl std::fmt::Debug for Fixup<'_> {
     230        20192 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     231        20192 :         let base = self as &dyn RelocationBase;
     232        20192 :         f.debug_struct("Fixup")
     233        20192 :             .field("base", &base)
     234        20192 :             .field("target", &self.target())
     235        20192 :             .field("ptr_format", &self.ptr_format())
     236        20192 :             .field("offset", &self.offset())
     237        20192 :             .finish()
     238        20192 :     }
     239              : }
     240              : 
     241              : /// This structure represents a relocation in a Mach-O object file (`.o`)
     242              : pub struct Object<'a> {
     243              :     ptr: cxx::UniquePtr<ffi::MachO_RelocationObject>,
     244              :     _owner: PhantomData<&'a ()>,
     245              : }
     246              : 
     247              : impl FromFFI<ffi::MachO_RelocationObject> for Object<'_> {
     248        16240 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_RelocationObject>) -> Self {
     249        16240 :         Self {
     250        16240 :             ptr,
     251        16240 :             _owner: PhantomData,
     252        16240 :         }
     253        16240 :     }
     254              : }
     255              : 
     256              : impl RelocationBase for Object<'_> {
     257        64960 :     fn get_base(&self) -> &ffi::MachO_Relocation {
     258        64960 :         self.ptr.as_ref().unwrap().as_ref()
     259        64960 :     }
     260              : }
     261              : 
     262              : impl std::fmt::Debug for Object<'_> {
     263        16240 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     264        16240 :         let base = self as &dyn RelocationBase;
     265        16240 :         f.debug_struct("Object").field("base", &base).finish()
     266        16240 :     }
     267              : }
     268              : 
     269        81968 : declare_iterator!(
     270        81968 :     Relocations,
     271        81968 :     Relocation<'a>,
     272        81968 :     ffi::MachO_Relocation,
     273        81968 :     ffi::MachO_Binary,
     274        81968 :     ffi::MachO_Binary_it_relocations
     275        81968 : );
        

Generated by: LCOV version 2.1-1