The assembler instructions gcc generates for a 'goto' statement only respect the low 16 bits of the destination address by default (or in when using PIC in general). This causes the program to jump to the wrong location and soon thereafter segfault. The -mno-explicit-relocs seems to work around this problem, but is no solution for a PIC compilation.
This problem appears in both: Using built-in specs. Target: mips-unknown-linux-gnu Configured with: ../gcc/configure --prefix=/home/terpstra/gcc.bin --enable-languages=c Thread model: posix gcc version 4.4.4 (GCC) and: Using built-in specs. Target: mips-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Debian 4.4.4-3' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --program-suffix=-4.4 --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --disable-libssp --enable-targets=all --enable-checking=release --build=mips-linux-gnu --host=mips-linux-gnu --target=mips-linux-gnu Thread model: posix gcc version 4.4.4 (Debian 4.4.4-3) However, I've been having related problems since as far back as gcc-3.4 (at least). The gcc-snapshot in debian also does not resolve this issue. Sometimes different compiler versions and/or optimization flags cause compilation to succeed. I presume this is because the jump offsets fit into 16 bits with different optimization choices. I've seen a related problem where gcc -fPIC creates invalid assembler that with 'branch out of range' .s files. However, first I'll see if this bug being fixed resolves the other. I've included an example C program which can produce the buggy assembler. Compile with: <gcc> -std=gnu99 -O0 -fno-common -fno-strict-aliasing -fomit-frame-pointer -w -S mlyacc.6.preprocessed-nolines.c -g -o bug.s The problem assembler comes from the goto on line 2928: goto leaveChunk; ... when tracing with gdb execution should resume on line 33861, however it instead jumps to line 2749: Inspecting the generated assembler: .loc 1 2928 0 .set noat lw $1,%got($L894)($28) nop addiu $1,$1,%lo($L894) jr $1 ... it is easy to see that the correct label (L894) is used as destination. However, only the low 16 bits of the address are used. When compiled with -mno-explicit-relocs, the assembler reads as: .loc 1 2928 0 .set noat la $1,$L894 # jr $1 ... which works. Modifying the -mexplicit-relocs version (gcc default) to use 'la' instead of the PIC %got results in correct program execution. -- Summary: gcc produces bad MIPS jumps (in large C files) Product: gcc Version: 4.4.4 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: wesley at terpstra dot ca GCC build triplet: mips-unknown-linux-gnu GCC host triplet: mips-unknown-linux-gnu GCC target triplet: mips-unknown-linux-gnu http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44537