Good evening, on and off for years, I've been bitten by a miscompilation of 'goto' on the mips target. I finally isolated it into a single test-case that I can report. I believe this bug to be at least 6 years old and it is still present in version 2.18.1~cvs20080103-7 (as used in debian/sid).
The problem boils down to these assembler constructs which SHOULD behave the same as I understand it: sw $3,%lo(nextFun)($2) - lw $1,%got($L894)($28) + lui $1,%hi($L894) nop addiu $1,$1,%lo($L894) jr $1 The '%got' variant which is used by default on EABI will lead to a segmentation fault. I suspect the problem is related to (at least) two facts: the entire method is over 64kB large and the jumps that get miscompiled are 'near' a 64kB boundary. I have put up a tarball with the miscompiled assembler, the original C file, and a library sufficient to link the final program at: < http://www.terpstra.ca/debian/bad-goto.tar.gz>. If you want to blame gcc (though i think the assembler it generated is valid) here is how to rebuild the assembler: gcc -std=gnu99 -O0 -g -w -fno-strict-aliasing mlyacc.6.preprocessed.c -S -o mlyacc.6.preprocessed.s To link the two alternatives: gcc -o ok mlyacc.6.preprocessed.ok.s link.a -lgmp -lm gcc -o bad mlyacc.6.preprocessed.bad.s link.a -lgmp -lm ... the gmp version used here is 5.0.1+dfsg-7 from debian sid. ... the glibc version is 2.11.2-11 (again from debian sid) To observe the bad jump: gdb ./bad break mlyacc.6.preprocessed.c:2915 run Breakpoint 1, Chunk6 () at mlyacc.6.preprocessed.c:2915 2915 *(Word8*)(stackTop + (60)) = (Word8)(Word8)0x0; (gdb) s 2916 *(CPointer*)(stackTop + (56)) = 25; (gdb) 2917 do { if (0) fprintf (stderr, "%s:%d: Push (%d)\n", "mlyacc.6.c", 912, 60); stackTop += (60); } while (0); (gdb) 2919 cont.nextChunk = (void*)Chunk0; (gdb) 2920 nextFun = 2736; } (gdb) 2922 goto leaveChunk; /* !!! This jump goes the wrong way !!! */ (gdb) Program received signal SIGSEGV, Segmentation fault. 0x2aabead0 in _dl_check_caller (caller=0x0, mask=0) at dl-caller.c:39 39 dl-caller.c: No such file or directory. in dl-caller.c If you run the same sequence on 'gdb ./ok' the program will proceed past the bad jump and die at the next bad jump. (Yes, in this file there are multiple jumps which get miscompiled. mlyacc.6.preprocessed.ok.s only has the first jump corrected.
_______________________________________________ bug-binutils mailing list bug-binutils@gnu.org https://lists.gnu.org/mailman/listinfo/bug-binutils