diff options
author | Richard Sandiford <rdsandiford@googlemail.com> | 2009-09-20 10:36:05 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2009-09-20 10:36:05 +0000 |
commit | 49576e25cbab7891bc3296e2bcd84d0c284560a6 (patch) | |
tree | a84e1e4e16568ba17408fdb8f2fe99d6a35e7ea4 | |
parent | 63c6c7e070b9c79d0a797ed50fa90c8f1d35480d (diff) | |
download | gcc-49576e25cbab7891bc3296e2bcd84d0c284560a6.zip gcc-49576e25cbab7891bc3296e2bcd84d0c284560a6.tar.gz gcc-49576e25cbab7891bc3296e2bcd84d0c284560a6.tar.bz2 |
configure.ac (gcc_cv_ld_mips_personality_relaxation): New feature check.
gcc/
* configure.ac (gcc_cv_ld_mips_personality_relaxation): New
feature check.
(HAVE_LD_PERSONALITY_RELAXATION): New macro definition.
* configure, config.in: Regenerate.
* dwarf2asm.c (eh_data_format_name): Handle DW_EH_PE_indirect |
DW_EH_PE_absptr.
* config/mips/mips.h (TARGET_WRITABLE_EH_FRAME): New macro.
(ASM_PREFERRED_EH_DATA_FORMAT): Define. Use MIPS_EH_INDIRECT
for global data if the output could be used in a shared library.
* config/mips/mips.c (mips_override_options): Set flag_dwarf2_cfi_asm
to 0 if TARGET_WRITABLE_EH_FRAME.
From-SVN: r151896
-rw-r--r-- | gcc/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/config.in | 7 | ||||
-rw-r--r-- | gcc/config/mips/mips.c | 5 | ||||
-rw-r--r-- | gcc/config/mips/mips.h | 35 | ||||
-rwxr-xr-x | gcc/configure | 51 | ||||
-rw-r--r-- | gcc/configure.ac | 45 | ||||
-rw-r--r-- | gcc/dwarf2asm.c | 2 |
7 files changed, 159 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9ed696d..91b323e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2009-09-20 Richard Sandiford <rdsandiford@googlemail.com> + + * configure.ac (gcc_cv_ld_mips_personality_relaxation): New + feature check. + (HAVE_LD_PERSONALITY_RELAXATION): New macro definition. + * configure, config.in: Regenerate. + * dwarf2asm.c (eh_data_format_name): Handle DW_EH_PE_indirect | + DW_EH_PE_absptr. + * config/mips/mips.h (TARGET_WRITABLE_EH_FRAME): New macro. + (ASM_PREFERRED_EH_DATA_FORMAT): Define. Use MIPS_EH_INDIRECT + for global data if the output could be used in a shared library. + * config/mips/mips.c (mips_override_options): Set flag_dwarf2_cfi_asm + to 0 if TARGET_WRITABLE_EH_FRAME. + 2009-09-20 Paolo Bonzini <bonzini@gnu.org> PR/39886 diff --git a/gcc/config.in b/gcc/config.in index 40d7e4d..9ee0bde 100644 --- a/gcc/config.in +++ b/gcc/config.in @@ -1108,6 +1108,13 @@ #endif +/* Define if your linker can relax absolute .eh_frame personality pointers + into PC-relative form. */ +#ifndef USED_FOR_TARGET +#undef HAVE_LD_PERSONALITY_RELAXATION +#endif + + /* Define if your linker supports -pie option. */ #ifndef USED_FOR_TARGET #undef HAVE_LD_PIE diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 2f0c56d..ace48ba 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -15528,6 +15528,11 @@ mips_override_options (void) if (mips_abi == ABI_EABI && TARGET_64BIT) flag_dwarf2_cfi_asm = 0; + /* .cfi_* directives generate a read-only section, so fall back on + manual .eh_frame creation if we need the section to be writable. */ + if (TARGET_WRITABLE_EH_FRAME) + flag_dwarf2_cfi_asm = 0; + mips_init_print_operand_punct (); /* Set up array to map GCC register number to debug register number. diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index 71b9b1b..defcd6e 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -230,6 +230,14 @@ enum mips_code_readable_setting { && !TARGET_ABSOLUTE_ABICALLS \ && !(mips_abi == ABI_64 && TARGET_IRIX)) +/* True if the output must have a writable .eh_frame. + See ASM_PREFERRED_EH_DATA_FORMAT for details. */ +#ifdef HAVE_LD_PERSONALITY_RELAXATION +#define TARGET_WRITABLE_EH_FRAME 0 +#else +#define TARGET_WRITABLE_EH_FRAME (flag_pic && TARGET_SHARED) +#endif + /* Generate mips16 code */ #define TARGET_MIPS16 ((target_flags & MASK_MIPS16) != 0) /* Generate mips16e code. Default 16bit ASE for mips32* and mips64* */ @@ -3182,3 +3190,30 @@ extern enum mips_code_readable_setting mips_code_readable; /* This is necessary to avoid a warning about comparing different enum types. */ #define mips_tune_attr ((enum attr_cpu) mips_tune) + +/* As on most targets, we want the .eh_frame section to be read-only where + possible. And as on most targets, this means two things: + + (a) Non-locally-binding pointers must have an indirect encoding, + so that the addresses in the .eh_frame section itself become + locally-binding. + + (b) A shared library's .eh_frame section must encode locally-binding + pointers in a relative (relocation-free) form. + + However, MIPS has traditionally not allowed directives like: + + .long x-. + + in cases where "x" is in a different section, or is not defined in the + same assembly file. We are therefore unable to emit the PC-relative + form required by (b) at assembly time. + + Fortunately, the linker is able to convert absolute addresses into + PC-relative addresses on our behalf. Unfortunately, only certain + versions of the linker know how to do this for indirect pointers, + and for personality data. We must fall back on using writable + .eh_frame sections for shared libraries if the linker does not + support this feature. */ +#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \ + (((GLOBAL) ? DW_EH_PE_indirect : 0) | DW_EH_PE_absptr) diff --git a/gcc/configure b/gcc/configure index 2369ba7..ced17cd 100755 --- a/gcc/configure +++ b/gcc/configure @@ -23725,6 +23725,57 @@ $as_echo_n "checking assembler and linker for explicit JALR relocation... " >&6; fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_ld_jalr_reloc" >&5 $as_echo "$gcc_cv_as_ld_jalr_reloc" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking linker for .eh_frame personality relaxation" >&5 +$as_echo_n "checking linker for .eh_frame personality relaxation... " >&6; } +if test "${gcc_cv_ld_mips_personality_relaxation+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + gcc_cv_ld_mips_personality_relaxation=no + if test $in_tree_ld = yes ; then + if test "$gcc_cv_gld_major_version" -eq 2 \ + -a "$gcc_cv_gld_minor_version" -ge 21 \ + -o "$gcc_cv_gld_major_version" -gt 2; then + gcc_cv_ld_mips_personality_relaxation=yes + fi + elif test x$gcc_cv_as != x \ + -a x$gcc_cv_ld != x \ + -a x$gcc_cv_readelf != x ; then + cat > conftest.s <<EOF + .cfi_startproc + .cfi_personality 0x80,indirect_ptr + .ent test +test: + nop + .end test + .cfi_endproc + + .section .data,"aw",@progbits +indirect_ptr: + .dc.a personality +EOF + if $gcc_cv_as -KPIC -o conftest.o conftest.s > /dev/null 2>&1 \ + && $gcc_cv_ld -o conftest conftest.o -shared > /dev/null 2>&1; then + if $gcc_cv_readelf -d conftest 2>&1 \ + | grep TEXTREL > /dev/null 2>&1; then + : + elif $gcc_cv_readelf --relocs conftest 2>&1 \ + | grep 'R_MIPS_REL32 *$' > /dev/null 2>&1; then + : + else + gcc_cv_ld_mips_personality_relaxation=yes + fi + fi + fi + rm -f conftest.s conftest.o conftest +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_mips_personality_relaxation" >&5 +$as_echo "$gcc_cv_ld_mips_personality_relaxation" >&6; } + if test x$gcc_cv_ld_mips_personality_relaxation = xyes; then + +$as_echo "#define HAVE_LD_PERSONALITY_RELAXATION 1" >>confdefs.h + + fi ;; esac diff --git a/gcc/configure.ac b/gcc/configure.ac index d1eed72..3f0ff7d 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -3315,6 +3315,51 @@ x: fi fi AC_MSG_RESULT($gcc_cv_as_ld_jalr_reloc) + + AC_CACHE_CHECK([linker for .eh_frame personality relaxation], + [gcc_cv_ld_mips_personality_relaxation], + [gcc_cv_ld_mips_personality_relaxation=no + if test $in_tree_ld = yes ; then + if test "$gcc_cv_gld_major_version" -eq 2 \ + -a "$gcc_cv_gld_minor_version" -ge 21 \ + -o "$gcc_cv_gld_major_version" -gt 2; then + gcc_cv_ld_mips_personality_relaxation=yes + fi + elif test x$gcc_cv_as != x \ + -a x$gcc_cv_ld != x \ + -a x$gcc_cv_readelf != x ; then + cat > conftest.s <<EOF + .cfi_startproc + .cfi_personality 0x80,indirect_ptr + .ent test +test: + nop + .end test + .cfi_endproc + + .section .data,"aw",@progbits +indirect_ptr: + .dc.a personality +EOF + if $gcc_cv_as -KPIC -o conftest.o conftest.s > /dev/null 2>&1 \ + && $gcc_cv_ld -o conftest conftest.o -shared > /dev/null 2>&1; then + if $gcc_cv_readelf -d conftest 2>&1 \ + | grep TEXTREL > /dev/null 2>&1; then + : + elif $gcc_cv_readelf --relocs conftest 2>&1 \ + | grep 'R_MIPS_REL32 *$' > /dev/null 2>&1; then + : + else + gcc_cv_ld_mips_personality_relaxation=yes + fi + fi + fi + rm -f conftest.s conftest.o conftest]) + if test x$gcc_cv_ld_mips_personality_relaxation = xyes; then + AC_DEFINE(HAVE_LD_PERSONALITY_RELAXATION, 1, + [Define if your linker can relax absolute .eh_frame personality +pointers into PC-relative form.]) + fi ;; esac diff --git a/gcc/dwarf2asm.c b/gcc/dwarf2asm.c index c12f809..c779e07 100644 --- a/gcc/dwarf2asm.c +++ b/gcc/dwarf2asm.c @@ -446,6 +446,8 @@ eh_data_format_name (int format) S(DW_EH_PE_sdata4 | DW_EH_PE_funcrel, "funcrel sdata4") S(DW_EH_PE_sdata8 | DW_EH_PE_funcrel, "funcrel sdata8") + S(DW_EH_PE_indirect | DW_EH_PE_absptr, "indirect absolute") + S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_pcrel, "indirect pcrel") S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_pcrel, |