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 | std::unique_ptr<ObjectFile> Obj; |
186 | if (!ObjOrErr) { |
187 | // TODO: Actually report errors helpfully. |
188 | consumeError(Err: ObjOrErr.takeError()); |
189 | return nullptr; |
190 | } |
191 | |
192 | auto *Ret = new OwningBinary<ObjectFile>(std::move(ObjOrErr.get()), std::move(Buf)); |
193 | return wrap(OF: Ret); |
194 | } |
195 | |
196 | void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile) { |
197 | delete unwrap(OF: ObjectFile); |
198 | } |
199 | |
200 | // ObjectFile Section iterators |
201 | LLVMSectionIteratorRef LLVMGetSections(LLVMObjectFileRef OF) { |
202 | OwningBinary<ObjectFile> *OB = unwrap(OF); |
203 | section_iterator SI = OB->getBinary()->section_begin(); |
204 | return wrap(SI: new section_iterator(SI)); |
205 | } |
206 | |
207 | void LLVMDisposeSectionIterator(LLVMSectionIteratorRef SI) { |
208 | delete unwrap(SI); |
209 | } |
210 | |
211 | LLVMBool LLVMIsSectionIteratorAtEnd(LLVMObjectFileRef OF, |
212 | LLVMSectionIteratorRef SI) { |
213 | OwningBinary<ObjectFile> *OB = unwrap(OF); |
214 | return (*unwrap(SI) == OB->getBinary()->section_end()) ? 1 : 0; |
215 | } |
216 | |
217 | void LLVMMoveToNextSection(LLVMSectionIteratorRef SI) { |
218 | ++(*unwrap(SI)); |
219 | } |
220 | |
221 | void LLVMMoveToContainingSection(LLVMSectionIteratorRef Sect, |
222 | LLVMSymbolIteratorRef Sym) { |
223 | Expected<section_iterator> SecOrErr = (*unwrap(SI: Sym))->getSection(); |
224 | if (!SecOrErr) { |
225 | std::string Buf; |
226 | raw_string_ostream OS(Buf); |
227 | logAllUnhandledErrors(E: SecOrErr.takeError(), OS); |
228 | report_fatal_error(reason: Twine(OS.str())); |
229 | } |
230 | *unwrap(SI: Sect) = *SecOrErr; |
231 | } |
232 | |
233 | // ObjectFile Symbol iterators |
234 | LLVMSymbolIteratorRef LLVMGetSymbols(LLVMObjectFileRef OF) { |
235 | OwningBinary<ObjectFile> *OB = unwrap(OF); |
236 | symbol_iterator SI = OB->getBinary()->symbol_begin(); |
237 | return wrap(SI: new symbol_iterator(SI)); |
238 | } |
239 | |
240 | void LLVMDisposeSymbolIterator(LLVMSymbolIteratorRef SI) { |
241 | delete unwrap(SI); |
242 | } |
243 | |
244 | LLVMBool LLVMIsSymbolIteratorAtEnd(LLVMObjectFileRef OF, |
245 | LLVMSymbolIteratorRef SI) { |
246 | OwningBinary<ObjectFile> *OB = unwrap(OF); |
247 | return (*unwrap(SI) == OB->getBinary()->symbol_end()) ? 1 : 0; |
248 | } |
249 | |
250 | void LLVMMoveToNextSymbol(LLVMSymbolIteratorRef SI) { |
251 | ++(*unwrap(SI)); |
252 | } |
253 | |
254 | // SectionRef accessors |
255 | const char *LLVMGetSectionName(LLVMSectionIteratorRef SI) { |
256 | auto NameOrErr = (*unwrap(SI))->getName(); |
257 | if (!NameOrErr) |
258 | report_fatal_error(Err: NameOrErr.takeError()); |
259 | return NameOrErr->data(); |
260 | } |
261 | |
262 | uint64_t LLVMGetSectionSize(LLVMSectionIteratorRef SI) { |
263 | return (*unwrap(SI))->getSize(); |
264 | } |
265 | |
266 | const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI) { |
267 | if (Expected<StringRef> E = (*unwrap(SI))->getContents()) |
268 | return E->data(); |
269 | else |
270 | report_fatal_error(Err: E.takeError()); |
271 | } |
272 | |
273 | uint64_t LLVMGetSectionAddress(LLVMSectionIteratorRef SI) { |
274 | return (*unwrap(SI))->getAddress(); |
275 | } |
276 | |
277 | LLVMBool LLVMGetSectionContainsSymbol(LLVMSectionIteratorRef SI, |
278 | LLVMSymbolIteratorRef Sym) { |
279 | return (*unwrap(SI))->containsSymbol(S: **unwrap(SI: Sym)); |
280 | } |
281 | |
282 | // Section Relocation iterators |
283 | LLVMRelocationIteratorRef LLVMGetRelocations(LLVMSectionIteratorRef Section) { |
284 | relocation_iterator SI = (*unwrap(SI: Section))->relocation_begin(); |
285 | return wrap(SI: new relocation_iterator(SI)); |
286 | } |
287 | |
288 | void LLVMDisposeRelocationIterator(LLVMRelocationIteratorRef SI) { |
289 | delete unwrap(SI); |
290 | } |
291 | |
292 | LLVMBool LLVMIsRelocationIteratorAtEnd(LLVMSectionIteratorRef Section, |
293 | LLVMRelocationIteratorRef SI) { |
294 | return (*unwrap(SI) == (*unwrap(SI: Section))->relocation_end()) ? 1 : 0; |
295 | } |
296 | |
297 | void LLVMMoveToNextRelocation(LLVMRelocationIteratorRef SI) { |
298 | ++(*unwrap(SI)); |
299 | } |
300 | |
301 | |
302 | // SymbolRef accessors |
303 | const char *LLVMGetSymbolName(LLVMSymbolIteratorRef SI) { |
304 | Expected<StringRef> Ret = (*unwrap(SI))->getName(); |
305 | if (!Ret) { |
306 | std::string Buf; |
307 | raw_string_ostream OS(Buf); |
308 | logAllUnhandledErrors(E: Ret.takeError(), OS); |
309 | report_fatal_error(reason: Twine(OS.str())); |
310 | } |
311 | return Ret->data(); |
312 | } |
313 | |
314 | uint64_t LLVMGetSymbolAddress(LLVMSymbolIteratorRef SI) { |
315 | Expected<uint64_t> Ret = (*unwrap(SI))->getAddress(); |
316 | if (!Ret) { |
317 | std::string Buf; |
318 | raw_string_ostream OS(Buf); |
319 | logAllUnhandledErrors(E: Ret.takeError(), OS); |
320 | report_fatal_error(reason: Twine(OS.str())); |
321 | } |
322 | return *Ret; |
323 | } |
324 | |
325 | uint64_t LLVMGetSymbolSize(LLVMSymbolIteratorRef SI) { |
326 | return (*unwrap(SI))->getCommonSize(); |
327 | } |
328 | |
329 | // RelocationRef accessors |
330 | uint64_t LLVMGetRelocationOffset(LLVMRelocationIteratorRef RI) { |
331 | return (*unwrap(SI: RI))->getOffset(); |
332 | } |
333 | |
334 | LLVMSymbolIteratorRef LLVMGetRelocationSymbol(LLVMRelocationIteratorRef RI) { |
335 | symbol_iterator ret = (*unwrap(SI: RI))->getSymbol(); |
336 | return wrap(SI: new symbol_iterator(ret)); |
337 | } |
338 | |
339 | uint64_t LLVMGetRelocationType(LLVMRelocationIteratorRef RI) { |
340 | return (*unwrap(SI: RI))->getType(); |
341 | } |
342 | |
343 | // NOTE: Caller takes ownership of returned string. |
344 | const char *LLVMGetRelocationTypeName(LLVMRelocationIteratorRef RI) { |
345 | SmallVector<char, 0> ret; |
346 | (*unwrap(SI: RI))->getTypeName(Result&: ret); |
347 | char *str = static_cast<char*>(safe_malloc(Sz: ret.size())); |
348 | llvm::copy(Range&: ret, Out: str); |
349 | return str; |
350 | } |
351 | |
352 | // NOTE: Caller takes ownership of returned string. |
353 | const char *LLVMGetRelocationValueString(LLVMRelocationIteratorRef RI) { |
354 | return strdup(s: "" ); |
355 | } |
356 | |
357 | |