diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -485,6 +485,14 @@ p->r_addend = sym.getVA(addend) - section->getOutputSection()->addr; else if (config->relocatable && type != target->noneRel) sec->relocations.push_back({R_ABS, type, rel.r_offset, addend, &sym}); + } else if (config->emachine == EM_PPC && type == R_PPC_PLTREL24 && + p->r_addend >= 0x8000) { + // Similar to R_MIPS_GPREL{16,32}. If the addend of R_PPC_PLTREL24 + // indicates that r30 is relative to the input section .got2 + // (r_addend>=0x8000), after linking, r30 should be relative to the output + // section .got2 . To compensate for the shift, adjust r_addend by + // ppc32Got2OutSecOff. + p->r_addend += sec->file->ppc32Got2OutSecOff; } } } diff --git a/lld/test/ELF/ppc32-relocatable-got2.s b/lld/test/ELF/ppc32-relocatable-got2.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/ppc32-relocatable-got2.s @@ -0,0 +1,41 @@ +# REQUIRES: ppc +## Test addend adjustment of R_PPC_PLTREL24 when copying relocations. +## If r_addend indicates .got2, adjust it by the local .got2's output section offset. + +# RUN: llvm-mc -filetype=obj -triple=powerpc %s -o %t.o +# RUN: ld.lld -r %t.o %t.o -o %t +# RUN: llvm-readobj -r %t | FileCheck %s + +# RUN: ld.lld -shared --emit-relocs %t.o %t.o -o %t.so +# RUN: llvm-readobj -r %t.so | FileCheck %s + +# CHECK: .rela.adjust { +# CHECK-NEXT: R_PPC_REL16_HA .got2 0x8002 +# CHECK-NEXT: R_PPC_REL16_LO .got2 0x8006 +# CHECK-NEXT: R_PPC_PLTREL24 foo 0x8000 +# CHECK-NEXT: R_PPC_PLTREL24 bar 0x8000 +# CHECK-NEXT: R_PPC_REL16_HA .got2 0x8006 +# CHECK-NEXT: R_PPC_REL16_LO .got2 0x800A +# CHECK-NEXT: R_PPC_PLTREL24 foo 0x8004 +# CHECK-NEXT: R_PPC_PLTREL24 bar 0x8004 +# CHECK-NEXT: } +# CHECK-NEXT: .rela.no_adjust { +# CHECK-NEXT: R_PPC_PLTREL24 foo 0x0 +# CHECK-NEXT: R_PPC_PLTREL24 foo 0x0 +# CHECK-NEXT: } +.section .got2,"aw" +.long 0 + +.section .adjust,"ax" +bcl 20,30,.L0 +.L0: +addis 30,30,.got2+0x8000-.L0@ha +addi 30,30,.got2+0x8000-.L0@l + +## Refers to .got2+addend, adjust. +bl foo+0x8000@plt +bl bar+0x8000@plt + +.section .no_adjust,"ax" +## Refers to .got, no adjustment. +bl foo@plt