Skip to main content

macho_core/model/
relocation.rs

1use std::fmt;
2
3/// A decoded relocation entry, either standard or scattered.
4#[derive(Debug, Clone, Copy)]
5pub enum Relocation {
6    /// The Standard variant.
7    Standard(StandardRelocation),
8    /// The Scattered variant.
9    Scattered(ScatteredRelocation),
10}
11
12impl Relocation {
13    /// Performs address.
14    pub fn address(&self) -> u32 {
15        match self {
16            Self::Standard(r) => r.address,
17            Self::Scattered(r) => r.address,
18        }
19    }
20
21    /// Performs reloc_type.
22    pub fn reloc_type(&self) -> u8 {
23        match self {
24            Self::Standard(r) => r.reloc_type,
25            Self::Scattered(r) => r.reloc_type,
26        }
27    }
28
29    /// Performs length.
30    pub fn length(&self) -> u8 {
31        match self {
32            Self::Standard(r) => r.length,
33            Self::Scattered(r) => r.length,
34        }
35    }
36
37    /// Performs pc_relative.
38    pub fn pc_relative(&self) -> bool {
39        match self {
40            Self::Standard(r) => r.pc_relative,
41            Self::Scattered(r) => r.pc_relative,
42        }
43    }
44
45    /// Performs is_scattered.
46    pub fn is_scattered(&self) -> bool {
47        matches!(self, Self::Scattered(_))
48    }
49}
50
51impl fmt::Display for Relocation {
52    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53        match self {
54            Self::Standard(r) => write!(
55                f,
56                "addr={:#x} type={} len={} pcrel={} extern={} sym={}",
57                r.address, r.reloc_type, r.length, r.pc_relative, r.is_extern, r.symbol_num
58            ),
59            Self::Scattered(r) => write!(
60                f,
61                "SCATTERED addr={:#x} type={} len={} pcrel={} value={:#x}",
62                r.address, r.reloc_type, r.length, r.pc_relative, r.value
63            ),
64        }
65    }
66}
67
68#[derive(Debug, Clone, Copy)]
69/// The StandardRelocation type.
70pub struct StandardRelocation {
71    /// The address field.
72    pub address: u32,
73    /// Symbol table index (if extern) or section ordinal (if not extern). 24 bits.
74    pub symbol_num: u32,
75    /// The pc_relative field.
76    pub pc_relative: bool,
77    /// Log2 of the relocation size: 0=byte, 1=word, 2=long, 3=quad.
78    pub length: u8,
79    /// The is_extern field.
80    pub is_extern: bool,
81    /// Architecture-specific relocation type. 4 bits.
82    pub reloc_type: u8,
83}
84
85#[derive(Debug, Clone, Copy)]
86/// The ScatteredRelocation type.
87pub struct ScatteredRelocation {
88    /// Architecture-specific relocation type. 4 bits.
89    pub reloc_type: u8,
90    /// Log2 of the relocation size.
91    pub length: u8,
92    /// The pc_relative field.
93    pub pc_relative: bool,
94    /// Offset within the section. 24 bits.
95    pub address: u32,
96    /// The value the relocation refers to (address of the symbol).
97    pub value: i32,
98}