LCOV - code coverage report
Current view: top level - src/pe - relocation.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 80.2 % 86 69
Test Date: 2024-10-27:00:00:00 Functions: 93.8 % 16 15

            Line data    Source code
       1              : //! This module includes the different structures related to the relocation process in a PE binary
       2              : 
       3              : use std::marker::PhantomData;
       4              : 
       5              : use lief_ffi as ffi;
       6              : 
       7              : use crate::common::FromFFI;
       8              : use crate::{declare_iterator, generic};
       9              : 
      10              : /// Class which represents the *Base Relocation Block*
      11              : /// We usually find this structure in the `.reloc` section
      12              : pub struct Relocation<'a> {
      13              :     ptr: cxx::UniquePtr<ffi::PE_Relocation>,
      14              :     _owner: PhantomData<&'a ffi::PE_Binary>,
      15              : }
      16              : 
      17              : impl Relocation<'_> {
      18              :     /// The RVA for which the offset of the relocation entries is added
      19        13616 :     pub fn virtual_address(&self) -> u32 {
      20        13616 :         self.ptr.virtual_address()
      21        13616 :     }
      22              : 
      23              :     /// The total number of bytes in the base relocation block.
      24              :     /// `block_size = sizeof(BaseRelocationBlock) + nb_of_relocs * sizeof(uint16_t = RelocationEntry)`
      25        13616 :     pub fn block_size(&self) -> u32 {
      26        13616 :         self.ptr.block_size()
      27        13616 :     }
      28              :     /// Iterator over the Relocation [`Entry`]
      29        13616 :     pub fn entries(&self) -> RelocationEntries {
      30        13616 :         RelocationEntries::new(self.ptr.entries())
      31        13616 :     }
      32              : }
      33              : 
      34              : impl std::fmt::Debug for Relocation<'_> {
      35        13616 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
      36        13616 :         f.debug_struct("Relocation")
      37        13616 :             .field("virtual_address", &self.virtual_address())
      38        13616 :             .field("block_size", &self.block_size())
      39        13616 :             .finish()
      40        13616 :     }
      41              : }
      42              : 
      43              : impl<'a> FromFFI<ffi::PE_Relocation> for Relocation<'a> {
      44        13616 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_Relocation>) -> Self {
      45        13616 :         Relocation {
      46        13616 :             ptr,
      47        13616 :             _owner: PhantomData,
      48        13616 :         }
      49        13616 :     }
      50              : }
      51              : 
      52              : #[allow(non_camel_case_types)]
      53      1124224 : #[derive(Debug, Copy, Clone)]
      54              : pub enum BaseType {
      55              :     ABS,
      56              :     HIGH,
      57              :     LOW,
      58              :     HIGHLOW,
      59              :     HIGHADJ,
      60              :     MIPS_JMPADDR,
      61              :     ARM_MOV32A,
      62              :     ARM_MOV32,
      63              :     RISCV_HI20,
      64              :     SECTION,
      65              :     REL,
      66              :     ARM_MOV32T,
      67              :     THUMB_MOV32,
      68              :     RISCV_LOW12I,
      69              :     RISCV_LOW12S,
      70              :     IA64_IMM64,
      71              :     MIPS_JMPADDR16,
      72              :     DIR64,
      73              :     HIGH3ADJ,
      74              :     UNKNOWN(u32),
      75              : }
      76              : 
      77              : impl BaseType {
      78      1124224 :     pub fn from_value(value: u32) -> Self {
      79      1124224 :         match value {
      80         6840 :             0x00000000 => BaseType::ABS,
      81            0 :             0x00000001 => BaseType::HIGH,
      82            0 :             0x00000002 => BaseType::LOW,
      83       979392 :             0x00000003 => BaseType::HIGHLOW,
      84            0 :             0x00000004 => BaseType::HIGHADJ,
      85            0 :             0x00000005 => BaseType::MIPS_JMPADDR,
      86            0 :             0x00000106 => BaseType::ARM_MOV32A,
      87            0 :             0x00000107 => BaseType::ARM_MOV32,
      88            0 :             0x00000108 => BaseType::RISCV_HI20,
      89            0 :             0x00000006 => BaseType::SECTION,
      90            0 :             0x00000007 => BaseType::REL,
      91            0 :             0x00000208 => BaseType::ARM_MOV32T,
      92            0 :             0x00000209 => BaseType::THUMB_MOV32,
      93            0 :             0x0000020a => BaseType::RISCV_LOW12I,
      94            0 :             0x00000008 => BaseType::RISCV_LOW12S,
      95            0 :             0x00000009 => BaseType::IA64_IMM64,
      96            0 :             0x00000309 => BaseType::MIPS_JMPADDR16,
      97       137992 :             0x0000000a => BaseType::DIR64,
      98            0 :             0x0000000b => BaseType::HIGH3ADJ,
      99            0 :             _ => BaseType::UNKNOWN(value),
     100              :         }
     101      1124224 :     }
     102              : }
     103              : 
     104              : /// Class which represents an entry in the relocation table
     105              : ///
     106              : /// It implements the [`generic::Relocation`] trait which provides additional functions
     107              : pub struct Entry<'a> {
     108              :     ptr: cxx::UniquePtr<ffi::PE_RelocationEntry>,
     109              :     _owner: PhantomData<&'a ffi::PE_Relocation>,
     110              : }
     111              : 
     112              : impl generic::Relocation for Entry<'_> {
     113      2248448 :     fn as_generic(&self) -> &ffi::AbstractRelocation {
     114      2248448 :         self.ptr.as_ref().unwrap().as_ref()
     115      2248448 :     }
     116              : }
     117              : 
     118              : impl Entry<'_> {
     119              :     /// Offset relative to [`Relocation::virtual_address`] where the relocation occurs.
     120      1124224 :     pub fn position(&self) -> u64 {
     121      1124224 :         self.ptr.position()
     122      1124224 :     }
     123              : 
     124              :     /// Type of the relocation
     125      1124224 :     pub fn get_type(&self) -> BaseType {
     126      1124224 :         BaseType::from_value(self.ptr.get_type())
     127      1124224 :     }
     128              : 
     129              :     /// Raw data of the relocation:
     130              :     /// - The **high** 4 bits store the relocation type
     131              :     /// - The **low** 12 bits store the relocation offset
     132      1124224 :     pub fn data(&self) -> u16 {
     133      1124224 :         self.ptr.data()
     134      1124224 :     }
     135              : }
     136              : 
     137              : impl std::fmt::Debug for Entry<'_> {
     138      1124224 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     139      1124224 :         let base = self as &dyn generic::Relocation;
     140      1124224 :         f.debug_struct("RelocationEntry")
     141      1124224 :             .field("base", &base)
     142      1124224 :             .field("type", &self.get_type())
     143      1124224 :             .field("data", &self.data())
     144      1124224 :             .field("position", &self.position())
     145      1124224 :             .finish()
     146      1124224 :     }
     147              : }
     148              : 
     149              : impl<'a> FromFFI<ffi::PE_RelocationEntry> for Entry<'a> {
     150      1124224 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_RelocationEntry>) -> Self {
     151      1124224 :         Entry {
     152      1124224 :             ptr,
     153      1124224 :             _owner: PhantomData,
     154      1124224 :         }
     155      1124224 :     }
     156              : }
     157              : 
     158      1124224 : declare_iterator!(
     159      1124224 :     RelocationEntries,
     160      1124224 :     Entry<'a>,
     161      1124224 :     ffi::PE_RelocationEntry,
     162      1124224 :     ffi::PE_Relocation,
     163      1124224 :     ffi::PE_Relocation_it_entries
     164      1124224 : );
     165        13616 : declare_iterator!(
     166        13616 :     Relocations,
     167        13616 :     Relocation<'a>,
     168        13616 :     ffi::PE_Relocation,
     169        13616 :     ffi::PE_Binary,
     170        13616 :     ffi::PE_Binary_it_relocations
     171        13616 : );
        

Generated by: LCOV version 2.1-1