358 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// This file defines the C bindings to the file-format-independent object10// 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 21using namespace llvm;22using namespace object;23 24inline OwningBinary<ObjectFile> *unwrap(LLVMObjectFileRef OF) {25 return reinterpret_cast<OwningBinary<ObjectFile> *>(OF);26}27 28inline LLVMObjectFileRef wrap(const OwningBinary<ObjectFile> *OF) {29 return reinterpret_cast<LLVMObjectFileRef>(30 const_cast<OwningBinary<ObjectFile> *>(OF));31}32 33inline section_iterator *unwrap(LLVMSectionIteratorRef SI) {34 return reinterpret_cast<section_iterator*>(SI);35}36 37inline LLVMSectionIteratorRef38wrap(const section_iterator *SI) {39 return reinterpret_cast<LLVMSectionIteratorRef>40 (const_cast<section_iterator*>(SI));41}42 43inline symbol_iterator *unwrap(LLVMSymbolIteratorRef SI) {44 return reinterpret_cast<symbol_iterator*>(SI);45}46 47inline LLVMSymbolIteratorRef48wrap(const symbol_iterator *SI) {49 return reinterpret_cast<LLVMSymbolIteratorRef>50 (const_cast<symbol_iterator*>(SI));51}52 53inline relocation_iterator *unwrap(LLVMRelocationIteratorRef SI) {54 return reinterpret_cast<relocation_iterator*>(SI);55}56 57inline LLVMRelocationIteratorRef58wrap(const relocation_iterator *SI) {59 return reinterpret_cast<LLVMRelocationIteratorRef>60 (const_cast<relocation_iterator*>(SI));61}62 63/*--.. Operations on binary files ..........................................--*/64 65LLVMBinaryRef 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 79LLVMMemoryBufferRef 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 86void LLVMDisposeBinary(LLVMBinaryRef BR) {87 delete unwrap(BR);88}89 90LLVMBinaryType 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_DXContainer:128 return LLVMBinaryTypeDXcontainer;129 case ID_StartObjects:130 case ID_EndObjects:131 llvm_unreachable("Marker types are not valid binary kinds!");132 default:133 llvm_unreachable("Unknown binary kind!");134 }135 }136 };137 return BinaryTypeMapper::mapBinaryTypeToLLVMBinaryType(unwrap(BR)->getType());138}139 140LLVMBinaryRef LLVMMachOUniversalBinaryCopyObjectForArch(LLVMBinaryRef BR,141 const char *Arch,142 size_t ArchLen,143 char **ErrorMessage) {144 auto universal = cast<MachOUniversalBinary>(unwrap(BR));145 Expected<std::unique_ptr<ObjectFile>> ObjOrErr(146 universal->getMachOObjectForArch({Arch, ArchLen}));147 if (!ObjOrErr) {148 *ErrorMessage = strdup(toString(ObjOrErr.takeError()).c_str());149 return nullptr;150 }151 return wrap(ObjOrErr.get().release());152}153 154LLVMSectionIteratorRef LLVMObjectFileCopySectionIterator(LLVMBinaryRef BR) {155 auto OF = cast<ObjectFile>(unwrap(BR));156 auto sections = OF->sections();157 if (sections.begin() == sections.end())158 return nullptr;159 return wrap(new section_iterator(sections.begin()));160}161 162LLVMBool LLVMObjectFileIsSectionIteratorAtEnd(LLVMBinaryRef BR,163 LLVMSectionIteratorRef SI) {164 auto OF = cast<ObjectFile>(unwrap(BR));165 return (*unwrap(SI) == OF->section_end()) ? 1 : 0;166}167 168LLVMSymbolIteratorRef LLVMObjectFileCopySymbolIterator(LLVMBinaryRef BR) {169 auto OF = cast<ObjectFile>(unwrap(BR));170 auto symbols = OF->symbols();171 if (symbols.begin() == symbols.end())172 return nullptr;173 return wrap(new symbol_iterator(symbols.begin()));174}175 176LLVMBool LLVMObjectFileIsSymbolIteratorAtEnd(LLVMBinaryRef BR,177 LLVMSymbolIteratorRef SI) {178 auto OF = cast<ObjectFile>(unwrap(BR));179 return (*unwrap(SI) == OF->symbol_end()) ? 1 : 0;180}181 182// ObjectFile creation183LLVMObjectFileRef LLVMCreateObjectFile(LLVMMemoryBufferRef MemBuf) {184 std::unique_ptr<MemoryBuffer> Buf(unwrap(MemBuf));185 Expected<std::unique_ptr<ObjectFile>> ObjOrErr(186 ObjectFile::createObjectFile(Buf->getMemBufferRef()));187 if (!ObjOrErr) {188 // TODO: Actually report errors helpfully.189 consumeError(ObjOrErr.takeError());190 return nullptr;191 }192 193 auto *Ret = new OwningBinary<ObjectFile>(std::move(ObjOrErr.get()), std::move(Buf));194 return wrap(Ret);195}196 197void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile) {198 delete unwrap(ObjectFile);199}200 201// ObjectFile Section iterators202LLVMSectionIteratorRef LLVMGetSections(LLVMObjectFileRef OF) {203 OwningBinary<ObjectFile> *OB = unwrap(OF);204 section_iterator SI = OB->getBinary()->section_begin();205 return wrap(new section_iterator(SI));206}207 208void LLVMDisposeSectionIterator(LLVMSectionIteratorRef SI) {209 delete unwrap(SI);210}211 212LLVMBool LLVMIsSectionIteratorAtEnd(LLVMObjectFileRef OF,213 LLVMSectionIteratorRef SI) {214 OwningBinary<ObjectFile> *OB = unwrap(OF);215 return (*unwrap(SI) == OB->getBinary()->section_end()) ? 1 : 0;216}217 218void LLVMMoveToNextSection(LLVMSectionIteratorRef SI) {219 ++(*unwrap(SI));220}221 222void LLVMMoveToContainingSection(LLVMSectionIteratorRef Sect,223 LLVMSymbolIteratorRef Sym) {224 Expected<section_iterator> SecOrErr = (*unwrap(Sym))->getSection();225 if (!SecOrErr) {226 std::string Buf;227 raw_string_ostream OS(Buf);228 logAllUnhandledErrors(SecOrErr.takeError(), OS);229 report_fatal_error(Twine(OS.str()));230 }231 *unwrap(Sect) = *SecOrErr;232}233 234// ObjectFile Symbol iterators235LLVMSymbolIteratorRef LLVMGetSymbols(LLVMObjectFileRef OF) {236 OwningBinary<ObjectFile> *OB = unwrap(OF);237 symbol_iterator SI = OB->getBinary()->symbol_begin();238 return wrap(new symbol_iterator(SI));239}240 241void LLVMDisposeSymbolIterator(LLVMSymbolIteratorRef SI) {242 delete unwrap(SI);243}244 245LLVMBool LLVMIsSymbolIteratorAtEnd(LLVMObjectFileRef OF,246 LLVMSymbolIteratorRef SI) {247 OwningBinary<ObjectFile> *OB = unwrap(OF);248 return (*unwrap(SI) == OB->getBinary()->symbol_end()) ? 1 : 0;249}250 251void LLVMMoveToNextSymbol(LLVMSymbolIteratorRef SI) {252 ++(*unwrap(SI));253}254 255// SectionRef accessors256const char *LLVMGetSectionName(LLVMSectionIteratorRef SI) {257 auto NameOrErr = (*unwrap(SI))->getName();258 if (!NameOrErr)259 report_fatal_error(NameOrErr.takeError());260 return NameOrErr->data();261}262 263uint64_t LLVMGetSectionSize(LLVMSectionIteratorRef SI) {264 return (*unwrap(SI))->getSize();265}266 267const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI) {268 if (Expected<StringRef> E = (*unwrap(SI))->getContents())269 return E->data();270 else271 report_fatal_error(E.takeError());272}273 274uint64_t LLVMGetSectionAddress(LLVMSectionIteratorRef SI) {275 return (*unwrap(SI))->getAddress();276}277 278LLVMBool LLVMGetSectionContainsSymbol(LLVMSectionIteratorRef SI,279 LLVMSymbolIteratorRef Sym) {280 return (*unwrap(SI))->containsSymbol(**unwrap(Sym));281}282 283// Section Relocation iterators284LLVMRelocationIteratorRef LLVMGetRelocations(LLVMSectionIteratorRef Section) {285 relocation_iterator SI = (*unwrap(Section))->relocation_begin();286 return wrap(new relocation_iterator(SI));287}288 289void LLVMDisposeRelocationIterator(LLVMRelocationIteratorRef SI) {290 delete unwrap(SI);291}292 293LLVMBool LLVMIsRelocationIteratorAtEnd(LLVMSectionIteratorRef Section,294 LLVMRelocationIteratorRef SI) {295 return (*unwrap(SI) == (*unwrap(Section))->relocation_end()) ? 1 : 0;296}297 298void LLVMMoveToNextRelocation(LLVMRelocationIteratorRef SI) {299 ++(*unwrap(SI));300}301 302 303// SymbolRef accessors304const char *LLVMGetSymbolName(LLVMSymbolIteratorRef SI) {305 Expected<StringRef> Ret = (*unwrap(SI))->getName();306 if (!Ret) {307 std::string Buf;308 raw_string_ostream OS(Buf);309 logAllUnhandledErrors(Ret.takeError(), OS);310 report_fatal_error(Twine(OS.str()));311 }312 return Ret->data();313}314 315uint64_t LLVMGetSymbolAddress(LLVMSymbolIteratorRef SI) {316 Expected<uint64_t> Ret = (*unwrap(SI))->getAddress();317 if (!Ret) {318 std::string Buf;319 raw_string_ostream OS(Buf);320 logAllUnhandledErrors(Ret.takeError(), OS);321 report_fatal_error(Twine(OS.str()));322 }323 return *Ret;324}325 326uint64_t LLVMGetSymbolSize(LLVMSymbolIteratorRef SI) {327 return (*unwrap(SI))->getCommonSize();328}329 330// RelocationRef accessors331uint64_t LLVMGetRelocationOffset(LLVMRelocationIteratorRef RI) {332 return (*unwrap(RI))->getOffset();333}334 335LLVMSymbolIteratorRef LLVMGetRelocationSymbol(LLVMRelocationIteratorRef RI) {336 symbol_iterator ret = (*unwrap(RI))->getSymbol();337 return wrap(new symbol_iterator(ret));338}339 340uint64_t LLVMGetRelocationType(LLVMRelocationIteratorRef RI) {341 return (*unwrap(RI))->getType();342}343 344// NOTE: Caller takes ownership of returned string.345const char *LLVMGetRelocationTypeName(LLVMRelocationIteratorRef RI) {346 SmallVector<char, 0> ret;347 (*unwrap(RI))->getTypeName(ret);348 char *str = static_cast<char*>(safe_malloc(ret.size()));349 llvm::copy(ret, str);350 return str;351}352 353// NOTE: Caller takes ownership of returned string.354const char *LLVMGetRelocationValueString(LLVMRelocationIteratorRef RI) {355 return strdup("");356}357 358