[llvm] ab472c9 - [JITLink][ELF][AArch64] Implement R_AARCH64_LDST*_ABS_LO12_NC relocation types.

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 7 17:32:19 PDT 2022


Author: Sunho Kim
Date: 2022-06-07T17:32:09-07:00
New Revision: ab472c9615447c8a036d198df7debd4fd9b2e8cc

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

LOG: [JITLink][ELF][AArch64] Implement R_AARCH64_LDST*_ABS_LO12_NC relocation types.

Implement R_AARCH64_LDST*_ABS_LO12_NC relocaiton entries by reusing PageOffset21
generic relocation edge. The difference between MachO backend is that in ELF,
the shift value is explicitly given by relocation type. lld generates the
relocation type that matches with instruction bitwidth, so getting the shift
value implicitly from instruction bytes should be fine in typical use cases.

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 008358d661d4a..5a24a69f9fd08 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
@@ -16,6 +16,7 @@
 #include "llvm/BinaryFormat/ELF.h"
 #include "llvm/ExecutionEngine/JITLink/aarch64.h"
 #include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Support/Endian.h"
 #include "llvm/Support/MathExtras.h"
 
 #define DEBUG_TYPE "jitlink"
@@ -48,6 +49,11 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
     ELFCall26 = Edge::FirstRelocation,
     ELFAdrPage21,
     ELFAddAbs12,
+    ELFLdSt8Abs12,
+    ELFLdSt16Abs12,
+    ELFLdSt32Abs12,
+    ELFLdSt64Abs12,
+    ELFLdSt128Abs12,
   };
 
   static Expected<ELFAArch64RelocationKind>
@@ -60,6 +66,16 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
       return ELFAdrPage21;
     case ELF::R_AARCH64_ADD_ABS_LO12_NC:
       return ELFAddAbs12;
+    case ELF::R_AARCH64_LDST8_ABS_LO12_NC:
+      return ELFLdSt8Abs12;
+    case ELF::R_AARCH64_LDST16_ABS_LO12_NC:
+      return ELFLdSt16Abs12;
+    case ELF::R_AARCH64_LDST32_ABS_LO12_NC:
+      return ELFLdSt32Abs12;
+    case ELF::R_AARCH64_LDST64_ABS_LO12_NC:
+      return ELFLdSt64Abs12;
+    case ELF::R_AARCH64_LDST128_ABS_LO12_NC:
+      return ELFLdSt128Abs12;
     }
 
     return make_error<JITLinkError>("Unsupported aarch64 relocation:" +
@@ -82,6 +98,7 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
   Error addSingleRelocation(const typename ELFT::Rela &Rel,
                             const typename ELFT::Shdr &FixupSect,
                             Block &BlockToFix) {
+    using support::ulittle32_t;
     using Base = ELFLinkGraphBuilder<ELFT>;
 
     uint32_t SymbolIndex = Rel.getSymbol(false);
@@ -108,6 +125,10 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
         orc::ExecutorAddr(FixupSect.sh_addr) + Rel.r_offset;
     Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress();
 
+    // Get a pointer to the fixup content.
+    const void *FixupContent = BlockToFix.getContent().data() +
+                               (FixupAddress - BlockToFix.getAddress());
+
     Edge::Kind Kind = Edge::Invalid;
 
     switch (*RelocKind) {
@@ -123,6 +144,61 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
       Kind = aarch64::PageOffset12;
       break;
     }
+    case ELFLdSt8Abs12: {
+      uint32_t Instr = *(const ulittle32_t *)FixupContent;
+      if (!aarch64::isLoadStoreImm12(Instr) ||
+          aarch64::getPageOffset12Shift(Instr) != 0)
+        return make_error<JITLinkError>(
+            "R_AARCH64_LDST8_ABS_LO12_NC target is not a "
+            "LDRB/STRB (imm12) instruction");
+
+      Kind = aarch64::PageOffset12;
+      break;
+    }
+    case ELFLdSt16Abs12: {
+      uint32_t Instr = *(const ulittle32_t *)FixupContent;
+      if (!aarch64::isLoadStoreImm12(Instr) ||
+          aarch64::getPageOffset12Shift(Instr) != 1)
+        return make_error<JITLinkError>(
+            "R_AARCH64_LDST16_ABS_LO12_NC target is not a "
+            "LDRH/STRH (imm12) instruction");
+
+      Kind = aarch64::PageOffset12;
+      break;
+    }
+    case ELFLdSt32Abs12: {
+      uint32_t Instr = *(const ulittle32_t *)FixupContent;
+      if (!aarch64::isLoadStoreImm12(Instr) ||
+          aarch64::getPageOffset12Shift(Instr) != 2)
+        return make_error<JITLinkError>(
+            "R_AARCH64_LDST32_ABS_LO12_NC target is not a "
+            "LDR/STR (imm12, 32 bit) instruction");
+
+      Kind = aarch64::PageOffset12;
+      break;
+    }
+    case ELFLdSt64Abs12: {
+      uint32_t Instr = *(const ulittle32_t *)FixupContent;
+      if (!aarch64::isLoadStoreImm12(Instr) ||
+          aarch64::getPageOffset12Shift(Instr) != 3)
+        return make_error<JITLinkError>(
+            "R_AARCH64_LDST64_ABS_LO12_NC target is not a "
+            "LDR/STR (imm12, 64 bit) instruction");
+
+      Kind = aarch64::PageOffset12;
+      break;
+    }
+    case ELFLdSt128Abs12: {
+      uint32_t Instr = *(const ulittle32_t *)FixupContent;
+      if (!aarch64::isLoadStoreImm12(Instr) ||
+          aarch64::getPageOffset12Shift(Instr) != 4)
+        return make_error<JITLinkError>(
+            "R_AARCH64_LDST128_ABS_LO12_NC target is not a "
+            "LDR/STR (imm12, 128 bit) instruction");
+
+      Kind = aarch64::PageOffset12;
+      break;
+    }
     };
 
     Edge GE(Kind, Offset, *GraphSymbol, Addend);
@@ -145,6 +221,16 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
       return "ELFAdrPage21";
     case ELFAddAbs12:
       return "ELFAddAbs12";
+    case ELFLdSt8Abs12:
+      return "ELFLdSt8Abs12";
+    case ELFLdSt16Abs12:
+      return "ELFLdSt16Abs12";
+    case ELFLdSt32Abs12:
+      return "ELFLdSt32Abs12";
+    case ELFLdSt64Abs12:
+      return "ELFLdSt64Abs12";
+    case ELFLdSt128Abs12:
+      return "ELFLdSt128Abs12";
     default:
       return getGenericEdgeKindName(static_cast<Edge::Kind>(R));
     }

diff  --git a/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_aarch64_relocations.s b/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_aarch64_relocations.s
index 5534fa9b769db..1a670c2648a8a 100644
--- a/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_aarch64_relocations.s
+++ b/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_aarch64_relocations.s
@@ -48,6 +48,71 @@ test_add_abs_lo12:
         add	x0, x0, :lo12:named_data
         .size test_add_abs_lo12, .-test_add_abs_lo12
 
+# Check R_AARCH64_LDST*_ABS_LO12_NC relocation of a local symbol
+#
+# The immediate value should be the symbol address right shifted according to its instruction bitwidth.
+#
+# jitlink-check: decode_operand(test_ldrb, 2) = named_data[11:0]
+# jitlink-check: decode_operand(test_ldrsb, 2) = (named_data + 0)[11:0]
+# jitlink-check: decode_operand(test_ldrh, 2) = (named_data + 0)[11:1]
+# jitlink-check: decode_operand(test_ldrsh, 2) = (named_data + 0)[11:1]
+# jitlink-check: decode_operand(test_ldr_32bit, 2) = (named_data + 0)[11:2]
+# jitlink-check: decode_operand(test_ldr_64bit, 2) = (named_data + 0)[11:3]
+# jitlink-check: decode_operand(test_strb, 2) = named_data[11:0]
+# jitlink-check: decode_operand(test_strh, 2) = (named_data + 0)[11:1]
+# jitlink-check: decode_operand(test_str_32bit, 2) = (named_data + 0)[11:2]
+# jitlink-check: decode_operand(test_str_64bit, 2) = (named_data + 0)[11:3]
+
+        .globl  test_ldrb
+test_ldrb:
+        ldrb	w0, [x1, :lo12:named_data]
+        .size test_ldrb, .-test_ldrb
+
+        .globl  test_ldrsb
+test_ldrsb:
+        ldrsb	w0, [x1, :lo12:named_data]
+        .size test_ldrsb, .-test_ldrsb
+
+        .globl  test_ldrh
+test_ldrh:
+        ldrh	w0, [x1, :lo12:named_data]
+        .size test_ldrh, .-test_ldrh
+
+        .globl  test_ldrsh
+test_ldrsh:
+        ldrsh	w0, [x1, :lo12:named_data]
+        .size test_ldrsh, .-test_ldrsh
+
+        .globl  test_ldr_32bit
+test_ldr_32bit:
+        ldr	w0, [x1, :lo12:named_data]
+        .size test_ldr_32bit, .-test_ldr_32bit
+
+        .globl  test_ldr_64bit
+test_ldr_64bit:
+        ldr	x0, [x1, :lo12:named_data]
+        .size test_ldr_64bit, .-test_ldr_64bit
+
+        .globl  test_strb
+test_strb:
+        strb	w0, [x1, :lo12:named_data]
+        .size test_strb, .-test_strb
+
+        .globl  test_strh
+test_strh:
+        strh	w0, [x1, :lo12:named_data]
+        .size test_strh, .-test_strh
+
+        .globl  test_str_32bit
+test_str_32bit:
+        str	w0, [x1, :lo12:named_data]
+        .size test_str_32bit, .-test_str_32bit
+
+        .globl  test_str_64bit
+test_str_64bit:
+        str	x0, [x1, :lo12:named_data]
+        .size test_str_64bit, .-test_str_64bit
+
         .globl  named_data
         .p2align  4
         .type   named_data, at object


        


More information about the llvm-commits mailing list