xref: /freebsd/contrib/llvm-project/llvm/lib/Object/Object.cpp (revision dddf29712f38ba1d804c02bcfd02d24098ae48b0)
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(Context) : nullptr;
69    Expected<std::unique_ptr<Binary>> ObjOrErr(
70        createBinary(unwrap(MemBuf)->getMemBufferRef(), maybeContext));
71    if (!ObjOrErr) {
72      *ErrorMessage = strdup(toString(ObjOrErr.takeError()).c_str());
73      return nullptr;
74    }
75  
76    return wrap(ObjOrErr.get().release());
77  }
78  
79  LLVMMemoryBufferRef LLVMBinaryCopyMemoryBuffer(LLVMBinaryRef BR) {
80    auto Buf = unwrap(BR)->getMemoryBufferRef();
81    return wrap(llvm::MemoryBuffer::getMemBuffer(
82                  Buf.getBuffer(), Buf.getBufferIdentifier(),
83                  /*RequiresNullTerminator*/false).release());
84  }
85  
86  void LLVMDisposeBinary(LLVMBinaryRef BR) {
87    delete unwrap(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(unwrap(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>(unwrap(BR));
143    Expected<std::unique_ptr<ObjectFile>> ObjOrErr(
144        universal->getMachOObjectForArch({Arch, ArchLen}));
145    if (!ObjOrErr) {
146      *ErrorMessage = strdup(toString(ObjOrErr.takeError()).c_str());
147      return nullptr;
148    }
149    return wrap(ObjOrErr.get().release());
150  }
151  
152  LLVMSectionIteratorRef LLVMObjectFileCopySectionIterator(LLVMBinaryRef BR) {
153    auto OF = cast<ObjectFile>(unwrap(BR));
154    auto sections = OF->sections();
155    if (sections.begin() == sections.end())
156      return nullptr;
157    return wrap(new section_iterator(sections.begin()));
158  }
159  
160  LLVMBool LLVMObjectFileIsSectionIteratorAtEnd(LLVMBinaryRef BR,
161                                                LLVMSectionIteratorRef SI) {
162    auto OF = cast<ObjectFile>(unwrap(BR));
163    return (*unwrap(SI) == OF->section_end()) ? 1 : 0;
164  }
165  
166  LLVMSymbolIteratorRef LLVMObjectFileCopySymbolIterator(LLVMBinaryRef BR) {
167    auto OF = cast<ObjectFile>(unwrap(BR));
168    auto symbols = OF->symbols();
169    if (symbols.begin() == symbols.end())
170      return nullptr;
171    return wrap(new symbol_iterator(symbols.begin()));
172  }
173  
174  LLVMBool LLVMObjectFileIsSymbolIteratorAtEnd(LLVMBinaryRef BR,
175                                               LLVMSymbolIteratorRef SI) {
176    auto OF = cast<ObjectFile>(unwrap(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(MemBuf));
183    Expected<std::unique_ptr<ObjectFile>> ObjOrErr(
184        ObjectFile::createObjectFile(Buf->getMemBufferRef()));
185    std::unique_ptr<ObjectFile> Obj;
186    if (!ObjOrErr) {
187      // TODO: Actually report errors helpfully.
188      consumeError(ObjOrErr.takeError());
189      return nullptr;
190    }
191  
192    auto *Ret = new OwningBinary<ObjectFile>(std::move(ObjOrErr.get()), std::move(Buf));
193    return wrap(Ret);
194  }
195  
196  void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile) {
197    delete unwrap(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(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(Sym))->getSection();
224    if (!SecOrErr) {
225     std::string Buf;
226     raw_string_ostream OS(Buf);
227     logAllUnhandledErrors(SecOrErr.takeError(), OS);
228     report_fatal_error(Twine(OS.str()));
229    }
230    *unwrap(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(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(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(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(**unwrap(Sym));
280  }
281  
282  // Section Relocation iterators
283  LLVMRelocationIteratorRef LLVMGetRelocations(LLVMSectionIteratorRef Section) {
284    relocation_iterator SI = (*unwrap(Section))->relocation_begin();
285    return wrap(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(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(Ret.takeError(), OS);
309      report_fatal_error(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(Ret.takeError(), OS);
320      report_fatal_error(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(RI))->getOffset();
332  }
333  
334  LLVMSymbolIteratorRef LLVMGetRelocationSymbol(LLVMRelocationIteratorRef RI) {
335    symbol_iterator ret = (*unwrap(RI))->getSymbol();
336    return wrap(new symbol_iterator(ret));
337  }
338  
339  uint64_t LLVMGetRelocationType(LLVMRelocationIteratorRef RI) {
340    return (*unwrap(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(RI))->getTypeName(ret);
347    char *str = static_cast<char*>(safe_malloc(ret.size()));
348    llvm::copy(ret, str);
349    return str;
350  }
351  
352  // NOTE: Caller takes ownership of returned string.
353  const char *LLVMGetRelocationValueString(LLVMRelocationIteratorRef RI) {
354    return strdup("");
355  }
356  
357