This is the mail archive of the cygwin@cygwin.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

cygwin gcc bug: stack-arg-probe (alloca) logic clobbers regparm


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/


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]