I am using the GCC 4.1.1 ARM build for Cygwin from GNUARM. $ arm-elf-gcc -v Using built-in specs. Target: arm-elf Configured with: ../gcc-4.1.1/configure --target=arm-elf --prefix=/g/gnuarm-4.1.1 --enable-interwork --enable-multilib --with-float=soft --with-newlib --with-headers=../newlib-1.14.0/newlib/libc/include --enable-languages=c,c++ Thread model: single gcc version 4.1.1
In a certain situation, the compiler generates incorrect code for a function which results in the stack pointer being restored to the wrong value on return from the function, and the stack then becomes corrupted. The following code demonstrates the bug: void dummy_func() { } int test_func(void *p) { dummy_func(); register int r; register void *h; if (p == 0) { return 0; } //r = (int)h; return r; } Save it as register_bug.c, and compile with: $ arm-elf-gcc -mthumb -mtpcs-frame -S -mcpu=arm7tdmi -fno-builtin -fno-exceptions -mlittle-endian -fomit-frame-pointer -o register_bug_nor.s register_bug.c Uncomment the commented-out line, and compile again: $ arm-elf-gcc -mthumb -mtpcs-frame -S -mcpu=arm7tdmi -fno-builtin -fno-exceptions -mlittle-endian -fomit-frame-pointer -o register_bug_r.s register_bug.c If you now diff the two assembly files, you will notice that uncommenting the line results in the following lines being added near the start of the function: + mov r2, r8 + push {r2, lr} and near the end: + pop {r2} + mov r8, r2 As you can see, more registers are pushed than popped. This means that when the stack pointer register is later restored from the stack (pop {r1, r2, r3}; mov sp, r3) it gets the wrong value. -- Summary: GCC generates incorrect code on ARM in certain case, resulting in stack corruption Product: gcc Version: 4.1.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: awalbran at innaworks dot com GCC target triplet: arm-elf http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34341