1 //===--------------- PerGraphGOTAndPLTStubBuilder.h -------------*- 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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Construct GOT and PLT entries for each graph. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_EXECUTIONENGINE_JITLINK_PERGRAPHGOTANDPLTSTUBSBUILDER_H 14 #define LLVM_EXECUTIONENGINE_JITLINK_PERGRAPHGOTANDPLTSTUBSBUILDER_H 15 16 #include "llvm/ExecutionEngine/JITLink/JITLink.h" 17 #include "llvm/Support/Debug.h" 18 19 #define DEBUG_TYPE "jitlink" 20 21 namespace llvm { 22 namespace jitlink { 23 24 /// Per-object GOT and PLT Stub builder. 25 /// 26 /// Constructs GOT entries and PLT stubs in every graph for referenced symbols. 27 /// Building these blocks in every graph is likely to lead to duplicate entries 28 /// in the JITLinkDylib, but allows graphs to be trivially removed independently 29 /// without affecting other graphs (since those other graphs will have their own 30 /// copies of any required entries). 31 template <typename BuilderImplT> 32 class PerGraphGOTAndPLTStubsBuilder { 33 public: 34 PerGraphGOTAndPLTStubsBuilder(LinkGraph &G) : G(G) {} 35 36 static Error asPass(LinkGraph &G) { return BuilderImplT(G).run(); } 37 38 Error run() { 39 LLVM_DEBUG(dbgs() << "Running Per-Graph GOT and Stubs builder:\n"); 40 41 // We're going to be adding new blocks, but we don't want to iterate over 42 // the new ones, so build a worklist. 43 std::vector<Block *> Worklist(G.blocks().begin(), G.blocks().end()); 44 45 for (auto *B : Worklist) 46 for (auto &E : B->edges()) { 47 if (impl().isGOTEdgeToFix(E)) { 48 LLVM_DEBUG({ 49 dbgs() << " Fixing " << G.getEdgeKindName(E.getKind()) 50 << " edge at " << B->getFixupAddress(E) << " (" 51 << B->getAddress() << " + " 52 << formatv("{0:x}", E.getOffset()) << ")\n"; 53 }); 54 impl().fixGOTEdge(E, getGOTEntry(E.getTarget())); 55 } else if (impl().isExternalBranchEdge(E)) { 56 LLVM_DEBUG({ 57 dbgs() << " Fixing " << G.getEdgeKindName(E.getKind()) 58 << " edge at " << B->getFixupAddress(E) << " (" 59 << B->getAddress() << " + " 60 << formatv("{0:x}", E.getOffset()) << ")\n"; 61 }); 62 impl().fixPLTEdge(E, getPLTStub(E.getTarget())); 63 } 64 } 65 66 return Error::success(); 67 } 68 69 protected: 70 Symbol &getGOTEntry(Symbol &Target) { 71 assert(Target.hasName() && "GOT edge cannot point to anonymous target"); 72 73 auto GOTEntryI = GOTEntries.find(Target.getName()); 74 75 // Build the entry if it doesn't exist. 76 if (GOTEntryI == GOTEntries.end()) { 77 auto &GOTEntry = impl().createGOTEntry(Target); 78 LLVM_DEBUG({ 79 dbgs() << " Created GOT entry for " << Target.getName() << ": " 80 << GOTEntry << "\n"; 81 }); 82 GOTEntryI = 83 GOTEntries.insert(std::make_pair(Target.getName(), &GOTEntry)).first; 84 } 85 86 assert(GOTEntryI != GOTEntries.end() && "Could not get GOT entry symbol"); 87 LLVM_DEBUG( 88 { dbgs() << " Using GOT entry " << *GOTEntryI->second << "\n"; }); 89 return *GOTEntryI->second; 90 } 91 92 Symbol &getPLTStub(Symbol &Target) { 93 assert(Target.hasName() && 94 "External branch edge can not point to an anonymous target"); 95 auto StubI = PLTStubs.find(Target.getName()); 96 97 if (StubI == PLTStubs.end()) { 98 auto &StubSymbol = impl().createPLTStub(Target); 99 LLVM_DEBUG({ 100 dbgs() << " Created PLT stub for " << Target.getName() << ": " 101 << StubSymbol << "\n"; 102 }); 103 StubI = 104 PLTStubs.insert(std::make_pair(Target.getName(), &StubSymbol)).first; 105 } 106 107 assert(StubI != PLTStubs.end() && "Count not get stub symbol"); 108 LLVM_DEBUG({ dbgs() << " Using PLT stub " << *StubI->second << "\n"; }); 109 return *StubI->second; 110 } 111 112 LinkGraph &G; 113 114 private: 115 BuilderImplT &impl() { return static_cast<BuilderImplT &>(*this); } 116 117 DenseMap<StringRef, Symbol *> GOTEntries; 118 DenseMap<StringRef, Symbol *> PLTStubs; 119 }; 120 121 } // end namespace jitlink 122 } // end namespace llvm 123 124 #undef DEBUG_TYPE 125 126 #endif // LLVM_EXECUTIONENGINE_JITLINK_PERGRAPHGOTANDPLTSTUBSBUILDER_H 127