[llvm] cc4ad2c - [JITLink][ELF/x86-64] Add support for GOTOFF64 relocation.

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 22 10:40:57 PDT 2021


Author: Lang Hames
Date: 2021-03-22T10:40:50-07:00
New Revision: cc4ad2c540c46bd1e3da065040786769c92b8a13

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

LOG: [JITLink][ELF/x86-64] Add support for GOTOFF64 relocation.

Added: 
    

Modified: 
    llvm/include/llvm/ExecutionEngine/JITLink/ELF_x86_64.h
    llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
    llvm/test/ExecutionEngine/JITLink/X86/ELF_x86-64_small_pic_relocations.s
    llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/ExecutionEngine/JITLink/ELF_x86_64.h b/llvm/include/llvm/ExecutionEngine/JITLink/ELF_x86_64.h
index 0a593b2b4a31..d8ed953363e6 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/ELF_x86_64.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/ELF_x86_64.h
@@ -37,6 +37,7 @@ enum ELFX86RelocationKind : Edge::Kind {
   PCRel32GOTLoad,
   PCRel32GOT,
   PCRel64GOT,
+  GOTOFF64,
   GOT64,
   PCRel32TLV,
   Delta32,

diff  --git a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
index eb38313b4280..17c537eea6b5 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
@@ -29,6 +29,9 @@ using namespace llvm::jitlink::ELF_x86_64_Edges;
 
 namespace {
 
+constexpr StringRef ELFGOTSectionName = "$__GOT";
+constexpr StringRef ELFGOTSymbolName = "_GLOBAL_OFFSET_TABLE_";
+
 class PerGraphGOTAndPLTStubsBuilder_ELF_x86_64
     : public PerGraphGOTAndPLTStubsBuilder<
           PerGraphGOTAndPLTStubsBuilder_ELF_x86_64> {
@@ -40,6 +43,13 @@ class PerGraphGOTAndPLTStubsBuilder_ELF_x86_64
       PerGraphGOTAndPLTStubsBuilder_ELF_x86_64>::PerGraphGOTAndPLTStubsBuilder;
 
   bool isGOTEdgeToFix(Edge &E) const {
+    if (E.getKind() == GOTOFF64) {
+      // We need to make sure that the GOT section exists, but don't otherwise
+      // need to fix up this edge.
+      getGOTSection();
+      return false;
+    }
+
     return E.getKind() == PCRel32GOT || E.getKind() == PCRel32GOTLoad ||
            E.getKind() == PCRel64GOT || E.getKind() == GOT64;
   }
@@ -100,13 +110,13 @@ class PerGraphGOTAndPLTStubsBuilder_ELF_x86_64
   }
 
 private:
-  Section &getGOTSection() {
+  Section &getGOTSection() const {
     if (!GOTSection)
-      GOTSection = &G.createSection("$__GOT", sys::Memory::MF_READ);
+      GOTSection = &G.createSection(ELFGOTSectionName, sys::Memory::MF_READ);
     return *GOTSection;
   }
 
-  Section &getStubsSection() {
+  Section &getStubsSection() const {
     if (!StubsSection) {
       auto StubsProt = static_cast<sys::Memory::ProtectionFlags>(
           sys::Memory::MF_READ | sys::Memory::MF_EXEC);
@@ -125,13 +135,10 @@ class PerGraphGOTAndPLTStubsBuilder_ELF_x86_64
                      sizeof(StubContent));
   }
 
-  Section *GOTSection = nullptr;
-  Section *StubsSection = nullptr;
+  mutable Section *GOTSection = nullptr;
+  mutable Section *StubsSection = nullptr;
 };
 
-constexpr StringRef ELFGOTSectionName = "$__GOT";
-constexpr StringRef ELFGOTSymbolName = "_GLOBAL_OFFSET_TABLE_";
-
 const char *const DwarfSectionNames[] = {
 #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION)        \
   ELF_NAME,
@@ -270,6 +277,8 @@ class ELFLinkGraphBuilder_x86_64 {
       return ELF_x86_64_Edges::ELFX86RelocationKind::PCRel64GOT;
     case ELF::R_X86_64_GOT64:
       return ELF_x86_64_Edges::ELFX86RelocationKind::GOT64;
+    case ELF::R_X86_64_GOTOFF64:
+      return ELF_x86_64_Edges::ELFX86RelocationKind::GOTOFF64;
     case ELF::R_X86_64_PLT32:
       return ELF_x86_64_Edges::ELFX86RelocationKind::Branch32;
     }
@@ -726,13 +735,11 @@ class ELFJITLinker_x86_64 : public JITLinker<ELFJITLinker_x86_64> {
   Symbol *GOTSymbol = nullptr;
 
   Error getOrCreateGOTSymbol(LinkGraph &G) {
-    Section *GOTSection = nullptr;
-
     auto DefineExternalGOTSymbolIfPresent =
         createDefineExternalSectionStartAndEndSymbolsPass(
             [&](LinkGraph &LG, Symbol &Sym) -> SectionRangeSymbolDesc {
               if (Sym.getName() == ELFGOTSymbolName)
-                if ((GOTSection = G.findSectionByName(ELFGOTSectionName))) {
+                if (auto *GOTSection = G.findSectionByName(ELFGOTSectionName)) {
                   GOTSymbol = &Sym;
                   return {*GOTSection, true};
                 }
@@ -744,8 +751,14 @@ class ELFJITLinker_x86_64 : public JITLinker<ELFJITLinker_x86_64> {
     if (auto Err = DefineExternalGOTSymbolIfPresent(G))
       return Err;
 
+    // If we succeeded then we're done.
+    if (GOTSymbol)
+      return Error::success();
+
+    // Otherwise look for a GOT section: If it already has a start symbol we'll
+    // record it, otherwise we'll create our own.
     // If there's a GOT section but we didn't find an external GOT symbol...
-    if (GOTSection && !GOTSymbol) {
+    if (auto *GOTSection = G.findSectionByName(ELFGOTSectionName)) {
 
       // Check for an existing defined symbol.
       for (auto *Sym : GOTSection->symbols())
@@ -822,7 +835,13 @@ class ELFJITLinker_x86_64 : public JITLinker<ELFJITLinker_x86_64> {
       *(little64_t *)FixupPtr = Value;
       break;
     }
-    case ELFX86RelocationKind::GOT64: {
+    case ELFX86RelocationKind::GOT64:
+    case ELFX86RelocationKind::GOTOFF64: {
+      // GOT64: Offset of GOT entry within GOT.
+      // GOTOFF64: Offset from GOT base to target.
+      // The expressions are the same in both cases, but in the GOT64 case the
+      // edge will have been fixed to point at the GOT entry, and in the
+      // GOTOFF64 case it will still point at the original target.
       assert(GOTSymbol && "No GOT section symbol");
       int64_t Value =
           E.getTarget().getAddress() - GOTSymbol->getAddress() + E.getAddend();

diff  --git a/llvm/test/ExecutionEngine/JITLink/X86/ELF_x86-64_small_pic_relocations.s b/llvm/test/ExecutionEngine/JITLink/X86/ELF_x86-64_small_pic_relocations.s
index 50f073beb662..147f2b48bbb7 100644
--- a/llvm/test/ExecutionEngine/JITLink/X86/ELF_x86-64_small_pic_relocations.s
+++ b/llvm/test/ExecutionEngine/JITLink/X86/ELF_x86-64_small_pic_relocations.s
@@ -111,6 +111,16 @@ test_rex_gotpcrelx:
 
         .size   test_rex_gotpcrelx, .-test_rex_gotpcrelx
 
+# Test GOTOFF64 handling.
+# jitlink-check: decode_operand(test_gotoff64, 1) = named_func - _GLOBAL_OFFSET_TABLE_
+        .globl test_gotoff64
+        .p2align     4, 0x90
+        .type  test_gotoff64, at function
+test_gotoff64:
+        movabsq $named_func at GOTOFF, %rax
+
+        .size   test_gotoff64, .-test_gotoff64
+
 # Test that relocations to anonymous constant pool entries work.
         .globl  test_anchor_LCPI
         .p2align        4, 0x90

diff  --git a/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp
index efa39b02b325..3f222af3222d 100644
--- a/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp
+++ b/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp
@@ -116,11 +116,15 @@ Error registerELFGraphInfo(Session &S, LinkGraph &G) {
           return make_error<StringError>("zero-fill atom in GOT section",
                                          inconvertibleErrorCode());
 
-        if (auto TS = getELFGOTTarget(G, Sym->getBlock()))
-          FileInfo.GOTEntryInfos[TS->getName()] = {Sym->getSymbolContent(),
-                                                   Sym->getAddress()};
-        else
-          return TS.takeError();
+        // If this is a GOT symbol with size (i.e. not the GOT start symbol)
+        // then add it to the GOT entry info table.
+        if (Sym->getSize() != 0) {
+          if (auto TS = getELFGOTTarget(G, Sym->getBlock()))
+            FileInfo.GOTEntryInfos[TS->getName()] = {Sym->getSymbolContent(),
+                                                     Sym->getAddress()};
+          else
+            return TS.takeError();
+        }
         SectionContainsContent = true;
       } else if (isStubsSection) {
         if (Sym->isSymbolZeroFill())


        


More information about the llvm-commits mailing list