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

Reply via email to