1 | //===- Object.cpp - C bindings to the object file library--------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file defines the C bindings to the file-format-independent object |
10 | // library. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "llvm-c/Object.h" |
15 | #include "llvm/ADT/SmallVector.h" |
16 | #include "llvm/IR/LLVMContext.h" |
17 | #include "llvm/Object/ObjectFile.h" |
18 | #include "llvm/Object/MachOUniversal.h" |
19 | #include "llvm/Support/MemAlloc.h" |
20 | |
21 | using namespace llvm; |
22 | using namespace object; |
23 | |
24 | inline OwningBinary<ObjectFile> *unwrap(LLVMObjectFileRef OF) { |
25 | return reinterpret_cast<OwningBinary<ObjectFile> *>(OF); |
26 | } |
27 | |
28 | inline LLVMObjectFileRef wrap(const OwningBinary<ObjectFile> *OF) { |
29 | return reinterpret_cast<LLVMObjectFileRef>( |
30 | const_cast<OwningBinary<ObjectFile> *>(OF)); |
31 | } |
32 | |
33 | inline section_iterator *unwrap(LLVMSectionIteratorRef SI) { |
34 | return reinterpret_cast<section_iterator*>(SI); |
35 | } |
36 | |
37 | inline LLVMSectionIteratorRef |
38 | wrap(const section_iterator *SI) { |
39 | return reinterpret_cast<LLVMSectionIteratorRef> |
40 | (const_cast<section_iterator*>(SI)); |
41 | } |
42 | |
43 | inline symbol_iterator *unwrap(LLVMSymbolIteratorRef SI) { |
44 | return reinterpret_cast<symbol_iterator*>(SI); |
45 | } |
46 | |
47 | inline LLVMSymbolIteratorRef |
48 | wrap(const symbol_iterator *SI) { |
49 | return reinterpret_cast<LLVMSymbolIteratorRef> |
50 | (const_cast<symbol_iterator*>(SI)); |
51 | } |
52 | |
53 | inline relocation_iterator *unwrap(LLVMRelocationIteratorRef SI) { |
54 | return reinterpret_cast<relocation_iterator*>(SI); |
55 | } |
56 | |
57 | inline LLVMRelocationIteratorRef |
58 | wrap(const relocation_iterator *SI) { |
59 | return reinterpret_cast<LLVMRelocationIteratorRef> |
60 | (const_cast<relocation_iterator*>(SI)); |
61 | } |
62 | |
63 | /*--.. Operations on binary files ..........................................--*/ |
64 | |
65 | LLVMBinaryRef LLVMCreateBinary(LLVMMemoryBufferRef MemBuf, |
66 | LLVMContextRef Context, |
67 | char **ErrorMessage) { |
68 | auto maybeContext = Context ? unwrap(P: Context) : nullptr; |
69 | Expected<std::unique_ptr<Binary>> ObjOrErr( |
70 | createBinary(Source: unwrap(P: MemBuf)->getMemBufferRef(), Context: maybeContext)); |
71 | if (!ObjOrErr) { |
72 | *ErrorMessage = strdup(s: toString(E: ObjOrErr.takeError()).c_str()); |
73 | return nullptr; |
74 | } |
75 | |
76 | return wrap(P: ObjOrErr.get().release()); |
77 | } |
78 | |
79 | LLVMMemoryBufferRef LLVMBinaryCopyMemoryBuffer(LLVMBinaryRef BR) { |
80 | auto Buf = unwrap(P: BR)->getMemoryBufferRef(); |
81 | return wrap(P: llvm::MemoryBuffer::getMemBuffer( |
82 | InputData: Buf.getBuffer(), BufferName: Buf.getBufferIdentifier(), |
83 | /*RequiresNullTerminator*/false).release()); |
84 | } |
85 | |
86 | void LLVMDisposeBinary(LLVMBinaryRef BR) { |
87 | delete unwrap(P: BR); |
88 | } |
89 | |
90 | LLVMBinaryType LLVMBinaryGetType(LLVMBinaryRef BR) { |
91 | class BinaryTypeMapper final : public Binary { |
92 | public: |
93 | static LLVMBinaryType mapBinaryTypeToLLVMBinaryType(unsigned Kind) { |
94 | switch (Kind) { |
95 | case ID_Archive: |
96 | return LLVMBinaryTypeArchive; |
97 | case ID_MachOUniversalBinary: |
98 | return LLVMBinaryTypeMachOUniversalBinary; |
99 | case ID_COFFImportFile: |
100 | return LLVMBinaryTypeCOFFImportFile; |
101 | case ID_IR: |
102 | return LLVMBinaryTypeIR; |
103 | case ID_WinRes: |
104 | return LLVMBinaryTypeWinRes; |
105 | case ID_COFF: |
106 | return LLVMBinaryTypeCOFF; |
107 | case ID_ELF32L: |
108 | return LLVMBinaryTypeELF32L; |
109 | case ID_ELF32B: |
110 | return LLVMBinaryTypeELF32B; |
111 | case ID_ELF64L: |
112 | return LLVMBinaryTypeELF64L; |
113 | case ID_ELF64B: |
114 | return LLVMBinaryTypeELF64B; |
115 | case ID_MachO32L: |
116 | return LLVMBinaryTypeMachO32L; |
117 | case ID_MachO32B: |
118 | return LLVMBinaryTypeMachO32B; |
119 | case ID_MachO64L: |
120 | return LLVMBinaryTypeMachO64L; |
121 | case ID_MachO64B: |
122 | return LLVMBinaryTypeMachO64B; |
123 | case ID_Offload: |
124 | return LLVMBinaryTypeOffload; |
125 | case ID_Wasm: |
126 | return LLVMBinaryTypeWasm; |
127 | case ID_StartObjects: |
128 | case ID_EndObjects: |
129 | llvm_unreachable("Marker types are not valid binary kinds!" ); |
130 | default: |
131 | llvm_unreachable("Unknown binary kind!" ); |
132 | } |
133 | } |
134 | }; |
135 | return BinaryTypeMapper::mapBinaryTypeToLLVMBinaryType(Kind: unwrap(P: BR)->getType()); |
136 | } |
137 | |
138 | LLVMBinaryRef LLVMMachOUniversalBinaryCopyObjectForArch(LLVMBinaryRef BR, |
139 | const char *Arch, |
140 | size_t ArchLen, |
141 | char **ErrorMessage) { |
142 | auto universal = cast<MachOUniversalBinary>(Val: unwrap(P: BR)); |
143 | Expected<std::unique_ptr<ObjectFile>> ObjOrErr( |
144 | universal->getMachOObjectForArch(ArchName: {Arch, ArchLen})); |
145 | if (!ObjOrErr) { |
146 | *ErrorMessage = strdup(s: toString(E: ObjOrErr.takeError()).c_str()); |
147 | return nullptr; |
148 | } |
149 | return wrap(P: ObjOrErr.get().release()); |
150 | } |
151 | |
152 | LLVMSectionIteratorRef LLVMObjectFileCopySectionIterator(LLVMBinaryRef BR) { |
153 | auto OF = cast<ObjectFile>(Val: unwrap(P: BR)); |
154 | auto sections = OF->sections(); |
155 | if (sections.begin() == sections.end()) |
156 | return nullptr; |
157 | return wrap(SI: new section_iterator(sections.begin())); |
158 | } |
159 | |
160 | LLVMBool LLVMObjectFileIsSectionIteratorAtEnd(LLVMBinaryRef BR, |
161 | LLVMSectionIteratorRef SI) { |
162 | auto OF = cast<ObjectFile>(Val: unwrap(P: BR)); |
163 | return (*unwrap(SI) == OF->section_end()) ? 1 : 0; |
164 | } |
165 | |
166 | LLVMSymbolIteratorRef LLVMObjectFileCopySymbolIterator(LLVMBinaryRef BR) { |
167 | auto OF = cast<ObjectFile>(Val: unwrap(P: BR)); |
168 | auto symbols = OF->symbols(); |
169 | if (symbols.begin() == symbols.end()) |
170 | return nullptr; |
171 | return wrap(SI: new symbol_iterator(symbols.begin())); |
172 | } |
173 | |
174 | LLVMBool LLVMObjectFileIsSymbolIteratorAtEnd(LLVMBinaryRef BR, |
175 | LLVMSymbolIteratorRef SI) { |
176 | auto OF = cast<ObjectFile>(Val: unwrap(P: BR)); |
177 | return (*unwrap(SI) == OF->symbol_end()) ? 1 : 0; |
178 | } |
179 | |
180 | // ObjectFile creation |
181 | LLVMObjectFileRef LLVMCreateObjectFile(LLVMMemoryBufferRef MemBuf) { |
182 | std::unique_ptr<MemoryBuffer> Buf(unwrap(P: MemBuf)); |
183 | Expected<std::unique_ptr<ObjectFile>> ObjOrErr( |
184 | ObjectFile::createObjectFile(Object: Buf->getMemBufferRef())); |
185 | if (!ObjOrErr) { |
186 | // TODO: Actually report errors helpfully. |
187 | consumeError(Err: ObjOrErr.takeError()); |
188 | return nullptr; |
189 | } |
190 | |
191 | auto *Ret = new OwningBinary<ObjectFile>(std::move(ObjOrErr.get()), std::move(Buf)); |
192 | return wrap(OF: Ret); |
193 | } |
194 | |
195 | void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile) { |
196 | delete unwrap(OF: ObjectFile); |
197 | } |
198 | |
199 | // ObjectFile Section iterators |
200 | LLVMSectionIteratorRef LLVMGetSections(LLVMObjectFileRef OF) { |
201 | OwningBinary<ObjectFile> *OB = unwrap(OF); |
202 | section_iterator SI = OB->getBinary()->section_begin(); |
203 | return wrap(SI: new section_iterator(SI)); |
204 | } |
205 | |
206 | void LLVMDisposeSectionIterator(LLVMSectionIteratorRef SI) { |
207 | delete unwrap(SI); |
208 | } |
209 | |
210 | LLVMBool LLVMIsSectionIteratorAtEnd(LLVMObjectFileRef OF, |
211 | LLVMSectionIteratorRef SI) { |
212 | OwningBinary<ObjectFile> *OB = unwrap(OF); |
213 | return (*unwrap(SI) == OB->getBinary()->section_end()) ? 1 : 0; |
214 | } |
215 | |
216 | void LLVMMoveToNextSection(LLVMSectionIteratorRef SI) { |
217 | ++(*unwrap(SI)); |
218 | } |
219 | |
220 | void LLVMMoveToContainingSection(LLVMSectionIteratorRef Sect, |
221 | LLVMSymbolIteratorRef Sym) { |
222 | Expected<section_iterator> SecOrErr = (*unwrap(SI: Sym))->getSection(); |
223 | if (!SecOrErr) { |
224 | std::string Buf; |
225 | raw_string_ostream OS(Buf); |
226 | logAllUnhandledErrors(E: SecOrErr.takeError(), OS); |
227 | report_fatal_error(reason: Twine(OS.str())); |
228 | } |
229 | *unwrap(SI: Sect) = *SecOrErr; |
230 | } |
231 | |
232 | // ObjectFile Symbol iterators |
233 | LLVMSymbolIteratorRef LLVMGetSymbols(LLVMObjectFileRef OF) { |
234 | OwningBinary<ObjectFile> *OB = unwrap(OF); |
235 | symbol_iterator SI = OB->getBinary()->symbol_begin(); |
236 | return wrap(SI: new symbol_iterator(SI)); |
237 | } |
238 | |
239 | void LLVMDisposeSymbolIterator(LLVMSymbolIteratorRef SI) { |
240 | delete unwrap(SI); |
241 | } |
242 | |
243 | LLVMBool LLVMIsSymbolIteratorAtEnd(LLVMObjectFileRef OF, |
244 | LLVMSymbolIteratorRef SI) { |
245 | OwningBinary<ObjectFile> *OB = unwrap(OF); |
246 | return (*unwrap(SI) == OB->getBinary()->symbol_end()) ? 1 : 0; |
247 | } |
248 | |
249 | void LLVMMoveToNextSymbol(LLVMSymbolIteratorRef SI) { |
250 | ++(*unwrap(SI)); |
251 | } |
252 | |
253 | // SectionRef accessors |
254 | const char *LLVMGetSectionName(LLVMSectionIteratorRef SI) { |
255 | auto NameOrErr = (*unwrap(SI))->getName(); |
256 | if (!NameOrErr) |
257 | report_fatal_error(Err: NameOrErr.takeError()); |
258 | return NameOrErr->data(); |
259 | } |
260 | |
261 | uint64_t LLVMGetSectionSize(LLVMSectionIteratorRef SI) { |
262 | return (*unwrap(SI))->getSize(); |
263 | } |
264 | |
265 | const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI) { |
266 | if (Expected<StringRef> E = (*unwrap(SI))->getContents()) |
267 | return E->data(); |
268 | else |
269 | report_fatal_error(Err: E.takeError()); |
270 | } |
271 | |
272 | uint64_t LLVMGetSectionAddress(LLVMSectionIteratorRef SI) { |
273 | return (*unwrap(SI))->getAddress(); |
274 | } |
275 | |
276 | LLVMBool LLVMGetSectionContainsSymbol(LLVMSectionIteratorRef SI, |
277 | LLVMSymbolIteratorRef Sym) { |
278 | return (*unwrap(SI))->containsSymbol(S: **unwrap(SI: Sym)); |
279 | } |
280 | |
281 | // Section Relocation iterators |
282 | LLVMRelocationIteratorRef LLVMGetRelocations(LLVMSectionIteratorRef Section) { |
283 | relocation_iterator SI = (*unwrap(SI: Section))->relocation_begin(); |
284 | return wrap(SI: new relocation_iterator(SI)); |
285 | } |
286 | |
287 | void LLVMDisposeRelocationIterator(LLVMRelocationIteratorRef SI) { |
288 | delete unwrap(SI); |
289 | } |
290 | |
291 | LLVMBool LLVMIsRelocationIteratorAtEnd(LLVMSectionIteratorRef Section, |
292 | LLVMRelocationIteratorRef SI) { |
293 | return (*unwrap(SI) == (*unwrap(SI: Section))->relocation_end()) ? 1 : 0; |
294 | } |
295 | |
296 | void LLVMMoveToNextRelocation(LLVMRelocationIteratorRef SI) { |
297 | ++(*unwrap(SI)); |
298 | } |
299 | |
300 | |
301 | // SymbolRef accessors |
302 | const char *LLVMGetSymbolName(LLVMSymbolIteratorRef SI) { |
303 | Expected<StringRef> Ret = (*unwrap(SI))->getName(); |
304 | if (!Ret) { |
305 | std::string Buf; |
306 | raw_string_ostream OS(Buf); |
307 | logAllUnhandledErrors(E: Ret.takeError(), OS); |
308 | report_fatal_error(reason: Twine(OS.str())); |
309 | } |
310 | return Ret->data(); |
311 | } |
312 | |
313 | uint64_t LLVMGetSymbolAddress(LLVMSymbolIteratorRef SI) { |
314 | Expected<uint64_t> Ret = (*unwrap(SI))->getAddress(); |
315 | if (!Ret) { |
316 | std::string Buf; |
317 | raw_string_ostream OS(Buf); |
318 | logAllUnhandledErrors(E: Ret.takeError(), OS); |
319 | report_fatal_error(reason: Twine(OS.str())); |
320 | } |
321 | return *Ret; |
322 | } |
323 | |
324 | uint64_t LLVMGetSymbolSize(LLVMSymbolIteratorRef SI) { |
325 | return (*unwrap(SI))->getCommonSize(); |
326 | } |
327 | |
328 | // RelocationRef accessors |
329 | uint64_t LLVMGetRelocationOffset(LLVMRelocationIteratorRef RI) { |
330 | return (*unwrap(SI: RI))->getOffset(); |
331 | } |
332 | |
333 | LLVMSymbolIteratorRef LLVMGetRelocationSymbol(LLVMRelocationIteratorRef RI) { |
334 | symbol_iterator ret = (*unwrap(SI: RI))->getSymbol(); |
335 | return wrap(SI: new symbol_iterator(ret)); |
336 | } |
337 | |
338 | uint64_t LLVMGetRelocationType(LLVMRelocationIteratorRef RI) { |
339 | return (*unwrap(SI: RI))->getType(); |
340 | } |
341 | |
342 | // NOTE: Caller takes ownership of returned string. |
343 | const char *LLVMGetRelocationTypeName(LLVMRelocationIteratorRef RI) { |
344 | SmallVector<char, 0> ret; |
345 | (*unwrap(SI: RI))->getTypeName(Result&: ret); |
346 | char *str = static_cast<char*>(safe_malloc(Sz: ret.size())); |
347 | llvm::copy(Range&: ret, Out: str); |
348 | return str; |
349 | } |
350 | |
351 | // NOTE: Caller takes ownership of returned string. |
352 | const char *LLVMGetRelocationValueString(LLVMRelocationIteratorRef RI) { |
353 | return strdup(s: "" ); |
354 | } |
355 | |
356 | |