I couldn't find a description of Host, Target and Build Triplet inside gcc.gnu.org. Here is my gcc version $ gcc -v Reading specs from /usr/lib/gcc-lib/powerpc-linux/3.3.4/specs Configured with: ../src/configure -v --enable-languages=c,c++,java,f77,pascal,objc,ada --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-gxx-include-dir=/usr/include/c++/3.3 --enable-shared --with-system-zlib --enable-nls --without-included-gettext --enable-__cxa_atexit --enable-clocale=gnu --enable-debug --enable-java-gc=boehm --enable-java-awt=xlib --enable-objc-gc --disable-multilib powerpc-linux Thread model: posix gcc version 3.3.4 (Debian 1:3.3.4-2) The function rs6000_va_start() in gcc/gcc/config/rs6000/rs6000.c incorrectly sets va_list.gpr (and fpr). gpr should have a maximum value equal to the number of integer registers available for parameter passing. If gpr takes greater number of values, this results in a wraparound, as in the example below, where 256 integer parameters are passed. I don't know if I looking at the correct function corresponding to the target, but the bug exists. Using gdb and inspecting the va_list after the va_start function shows that va_list.gpr wraps around. The preprocessed file is (also) available at http://www.cs.utexas.edu/users/suriya/va_list.i # 1 "va_list.c" # 1 "<built-in>" # 1 "<command line>" # 1 "va_list.c" # 1 "/usr/lib/gcc-lib/powerpc-linux/3.3.4/include/stdarg.h" 1 3 4 # 43 "/usr/lib/gcc-lib/powerpc-linux/3.3.4/include/stdarg.h" 3 4 typedef __builtin_va_list __gnuc_va_list; # 105 "/usr/lib/gcc-lib/powerpc-linux/3.3.4/include/stdarg.h" 3 4 typedef __gnuc_va_list va_list; # 2 "va_list.c" 2 int foo( int a0x00, int a0x01, int a0x02, int a0x03, int a0x04, int a0x05, int a0x06, int a0x07, int a0x08, int a0x09, int a0x0a, int a0x0b, int a0x0c, int a0x0d, int a0x0e, int a0x0f, int a0x10, int a0x11, int a0x12, int a0x13, int a0x14, int a0x15, int a0x16, int a0x17, int a0x18, int a0x19, int a0x1a, int a0x1b, int a0x1c, int a0x1d, int a0x1e, int a0x1f, int a0x20, int a0x21, int a0x22, int a0x23, int a0x24, int a0x25, int a0x26, int a0x27, int a0x28, int a0x29, int a0x2a, int a0x2b, int a0x2c, int a0x2d, int a0x2e, int a0x2f, int a0x30, int a0x31, int a0x32, int a0x33, int a0x34, int a0x35, int a0x36, int a0x37, int a0x38, int a0x39, int a0x3a, int a0x3b, int a0x3c, int a0x3d, int a0x3e, int a0x3f, int a0x40, int a0x41, int a0x42, int a0x43, int a0x44, int a0x45, int a0x46, int a0x47, int a0x48, int a0x49, int a0x4a, int a0x4b, int a0x4c, int a0x4d, int a0x4e, int a0x4f, int a0x50, int a0x51, int a0x52, int a0x53, int a0x54, int a0x55, int a0x56, int a0x57, int a0x58, int a0x59, int a0x5a, int a0x5b, int a0x5c, int a0x5d, int a0x5e, int a0x5f, int a0x60, int a0x61, int a0x62, int a0x63, int a0x64, int a0x65, int a0x66, int a0x67, int a0x68, int a0x69, int a0x6a, int a0x6b, int a0x6c, int a0x6d, int a0x6e, int a0x6f, int a0x70, int a0x71, int a0x72, int a0x73, int a0x74, int a0x75, int a0x76, int a0x77, int a0x78, int a0x79, int a0x7a, int a0x7b, int a0x7c, int a0x7d, int a0x7e, int a0x7f, int a0x80, int a0x81, int a0x82, int a0x83, int a0x84, int a0x85, int a0x86, int a0x87, int a0x88, int a0x89, int a0x8a, int a0x8b, int a0x8c, int a0x8d, int a0x8e, int a0x8f, int a0x90, int a0x91, int a0x92, int a0x93, int a0x94, int a0x95, int a0x96, int a0x97, int a0x98, int a0x99, int a0x9a, int a0x9b, int a0x9c, int a0x9d, int a0x9e, int a0x9f, int a0xa0, int a0xa1, int a0xa2, int a0xa3, int a0xa4, int a0xa5, int a0xa6, int a0xa7, int a0xa8, int a0xa9, int a0xaa, int a0xab, int a0xac, int a0xad, int a0xae, int a0xaf, int a0xb0, int a0xb1, int a0xb2, int a0xb3, int a0xb4, int a0xb5, int a0xb6, int a0xb7, int a0xb8, int a0xb9, int a0xba, int a0xbb, int a0xbc, int a0xbd, int a0xbe, int a0xbf, int a0xc0, int a0xc1, int a0xc2, int a0xc3, int a0xc4, int a0xc5, int a0xc6, int a0xc7, int a0xc8, int a0xc9, int a0xca, int a0xcb, int a0xcc, int a0xcd, int a0xce, int a0xcf, int a0xd0, int a0xd1, int a0xd2, int a0xd3, int a0xd4, int a0xd5, int a0xd6, int a0xd7, int a0xd8, int a0xd9, int a0xda, int a0xdb, int a0xdc, int a0xdd, int a0xde, int a0xdf, int a0xe0, int a0xe1, int a0xe2, int a0xe3, int a0xe4, int a0xe5, int a0xe6, int a0xe7, int a0xe8, int a0xe9, int a0xea, int a0xeb, int a0xec, int a0xed, int a0xee, int a0xef, int a0xf0, int a0xf1, int a0xf2, int a0xf3, int a0xf4, int a0xf5, int a0xf6, int a0xf7, int a0xf8, int a0xf9, int a0xfa, int a0xfb, int a0xfc, int a0xfd, int a0xfe, int a0xff, ...) { va_list list; int i; __builtin_va_start(list,a0xff); i = __builtin_va_arg(list,int); return i; } int main() { return foo( 689 + 0x00, 689 + 0x01, 689 + 0x02, 689 + 0x03, 689 + 0x04, 689 + 0x05, 689 + 0x06, 689 + 0x07, 689 + 0x08, 689 + 0x09, 689 + 0x0a, 689 + 0x0b, 689 + 0x0c, 689 + 0x0d, 689 + 0x0e, 689 + 0x0f, 689 + 0x10, 689 + 0x11, 689 + 0x12, 689 + 0x13, 689 + 0x14, 689 + 0x15, 689 + 0x16, 689 + 0x17, 689 + 0x18, 689 + 0x19, 689 + 0x1a, 689 + 0x1b, 689 + 0x1c, 689 + 0x1d, 689 + 0x1e, 689 + 0x1f, 689 + 0x20, 689 + 0x21, 689 + 0x22, 689 + 0x23, 689 + 0x24, 689 + 0x25, 689 + 0x26, 689 + 0x27, 689 + 0x28, 689 + 0x29, 689 + 0x2a, 689 + 0x2b, 689 + 0x2c, 689 + 0x2d, 689 + 0x2e, 689 + 0x2f, 689 + 0x30, 689 + 0x31, 689 + 0x32, 689 + 0x33, 689 + 0x34, 689 + 0x35, 689 + 0x36, 689 + 0x37, 689 + 0x38, 689 + 0x39, 689 + 0x3a, 689 + 0x3b, 689 + 0x3c, 689 + 0x3d, 689 + 0x3e, 689 + 0x3f, 689 + 0x40, 689 + 0x41, 689 + 0x42, 689 + 0x43, 689 + 0x44, 689 + 0x45, 689 + 0x46, 689 + 0x47, 689 + 0x48, 689 + 0x49, 689 + 0x4a, 689 + 0x4b, 689 + 0x4c, 689 + 0x4d, 689 + 0x4e, 689 + 0x4f, 689 + 0x50, 689 + 0x51, 689 + 0x52, 689 + 0x53, 689 + 0x54, 689 + 0x55, 689 + 0x56, 689 + 0x57, 689 + 0x58, 689 + 0x59, 689 + 0x5a, 689 + 0x5b, 689 + 0x5c, 689 + 0x5d, 689 + 0x5e, 689 + 0x5f, 689 + 0x60, 689 + 0x61, 689 + 0x62, 689 + 0x63, 689 + 0x64, 689 + 0x65, 689 + 0x66, 689 + 0x67, 689 + 0x68, 689 + 0x69, 689 + 0x6a, 689 + 0x6b, 689 + 0x6c, 689 + 0x6d, 689 + 0x6e, 689 + 0x6f, 689 + 0x70, 689 + 0x71, 689 + 0x72, 689 + 0x73, 689 + 0x74, 689 + 0x75, 689 + 0x76, 689 + 0x77, 689 + 0x78, 689 + 0x79, 689 + 0x7a, 689 + 0x7b, 689 + 0x7c, 689 + 0x7d, 689 + 0x7e, 689 + 0x7f, 689 + 0x80, 689 + 0x81, 689 + 0x82, 689 + 0x83, 689 + 0x84, 689 + 0x85, 689 + 0x86, 689 + 0x87, 689 + 0x88, 689 + 0x89, 689 + 0x8a, 689 + 0x8b, 689 + 0x8c, 689 + 0x8d, 689 + 0x8e, 689 + 0x8f, 689 + 0x90, 689 + 0x91, 689 + 0x92, 689 + 0x93, 689 + 0x94, 689 + 0x95, 689 + 0x96, 689 + 0x97, 689 + 0x98, 689 + 0x99, 689 + 0x9a, 689 + 0x9b, 689 + 0x9c, 689 + 0x9d, 689 + 0x9e, 689 + 0x9f, 689 + 0xa0, 689 + 0xa1, 689 + 0xa2, 689 + 0xa3, 689 + 0xa4, 689 + 0xa5, 689 + 0xa6, 689 + 0xa7, 689 + 0xa8, 689 + 0xa9, 689 + 0xaa, 689 + 0xab, 689 + 0xac, 689 + 0xad, 689 + 0xae, 689 + 0xaf, 689 + 0xb0, 689 + 0xb1, 689 + 0xb2, 689 + 0xb3, 689 + 0xb4, 689 + 0xb5, 689 + 0xb6, 689 + 0xb7, 689 + 0xb8, 689 + 0xb9, 689 + 0xba, 689 + 0xbb, 689 + 0xbc, 689 + 0xbd, 689 + 0xbe, 689 + 0xbf, 689 + 0xc0, 689 + 0xc1, 689 + 0xc2, 689 + 0xc3, 689 + 0xc4, 689 + 0xc5, 689 + 0xc6, 689 + 0xc7, 689 + 0xc8, 689 + 0xc9, 689 + 0xca, 689 + 0xcb, 689 + 0xcc, 689 + 0xcd, 689 + 0xce, 689 + 0xcf, 689 + 0xd0, 689 + 0xd1, 689 + 0xd2, 689 + 0xd3, 689 + 0xd4, 689 + 0xd5, 689 + 0xd6, 689 + 0xd7, 689 + 0xd8, 689 + 0xd9, 689 + 0xda, 689 + 0xdb, 689 + 0xdc, 689 + 0xdd, 689 + 0xde, 689 + 0xdf, 689 + 0xe0, 689 + 0xe1, 689 + 0xe2, 689 + 0xe3, 689 + 0xe4, 689 + 0xe5, 689 + 0xe6, 689 + 0xe7, 689 + 0xe8, 689 + 0xe9, 689 + 0xea, 689 + 0xeb, 689 + 0xec, 689 + 0xed, 689 + 0xee, 689 + 0xef, 689 + 0xf0, 689 + 0xf1, 689 + 0xf2, 689 + 0xf3, 689 + 0xf4, 689 + 0xf5, 689 + 0xf6, 689 + 0xf7, 689 + 0xf8, 689 + 0xf9, 689 + 0xfa, 689 + 0xfb, 689 + 0xfc, 689 + 0xfd, 689 + 0xfe, 689 + 0xff, 5555) - 5555; }
GCC 3.3 used the magic number of 1000 when initializing the number of arguments. This bug report does not state the exact failure mode of the example, but the slightly greater than 1000 words (256 arguments) might interact incorrectly with the magic value 1000. The use of "1000" was removed in GCC 3.4, so I would recommend retesting with that GCC release. The lack of description about the failure makes it difficult for anyone else to confirm the report or test if the problem already is corrected.
Created attachment 8022 [details] Test case, should return success
(In reply to comment #1) > GCC 3.3 used the magic number of 1000 when initializing the number of > arguments. This bug report does not state the exact failure mode of the > example, but the slightly greater than 1000 words (256 arguments) might > interact incorrectly with the magic value 1000. The use of "1000" was removed > in GCC 3.4, so I would recommend retesting with that GCC release. The lack of > description about the failure makes it difficult for anyone else to confirm > the report or test if the problem already is corrected. The same problem exists with GCC 3.4. Let me restate the problem. va_start(va_list, param) sets fields { gpr, fpr, overflow_arg_area, reg_save_area } in the va_list structure. `gpr' is an index into the reg_save_area. Parameters are passed into integer registers r3 through r10. So, the index into the integer portion of reg_save_area (where the 8 integer registers, followed by the floating point registers are saved) should be between 0 and 7 (both inclusive) to be meaningful. Any value greater than 7 indicates that the next parameter is not in the integer save area but in overflow_arg_area. For example, if the function was int foo(int a0, int a1, ...), then gpr would be 2, to indicate that the next integer parameter (afdter a1) is in offset 2 (the parameter was passed in r5) of the reg_save_area. For example, if the function was int foo(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, ...), then gpr would be 8. This means that this is an offset greater than 7 and as a result the next integer parameter (passed after a7) is inthe overflow_arg_area. For example, if the function was foo(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, ...), then gprturns out to be be 9 (confirmed using gdb). This is again a value greater than 7 indicating that the next integer parameter (passed after a8) is in the overflow_arg_area. va_arg which gets the next argument, compares gpr to 8 to decide from which area the load the parameter from. In the above examples, gpr is not bound to a maximum value of 8, but instead increments for each additional argument. gpr is of type char. As a result, if there are 256 parameters before the ellipsis '...', gpr takes a value 0 (due to overflow). This, incorrectly indicates (because va_arg compares gpr to 8, and 0 < 8) that the parameter is in the reg_save_area, though in reality, the parameter is in the overflow_arg_area. The test program I sent, had 256 parameters followed by the ellipsis. va_arg(list, int) should give the value of the 257th parameter (counting from one), which is 5555 (in the example, the last argument passed by main). The program should return success, however it doesn't, because of incorrect setting of gpr in va_start.
PowerPC SVR4 va_arg bug.
Created attachment 8035 [details] rs6000_va_start patch
Subject: Bug 19491 CVSROOT: /cvs/gcc Module name: gcc Changes by: dje@gcc.gnu.org 2005-01-22 03:09:31 Modified files: gcc : ChangeLog gcc/config/rs6000: rs6000.c Log message: 2005-01-20 David Edelsohn <edelsohn@gnu.org> Andrew Pinski <pinskia@physics.uc.edu> PR target/19491 * config/rs6000/rs6000.c (rs6000_va_start): Saturate n_gpr at maximum number of GPRs. Saturate n_fpr at maximum number of FPRs. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.7225&r2=2.7226 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/rs6000/rs6000.c.diff?cvsroot=gcc&r1=1.780&r2=1.781
Patch committed. This is not a regression, so it will not be fixed on earlier branches.