diff --git a/lld/ELF/Arch/PPC64.cpp b/lld/ELF/Arch/PPC64.cpp --- a/lld/ELF/Arch/PPC64.cpp +++ b/lld/ELF/Arch/PPC64.cpp @@ -671,6 +671,8 @@ case R_PPC64_TOC16_HI: case R_PPC64_TOC16_LO: return R_GOTREL; + case R_PPC64_GOT_PCREL34: + return R_GOT_PC; case R_PPC64_TOC16_HA: case R_PPC64_TOC16_LO_DS: return config->tocOptimize ? R_PPC64_RELAX_TOC : R_GOTREL; @@ -1012,6 +1014,17 @@ (val & si1Mask)); break; } + case R_PPC64_GOT_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-got-pcrel34.s b/lld/test/ELF/ppc64-reloc-got-pcrel34.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/ppc64-reloc-got-pcrel34.s @@ -0,0 +1,51 @@ +# 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 --shared %t.o -o %t +# RUN: llvm-readelf -s %t | FileCheck %s --check-prefix=SYMBOL +# RUN: llvm-readelf -r %t | FileCheck %s --check-prefix=RELA +# 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 --shared %t.o -o %t +# RUN: llvm-readelf -s %t | FileCheck %s --check-prefix=SYMBOL +# RUN: llvm-readelf -r %t | FileCheck %s --check-prefix=RELA +# RUN: llvm-objdump -d --no-show-raw-insn --mcpu=future %t | FileCheck %s + +.text +.section .text_low, "ax", %progbits +# CHECK-LABEL: : +# CHECK-NEXT: pld 3, 458928(0), 1 +# CHECK-NEXT: lwa 3, 0(3) +# SYMBOL: Symbol table '.dynsym' contains 4 entries: +# SYMBOL: 00000000 0 NOTYPE GLOBAL DEFAULT UND glob_int +# RELA: 100800b0 0000000100000014 R_PPC64_GLOB_DAT 0000000000000000 glob_int + 0 +GlobIntPCRel: + pld 3, glob_int@got@PCREL(0), 1 + lwa 3, 0(3) + blr + +# CHECK-LABEL: : +# CHECK-NEXT: pld 3, 458920(0), 1 +# CHECK-NEXT: lwa 3, 8(3) +# SYMBOL: 00000000 0 NOTYPE GLOBAL DEFAULT UND glob_int8 +# RELA: 100800b8 0000000200000014 R_PPC64_GLOB_DAT 0000000000000000 glob_int8 + 0 +GlobIntPCRelOffset: + pld 3, glob_int8@got@PCREL(0), 1 + lwa 3, 8(3) + blr + +# CHECK-LABEL: : +# CHECK-NEXT: pld 3, 192(0), 1 +# CHECK-NEXT: lwa 3, 64(3) +# SYMBOL: 00000000 0 NOTYPE GLOBAL DEFAULT UND glob_int8_big +# RELA: 100800c0 0000000300000014 R_PPC64_GLOB_DAT 0000000000000000 glob_int8_big + 0 +.section .text_high, "ax", %progbits +GlobIntPCRelBigOffset: + pld 3, glob_int8_big@got@PCREL(0), 1 + lwa 3, 64(3) + blr