diff options
author | Alan Modra <amodra@gmail.com> | 2021-06-29 13:31:45 +0930 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2021-07-15 15:27:09 +0930 |
commit | cd6ca96f5d530e4ee07b65ac8b075119ba5bb035 (patch) | |
tree | 5656cb884387d4b3aae4d1aec237dbceaa1bfaa3 /libgcc | |
parent | 4f3b383cf8825197e714a4a21852eca071f8e67e (diff) | |
download | gcc-cd6ca96f5d530e4ee07b65ac8b075119ba5bb035.zip gcc-cd6ca96f5d530e4ee07b65ac8b075119ba5bb035.tar.gz gcc-cd6ca96f5d530e4ee07b65ac8b075119ba5bb035.tar.bz2 |
[POWER10] __morestack calls from pcrel code
Compiling gcc/testsuite/gcc.dg/split-*.c and others with -mcpu=power10
and linking with a non-pcrel libgcc results in crashes due to the
power10 pcrel code not having r2 set for the generic-morestack.c
functions called from __morestack. There is also a problem when
non-pcrel code calls a pcrel libgcc. See the patch comments.
A similar situation theoretically occurs with ELFv1 multi-toc
executables, when __morestack might be located in a different toc
group to its caller. This patch makes no attempt to fix that, since
the gold linker does not support multi-toc (gold is needed for proper
support of -fsplit-stack code) nor does gcc emit __morestack calls
that support multi-toc.
* config/rs6000/morestack.S (R2_SAVE): Define.
(__morestack): Save and restore r2. Set up r2 for called
functions.
Diffstat (limited to 'libgcc')
-rw-r--r-- | libgcc/config/rs6000/morestack.S | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/libgcc/config/rs6000/morestack.S b/libgcc/config/rs6000/morestack.S index 4a07de9..a2e255e 100644 --- a/libgcc/config/rs6000/morestack.S +++ b/libgcc/config/rs6000/morestack.S @@ -31,6 +31,7 @@ #define PARAMS 48 #endif #define MORESTACK_FRAMESIZE (PARAMS+96) +#define R2_SAVE -MORESTACK_FRAMESIZE+PARAMS-8 #define PARAMREG_SAVE -MORESTACK_FRAMESIZE+PARAMS+0 #define STATIC_CHAIN_SAVE -MORESTACK_FRAMESIZE+PARAMS+64 #define R29_SAVE -MORESTACK_FRAMESIZE+PARAMS+72 @@ -143,6 +144,17 @@ ENTRY0(__morestack_non_split) # cr7 must also be preserved. ENTRY0(__morestack) + +#if _CALL_ELF == 2 +# Functions with localentry bits of zero cannot make calls if those +# calls might change r2. This is true generally, and also true for +# __morestack with its special calling convention. When __morestack's +# caller is non-pcrel but libgcc is pcrel, the functions called here +# might modify r2. r2 must be preserved on exit, and also restored +# for the call back to our caller. + std %r2,R2_SAVE(%r1) +#endif + # Save parameter passing registers, our arguments, lr, r29 # and use r29 as a frame pointer. std %r3,PARAMREG_SAVE+0(%r1) @@ -161,10 +173,24 @@ ENTRY0(__morestack) std %r12,LINKREG_SAVE(%r1) std %r3,NEWSTACKSIZE_SAVE(%r1) # new stack size mr %r29,%r1 +#if _CALL_ELF == 2 + .cfi_offset %r2,R2_SAVE +#endif .cfi_offset %r29,R29_SAVE .cfi_def_cfa_register %r29 stdu %r1,-MORESTACK_FRAMESIZE(%r1) +#if _CALL_ELF == 2 && !defined __PCREL__ +# If this isn't a pcrel libgcc then the functions we call here will +# require r2 to be valid. If __morestack is called from pcrel code r2 +# won't be valid. Set it up. + bcl 20,31,1f +1: + mflr %r12 + addis %r2,%r12,.TOC.-1b@ha + addi %r2,%r2,.TOC.-1b@l +#endif + # void __morestack_block_signals (void) bl JUMP_TARGET(__morestack_block_signals) @@ -199,6 +225,9 @@ ENTRY0(__morestack) # instructions after __morestack's return address. # ld %r12,LINKREG_SAVE(%r29) +#if _CALL_ELF == 2 + ld %r2,R2_SAVE(%r29) +#endif ld %r3,PARAMREG_SAVE+0(%r29) # restore arg regs ld %r4,PARAMREG_SAVE+8(%r29) ld %r5,PARAMREG_SAVE+16(%r29) @@ -228,6 +257,15 @@ ENTRY0(__morestack) std %r10,PARAMREG_SAVE+56(%r29) #endif +#if _CALL_ELF == 2 && !defined __PCREL__ +# r2 was restored for calling back into our caller. Set it up again. + bcl 20,31,1f +1: + mflr %r12 + addis %r2,%r12,.TOC.-1b@ha + addi %r2,%r2,.TOC.-1b@l +#endif + bl JUMP_TARGET(__morestack_block_signals) # void *__generic_releasestack (size_t *pavailable) @@ -249,6 +287,9 @@ ENTRY0(__morestack) # Restore return value regs, and return. ld %r0,LINKREG_SAVE(%r29) mtlr %r0 +#if _CALL_ELF == 2 + ld %r2,R2_SAVE(%r29) +#endif ld %r3,PARAMREG_SAVE+0(%r29) ld %r4,PARAMREG_SAVE+8(%r29) ld %r5,PARAMREG_SAVE+16(%r29) |