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 598bcb0991SDimitry 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 708bcb0991SDimitry Andric const char *getLinkageName(Linkage L) { 718bcb0991SDimitry Andric switch (L) { 728bcb0991SDimitry Andric case Linkage::Strong: 738bcb0991SDimitry Andric return "strong"; 748bcb0991SDimitry Andric case Linkage::Weak: 758bcb0991SDimitry Andric return "weak"; 768bcb0991SDimitry Andric } 778bcb0991SDimitry Andric llvm_unreachable("Unrecognized llvm.jitlink.Linkage enum"); 788bcb0991SDimitry Andric } 798bcb0991SDimitry Andric 808bcb0991SDimitry Andric const char *getScopeName(Scope S) { 818bcb0991SDimitry Andric switch (S) { 828bcb0991SDimitry Andric case Scope::Default: 838bcb0991SDimitry Andric return "default"; 848bcb0991SDimitry Andric case Scope::Hidden: 858bcb0991SDimitry Andric return "hidden"; 868bcb0991SDimitry Andric case Scope::Local: 878bcb0991SDimitry Andric return "local"; 888bcb0991SDimitry Andric } 898bcb0991SDimitry Andric llvm_unreachable("Unrecognized llvm.jitlink.Scope enum"); 908bcb0991SDimitry Andric } 918bcb0991SDimitry Andric 928bcb0991SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const Block &B) { 938bcb0991SDimitry Andric return OS << formatv("{0:x16}", B.getAddress()) << " -- " 948bcb0991SDimitry Andric << formatv("{0:x16}", B.getAddress() + B.getSize()) << ": " 958bcb0991SDimitry Andric << (B.isZeroFill() ? "zero-fill" : "content") 968bcb0991SDimitry Andric << ", align = " << B.getAlignment() 978bcb0991SDimitry Andric << ", align-ofs = " << B.getAlignmentOffset() 988bcb0991SDimitry Andric << ", section = " << B.getSection().getName(); 998bcb0991SDimitry Andric } 1008bcb0991SDimitry Andric 1018bcb0991SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const Symbol &Sym) { 1020b57cec5SDimitry Andric OS << "<"; 1038bcb0991SDimitry Andric if (Sym.getName().empty()) 1048bcb0991SDimitry Andric OS << "*anon*"; 1050b57cec5SDimitry Andric else 1068bcb0991SDimitry Andric OS << Sym.getName(); 1078bcb0991SDimitry Andric OS << ": flags = "; 1088bcb0991SDimitry Andric switch (Sym.getLinkage()) { 1098bcb0991SDimitry Andric case Linkage::Strong: 1108bcb0991SDimitry Andric OS << 'S'; 1118bcb0991SDimitry Andric break; 1128bcb0991SDimitry Andric case Linkage::Weak: 1138bcb0991SDimitry Andric OS << 'W'; 1148bcb0991SDimitry Andric break; 1158bcb0991SDimitry Andric } 1168bcb0991SDimitry Andric switch (Sym.getScope()) { 1178bcb0991SDimitry Andric case Scope::Default: 1188bcb0991SDimitry Andric OS << 'D'; 1198bcb0991SDimitry Andric break; 1208bcb0991SDimitry Andric case Scope::Hidden: 1218bcb0991SDimitry Andric OS << 'H'; 1228bcb0991SDimitry Andric break; 1238bcb0991SDimitry Andric case Scope::Local: 1248bcb0991SDimitry Andric OS << 'L'; 1258bcb0991SDimitry Andric break; 1268bcb0991SDimitry Andric } 1278bcb0991SDimitry Andric OS << (Sym.isLive() ? '+' : '-') 1288bcb0991SDimitry Andric << ", size = " << formatv("{0:x8}", Sym.getSize()) 1298bcb0991SDimitry Andric << ", addr = " << formatv("{0:x16}", Sym.getAddress()) << " (" 1308bcb0991SDimitry Andric << formatv("{0:x16}", Sym.getAddressable().getAddress()) << " + " 1318bcb0991SDimitry Andric << formatv("{0:x8}", Sym.getOffset()); 1328bcb0991SDimitry Andric if (Sym.isDefined()) 1338bcb0991SDimitry Andric OS << " " << Sym.getBlock().getSection().getName(); 1348bcb0991SDimitry Andric OS << ")>"; 1350b57cec5SDimitry Andric return OS; 1360b57cec5SDimitry Andric } 1370b57cec5SDimitry Andric 1388bcb0991SDimitry Andric void printEdge(raw_ostream &OS, const Block &B, const Edge &E, 1390b57cec5SDimitry Andric StringRef EdgeKindName) { 1408bcb0991SDimitry Andric OS << "edge@" << formatv("{0:x16}", B.getAddress() + E.getOffset()) << ": " 1418bcb0991SDimitry Andric << formatv("{0:x16}", B.getAddress()) << " + " << E.getOffset() << " -- " 1428bcb0991SDimitry Andric << EdgeKindName << " -> " << E.getTarget() << " + " << E.getAddend(); 1430b57cec5SDimitry Andric } 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric Section::~Section() { 1468bcb0991SDimitry Andric for (auto *Sym : Symbols) 1478bcb0991SDimitry Andric Sym->~Symbol(); 1488bcb0991SDimitry Andric for (auto *B : Blocks) 1498bcb0991SDimitry Andric B->~Block(); 1508bcb0991SDimitry Andric } 1518bcb0991SDimitry Andric 152*480093f4SDimitry Andric Block &LinkGraph::splitBlock(Block &B, size_t SplitIndex, 153*480093f4SDimitry Andric SplitBlockCache *Cache) { 154*480093f4SDimitry Andric 155*480093f4SDimitry Andric assert(SplitIndex > 0 && "splitBlock can not be called with SplitIndex == 0"); 156*480093f4SDimitry Andric 157*480093f4SDimitry Andric // If the split point covers all of B then just return B. 158*480093f4SDimitry Andric if (SplitIndex == B.getSize()) 159*480093f4SDimitry Andric return B; 160*480093f4SDimitry Andric 161*480093f4SDimitry Andric assert(SplitIndex < B.getSize() && "SplitIndex out of range"); 162*480093f4SDimitry Andric 163*480093f4SDimitry Andric // Create the new block covering [ 0, SplitIndex ). 164*480093f4SDimitry Andric auto &NewBlock = 165*480093f4SDimitry Andric B.isZeroFill() 166*480093f4SDimitry Andric ? createZeroFillBlock(B.getSection(), SplitIndex, B.getAddress(), 167*480093f4SDimitry Andric B.getAlignment(), B.getAlignmentOffset()) 168*480093f4SDimitry Andric : createContentBlock( 169*480093f4SDimitry Andric B.getSection(), B.getContent().substr(0, SplitIndex), 170*480093f4SDimitry Andric B.getAddress(), B.getAlignment(), B.getAlignmentOffset()); 171*480093f4SDimitry Andric 172*480093f4SDimitry Andric // Modify B to cover [ SplitIndex, B.size() ). 173*480093f4SDimitry Andric B.setAddress(B.getAddress() + SplitIndex); 174*480093f4SDimitry Andric B.setContent(B.getContent().substr(SplitIndex)); 175*480093f4SDimitry Andric B.setAlignmentOffset((B.getAlignmentOffset() + SplitIndex) % 176*480093f4SDimitry Andric B.getAlignment()); 177*480093f4SDimitry Andric 178*480093f4SDimitry Andric // Handle edge transfer/update. 179*480093f4SDimitry Andric { 180*480093f4SDimitry Andric // Copy edges to NewBlock (recording their iterators so that we can remove 181*480093f4SDimitry Andric // them from B), and update of Edges remaining on B. 182*480093f4SDimitry Andric std::vector<Block::edge_iterator> EdgesToRemove; 183*480093f4SDimitry Andric for (auto I = B.edges().begin(), E = B.edges().end(); I != E; ++I) { 184*480093f4SDimitry Andric if (I->getOffset() < SplitIndex) { 185*480093f4SDimitry Andric NewBlock.addEdge(*I); 186*480093f4SDimitry Andric EdgesToRemove.push_back(I); 187*480093f4SDimitry Andric } else 188*480093f4SDimitry Andric I->setOffset(I->getOffset() - SplitIndex); 189*480093f4SDimitry Andric } 190*480093f4SDimitry Andric 191*480093f4SDimitry Andric // Remove edges that were transfered to NewBlock from B. 192*480093f4SDimitry Andric while (!EdgesToRemove.empty()) { 193*480093f4SDimitry Andric B.removeEdge(EdgesToRemove.back()); 194*480093f4SDimitry Andric EdgesToRemove.pop_back(); 195*480093f4SDimitry Andric } 196*480093f4SDimitry Andric } 197*480093f4SDimitry Andric 198*480093f4SDimitry Andric // Handle symbol transfer/update. 199*480093f4SDimitry Andric { 200*480093f4SDimitry Andric // Initialize the symbols cache if necessary. 201*480093f4SDimitry Andric SplitBlockCache LocalBlockSymbolsCache; 202*480093f4SDimitry Andric if (!Cache) 203*480093f4SDimitry Andric Cache = &LocalBlockSymbolsCache; 204*480093f4SDimitry Andric if (*Cache == None) { 205*480093f4SDimitry Andric *Cache = SplitBlockCache::value_type(); 206*480093f4SDimitry Andric for (auto *Sym : B.getSection().symbols()) 207*480093f4SDimitry Andric if (&Sym->getBlock() == &B) 208*480093f4SDimitry Andric (*Cache)->push_back(Sym); 209*480093f4SDimitry Andric 210*480093f4SDimitry Andric llvm::sort(**Cache, [](const Symbol *LHS, const Symbol *RHS) { 211*480093f4SDimitry Andric return LHS->getOffset() > RHS->getOffset(); 212*480093f4SDimitry Andric }); 213*480093f4SDimitry Andric } 214*480093f4SDimitry Andric auto &BlockSymbols = **Cache; 215*480093f4SDimitry Andric 216*480093f4SDimitry Andric // Transfer all symbols with offset less than SplitIndex to NewBlock. 217*480093f4SDimitry Andric while (!BlockSymbols.empty() && 218*480093f4SDimitry Andric BlockSymbols.back()->getOffset() < SplitIndex) { 219*480093f4SDimitry Andric BlockSymbols.back()->setBlock(NewBlock); 220*480093f4SDimitry Andric BlockSymbols.pop_back(); 221*480093f4SDimitry Andric } 222*480093f4SDimitry Andric 223*480093f4SDimitry Andric // Update offsets for all remaining symbols in B. 224*480093f4SDimitry Andric for (auto *Sym : BlockSymbols) 225*480093f4SDimitry Andric Sym->setOffset(Sym->getOffset() - SplitIndex); 226*480093f4SDimitry Andric } 227*480093f4SDimitry Andric 228*480093f4SDimitry Andric return NewBlock; 229*480093f4SDimitry Andric } 230*480093f4SDimitry Andric 2318bcb0991SDimitry Andric void LinkGraph::dump(raw_ostream &OS, 2320b57cec5SDimitry Andric std::function<StringRef(Edge::Kind)> EdgeKindToName) { 2330b57cec5SDimitry Andric if (!EdgeKindToName) 2340b57cec5SDimitry Andric EdgeKindToName = [](Edge::Kind K) { return StringRef(); }; 2350b57cec5SDimitry Andric 2368bcb0991SDimitry Andric OS << "Symbols:\n"; 2378bcb0991SDimitry Andric for (auto *Sym : defined_symbols()) { 2388bcb0991SDimitry Andric OS << " " << format("0x%016" PRIx64, Sym->getAddress()) << ": " << *Sym 2390b57cec5SDimitry Andric << "\n"; 2408bcb0991SDimitry Andric if (Sym->isDefined()) { 2418bcb0991SDimitry Andric for (auto &E : Sym->getBlock().edges()) { 2420b57cec5SDimitry Andric OS << " "; 2430b57cec5SDimitry Andric StringRef EdgeName = (E.getKind() < Edge::FirstRelocation 2440b57cec5SDimitry Andric ? getGenericEdgeKindName(E.getKind()) 2450b57cec5SDimitry Andric : EdgeKindToName(E.getKind())); 2460b57cec5SDimitry Andric 2470b57cec5SDimitry Andric if (!EdgeName.empty()) 2488bcb0991SDimitry Andric printEdge(OS, Sym->getBlock(), E, EdgeName); 2490b57cec5SDimitry Andric else { 2500b57cec5SDimitry Andric auto EdgeNumberString = std::to_string(E.getKind()); 2518bcb0991SDimitry Andric printEdge(OS, Sym->getBlock(), E, EdgeNumberString); 2520b57cec5SDimitry Andric } 2530b57cec5SDimitry Andric OS << "\n"; 2540b57cec5SDimitry Andric } 2550b57cec5SDimitry Andric } 2568bcb0991SDimitry Andric } 2570b57cec5SDimitry Andric 2588bcb0991SDimitry Andric OS << "Absolute symbols:\n"; 2598bcb0991SDimitry Andric for (auto *Sym : absolute_symbols()) 2608bcb0991SDimitry Andric OS << " " << format("0x%016" PRIx64, Sym->getAddress()) << ": " << *Sym 2610b57cec5SDimitry Andric << "\n"; 2620b57cec5SDimitry Andric 2638bcb0991SDimitry Andric OS << "External symbols:\n"; 2648bcb0991SDimitry Andric for (auto *Sym : external_symbols()) 2658bcb0991SDimitry Andric OS << " " << format("0x%016" PRIx64, Sym->getAddress()) << ": " << *Sym 2660b57cec5SDimitry Andric << "\n"; 2670b57cec5SDimitry Andric } 2680b57cec5SDimitry Andric 269*480093f4SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupFlags &LF) { 270*480093f4SDimitry Andric switch (LF) { 271*480093f4SDimitry Andric case SymbolLookupFlags::RequiredSymbol: 272*480093f4SDimitry Andric return OS << "RequiredSymbol"; 273*480093f4SDimitry Andric case SymbolLookupFlags::WeaklyReferencedSymbol: 274*480093f4SDimitry Andric return OS << "WeaklyReferencedSymbol"; 275*480093f4SDimitry Andric } 276*480093f4SDimitry Andric llvm_unreachable("Unrecognized lookup flags"); 277*480093f4SDimitry Andric } 278*480093f4SDimitry Andric 2798bcb0991SDimitry Andric void JITLinkAsyncLookupContinuation::anchor() {} 2808bcb0991SDimitry Andric 2810b57cec5SDimitry Andric JITLinkContext::~JITLinkContext() {} 2820b57cec5SDimitry Andric 2830b57cec5SDimitry Andric bool JITLinkContext::shouldAddDefaultTargetPasses(const Triple &TT) const { 2840b57cec5SDimitry Andric return true; 2850b57cec5SDimitry Andric } 2860b57cec5SDimitry Andric 2878bcb0991SDimitry Andric LinkGraphPassFunction JITLinkContext::getMarkLivePass(const Triple &TT) const { 2888bcb0991SDimitry Andric return LinkGraphPassFunction(); 2890b57cec5SDimitry Andric } 2900b57cec5SDimitry Andric 2910b57cec5SDimitry Andric Error JITLinkContext::modifyPassConfig(const Triple &TT, 2920b57cec5SDimitry Andric PassConfiguration &Config) { 2930b57cec5SDimitry Andric return Error::success(); 2940b57cec5SDimitry Andric } 2950b57cec5SDimitry Andric 2968bcb0991SDimitry Andric Error markAllSymbolsLive(LinkGraph &G) { 2978bcb0991SDimitry Andric for (auto *Sym : G.defined_symbols()) 2988bcb0991SDimitry Andric Sym->setLive(true); 2990b57cec5SDimitry Andric return Error::success(); 3000b57cec5SDimitry Andric } 3010b57cec5SDimitry Andric 3020b57cec5SDimitry Andric void jitLink(std::unique_ptr<JITLinkContext> Ctx) { 3030b57cec5SDimitry Andric auto Magic = identify_magic(Ctx->getObjectBuffer().getBuffer()); 3040b57cec5SDimitry Andric switch (Magic) { 3050b57cec5SDimitry Andric case file_magic::macho_object: 3060b57cec5SDimitry Andric return jitLink_MachO(std::move(Ctx)); 3070b57cec5SDimitry Andric default: 3080b57cec5SDimitry Andric Ctx->notifyFailed(make_error<JITLinkError>("Unsupported file format")); 3090b57cec5SDimitry Andric }; 3100b57cec5SDimitry Andric } 3110b57cec5SDimitry Andric 3120b57cec5SDimitry Andric } // end namespace jitlink 3130b57cec5SDimitry Andric } // end namespace llvm 314