[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