http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45867
Summary: Sparc64: bogus %g4 reference in libgcc __udivti3() Product: gcc Version: 4.5.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c AssignedTo: unassig...@gcc.gnu.org ReportedBy: blauwir...@gmail.com Sparc64 GCC (at least 4.2.4 and 4.5.0 cross compilers) generates incorrect code for the minimal test case below. I found the bug because of obscure crashes in OpenBIOS inside libgcc, in __udivti3(). The problem can be isolated from __udivti3() to count_leading_zeros() macro and further to this minimal test case. As can be seen in the output, there is a strange extra instruction, 'add %g1, %g4, %g1'. %g4 is not initialized anywhere in the function but any previous value will be used. Thus the __clz_tab table access can lead to crashes. This may in theory even have some security implications if %g4 value could be feasibly controlled by an attacker. $ cat libgcc2.c extern const char __clz_tab[256]; char test(void) { return __clz_tab[0]; } $ sparc64-elf-gcc-4.2.4 -save-temps -S libgcc2.c -O2 $ cat libgcc2.s .file "libgcc2.c" .section ".text" .align 4 .global test .type test, #function .proc 04 test: sethi %hi(__clz_tab), %g1 add %g1, %g4, %g1 ldsb [%g1+%lo(__clz_tab)], %o0 jmp %o7+8 sra %o0, 0, %o0 .size test, .-test .ident "GCC: (GNU) 4.2.4" $ cat libgcc2.i # 1 "libgcc2.c" # 1 "<built-in>" # 1 "<command-line>" # 1 "libgcc2.c" extern const char __clz_tab[256]; char test(void) { return __clz_tab[0]; } $ sparc64-elf-gcc-4.2.4 -v Using built-in specs. Target: sparc64-elf Configured with: ../configure --target=sparc64-elf --enable-targets=sparc-elf,sparc64-elf --disable-nls --disable-threads --enable-languages=c --disable-shared --enable-multilib : (reconfigured) ../configure --target=sparc64-elf --enable-targets=sparc-elf,sparc64-elf --disable-nls --disable-threads --enable-languages=c --disable-shared --enable-multilib --disable-ssp : (reconfigured) ../configure --target=sparc64-elf --enable-targets=sparc-elf,sparc64-elf --disable-nls --disable-threads --enable-languages=c --disable-shared --enable-multilib --disable-libssp Thread model: single gcc version 4.2.4 Same case with 4.5.0: $ sparc64-elf-gcc-4.5.0 -save-temps -S libgcc2.c -O2 $ cat libgcc2.s .file "libgcc2.c" .section ".text" .align 4 .global test .type test, #function .proc 02 test: sethi %hi(__clz_tab), %g1 add %g1, %g4, %g1 jmp %o7+8 ldsb [%g1+%lo(__clz_tab)], %o0 .size test, .-test .ident "GCC: (GNU) 4.5.0" $ cat libgcc2.i # 1 "libgcc2.c" # 1 "<built-in>" # 1 "<command-line>" # 1 "libgcc2.c" extern const char __clz_tab[256]; char test(void) { return __clz_tab[0]; } $ sparc64-elf-gcc-4.5.0 -v Using built-in specs. COLLECT_GCC=sparc64-elf-gcc-4.5.0 COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/sparc64-elf/4.5.0/lto-wrapper Target: sparc64-elf Configured with: ../configure --target=sparc64-elf --enable-targets=sparc64-elf --disable-nls --disable-threads --enable-languages=c --disable-shared --disable-multilib --disable-libssp Thread model: single gcc version 4.5.0 (GCC) The above are cross compilers, with host: $ uname -srvmo Linux 2.6.36-rc5+ #3 SMP Sat Sep 25 17:06:06 UTC 2010 x86_64 GNU/Linux It doesn't happen with native 3.3.5 from OpenBSD/Sparc64: $ gcc -save-temps -S libgcc2.c -O2 $ cat libgcc2.s .file "libgcc2.c" .section ".text" .align 4 .align 32 .globl test .type test, @function .proc 04 test: !#PROLOGUE# 0 !#PROLOGUE# 1 sethi %h44(__clz_tab), %g1 or %g1, %m44(__clz_tab), %g1 sllx %g1, 12, %g1 retl ldsb [%g1+%l44(__clz_tab)], %o0 .size test, .-test $ cat libgcc2.i # 1 "libgcc2.c" # 1 "<built-in>" # 1 "<command line>" # 1 "libgcc2.c" extern const char __clz_tab[256]; char test(void) { return __clz_tab[0]; } $ gcc -v Reading specs from /usr/lib/gcc-lib/sparc64-unknown-openbsd4.6/3.3.5/specs Configured with: Thread model: single gcc version 3.3.5 (propolice) $ uname -mrsv OpenBSD 4.6 GENERIC#43 sparc64