1*0b57cec5SDimitry Andric //===------------- JITLink.cpp - Core Run-time JIT linker APIs ------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // The LLVM Compiler Infrastructure 4*0b57cec5SDimitry Andric // 5*0b57cec5SDimitry Andric // This file is distributed under the University of Illinois Open Source 6*0b57cec5SDimitry Andric // License. See LICENSE.TXT for details. 7*0b57cec5SDimitry Andric // 8*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 9*0b57cec5SDimitry Andric 10*0b57cec5SDimitry Andric #include "llvm/ExecutionEngine/JITLink/JITLink.h" 11*0b57cec5SDimitry Andric 12*0b57cec5SDimitry Andric #include "llvm/BinaryFormat/Magic.h" 13*0b57cec5SDimitry Andric #include "llvm/ExecutionEngine/JITLink/MachO.h" 14*0b57cec5SDimitry Andric #include "llvm/Support/Format.h" 15*0b57cec5SDimitry Andric #include "llvm/Support/ManagedStatic.h" 16*0b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 17*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 18*0b57cec5SDimitry Andric 19*0b57cec5SDimitry Andric using namespace llvm; 20*0b57cec5SDimitry Andric using namespace llvm::object; 21*0b57cec5SDimitry Andric 22*0b57cec5SDimitry Andric #define DEBUG_TYPE "jitlink" 23*0b57cec5SDimitry Andric 24*0b57cec5SDimitry Andric namespace { 25*0b57cec5SDimitry Andric 26*0b57cec5SDimitry Andric enum JITLinkErrorCode { GenericJITLinkError = 1 }; 27*0b57cec5SDimitry Andric 28*0b57cec5SDimitry Andric // FIXME: This class is only here to support the transition to llvm::Error. It 29*0b57cec5SDimitry Andric // will be removed once this transition is complete. Clients should prefer to 30*0b57cec5SDimitry Andric // deal with the Error value directly, rather than converting to error_code. 31*0b57cec5SDimitry Andric class JITLinkerErrorCategory : public std::error_category { 32*0b57cec5SDimitry Andric public: 33*0b57cec5SDimitry Andric const char *name() const noexcept override { return "runtimedyld"; } 34*0b57cec5SDimitry Andric 35*0b57cec5SDimitry Andric std::string message(int Condition) const override { 36*0b57cec5SDimitry Andric switch (static_cast<JITLinkErrorCode>(Condition)) { 37*0b57cec5SDimitry Andric case GenericJITLinkError: 38*0b57cec5SDimitry Andric return "Generic JITLink error"; 39*0b57cec5SDimitry Andric } 40*0b57cec5SDimitry Andric llvm_unreachable("Unrecognized JITLinkErrorCode"); 41*0b57cec5SDimitry Andric } 42*0b57cec5SDimitry Andric }; 43*0b57cec5SDimitry Andric 44*0b57cec5SDimitry Andric static ManagedStatic<JITLinkerErrorCategory> JITLinkerErrorCategory; 45*0b57cec5SDimitry Andric 46*0b57cec5SDimitry Andric } // namespace 47*0b57cec5SDimitry Andric 48*0b57cec5SDimitry Andric namespace llvm { 49*0b57cec5SDimitry Andric namespace jitlink { 50*0b57cec5SDimitry Andric 51*0b57cec5SDimitry Andric char JITLinkError::ID = 0; 52*0b57cec5SDimitry Andric 53*0b57cec5SDimitry Andric void JITLinkError::log(raw_ostream &OS) const { OS << ErrMsg << "\n"; } 54*0b57cec5SDimitry Andric 55*0b57cec5SDimitry Andric std::error_code JITLinkError::convertToErrorCode() const { 56*0b57cec5SDimitry Andric return std::error_code(GenericJITLinkError, *JITLinkerErrorCategory); 57*0b57cec5SDimitry Andric } 58*0b57cec5SDimitry Andric 59*0b57cec5SDimitry Andric const StringRef getGenericEdgeKindName(Edge::Kind K) { 60*0b57cec5SDimitry Andric switch (K) { 61*0b57cec5SDimitry Andric case Edge::Invalid: 62*0b57cec5SDimitry Andric return "INVALID RELOCATION"; 63*0b57cec5SDimitry Andric case Edge::KeepAlive: 64*0b57cec5SDimitry Andric return "Keep-Alive"; 65*0b57cec5SDimitry Andric case Edge::LayoutNext: 66*0b57cec5SDimitry Andric return "Layout-Next"; 67*0b57cec5SDimitry Andric default: 68*0b57cec5SDimitry Andric llvm_unreachable("Unrecognized relocation kind"); 69*0b57cec5SDimitry Andric } 70*0b57cec5SDimitry Andric } 71*0b57cec5SDimitry Andric 72*0b57cec5SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const Atom &A) { 73*0b57cec5SDimitry Andric OS << "<"; 74*0b57cec5SDimitry Andric if (A.getName().empty()) 75*0b57cec5SDimitry Andric OS << "anon@" << format("0x%016" PRIx64, A.getAddress()); 76*0b57cec5SDimitry Andric else 77*0b57cec5SDimitry Andric OS << A.getName(); 78*0b57cec5SDimitry Andric OS << " ["; 79*0b57cec5SDimitry Andric if (A.isDefined()) { 80*0b57cec5SDimitry Andric auto &DA = static_cast<const DefinedAtom &>(A); 81*0b57cec5SDimitry Andric OS << " section=" << DA.getSection().getName(); 82*0b57cec5SDimitry Andric if (DA.isLive()) 83*0b57cec5SDimitry Andric OS << " live"; 84*0b57cec5SDimitry Andric if (DA.shouldDiscard()) 85*0b57cec5SDimitry Andric OS << " should-discard"; 86*0b57cec5SDimitry Andric } else 87*0b57cec5SDimitry Andric OS << " external"; 88*0b57cec5SDimitry Andric OS << " ]>"; 89*0b57cec5SDimitry Andric return OS; 90*0b57cec5SDimitry Andric } 91*0b57cec5SDimitry Andric 92*0b57cec5SDimitry Andric void printEdge(raw_ostream &OS, const Atom &FixupAtom, const Edge &E, 93*0b57cec5SDimitry Andric StringRef EdgeKindName) { 94*0b57cec5SDimitry Andric OS << "edge@" << formatv("{0:x16}", FixupAtom.getAddress() + E.getOffset()) 95*0b57cec5SDimitry Andric << ": " << FixupAtom << " + " << E.getOffset() << " -- " << EdgeKindName 96*0b57cec5SDimitry Andric << " -> " << E.getTarget() << " + " << E.getAddend(); 97*0b57cec5SDimitry Andric } 98*0b57cec5SDimitry Andric 99*0b57cec5SDimitry Andric Section::~Section() { 100*0b57cec5SDimitry Andric for (auto *DA : DefinedAtoms) 101*0b57cec5SDimitry Andric DA->~DefinedAtom(); 102*0b57cec5SDimitry Andric } 103*0b57cec5SDimitry Andric 104*0b57cec5SDimitry Andric void AtomGraph::dump(raw_ostream &OS, 105*0b57cec5SDimitry Andric std::function<StringRef(Edge::Kind)> EdgeKindToName) { 106*0b57cec5SDimitry Andric if (!EdgeKindToName) 107*0b57cec5SDimitry Andric EdgeKindToName = [](Edge::Kind K) { return StringRef(); }; 108*0b57cec5SDimitry Andric 109*0b57cec5SDimitry Andric OS << "Defined atoms:\n"; 110*0b57cec5SDimitry Andric for (auto *DA : defined_atoms()) { 111*0b57cec5SDimitry Andric OS << " " << format("0x%016" PRIx64, DA->getAddress()) << ": " << *DA 112*0b57cec5SDimitry Andric << "\n"; 113*0b57cec5SDimitry Andric for (auto &E : DA->edges()) { 114*0b57cec5SDimitry Andric OS << " "; 115*0b57cec5SDimitry Andric StringRef EdgeName = (E.getKind() < Edge::FirstRelocation 116*0b57cec5SDimitry Andric ? getGenericEdgeKindName(E.getKind()) 117*0b57cec5SDimitry Andric : EdgeKindToName(E.getKind())); 118*0b57cec5SDimitry Andric 119*0b57cec5SDimitry Andric if (!EdgeName.empty()) 120*0b57cec5SDimitry Andric printEdge(OS, *DA, E, EdgeName); 121*0b57cec5SDimitry Andric else { 122*0b57cec5SDimitry Andric auto EdgeNumberString = std::to_string(E.getKind()); 123*0b57cec5SDimitry Andric printEdge(OS, *DA, E, EdgeNumberString); 124*0b57cec5SDimitry Andric } 125*0b57cec5SDimitry Andric OS << "\n"; 126*0b57cec5SDimitry Andric } 127*0b57cec5SDimitry Andric } 128*0b57cec5SDimitry Andric 129*0b57cec5SDimitry Andric OS << "Absolute atoms:\n"; 130*0b57cec5SDimitry Andric for (auto *A : absolute_atoms()) 131*0b57cec5SDimitry Andric OS << " " << format("0x%016" PRIx64, A->getAddress()) << ": " << *A 132*0b57cec5SDimitry Andric << "\n"; 133*0b57cec5SDimitry Andric 134*0b57cec5SDimitry Andric OS << "External atoms:\n"; 135*0b57cec5SDimitry Andric for (auto *A : external_atoms()) 136*0b57cec5SDimitry Andric OS << " " << format("0x%016" PRIx64, A->getAddress()) << ": " << *A 137*0b57cec5SDimitry Andric << "\n"; 138*0b57cec5SDimitry Andric } 139*0b57cec5SDimitry Andric 140*0b57cec5SDimitry Andric JITLinkContext::~JITLinkContext() {} 141*0b57cec5SDimitry Andric 142*0b57cec5SDimitry Andric bool JITLinkContext::shouldAddDefaultTargetPasses(const Triple &TT) const { 143*0b57cec5SDimitry Andric return true; 144*0b57cec5SDimitry Andric } 145*0b57cec5SDimitry Andric 146*0b57cec5SDimitry Andric AtomGraphPassFunction JITLinkContext::getMarkLivePass(const Triple &TT) const { 147*0b57cec5SDimitry Andric return AtomGraphPassFunction(); 148*0b57cec5SDimitry Andric } 149*0b57cec5SDimitry Andric 150*0b57cec5SDimitry Andric Error JITLinkContext::modifyPassConfig(const Triple &TT, 151*0b57cec5SDimitry Andric PassConfiguration &Config) { 152*0b57cec5SDimitry Andric return Error::success(); 153*0b57cec5SDimitry Andric } 154*0b57cec5SDimitry Andric 155*0b57cec5SDimitry Andric Error markAllAtomsLive(AtomGraph &G) { 156*0b57cec5SDimitry Andric for (auto *DA : G.defined_atoms()) 157*0b57cec5SDimitry Andric DA->setLive(true); 158*0b57cec5SDimitry Andric return Error::success(); 159*0b57cec5SDimitry Andric } 160*0b57cec5SDimitry Andric 161*0b57cec5SDimitry Andric void jitLink(std::unique_ptr<JITLinkContext> Ctx) { 162*0b57cec5SDimitry Andric auto Magic = identify_magic(Ctx->getObjectBuffer().getBuffer()); 163*0b57cec5SDimitry Andric switch (Magic) { 164*0b57cec5SDimitry Andric case file_magic::macho_object: 165*0b57cec5SDimitry Andric return jitLink_MachO(std::move(Ctx)); 166*0b57cec5SDimitry Andric default: 167*0b57cec5SDimitry Andric Ctx->notifyFailed(make_error<JITLinkError>("Unsupported file format")); 168*0b57cec5SDimitry Andric }; 169*0b57cec5SDimitry Andric } 170*0b57cec5SDimitry Andric 171*0b57cec5SDimitry Andric } // end namespace jitlink 172*0b57cec5SDimitry Andric } // end namespace llvm 173