Fix logic error in 32-bit trampolines.

The test in the PowerPC 32-bit trampoline support is backwards.  It aborts
if the trampoline size is greater than the expected size.  It should abort
when the trampoline size is less than the expected size.  I fixed the test
so the operands are reversed.  I then folded the load immediate into the
compare instruction.

I verified this by creating a 32-bit trampoline program and manually
changing the size of the trampoline to be 48 instead of 40.  The program
aborted with the larger size.  I updated this code and ran the test again
and it passed.

I added a test case that runs on PowerPC 32-bit Linux systems and it calls
the __trampoline_setup function with a larger buffer size than the
compiler uses.  The test is not run on 64-bit systems, since the function
__trampoline_setup is not called.  I also limited the test to just Linux
systems, in case trampolines are handled differently in other systems.

libgcc/
2021-04-23  Michael Meissner  <meissner@linux.ibm.com>

	PR target/98952
	* config/rs6000/tramp.S (__trampoline_setup, elfv1 #ifdef): Fix
	trampoline size comparison in 32-bit by reversing test and
	combining load immediate with compare.
	(__trampoline_setup, elfv2 #ifdef): Fix trampoline size comparison
	in 32-bit by reversing test and combining load immediate with
	compare.

gcc/testsuite/
2021-04-23  Michael Meissner  <meissner@linux.ibm.com>

	PR target/98952
	* gcc.target/powerpc/pr98952.c: New test.
This commit is contained in:
Michael Meissner 2021-04-23 18:16:03 -04:00
parent 886b6c1e8a
commit 9a30a3f06b
2 changed files with 30 additions and 4 deletions

View file

@ -0,0 +1,28 @@
/* { dg-do run { target { powerpc*-*-linux* && ilp32 } } } */
/* { dg-options "-O2" } */
/* PR 96983 reported that the test in libgcc's tramp.S was backwards and it
would abort if the trampoline size passed to the function was greater than
the size the runtime was expecting (40). It should abort if the size is less
than 40, not greater than 40. This test creates a call to __trampoline_setup
with a much larger buffer to make sure the function does not abort.
We do not run this test on 64-bit since __trampoline_setup is not present in
64-bit systems.
We only run the test under Linux in case the other systems have some
different variant for __trampoline_setup. */
#ifndef SIZE
#define SIZE 100
#endif
extern void __trampoline_setup (int *, unsigned, void *, void *);
int main (void)
{
int tramp[SIZE / sizeof (int)];
__trampoline_setup (tramp, SIZE, 0, 0);
return 0;
}

View file

@ -64,8 +64,7 @@ FUNC_START(__trampoline_setup)
mflr r11
addi r7,r11,trampoline_initial-4-.LCF0 /* trampoline address -4 */
li r8,trampoline_size /* verify that the trampoline is big enough */
cmpw cr1,r8,r4
cmpwi cr1,r4,trampoline_size /* verify that the trampoline is big enough */
srwi r4,r4,2 /* # words to move */
addi r9,r3,-4 /* adjust pointer for lwzu */
mtctr r4
@ -156,8 +155,7 @@ FUNC_START(__trampoline_setup)
ld 7,.LC0@toc@l(7) /* trampoline address -8 */
#endif
li r8,trampoline_size /* verify that the trampoline is big enough */
cmpw cr1,r8,r4
cmpwi cr1,r4,trampoline_size /* verify that the trampoline is big enough */
srwi r4,r4,3 /* # doublewords to move */
addi r9,r3,-8 /* adjust pointer for stdu */
mtctr r4