10b57cec5SDimitry Andric //===------------- JITLink.cpp - Core Run-time JIT linker APIs ------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // The LLVM Compiler Infrastructure 40b57cec5SDimitry Andric // 50b57cec5SDimitry Andric // This file is distributed under the University of Illinois Open Source 60b57cec5SDimitry Andric // License. See LICENSE.TXT for details. 70b57cec5SDimitry Andric // 80b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 90b57cec5SDimitry Andric 100b57cec5SDimitry Andric #include "llvm/ExecutionEngine/JITLink/JITLink.h" 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #include "llvm/BinaryFormat/Magic.h" 130b57cec5SDimitry Andric #include "llvm/ExecutionEngine/JITLink/MachO.h" 140b57cec5SDimitry Andric #include "llvm/Support/Format.h" 150b57cec5SDimitry Andric #include "llvm/Support/ManagedStatic.h" 160b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 170b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric using namespace llvm; 200b57cec5SDimitry Andric using namespace llvm::object; 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric #define DEBUG_TYPE "jitlink" 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric namespace { 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric enum JITLinkErrorCode { GenericJITLinkError = 1 }; 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric // FIXME: This class is only here to support the transition to llvm::Error. It 290b57cec5SDimitry Andric // will be removed once this transition is complete. Clients should prefer to 300b57cec5SDimitry Andric // deal with the Error value directly, rather than converting to error_code. 310b57cec5SDimitry Andric class JITLinkerErrorCategory : public std::error_category { 320b57cec5SDimitry Andric public: 330b57cec5SDimitry Andric const char *name() const noexcept override { return "runtimedyld"; } 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric std::string message(int Condition) const override { 360b57cec5SDimitry Andric switch (static_cast<JITLinkErrorCode>(Condition)) { 370b57cec5SDimitry Andric case GenericJITLinkError: 380b57cec5SDimitry Andric return "Generic JITLink error"; 390b57cec5SDimitry Andric } 400b57cec5SDimitry Andric llvm_unreachable("Unrecognized JITLinkErrorCode"); 410b57cec5SDimitry Andric } 420b57cec5SDimitry Andric }; 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric static ManagedStatic<JITLinkerErrorCategory> JITLinkerErrorCategory; 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric } // namespace 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric namespace llvm { 490b57cec5SDimitry Andric namespace jitlink { 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric char JITLinkError::ID = 0; 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric void JITLinkError::log(raw_ostream &OS) const { OS << ErrMsg << "\n"; } 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric std::error_code JITLinkError::convertToErrorCode() const { 560b57cec5SDimitry Andric return std::error_code(GenericJITLinkError, *JITLinkerErrorCategory); 570b57cec5SDimitry Andric } 580b57cec5SDimitry Andric 59*8bcb0991SDimitry Andric const char *getGenericEdgeKindName(Edge::Kind K) { 600b57cec5SDimitry Andric switch (K) { 610b57cec5SDimitry Andric case Edge::Invalid: 620b57cec5SDimitry Andric return "INVALID RELOCATION"; 630b57cec5SDimitry Andric case Edge::KeepAlive: 640b57cec5SDimitry Andric return "Keep-Alive"; 650b57cec5SDimitry Andric default: 660b57cec5SDimitry Andric llvm_unreachable("Unrecognized relocation kind"); 670b57cec5SDimitry Andric } 680b57cec5SDimitry Andric } 690b57cec5SDimitry Andric 70*8bcb0991SDimitry Andric const char *getLinkageName(Linkage L) { 71*8bcb0991SDimitry Andric switch (L) { 72*8bcb0991SDimitry Andric case Linkage::Strong: 73*8bcb0991SDimitry Andric return "strong"; 74*8bcb0991SDimitry Andric case Linkage::Weak: 75*8bcb0991SDimitry Andric return "weak"; 76*8bcb0991SDimitry Andric } 77*8bcb0991SDimitry Andric llvm_unreachable("Unrecognized llvm.jitlink.Linkage enum"); 78*8bcb0991SDimitry Andric } 79*8bcb0991SDimitry Andric 80*8bcb0991SDimitry Andric const char *getScopeName(Scope S) { 81*8bcb0991SDimitry Andric switch (S) { 82*8bcb0991SDimitry Andric case Scope::Default: 83*8bcb0991SDimitry Andric return "default"; 84*8bcb0991SDimitry Andric case Scope::Hidden: 85*8bcb0991SDimitry Andric return "hidden"; 86*8bcb0991SDimitry Andric case Scope::Local: 87*8bcb0991SDimitry Andric return "local"; 88*8bcb0991SDimitry Andric } 89*8bcb0991SDimitry Andric llvm_unreachable("Unrecognized llvm.jitlink.Scope enum"); 90*8bcb0991SDimitry Andric } 91*8bcb0991SDimitry Andric 92*8bcb0991SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const Block &B) { 93*8bcb0991SDimitry Andric return OS << formatv("{0:x16}", B.getAddress()) << " -- " 94*8bcb0991SDimitry Andric << formatv("{0:x16}", B.getAddress() + B.getSize()) << ": " 95*8bcb0991SDimitry Andric << (B.isZeroFill() ? "zero-fill" : "content") 96*8bcb0991SDimitry Andric << ", align = " << B.getAlignment() 97*8bcb0991SDimitry Andric << ", align-ofs = " << B.getAlignmentOffset() 98*8bcb0991SDimitry Andric << ", section = " << B.getSection().getName(); 99*8bcb0991SDimitry Andric } 100*8bcb0991SDimitry Andric 101*8bcb0991SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const Symbol &Sym) { 1020b57cec5SDimitry Andric OS << "<"; 103*8bcb0991SDimitry Andric if (Sym.getName().empty()) 104*8bcb0991SDimitry Andric OS << "*anon*"; 1050b57cec5SDimitry Andric else 106*8bcb0991SDimitry Andric OS << Sym.getName(); 107*8bcb0991SDimitry Andric OS << ": flags = "; 108*8bcb0991SDimitry Andric switch (Sym.getLinkage()) { 109*8bcb0991SDimitry Andric case Linkage::Strong: 110*8bcb0991SDimitry Andric OS << 'S'; 111*8bcb0991SDimitry Andric break; 112*8bcb0991SDimitry Andric case Linkage::Weak: 113*8bcb0991SDimitry Andric OS << 'W'; 114*8bcb0991SDimitry Andric break; 115*8bcb0991SDimitry Andric } 116*8bcb0991SDimitry Andric switch (Sym.getScope()) { 117*8bcb0991SDimitry Andric case Scope::Default: 118*8bcb0991SDimitry Andric OS << 'D'; 119*8bcb0991SDimitry Andric break; 120*8bcb0991SDimitry Andric case Scope::Hidden: 121*8bcb0991SDimitry Andric OS << 'H'; 122*8bcb0991SDimitry Andric break; 123*8bcb0991SDimitry Andric case Scope::Local: 124*8bcb0991SDimitry Andric OS << 'L'; 125*8bcb0991SDimitry Andric break; 126*8bcb0991SDimitry Andric } 127*8bcb0991SDimitry Andric OS << (Sym.isLive() ? '+' : '-') 128*8bcb0991SDimitry Andric << ", size = " << formatv("{0:x8}", Sym.getSize()) 129*8bcb0991SDimitry Andric << ", addr = " << formatv("{0:x16}", Sym.getAddress()) << " (" 130*8bcb0991SDimitry Andric << formatv("{0:x16}", Sym.getAddressable().getAddress()) << " + " 131*8bcb0991SDimitry Andric << formatv("{0:x8}", Sym.getOffset()); 132*8bcb0991SDimitry Andric if (Sym.isDefined()) 133*8bcb0991SDimitry Andric OS << " " << Sym.getBlock().getSection().getName(); 134*8bcb0991SDimitry Andric OS << ")>"; 1350b57cec5SDimitry Andric return OS; 1360b57cec5SDimitry Andric } 1370b57cec5SDimitry Andric 138*8bcb0991SDimitry Andric void printEdge(raw_ostream &OS, const Block &B, const Edge &E, 1390b57cec5SDimitry Andric StringRef EdgeKindName) { 140*8bcb0991SDimitry Andric OS << "edge@" << formatv("{0:x16}", B.getAddress() + E.getOffset()) << ": " 141*8bcb0991SDimitry Andric << formatv("{0:x16}", B.getAddress()) << " + " << E.getOffset() << " -- " 142*8bcb0991SDimitry Andric << EdgeKindName << " -> " << E.getTarget() << " + " << E.getAddend(); 1430b57cec5SDimitry Andric } 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric Section::~Section() { 146*8bcb0991SDimitry Andric for (auto *Sym : Symbols) 147*8bcb0991SDimitry Andric Sym->~Symbol(); 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric 150*8bcb0991SDimitry Andric LinkGraph::~LinkGraph() { 151*8bcb0991SDimitry Andric // Destroy blocks. 152*8bcb0991SDimitry Andric for (auto *B : Blocks) 153*8bcb0991SDimitry Andric B->~Block(); 154*8bcb0991SDimitry Andric } 155*8bcb0991SDimitry Andric 156*8bcb0991SDimitry Andric void LinkGraph::dump(raw_ostream &OS, 1570b57cec5SDimitry Andric std::function<StringRef(Edge::Kind)> EdgeKindToName) { 1580b57cec5SDimitry Andric if (!EdgeKindToName) 1590b57cec5SDimitry Andric EdgeKindToName = [](Edge::Kind K) { return StringRef(); }; 1600b57cec5SDimitry Andric 161*8bcb0991SDimitry Andric OS << "Symbols:\n"; 162*8bcb0991SDimitry Andric for (auto *Sym : defined_symbols()) { 163*8bcb0991SDimitry Andric OS << " " << format("0x%016" PRIx64, Sym->getAddress()) << ": " << *Sym 1640b57cec5SDimitry Andric << "\n"; 165*8bcb0991SDimitry Andric if (Sym->isDefined()) { 166*8bcb0991SDimitry Andric for (auto &E : Sym->getBlock().edges()) { 1670b57cec5SDimitry Andric OS << " "; 1680b57cec5SDimitry Andric StringRef EdgeName = (E.getKind() < Edge::FirstRelocation 1690b57cec5SDimitry Andric ? getGenericEdgeKindName(E.getKind()) 1700b57cec5SDimitry Andric : EdgeKindToName(E.getKind())); 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric if (!EdgeName.empty()) 173*8bcb0991SDimitry Andric printEdge(OS, Sym->getBlock(), E, EdgeName); 1740b57cec5SDimitry Andric else { 1750b57cec5SDimitry Andric auto EdgeNumberString = std::to_string(E.getKind()); 176*8bcb0991SDimitry Andric printEdge(OS, Sym->getBlock(), E, EdgeNumberString); 1770b57cec5SDimitry Andric } 1780b57cec5SDimitry Andric OS << "\n"; 1790b57cec5SDimitry Andric } 1800b57cec5SDimitry Andric } 181*8bcb0991SDimitry Andric } 1820b57cec5SDimitry Andric 183*8bcb0991SDimitry Andric OS << "Absolute symbols:\n"; 184*8bcb0991SDimitry Andric for (auto *Sym : absolute_symbols()) 185*8bcb0991SDimitry Andric OS << " " << format("0x%016" PRIx64, Sym->getAddress()) << ": " << *Sym 1860b57cec5SDimitry Andric << "\n"; 1870b57cec5SDimitry Andric 188*8bcb0991SDimitry Andric OS << "External symbols:\n"; 189*8bcb0991SDimitry Andric for (auto *Sym : external_symbols()) 190*8bcb0991SDimitry Andric OS << " " << format("0x%016" PRIx64, Sym->getAddress()) << ": " << *Sym 1910b57cec5SDimitry Andric << "\n"; 1920b57cec5SDimitry Andric } 1930b57cec5SDimitry Andric 194*8bcb0991SDimitry Andric void JITLinkAsyncLookupContinuation::anchor() {} 195*8bcb0991SDimitry Andric 1960b57cec5SDimitry Andric JITLinkContext::~JITLinkContext() {} 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric bool JITLinkContext::shouldAddDefaultTargetPasses(const Triple &TT) const { 1990b57cec5SDimitry Andric return true; 2000b57cec5SDimitry Andric } 2010b57cec5SDimitry Andric 202*8bcb0991SDimitry Andric LinkGraphPassFunction JITLinkContext::getMarkLivePass(const Triple &TT) const { 203*8bcb0991SDimitry Andric return LinkGraphPassFunction(); 2040b57cec5SDimitry Andric } 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric Error JITLinkContext::modifyPassConfig(const Triple &TT, 2070b57cec5SDimitry Andric PassConfiguration &Config) { 2080b57cec5SDimitry Andric return Error::success(); 2090b57cec5SDimitry Andric } 2100b57cec5SDimitry Andric 211*8bcb0991SDimitry Andric Error markAllSymbolsLive(LinkGraph &G) { 212*8bcb0991SDimitry Andric for (auto *Sym : G.defined_symbols()) 213*8bcb0991SDimitry Andric Sym->setLive(true); 2140b57cec5SDimitry Andric return Error::success(); 2150b57cec5SDimitry Andric } 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric void jitLink(std::unique_ptr<JITLinkContext> Ctx) { 2180b57cec5SDimitry Andric auto Magic = identify_magic(Ctx->getObjectBuffer().getBuffer()); 2190b57cec5SDimitry Andric switch (Magic) { 2200b57cec5SDimitry Andric case file_magic::macho_object: 2210b57cec5SDimitry Andric return jitLink_MachO(std::move(Ctx)); 2220b57cec5SDimitry Andric default: 2230b57cec5SDimitry Andric Ctx->notifyFailed(make_error<JITLinkError>("Unsupported file format")); 2240b57cec5SDimitry Andric }; 2250b57cec5SDimitry Andric } 2260b57cec5SDimitry Andric 2270b57cec5SDimitry Andric } // end namespace jitlink 2280b57cec5SDimitry Andric } // end namespace llvm 229