public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c/45867] New: Sparc64: bogus %g4 reference in libgcc __udivti3()
@ 2010-10-02 12:38 blauwirbel at gmail dot com
  2010-10-02 13:40 ` [Bug c/45867] reference to %g4 in code generated for sparc64-elf ebotcazou at gcc dot gnu.org
  0 siblings, 1 reply; 2+ messages in thread
From: blauwirbel at gmail dot com @ 2010-10-02 12:38 UTC (permalink / raw)
  To: gcc-bugs

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: unassigned@gcc.gnu.org
        ReportedBy: blauwirbel@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


^ permalink raw reply	[flat|nested] 2+ messages in thread

* [Bug c/45867] reference to %g4 in code generated for sparc64-elf
  2010-10-02 12:38 [Bug c/45867] New: Sparc64: bogus %g4 reference in libgcc __udivti3() blauwirbel at gmail dot com
@ 2010-10-02 13:40 ` ebotcazou at gcc dot gnu.org
  0 siblings, 0 replies; 2+ messages in thread
From: ebotcazou at gcc dot gnu.org @ 2010-10-02 13:40 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45867

Eric Botcazou <ebotcazou at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Target|                            |sparc64-elf
             Status|UNCONFIRMED                 |RESOLVED
                 CC|                            |ebotcazou at gcc dot
                   |                            |gnu.org
         Resolution|                            |WORKSFORME
            Summary|Sparc64: bogus %g4          |reference to %g4 in code
                   |reference in libgcc         |generated for sparc64-elf
                   |__udivti3()                 |

--- Comment #1 from Eric Botcazou <ebotcazou at gcc dot gnu.org> 2010-10-02 13:40:39 UTC ---
> 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.

The attacker is supposed to be you here.  The sparc64-elf compiler defaults to
the CM_EMBMEDANY memory model:

   TARGET_CM_EMBMEDANY: 64-bit address space.
                     The text and data segments have a maximum size of 2GB
                     (31-bit span) and may be located anywhere in memory.
                     The global register %g4 contains the start address of
                     the data segment.  Programs are statically linked and
                     PIC is not supported.


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2010-10-02 13:40 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-10-02 12:38 [Bug c/45867] New: Sparc64: bogus %g4 reference in libgcc __udivti3() blauwirbel at gmail dot com
2010-10-02 13:40 ` [Bug c/45867] reference to %g4 in code generated for sparc64-elf ebotcazou at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).