[gnu.gcc.bug] Problems with short

b-davis%cai@CS.UTAH.EDU (Brad Davis) (09/30/89)

Two bugs in GCC (or 1 in GCC and 1 in GDB):

GCC: 1.36 (-g -S)
GDB: 3.2
GAS: 1.34

HOST: ISI Optimum V16
OS:  BSD4.3  4.0E	(config.gcc isi68-nfp)

Following is a program, its output, and its assembly listing for two
bugs.  Look for the **** markers in the assembly listing



Problem 1.

STDARGS don't work on BIG_ENDIAN machines.  Bytes and words are
fetched out of the stdarg list when the va_list variable is pointing
at the longword position.  This gives a 0, not the real value on
BIG_ENDIAN machines.

Suggested fix: On BIG_ENDIAN machings, replace the macro 'va_arg' with
the following (change the second __va_rounded_size() to sizeof()):

#define va_arg(AP, TYPE)						\
 (AP += __va_rounded_size (TYPE),					\
  *((TYPE *) (AP - sizeof (TYPE))))

varargs.h needs to be fixed too.


Problem 2.

Short (word or char) parameters aren't packed on the stack, they are
pushed as 32 bit entries.  The 'stabs' entry GCC creates for these
objects treats them as the shorter object, pointing the 'stabs' offset
to the appropriate word or byte.  GDB, however fetches a longword from
this location, shifting the data up 16 or 24 bits.

Suggested fix: Change the 'stabs' entry to point to the longword
address for stack variables or change GDB to fetch the right data.  I
think it easier to change GCC.  Jim Kingdon said this was working ok
on the Sony News system.  Maybe a #define flag needs to be set
differently?


Both of the problems exist on a Sun running GCC 1.25 and GDB 3.2.

GCC was copied off prep.ai.mit.edu on Friday.  The only changes made
were for stage0 (cc) compiler switches.  The GCC used was the output
of stage2 and all stage1 and stage2 object files compared equal.


Brad Davis
Chief software breaker,
University of Utah CAI Project
------------------------------------------------------------------------------

#include <stdarg.h>

foo1(int n, ...)
{
	char c;
	char *s;
	short i;
	va_list pvar;

	va_start(pvar, n);
	printf("%d ", n);
	printf("%c ", c = va_arg(pvar, char));
	printf("%s ", s = va_arg(pvar, char *));
	printf("%d \n", i = va_arg(pvar, short));
	va_end(pvar);
}

foo2(int n, char c1, char *s1, short i1)
{
	char c;
	char *s;
	short i;

	printf("%d ", n);
	printf("%c ", c = c1);
	printf("%s ", s = s1);
	printf("%d \n", i = i1);
}

main()
{
	foo1(4, 'a', "abcdefg", 1);
	foo2(4, 'a', "abcdefg", 1);
}

------------------------------------------------------------------------------

4 ^@ abcdefg 0 
4 a abcdefg 1 

------------------------------------------------------------------------------
#NO_APP

gcc_compiled.:
	.stabs "bad.c",100,0,0,Ltext
Ltext:
.stabs "int:t1=r1;-2147483648;2147483647;",128,0,0,0
.stabs "char:t2=r2;0;127;",128,0,0,0
.stabs "long int:t3=r1;-2147483648;2147483647;",128,0,0,0
.stabs "unsigned int:t4=r1;0;-1;",128,0,0,0
.stabs "long unsigned int:t5=r1;0;-1;",128,0,0,0
.stabs "short int:t6=r1;-32768;32767;",128,0,0,0
.stabs "long long int:t7=r1;0;-1;",128,0,0,0
.stabs "short unsigned int:t8=r1;0;65535;",128,0,0,0
.stabs "long long unsigned int:t9=r1;0;-1;",128,0,0,0
.stabs "signed char:t10=r1;-128;127;",128,0,0,0
.stabs "unsigned char:t11=r1;0;255;",128,0,0,0
.stabs "float:t12=r1;4;0;",128,0,0,0
.stabs "double:t13=r1;8;0;",128,0,0,0
.stabs "long double:t14=r1;8;0;",128,0,0,0
.stabs "void:t15=15",128,0,0,0
.stabs "va_list:t16=*2",128,0,0,0
.text
LC0:
	.ascii "%d \0"
LC1:
	.ascii "%c \0"
LC2:
	.ascii "%s \0"
LC3:
	.ascii "%d \12\0"
	.even
.globl _foo1
_foo1:
	.stabd 68,0,5
	link a6,#-12
LBB2:
	.stabd 68,0,11
	movel a6,d0
	addql #8,d0
	movel d0,d1
	addql #4,d1
	movel d1,a6@(-12)
	.stabd 68,0,12
	movel a6@(8),sp@-
	pea LC0
	jbsr _printf
	.stabd 68,0,13
	addql #4,a6@(-12)
	movel a6@(-12),a0
	subqw #4,a0
	moveb a0@,d0		**** A0 doesn't point at the byte
	moveb d0,a6@(-1)
	extbl d0
	movel d0,sp@-
	pea LC1
	jbsr _printf
	.stabd 68,0,14
	addql #4,a6@(-12)
	movel a6@(-12),a0
	subqw #4,a0
	movel a0@,d0
	movel d0,a6@(-6)
	movel d0,sp@-
	pea LC2
	jbsr _printf
	.stabd 68,0,15
	addql #4,a6@(-12)
	movel a6@(-12),a0
	subqw #4,a0
	movew a0@,d0		**** A0 doesn't point at the word
	movew d0,a6@(-8)
	movew d0,a0
	movel a0,sp@-
	pea LC3
	jbsr _printf
LBE2:
	.stabd 68,0,17
L1:
	unlk a6
	rts
.stabs "foo1:F1",36,0,0,_foo1
.stabs "n:p1",160,0,0,8
.stabs "c:2",128,0,0,-1
.stabs "s:16",128,0,0,-6
.stabs "i:6",128,0,0,-8
.stabs "pvar:16",128,0,0,-12
.stabn 192,0,0,LBB2
.stabn 224,0,0,LBE2
	.even
.globl _foo2
_foo2:
	.stabd 68,0,20
	link a6,#-8
	moveb a6@(15),a6@(15)
	movew a6@(22),a6@(22)
LBB3:
	.stabd 68,0,25
	movel a6@(8),sp@-
	pea LC0
	jbsr _printf
	.stabd 68,0,26
	moveb a6@(15),d0
	moveb d0,a6@(-1)
	extbl d0
	movel d0,sp@-
	pea LC1
	jbsr _printf
	.stabd 68,0,27
	movel a6@(16),d0
	movel d0,a6@(-6)
	movel d0,sp@-
	pea LC2
	jbsr _printf
	.stabd 68,0,28
	movew a6@(22),d0
	movew d0,a6@(-8)
	movew d0,a0
	movel a0,sp@-
	pea LC3
	jbsr _printf
LBE3:
	.stabd 68,0,29
L2:
	unlk a6
	rts
.stabs "foo2:F1",36,0,0,_foo2
.stabs "n:p1",160,0,0,8
.stabs "c1:p2",160,0,0,15	**** GDB fetches a long at 15 shifting the
				**** byte up 24 bits.  If GCC rounded this
				**** to down 12 all would be ok.
.stabs "s1:p16",160,0,0,16
.stabs "i1:p6",160,0,0,22	**** GDB fetches a long at 22 shifting the
				**** word up 16 bits.  If GCC rounded this
				**** to down 20 all would be ok.
.stabs "c:2",128,0,0,-1
.stabs "s:16",128,0,0,-6
.stabs "i:6",128,0,0,-8
.stabn 192,0,0,LBB3
.stabn 224,0,0,LBE3
LC4:
	.ascii "abcdefg\0"
	.even
.globl _main
_main:
	.stabd 68,0,32
	link a6,#0
	.stabd 68,0,33
	pea 1:w
	pea LC4
	pea 97:w
	pea 4:w
	jbsr _foo1
	.stabd 68,0,34
	pea 1:w
	pea LC4
	pea 97:w
	pea 4:w
	jbsr _foo2
	.stabd 68,0,35
L3:
	unlk a6
	rts
.stabs "main:F1",36,0,0,_main
------------------------------------------------------------------------------