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