NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: port-macppc/54827: alloca() is broken in gcc 8 on powerpc



The following reply was made to PR port-macppc/54827; it has been noted by GNATS.

From: Valery Ushakov <uwe%stderr.spb.ru@localhost>
To: gnats-bugs%netbsd.org@localhost
Cc: 
Subject: Re: port-macppc/54827: alloca() is broken in gcc 8 on powerpc
Date: Sat, 18 Jan 2020 20:24:58 +0300

 TL;DR: I suspect we might be inconsistently defining STACK_BOUNDARY.
 Its override in netbsd.h has this comment:
 
   /* Override STACK_BOUNDARY to use Altivec compliant one.  */
 
 I suspect some other define needs to be adjusted as well, but isn't.
 The bug doesn't happen with explicit -maltivec (that probably whacks
 that other value to be cosistent with "always altivec" STACK_BOUNDARY).
 
 
 
 I'm testing against stock gcc-8.3.0 cross-compiler configured with
 
   ./configure --target=powerpc--netbsd
 
 Running make to build it will eventually fail b/c the rest of the
 cross-toolchain is not present, but we don't care b/c by that time we
 already have "cc1" built, which is all that we really need here.
 
 
 $ cat main.c            # ----8<--------8<----
 #include <stdio.h>
 #include <string.h>
 
 void foo();
 
 int
 main()
 {
     foo();
     return 0;
 }
 
 
 void
 bar(char *s, int *pi)
 {
     printf("%p %p\n", s, pi);
 
     strcpy(s, "overwrite");
     printf("%#x\n", *pi);
 }
 
 
 
 $ cat alloca-test.c     # ----8<--------8<----
 void bar(char *, int *);
 
 void
 foo()
 {
     char *s;
     int i;
 
     s = __builtin_alloca(10);	/* sizeof("overwrite") */
     i = 0;
     bar(s, &i);
 }
 
 
 
 We are going to build all the interesting permutations, so here's the
 helper script.  -mregnames makes the output readable.  In-tree
 compiler emits CFI directives, but the stock compiler emits .eh_frame
 instead and seems to ignore -fdwarf2-cfi-asm, but eh_frame is even
 more convenient since we can ignore differences in it wholesale.
 
 
 $ cat runme.sh          # ----8<--------8<----
 CC1=.../gcc-8.3.0/host-x86_64-pc-linux-gnu/gcc/cc1	# stock gcc
 NB1=.../tools/libexec/gcc/powerpc--netbsd/8.3.0/cc1	# $TOOLDIR
 
 compile() {
     cc1=$1; kind=$2; in=$3
     base=out
 
     CC="$cc1 -quiet -fno-dwarf2-cfi-asm -mregnames $in"
 
     $CC -mno-altivec -O0 -o $base-$kind-no0.s
     $CC -mno-altivec -O2 -o $base-$kind-no2.s
 
     $CC -maltivec    -O0 -o $base-$kind-av0.s
     $CC -maltivec    -O2 -o $base-$kind-av2.s
 }
 
 compile $CC1 dist alloca-test.c
 compile $NB1 nb   alloca-test.c
 $ sh runme.sh
 $ ls *.s
 out-dist-av0.s	out-dist-no0.s	out-nb-av0.s  out-nb-no0.s
 out-dist-av2.s	out-dist-no2.s	out-nb-av2.s  out-nb-no2.s
 
 
 We can now confirm the problem using the .s file produced by the
 in-tree gcc8 compiler from -current with -O2 and without -maltivec.
 This test is done on my macppc 8-stable box.
 
 ppc$ cc -g -O0 main.c out-nb-no2.s && ./a.out 
 0xffffe1f0 0xffffe1f8
 0x65000000
 
 Allocated memory (0xffffe1f0 + 10 bytes) overlaps the stack slot where
 "i" lives (0xffffe1f8) so strcpy overwrites its value as we can see in
 the next output line ('e' is 0x65, macppc is big-endian).
 
 In-tree compiler with -maltivec produces the same (correct) output as
 the stock compiler with -maltivec:
 
 $ diff -u out-nb-av0.s out-dist-av0.s | sed '/eh_frame/q'
 --- out-nb-av0.s        2020-01-18 20:00:51.164188737 +0300
 +++ out-dist-av0.s      2020-01-18 20:00:51.096188833 +0300
 @@ -38,19 +38,19 @@
         blr
  .LFE0:
         .size   foo, .-foo
 -       .section        .eh_frame,"a",@progbits
 $ diff -u out-nb-av2.s out-dist-av2.s | sed '/eh_frame/q'
 --- out-nb-av2.s        2020-01-18 20:00:51.188188703 +0300
 +++ out-dist-av2.s      2020-01-18 20:00:51.104188822 +0300
 @@ -33,19 +33,19 @@
         blr
  .LFE0:
         .size   foo, .-foo
 -       .section        .eh_frame,"a",@progbits
 $ cc -g -O0 main.c out-nb-av2.s && ./a.out 
 0xffffe1f0 0xffffe200
 0
 
 
 
 The diff between in-tree without -maltivec (bad) and in-tree/stock
 with -maltivec (good) is:
 
 $ diff -u out-nb-no2.s out-dist-av2.s | sed '/eh_frame/q'
 --- out-nb-no2.s       2020-01-18 20:00:51.144188765 +0300
 +++ out-dist-av2.s     2020-01-18 20:00:51.104188822 +0300
 @@ -17,9 +17,9 @@
  .LCFI2:
 	stw %r0,52(%r1)
  .LCFI3:
 -	addi %r4,%r31,8
 +	addi %r4,%r31,16
  	stwu %r9,-16(%r1)
 -	stw %r10,8(%r31)
 +	stw %r10,16(%r31)
  	addi %r3,%r1,16
  	bl bar
  	addi %r11,%r31,48
 @@ [...]
 
 
 Someone with more ppc and gcc clue should look into what happens
 there.  My uneducated guess is that while our STACK_BOUNDARY is always
 16 bytes (NB: its value, 128, is in *bits*), some other alignment
 parameter is inconsistently 8 bytes without -maltivec and is 16 only
 with -maltivec.
 
 -uwe
 


Home | Main Index | Thread Index | Old Index