1 //===--- BasicGOTAndStubsBuilder.h - Generic GOT/Stub creation --*- 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 // A base for simple GOT and stub creation. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_LIB_EXECUTIONENGINE_JITLINK_BASICGOTANDSTUBSBUILDER_H 14 #define LLVM_LIB_EXECUTIONENGINE_JITLINK_BASICGOTANDSTUBSBUILDER_H 15 16 #include "llvm/ExecutionEngine/JITLink/JITLink.h" 17 18 #define DEBUG_TYPE "jitlink" 19 20 namespace llvm { 21 namespace jitlink { 22 23 template <typename BuilderImpl> class BasicGOTAndStubsBuilder { 24 public: BasicGOTAndStubsBuilder(LinkGraph & G)25 BasicGOTAndStubsBuilder(LinkGraph &G) : G(G) {} 26 run()27 void run() { 28 // We're going to be adding new blocks, but we don't want to iterate over 29 // the newly added ones, so just copy the existing blocks out. 30 std::vector<Block *> Blocks(G.blocks().begin(), G.blocks().end()); 31 32 LLVM_DEBUG(dbgs() << "Creating GOT entries and stubs:\n"); 33 34 for (auto *B : Blocks) 35 for (auto &E : B->edges()) 36 if (impl().isGOTEdge(E)) { 37 LLVM_DEBUG({ 38 dbgs() << " Updating GOT edge "; 39 printEdge(dbgs(), *B, E, "<target GOT>"); 40 dbgs() << "\n"; 41 }); 42 impl().fixGOTEdge(E, getGOTEntrySymbol(E.getTarget())); 43 } else if (impl().isExternalBranchEdge(E)) { 44 LLVM_DEBUG({ 45 dbgs() << " Updating external branch edge "; 46 printEdge(dbgs(), *B, E, "<target PC-rel>"); 47 dbgs() << "\n"; 48 }); 49 impl().fixExternalBranchEdge(E, getStubSymbol(E.getTarget())); 50 } 51 } 52 53 protected: getGOTEntrySymbol(Symbol & Target)54 Symbol &getGOTEntrySymbol(Symbol &Target) { 55 assert(Target.hasName() && "GOT edge cannot point to anonymous target"); 56 57 auto GOTEntryI = GOTEntries.find(Target.getName()); 58 59 // Build the entry if it doesn't exist. 60 if (GOTEntryI == GOTEntries.end()) { 61 auto &GOTEntry = impl().createGOTEntry(Target); 62 LLVM_DEBUG({ 63 dbgs() << " Created GOT entry for " << Target.getName() << ": " 64 << GOTEntry << "\n"; 65 }); 66 GOTEntryI = 67 GOTEntries.insert(std::make_pair(Target.getName(), &GOTEntry)).first; 68 } 69 70 assert(GOTEntryI != GOTEntries.end() && "Could not get GOT entry symbol"); 71 LLVM_DEBUG( 72 { dbgs() << " Using GOT entry " << *GOTEntryI->second << "\n"; }); 73 return *GOTEntryI->second; 74 } 75 getStubSymbol(Symbol & Target)76 Symbol &getStubSymbol(Symbol &Target) { 77 assert(Target.hasName() && 78 "External branch edge can not point to an anonymous target"); 79 auto StubI = Stubs.find(Target.getName()); 80 81 if (StubI == Stubs.end()) { 82 auto &StubSymbol = impl().createStub(Target); 83 LLVM_DEBUG({ 84 dbgs() << " Created stub for " << Target.getName() << ": " 85 << StubSymbol << "\n"; 86 }); 87 StubI = Stubs.insert(std::make_pair(Target.getName(), &StubSymbol)).first; 88 } 89 90 assert(StubI != Stubs.end() && "Count not get stub symbol"); 91 LLVM_DEBUG({ dbgs() << " Using stub " << *StubI->second << "\n"; }); 92 return *StubI->second; 93 } 94 95 LinkGraph &G; 96 97 private: impl()98 BuilderImpl &impl() { return static_cast<BuilderImpl &>(*this); } 99 100 DenseMap<StringRef, Symbol *> GOTEntries; 101 DenseMap<StringRef, Symbol *> Stubs; 102 }; 103 104 } // end namespace jitlink 105 } // end namespace llvm 106 107 #endif // LLVM_LIB_EXECUTIONENGINE_JITLINK_BASICGOTANDSTUBSBUILDER_H 108