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-11-30: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       207660 : #[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       207660 :     fn from_ffi(ffi_entry: cxx::UniquePtr<ffi::MachO_Relocation>) -> Self {
      30       207660 :         unsafe {
      31       207660 :             let cmd_ref = ffi_entry.as_ref().unwrap();
      32       207660 : 
      33       207660 :             if ffi::MachO_RelocationDyld::classof(cmd_ref) {
      34       162120 :                 let raw = {
      35       162120 :                     type From = cxx::UniquePtr<ffi::MachO_Relocation>;
      36       162120 :                     type To = cxx::UniquePtr<ffi::MachO_RelocationDyld>;
      37       162120 :                     std::mem::transmute::<From, To>(ffi_entry)
      38       162120 :                 };
      39       162120 :                 Relocation::Dyld(Dyld::from_ffi(raw))
      40        45540 :             } else if ffi::MachO_RelocationFixup::classof(cmd_ref) {
      41        25240 :                 let raw = {
      42        25240 :                     type From = cxx::UniquePtr<ffi::MachO_Relocation>;
      43        25240 :                     type To = cxx::UniquePtr<ffi::MachO_RelocationFixup>;
      44        25240 :                     std::mem::transmute::<From, To>(ffi_entry)
      45        25240 :                 };
      46        25240 :                 Relocation::Fixup(Fixup::from_ffi(raw))
      47        20300 :             } else if ffi::MachO_RelocationObject::classof(cmd_ref) {
      48        20300 :                 let raw = {
      49        20300 :                     type From = cxx::UniquePtr<ffi::MachO_Relocation>;
      50        20300 :                     type To = cxx::UniquePtr<ffi::MachO_RelocationObject>;
      51        20300 :                     std::mem::transmute::<From, To>(ffi_entry)
      52        20300 :                 };
      53        20300 :                 Relocation::Object(Object::from_ffi(raw))
      54              :             } else {
      55            0 :                 Relocation::Generic(Generic::from_ffi(ffi_entry))
      56              :             }
      57              :         }
      58       207660 :     }
      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       207660 :     fn is_pc_relative(&self) -> bool {
      72       207660 :         self.get_base().is_pc_relative()
      73       207660 :     }
      74              : 
      75              :     /// Symbol associated with the relocation (if any)
      76       207660 :     fn symbol(&self) -> Option<Symbol> {
      77       207660 :         into_optional(self.get_base().symbol())
      78       207660 :     }
      79              : 
      80              :     /// Section associated with the section (if any)
      81       207660 :     fn section(&self) -> Option<Section> {
      82       207660 :         into_optional(self.get_base().section())
      83       207660 :     }
      84              : 
      85              :     /// Segment command associated with the relocation (if any)
      86       207660 :     fn segment(&self) -> Option<Segment> {
      87       207660 :         into_optional(self.get_base().segment())
      88       207660 :     }
      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       207660 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     115       207660 :         f.debug_struct("Section")
     116       207660 :             .field("is_pc_relative", &self.is_pc_relative())
     117       207660 :             .field("symbol", &self.symbol())
     118       207660 :             .field("section", &self.section())
     119       207660 :             .field("segment", &self.segment())
     120       207660 :             .finish()
     121       207660 :     }
     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       162120 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_RelocationDyld>) -> Self {
     165       162120 :         Self {
     166       162120 :             ptr,
     167       162120 :             _owner: PhantomData,
     168       162120 :         }
     169       162120 :     }
     170              : }
     171              : 
     172              : impl RelocationBase for Dyld<'_> {
     173       648480 :     fn get_base(&self) -> &ffi::MachO_Relocation {
     174       648480 :         self.ptr.as_ref().unwrap().as_ref()
     175       648480 :     }
     176              : }
     177              : 
     178              : impl std::fmt::Debug for Dyld<'_> {
     179       162120 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     180       162120 :         let base = self as &dyn RelocationBase;
     181       162120 :         f.debug_struct("Dyld").field("base", &base).finish()
     182       162120 :     }
     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        25240 :     pub fn target(&self) -> u64 {
     197        25240 :         self.ptr.target()
     198        25240 :     }
     199        25240 :     pub fn ptr_format(&self) -> u32 {
     200        25240 :         self.ptr.ptr_format()
     201        25240 :     }
     202              : 
     203              :     /// The address of this relocation is bound to its offset
     204        25240 :     pub fn offset(&self) -> u32 {
     205        25240 :         self.ptr.offset()
     206        25240 :     }
     207              : 
     208              :     /// Return the (unscaled) next offset in the chain
     209        12620 :     pub fn next(&self) -> u32 {
     210        12620 :         self.ptr.next()
     211        12620 :     }
     212              : }
     213              : 
     214              : impl FromFFI<ffi::MachO_RelocationFixup> for Fixup<'_> {
     215        25240 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_RelocationFixup>) -> Self {
     216        25240 :         Self {
     217        25240 :             ptr,
     218        25240 :             _owner: PhantomData,
     219        25240 :         }
     220        25240 :     }
     221              : }
     222              : 
     223              : impl RelocationBase for Fixup<'_> {
     224       100960 :     fn get_base(&self) -> &ffi::MachO_Relocation {
     225       100960 :         self.ptr.as_ref().unwrap().as_ref()
     226       100960 :     }
     227              : }
     228              : 
     229              : impl std::fmt::Debug for Fixup<'_> {
     230        25240 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     231        25240 :         let base = self as &dyn RelocationBase;
     232        25240 :         f.debug_struct("Fixup")
     233        25240 :             .field("base", &base)
     234        25240 :             .field("target", &self.target())
     235        25240 :             .field("ptr_format", &self.ptr_format())
     236        25240 :             .field("offset", &self.offset())
     237        25240 :             .finish()
     238        25240 :     }
     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        20300 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_RelocationObject>) -> Self {
     249        20300 :         Self {
     250        20300 :             ptr,
     251        20300 :             _owner: PhantomData,
     252        20300 :         }
     253        20300 :     }
     254              : }
     255              : 
     256              : impl RelocationBase for Object<'_> {
     257        81200 :     fn get_base(&self) -> &ffi::MachO_Relocation {
     258        81200 :         self.ptr.as_ref().unwrap().as_ref()
     259        81200 :     }
     260              : }
     261              : 
     262              : impl std::fmt::Debug for Object<'_> {
     263        20300 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     264        20300 :         let base = self as &dyn RelocationBase;
     265        20300 :         f.debug_struct("Object").field("base", &base).finish()
     266        20300 :     }
     267              : }
     268              : 
     269       102460 : declare_iterator!(
     270       102460 :     Relocations,
     271       102460 :     Relocation<'a>,
     272       102460 :     ffi::MachO_Relocation,
     273       102460 :     ffi::MachO_Binary,
     274       102460 :     ffi::MachO_Binary_it_relocations
     275       102460 : );
        

Generated by: LCOV version 2.1-1