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