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