inkwell/
object_file.rs

1#![allow(deprecated)]
2
3use llvm_sys::object::{
4    LLVMDisposeObjectFile, LLVMDisposeRelocationIterator, LLVMDisposeSectionIterator, LLVMDisposeSymbolIterator,
5    LLVMGetRelocationOffset, LLVMGetRelocationSymbol, LLVMGetRelocationType, LLVMGetRelocationTypeName,
6    LLVMGetRelocationValueString, LLVMGetRelocations, LLVMGetSectionAddress, LLVMGetSectionContents,
7    LLVMGetSectionName, LLVMGetSectionSize, LLVMGetSections, LLVMGetSymbolAddress, LLVMGetSymbolName,
8    LLVMGetSymbolSize, LLVMGetSymbols, LLVMIsRelocationIteratorAtEnd, LLVMIsSectionIteratorAtEnd,
9    LLVMIsSymbolIteratorAtEnd, LLVMMoveToNextRelocation, LLVMMoveToNextSection, LLVMMoveToNextSymbol,
10    LLVMObjectFileRef, LLVMRelocationIteratorRef, LLVMSectionIteratorRef, LLVMSymbolIteratorRef,
11};
12
13use std::ffi::CStr;
14
15// REVIEW: Make sure SectionIterator's object_file ptr doesn't outlive ObjectFile
16// REVIEW: This module is very untested
17// TODO: More references to account for lifetimes
18#[derive(Debug)]
19pub struct ObjectFile {
20    object_file: LLVMObjectFileRef,
21}
22
23impl ObjectFile {
24    pub unsafe fn new(object_file: LLVMObjectFileRef) -> Self {
25        assert!(!object_file.is_null());
26
27        ObjectFile { object_file }
28    }
29
30    pub fn as_mut_ptr(&self) -> LLVMObjectFileRef {
31        self.object_file
32    }
33
34    pub fn get_sections(&self) -> SectionIterator {
35        let section_iterator = unsafe { LLVMGetSections(self.object_file) };
36
37        unsafe { SectionIterator::new(section_iterator, self.object_file) }
38    }
39
40    pub fn get_symbols(&self) -> SymbolIterator {
41        let symbol_iterator = unsafe { LLVMGetSymbols(self.object_file) };
42
43        unsafe { SymbolIterator::new(symbol_iterator, self.object_file) }
44    }
45}
46
47impl Drop for ObjectFile {
48    fn drop(&mut self) {
49        unsafe { LLVMDisposeObjectFile(self.object_file) }
50    }
51}
52
53#[derive(Debug)]
54pub struct SectionIterator {
55    section_iterator: LLVMSectionIteratorRef,
56    object_file: LLVMObjectFileRef,
57    before_first: bool,
58}
59
60impl SectionIterator {
61    pub unsafe fn new(section_iterator: LLVMSectionIteratorRef, object_file: LLVMObjectFileRef) -> Self {
62        assert!(!section_iterator.is_null());
63        assert!(!object_file.is_null());
64
65        SectionIterator {
66            section_iterator,
67            object_file,
68            before_first: true,
69        }
70    }
71
72    pub fn as_mut_ptr(&self) -> (LLVMSectionIteratorRef, LLVMObjectFileRef) {
73        (self.section_iterator, self.object_file)
74    }
75}
76
77impl Iterator for SectionIterator {
78    type Item = Section;
79
80    fn next(&mut self) -> Option<Self::Item> {
81        if self.before_first {
82            self.before_first = false;
83        } else {
84            unsafe {
85                LLVMMoveToNextSection(self.section_iterator);
86            }
87        }
88
89        let at_end = unsafe { LLVMIsSectionIteratorAtEnd(self.object_file, self.section_iterator) == 1 };
90
91        if at_end {
92            return None;
93        }
94
95        Some(unsafe { Section::new(self.section_iterator, self.object_file) })
96    }
97}
98
99impl Drop for SectionIterator {
100    fn drop(&mut self) {
101        unsafe { LLVMDisposeSectionIterator(self.section_iterator) }
102    }
103}
104
105#[derive(Debug)]
106pub struct Section {
107    section: LLVMSectionIteratorRef,
108    object_file: LLVMObjectFileRef,
109}
110
111impl Section {
112    pub unsafe fn new(section: LLVMSectionIteratorRef, object_file: LLVMObjectFileRef) -> Self {
113        assert!(!section.is_null());
114        assert!(!object_file.is_null());
115
116        Section { section, object_file }
117    }
118
119    pub unsafe fn as_mut_ptr(&self) -> (LLVMSectionIteratorRef, LLVMObjectFileRef) {
120        (self.section, self.object_file)
121    }
122
123    pub fn get_name(&self) -> Option<&CStr> {
124        let name = unsafe { LLVMGetSectionName(self.section) };
125        if !name.is_null() {
126            Some(unsafe { CStr::from_ptr(name) })
127        } else {
128            None
129        }
130    }
131
132    pub fn size(&self) -> u64 {
133        unsafe { LLVMGetSectionSize(self.section) }
134    }
135
136    pub fn get_contents(&self) -> &[u8] {
137        unsafe { std::slice::from_raw_parts(LLVMGetSectionContents(self.section) as *const u8, self.size() as usize) }
138    }
139
140    pub fn get_address(&self) -> u64 {
141        unsafe { LLVMGetSectionAddress(self.section) }
142    }
143
144    pub fn get_relocations(&self) -> RelocationIterator {
145        let relocation_iterator = unsafe { LLVMGetRelocations(self.section) };
146
147        unsafe { RelocationIterator::new(relocation_iterator, self.section, self.object_file) }
148    }
149}
150
151#[derive(Debug)]
152pub struct RelocationIterator {
153    relocation_iterator: LLVMRelocationIteratorRef,
154    section_iterator: LLVMSectionIteratorRef,
155    object_file: LLVMObjectFileRef,
156    before_first: bool,
157}
158
159impl RelocationIterator {
160    pub unsafe fn new(
161        relocation_iterator: LLVMRelocationIteratorRef,
162        section_iterator: LLVMSectionIteratorRef,
163        object_file: LLVMObjectFileRef,
164    ) -> Self {
165        assert!(!relocation_iterator.is_null());
166        assert!(!section_iterator.is_null());
167        assert!(!object_file.is_null());
168
169        RelocationIterator {
170            relocation_iterator,
171            section_iterator,
172            object_file,
173            before_first: true,
174        }
175    }
176
177    pub fn as_mut_ptr(&self) -> (LLVMRelocationIteratorRef, LLVMSectionIteratorRef, LLVMObjectFileRef) {
178        (self.relocation_iterator, self.section_iterator, self.object_file)
179    }
180}
181
182impl Iterator for RelocationIterator {
183    type Item = Relocation;
184
185    fn next(&mut self) -> Option<Self::Item> {
186        if self.before_first {
187            self.before_first = false;
188        } else {
189            unsafe { LLVMMoveToNextRelocation(self.relocation_iterator) }
190        }
191
192        let at_end = unsafe { LLVMIsRelocationIteratorAtEnd(self.section_iterator, self.relocation_iterator) == 1 };
193
194        if at_end {
195            return None;
196        }
197
198        Some(unsafe { Relocation::new(self.relocation_iterator, self.object_file) })
199    }
200}
201
202impl Drop for RelocationIterator {
203    fn drop(&mut self) {
204        unsafe { LLVMDisposeRelocationIterator(self.relocation_iterator) }
205    }
206}
207
208#[derive(Debug)]
209pub struct Relocation {
210    relocation: LLVMRelocationIteratorRef,
211    object_file: LLVMObjectFileRef,
212}
213
214impl Relocation {
215    pub unsafe fn new(relocation: LLVMRelocationIteratorRef, object_file: LLVMObjectFileRef) -> Self {
216        assert!(!relocation.is_null());
217        assert!(!object_file.is_null());
218
219        Relocation {
220            relocation,
221            object_file,
222        }
223    }
224
225    pub fn as_mut_ptr(&self) -> (LLVMRelocationIteratorRef, LLVMObjectFileRef) {
226        (self.relocation, self.object_file)
227    }
228
229    pub fn get_offset(&self) -> u64 {
230        unsafe { LLVMGetRelocationOffset(self.relocation) }
231    }
232
233    pub fn get_symbols(&self) -> SymbolIterator {
234        let symbol_iterator = unsafe {
235            // REVIEW: Is this just returning a single Symbol (given the name) and not a full iterator?
236            LLVMGetRelocationSymbol(self.relocation)
237        };
238
239        unsafe { SymbolIterator::new(symbol_iterator, self.object_file) }
240    }
241
242    pub fn get_type(&self) -> (u64, &CStr) {
243        let type_int = unsafe { LLVMGetRelocationType(self.relocation) };
244        let type_name = unsafe { CStr::from_ptr(LLVMGetRelocationTypeName(self.relocation)) };
245
246        (type_int, type_name)
247    }
248
249    pub fn get_value(&self) -> &CStr {
250        unsafe { CStr::from_ptr(LLVMGetRelocationValueString(self.relocation)) }
251    }
252}
253
254#[derive(Debug)]
255pub struct SymbolIterator {
256    symbol_iterator: LLVMSymbolIteratorRef,
257    object_file: LLVMObjectFileRef,
258    before_first: bool,
259}
260
261impl SymbolIterator {
262    pub unsafe fn new(symbol_iterator: LLVMSymbolIteratorRef, object_file: LLVMObjectFileRef) -> Self {
263        assert!(!symbol_iterator.is_null());
264        assert!(!object_file.is_null());
265
266        SymbolIterator {
267            symbol_iterator,
268            object_file,
269            before_first: true,
270        }
271    }
272
273    pub fn as_mut_ptr(&self) -> (LLVMSymbolIteratorRef, LLVMObjectFileRef) {
274        (self.symbol_iterator, self.object_file)
275    }
276}
277
278impl Iterator for SymbolIterator {
279    type Item = Symbol;
280
281    fn next(&mut self) -> Option<Self::Item> {
282        if self.before_first {
283            self.before_first = false;
284        } else {
285            unsafe { LLVMMoveToNextSymbol(self.symbol_iterator) }
286        }
287
288        let at_end = unsafe { LLVMIsSymbolIteratorAtEnd(self.object_file, self.symbol_iterator) == 1 };
289
290        if at_end {
291            return None;
292        }
293
294        Some(unsafe { Symbol::new(self.symbol_iterator) })
295    }
296}
297
298impl Drop for SymbolIterator {
299    fn drop(&mut self) {
300        unsafe { LLVMDisposeSymbolIterator(self.symbol_iterator) }
301    }
302}
303
304#[derive(Debug)]
305pub struct Symbol {
306    symbol: LLVMSymbolIteratorRef,
307}
308
309impl Symbol {
310    pub unsafe fn new(symbol: LLVMSymbolIteratorRef) -> Self {
311        assert!(!symbol.is_null());
312
313        Symbol { symbol }
314    }
315
316    pub fn as_mut_ptr(&self) -> LLVMSymbolIteratorRef {
317        self.symbol
318    }
319
320    pub fn get_name(&self) -> Option<&CStr> {
321        let name = unsafe { LLVMGetSymbolName(self.symbol) };
322        if !name.is_null() {
323            Some(unsafe { CStr::from_ptr(name) })
324        } else {
325            None
326        }
327    }
328
329    pub fn size(&self) -> u64 {
330        unsafe { LLVMGetSymbolSize(self.symbol) }
331    }
332
333    pub fn get_address(&self) -> u64 {
334        unsafe { LLVMGetSymbolAddress(self.symbol) }
335    }
336}