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"
21 using namespace object
;
23 inline OwningBinary
<ObjectFile
> *unwrap(LLVMObjectFileRef OF
) {
24 return reinterpret_cast<OwningBinary
<ObjectFile
> *>(OF
);
27 inline LLVMObjectFileRef
wrap(const OwningBinary
<ObjectFile
> *OF
) {
28 return reinterpret_cast<LLVMObjectFileRef
>(
29 const_cast<OwningBinary
<ObjectFile
> *>(OF
));
32 inline section_iterator
*unwrap(LLVMSectionIteratorRef SI
) {
33 return reinterpret_cast<section_iterator
*>(SI
);
36 inline LLVMSectionIteratorRef
37 wrap(const section_iterator
*SI
) {
38 return reinterpret_cast<LLVMSectionIteratorRef
>
39 (const_cast<section_iterator
*>(SI
));
42 inline symbol_iterator
*unwrap(LLVMSymbolIteratorRef SI
) {
43 return reinterpret_cast<symbol_iterator
*>(SI
);
46 inline LLVMSymbolIteratorRef
47 wrap(const symbol_iterator
*SI
) {
48 return reinterpret_cast<LLVMSymbolIteratorRef
>
49 (const_cast<symbol_iterator
*>(SI
));
52 inline relocation_iterator
*unwrap(LLVMRelocationIteratorRef SI
) {
53 return reinterpret_cast<relocation_iterator
*>(SI
);
56 inline LLVMRelocationIteratorRef
57 wrap(const relocation_iterator
*SI
) {
58 return reinterpret_cast<LLVMRelocationIteratorRef
>
59 (const_cast<relocation_iterator
*>(SI
));
62 /*--.. Operations on binary files ..........................................--*/
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
));
71 *ErrorMessage
= strdup(toString(ObjOrErr
.takeError()).c_str());
75 return wrap(ObjOrErr
.get().release());
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());
85 void LLVMDisposeBinary(LLVMBinaryRef BR
) {
89 LLVMBinaryType
LLVMBinaryGetType(LLVMBinaryRef BR
) {
90 class BinaryTypeMapper final
: public Binary
{
92 static LLVMBinaryType
mapBinaryTypeToLLVMBinaryType(unsigned Kind
) {
95 return LLVMBinaryTypeArchive
;
96 case ID_MachOUniversalBinary
:
97 return LLVMBinaryTypeMachOUniversalBinary
;
98 case ID_COFFImportFile
:
99 return LLVMBinaryTypeCOFFImportFile
;
101 return LLVMBinaryTypeIR
;
103 return LLVMBinaryTypeWinRes
;
105 return LLVMBinaryTypeCOFF
;
107 return LLVMBinaryTypeELF32L
;
109 return LLVMBinaryTypeELF32B
;
111 return LLVMBinaryTypeELF64L
;
113 return LLVMBinaryTypeELF64B
;
115 return LLVMBinaryTypeMachO32L
;
117 return LLVMBinaryTypeMachO32B
;
119 return LLVMBinaryTypeMachO64L
;
121 return LLVMBinaryTypeMachO64B
;
123 return LLVMBinaryTypeWasm
;
124 case ID_StartObjects
:
126 llvm_unreachable("Marker types are not valid binary kinds!");
128 llvm_unreachable("Unknown binary kind!");
132 return BinaryTypeMapper::mapBinaryTypeToLLVMBinaryType(unwrap(BR
)->getType());
135 LLVMBinaryRef
LLVMMachOUniversalBinaryCopyObjectForArch(LLVMBinaryRef BR
,
138 char **ErrorMessage
) {
139 auto universal
= cast
<MachOUniversalBinary
>(unwrap(BR
));
140 Expected
<std::unique_ptr
<ObjectFile
>> ObjOrErr(
141 universal
->getObjectForArch({Arch
, ArchLen
}));
143 *ErrorMessage
= strdup(toString(ObjOrErr
.takeError()).c_str());
146 return wrap(ObjOrErr
.get().release());
149 LLVMSectionIteratorRef
LLVMObjectFileCopySectionIterator(LLVMBinaryRef BR
) {
150 auto OF
= cast
<ObjectFile
>(unwrap(BR
));
151 auto sections
= OF
->sections();
152 if (sections
.begin() == sections
.end())
154 return wrap(new section_iterator(sections
.begin()));
157 LLVMBool
LLVMObjectFileIsSectionIteratorAtEnd(LLVMBinaryRef BR
,
158 LLVMSectionIteratorRef SI
) {
159 auto OF
= cast
<ObjectFile
>(unwrap(BR
));
160 return (*unwrap(SI
) == OF
->section_end()) ? 1 : 0;
163 LLVMSymbolIteratorRef
LLVMObjectFileCopySymbolIterator(LLVMBinaryRef BR
) {
164 auto OF
= cast
<ObjectFile
>(unwrap(BR
));
165 auto symbols
= OF
->symbols();
166 if (symbols
.begin() == symbols
.end())
168 return wrap(new symbol_iterator(symbols
.begin()));
171 LLVMBool
LLVMObjectFileIsSymbolIteratorAtEnd(LLVMBinaryRef BR
,
172 LLVMSymbolIteratorRef SI
) {
173 auto OF
= cast
<ObjectFile
>(unwrap(BR
));
174 return (*unwrap(SI
) == OF
->symbol_end()) ? 1 : 0;
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
;
184 // TODO: Actually report errors helpfully.
185 consumeError(ObjOrErr
.takeError());
189 auto *Ret
= new OwningBinary
<ObjectFile
>(std::move(ObjOrErr
.get()), std::move(Buf
));
193 void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile
) {
194 delete unwrap(ObjectFile
);
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
));
204 void LLVMDisposeSectionIterator(LLVMSectionIteratorRef SI
) {
208 LLVMBool
LLVMIsSectionIteratorAtEnd(LLVMObjectFileRef OF
,
209 LLVMSectionIteratorRef SI
) {
210 OwningBinary
<ObjectFile
> *OB
= unwrap(OF
);
211 return (*unwrap(SI
) == OB
->getBinary()->section_end()) ? 1 : 0;
214 void LLVMMoveToNextSection(LLVMSectionIteratorRef SI
) {
218 void LLVMMoveToContainingSection(LLVMSectionIteratorRef Sect
,
219 LLVMSymbolIteratorRef Sym
) {
220 Expected
<section_iterator
> SecOrErr
= (*unwrap(Sym
))->getSection();
223 raw_string_ostream
OS(Buf
);
224 logAllUnhandledErrors(SecOrErr
.takeError(), OS
);
226 report_fatal_error(Buf
);
228 *unwrap(Sect
) = *SecOrErr
;
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
));
238 void LLVMDisposeSymbolIterator(LLVMSymbolIteratorRef SI
) {
242 LLVMBool
LLVMIsSymbolIteratorAtEnd(LLVMObjectFileRef OF
,
243 LLVMSymbolIteratorRef SI
) {
244 OwningBinary
<ObjectFile
> *OB
= unwrap(OF
);
245 return (*unwrap(SI
) == OB
->getBinary()->symbol_end()) ? 1 : 0;
248 void LLVMMoveToNextSymbol(LLVMSymbolIteratorRef SI
) {
252 // SectionRef accessors
253 const char *LLVMGetSectionName(LLVMSectionIteratorRef SI
) {
255 if (std::error_code ec
= (*unwrap(SI
))->getName(ret
))
256 report_fatal_error(ec
.message());
260 uint64_t LLVMGetSectionSize(LLVMSectionIteratorRef SI
) {
261 return (*unwrap(SI
))->getSize();
264 const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI
) {
265 if (Expected
<StringRef
> E
= (*unwrap(SI
))->getContents())
268 report_fatal_error(E
.takeError());
271 uint64_t LLVMGetSectionAddress(LLVMSectionIteratorRef SI
) {
272 return (*unwrap(SI
))->getAddress();
275 LLVMBool
LLVMGetSectionContainsSymbol(LLVMSectionIteratorRef SI
,
276 LLVMSymbolIteratorRef Sym
) {
277 return (*unwrap(SI
))->containsSymbol(**unwrap(Sym
));
280 // Section Relocation iterators
281 LLVMRelocationIteratorRef
LLVMGetRelocations(LLVMSectionIteratorRef Section
) {
282 relocation_iterator SI
= (*unwrap(Section
))->relocation_begin();
283 return wrap(new relocation_iterator(SI
));
286 void LLVMDisposeRelocationIterator(LLVMRelocationIteratorRef SI
) {
290 LLVMBool
LLVMIsRelocationIteratorAtEnd(LLVMSectionIteratorRef Section
,
291 LLVMRelocationIteratorRef SI
) {
292 return (*unwrap(SI
) == (*unwrap(Section
))->relocation_end()) ? 1 : 0;
295 void LLVMMoveToNextRelocation(LLVMRelocationIteratorRef SI
) {
300 // SymbolRef accessors
301 const char *LLVMGetSymbolName(LLVMSymbolIteratorRef SI
) {
302 Expected
<StringRef
> Ret
= (*unwrap(SI
))->getName();
305 raw_string_ostream
OS(Buf
);
306 logAllUnhandledErrors(Ret
.takeError(), OS
);
308 report_fatal_error(Buf
);
313 uint64_t LLVMGetSymbolAddress(LLVMSymbolIteratorRef SI
) {
314 Expected
<uint64_t> Ret
= (*unwrap(SI
))->getAddress();
317 raw_string_ostream
OS(Buf
);
318 logAllUnhandledErrors(Ret
.takeError(), OS
);
320 report_fatal_error(Buf
);
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
) {