xref: /llvm-project/llvm/lib/Object/Object.cpp (revision a51883cfab4ea36215549a58f29d65b862ef857c)
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 // ObjectFile creation
135 LLVMObjectFileRef LLVMCreateObjectFile(LLVMMemoryBufferRef MemBuf) {
136   std::unique_ptr<MemoryBuffer> Buf(unwrap(MemBuf));
137   Expected<std::unique_ptr<ObjectFile>> ObjOrErr(
138       ObjectFile::createObjectFile(Buf->getMemBufferRef()));
139   std::unique_ptr<ObjectFile> Obj;
140   if (!ObjOrErr) {
141     // TODO: Actually report errors helpfully.
142     consumeError(ObjOrErr.takeError());
143     return nullptr;
144   }
145 
146   auto *Ret = new OwningBinary<ObjectFile>(std::move(ObjOrErr.get()), std::move(Buf));
147   return wrap(Ret);
148 }
149 
150 void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile) {
151   delete unwrap(ObjectFile);
152 }
153 
154 // ObjectFile Section iterators
155 LLVMSectionIteratorRef LLVMGetSections(LLVMObjectFileRef OF) {
156   OwningBinary<ObjectFile> *OB = unwrap(OF);
157   section_iterator SI = OB->getBinary()->section_begin();
158   return wrap(new section_iterator(SI));
159 }
160 
161 void LLVMDisposeSectionIterator(LLVMSectionIteratorRef SI) {
162   delete unwrap(SI);
163 }
164 
165 LLVMBool LLVMIsSectionIteratorAtEnd(LLVMObjectFileRef OF,
166                                     LLVMSectionIteratorRef SI) {
167   OwningBinary<ObjectFile> *OB = unwrap(OF);
168   return (*unwrap(SI) == OB->getBinary()->section_end()) ? 1 : 0;
169 }
170 
171 void LLVMMoveToNextSection(LLVMSectionIteratorRef SI) {
172   ++(*unwrap(SI));
173 }
174 
175 void LLVMMoveToContainingSection(LLVMSectionIteratorRef Sect,
176                                  LLVMSymbolIteratorRef Sym) {
177   Expected<section_iterator> SecOrErr = (*unwrap(Sym))->getSection();
178   if (!SecOrErr) {
179    std::string Buf;
180    raw_string_ostream OS(Buf);
181    logAllUnhandledErrors(SecOrErr.takeError(), OS);
182    OS.flush();
183    report_fatal_error(Buf);
184   }
185   *unwrap(Sect) = *SecOrErr;
186 }
187 
188 // ObjectFile Symbol iterators
189 LLVMSymbolIteratorRef LLVMGetSymbols(LLVMObjectFileRef OF) {
190   OwningBinary<ObjectFile> *OB = unwrap(OF);
191   symbol_iterator SI = OB->getBinary()->symbol_begin();
192   return wrap(new symbol_iterator(SI));
193 }
194 
195 void LLVMDisposeSymbolIterator(LLVMSymbolIteratorRef SI) {
196   delete unwrap(SI);
197 }
198 
199 LLVMBool LLVMIsSymbolIteratorAtEnd(LLVMObjectFileRef OF,
200                                    LLVMSymbolIteratorRef SI) {
201   OwningBinary<ObjectFile> *OB = unwrap(OF);
202   return (*unwrap(SI) == OB->getBinary()->symbol_end()) ? 1 : 0;
203 }
204 
205 void LLVMMoveToNextSymbol(LLVMSymbolIteratorRef SI) {
206   ++(*unwrap(SI));
207 }
208 
209 // SectionRef accessors
210 const char *LLVMGetSectionName(LLVMSectionIteratorRef SI) {
211   StringRef ret;
212   if (std::error_code ec = (*unwrap(SI))->getName(ret))
213    report_fatal_error(ec.message());
214   return ret.data();
215 }
216 
217 uint64_t LLVMGetSectionSize(LLVMSectionIteratorRef SI) {
218   return (*unwrap(SI))->getSize();
219 }
220 
221 const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI) {
222   StringRef ret;
223   if (std::error_code ec = (*unwrap(SI))->getContents(ret))
224     report_fatal_error(ec.message());
225   return ret.data();
226 }
227 
228 uint64_t LLVMGetSectionAddress(LLVMSectionIteratorRef SI) {
229   return (*unwrap(SI))->getAddress();
230 }
231 
232 LLVMBool LLVMGetSectionContainsSymbol(LLVMSectionIteratorRef SI,
233                                  LLVMSymbolIteratorRef Sym) {
234   return (*unwrap(SI))->containsSymbol(**unwrap(Sym));
235 }
236 
237 // Section Relocation iterators
238 LLVMRelocationIteratorRef LLVMGetRelocations(LLVMSectionIteratorRef Section) {
239   relocation_iterator SI = (*unwrap(Section))->relocation_begin();
240   return wrap(new relocation_iterator(SI));
241 }
242 
243 void LLVMDisposeRelocationIterator(LLVMRelocationIteratorRef SI) {
244   delete unwrap(SI);
245 }
246 
247 LLVMBool LLVMIsRelocationIteratorAtEnd(LLVMSectionIteratorRef Section,
248                                        LLVMRelocationIteratorRef SI) {
249   return (*unwrap(SI) == (*unwrap(Section))->relocation_end()) ? 1 : 0;
250 }
251 
252 void LLVMMoveToNextRelocation(LLVMRelocationIteratorRef SI) {
253   ++(*unwrap(SI));
254 }
255 
256 
257 // SymbolRef accessors
258 const char *LLVMGetSymbolName(LLVMSymbolIteratorRef SI) {
259   Expected<StringRef> Ret = (*unwrap(SI))->getName();
260   if (!Ret) {
261     std::string Buf;
262     raw_string_ostream OS(Buf);
263     logAllUnhandledErrors(Ret.takeError(), OS);
264     OS.flush();
265     report_fatal_error(Buf);
266   }
267   return Ret->data();
268 }
269 
270 uint64_t LLVMGetSymbolAddress(LLVMSymbolIteratorRef SI) {
271   Expected<uint64_t> Ret = (*unwrap(SI))->getAddress();
272   if (!Ret) {
273     std::string Buf;
274     raw_string_ostream OS(Buf);
275     logAllUnhandledErrors(Ret.takeError(), OS);
276     OS.flush();
277     report_fatal_error(Buf);
278   }
279   return *Ret;
280 }
281 
282 uint64_t LLVMGetSymbolSize(LLVMSymbolIteratorRef SI) {
283   return (*unwrap(SI))->getCommonSize();
284 }
285 
286 // RelocationRef accessors
287 uint64_t LLVMGetRelocationOffset(LLVMRelocationIteratorRef RI) {
288   return (*unwrap(RI))->getOffset();
289 }
290 
291 LLVMSymbolIteratorRef LLVMGetRelocationSymbol(LLVMRelocationIteratorRef RI) {
292   symbol_iterator ret = (*unwrap(RI))->getSymbol();
293   return wrap(new symbol_iterator(ret));
294 }
295 
296 uint64_t LLVMGetRelocationType(LLVMRelocationIteratorRef RI) {
297   return (*unwrap(RI))->getType();
298 }
299 
300 // NOTE: Caller takes ownership of returned string.
301 const char *LLVMGetRelocationTypeName(LLVMRelocationIteratorRef RI) {
302   SmallVector<char, 0> ret;
303   (*unwrap(RI))->getTypeName(ret);
304   char *str = static_cast<char*>(safe_malloc(ret.size()));
305   llvm::copy(ret, str);
306   return str;
307 }
308 
309 // NOTE: Caller takes ownership of returned string.
310 const char *LLVMGetRelocationValueString(LLVMRelocationIteratorRef RI) {
311   return strdup("");
312 }
313 
314