[llvm] r358838 - [JITLink] Factor basic common GOT and stub creation code into its own class.

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Sat Apr 20 20:14:42 PDT 2019


Author: lhames
Date: Sat Apr 20 20:14:42 2019
New Revision: 358838

URL: http://llvm.org/viewvc/llvm-project?rev=358838&view=rev
Log:
[JITLink] Factor basic common GOT and stub creation code into its own class.

Added:
    llvm/trunk/lib/ExecutionEngine/JITLink/BasicGOTAndStubsBuilder.h
Modified:
    llvm/trunk/lib/ExecutionEngine/JITLink/JITLink_MachO_x86_64.cpp

Added: llvm/trunk/lib/ExecutionEngine/JITLink/BasicGOTAndStubsBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/JITLink/BasicGOTAndStubsBuilder.h?rev=358838&view=auto
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/JITLink/BasicGOTAndStubsBuilder.h (added)
+++ llvm/trunk/lib/ExecutionEngine/JITLink/BasicGOTAndStubsBuilder.h Sat Apr 20 20:14:42 2019
@@ -0,0 +1,82 @@
+//===--- BasicGOTAndStubsBuilder.h - Generic GOT/Stub creation --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// A base for simple GOT and stub creation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_EXECUTIONENGINE_JITLINK_BASICGOTANDSTUBSBUILDER_H
+#define LLVM_LIB_EXECUTIONENGINE_JITLINK_BASICGOTANDSTUBSBUILDER_H
+
+#include "llvm/ExecutionEngine/JITLink/JITLink.h"
+
+namespace llvm {
+namespace jitlink {
+
+template <typename BuilderImpl> class BasicGOTAndStubsBuilder {
+public:
+  BasicGOTAndStubsBuilder(AtomGraph &G) : G(G) {}
+
+  void run() {
+    // We're going to be adding new atoms, but we don't want to iterate over
+    // the newly added ones, so just copy the existing atoms out.
+    std::vector<DefinedAtom *> DAs(G.defined_atoms().begin(),
+                                   G.defined_atoms().end());
+
+    for (auto *DA : DAs)
+      for (auto &E : DA->edges())
+        if (impl().isGOTEdge(E))
+          impl().fixGOTEdge(E, getGOTEntryAtom(E.getTarget()));
+        else if (impl().isExternalBranchEdge(E))
+          impl().fixExternalBranchEdge(E, getStubAtom(E.getTarget()));
+  }
+
+protected:
+  Atom &getGOTEntryAtom(Atom &Target) {
+    assert(Target.hasName() && "GOT edge cannot point to anonymous target");
+
+    auto GOTEntryI = GOTEntries.find(Target.getName());
+
+    // Build the entry if it doesn't exist.
+    if (GOTEntryI == GOTEntries.end()) {
+      auto &GOTEntry = impl().createGOTEntry(Target);
+      GOTEntryI =
+          GOTEntries.insert(std::make_pair(Target.getName(), &GOTEntry)).first;
+    }
+
+    assert(GOTEntryI != GOTEntries.end() && "Could not get GOT entry atom");
+    return *GOTEntryI->second;
+  }
+
+  Atom &getStubAtom(Atom &Target) {
+    assert(Target.hasName() &&
+           "External branch edge can not point to an anonymous target");
+    auto StubI = Stubs.find(Target.getName());
+
+    if (StubI == Stubs.end()) {
+      auto &StubAtom = impl().createStub(Target);
+      StubI = Stubs.insert(std::make_pair(Target.getName(), &StubAtom)).first;
+    }
+
+    assert(StubI != Stubs.end() && "Count not get stub atom");
+    return *StubI->second;
+  }
+
+  AtomGraph &G;
+
+private:
+  BuilderImpl &impl() { return static_cast<BuilderImpl &>(*this); }
+
+  DenseMap<StringRef, DefinedAtom *> GOTEntries;
+  DenseMap<StringRef, DefinedAtom *> Stubs;
+};
+
+} // end namespace jitlink
+} // end namespace llvm
+
+#endif // LLVM_LIB_EXECUTIONENGINE_JITLINK_BASICGOTANDSTUBSBUILDER_H

Modified: llvm/trunk/lib/ExecutionEngine/JITLink/JITLink_MachO_x86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/JITLink/JITLink_MachO_x86_64.cpp?rev=358838&r1=358837&r2=358838&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/JITLink/JITLink_MachO_x86_64.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/JITLink/JITLink_MachO_x86_64.cpp Sat Apr 20 20:14:42 2019
@@ -12,6 +12,7 @@
 
 #include "llvm/ExecutionEngine/JITLink/JITLink_MachO_x86_64.h"
 
+#include "BasicGOTAndStubsBuilder.h"
 #include "MachOAtomGraphBuilder.h"
 
 #define DEBUG_TYPE "jitlink"
@@ -346,104 +347,79 @@ private:
   unsigned NumSymbols = 0;
 };
 
-class MachOInPlaceGOTAndStubsBuilder {
+class MachO_x86_64_GOTAndStubsBuilder
+    : public BasicGOTAndStubsBuilder<MachO_x86_64_GOTAndStubsBuilder> {
 public:
-  MachOInPlaceGOTAndStubsBuilder(AtomGraph &G) : G(G) {}
+  MachO_x86_64_GOTAndStubsBuilder(AtomGraph &G)
+      : BasicGOTAndStubsBuilder<MachO_x86_64_GOTAndStubsBuilder>(G) {}
 
-  void run() {
-    // We're going to be adding new atoms, but we don't want to iterate over
-    // the newly added ones, so just copy the existing atoms out.
-    std::vector<DefinedAtom *> DAs(G.defined_atoms().begin(),
-                                   G.defined_atoms().end());
-
-    for (auto *DA : DAs)
-      for (auto &E : DA->edges())
-        if (E.getKind() == PCRel32GOT || E.getKind() == PCRel32GOTLoad)
-          fixGOTEdge(E);
-        else if (E.getKind() == Branch32 && !E.getTarget().isDefined())
-          fixExternalBranchEdge(E);
+  bool isGOTEdge(Edge &E) const {
+    return E.getKind() == PCRel32GOT || E.getKind() == PCRel32GOTLoad;
   }
 
-  Atom &getGOTEntryAtom(Atom &Target) {
-    assert(!Target.getName().empty() &&
-           "GOT load edge cannot point to anonymous target");
-
-    auto GOTEntryI = GOTEntries.find(Target.getName());
-
-    // Build the entry if it doesn't exist.
-    if (GOTEntryI == GOTEntries.end()) {
-      // Build a GOT section if we don't have one already.
-      if (!GOTSection)
-        GOTSection = &G.createSection("$__GOT", sys::Memory::MF_READ, false);
-
-      auto &GOTEntryAtom = G.addAnonymousAtom(*GOTSection, 0x0, 8);
-      GOTEntryAtom.setContent(
-          StringRef(reinterpret_cast<const char *>(NullGOTEntryContent), 8));
-      GOTEntryAtom.addEdge(Pointer64, 0, Target, 0);
-      GOTEntryI =
-          GOTEntries.insert(std::make_pair(Target.getName(), &GOTEntryAtom))
-              .first;
-    }
-
-    assert(GOTEntryI != GOTEntries.end() && "Could not get GOT entry atom");
-    return *GOTEntryI->second;
+  DefinedAtom &createGOTEntry(Atom &Target) {
+    auto &GOTEntryAtom = G.addAnonymousAtom(getGOTSection(), 0x0, 8);
+    GOTEntryAtom.setContent(
+        StringRef(reinterpret_cast<const char *>(NullGOTEntryContent), 8));
+    GOTEntryAtom.addEdge(Pointer64, 0, Target, 0);
+    return GOTEntryAtom;
   }
 
-  void fixGOTEdge(Edge &E) {
+  void fixGOTEdge(Edge &E, Atom &GOTEntry) {
     assert((E.getKind() == PCRel32GOT || E.getKind() == PCRel32GOTLoad) &&
            "Not a GOT edge?");
-    auto &GOTEntryAtom = getGOTEntryAtom(E.getTarget());
     E.setKind(PCRel32);
-    E.setTarget(GOTEntryAtom);
+    E.setTarget(GOTEntry);
     // Leave the edge addend as-is.
   }
 
-  Atom &getStubAtom(Atom &Target) {
-    assert(!Target.getName().empty() &&
-           "Branch edge can not point to an anonymous target");
-    auto StubI = Stubs.find(Target.getName());
-
-    if (StubI == Stubs.end()) {
-      // Build a Stubs section if we don't have one already.
-      if (!StubsSection) {
-        auto StubsProt = static_cast<sys::Memory::ProtectionFlags>(
-            sys::Memory::MF_READ | sys::Memory::MF_EXEC);
-        StubsSection = &G.createSection("$__STUBS", StubsProt, false);
-      }
-
-      auto &StubAtom = G.addAnonymousAtom(*StubsSection, 0x0, 2);
-      StubAtom.setContent(
-          StringRef(reinterpret_cast<const char *>(StubContent), 6));
+  bool isExternalBranchEdge(Edge &E) {
+    return E.getKind() == Branch32 && !E.getTarget().isDefined();
+  }
 
-      // Re-use GOT entries for stub targets.
-      auto &GOTEntryAtom = getGOTEntryAtom(Target);
-      StubAtom.addEdge(PCRel32, 2, GOTEntryAtom, 0);
+  DefinedAtom &createStub(Atom &Target) {
+    auto &StubAtom = G.addAnonymousAtom(getStubsSection(), 0x0, 2);
+    StubAtom.setContent(
+        StringRef(reinterpret_cast<const char *>(StubContent), 6));
 
-      StubI = Stubs.insert(std::make_pair(Target.getName(), &StubAtom)).first;
-    }
+    // Re-use GOT entries for stub targets.
+    auto &GOTEntryAtom = getGOTEntryAtom(Target);
+    StubAtom.addEdge(PCRel32, 2, GOTEntryAtom, 0);
 
-    assert(StubI != Stubs.end() && "Count not get stub atom");
-    return *StubI->second;
+    return StubAtom;
   }
 
-  void fixExternalBranchEdge(Edge &E) {
+  void fixExternalBranchEdge(Edge &E, Atom &Stub) {
     assert(E.getKind() == Branch32 && "Not a Branch32 edge?");
     assert(E.getAddend() == 0 && "Branch32 edge has non-zero addend?");
-    E.setTarget(getStubAtom(E.getTarget()));
+    E.setTarget(Stub);
+  }
+
+private:
+  Section &getGOTSection() {
+    if (!GOTSection)
+      GOTSection = &G.createSection("$__GOT", sys::Memory::MF_READ, false);
+    return *GOTSection;
+  }
+
+  Section &getStubsSection() {
+    if (!StubsSection) {
+      auto StubsProt = static_cast<sys::Memory::ProtectionFlags>(
+          sys::Memory::MF_READ | sys::Memory::MF_EXEC);
+      StubsSection = &G.createSection("$__STUBS", StubsProt, false);
+    }
+    return *StubsSection;
   }
 
-  AtomGraph &G;
-  DenseMap<StringRef, DefinedAtom *> GOTEntries;
-  DenseMap<StringRef, DefinedAtom *> Stubs;
   static const uint8_t NullGOTEntryContent[8];
   static const uint8_t StubContent[6];
   Section *GOTSection = nullptr;
   Section *StubsSection = nullptr;
 };
 
-const uint8_t MachOInPlaceGOTAndStubsBuilder::NullGOTEntryContent[8] = {
+const uint8_t MachO_x86_64_GOTAndStubsBuilder::NullGOTEntryContent[8] = {
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-const uint8_t MachOInPlaceGOTAndStubsBuilder::StubContent[6] = {
+const uint8_t MachO_x86_64_GOTAndStubsBuilder::StubContent[6] = {
     0xFF, 0x25, 0x00, 0x00, 0x00, 0x00};
 } // namespace
 
@@ -570,7 +546,7 @@ void jitLink_MachO_x86_64(std::unique_pt
 
     // Add an in-place GOT/Stubs pass.
     Config.PostPrunePasses.push_back([](AtomGraph &G) -> Error {
-      MachOInPlaceGOTAndStubsBuilder(G).run();
+      MachO_x86_64_GOTAndStubsBuilder(G).run();
       return Error::success();
     });
   }




More information about the llvm-commits mailing list