I have done some detailed research on this problem. It is after the needed information. Please do have a look.
The source is checked out on 2008-11-07
The system is using O32 abi.
The configure option is
var/tmp/portage/sys-devel/gcc-4.4.0_pre9999/work/gcc-4.4.0-9999/gcc/configure --cache-file=./config.cache --with-stabs --prefix=/usr --bindir=/usr/mipsel-unknown-linux-gnu/gcc-bin/4.4.0-pre9999 --includedir=/usr/lib/gcc/mipsel-unknown-linux-gnu/4.4.0-pre9999/include --datadir=/usr/share/gcc-data/mipsel-unknown-linux-gnu/4.4.0-pre9999 --mandir=/usr/share/gcc-data/mipsel-unknown-linux-gnu/4.4.0-pre9999/man --infodir=/usr/share/gcc-data/mipsel-unknown-linux-gnu/4.4.0-pre9999/info --with-gxx-include-dir=/usr/lib/gcc/mipsel-unknown-linux-gnu/4.4.0-pre9999/include/g++-v4 --disable-altivec --disable-fixed-point --enable-nls --without-included-gettext --with-system-zlib --disable-checking --disable-werror --enable-secureplt --disable-multilib --enable-libmudflap --disable-libssp --disable-libgomp --enable-cld --disable-libgcj --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-clocale=gnu --with-bugurl=http://bugs.gentoo.org/ --with-pkgversion= --enable-linux-futex --enable-languages=c,c++ --program-transform-name=s,y,y, --build=mipsel-unknown-linux-gnu --host=mipsel-unknown-linux-gnu --target=mipsel-unknown-linux-gnu --srcdir=/var/tmp/portage/sys-devel/gcc-4.4.0_pre9999/work/gcc-4.4.0-9999/gcc --with-build-libsubdir=.
The command to build genautomata is:
/var/tmp/portage/sys-devel/gcc-4.4.0_pre9999/work/build/./prev-gcc/xgcc -B/var/tmp/portage/sys-devel/gcc-4.4.0_pre9999/work/build/./prev-gcc/ -B/usr/mipsel-unknown-linux-gnu/bin/ -c -O2 -g -pipe -DIN_GCC -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wcast-qual -Wold-style-definition -Wc++-compat -Wmissing-format-attribute -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -DHAVE_CONFIG_H -DGENERATOR_FILE -I. -Ibuild -I/var/tmp/portage/sys-devel/gcc-4.4.0_pre9999/work/gcc-4.4.0-9999/gcc -I/var/tmp/portage/sys-devel/gcc-4.4.0_pre9999/work/gcc-4.4.0-9999/gcc/build -I/var/tmp/portage/sys-devel/gcc-4.4.0_pre9999/work/gcc-4.4.0-9999/gcc/../include -I/var/tmp/portage/sys-devel/gcc-4.4.0_pre9999/work/gcc-4.4.0-9999/gcc/../libcpp/include -I/var/tmp/portage/sys-devel/gcc-4.4.0_pre9999/work/gcc-4.4.0-9999/gcc/../libdecnumber -I/var/tmp/portage/sys-devel/gcc-4.4.0_pre9999/work/gcc-4.4.0-9999/gcc/../libdecnumber/dpd -I../libdecnumber -DCLOOG_PPL_BACKEND -o build/genautomata.o /var/tmp/portage/sys-devel/gcc-4.4.0_pre9999/work/gcc-4.4.0-9999/gcc/genautomata.c
/var/tmp/portage/sys-devel/gcc-4.4.0_pre9999/work/build/./prev-gcc/xgcc -B/var/tmp/portage/sys-devel/gcc-4.4.0_pre9999/work/build/./prev-gcc/ -B/usr/mipsel-unknown-linux-gnu/bin/ -O2 -g -pipe -DIN_GCC -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wcast-qual -Wold-style-definition -Wc++-compat -Wmissing-format-attribute -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -DHAVE_CONFIG_H -DGENERATOR_FILE -o build/genautomata \
build/genautomata.o build/rtl.o build/read-rtl.o build/ggc-none.o build/vec.o build/min-insn-modes.o build/gensupport.o build/print-rtl.o build/errors.o .././libiberty/libiberty.a -lm
The command segfaulted:
build/genautomata /var/tmp/portage/sys-devel/gcc-4.4.0_pre9999/work/gcc-4.4.0-9999/gcc/config/mips/mips.md insn-conditions.md
I have debugged this executable with gdb. And I found the exact instruction which caused the segfaults. It has something to do with the manipulation of $gp register.
From readelf -a genautomata, the Canonical gp value of Primary GOT: 00440090
Normally before calling an function, the gp register must be loaded with this value. This can be observed it compiled with no optimization option.
However if -O2 is enabled, the following code in genautomata.c:
6975 fprintf (output_file, "static const ");
6976 output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
6977 fprintf (output_file, " ");
6978 output_translate_vect_name (output_file, automaton);
becomes(this is generated with -S option):
li $5,1 # 0x1
li $6,13 # 0xd
li $4,32 # 0x20
We can see there is no "lw $28,16($sp)" before "jal output_range_type" or "jal output_translate_vect_name"
In the case of output_range_type, there is no problem, because inside the function, the only access to GOT is to find "fwrite"'s GOT entry. And the entry already contains the resolved address, since immediately before the call to output_range_type, there is a call to fwrite.
The problem with output_translate_vect_name is this function has two calls to fprintf, and they are called for the first time in this program. So we need to call the lazy resolver. And that's exactly where the program segfaults. Since gp's value is incorrect, neither will be the resolver's address.
That's what I have got so far. Hope this could help to solve the problem.
(In reply to comment #0)
> The problem with output_translate_vect_name is this function has two calls to
> fprintf, and they are called for the first time in this program.
Another thing I don't understand is why fprintf elsewhere is replaced with fwrite including in the output_range_type function, but it is still itself in output_translate_vect_name.
I have done an experiment. Please take a look at the beginning of output_translate_vect_name function:
0x0040647c <output_translate_vect_name+0>: addiu sp,sp,-8
0x00406480 <output_translate_vect_name+4>: lw v0,4(a1)
0x00406484 <output_translate_vect_name+8>: sw gp,4(sp)
0x00406488 <output_translate_vect_name+12>: lui gp,0x44
0x0040648c <output_translate_vect_name+16>: beqz v0,0x4064b0 <output_translate_vect_name+52>
0x00406490 <output_translate_vect_name+20>: addiu gp,gp,4240
0x00406494 <output_translate_vect_name+24>: lw t9,-32532(gp)
0x00406498 <output_translate_vect_name+28>: lui a1,0x42
0x0040649c <output_translate_vect_name+32>: lw gp,4(sp)
0x004064a0 <output_translate_vect_name+36>: lw a2,0(v0)
0x004064a4 <output_translate_vect_name+40>: addiu a1,a1,-8008
0x004064a8 <output_translate_vect_name+44>: jr t9
If I replace the following instruction with nop, then the genautomata will succeed.
0x0040649c <output_translate_vect_name+32>: lw gp,4(sp)
I ran into this too. The problem flag is -foptimize-sibling-calls. You can pass that with -O1 to trigger the bug, but not with -O0. Some other optimization in -O1 seems to be mixing with this one and causing the flaw.
Ran into this on mips-unknown-linux-gnu, btw. Mips-specific maybe?
liblbxutil-1.0.1 package could be used to reproduce this bug.
I will investigate this later when i have time.
and sed-4.1.5, too.
I am trying to find which specific flag or flags when used together with -foptimize-sibling-calls could trigger this problem.
As the first step I tried to find a set of flags used together with -O0 and -foptimize-sibling-calls could trigger this problem. Presumably this set of flags should be those disabled at -O0 but enabled at -O1.
So I did the following to find the differences:
gcc -c -Q -O0 --help=optimizers > /tmp/O0-opts
gcc -c -Q -O1 --help=optimizers > /tmp/O1-opts
diff /tmp/O0-opts /tmp/O1-opts | grep enabled | cut -d " " -f 4
Then I used these flags with -O0 and -foptimize-sibling-calls together, but this didn't trigger the bug.
Is there anything I have overlooked here?
> Then I used these flags with -O0 and -foptimize-sibling-calls together, but
> this didn't trigger the bug.
> Is there anything I have overlooked here?
Yes, not all optimizations are controlled by a specific flag, as explained in
I'll try to look at this tomorrow. The code in comment #1 is certainly wrong: the store at <output_translate_vect_name+8> is supposed come after the GP addiu at <output_translate_vect_name+20>. With that fixed, the function should work as expected.
I'm guessing this is a scheduling bug, but time will tell.
Subject: Bug 38052
Date: Sun Nov 16 20:25:40 2008
New Revision: 141925
* config/mips/mips.c (machine_function): Update the comment
(mips_global_pointer): Use INVALID_REGNUM rather than 0 to indicate
that a function doesn't need a global pointer.
(mips_current_loadgp_style): Update accordingly.
Subject: Bug 38052
Date: Sun Nov 16 20:31:13 2008
New Revision: 141926
* config/mips/mips.c (mips_cfun_call_saved_reg_p)
(mips_cfun_might_clobber_call_saved_reg_p): New functions,
split out from...
(mips_save_reg_p): ...here. Always consult TARGET_CALL_SAVED_GP
rather than call_really_used_regs when handling $gp.
Fixed on mainline.