use super::{Section, Symbol};
use crate::common::{FromFFI, into_optional};
use crate::generic;
use std::marker::PhantomData;
use lief_ffi as ffi;
pub struct Relocation<'a> {
ptr: cxx::UniquePtr<ffi::COFF_Relocation>,
_owner: PhantomData<&'a ffi::COFF_Binary>,
}
impl FromFFI<ffi::COFF_Relocation> for Relocation<'_> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::COFF_Relocation>) -> Self {
Relocation {
ptr,
_owner: PhantomData,
}
}
}
impl generic::Relocation for Relocation<'_> {
fn as_generic(&self) -> &ffi::AbstractRelocation {
self.ptr.as_ref().unwrap().as_ref()
}
}
impl Relocation<'_> {
pub fn symbol_idx(&self) -> u32 {
self.ptr.symbol_idx()
}
pub fn symbol(&self) -> Option<Symbol<'_>> {
into_optional(self.ptr.symbol())
}
pub fn get_type(&self) -> Type {
Type::from(self.ptr.get_type())
}
pub fn section(&self) -> Option<Section<'_>> {
into_optional(self.ptr.section())
}
}
impl std::fmt::Debug for Relocation<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn generic::Relocation;
f.debug_struct("Relocation")
.field("base", &base)
.field("symbol_idx", &self.symbol_idx())
.field("type", &self.get_type())
.finish()
}
}
impl std::fmt::Display for Relocation<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.ptr.to_string())
}
}
#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Type {
I386_ABSOLUTE,
I386_DIR16,
I386_REL16,
I386_DIR32,
I386_DIR32NB,
I386_SEG12,
I386_SECTION,
I386_SECREL,
I386_TOKEN,
I386_SECREL7,
I386_REL32,
AMD64_ABSOLUTE,
AMD64_ADDR64,
AMD64_ADDR32,
AMD64_ADDR32NB,
AMD64_REL32,
AMD64_REL32_1,
AMD64_REL32_2,
AMD64_REL32_3,
AMD64_REL32_4,
AMD64_REL32_5,
AMD64_SECTION,
AMD64_SECREL,
AMD64_SECREL7,
AMD64_TOKEN,
AMD64_SREL32,
AMD64_PAIR,
AMD64_SSPAN32,
ARM_ABSOLUTE,
ARM_ADDR32,
ARM_ADDR32NB,
ARM_BRANCH24,
ARM_BRANCH11,
ARM_TOKEN,
ARM_BLX24,
ARM_BLX11,
ARM_REL32,
ARM_SECTION,
ARM_SECREL,
ARM_MOV32A,
ARM_MOV32T,
ARM_BRANCH20T,
ARM_BRANCH24T,
ARM_BLX23T,
ARM_PAIR,
ARM64_ABSOLUTE,
ARM64_ADDR32,
ARM64_ADDR32NB,
ARM64_BRANCH26,
ARM64_PAGEBASE_REL21,
ARM64_REL21,
ARM64_PAGEOFFSET_12A,
ARM64_PAGEOFFSET_12L,
ARM64_SECREL,
ARM64_SECREL_LOW12A,
ARM64_SECREL_HIGH12A,
ARM64_SECREL_LOW12L,
ARM64_TOKEN,
ARM64_SECTION,
ARM64_ADDR64,
ARM64_BRANCH19,
ARM64_BRANCH14,
ARM64_REL32,
MIPS_ABSOLUTE,
MIPS_REFHALF,
MIPS_REFWORD,
MIPS_JMPADDR,
MIPS_REFHI,
MIPS_REFLO,
MIPS_GPREL,
MIPS_LITERAL,
MIPS_SECTION,
MIPS_SECREL,
MIPS_SECRELLO,
MIPS_SECRELHI,
MIPS_JMPADDR16,
MIPS_REFWORDNB,
MIPS_PAIR,
UNKNOWN(u32),
}
impl From<u32> for Type {
fn from(value: u32) -> Self {
match value {
0x00020000 => Type::I386_ABSOLUTE,
0x00020001 => Type::I386_DIR16,
0x00020002 => Type::I386_REL16,
0x00020006 => Type::I386_DIR32,
0x00020007 => Type::I386_DIR32NB,
0x00020009 => Type::I386_SEG12,
0x0002000a => Type::I386_SECTION,
0x0002000b => Type::I386_SECREL,
0x0002000c => Type::I386_TOKEN,
0x0002000d => Type::I386_SECREL7,
0x00020014 => Type::I386_REL32,
0x00040000 => Type::AMD64_ABSOLUTE,
0x00040001 => Type::AMD64_ADDR64,
0x00040002 => Type::AMD64_ADDR32,
0x00040003 => Type::AMD64_ADDR32NB,
0x00040004 => Type::AMD64_REL32,
0x00040005 => Type::AMD64_REL32_1,
0x00040006 => Type::AMD64_REL32_2,
0x00040007 => Type::AMD64_REL32_3,
0x00040008 => Type::AMD64_REL32_4,
0x00040009 => Type::AMD64_REL32_5,
0x0004000a => Type::AMD64_SECTION,
0x0004000b => Type::AMD64_SECREL,
0x0004000c => Type::AMD64_SECREL7,
0x0004000d => Type::AMD64_TOKEN,
0x0004000e => Type::AMD64_SREL32,
0x0004000f => Type::AMD64_PAIR,
0x00040010 => Type::AMD64_SSPAN32,
0x00080000 => Type::ARM_ABSOLUTE,
0x00080001 => Type::ARM_ADDR32,
0x00080002 => Type::ARM_ADDR32NB,
0x00080003 => Type::ARM_BRANCH24,
0x00080004 => Type::ARM_BRANCH11,
0x00080005 => Type::ARM_TOKEN,
0x00080008 => Type::ARM_BLX24,
0x00080009 => Type::ARM_BLX11,
0x0008000a => Type::ARM_REL32,
0x0008000e => Type::ARM_SECTION,
0x0008000f => Type::ARM_SECREL,
0x00080010 => Type::ARM_MOV32A,
0x00080011 => Type::ARM_MOV32T,
0x00080012 => Type::ARM_BRANCH20T,
0x00080014 => Type::ARM_BRANCH24T,
0x00080015 => Type::ARM_BLX23T,
0x00080016 => Type::ARM_PAIR,
0x00100000 => Type::ARM64_ABSOLUTE,
0x00100001 => Type::ARM64_ADDR32,
0x00100002 => Type::ARM64_ADDR32NB,
0x00100003 => Type::ARM64_BRANCH26,
0x00100004 => Type::ARM64_PAGEBASE_REL21,
0x00100005 => Type::ARM64_REL21,
0x00100006 => Type::ARM64_PAGEOFFSET_12A,
0x00100007 => Type::ARM64_PAGEOFFSET_12L,
0x00100008 => Type::ARM64_SECREL,
0x00100009 => Type::ARM64_SECREL_LOW12A,
0x0010000a => Type::ARM64_SECREL_HIGH12A,
0x0010000b => Type::ARM64_SECREL_LOW12L,
0x0010000c => Type::ARM64_TOKEN,
0x0010000d => Type::ARM64_SECTION,
0x0010000e => Type::ARM64_ADDR64,
0x0010000f => Type::ARM64_BRANCH19,
0x00100010 => Type::ARM64_BRANCH14,
0x00100011 => Type::ARM64_REL32,
0x00200000 => Type::MIPS_ABSOLUTE,
0x00200001 => Type::MIPS_REFHALF,
0x00200002 => Type::MIPS_REFWORD,
0x00200003 => Type::MIPS_JMPADDR,
0x00200004 => Type::MIPS_REFHI,
0x00200005 => Type::MIPS_REFLO,
0x00200006 => Type::MIPS_GPREL,
0x00200007 => Type::MIPS_LITERAL,
0x0020000a => Type::MIPS_SECTION,
0x0020000b => Type::MIPS_SECREL,
0x0020000c => Type::MIPS_SECRELLO,
0x0020000d => Type::MIPS_SECRELHI,
0x00200010 => Type::MIPS_JMPADDR16,
0x00200022 => Type::MIPS_REFWORDNB,
0x00200025 => Type::MIPS_PAIR,
_ => Type::UNKNOWN(value),
}
}
}
impl From<Type> for u32 {
fn from(value: Type) -> u32 {
match value {
Type::I386_ABSOLUTE => 0x00020000,
Type::I386_DIR16 => 0x00020001,
Type::I386_REL16 => 0x00020002,
Type::I386_DIR32 => 0x00020006,
Type::I386_DIR32NB => 0x00020007,
Type::I386_SEG12 => 0x00020009,
Type::I386_SECTION => 0x0002000a,
Type::I386_SECREL => 0x0002000b,
Type::I386_TOKEN => 0x0002000c,
Type::I386_SECREL7 => 0x0002000d,
Type::I386_REL32 => 0x00020014,
Type::AMD64_ABSOLUTE => 0x00040000,
Type::AMD64_ADDR64 => 0x00040001,
Type::AMD64_ADDR32 => 0x00040002,
Type::AMD64_ADDR32NB => 0x00040003,
Type::AMD64_REL32 => 0x00040004,
Type::AMD64_REL32_1 => 0x00040005,
Type::AMD64_REL32_2 => 0x00040006,
Type::AMD64_REL32_3 => 0x00040007,
Type::AMD64_REL32_4 => 0x00040008,
Type::AMD64_REL32_5 => 0x00040009,
Type::AMD64_SECTION => 0x0004000a,
Type::AMD64_SECREL => 0x0004000b,
Type::AMD64_SECREL7 => 0x0004000c,
Type::AMD64_TOKEN => 0x0004000d,
Type::AMD64_SREL32 => 0x0004000e,
Type::AMD64_PAIR => 0x0004000f,
Type::AMD64_SSPAN32 => 0x00040010,
Type::ARM_ABSOLUTE => 0x00080000,
Type::ARM_ADDR32 => 0x00080001,
Type::ARM_ADDR32NB => 0x00080002,
Type::ARM_BRANCH24 => 0x00080003,
Type::ARM_BRANCH11 => 0x00080004,
Type::ARM_TOKEN => 0x00080005,
Type::ARM_BLX24 => 0x00080008,
Type::ARM_BLX11 => 0x00080009,
Type::ARM_REL32 => 0x0008000a,
Type::ARM_SECTION => 0x0008000e,
Type::ARM_SECREL => 0x0008000f,
Type::ARM_MOV32A => 0x00080010,
Type::ARM_MOV32T => 0x00080011,
Type::ARM_BRANCH20T => 0x00080012,
Type::ARM_BRANCH24T => 0x00080014,
Type::ARM_BLX23T => 0x00080015,
Type::ARM_PAIR => 0x00080016,
Type::ARM64_ABSOLUTE => 0x00100000,
Type::ARM64_ADDR32 => 0x00100001,
Type::ARM64_ADDR32NB => 0x00100002,
Type::ARM64_BRANCH26 => 0x00100003,
Type::ARM64_PAGEBASE_REL21 => 0x00100004,
Type::ARM64_REL21 => 0x00100005,
Type::ARM64_PAGEOFFSET_12A => 0x00100006,
Type::ARM64_PAGEOFFSET_12L => 0x00100007,
Type::ARM64_SECREL => 0x00100008,
Type::ARM64_SECREL_LOW12A => 0x00100009,
Type::ARM64_SECREL_HIGH12A => 0x0010000a,
Type::ARM64_SECREL_LOW12L => 0x0010000b,
Type::ARM64_TOKEN => 0x0010000c,
Type::ARM64_SECTION => 0x0010000d,
Type::ARM64_ADDR64 => 0x0010000e,
Type::ARM64_BRANCH19 => 0x0010000f,
Type::ARM64_BRANCH14 => 0x00100010,
Type::ARM64_REL32 => 0x00100011,
Type::MIPS_ABSOLUTE => 0x00200000,
Type::MIPS_REFHALF => 0x00200001,
Type::MIPS_REFWORD => 0x00200002,
Type::MIPS_JMPADDR => 0x00200003,
Type::MIPS_REFHI => 0x00200004,
Type::MIPS_REFLO => 0x00200005,
Type::MIPS_GPREL => 0x00200006,
Type::MIPS_LITERAL => 0x00200007,
Type::MIPS_SECTION => 0x0020000a,
Type::MIPS_SECREL => 0x0020000b,
Type::MIPS_SECRELLO => 0x0020000c,
Type::MIPS_SECRELHI => 0x0020000d,
Type::MIPS_JMPADDR16 => 0x00200010,
Type::MIPS_REFWORDNB => 0x00200022,
Type::MIPS_PAIR => 0x00200025,
Type::UNKNOWN(value) => value,
}
}
}