Date: Wed, 25 Sep 2002 20:10:04 -0700 (PDT) From: Bruce Evans <bde@zeta.org.au> To: freebsd-bugs@FreeBSD.org Subject: Re: i386/41528: better stack alignment patch for lib/csu/i386-elf/ Message-ID: <200209260310.g8Q3A43r031347@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR i386/41528; it has been noted by GNATS. From: Bruce Evans <bde@zeta.org.au> To: NIIMI Satoshi <sa2c@sa2c.net> Cc: FreeBSD-gnats-submit@FreeBSD.ORG Subject: Re: i386/41528: better stack alignment patch for lib/csu/i386-elf/ Date: Thu, 26 Sep 2002 13:15:26 +1000 (EST) On 26 Sep 2002, NIIMI Satoshi wrote: > Bruce Evans <bde@zeta.org.au> writes: > > > I just got around to preparing this for commit (hopefully just before 4.7), > > and found a small problem. There seems to be an off-by-8 error. > > I confirm the problem. Thanks. > I tested your patch with the following code. > > Test code: > #include <stdio.h> > > struct foo > { > int a; > } __attribute__((aligned(16))); > > int > main(int argc, char **argv, char *envp) > { > struct foo x; > struct foo y; > > printf("%p %p\n", &x, &y); > } > > Produced assembly (with cc -O): > main: > pushl %ebp > movl %esp,%ebp > subl $40,%esp > addl $-4,%esp > leal -32(%ebp),%eax #A > pushl %eax > leal -16(%ebp),%eax #B > pushl %eax > pushl $.LC0 > call printf > leave > ret > > At #A and #B, GCC expects %ebp as aligned by PREFERRED_STACK_BOUNDARY. > (This is what your diagram shows.) > > But with 'cc -O -fomit-frame-pointer', the expected alignment is different. Urk. > Produced assembly (with cc -O -fomit-frame-pointer): > main: > subl $44,%esp > addl $-4,%esp > leal 4(%esp),%eax #A > pushl %eax > leal 24(%esp),%eax #B > pushl %eax > pushl $.LC0 > call printf > addl $16,%esp > addl $44,%esp > ret > > #A points to original %esp - 44. #B points to original %esp - 28. > In this case, GCC expects argument address as aligned by > PREFERRED_STACK_BOUNDARY. (This is what my diagram shows.) > And there is an off-by-8 error with your patch. > > This means that there are no way to remove an off-by-8 error. Yes, there is no general way, since the alignment required in crt1.c depends on at least the compiler version and options. > Because '-fomit-frame-pointer' is not used in the default setting of > FreeBSD, I think your patch is preferable. > > BTW, why did you substruct 12+12 from %esp? I think 12+4 is > sufficient. The extra 8 is to fix the off-by-8 error in some cases :-). When main() is compiled by: - gcc-2.95.4 extra 8 aligns stack right - gcc-2.95.4 -fomit-frame-pointer extra 8 gives off-by-8 error - gcc-3.2.1 extra 8 gives off-by-8 error - gcc-3.2.1 -fomit-frame-pointer extra 8 gives off-by-8 error gcc-3.2.1 does things better but still has 1 bug here: it does the "andl" adjustment after allocating space for auto variables in main(), so these variables may be misaligned. But the "andl" realigns the stack for functions called by main(), so the off-by-8 error is not very serious. I tried to align the stack less unportably using alloca(16), but gave up after finding just a different morass of bugs and incompatibilities. I learned of the following useful non-bugs: - the alignment given by the builtin alloca() is fixed in gcc-3.2.1. So you can now allocate auto variables that need to be strictly aligned using "foo_t *fp = alloca(sizeof(foo_t));" even when the function or one of its callers is compiled with a non-default -mpreferred-stack-boundary. "foo_t f;" is still broken here. - variable-sized auto arrays are fixed similarly. Bruce To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200209260310.g8Q3A43r031347>