1 //===- Object.cpp - C bindings to the object file library--------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file defines the C bindings to the file-format-independent object
12 //===----------------------------------------------------------------------===//
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"
22 using namespace object
;
24 inline OwningBinary
<ObjectFile
> *unwrap(LLVMObjectFileRef OF
) {
25 return reinterpret_cast<OwningBinary
<ObjectFile
> *>(OF
);
28 inline LLVMObjectFileRef
wrap(const OwningBinary
<ObjectFile
> *OF
) {
29 return reinterpret_cast<LLVMObjectFileRef
>(
30 const_cast<OwningBinary
<ObjectFile
> *>(OF
));
33 inline section_iterator
*unwrap(LLVMSectionIteratorRef SI
) {
34 return reinterpret_cast<section_iterator
*>(SI
);
37 inline LLVMSectionIteratorRef
38 wrap(const section_iterator
*SI
) {
39 return reinterpret_cast<LLVMSectionIteratorRef
>
40 (const_cast<section_iterator
*>(SI
));
43 inline symbol_iterator
*unwrap(LLVMSymbolIteratorRef SI
) {
44 return reinterpret_cast<symbol_iterator
*>(SI
);
47 inline LLVMSymbolIteratorRef
48 wrap(const symbol_iterator
*SI
) {
49 return reinterpret_cast<LLVMSymbolIteratorRef
>
50 (const_cast<symbol_iterator
*>(SI
));
53 inline relocation_iterator
*unwrap(LLVMRelocationIteratorRef SI
) {
54 return reinterpret_cast<relocation_iterator
*>(SI
);
57 inline LLVMRelocationIteratorRef
58 wrap(const relocation_iterator
*SI
) {
59 return reinterpret_cast<LLVMRelocationIteratorRef
>
60 (const_cast<relocation_iterator
*>(SI
));
63 /*--.. Operations on binary files ..........................................--*/
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
));
72 *ErrorMessage
= strdup(toString(ObjOrErr
.takeError()).c_str());
76 return wrap(ObjOrErr
.get().release());
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());
86 void LLVMDisposeBinary(LLVMBinaryRef BR
) {
90 LLVMBinaryType
LLVMBinaryGetType(LLVMBinaryRef BR
) {
91 class BinaryTypeMapper final
: public Binary
{
93 static LLVMBinaryType
mapBinaryTypeToLLVMBinaryType(unsigned Kind
) {
96 return LLVMBinaryTypeArchive
;
97 case ID_MachOUniversalBinary
:
98 return LLVMBinaryTypeMachOUniversalBinary
;
99 case ID_COFFImportFile
:
100 return LLVMBinaryTypeCOFFImportFile
;
102 return LLVMBinaryTypeIR
;
104 return LLVMBinaryTypeWinRes
;
106 return LLVMBinaryTypeCOFF
;
108 return LLVMBinaryTypeELF32L
;
110 return LLVMBinaryTypeELF32B
;
112 return LLVMBinaryTypeELF64L
;
114 return LLVMBinaryTypeELF64B
;
116 return LLVMBinaryTypeMachO32L
;
118 return LLVMBinaryTypeMachO32B
;
120 return LLVMBinaryTypeMachO64L
;
122 return LLVMBinaryTypeMachO64B
;
124 return LLVMBinaryTypeOffload
;
126 return LLVMBinaryTypeWasm
;
127 case ID_StartObjects
:
129 llvm_unreachable("Marker types are not valid binary kinds!");
131 llvm_unreachable("Unknown binary kind!");
135 return BinaryTypeMapper::mapBinaryTypeToLLVMBinaryType(unwrap(BR
)->getType());
138 LLVMBinaryRef
LLVMMachOUniversalBinaryCopyObjectForArch(LLVMBinaryRef BR
,
141 char **ErrorMessage
) {
142 auto universal
= cast
<MachOUniversalBinary
>(unwrap(BR
));
143 Expected
<std::unique_ptr
<ObjectFile
>> ObjOrErr(
144 universal
->getMachOObjectForArch({Arch
, ArchLen
}));
146 *ErrorMessage
= strdup(toString(ObjOrErr
.takeError()).c_str());
149 return wrap(ObjOrErr
.get().release());
152 LLVMSectionIteratorRef
LLVMObjectFileCopySectionIterator(LLVMBinaryRef BR
) {
153 auto OF
= cast
<ObjectFile
>(unwrap(BR
));
154 auto sections
= OF
->sections();
155 if (sections
.begin() == sections
.end())
157 return wrap(new section_iterator(sections
.begin()));
160 LLVMBool
LLVMObjectFileIsSectionIteratorAtEnd(LLVMBinaryRef BR
,
161 LLVMSectionIteratorRef SI
) {
162 auto OF
= cast
<ObjectFile
>(unwrap(BR
));
163 return (*unwrap(SI
) == OF
->section_end()) ? 1 : 0;
166 LLVMSymbolIteratorRef
LLVMObjectFileCopySymbolIterator(LLVMBinaryRef BR
) {
167 auto OF
= cast
<ObjectFile
>(unwrap(BR
));
168 auto symbols
= OF
->symbols();
169 if (symbols
.begin() == symbols
.end())
171 return wrap(new symbol_iterator(symbols
.begin()));
174 LLVMBool
LLVMObjectFileIsSymbolIteratorAtEnd(LLVMBinaryRef BR
,
175 LLVMSymbolIteratorRef SI
) {
176 auto OF
= cast
<ObjectFile
>(unwrap(BR
));
177 return (*unwrap(SI
) == OF
->symbol_end()) ? 1 : 0;
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
;
187 // TODO: Actually report errors helpfully.
188 consumeError(ObjOrErr
.takeError());
192 auto *Ret
= new OwningBinary
<ObjectFile
>(std::move(ObjOrErr
.get()), std::move(Buf
));
196 void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile
) {
197 delete unwrap(ObjectFile
);
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
));
207 void LLVMDisposeSectionIterator(LLVMSectionIteratorRef SI
) {
211 LLVMBool
LLVMIsSectionIteratorAtEnd(LLVMObjectFileRef OF
,
212 LLVMSectionIteratorRef SI
) {
213 OwningBinary
<ObjectFile
> *OB
= unwrap(OF
);
214 return (*unwrap(SI
) == OB
->getBinary()->section_end()) ? 1 : 0;
217 void LLVMMoveToNextSection(LLVMSectionIteratorRef SI
) {
221 void LLVMMoveToContainingSection(LLVMSectionIteratorRef Sect
,
222 LLVMSymbolIteratorRef Sym
) {
223 Expected
<section_iterator
> SecOrErr
= (*unwrap(Sym
))->getSection();
226 raw_string_ostream
OS(Buf
);
227 logAllUnhandledErrors(SecOrErr
.takeError(), OS
);
228 report_fatal_error(Twine(OS
.str()));
230 *unwrap(Sect
) = *SecOrErr
;
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
));
240 void LLVMDisposeSymbolIterator(LLVMSymbolIteratorRef SI
) {
244 LLVMBool
LLVMIsSymbolIteratorAtEnd(LLVMObjectFileRef OF
,
245 LLVMSymbolIteratorRef SI
) {
246 OwningBinary
<ObjectFile
> *OB
= unwrap(OF
);
247 return (*unwrap(SI
) == OB
->getBinary()->symbol_end()) ? 1 : 0;
250 void LLVMMoveToNextSymbol(LLVMSymbolIteratorRef SI
) {
254 // SectionRef accessors
255 const char *LLVMGetSectionName(LLVMSectionIteratorRef SI
) {
256 auto NameOrErr
= (*unwrap(SI
))->getName();
258 report_fatal_error(NameOrErr
.takeError());
259 return NameOrErr
->data();
262 uint64_t LLVMGetSectionSize(LLVMSectionIteratorRef SI
) {
263 return (*unwrap(SI
))->getSize();
266 const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI
) {
267 if (Expected
<StringRef
> E
= (*unwrap(SI
))->getContents())
270 report_fatal_error(E
.takeError());
273 uint64_t LLVMGetSectionAddress(LLVMSectionIteratorRef SI
) {
274 return (*unwrap(SI
))->getAddress();
277 LLVMBool
LLVMGetSectionContainsSymbol(LLVMSectionIteratorRef SI
,
278 LLVMSymbolIteratorRef Sym
) {
279 return (*unwrap(SI
))->containsSymbol(**unwrap(Sym
));
282 // Section Relocation iterators
283 LLVMRelocationIteratorRef
LLVMGetRelocations(LLVMSectionIteratorRef Section
) {
284 relocation_iterator SI
= (*unwrap(Section
))->relocation_begin();
285 return wrap(new relocation_iterator(SI
));
288 void LLVMDisposeRelocationIterator(LLVMRelocationIteratorRef SI
) {
292 LLVMBool
LLVMIsRelocationIteratorAtEnd(LLVMSectionIteratorRef Section
,
293 LLVMRelocationIteratorRef SI
) {
294 return (*unwrap(SI
) == (*unwrap(Section
))->relocation_end()) ? 1 : 0;
297 void LLVMMoveToNextRelocation(LLVMRelocationIteratorRef SI
) {
302 // SymbolRef accessors
303 const char *LLVMGetSymbolName(LLVMSymbolIteratorRef SI
) {
304 Expected
<StringRef
> Ret
= (*unwrap(SI
))->getName();
307 raw_string_ostream
OS(Buf
);
308 logAllUnhandledErrors(Ret
.takeError(), OS
);
309 report_fatal_error(Twine(OS
.str()));
314 uint64_t LLVMGetSymbolAddress(LLVMSymbolIteratorRef SI
) {
315 Expected
<uint64_t> Ret
= (*unwrap(SI
))->getAddress();
318 raw_string_ostream
OS(Buf
);
319 logAllUnhandledErrors(Ret
.takeError(), OS
);
320 report_fatal_error(Twine(OS
.str()));
325 uint64_t LLVMGetSymbolSize(LLVMSymbolIteratorRef SI
) {
326 return (*unwrap(SI
))->getCommonSize();
329 // RelocationRef accessors
330 uint64_t LLVMGetRelocationOffset(LLVMRelocationIteratorRef RI
) {
331 return (*unwrap(RI
))->getOffset();
334 LLVMSymbolIteratorRef
LLVMGetRelocationSymbol(LLVMRelocationIteratorRef RI
) {
335 symbol_iterator ret
= (*unwrap(RI
))->getSymbol();
336 return wrap(new symbol_iterator(ret
));
339 uint64_t LLVMGetRelocationType(LLVMRelocationIteratorRef RI
) {
340 return (*unwrap(RI
))->getType();
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
);
352 // NOTE: Caller takes ownership of returned string.
353 const char *LLVMGetRelocationValueString(LLVMRelocationIteratorRef RI
) {