[lld] 3a55a2a - [LLD][PowerPC] Add support for R_PPC64_PCREL34

Kamau Bridgeman via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 23 12:59:46 PDT 2020


Author: Stefan Pintilie
Date: 2020-06-23T14:59:19-05:00
New Revision: 3a55a2a97fd419c1b6c5299b3523846a9fa9bc52

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

LOG: [LLD][PowerPC] Add support for R_PPC64_PCREL34

Add support for the 34bit relocation R_PPC64_PCREL34 for PC Relative in LLD.

Added: 
    lld/test/ELF/ppc64-reloc-pcrel34-overflow.s
    lld/test/ELF/ppc64-reloc-pcrel34.s

Modified: 
    lld/ELF/Arch/PPC64.cpp

Removed: 
    


################################################################################
diff  --git a/lld/ELF/Arch/PPC64.cpp b/lld/ELF/Arch/PPC64.cpp
index a182c77209ae..cadbf9ad3ec2 100644
--- a/lld/ELF/Arch/PPC64.cpp
+++ b/lld/ELF/Arch/PPC64.cpp
@@ -376,6 +376,20 @@ static uint32_t readFromHalf16(const uint8_t *loc) {
   return read32(config->isLE ? loc : loc - 2);
 }
 
+// The prefixed instruction is always a 4 byte prefix followed by a 4 byte
+// instruction. Therefore, the prefix is always in lower memory than the
+// instruction (regardless of endianness).
+// As a result, we need to shift the pieces around on little endian machines.
+static void writePrefixedInstruction(uint8_t *loc, uint64_t insn) {
+  insn = config->isLE ? insn << 32 | insn >> 32 : insn;
+  write64(loc, insn);
+}
+
+static uint64_t readPrefixedInstruction(const uint8_t *loc) {
+  uint64_t fullInstr = read64(loc);
+  return config->isLE ? (fullInstr << 32 | fullInstr >> 32) : fullInstr;
+}
+
 PPC64::PPC64() {
   copyRel = R_PPC64_COPY;
   gotRel = R_PPC64_GLOB_DAT;
@@ -670,6 +684,7 @@ RelExpr PPC64::getRelExpr(RelType type, const Symbol &s,
   case R_PPC64_REL16_HI:
   case R_PPC64_REL32:
   case R_PPC64_REL64:
+  case R_PPC64_PCREL34:
     return R_PC;
   case R_PPC64_GOT_TLSGD16:
   case R_PPC64_GOT_TLSGD16_HA:
@@ -986,6 +1001,17 @@ void PPC64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
   case R_PPC64_DTPREL64:
     write64(loc, val - dynamicThreadPointerOffset);
     break;
+  case R_PPC64_PCREL34: {
+    const uint64_t si0Mask = 0x00000003ffff0000;
+    const uint64_t si1Mask = 0x000000000000ffff;
+    const uint64_t fullMask = 0x0003ffff0000ffff;
+    checkInt(loc, val, 34, rel);
+
+    uint64_t instr = readPrefixedInstruction(loc) & ~fullMask;
+    writePrefixedInstruction(loc, instr | ((val & si0Mask) << 16) |
+                             (val & si1Mask));
+    break;
+  }
   default:
     llvm_unreachable("unknown relocation");
   }

diff  --git a/lld/test/ELF/ppc64-reloc-pcrel34-overflow.s b/lld/test/ELF/ppc64-reloc-pcrel34-overflow.s
new file mode 100644
index 000000000000..a97160a430dd
--- /dev/null
+++ b/lld/test/ELF/ppc64-reloc-pcrel34-overflow.s
@@ -0,0 +1,21 @@
+# REQUIRES: ppc
+# RUN: echo 'SECTIONS { \
+# RUN:       .text_low 0x10010000: { *(.text_low) } \
+# RUN:       .text_overflow 0x1000000000 : { *(.text_overflow) } \
+# RUN:       }' > %t.script
+
+# RUN: llvm-mc -filetype=obj -triple=powerpc64le %s -o %t.o
+# RUN: not ld.lld -T %t.script %t.o -o %t
+
+# RUN: llvm-mc -filetype=obj -triple=powerpc64 %s -o %t.o
+# RUN: not ld.lld -T %t.script %t.o -o %t
+
+.section .text_low, "ax", %progbits
+# CHECK: relocation R_PPC64_PCREL34 out of range
+GlobIntOverflow:
+	plwa 3, glob_overflow at PCREL(0), 1
+	blr
+.section .text_overflow, "ax", %progbits
+glob_overflow:
+	.long	0
+	.size	glob_overflow, 4

diff  --git a/lld/test/ELF/ppc64-reloc-pcrel34.s b/lld/test/ELF/ppc64-reloc-pcrel34.s
new file mode 100644
index 000000000000..1bc2adf8dcdd
--- /dev/null
+++ b/lld/test/ELF/ppc64-reloc-pcrel34.s
@@ -0,0 +1,49 @@
+# REQUIRES: ppc
+# RUN: echo 'SECTIONS { \
+# RUN:       .text_low 0x10010000: { *(.text_low) } \
+# RUN:       .text_high 0x10080000 : { *(.text_high) } \
+# RUN:       }' > %t.script
+
+# RUN: llvm-mc -filetype=obj -triple=powerpc64le %s -o %t.o
+# RUN: ld.lld -T %t.script %t.o -o %t
+# RUN: llvm-readelf -s %t | FileCheck %s --check-prefix=SYMBOL
+# RUN: llvm-objdump -d --no-show-raw-insn --mcpu=future %t | FileCheck %s
+
+# RUN: llvm-mc -filetype=obj -triple=powerpc64 %s -o %t.o
+# RUN: ld.lld -T %t.script %t.o -o %t
+# RUN: llvm-readelf -s %t | FileCheck %s --check-prefix=SYMBOL
+# RUN: llvm-objdump -d --no-show-raw-insn --mcpu=future %t | FileCheck %s
+
+.section .text_low, "ax", %progbits
+# CHECK-LABEL: <GlobIntPCRel>:
+# CHECK-NEXT:    10010000:        plwa 3, 12(0), 1
+# SYMBOL:        1001000c     4 NOTYPE  LOCAL  DEFAULT     1 glob_int
+GlobIntPCRel:
+	plwa 3, glob_int at PCREL(0), 1
+	blr
+glob_int:
+	.long	0
+	.size	glob_int, 4
+
+
+# CHECK-LABEL: <GlobIntPCRelOffset>:
+# CHECK-NEXT:    10010010:        plwa 3, 16(0), 1
+# SYMBOL:        1001001c     8 NOTYPE  LOCAL  DEFAULT     1 glob_int8
+GlobIntPCRelOffset:
+	plwa 3, glob_int8 at PCREL+4(0), 1
+	blr
+glob_int8:
+	.quad	0
+	.size	glob_int8, 8
+
+
+# CHECK-LABEL: <GlobIntPCRelBigOffset>:
+# CHECK-NEXT:    10010024:        plwa 3, 458720(0), 1
+# SYMBOL:        10080000     8 NOTYPE  LOCAL  DEFAULT     2 glob_int8_big
+GlobIntPCRelBigOffset:
+	plwa 3, glob_int8_big at PCREL+4(0), 1
+	blr
+.section .text_high, "ax", %progbits
+glob_int8_big:
+	.quad	0
+	.size	glob_int8_big, 8


        


More information about the llvm-commits mailing list