| //===- Object.cpp - C bindings to the object file library--------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file defines the C bindings to the file-format-independent object |
| // library. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "llvm-c/Object.h" |
| #include "llvm/ADT/SmallVector.h" |
| #include "llvm/IR/LLVMContext.h" |
| #include "llvm/Object/ObjectFile.h" |
| #include "llvm/Object/MachOUniversal.h" |
| |
| using namespace llvm; |
| using namespace object; |
| |
| inline OwningBinary<ObjectFile> *unwrap(LLVMObjectFileRef OF) { |
| return reinterpret_cast<OwningBinary<ObjectFile> *>(OF); |
| } |
| |
| inline LLVMObjectFileRef wrap(const OwningBinary<ObjectFile> *OF) { |
| return reinterpret_cast<LLVMObjectFileRef>( |
| const_cast<OwningBinary<ObjectFile> *>(OF)); |
| } |
| |
| inline section_iterator *unwrap(LLVMSectionIteratorRef SI) { |
| return reinterpret_cast<section_iterator*>(SI); |
| } |
| |
| inline LLVMSectionIteratorRef |
| wrap(const section_iterator *SI) { |
| return reinterpret_cast<LLVMSectionIteratorRef> |
| (const_cast<section_iterator*>(SI)); |
| } |
| |
| inline symbol_iterator *unwrap(LLVMSymbolIteratorRef SI) { |
| return reinterpret_cast<symbol_iterator*>(SI); |
| } |
| |
| inline LLVMSymbolIteratorRef |
| wrap(const symbol_iterator *SI) { |
| return reinterpret_cast<LLVMSymbolIteratorRef> |
| (const_cast<symbol_iterator*>(SI)); |
| } |
| |
| inline relocation_iterator *unwrap(LLVMRelocationIteratorRef SI) { |
| return reinterpret_cast<relocation_iterator*>(SI); |
| } |
| |
| inline LLVMRelocationIteratorRef |
| wrap(const relocation_iterator *SI) { |
| return reinterpret_cast<LLVMRelocationIteratorRef> |
| (const_cast<relocation_iterator*>(SI)); |
| } |
| |
| /*--.. Operations on binary files ..........................................--*/ |
| |
| LLVMBinaryRef LLVMCreateBinary(LLVMMemoryBufferRef MemBuf, |
| LLVMContextRef Context, |
| char **ErrorMessage) { |
| auto maybeContext = Context ? unwrap(Context) : nullptr; |
| Expected<std::unique_ptr<Binary>> ObjOrErr( |
| createBinary(unwrap(MemBuf)->getMemBufferRef(), maybeContext)); |
| if (!ObjOrErr) { |
| *ErrorMessage = strdup(toString(ObjOrErr.takeError()).c_str()); |
| return nullptr; |
| } |
| |
| return wrap(ObjOrErr.get().release()); |
| } |
| |
| LLVMMemoryBufferRef LLVMBinaryCopyMemoryBuffer(LLVMBinaryRef BR) { |
| auto Buf = unwrap(BR)->getMemoryBufferRef(); |
| return wrap(llvm::MemoryBuffer::getMemBuffer( |
| Buf.getBuffer(), Buf.getBufferIdentifier(), |
| /*RequiresNullTerminator*/false).release()); |
| } |
| |
| void LLVMDisposeBinary(LLVMBinaryRef BR) { |
| delete unwrap(BR); |
| } |
| |
| LLVMBinaryType LLVMBinaryGetType(LLVMBinaryRef BR) { |
| class BinaryTypeMapper final : public Binary { |
| public: |
| static LLVMBinaryType mapBinaryTypeToLLVMBinaryType(unsigned Kind) { |
| switch (Kind) { |
| case ID_Archive: |
| return LLVMBinaryTypeArchive; |
| case ID_MachOUniversalBinary: |
| return LLVMBinaryTypeMachOUniversalBinary; |
| case ID_COFFImportFile: |
| return LLVMBinaryTypeCOFFImportFile; |
| case ID_IR: |
| return LLVMBinaryTypeIR; |
| case ID_WinRes: |
| return LLVMBinaryTypeWinRes; |
| case ID_COFF: |
| return LLVMBinaryTypeCOFF; |
| case ID_ELF32L: |
| return LLVMBinaryTypeELF32L; |
| case ID_ELF32B: |
| return LLVMBinaryTypeELF32B; |
| case ID_ELF64L: |
| return LLVMBinaryTypeELF64L; |
| case ID_ELF64B: |
| return LLVMBinaryTypeELF64B; |
| case ID_MachO32L: |
| return LLVMBinaryTypeMachO32L; |
| case ID_MachO32B: |
| return LLVMBinaryTypeMachO32B; |
| case ID_MachO64L: |
| return LLVMBinaryTypeMachO64L; |
| case ID_MachO64B: |
| return LLVMBinaryTypeMachO64B; |
| case ID_Wasm: |
| return LLVMBinaryTypeWasm; |
| case ID_StartObjects: |
| case ID_EndObjects: |
| llvm_unreachable("Marker types are not valid binary kinds!"); |
| default: |
| llvm_unreachable("Unknown binary kind!"); |
| } |
| } |
| }; |
| return BinaryTypeMapper::mapBinaryTypeToLLVMBinaryType(unwrap(BR)->getType()); |
| } |
| |
| LLVMBinaryRef LLVMMachOUniversalBinaryCopyObjectForArch(LLVMBinaryRef BR, |
| const char *Arch, |
| size_t ArchLen, |
| char **ErrorMessage) { |
| auto universal = cast<MachOUniversalBinary>(unwrap(BR)); |
| Expected<std::unique_ptr<ObjectFile>> ObjOrErr( |
| universal->getMachOObjectForArch({Arch, ArchLen})); |
| if (!ObjOrErr) { |
| *ErrorMessage = strdup(toString(ObjOrErr.takeError()).c_str()); |
| return nullptr; |
| } |
| return wrap(ObjOrErr.get().release()); |
| } |
| |
| LLVMSectionIteratorRef LLVMObjectFileCopySectionIterator(LLVMBinaryRef BR) { |
| auto OF = cast<ObjectFile>(unwrap(BR)); |
| auto sections = OF->sections(); |
| if (sections.begin() == sections.end()) |
| return nullptr; |
| return wrap(new section_iterator(sections.begin())); |
| } |
| |
| LLVMBool LLVMObjectFileIsSectionIteratorAtEnd(LLVMBinaryRef BR, |
| LLVMSectionIteratorRef SI) { |
| auto OF = cast<ObjectFile>(unwrap(BR)); |
| return (*unwrap(SI) == OF->section_end()) ? 1 : 0; |
| } |
| |
| LLVMSymbolIteratorRef LLVMObjectFileCopySymbolIterator(LLVMBinaryRef BR) { |
| auto OF = cast<ObjectFile>(unwrap(BR)); |
| auto symbols = OF->symbols(); |
| if (symbols.begin() == symbols.end()) |
| return nullptr; |
| return wrap(new symbol_iterator(symbols.begin())); |
| } |
| |
| LLVMBool LLVMObjectFileIsSymbolIteratorAtEnd(LLVMBinaryRef BR, |
| LLVMSymbolIteratorRef SI) { |
| auto OF = cast<ObjectFile>(unwrap(BR)); |
| return (*unwrap(SI) == OF->symbol_end()) ? 1 : 0; |
| } |
| |
| // ObjectFile creation |
| LLVMObjectFileRef LLVMCreateObjectFile(LLVMMemoryBufferRef MemBuf) { |
| std::unique_ptr<MemoryBuffer> Buf(unwrap(MemBuf)); |
| Expected<std::unique_ptr<ObjectFile>> ObjOrErr( |
| ObjectFile::createObjectFile(Buf->getMemBufferRef())); |
| std::unique_ptr<ObjectFile> Obj; |
| if (!ObjOrErr) { |
| // TODO: Actually report errors helpfully. |
| consumeError(ObjOrErr.takeError()); |
| return nullptr; |
| } |
| |
| auto *Ret = new OwningBinary<ObjectFile>(std::move(ObjOrErr.get()), std::move(Buf)); |
| return wrap(Ret); |
| } |
| |
| void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile) { |
| delete unwrap(ObjectFile); |
| } |
| |
| // ObjectFile Section iterators |
| LLVMSectionIteratorRef LLVMGetSections(LLVMObjectFileRef OF) { |
| OwningBinary<ObjectFile> *OB = unwrap(OF); |
| section_iterator SI = OB->getBinary()->section_begin(); |
| return wrap(new section_iterator(SI)); |
| } |
| |
| void LLVMDisposeSectionIterator(LLVMSectionIteratorRef SI) { |
| delete unwrap(SI); |
| } |
| |
| LLVMBool LLVMIsSectionIteratorAtEnd(LLVMObjectFileRef OF, |
| LLVMSectionIteratorRef SI) { |
| OwningBinary<ObjectFile> *OB = unwrap(OF); |
| return (*unwrap(SI) == OB->getBinary()->section_end()) ? 1 : 0; |
| } |
| |
| void LLVMMoveToNextSection(LLVMSectionIteratorRef SI) { |
| ++(*unwrap(SI)); |
| } |
| |
| void LLVMMoveToContainingSection(LLVMSectionIteratorRef Sect, |
| LLVMSymbolIteratorRef Sym) { |
| Expected<section_iterator> SecOrErr = (*unwrap(Sym))->getSection(); |
| if (!SecOrErr) { |
| std::string Buf; |
| raw_string_ostream OS(Buf); |
| logAllUnhandledErrors(SecOrErr.takeError(), OS); |
| OS.flush(); |
| report_fatal_error(Buf); |
| } |
| *unwrap(Sect) = *SecOrErr; |
| } |
| |
| // ObjectFile Symbol iterators |
| LLVMSymbolIteratorRef LLVMGetSymbols(LLVMObjectFileRef OF) { |
| OwningBinary<ObjectFile> *OB = unwrap(OF); |
| symbol_iterator SI = OB->getBinary()->symbol_begin(); |
| return wrap(new symbol_iterator(SI)); |
| } |
| |
| void LLVMDisposeSymbolIterator(LLVMSymbolIteratorRef SI) { |
| delete unwrap(SI); |
| } |
| |
| LLVMBool LLVMIsSymbolIteratorAtEnd(LLVMObjectFileRef OF, |
| LLVMSymbolIteratorRef SI) { |
| OwningBinary<ObjectFile> *OB = unwrap(OF); |
| return (*unwrap(SI) == OB->getBinary()->symbol_end()) ? 1 : 0; |
| } |
| |
| void LLVMMoveToNextSymbol(LLVMSymbolIteratorRef SI) { |
| ++(*unwrap(SI)); |
| } |
| |
| // SectionRef accessors |
| const char *LLVMGetSectionName(LLVMSectionIteratorRef SI) { |
| auto NameOrErr = (*unwrap(SI))->getName(); |
| if (!NameOrErr) |
| report_fatal_error(NameOrErr.takeError()); |
| return NameOrErr->data(); |
| } |
| |
| uint64_t LLVMGetSectionSize(LLVMSectionIteratorRef SI) { |
| return (*unwrap(SI))->getSize(); |
| } |
| |
| const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI) { |
| if (Expected<StringRef> E = (*unwrap(SI))->getContents()) |
| return E->data(); |
| else |
| report_fatal_error(E.takeError()); |
| } |
| |
| uint64_t LLVMGetSectionAddress(LLVMSectionIteratorRef SI) { |
| return (*unwrap(SI))->getAddress(); |
| } |
| |
| LLVMBool LLVMGetSectionContainsSymbol(LLVMSectionIteratorRef SI, |
| LLVMSymbolIteratorRef Sym) { |
| return (*unwrap(SI))->containsSymbol(**unwrap(Sym)); |
| } |
| |
| // Section Relocation iterators |
| LLVMRelocationIteratorRef LLVMGetRelocations(LLVMSectionIteratorRef Section) { |
| relocation_iterator SI = (*unwrap(Section))->relocation_begin(); |
| return wrap(new relocation_iterator(SI)); |
| } |
| |
| void LLVMDisposeRelocationIterator(LLVMRelocationIteratorRef SI) { |
| delete unwrap(SI); |
| } |
| |
| LLVMBool LLVMIsRelocationIteratorAtEnd(LLVMSectionIteratorRef Section, |
| LLVMRelocationIteratorRef SI) { |
| return (*unwrap(SI) == (*unwrap(Section))->relocation_end()) ? 1 : 0; |
| } |
| |
| void LLVMMoveToNextRelocation(LLVMRelocationIteratorRef SI) { |
| ++(*unwrap(SI)); |
| } |
| |
| |
| // SymbolRef accessors |
| const char *LLVMGetSymbolName(LLVMSymbolIteratorRef SI) { |
| Expected<StringRef> Ret = (*unwrap(SI))->getName(); |
| if (!Ret) { |
| std::string Buf; |
| raw_string_ostream OS(Buf); |
| logAllUnhandledErrors(Ret.takeError(), OS); |
| OS.flush(); |
| report_fatal_error(Buf); |
| } |
| return Ret->data(); |
| } |
| |
| uint64_t LLVMGetSymbolAddress(LLVMSymbolIteratorRef SI) { |
| Expected<uint64_t> Ret = (*unwrap(SI))->getAddress(); |
| if (!Ret) { |
| std::string Buf; |
| raw_string_ostream OS(Buf); |
| logAllUnhandledErrors(Ret.takeError(), OS); |
| OS.flush(); |
| report_fatal_error(Buf); |
| } |
| return *Ret; |
| } |
| |
| uint64_t LLVMGetSymbolSize(LLVMSymbolIteratorRef SI) { |
| return (*unwrap(SI))->getCommonSize(); |
| } |
| |
| // RelocationRef accessors |
| uint64_t LLVMGetRelocationOffset(LLVMRelocationIteratorRef RI) { |
| return (*unwrap(RI))->getOffset(); |
| } |
| |
| LLVMSymbolIteratorRef LLVMGetRelocationSymbol(LLVMRelocationIteratorRef RI) { |
| symbol_iterator ret = (*unwrap(RI))->getSymbol(); |
| return wrap(new symbol_iterator(ret)); |
| } |
| |
| uint64_t LLVMGetRelocationType(LLVMRelocationIteratorRef RI) { |
| return (*unwrap(RI))->getType(); |
| } |
| |
| // NOTE: Caller takes ownership of returned string. |
| const char *LLVMGetRelocationTypeName(LLVMRelocationIteratorRef RI) { |
| SmallVector<char, 0> ret; |
| (*unwrap(RI))->getTypeName(ret); |
| char *str = static_cast<char*>(safe_malloc(ret.size())); |
| llvm::copy(ret, str); |
| return str; |
| } |
| |
| // NOTE: Caller takes ownership of returned string. |
| const char *LLVMGetRelocationValueString(LLVMRelocationIteratorRef RI) { |
| return strdup(""); |
| } |
| |