[llvm] 2094fad - [JITLink][ELF][AArch64] Implement ADR_GOT_PAGE, LD64_GOT_LO12_NC.

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 7 18:24:00 PDT 2022


Author: Sunho Kim
Date: 2022-06-07T18:20:37-07:00
New Revision: 2094fad00962c1be99ed4db2cafb18d40d3cf8a3

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

LOG: [JITLink][ELF][AArch64] Implement ADR_GOT_PAGE, LD64_GOT_LO12_NC.

This patch implements two most commonly used Global Offset Table relocations in
ELF/AARCH64: R_AARCH64_ADR_GOT_PAGE and R_AARCH64_LD64_GOT_LO12_NC. It
implements the GOT table manager by extending the existing
PerGraphGOTAndPLTStubsBuilder. A future patch will unify this with the MachO
implementation to produce a generic aarch64 got table manager.

Reviewed By: lhames

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

Added: 
    

Modified: 
    llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
    llvm/test/ExecutionEngine/JITLink/AArch64/ELF_aarch64_relocations.s

Removed: 
    


################################################################################
diff  --git a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
index 8ce1f67d63cf8..02615a502250e 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
@@ -19,6 +19,8 @@
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/MathExtras.h"
 
+#include "PerGraphGOTAndPLTStubsBuilder.h"
+
 #define DEBUG_TYPE "jitlink"
 
 using namespace llvm;
@@ -55,6 +57,8 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
     ELFLdSt64Abs12,
     ELFLdSt128Abs12,
     ELFAbs64,
+    ELFAdrGOTPage21,
+    ELFLd64GOTLo12,
   };
 
   static Expected<ELFAArch64RelocationKind>
@@ -79,6 +83,10 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
       return ELFLdSt128Abs12;
     case ELF::R_AARCH64_ABS64:
       return ELFAbs64;
+    case ELF::R_AARCH64_ADR_GOT_PAGE:
+      return ELFAdrGOTPage21;
+    case ELF::R_AARCH64_LD64_GOT_LO12_NC:
+      return ELFLd64GOTLo12;
     }
 
     return make_error<JITLinkError>("Unsupported aarch64 relocation:" +
@@ -206,6 +214,14 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
       Kind = aarch64::Pointer64;
       break;
     }
+    case ELFAdrGOTPage21: {
+      Kind = aarch64::GOTPage21;
+      break;
+    }
+    case ELFLd64GOTLo12: {
+      Kind = aarch64::GOTPageOffset12;
+      break;
+    }
     };
 
     Edge GE(Kind, Offset, *GraphSymbol, Addend);
@@ -240,6 +256,10 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
       return "ELFLdSt128Abs12";
     case ELFAbs64:
       return "ELFAbs64";
+    case ELFAdrGOTPage21:
+      return "ELFAdrGOTPage21";
+    case ELFLd64GOTLo12:
+      return "ELFLd64GOTLo12";
     default:
       return getGenericEdgeKindName(static_cast<Edge::Kind>(R));
     }
@@ -252,6 +272,64 @@ 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 false; }
+
+  Symbol &createPLTStub(Symbol &Target) {
+    assert(false && "unimplemetned");
+    return Target;
+  }
+
+  void fixPLTEdge(Edge &E, Symbol &Stub) { assert(false && "unimplemetned"); }
+
+private:
+  Section &getGOTSection() {
+    if (!GOTSection)
+      GOTSection = &G.createSection("$__GOT", MemProt::Read | MemProt::Exec);
+    return *GOTSection;
+  }
+
+  ArrayRef<char> getGOTEntryBlockContent() {
+    return {reinterpret_cast<const char *>(NullGOTEntryContent),
+            sizeof(NullGOTEntryContent)};
+  }
+
+  static const uint8_t NullGOTEntryContent[8];
+  Section *GOTSection = nullptr;
+};
+
+const uint8_t PerGraphGOTAndPLTStubsBuilder_ELF_arm64::NullGOTEntryContent[8] =
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
 Expected<std::unique_ptr<LinkGraph>>
 createLinkGraphFromELFObject_aarch64(MemoryBufferRef ObjectBuffer) {
   LLVM_DEBUG({
@@ -283,6 +361,10 @@ void link_ELF_aarch64(std::unique_ptr<LinkGraph> G,
     else
       Config.PrePrunePasses.push_back(markAllSymbolsLive);
   }
+
+  Config.PostPrunePasses.push_back(
+      PerGraphGOTAndPLTStubsBuilder_ELF_arm64::asPass);
+
   if (auto Err = Ctx->modifyPassConfig(*G, Config))
     return Ctx->notifyFailed(std::move(Err));
 

diff  --git a/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_aarch64_relocations.s b/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_aarch64_relocations.s
index 7a433e1715ba7..2714ef4183f78 100644
--- a/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_aarch64_relocations.s
+++ b/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_aarch64_relocations.s
@@ -1,7 +1,9 @@
 # RUN: rm -rf %t && mkdir -p %t
 # RUN: llvm-mc -triple=aarch64-unknown-linux-gnu -relax-relocations=false \
 # RUN:   -position-independent -filetype=obj -o %t/elf_reloc.o %s
-# RUN: llvm-jitlink -noexec -check %s %t/elf_reloc.o
+# RUN: llvm-jitlink -noexec \
+# RUN:              -abs external_data=0xdeadbeef \
+# RUN:              -check %s %t/elf_reloc.o
 
         .text
 
@@ -123,6 +125,34 @@ local_func_addr_quad:
         .xword	named_func
         .size	local_func_addr_quad, 8
 
+# Check R_AARCH64_ADR_GOT_PAGE / R_AARCH64_LD64_GOT_LO12_NC handling with a
+# reference to an external symbol. Validate both the reference to the GOT entry,
+# and also the content of the GOT entry.
+#
+# For the ADRP :got: instruction we have the 21-bit delta to the 4k page
+# containing the GOT entry for external_data.
+#
+# For the LDR :got_lo12: instruction we have the 12-bit offset of the entry
+# within the page.
+#
+# jitlink-check: *{8}(got_addr(elf_reloc.o, external_data)) = external_data
+# jitlink-check: decode_operand(test_adr_gotpage_external, 1) = \
+# jitlink-check:     (got_addr(elf_reloc.o, external_data)[32:12] - \
+# jitlink-check:        test_adr_gotpage_external[32:12])
+# jitlink-check: decode_operand(test_ld64_gotlo12_external, 2) = \
+# jitlink-check:     got_addr(elf_reloc.o, external_data)[11:3]
+        .globl  test_adr_gotpage_external
+        .p2align  2
+test_adr_gotpage_external:
+        adrp  x0, :got:external_data
+        .size test_adr_gotpage_external, .-test_adr_gotpage_external
+
+        .globl  test_ld64_gotlo12_external
+        .p2align  2
+test_ld64_gotlo12_external:
+        ldr   x0, [x0, :got_lo12:external_data]
+        .size test_ld64_gotlo12_external, .-test_ld64_gotlo12_external
+
         .globl  named_data
         .p2align  4
         .type   named_data, at object


        


More information about the llvm-commits mailing list