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