This is the mail archive of the
cygwin@cygwin.com
mailing list for the Cygwin project.
cygwin gcc bug: stack-arg-probe (alloca) logic clobbers regparm
- From: "Fish" <fish at infidels dot org>
- To: "Cygwin" <cygwin at cygwin dot com>
- Date: Mon, 3 Jun 2002 19:39:52 -0700
- Subject: cygwin gcc bug: stack-arg-probe (alloca) logic clobbers regparm
- Reply-to: <dtrout at sprintmail dot com>
Hello.
I believe I have stumbled across what appears to be a serious(?) gcc compiler
bug with the "cygwin special" version of gcc.
Whenever I define a function with the regparm(n) attribute it appears gcc
prologue code sometimes clobbers one of my parameter registers producing
incorrect results.
This only occurs if: a) more than 4000 bytes are needed for local variable
storage, and b) if -mstack-arg-probe is specified (which appears to be the
default).
If less than 4000 bytes *OR* -mno-stack-arg-probe is used, the problem does NOT
occur.
If more than 4000 bytes *AND* -mstack-arg-probe is used, the problem DOES occur.
The 'eax' register -- which is one of the (the first?) regparm(n) parameter
registers used to pass parameter values to my function -- appears to be getting
clobbered by the prologue code that calls the __alloca function to reserve stack
space for local variables (i.e. the "stack probe" logic?).
A very small and simple test case is included below that tends to confirm the
incorrect (buggy) behavior of the "cygwin special" version of gcc. It should,
when run, display "compress: a=1, b=2, c=3" but instead displays "compress:
a=4198609, b=2, c=3" when the conditions mentioned earlier exist (more than 4000
bytes of local variables *AND* -mstack-arg-probe specified).
Some questions:
1. Could someone please confirm whether or not this is indeed a bug in the
"cygwin special" version of gcc for me? (Or am I perhaps not doing something
correctly?) Thanks.
2. What is the "cygwin special" part of gcc? That is to say, why is there a
special version? Not important; just curious. :)
3. Assuming the answer to #1 is 'yes' (i.e. that this is indeed a bug), could
someone give a rough estimate as to when it might be fixed? NOTE! I'm *not* in
any real hurry for an immediate fix or anything! Take your time and look into it
properly so you can be confident in your fix, by all means! Once again, I'm just
curious, that's all. I do have a workable work-around for the time being: always
use "-mno-stack-arg-probe" whenever using regparm(n).
4. Regarding the overall bug itself (assuming of course it is one): could
someone please explain *why* _alloca is being called in the first place? Once
again, I'm just curious. It seems to me that the -mno-stack-arg-probe behavior
(emitting a simple subtract instruction ("subl $4052,%esp")) to reserve stack
space for the local variables should be just as good or even better than having
to call _alloca to do it, or am I missing something? Does it have to do with
automatic cleanup/deallocation of local variable storage in case a longjmp is
done? Is that it? (Once again, I'm just curious).
That's it. Just wanted to report what appears to be a bug.
Test case follows my signature below.
Thanks.
--
"Fish" (David B. Trout)
fish@infidels.org
==============================================
$ gcc -v
Reading specs from /usr/lib/gcc-lib/i686-pc-cygwin/2.95.3-5/specs
gcc version 2.95.3-5 (cygwin special)
================( fishtest.c )================
#include <stdio.h>
#include <setjmp.h>
#define uint8_t u_int8_t
typedef uint8_t BYTE;
typedef struct _REGS
{
int a, b, c, d;
BYTE me[4000];
}
REGS;
#define ATTR_REGPARM(n) __attribute__ ((regparm(n)))
#define DEF_INST(_name) \
ATTR_REGPARM(3) void _name (int a, int b, int c, REGS *regs)
#define ARCH_DEP(_name) \
_name
DEF_INST(compress);
DEF_INST(compression_call);
int main ( int argc, char *argv[] )
{
REGS* regs = 0;
ARCH_DEP (compression_call) (1, 2, 3, regs);
return 0;
}
DEF_INST(compress)
{
printf("compress: a=%d, b=%d, c=%d\n",a,b,c);
}
DEF_INST(compression_call)
{
REGS iregs;
ARCH_DEP (compress) (a, b, c, &iregs);
}
==============================================
gcc -DWIN32 -D_WIN32 -Wall -malign-double -mno-stack-arg-probe -DDEBUG -D_DEBUG
-g -o fishtest.o -c fishtest.c -Wa,-adhln=fishtest.c.listing.txt
gcc -Xlinker -Map -Xlinker fishtest.linkmap.txt -o fishtest fishtest.o
==============================================
234 .align 4
240 .globl _compression_call
242 _compression_call:
243 0080 55 pushl %ebp
244 0081 89E5 movl %esp,%ebp
245 0083 81ECD40F subl $4052,%esp
245 0000
246 0089 53 pushl %ebx
180:fishtest.c ****
181:fishtest.c **** ///////////////////////////////////////////////////////
182:fishtest.c ****
183:fishtest.c **** DEF_INST(compression_call)
184:fishtest.c **** {
248 LM10:
249 008a 8945FC movl %eax,-4(%ebp)
250 008d 8955F8 movl %edx,-8(%ebp)
251 0090 894DF4 movl %ecx,-12(%ebp)
185:fishtest.c **** REGS iregs;
253 LM11:
254 LBB3:
186:fishtest.c **** ARCH_DEP (compress) (a, b, c, &iregs);
256 LM12:
257 0093 83C4F4 addl $-12,%esp
258 0096 8B4DF4 movl -12(%ebp),%ecx
259 0099 8B55F8 movl -8(%ebp),%edx
260 009c 8B45FC movl -4(%ebp),%eax
261 009f 8D9D40F0 leal -4032(%ebp),%ebx
261 FFFF
262 00a5 53 pushl %ebx
263 00a6 89C9 movl %ecx,%ecx
264 00a8 89D2 movl %edx,%edx
265 00aa 89C0 movl %eax,%eax
266 00ac E8A3FFFF call _compress
266 FF
267 00b1 83C410 addl $16,%esp
187:fishtest.c **** }
269 LM13:
270 LBE3:
272 LM14:
273 L12:
274 00b4 8B9D28F0 movl -4056(%ebp),%ebx
274 FFFF
275 00ba 89EC movl %ebp,%esp
276 00bc 5D popl %ebp
277 00bd C3 ret
==============================================
$ fishtest
compress: a=1, b=2, c=3
==============================================
gcc -DWIN32 -D_WIN32 -Wall -malign-double -mstack-arg-probe -DDEBUG -D_DEBUG -g
-o fishtest.o -c fishtest.c -Wa,-adhln=fishtest.c.listing.txt
gcc -Xlinker -Map -Xlinker fishtest.linkmap.txt -o fishtest fishtest.o
==============================================
234 .align 4
240 .globl _compression_call
242 _compression_call:
243 0080 55 pushl %ebp
244 0081 89E5 movl %esp,%ebp
245 0083 B8D40F00 movl $4052,%eax
245 00
246 0088 E8000000 call __alloca
246 00
247 008d 53 pushl %ebx
180:fishtest.c ****
181:fishtest.c **** ///////////////////////////////////////////////////////
182:fishtest.c ****
183:fishtest.c **** DEF_INST(compression_call)
184:fishtest.c **** {
249 LM10:
250 008e 8945FC movl %eax,-4(%ebp)
251 0091 8955F8 movl %edx,-8(%ebp)
252 0094 894DF4 movl %ecx,-12(%ebp)
185:fishtest.c **** REGS iregs;
254 LM11:
255 LBB3:
186:fishtest.c **** ARCH_DEP (compress) (a, b, c, &iregs);
257 LM12:
258 0097 83C4F4 addl $-12,%esp
259 009a 8B4DF4 movl -12(%ebp),%ecx
260 009d 8B55F8 movl -8(%ebp),%edx
261 00a0 8B45FC movl -4(%ebp),%eax
262 00a3 8D9D40F0 leal -4032(%ebp),%ebx
262 FFFF
263 00a9 53 pushl %ebx
264 00aa 89C9 movl %ecx,%ecx
265 00ac 89D2 movl %edx,%edx
266 00ae 89C0 movl %eax,%eax
267 00b0 E89FFFFF call _compress
267 FF
268 00b5 83C410 addl $16,%esp
187:fishtest.c **** }
270 LM13:
271 LBE3:
273 LM14:
274 L12:
275 00b8 8B9D28F0 movl -4056(%ebp),%ebx
275 FFFF
276 00be 89EC movl %ebp,%esp
277 00c0 5D popl %ebp
278 00c1 C3 ret
==============================================
$ fishtest
compress: a=4198609, b=2, c=3
==============================================
--
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
Bug reporting: http://cygwin.com/bugs.html
Documentation: http://cygwin.com/docs.html
FAQ: http://cygwin.com/faq/