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 20namespace llvm { 21namespace jitlink { 22 23template <typename BuilderImpl> class BasicGOTAndStubsBuilder { 24public: 25 BasicGOTAndStubsBuilder(LinkGraph &G) : G(G) {} 26 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 53protected: 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 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 97private: 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