diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -949,7 +949,8 @@ assert(flags & SHF_ALLOC); const unsigned bits = config->wordsize * 8; - for (const Relocation &rel : relocations) { + for (size_t i = 0, e = relocations.size(); i != e; ++i) { + const Relocation &rel = relocations[i]; if (rel.expr == R_NONE) continue; uint64_t offset = rel.offset; @@ -969,10 +970,16 @@ case R_RELAX_GOT_PC_NOPIC: target->relaxGot(bufLoc, rel, targetVA); break; - case R_PPC64_RELAX_TOC: - if (!tryRelaxPPC64TocIndirection(rel, bufLoc)) + case R_PPC64_RELAX_TOC: { + // For R_PPC64_TOC16_HA, if it is not paired with an R_PPC64_TOC16_LO_DS, + // don't relax. + bool relax = + rel.type == R_PPC64_TOC16_LO_DS || + (i + 1 != e && relocations[i + 1].type == R_PPC64_TOC16_LO_DS); + if (!relax || !tryRelaxPPC64TocIndirection(rel, bufLoc)) target->relocate(bufLoc, rel, targetVA); break; + } case R_RELAX_TLS_IE_TO_LE: target->relaxTlsIeToLe(bufLoc, rel, targetVA); break; diff --git a/lld/test/ELF/ppc64-toc-relax2.s b/lld/test/ELF/ppc64-toc-relax2.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/ppc64-toc-relax2.s @@ -0,0 +1,34 @@ +# REQUIRES: ppc +# RUN: llvm-mc -filetype=obj -triple=powerpc64le %s -o %t.o +# RUN: ld.lld %t.o -o %t +# RUN: llvm-objdump -d %t | FileCheck %s + +# CHECK-LABEL: <_start>: +.globl _start +_start: +## Perform toc-indirect to toc-relative relaxation even if there are unrelated instructions in between. +# CHECK-NEXT: addis 3, 2, -1 +# CHECK-NEXT: li 9, 0 +# CHECK-NEXT: addi 3, 3, -32768 +# CHECK-NEXT: lwa 3, 0(3) +# CHECK-NEXT: li 9, 0 + addis 3, 2, .LC0@toc@ha # R_PPC64_TOC16_HA + li 9, 0 + ld 3, .LC0@toc@l(3) # R_PPC64_TOC16_LO_DS + lwa 3, 0(3) + li 9, 0 + +## The R_PPC64_TOC16_HA is not followed by an R_PPC64_TOC16_LO_DS. +## Don't perform toc-indirect to toc-relative relaxation. +# CHECK-NEXT: nop +# CHECK-NEXT: addi 3, 2, -32768 +# CHECK-NEXT: blr + addis 3, 2, .LC0@toc@ha # R_PPC64_TOC16_HA + addi 3, 3, .LC0@toc@l # R_PPC64_TOC16_LO + blr + +AES_encrypt: + +.section .toc,"aw",@progbits +.LC0: + .tc AES_encrypt[TC], AES_encrypt