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