Index: ELF/Arch/PPC64.cpp =================================================================== --- ELF/Arch/PPC64.cpp +++ 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: @@ -525,30 +532,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: @@ -589,9 +602,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) { Index: test/ELF/ppc64-got-off.s =================================================================== --- /dev/null +++ test/ELF/ppc64-got-off.s @@ -0,0 +1,47 @@ +# 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 + + + .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