[llvm] db37225 - [JITLink][AArch64] Unify table managers of ELF and MachO.

Sunho Kim via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 13 21:16:55 PDT 2022


Author: Sunho Kim
Date: 2022-06-14T13:16:03+09:00
New Revision: db3722580335c5e80c1c76ee565aa57a1791a505

URL: https://github.com/llvm/llvm-project/commit/db3722580335c5e80c1c76ee565aa57a1791a505
DIFF: https://github.com/llvm/llvm-project/commit/db3722580335c5e80c1c76ee565aa57a1791a505.diff

LOG: [JITLink][AArch64] Unify table managers of ELF and MachO.

Unifies GOT/PLT table managers of ELF and MachO on aarch64 architecture. Additionally, it migrates table managers from PerGraphGOTAndPLTStubsBuilder to generic crtp TableManager.

Reviewed By: lhames

Differential Revision: https://reviews.llvm.org/D127558

Added: 
    

Modified: 
    llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h
    llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
    llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp
    llvm/lib/ExecutionEngine/JITLink/aarch64.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h b/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h
index 5662c433d96a8..36403fab9efbb 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h
@@ -13,7 +13,9 @@
 #ifndef LLVM_EXECUTIONENGINE_JITLINK_AARCH64_H
 #define LLVM_EXECUTIONENGINE_JITLINK_AARCH64_H
 
+#include "TableManager.h"
 #include "llvm/ExecutionEngine/JITLink/JITLink.h"
+#include "llvm/ExecutionEngine/JITLink/MemoryFlags.h"
 
 namespace llvm {
 namespace jitlink {
@@ -49,6 +51,125 @@ unsigned getPageOffset12Shift(uint32_t Instr);
 
 Error applyFixup(LinkGraph &G, Block &B, const Edge &E);
 
+/// AArch64 null pointer content.
+extern const uint8_t NullGOTEntryContent[8];
+
+/// AArch64 PLT stub content.
+extern const uint8_t StubContent[8];
+
+/// Global Offset Table Builder.
+class GOTTableManager : public TableManager<GOTTableManager> {
+public:
+  static StringRef getSectionName() { return "$__GOT"; }
+
+  bool visitEdge(LinkGraph &G, Block *B, Edge &E) {
+    Edge::Kind KindToSet = Edge::Invalid;
+    const char *BlockWorkingMem = B->getContent().data();
+    const char *FixupPtr = BlockWorkingMem + E.getOffset();
+
+    switch (E.getKind()) {
+    case aarch64::GOTPage21:
+    case aarch64::TLVPage21: {
+      KindToSet = aarch64::Page21;
+      break;
+    }
+    case aarch64::GOTPageOffset12:
+    case aarch64::TLVPageOffset12: {
+      KindToSet = aarch64::PageOffset12;
+      uint32_t RawInstr = *(const support::ulittle32_t *)FixupPtr;
+      assert(E.getAddend() == 0 &&
+             "GOTPageOffset12/TLVPageOffset12 with non-zero addend");
+      assert((RawInstr & 0xfffffc00) == 0xf9400000 &&
+             "RawInstr isn't a 64-bit LDR immediate");
+      break;
+    }
+    case aarch64::PointerToGOT: {
+      KindToSet = aarch64::Delta64;
+      break;
+    }
+    default:
+      return false;
+    }
+    assert(KindToSet != Edge::Invalid &&
+           "Fell through switch, but no new kind to set");
+    DEBUG_WITH_TYPE("jitlink", {
+      dbgs() << "  Fixing " << G.getEdgeKindName(E.getKind()) << " edge at "
+             << B->getFixupAddress(E) << " (" << B->getAddress() << " + "
+             << formatv("{0:x}", E.getOffset()) << ")\n";
+    });
+    E.setKind(KindToSet);
+    E.setTarget(getEntryForTarget(G, E.getTarget()));
+    return true;
+  }
+
+  Symbol &createEntry(LinkGraph &G, Symbol &Target) {
+    auto &GOTEntryBlock = G.createContentBlock(
+        getGOTSection(G), getGOTEntryBlockContent(), orc::ExecutorAddr(), 8, 0);
+    GOTEntryBlock.addEdge(aarch64::Pointer64, 0, Target, 0);
+    return G.addAnonymousSymbol(GOTEntryBlock, 0, 8, false, false);
+  }
+
+private:
+  Section &getGOTSection(LinkGraph &G) {
+    if (!GOTSection)
+      GOTSection =
+          &G.createSection(getSectionName(), MemProt::Read | MemProt::Exec);
+    return *GOTSection;
+  }
+
+  ArrayRef<char> getGOTEntryBlockContent() {
+    return {reinterpret_cast<const char *>(NullGOTEntryContent),
+            sizeof(NullGOTEntryContent)};
+  }
+
+  Section *GOTSection = nullptr;
+};
+
+/// Procedure Linkage Table Builder.
+class PLTTableManager : public TableManager<PLTTableManager> {
+public:
+  PLTTableManager(GOTTableManager &GOT) : GOT(GOT) {}
+
+  static StringRef getSectionName() { return "$__STUBS"; }
+
+  bool visitEdge(LinkGraph &G, Block *B, Edge &E) {
+    if (E.getKind() == aarch64::Branch26 && !E.getTarget().isDefined()) {
+      DEBUG_WITH_TYPE("jitlink", {
+        dbgs() << "  Fixing " << G.getEdgeKindName(E.getKind()) << " edge at "
+               << B->getFixupAddress(E) << " (" << B->getAddress() << " + "
+               << formatv("{0:x}", E.getOffset()) << ")\n";
+      });
+      E.setTarget(getEntryForTarget(G, E.getTarget()));
+      return true;
+    }
+    return false;
+  }
+
+  Symbol &createEntry(LinkGraph &G, Symbol &Target) {
+    auto &StubContentBlock = G.createContentBlock(
+        getStubsSection(G), getStubBlockContent(), orc::ExecutorAddr(), 1, 0);
+    // Re-use GOT entries for stub targets.
+    auto &GOTEntrySymbol = GOT.getEntryForTarget(G, Target);
+    StubContentBlock.addEdge(aarch64::LDRLiteral19, 0, GOTEntrySymbol, 0);
+    return G.addAnonymousSymbol(StubContentBlock, 0, 8, true, false);
+  }
+
+public:
+  Section &getStubsSection(LinkGraph &G) {
+    if (!StubsSection)
+      StubsSection =
+          &G.createSection(getSectionName(), MemProt::Read | MemProt::Exec);
+    return *StubsSection;
+  }
+
+  ArrayRef<char> getStubBlockContent() {
+    return {reinterpret_cast<const char *>(StubContent), sizeof(StubContent)};
+  }
+
+  GOTTableManager &GOT;
+  Section *StubsSection = nullptr;
+};
+
 } // namespace aarch64
 } // namespace jitlink
 } // namespace llvm

diff  --git a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
index e6b44b11e91be..9c2dff7765828 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
@@ -21,15 +21,12 @@
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/MathExtras.h"
 
-#include "PerGraphGOTAndPLTStubsBuilder.h"
-
 #define DEBUG_TYPE "jitlink"
 
 using namespace llvm;
 using namespace llvm::jitlink;
 
-namespace llvm {
-namespace jitlink {
+namespace {
 
 class ELFJITLinker_aarch64 : public JITLinker<ELFJITLinker_aarch64> {
   friend class JITLinker<ELFJITLinker_aarch64>;
@@ -293,90 +290,19 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
                                   aarch64::getEdgeKindName) {}
 };
 
-class PerGraphGOTAndPLTStubsBuilder_ELF_arm64
-    : public PerGraphGOTAndPLTStubsBuilder<
-          PerGraphGOTAndPLTStubsBuilder_ELF_arm64> {
-public:
-  using PerGraphGOTAndPLTStubsBuilder<
-      PerGraphGOTAndPLTStubsBuilder_ELF_arm64>::PerGraphGOTAndPLTStubsBuilder;
-
-  bool isGOTEdgeToFix(Edge &E) const {
-    return E.getKind() == aarch64::GOTPage21 ||
-           E.getKind() == aarch64::GOTPageOffset12;
-  }
-
-  Symbol &createGOTEntry(Symbol &Target) {
-    auto &GOTEntryBlock = G.createContentBlock(
-        getGOTSection(), getGOTEntryBlockContent(), orc::ExecutorAddr(), 8, 0);
-    GOTEntryBlock.addEdge(aarch64::Pointer64, 0, Target, 0);
-    return G.addAnonymousSymbol(GOTEntryBlock, 0, 8, false, false);
-  }
-
-  void fixGOTEdge(Edge &E, Symbol &GOTEntry) {
-    if (E.getKind() == aarch64::GOTPage21) {
-      E.setKind(aarch64::Page21);
-      E.setTarget(GOTEntry);
-    } else if (E.getKind() == aarch64::GOTPageOffset12) {
-      E.setKind(aarch64::PageOffset12);
-      E.setTarget(GOTEntry);
-    } else
-      llvm_unreachable("Not a GOT edge?");
-  }
-
-  bool isExternalBranchEdge(Edge &E) {
-    return E.getKind() == aarch64::Branch26 && !E.getTarget().isDefined();
-  }
-
-  Symbol &createPLTStub(Symbol &Target) {
-    auto &StubContentBlock = G.createContentBlock(
-        getStubsSection(), getStubBlockContent(), orc::ExecutorAddr(), 1, 0);
-    // Re-use GOT entries for stub targets.
-    auto &GOTEntrySymbol = getGOTEntry(Target);
-    StubContentBlock.addEdge(aarch64::LDRLiteral19, 0, GOTEntrySymbol, 0);
-    return G.addAnonymousSymbol(StubContentBlock, 0, 8, true, false);
-  }
-
-  void fixPLTEdge(Edge &E, Symbol &Stub) {
-    assert(E.getKind() == aarch64::Branch26 && "Not a Branch26 edge?");
-    assert(E.getAddend() == 0 && "Branch26 edge has non-zero addend?");
-    E.setTarget(Stub);
-  }
-
-private:
-  Section &getGOTSection() {
-    if (!GOTSection)
-      GOTSection = &G.createSection("$__GOT", MemProt::Read | MemProt::Exec);
-    return *GOTSection;
-  }
-
-  Section &getStubsSection() {
-    if (!StubsSection)
-      StubsSection =
-          &G.createSection("$__STUBS", MemProt::Read | MemProt::Exec);
-    return *StubsSection;
-  }
-
-  ArrayRef<char> getGOTEntryBlockContent() {
-    return {reinterpret_cast<const char *>(NullGOTEntryContent),
-            sizeof(NullGOTEntryContent)};
-  }
+Error buildTables_ELF_aarch64(LinkGraph &G) {
+  LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n");
 
-  ArrayRef<char> getStubBlockContent() {
-    return {reinterpret_cast<const char *>(StubContent), sizeof(StubContent)};
-  }
+  aarch64::GOTTableManager GOT;
+  aarch64::PLTTableManager PLT(GOT);
+  visitExistingEdges(G, GOT, PLT);
+  return Error::success();
+}
 
-  static const uint8_t NullGOTEntryContent[8];
-  static const uint8_t StubContent[8];
-  Section *GOTSection = nullptr;
-  Section *StubsSection = nullptr;
-};
+} // namespace
 
-const uint8_t PerGraphGOTAndPLTStubsBuilder_ELF_arm64::NullGOTEntryContent[8] =
-    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-const uint8_t PerGraphGOTAndPLTStubsBuilder_ELF_arm64::StubContent[8] = {
-    0x10, 0x00, 0x00, 0x58, // LDR x16, <literal>
-    0x00, 0x02, 0x1f, 0xd6  // BR  x16
-};
+namespace llvm {
+namespace jitlink {
 
 Expected<std::unique_ptr<LinkGraph>>
 createLinkGraphFromELFObject_aarch64(MemoryBufferRef ObjectBuffer) {
@@ -404,18 +330,21 @@ void link_ELF_aarch64(std::unique_ptr<LinkGraph> G,
   PassConfiguration Config;
   const Triple &TT = G->getTargetTriple();
   if (Ctx->shouldAddDefaultTargetPasses(TT)) {
+    // Add eh-frame passses.
     Config.PrePrunePasses.push_back(DWARFRecordSectionSplitter(".eh_frame"));
     Config.PrePrunePasses.push_back(EHFrameEdgeFixer(
         ".eh_frame", 8, aarch64::Pointer32, aarch64::Pointer64,
         aarch64::Delta32, aarch64::Delta64, aarch64::NegDelta32));
+
+    // Add a mark-live pass.
     if (auto MarkLive = Ctx->getMarkLivePass(TT))
       Config.PrePrunePasses.push_back(std::move(MarkLive));
     else
       Config.PrePrunePasses.push_back(markAllSymbolsLive);
-  }
 
-  Config.PostPrunePasses.push_back(
-      PerGraphGOTAndPLTStubsBuilder_ELF_arm64::asPass);
+    // Add an in-place GOT/Stubs build pass.
+    Config.PostPrunePasses.push_back(buildTables_ELF_aarch64);
+  }
 
   if (auto Err = Ctx->modifyPassConfig(*G, Config))
     return Ctx->notifyFailed(std::move(Err));

diff  --git a/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp b/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp
index 1356f53b62922..dd50314d3ed75 100644
--- a/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp
@@ -15,7 +15,6 @@
 #include "llvm/ExecutionEngine/JITLink/aarch64.h"
 
 #include "MachOLinkGraphBuilder.h"
-#include "PerGraphGOTAndPLTStubsBuilder.h"
 
 #define DEBUG_TYPE "jitlink"
 
@@ -506,103 +505,20 @@ class MachOLinkGraphBuilder_arm64 : public MachOLinkGraphBuilder {
   unsigned NumSymbols = 0;
 };
 
-class PerGraphGOTAndPLTStubsBuilder_MachO_arm64
-    : public PerGraphGOTAndPLTStubsBuilder<
-          PerGraphGOTAndPLTStubsBuilder_MachO_arm64> {
-public:
-  using PerGraphGOTAndPLTStubsBuilder<
-      PerGraphGOTAndPLTStubsBuilder_MachO_arm64>::PerGraphGOTAndPLTStubsBuilder;
-
-  bool isGOTEdgeToFix(Edge &E) const {
-    return E.getKind() == aarch64::GOTPage21 ||
-           E.getKind() == aarch64::GOTPageOffset12 ||
-           E.getKind() == aarch64::TLVPage21 ||
-           E.getKind() == aarch64::TLVPageOffset12 ||
-           E.getKind() == aarch64::PointerToGOT;
-  }
-
-  Symbol &createGOTEntry(Symbol &Target) {
-    auto &GOTEntryBlock = G.createContentBlock(
-        getGOTSection(), getGOTEntryBlockContent(), orc::ExecutorAddr(), 8, 0);
-    GOTEntryBlock.addEdge(aarch64::Pointer64, 0, Target, 0);
-    return G.addAnonymousSymbol(GOTEntryBlock, 0, 8, false, false);
-  }
-
-  void fixGOTEdge(Edge &E, Symbol &GOTEntry) {
-    if (E.getKind() == aarch64::GOTPage21 ||
-        E.getKind() == aarch64::GOTPageOffset12 ||
-        E.getKind() == aarch64::TLVPage21 ||
-        E.getKind() == aarch64::TLVPageOffset12) {
-      // Update the target, but leave the edge addend as-is.
-      E.setTarget(GOTEntry);
-    } else if (E.getKind() == aarch64::PointerToGOT) {
-      E.setTarget(GOTEntry);
-      E.setKind(aarch64::Delta32);
-    } else
-      llvm_unreachable("Not a GOT edge?");
-  }
-
-  bool isExternalBranchEdge(Edge &E) {
-    return E.getKind() == aarch64::Branch26 && !E.getTarget().isDefined();
-  }
-
-  Symbol &createPLTStub(Symbol &Target) {
-    auto &StubContentBlock = G.createContentBlock(
-        getStubsSection(), getStubBlockContent(), orc::ExecutorAddr(), 1, 0);
-    // Re-use GOT entries for stub targets.
-    auto &GOTEntrySymbol = getGOTEntry(Target);
-    StubContentBlock.addEdge(aarch64::LDRLiteral19, 0, GOTEntrySymbol, 0);
-    return G.addAnonymousSymbol(StubContentBlock, 0, 8, true, false);
-  }
-
-  void fixPLTEdge(Edge &E, Symbol &Stub) {
-    assert(E.getKind() == aarch64::Branch26 && "Not a Branch32 edge?");
-    assert(E.getAddend() == 0 && "Branch32 edge has non-zero addend?");
-    E.setTarget(Stub);
-  }
-
-private:
-  Section &getGOTSection() {
-    if (!GOTSection)
-      GOTSection = &G.createSection("$__GOT", MemProt::Read | MemProt::Exec);
-    return *GOTSection;
-  }
-
-  Section &getStubsSection() {
-    if (!StubsSection)
-      StubsSection =
-          &G.createSection("$__STUBS", MemProt::Read | MemProt::Exec);
-    return *StubsSection;
-  }
-
-  ArrayRef<char> getGOTEntryBlockContent() {
-    return {reinterpret_cast<const char *>(NullGOTEntryContent),
-            sizeof(NullGOTEntryContent)};
-  }
-
-  ArrayRef<char> getStubBlockContent() {
-    return {reinterpret_cast<const char *>(StubContent), sizeof(StubContent)};
-  }
-
-  static const uint8_t NullGOTEntryContent[8];
-  static const uint8_t StubContent[8];
-  Section *GOTSection = nullptr;
-  Section *StubsSection = nullptr;
-};
-
-const uint8_t
-    PerGraphGOTAndPLTStubsBuilder_MachO_arm64::NullGOTEntryContent[8] = {
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-const uint8_t PerGraphGOTAndPLTStubsBuilder_MachO_arm64::StubContent[8] = {
-    0x10, 0x00, 0x00, 0x58, // LDR x16, <literal>
-    0x00, 0x02, 0x1f, 0xd6  // BR  x16
-};
-
 } // namespace
 
 namespace llvm {
 namespace jitlink {
 
+Error buildTables_MachO_arm64(LinkGraph &G) {
+  LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n");
+
+  aarch64::GOTTableManager GOT;
+  aarch64::PLTTableManager PLT(GOT);
+  visitExistingEdges(G, GOT, PLT);
+  return Error::success();
+}
+
 class MachOJITLinker_arm64 : public JITLinker<MachOJITLinker_arm64> {
   friend class JITLinker<MachOJITLinker_arm64>;
 
@@ -654,8 +570,7 @@ void link_MachO_arm64(std::unique_ptr<LinkGraph> G,
         aarch64::Delta32, aarch64::Delta64, aarch64::NegDelta32));
 
     // Add an in-place GOT/Stubs pass.
-    Config.PostPrunePasses.push_back(
-        PerGraphGOTAndPLTStubsBuilder_MachO_arm64::asPass);
+    Config.PostPrunePasses.push_back(buildTables_MachO_arm64);
   }
 
   if (auto Err = Ctx->modifyPassConfig(*G, Config))

diff  --git a/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp b/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp
index fb5429eed96e3..697c31b65a0b2 100644
--- a/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp
@@ -80,9 +80,7 @@ Error applyFixup(LinkGraph &G, Block &B, const Edge &E) {
     *(ulittle64_t *)FixupPtr = Value;
     break;
   }
-  case Page21:
-  case TLVPage21:
-  case GOTPage21: {
+  case Page21: {
     assert((E.getKind() != GOTPage21 || E.getAddend() == 0) &&
            "GOTPAGE21 with non-zero addend");
     uint64_t TargetPage =
@@ -119,21 +117,6 @@ Error applyFixup(LinkGraph &G, Block &B, const Edge &E) {
     *(ulittle32_t *)FixupPtr = FixedInstr;
     break;
   }
-  case TLVPageOffset12:
-  case GOTPageOffset12: {
-    assert(E.getAddend() == 0 && "GOTPAGEOF12 with non-zero addend");
-
-    uint32_t RawInstr = *(ulittle32_t *)FixupPtr;
-    assert((RawInstr & 0xfffffc00) == 0xf9400000 &&
-           "RawInstr isn't a 64-bit LDR immediate");
-
-    uint32_t TargetOffset = E.getTarget().getAddress().getValue() & 0xfff;
-    assert((TargetOffset & 0x7) == 0 && "GOT entry is not 8-byte aligned");
-    uint32_t EncodedImm = (TargetOffset >> 3) << 10;
-    uint32_t FixedInstr = RawInstr | EncodedImm;
-    *(ulittle32_t *)FixupPtr = FixedInstr;
-    break;
-  }
   case LDRLiteral19: {
     assert((FixupAddress.getValue() & 0x3) == 0 && "LDR is not 32-bit aligned");
     assert(E.getAddend() == 0 && "LDRLiteral19 with non-zero addend");
@@ -170,6 +153,15 @@ Error applyFixup(LinkGraph &G, Block &B, const Edge &E) {
       *(little64_t *)FixupPtr = Value;
     break;
   }
+  case TLVPage21:
+  case GOTPage21:
+  case TLVPageOffset12:
+  case GOTPageOffset12:
+  case PointerToGOT: {
+    return make_error<JITLinkError>(
+        "In graph " + G.getName() + ", section " + B.getSection().getName() +
+        "GOT/TLV edge kinds not lowered: " + getEdgeKindName(E.getKind()));
+  }
   default:
     return make_error<JITLinkError>(
         "In graph " + G.getName() + ", section " + B.getSection().getName() +
@@ -179,6 +171,14 @@ Error applyFixup(LinkGraph &G, Block &B, const Edge &E) {
   return Error::success();
 }
 
+const uint8_t NullGOTEntryContent[8] = {0x00, 0x00, 0x00, 0x00,
+                                        0x00, 0x00, 0x00, 0x00};
+
+const uint8_t StubContent[8] = {
+    0x10, 0x00, 0x00, 0x58, // LDR x16, <literal>
+    0x00, 0x02, 0x1f, 0xd6  // BR  x16
+};
+
 const char *getEdgeKindName(Edge::Kind R) {
   switch (R) {
   case Branch26:


        


More information about the llvm-commits mailing list