public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/44328]  New: switch/case optimization produces an invalid jump table index
@ 2010-05-30  0:00 eblot dot ml at gmail dot com
  2010-05-30 10:36 ` [Bug c++/44328] " eblot dot ml at gmail dot com
                   ` (36 more replies)
  0 siblings, 37 replies; 39+ messages in thread
From: eblot dot ml at gmail dot com @ 2010-05-30  0:00 UTC (permalink / raw)
  To: gcc-bugs

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 9744 bytes --]

Notes: 
 1. the same issue occurs on x86 and x86_64 linux hosts, with a GCC
cross-compiler of the same version is built with the same options
 2. the same issue occurs with GCC cross compiler 4.4.3 (same build options,
without the MPC host library)

I'm afraid I failed to understand something obvious, as this "bug" seems so
weird that I can't really believe it is an actual compiler bug. Please let me
know if/where I'm wrong.

I first encountered this "bug" while compiling the eCos 3.0+ kernel for an
ARM926 target.
The issue appends within the fopen.cxx source file (fopen() implementation):
the 'mode' parameter is converted from a char string - such as "r" - into a
fcntl enumerated value - O_RDONLY in this case, through two switch/case
statements

When built with -O0 or-01, the compiler does not emit a jump table for the
switch/case and the produced 'mode' integer value is the expected one.
When build with -O2 or -O3, the compiler does emit a jump table, but the jump
table is invalid: the net result is that for the '0' case value, the jump table
index points to an address that is outside the jump table, and the value
returned from the jump table is random.

When the -Wtype-limits option switch is used, the compiler does emit a warning,
but I failed to understand the reason for this warning.

I shrinked down the 'fopen.cxx' code to a single, simple function and the
assembly code contains the same invalid statement as it is in the original
file, the type-limits warning is also the same.
The source code does not rely on any other file (no header file).

//------------- C source ----------------------------------------------

#define O_RDONLY     (1<<0)
#define O_WRONLY     (1<<1)
#define O_RDWR       (O_RDONLY|O_WRONLY)
#define O_CREAT      (1<<3)
#define O_TRUNC      (1<<6)

typedef enum {
    OM_READ = 0,
    OM_WRITE,
    OM_READWRITE_NOCREATE,
    OM_READWRITE_CREATE
} OpenMode;

extern "C" int open(const char *name, int mode);

void open_file(const char *filename, const OpenMode rw)
{
    int mode = 0;

    switch( rw )
    {
    case OM_WRITE:
        mode = O_WRONLY|O_CREAT|O_TRUNC;
        break;
    case OM_READ:
        mode = O_RDONLY;
        break;
    case OM_READWRITE_NOCREATE:
        mode = O_RDWR;
        break;
    case OM_READWRITE_CREATE:
        mode = O_RDWR|O_CREAT|O_TRUNC;
        break;
    }

    open( filename, mode );
}
// ----------------- end of C code ------------------------------------

The above C code is built with the following command:
arm-eabi-gcc -c -O2 -mcpu=arm926ej-s -fno-rtti -fno-exceptions -Wtype-limits \
 -o fopen.o fopen.cxx 

The compiler emits the following warning:
fopen.cxx: In function ‘void open_file(const char*, OpenMode)’:
fopen.cxx:16:6: warning: comparison always true due to limited range of data
type

The disassemble code looks like the following:

//------------- ASM ---------------------------------------------------
fopen.o:     file format elf32-littlearm

Disassembly of section .text:

00000000 <_Z9open_filePKc8OpenMode>:
   0:   e59f300c        ldr     r3, [pc, #12]   ; 14
<_Z9open_filePKc8OpenMode+0x14>
   4:   e2411001        sub     r1, r1, #1
   8:   e20110ff        and     r1, r1, #255    ; 0xff
   c:   e7931101        ldr     r1, [r3, r1, lsl #2]
  10:   eafffffe        b       0 <open>
  14:   00000000        andeq   r0, r0, r0

Disassembly of section .rodata:

00000000 <CSWTCH.1>:
   0:   0000004a        andeq   r0, r0, r10, asr #32
   4:   00000003        andeq   r0, r0, r3
   8:   0000004b        andeq   r0, r0, r11, asr #32
//------------- end of ASM --------------------------------------------

The jump table should contain 4 entries. It is only 3 entry wide.
There's no entry for 'case OM_READ'.
Nevertheless, the compiler shifts the index (sub r1, r1, #1), as if the
switch() value were starting from 1, rather than from 0.
When switch (OM_READ) is executed, r1 is decremented from 0 to 0xffffffff,
then masked to a single byte 0xff, following the ARM AAPCS variable-width
enumerated types.
This new index is used to access the jump table, but index 0xff is out of the 
jump table.

Notes:
 * If OpenMode enum is forced to start from 1 -rather than 0-, the emitted code
   is valid (4-entry jump table):
     OM_READ = 1
 * If OpenMode enum is simply added another entry, the emitted code changes 
   and becomes valid (4-entry jump table):
     OM_READWRITE_CREATE,
     OM_DUMMY,
 * If mode is not initialized to a default value, but mode is assigned the
   same value (0) within a 'default', emitted code is valid:
     int mode;
     //
     default: mode = 0; break;

The compiler has been built with the following options:
$> arm-eabi-gcc -c -O2 -mcpu=arm926ej-s -fno-rtti -fno-exceptions -o fopen.o
fopen.cxx -Wtype-limits -v
Using built-in specs.
COLLECT_GCC=arm-eabi-gcc
COLLECT_LTO_WRAPPER=/usr/local/homebrew/Cellar/gcc-arm-ecos/4.5.0/libexec/gcc/arm-eabi/4.5.0/lto-wrapper
Target: arm-eabi
Configured with: ../configure
--prefix=/usr/local/homebrew/Cellar/gcc-arm-ecos/4.5.0 --target=arm-eabi
--disable-shared --with-gnu-as --with-gnu-ld --with-newlib --enable-softfloat
--disable-bigendian --disable-fpu --disable-underscore --enable-multilibs
--with-float=soft --enable-interwork --enable-lto
--with-multilib-list=interwork --with-abi=aapcs --enable-languages=c,c++
--disable-__cxa_atexit --with-gmp=/usr/local/homebrew/Cellar/gmp/5.0.1
--with-mpfr=/usr/local/homebrew/Cellar/mpfr/2.4.2
--with-mpc=/usr/local/homebrew/Cellar/libmpc/0.8.1
--with-ppl=/usr/local/homebrew/Cellar/ppl/0.10.2
--with-cloog=/usr/local/homebrew/Cellar/cloog-ppl/0.15.7
--with-libelf=/usr/local/homebrew/Cellar/libelf/0.8.13
--with-gxx-include-dir=/usr/local/homebrew/Cellar/gcc-arm-ecos/4.5.0/arm-eabi/include
--disable-debug 
Thread model: single
gcc version 4.5.0
COLLECT_GCC_OPTIONS='-c' '-O2' '-mcpu=arm926ej-s' '-fno-rtti' '-fno-exceptions'
'-o' 'fopen.o' '-Wextra' '-save-temps' '-v' '-mfloat-abi=soft' '-mabi=aapcs'

/usr/local/homebrew/Cellar/gcc-arm-ecos/4.5.0/libexec/gcc/arm-eabi/4.5.0/cc1plus
-E -quiet -v -D__USES_INITFINI__ fopen.cxx -mcpu=arm926ej-s -mfloat-abi=soft
-mabi=aapcs -Wextra -fno-rtti -fno-exceptions -O2 -fpch-preprocess -o fopen.ii
ignoring nonexistent directory
"/usr/local/homebrew/Cellar/gcc-arm-ecos/4.5.0/lib/gcc/arm-eabi/4.5.0/../../../../arm-eabi/sys-include"
ignoring duplicate directory
"/usr/local/homebrew/Cellar/gcc-arm-ecos/4.5.0/lib/gcc/arm-eabi/4.5.0/../../../../arm-eabi/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/local/homebrew/Cellar/gcc-arm-ecos/4.5.0/arm-eabi/include
 /usr/local/homebrew/Cellar/gcc-arm-ecos/4.5.0/arm-eabi/include/arm-eabi
 /usr/local/homebrew/Cellar/gcc-arm-ecos/4.5.0/arm-eabi/include/backward
 /usr/local/homebrew/Cellar/gcc-arm-ecos/4.5.0/lib/gcc/arm-eabi/4.5.0/include

/usr/local/homebrew/Cellar/gcc-arm-ecos/4.5.0/lib/gcc/arm-eabi/4.5.0/include-fixed
End of search list.
COLLECT_GCC_OPTIONS='-c' '-O2' '-mcpu=arm926ej-s' '-fno-rtti' '-fno-exceptions'
'-o' 'fopen.o' '-Wextra' '-save-temps' '-v' '-mfloat-abi=soft' '-mabi=aapcs'

/usr/local/homebrew/Cellar/gcc-arm-ecos/4.5.0/libexec/gcc/arm-eabi/4.5.0/cc1plus
-fpreprocessed fopen.ii -quiet -dumpbase fopen.cxx -mcpu=arm926ej-s
-mfloat-abi=soft -mabi=aapcs -auxbase-strip fopen.o -O2 -Wextra -version
-fno-rtti -fno-exceptions -o fopen.s
GNU C++ version 4.5.0 (arm-eabi)
        compiled by GNU C version 4.2.1 (Apple Inc. build 5659), GMP version
5.0.1, MPFR version 2.4.2, MPC version 0.8.1
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
GNU C++ version 4.5.0 (arm-eabi)
        compiled by GNU C version 4.2.1 (Apple Inc. build 5659), GMP version
5.0.1, MPFR version 2.4.2, MPC version 0.8.1
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: dc4afb9bd29f2a2942808dba7d87c9cb
fopen.cxx: In function ‘void open_file(const char*, OpenMode)’:
fopen.cxx:17:6: warning: comparison always true due to limited range of data
type
COLLECT_GCC_OPTIONS='-c' '-O2' '-mcpu=arm926ej-s' '-fno-rtti' '-fno-exceptions'
'-o' 'fopen.o' '-Wextra' '-save-temps' '-v' '-mfloat-abi=soft' '-mabi=aapcs'

/usr/local/homebrew/Cellar/gcc-arm-ecos/4.5.0/lib/gcc/arm-eabi/4.5.0/../../../../arm-eabi/bin/as
-v -mcpu=arm926ej-s -mfloat-abi=soft -meabi=5 -o fopen.o fopen.s
GNU assembler version 2.20.1 (arm-eabi) using BFD version (GNU Binutils)
2.20.1.20100303
COMPILER_PATH=/usr/local/homebrew/Cellar/gcc-arm-ecos/4.5.0/libexec/gcc/arm-eabi/4.5.0/:/usr/local/homebrew/Cellar/gcc-arm-ecos/4.5.0/libexec/gcc/arm-eabi/4.5.0/:/usr/local/homebrew/Cellar/gcc-arm-ecos/4.5.0/libexec/gcc/arm-eabi/:/usr/local/homebrew/Cellar/gcc-arm-ecos/4.5.0/lib/gcc/arm-eabi/4.5.0/:/usr/local/homebrew/Cellar/gcc-arm-ecos/4.5.0/lib/gcc/arm-eabi/:/usr/local/homebrew/Cellar/gcc-arm-ecos/4.5.0/lib/gcc/arm-eabi/4.5.0/../../../../arm-eabi/bin/
LIBRARY_PATH=/usr/local/homebrew/Cellar/gcc-arm-ecos/4.5.0/lib/gcc/arm-eabi/4.5.0/:/usr/local/homebrew/Cellar/gcc-arm-ecos/4.5.0/lib/gcc/arm-eabi/4.5.0/../../../../arm-eabi/lib/
COLLECT_GCC_OPTIONS='-c' '-O2' '-mcpu=arm926ej-s' '-fno-rtti' '-fno-exceptions'
'-o' 'fopen.o' '-Wextra' '-save-temps' '-v' '-mfloat-abi=soft' '-mabi=aapcs'


-- 
           Summary: switch/case optimization produces an invalid jump table
                    index
           Product: gcc
           Version: 4.5.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: eblot dot ml at gmail dot com
 GCC build triplet: x86_64-apple-darwin10
  GCC host triplet: x86_64-apple-darwin10
GCC target triplet: arm-eabi


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


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

end of thread, other threads:[~2010-09-09 15:38 UTC | newest]

Thread overview: 39+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-05-30  0:00 [Bug c++/44328] New: switch/case optimization produces an invalid jump table index eblot dot ml at gmail dot com
2010-05-30 10:36 ` [Bug c++/44328] " eblot dot ml at gmail dot com
2010-05-30 14:50 ` mikpe at it dot uu dot se
2010-05-30 17:36 ` eblot dot ml at gmail dot com
2010-06-04 23:41 ` [Bug c++/44328] switch/case optimization produces an invalid lookup " eblot dot ml at gmail dot com
2010-06-15 15:09 ` jamborm at gcc dot gnu dot org
2010-06-17  9:21 ` eblot dot ml at gmail dot com
2010-06-17  9:37   ` Andrew Pinski
2010-06-17  9:34 ` eblot dot ml at gmail dot com
2010-06-17  9:37 ` pinskia at gmail dot com
2010-06-17 14:02 ` jamborm at gcc dot gnu dot org
2010-06-17 15:01 ` jamborm at gcc dot gnu dot org
2010-06-17 16:34 ` eblot dot ml at gmail dot com
2010-06-17 16:37 ` jamborm at gcc dot gnu dot org
2010-06-17 16:41 ` eblot dot ml at gmail dot com
2010-06-20 13:53 ` eblot dot ml at gmail dot com
2010-06-20 16:51 ` jamborm at gcc dot gnu dot org
2010-06-20 16:57 ` eblot dot ml at gmail dot com
2010-06-20 17:03 ` eblot dot ml at gmail dot com
2010-06-20 18:26 ` mikpe at it dot uu dot se
2010-06-21  8:29 ` jamborm at gcc dot gnu dot org
2010-06-21 10:45 ` mikpe at it dot uu dot se
2010-06-21 11:18 ` mikpe at it dot uu dot se
2010-07-05 13:43 ` [Bug tree-optimization/44328] " ramana at gcc dot gnu dot org
2010-07-24 22:24 ` jifl-bugzilla at jifvik dot org
2010-08-02 12:24 ` ian dot bolton at arm dot com
2010-08-02 13:33 ` ian dot bolton at arm dot com
2010-08-03 17:09 ` ian dot bolton at arm dot com
2010-09-01 11:10 ` jamborm at gcc dot gnu dot org
2010-09-01 11:23 ` jamborm at gcc dot gnu dot org
2010-09-01 11:24 ` jamborm at gcc dot gnu dot org
2010-09-01 11:25 ` ibolton at gcc dot gnu dot org
2010-09-01 11:33 ` jamborm at gcc dot gnu dot org
2010-09-01 11:47 ` jifl-bugzilla at jifvik dot org
2010-09-01 11:50 ` jakub at gcc dot gnu dot org
2010-09-02 13:10 ` ibolton at gcc dot gnu dot org
2010-09-07  9:28 ` ibolton at gcc dot gnu dot org
2010-09-09 15:37 ` ibolton at gcc dot gnu dot org
2010-09-09 15:38 ` rguenth at gcc dot gnu dot 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).