Skip to main content

gen_elf/
common.rs

1/// Type of an ELF symbol.
2#[derive(Clone, Copy, Debug, PartialEq)]
3pub enum SymbolType {
4    /// Function symbol.
5    Func,
6    /// Data object symbol.
7    Object,
8    /// Thread-local storage symbol.
9    Tls,
10}
11
12/// Visibility and binding scope of an ELF symbol.
13#[derive(Clone, Copy, Debug, PartialEq)]
14pub enum SymbolScope {
15    /// Global symbol, visible to other objects.
16    Global,
17    /// Local symbol, visible only within the defining object.
18    Local,
19    /// Weak symbol, can be overridden by a global symbol.
20    Weak,
21}
22
23/// Purpose or category of an ELF section.
24#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
25pub enum SectionKind {
26    Null,
27    DynStr,
28    DynSym,
29    RelaDyn,
30    RelaPlt,
31    RelDyn,
32    RelPlt,
33    Dynamic,
34    Hash,
35    ShStrTab,
36    Plt,
37    Text,
38    Data,
39    Got,
40    GotPlt,
41    Tls,
42}
43
44/// Content of an ELF section.
45#[derive(Debug, Clone)]
46pub struct Content {
47    /// Raw bytes of the section.
48    pub data: Vec<u8>,
49    /// The kind of section this content belongs to.
50    pub kind: SectionKind,
51}
52
53/// Description of an ELF symbol to be generated.
54#[derive(Clone, Debug)]
55pub struct SymbolDesc {
56    /// Name of the symbol.
57    pub name: String,
58    /// Type of the symbol (Func, Object, etc.).
59    pub sym_type: SymbolType,
60    /// Scope of the symbol (Global, Local, etc.).
61    pub scope: SymbolScope,
62    /// Optional content associated with the symbol.
63    pub content: Option<Content>,
64    /// Optional size of the symbol. If None, it may be calculated from content.
65    pub size: Option<u64>,
66}
67
68impl SymbolDesc {
69    /// Create a global function symbol with associated code.
70    pub fn global_func(name: impl Into<String>, code: &[u8]) -> Self {
71        Self {
72            name: name.into(),
73            sym_type: SymbolType::Func,
74            scope: SymbolScope::Global,
75            content: Some(Content {
76                data: code.to_vec(),
77                kind: SectionKind::Text,
78            }),
79            size: Some(code.len() as u64),
80        }
81    }
82
83    /// Create a global data object symbol.
84    pub fn global_object(name: impl Into<String>, data: &[u8]) -> Self {
85        Self {
86            name: name.into(),
87            sym_type: SymbolType::Object,
88            scope: SymbolScope::Global,
89            content: Some(Content {
90                data: data.to_vec(),
91                kind: SectionKind::Data,
92            }),
93            size: Some(data.len() as u64),
94        }
95    }
96
97    /// Create an undefined function symbol.
98    pub fn undefined_func(name: impl Into<String>) -> Self {
99        Self {
100            name: name.into(),
101            sym_type: SymbolType::Func,
102            scope: SymbolScope::Global,
103            content: None,
104            size: None,
105        }
106    }
107
108    /// Create an undefined data object symbol.
109    pub fn undefined_object(name: impl Into<String>) -> Self {
110        Self {
111            name: name.into(),
112            sym_type: SymbolType::Object,
113            scope: SymbolScope::Global,
114            content: None,
115            size: None,
116        }
117    }
118
119    /// Create a global TLS symbol with associated data.
120    pub fn global_tls(name: impl Into<String>, data: &[u8]) -> Self {
121        Self {
122            name: name.into(),
123            sym_type: SymbolType::Tls,
124            scope: SymbolScope::Global,
125            content: Some(Content {
126                data: data.to_vec(),
127                kind: SectionKind::Tls,
128            }),
129            size: Some(data.len() as u64),
130        }
131    }
132
133    /// Create an undefined TLS symbol.
134    pub fn undefined_tls(name: impl Into<String>) -> Self {
135        Self {
136            name: name.into(),
137            sym_type: SymbolType::Tls,
138            scope: SymbolScope::Global,
139            content: None,
140            size: None,
141        }
142    }
143
144    /// Create a function symbol located in the PLT section.
145    pub fn plt_func(name: impl Into<String>, code: Vec<u8>) -> Self {
146        let size = code.len() as u64;
147        Self {
148            name: name.into(),
149            sym_type: SymbolType::Func,
150            scope: SymbolScope::Global,
151            content: Some(Content {
152                data: code,
153                kind: SectionKind::Plt,
154            }),
155            size: Some(size),
156        }
157    }
158
159    /// Set a custom size for the symbol.
160    pub fn with_size(mut self, size: u64) -> Self {
161        self.size = Some(size);
162        self
163    }
164
165    /// Set a custom scope for the symbol.
166    pub fn with_scope(mut self, scope: SymbolScope) -> Self {
167        self.scope = scope;
168        self
169    }
170}
171
172/// Wrapper for architecture-specific relocation types.
173#[derive(Clone, Copy, PartialEq, Eq, Debug)]
174pub struct RelocType(pub u32);
175
176impl RelocType {
177    /// Returns the relocation type as a u32.
178    pub fn as_u32(&self) -> u32 {
179        self.0
180    }
181
182    /// Returns the relocation type as a u64.
183    pub fn as_u64(&self) -> u64 {
184        self.0 as u64
185    }
186}
187
188/// Represents a relocation entry to be generated.
189#[derive(Clone, Debug)]
190pub struct RelocEntry {
191    /// Symbol name that this relocation references.
192    pub symbol_name: String,
193    /// Architecture-specific relocation type.
194    pub r_type: RelocType,
195    /// Addend for the relocation.
196    pub addend: i64,
197}
198
199impl RelocEntry {
200    /// Create a new relocation entry referencing a symbol.
201    pub fn with_name(symbol_name: impl Into<String>, r_type: u32) -> Self {
202        Self {
203            symbol_name: symbol_name.into(),
204            r_type: RelocType(r_type),
205            addend: 0,
206        }
207    }
208
209    /// Create a new relocation entry without a symbol reference (e.g., RELATIVE).
210    pub fn new(r_type: u32) -> Self {
211        Self {
212            symbol_name: String::new(),
213            r_type: RelocType(r_type),
214            addend: 0,
215        }
216    }
217
218    /// Set the addend for the relocation.
219    pub fn with_addend(mut self, addend: i64) -> Self {
220        self.addend = addend;
221        self
222    }
223
224    /// Create a JUMP_SLOT relocation for the given architecture.
225    pub fn jump_slot(symbol_name: impl Into<String>, arch: crate::Arch) -> Self {
226        Self::with_name(symbol_name, arch.jump_slot_reloc())
227    }
228
229    /// Create a GLOB_DAT relocation for the given architecture.
230    pub fn glob_dat(symbol_name: impl Into<String>, arch: crate::Arch) -> Self {
231        Self::with_name(symbol_name, arch.glob_dat_reloc())
232    }
233
234    /// Create a RELATIVE relocation for the given architecture.
235    pub fn relative(arch: crate::Arch) -> Self {
236        Self::new(arch.relative_reloc())
237    }
238
239    /// Create an IRELATIVE relocation for the given architecture.
240    pub fn irelative(arch: crate::Arch) -> Self {
241        Self::new(arch.irelative_reloc())
242    }
243
244    /// Create a COPY relocation for the given architecture.
245    pub fn copy(symbol_name: impl Into<String>, arch: crate::Arch) -> Self {
246        Self::with_name(symbol_name, arch.copy_reloc())
247    }
248
249    /// Create a DTPOFF relocation for the given architecture.
250    pub fn dtpoff(symbol_name: impl Into<String>, arch: crate::Arch) -> Self {
251        Self::with_name(symbol_name, arch.dtpoff_reloc())
252    }
253
254    /// Create a DTPMOD relocation for the given architecture.
255    pub fn dtpmod(symbol_name: impl Into<String>, arch: crate::Arch) -> Self {
256        Self::with_name(symbol_name, arch.dtpmod_reloc())
257    }
258
259    /// Create an absolute relocation for the given architecture.
260    pub fn abs(symbol_name: impl Into<String>, arch: crate::Arch) -> Self {
261        Self::with_name(symbol_name, arch.abs_reloc())
262    }
263}