This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
gas misoptimizes gcc3 .eh_frame
- To: gcc-patches at gcc dot gnu dot org
- Subject: gas misoptimizes gcc3 .eh_frame
- From: Richard Henderson <rth at redhat dot com>
- Date: Mon, 14 May 2001 19:03:41 -0700
I've just committed a binutils patch that I believe fixes it. However,
what remains is the problem of what to do for still broken assemblers.
The following doesn't exactly test what's broken with the old assembler.
The breakage was of a curious form that would give nonsensical error
messages on e.g. x86, while producing incorrect data on e.g. alpha.
Instead it tests something that should work with the fixed assembler,
and will definitely not work with a broken assembler.
Applied to branch and mainline.
r~
PS: At some point it'd be nice to say, "dammit, upgrade" instead
of working around the problem. Perhaps gcc 3.1 configure should
hard error on all binutils bugs worked around for gcc 3.0.
* configure.in (gcc_cv_as_eh_frame): New test.
* config.in, configure: Rebuild.
* gcc.c (init_spec): Honor USE_AS_TRADITIONAL_FORMAT.
Index: configure.in
===================================================================
RCS file: /cvs/gcc/egcs/gcc/configure.in,v
retrieving revision 1.522
diff -c -p -d -r1.522 configure.in
*** configure.in 2001/05/13 11:25:55 1.522
--- configure.in 2001/05/15 01:39:17
*************** if test x"$gcc_cv_as_leb128" = xyes; the
*** 1410,1415 ****
--- 1410,1486 ----
fi
AC_MSG_RESULT($gcc_cv_as_leb128)
+ AC_MSG_CHECKING(assembler eh_frame optimization)
+ gcc_cv_as_eh_frame=no
+ if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x; then
+ if test "$gcc_cv_gas_major_version" -eq 2 -a "$gcc_cv_gas_minor_version" -ge 12 -o "$gcc_cv_gas_major_version" -gt 2 && grep 'obj_format = elf' ../gas/Makefile > /dev/null; then
+ gcc_cv_as_eh_frame="yes"
+ fi
+ elif test x$gcc_cv_as != x; then
+ # Check if this is GAS.
+ as_ver=`$gcc_cv_as --version 2>/dev/null | head -1`
+ if echo "$as_ver" | grep GNU > /dev/null; then
+ # Versions up to and including 2.11.0 may mis-optimize
+ # .eh_frame data. Try something.
+ cat > conftest.s <<EOF
+ .text
+ .LFB1:
+ .4byte 0
+ .L1:
+ .4byte 0
+ .LFE1:
+ .section .eh_frame,"aw",@progbits
+ __FRAME_BEGIN__:
+ .4byte .LECIE1-.LSCIE1
+ .LSCIE1:
+ .4byte 0x0
+ .byte 0x1
+ .ascii "z\0"
+ .byte 0x1
+ .byte 0x78
+ .byte 0x1a
+ .byte 0x0
+ .byte 0x4
+ .4byte 1
+ .p2align 1
+ .LECIE1:
+ .LSFDE1:
+ .4byte .LEFDE1-.LASFDE1
+ .LASFDE1:
+ .4byte .LASFDE1-__FRAME_BEGIN__
+ .4byte .LFB1
+ .4byte .LFE1-.LFB1
+ .byte 0x4
+ .4byte .LFE1-.LFB1
+ .byte 0x4
+ .4byte .L1-.LFB1
+ .LEFDE1:
+ EOF
+ cat > conftest.exp <<EOF
+ 0000 10000000 00000000 017a0001 781a0004 .........z..x...
+ 0010 01000000 12000000 18000000 00000000 ................
+ 0020 08000000 04080000 0044 .........D
+ EOF
+ # If the assembler didn't choke, and we can objdump,
+ # and we got the correct data, then succeed.
+ if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1 \
+ && objdump -s -j .eh_frame conftest.o 2>/dev/null \
+ | tail -3 > conftest.got \
+ && cmp conftest.exp conftest.got > /dev/null 2>&1
+ then
+ gcc_cv_as_eh_frame="yes"
+ else
+ gcc_cv_as_eh_frame="bad"
+ if $gcc_cv_as -o conftest.o --traditional-format /dev/null; then
+ AC_DEFINE(USE_AS_TRADITIONAL_FORMAT, 1,
+ [Define if your assembler mis-optimizes .eh_frame data.])
+ fi
+ fi
+ fi
+ rm -f conftest.*
+ fi
+ AC_MSG_RESULT($gcc_cv_as_eh_frame)
+
case "$target" in
sparc*-*-*)
AC_CACHE_CHECK([assembler .register pseudo-op support],
Index: gcc.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/gcc.c,v
retrieving revision 1.226
diff -c -p -d -r1.226 gcc.c
*** gcc.c 2001/05/13 22:17:02 1.226
--- gcc.c 2001/05/15 01:39:17
*************** init_spec ()
*** 1454,1459 ****
--- 1454,1468 ----
libgcc_spec = obstack_finish (&obstack);
}
#endif
+ #ifdef USE_AS_TRADITIONAL_FORMAT
+ /* Prepend "--traditional-format" to whatever asm_spec we had before. */
+ {
+ static char tf[] = "--traditional-format ";
+ obstack_grow (&obstack, tf, sizeof(tf) - 1);
+ obstack_grow0 (&obstack, asm_spec, strlen (asm_spec));
+ asm_spec = obstack_finish (&obstack);
+ }
+ #endif
specs = sl;
}