PerGraphGOTAndPLTStubsBuilder.h 4.3 KB

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