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 namespace llvm { 19 namespace jitlink { 20 21 template <typename BuilderImpl> class BasicGOTAndStubsBuilder { 22 public: BasicGOTAndStubsBuilder(LinkGraph & G)23 BasicGOTAndStubsBuilder(LinkGraph &G) : G(G) {} 24 run()25 void run() { 26 // We're going to be adding new blocks, but we don't want to iterate over 27 // the newly added ones, so just copy the existing blocks out. 28 std::vector<Block *> Blocks(G.blocks().begin(), G.blocks().end()); 29 30 for (auto *B : Blocks) 31 for (auto &E : B->edges()) 32 if (impl().isGOTEdge(E)) 33 impl().fixGOTEdge(E, getGOTEntrySymbol(E.getTarget())); 34 else if (impl().isExternalBranchEdge(E)) 35 impl().fixExternalBranchEdge(E, getStubSymbol(E.getTarget())); 36 } 37 38 protected: getGOTEntrySymbol(Symbol & Target)39 Symbol &getGOTEntrySymbol(Symbol &Target) { 40 assert(Target.hasName() && "GOT edge cannot point to anonymous target"); 41 42 auto GOTEntryI = GOTEntries.find(Target.getName()); 43 44 // Build the entry if it doesn't exist. 45 if (GOTEntryI == GOTEntries.end()) { 46 auto &GOTEntry = impl().createGOTEntry(Target); 47 GOTEntryI = 48 GOTEntries.insert(std::make_pair(Target.getName(), &GOTEntry)).first; 49 } 50 51 assert(GOTEntryI != GOTEntries.end() && "Could not get GOT entry symbol"); 52 return *GOTEntryI->second; 53 } 54 getStubSymbol(Symbol & Target)55 Symbol &getStubSymbol(Symbol &Target) { 56 assert(Target.hasName() && 57 "External branch edge can not point to an anonymous target"); 58 auto StubI = Stubs.find(Target.getName()); 59 60 if (StubI == Stubs.end()) { 61 auto &StubSymbol = impl().createStub(Target); 62 StubI = Stubs.insert(std::make_pair(Target.getName(), &StubSymbol)).first; 63 } 64 65 assert(StubI != Stubs.end() && "Count not get stub symbol"); 66 return *StubI->second; 67 } 68 69 LinkGraph &G; 70 71 private: impl()72 BuilderImpl &impl() { return static_cast<BuilderImpl &>(*this); } 73 74 DenseMap<StringRef, Symbol *> GOTEntries; 75 DenseMap<StringRef, Symbol *> Stubs; 76 }; 77 78 } // end namespace jitlink 79 } // end namespace llvm 80 81 #endif // LLVM_LIB_EXECUTIONENGINE_JITLINK_BASICGOTANDSTUBSBUILDER_H 82