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 ------------------------------------------------------------------------------