[lld] f0adf3a - [PowerPC][LLD] Make sure that the correct Thunks are used.

Stefan Pintilie via llvm-commits llvm-commits at lists.llvm.org
Thu May 6 10:00:13 PDT 2021


Author: Stefan Pintilie
Date: 2021-05-06T12:00:04-05:00
New Revision: f0adf3a24cdedb4c48e49a8792c5cfbd40ba3345

URL: https://github.com/llvm/llvm-project/commit/f0adf3a24cdedb4c48e49a8792c5cfbd40ba3345
DIFF: https://github.com/llvm/llvm-project/commit/f0adf3a24cdedb4c48e49a8792c5cfbd40ba3345.diff

LOG: [PowerPC][LLD] Make sure that the correct Thunks are used.

This fixes an issue where mixed TOC / NOTOC calls can call the incorrect
thunks if a previous thunk already exists. The issue appears when a TOC
funciton calls a NOTOC callee and then a different NOTOC function calls the same
NOTOC callee. In this case the linker would sometimes incorrectly call the
same thunk for both cases.

Reviewed By: MaskRay

Differential Revision: https://reviews.llvm.org/D101837

Added: 
    lld/test/ELF/ppc64-pcrel-cross-link.s

Modified: 
    lld/ELF/Thunks.cpp

Removed: 
    


################################################################################
diff  --git a/lld/ELF/Thunks.cpp b/lld/ELF/Thunks.cpp
index 331c5c89d5016..3d9b6517f91bf 100644
--- a/lld/ELF/Thunks.cpp
+++ b/lld/ELF/Thunks.cpp
@@ -312,6 +312,8 @@ class PPC64R2SaveStub final : public Thunk {
   uint32_t size() override { return getMayUseShortThunk() ? 8 : 32; }
   void writeTo(uint8_t *buf) override;
   void addSymbols(ThunkSection &isec) override;
+  bool isCompatibleWith(const InputSection &isec,
+                        const Relocation &rel) const override;
 
 private:
   // Transitioning from long to short can create layout oscillations in
@@ -333,6 +335,8 @@ class PPC64R12SetupStub final : public Thunk {
   uint32_t size() override { return 32; }
   void writeTo(uint8_t *buf) override;
   void addSymbols(ThunkSection &isec) override;
+  bool isCompatibleWith(const InputSection &isec,
+                        const Relocation &rel) const override;
 };
 
 // PPC64 PC-relative PLT Stub
@@ -965,6 +969,11 @@ void PPC64R2SaveStub::addSymbols(ThunkSection &isec) {
   s->needsTocRestore = true;
 }
 
+bool PPC64R2SaveStub::isCompatibleWith(const InputSection &isec,
+                                       const Relocation &rel) const {
+  return rel.type == R_PPC64_REL24 || rel.type == R_PPC64_REL14;
+}
+
 void PPC64R12SetupStub::writeTo(uint8_t *buf) {
   int64_t offset = destination.getVA() - getThunkTargetSym()->getVA();
   if (!isInt<34>(offset))
@@ -995,6 +1004,11 @@ void PPC64R12SetupStub::addSymbols(ThunkSection &isec) {
             isec);
 }
 
+bool PPC64R12SetupStub::isCompatibleWith(const InputSection &isec,
+                                         const Relocation &rel) const {
+  return rel.type == R_PPC64_REL24_NOTOC;
+}
+
 void PPC64PCRelPLTStub::writeTo(uint8_t *buf) {
   int nextInstOffset = 0;
   int64_t offset = destination.getGotPltVA() - getThunkTargetSym()->getVA();

diff  --git a/lld/test/ELF/ppc64-pcrel-cross-link.s b/lld/test/ELF/ppc64-pcrel-cross-link.s
new file mode 100644
index 0000000000000..620e113196bd9
--- /dev/null
+++ b/lld/test/ELF/ppc64-pcrel-cross-link.s
@@ -0,0 +1,140 @@
+# REQUIRES: ppc
+# RUN: split-file %s %t
+
+# RUN: llvm-mc -filetype=obj -triple=powerpc64le %t/callees.s -o %t-callees.o
+# RUN: llvm-mc -filetype=obj -triple=powerpc64le %t/callertoc.s -o %t-callertoc.o
+# RUN: llvm-mc -filetype=obj -triple=powerpc64le %t/callernotoc.s -o %t-callernotoc.o
+# RUN: ld.lld -T %t/lds %t-callees.o %t-callernotoc.o %t-callertoc.o -o %t-r12setup
+# RUN: ld.lld -T %t/ldsswap %t-callees.o %t-callernotoc.o %t-callertoc.o -o %t-r2save
+
+# RUN: llvm-objdump -d --no-show-raw-insn --mcpu=pwr10 %t-r12setup | \
+# RUN:   FileCheck %s --check-prefix=NOSWAP
+# RUN: llvm-objdump -d --no-show-raw-insn --mcpu=pwr10 %t-r2save | \
+# RUN:   FileCheck %s --check-prefix=SWAP
+
+## This test checks that it is possible to mix TOC and NOTOC functions and have
+## the correct thunks for all of the calls.
+
+# NOSWAP-LABEL: 01001000 <func>:
+# NOSWAP-NEXT:    blr
+# NOSWAP-LABEL: 01002000 <callee_toc>:
+# NOSWAP:         bl 0x1001000
+# NOSWAP:         blr
+# NOSWAP-LABEL: 01002018 <callee_notoc>:
+# NOSWAP:         bl 0x1001000
+# NOSWAP:         blr
+# NOSWAP-LABEL: 10030000 <caller_notoc>:
+# NOSWAP-NEXT:    bl 0x10030010
+# NOSWAP-NEXT:    bl 0x10030030
+# NOSWAP-NEXT:    blr
+# NOSWAP-LABEL: 10030010 <__gep_setup_callee_toc>:
+# NOSWAP:         bctr
+# NOSWAP-LABEL: 10030030 <__long_branch_pcrel_callee_notoc>:
+# NOSWAP:         bctr
+# NOSWAP-LABEL: 10040000 <caller_toc>:
+# NOSWAP:         bl 0x10040020
+# NOSWAP-NEXT:    nop
+# NOSWAP-NEXT:    bl 0x10040040
+# NOSWAP-NEXT:    ld 2, 24(1)
+# NOSWAP-NEXT:    blr
+# NOSWAP-LABEL: 10040020 <__long_branch_callee_toc>:
+# NOSWAP:         bctr
+# NOSWAP-LABEL: 10040040 <__toc_save_callee_notoc>:
+# NOSWAP-NEXT:    std 2, 24(1)
+# NOSWAP:         bctr
+
+# SWAP-LABEL: 01001000 <func>:
+# SWAP-NEXT:    blr
+# SWAP-LABEL: 01002000 <callee_toc>:
+# SWAP:         bl 0x1001000
+# SWAP:         blr
+# SWAP-LABEL: 01002018 <callee_notoc>:
+# SWAP:         bl 0x1001000
+# SWAP:         blr
+# SWAP-LABEL: 10030000 <caller_toc>:
+# SWAP:         bl 0x10030020
+# SWAP-NEXT:    nop
+# SWAP-NEXT:    bl 0x10030040
+# SWAP-NEXT:    ld 2, 24(1)
+# SWAP-NEXT:    blr
+# SWAP-LABEL: 10030020 <__long_branch_callee_toc>:
+# SWAP:         bctr
+# SWAP-LABEL: 10030040 <__toc_save_callee_notoc>:
+# SWAP-NEXT:    std 2, 24(1)
+# SWAP:         bctr
+# SWAP-LABEL: 10040000 <caller_notoc>:
+# SWAP-NEXT:    bl 0x10040010
+# SWAP-NEXT:    bl 0x10040030
+# SWAP-NEXT:    blr
+# SWAP-LABEL: 10040010 <__gep_setup_callee_toc>:
+# SWAP:         bctr
+# SWAP-LABEL: 10040030 <__long_branch_pcrel_callee_notoc>:
+# SWAP:         bctr
+
+#--- lds
+SECTIONS {
+  .text_func         0x1001000 : { *(.text_func) }
+  .text_callee       0x1002000 : { *(.text_callee) }
+  .text_caller_notoc 0x10030000 : { *(.text_caller_notoc) }
+  .text_caller_toc   0x10040000 : { *(.text_caller_toc) }
+}
+
+#--- ldsswap
+SECTIONS {
+  .text_func         0x1001000 : { *(.text_func) }
+  .text_callee       0x1002000 : { *(.text_callee) }
+  .text_caller_toc   0x10030000 : { *(.text_caller_toc) }
+  .text_caller_notoc 0x10040000 : { *(.text_caller_notoc) }
+}
+
+#--- callees.s
+.section .text_func, "ax", %progbits
+func:
+  blr
+
+.globl callee_toc
+.section .text_callee, "ax", %progbits
+callee_toc:
+.Lfunc_gep1:
+  addis 2, 12, .TOC.-.Lfunc_gep1 at ha
+  addi 2, 2, .TOC.-.Lfunc_gep1 at l
+.Lfunc_lep1:
+  .localentry callee_toc, .Lfunc_lep1-.Lfunc_gep1
+  bl func
+  addis 4, 2, global at toc@ha
+  lwz 4, global at toc@l(4)
+  blr
+
+.globl callee_notoc
+callee_notoc:
+  .localentry callee_notoc, 1
+  bl func
+  plwz 4, global at pcrel(0), 1
+  blr
+
+## .globl global
+global:
+  .long	0
+  .size	global, 4
+
+#--- callernotoc.s
+.section .text_caller_notoc, "ax", %progbits
+caller_notoc:
+  .localentry caller, 1
+  bl callee_toc at notoc
+  bl callee_notoc at notoc
+  blr
+
+#--- callertoc.s
+.section .text_caller_toc, "ax", %progbits
+caller_toc:
+.Lfunc_gep2:
+  addis 2, 12, .TOC.-.Lfunc_gep2 at ha
+  addi 2, 2, .TOC.-.Lfunc_gep2 at l
+.Lfunc_lep2:
+  .localentry caller_toc, .Lfunc_lep2-.Lfunc_gep2
+  bl callee_toc
+  nop
+  bl callee_notoc
+  nop
+  blr


        


More information about the llvm-commits mailing list