[PPC64] Support got-based relocations.
Differential Revison: https://reviews.llvm.org/D54859
git-svn-id: https://llvm.org/svn/llvm-project/lld/trunk@349511 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/ELF/Arch/PPC64.cpp b/ELF/Arch/PPC64.cpp
index 259ebf7..4d42a26 100644
--- a/ELF/Arch/PPC64.cpp
+++ b/ELF/Arch/PPC64.cpp
@@ -412,6 +412,13 @@
RelExpr PPC64::getRelExpr(RelType Type, const Symbol &S,
const uint8_t *Loc) const {
switch (Type) {
+ case R_PPC64_GOT16:
+ case R_PPC64_GOT16_DS:
+ case R_PPC64_GOT16_HA:
+ case R_PPC64_GOT16_HI:
+ case R_PPC64_GOT16_LO:
+ case R_PPC64_GOT16_LO_DS:
+ return R_GOT_OFF;
case R_PPC64_TOC16:
case R_PPC64_TOC16_DS:
case R_PPC64_TOC16_HA:
@@ -526,30 +533,36 @@
switch (Type) {
// TOC biased relocation.
+ case R_PPC64_GOT16:
case R_PPC64_GOT_TLSGD16:
case R_PPC64_GOT_TLSLD16:
case R_PPC64_TOC16:
return {R_PPC64_ADDR16, TocBiasedVal};
+ case R_PPC64_GOT16_DS:
case R_PPC64_TOC16_DS:
case R_PPC64_GOT_TPREL16_DS:
case R_PPC64_GOT_DTPREL16_DS:
return {R_PPC64_ADDR16_DS, TocBiasedVal};
+ case R_PPC64_GOT16_HA:
case R_PPC64_GOT_TLSGD16_HA:
case R_PPC64_GOT_TLSLD16_HA:
case R_PPC64_GOT_TPREL16_HA:
case R_PPC64_GOT_DTPREL16_HA:
case R_PPC64_TOC16_HA:
return {R_PPC64_ADDR16_HA, TocBiasedVal};
+ case R_PPC64_GOT16_HI:
case R_PPC64_GOT_TLSGD16_HI:
case R_PPC64_GOT_TLSLD16_HI:
case R_PPC64_GOT_TPREL16_HI:
case R_PPC64_GOT_DTPREL16_HI:
case R_PPC64_TOC16_HI:
return {R_PPC64_ADDR16_HI, TocBiasedVal};
+ case R_PPC64_GOT16_LO:
case R_PPC64_GOT_TLSGD16_LO:
case R_PPC64_GOT_TLSLD16_LO:
case R_PPC64_TOC16_LO:
return {R_PPC64_ADDR16_LO, TocBiasedVal};
+ case R_PPC64_GOT16_LO_DS:
case R_PPC64_TOC16_LO_DS:
case R_PPC64_GOT_TPREL16_LO_DS:
case R_PPC64_GOT_DTPREL16_LO_DS:
@@ -590,9 +603,11 @@
}
void PPC64::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
- // For a TOC-relative relocation, proceed in terms of the corresponding
- // ADDR16 relocation type.
+ // We need to save the original relocation type to determine if we should
+ // toc-optimize the instructions being relocated.
bool IsTocRelType = isTocRelType(Type);
+ // For TOC-relative and GOT-indirect relocations, proceed in terms of the
+ // corresponding ADDR16 relocation type.
std::tie(Type, Val) = toAddr16Rel(Type, Val);
switch (Type) {
diff --git a/test/ELF/ppc64-got-off.s b/test/ELF/ppc64-got-off.s
new file mode 100644
index 0000000..0a1a09e
--- /dev/null
+++ b/test/ELF/ppc64-got-off.s
@@ -0,0 +1,50 @@
+# REQUIRES: ppc
+
+# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o
+# RUN: ld.lld -shared --no-toc-optimize %t.o -o %t
+# RUN: llvm-objdump -d %t | FileCheck %s
+
+# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
+# RUN: ld.lld -shared --no-toc-optimize %t.o -o %t
+# RUN: llvm-objdump -d %t | FileCheck %s
+
+ .abiversion 2
+ .section ".text"
+
+ .p2align 2
+ .global func
+ .type func, @function
+func:
+.Lfunc_gep:
+ addis 2, 12, .TOC.-.Lfunc_gep@ha
+ addi 2, 2, .TOC.-.Lfunc_gep@l
+.Lfunc_lep:
+ .localentry func, .-func
+ addis 3, 2, a@got@ha
+ ld 3, a@got@l(3)
+ ld 4, a@got(2)
+ lis 5, a@got@h
+ ori 5, 5, a@got@l
+ li 6, 0
+ ori 6, 6, a@got
+ blr
+
+# CHECK-LABEL: func
+# CHECK: addis 3, 2, 0
+# CHECK-NEXT: ld 3, -32760(3)
+# CHECK-NEXT: ld 4, -32760(2)
+# CHECK-NEXT: lis 5, -1
+# CHECK-NEXT: ori 5, 5, 32776
+# CHECK-NEXT: li 6, 0
+# CHECK-NEXT: ori 6, 6, 32776
+
+# Since the got entry for a is .got[1] and the TOC base points to
+# .got + 0x8000, the offset for a@got is -0x7FF8 --> -32760
+
+ .section ".data"
+ .global a
+ .type a, @object
+ .size a, 4
+ .p2align 2
+a:
+ .long 0x1000