diff options
-rw-r--r-- | gcc/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/config.in | 7 | ||||
-rwxr-xr-x | gcc/configure | 47 | ||||
-rw-r--r-- | gcc/configure.ac | 43 | ||||
-rw-r--r-- | gcc/except.c | 16 | ||||
-rw-r--r-- | gcc/except.h | 2 | ||||
-rw-r--r-- | gcc/final.c | 4 |
7 files changed, 127 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fe590bf..344caf3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2006-10-28 Eric Botcazou <ebotcazou@adacore.com> + + * except.h (output_function_exception_table): Add 'const char*' param. + * except.c (switch_to_exception_section): Add 'const char*' param. + If named sections are supported and HAVE_LD_EH_GC_SECTIONS is defined + and flag_function_sections is set, use a function-specific section. + (output_function_exception_table): Add 'const char*' param. + Adjust call to switch_to_exception_section. + * final.c (rest_of_handle_final): Adjust calls to + output_function_exception_table. + * configure.ac (HAVE_LD_EH_GC_SECTIONS): New check. + * config.in: Regenerate. + * configure: Likewise. + 2006-10-28 Richard Guenther <rguenther@suse.de> PR middle-end/26899 diff --git a/gcc/config.in b/gcc/config.in index 65b583b..91146bb 100644 --- a/gcc/config.in +++ b/gcc/config.in @@ -883,6 +883,13 @@ /* Define if your linker supports --eh-frame-hdr option. */ #undef HAVE_LD_EH_FRAME_HDR +/* Define if your linker supports garbage collection of sections in presence + of EH frames. */ +#ifndef USED_FOR_TARGET +#undef HAVE_LD_EH_GC_SECTIONS +#endif + + /* Define if your PowerPC64 linker only needs function descriptor syms. */ #ifndef USED_FOR_TARGET #undef HAVE_LD_NO_DOT_SYMS diff --git a/gcc/configure b/gcc/configure index 2eb6bb7..54a2a17 100755 --- a/gcc/configure +++ b/gcc/configure @@ -15889,6 +15889,53 @@ fi echo "$as_me:$LINENO: result: $gcc_cv_ld_pie" >&5 echo "${ECHO_T}$gcc_cv_ld_pie" >&6 +echo "$as_me:$LINENO: checking linker EH-compatible garbage collection of sections" >&5 +echo $ECHO_N "checking linker EH-compatible garbage collection of sections... $ECHO_C" >&6 +gcc_cv_ld_eh_gc_sections=no +if test $in_tree_ld = yes ; then + if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 17 -o "$gcc_cv_gld_major_version" -gt 2 \ + && test $in_tree_ld_is_elf = yes; then + gcc_cv_ld_eh_gc_sections=yes + fi +elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x -a x$gcc_cv_objdump != x ; then + cat > conftest.s <<EOF + .section .text +.globl _start + .type _start, @function +_start: + .long foo + .size _start, .-_start + .section .text.foo,"ax",@progbits + .type foo, @function +foo: + .long 0 + .size foo, .-foo + .section .gcc_except_table.foo,"a",@progbits +.L0: + .long 0 + .section .eh_frame,"a",@progbits + .long .L0 +EOF + if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1; then + if $gcc_cv_ld -o conftest conftest.o --entry=_start --gc-sections 2>&1 \ + | grep "gc-sections option ignored" > /dev/null; then + gcc_cv_ld_eh_gc_sections=no + elif $gcc_cv_objdump -h conftest | grep gcc_except_table > /dev/null; then + gcc_cv_ld_eh_gc_sections=yes + fi + fi + rm -f conftest.s conftest.o conftest +fi +if test x$gcc_cv_ld_eh_gc_sections = xyes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LD_EH_GC_SECTIONS 1 +_ACEOF + +fi +echo "$as_me:$LINENO: result: $gcc_cv_ld_eh_gc_sections" >&5 +echo "${ECHO_T}$gcc_cv_ld_eh_gc_sections" >&6 + # -------- # UNSORTED # -------- diff --git a/gcc/configure.ac b/gcc/configure.ac index 7c8b3af..1dafd85 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -3119,6 +3119,49 @@ if test x"$gcc_cv_ld_pie" = xyes; then fi AC_MSG_RESULT($gcc_cv_ld_pie) +AC_MSG_CHECKING(linker EH-compatible garbage collection of sections) +gcc_cv_ld_eh_gc_sections=no +if test $in_tree_ld = yes ; then + if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 17 -o "$gcc_cv_gld_major_version" -gt 2 \ + && test $in_tree_ld_is_elf = yes; then + gcc_cv_ld_eh_gc_sections=yes + fi +elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x -a x$gcc_cv_objdump != x ; then + cat > conftest.s <<EOF + .section .text +.globl _start + .type _start, @function +_start: + .long foo + .size _start, .-_start + .section .text.foo,"ax",@progbits + .type foo, @function +foo: + .long 0 + .size foo, .-foo + .section .gcc_except_table.foo,"a",@progbits +.L0: + .long 0 + .section .eh_frame,"a",@progbits + .long .L0 +EOF + if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1; then + if $gcc_cv_ld -o conftest conftest.o --entry=_start --gc-sections 2>&1 \ + | grep "gc-sections option ignored" > /dev/null; then + gcc_cv_ld_eh_gc_sections=no + elif $gcc_cv_objdump -h conftest | grep gcc_except_table > /dev/null; then + gcc_cv_ld_eh_gc_sections=yes + fi + fi + rm -f conftest.s conftest.o conftest +fi +if test x$gcc_cv_ld_eh_gc_sections = xyes; then + AC_DEFINE(HAVE_LD_EH_GC_SECTIONS, 1, + [Define if your linker supports garbage collection of + sections in presence of EH frames.]) +fi +AC_MSG_RESULT($gcc_cv_ld_eh_gc_sections) + # -------- # UNSORTED # -------- diff --git a/gcc/except.c b/gcc/except.c index 30dafbb..3069169 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -3520,7 +3520,7 @@ sjlj_output_call_site_table (void) /* Switch to the section that should be used for exception tables. */ static void -switch_to_exception_section (void) +switch_to_exception_section (const char * ARG_UNUSED (fnname)) { if (exception_section == 0) { @@ -3539,6 +3539,16 @@ switch_to_exception_section (void) } else flags = SECTION_WRITE; +#ifdef HAVE_LD_EH_GC_SECTIONS + if (flag_function_sections) + { + char *section_name = xmalloc (strlen (fnname) + 32); + sprintf (section_name, ".gcc_except_table.%s", fnname); + exception_section = get_section (section_name, flags, NULL); + free (section_name); + } + else +#endif exception_section = get_section (".gcc_except_table", flags, NULL); } else @@ -3599,7 +3609,7 @@ output_ttype (tree type, int tt_format, int tt_format_size) } void -output_function_exception_table (void) +output_function_exception_table (const char * ARG_UNUSED (fnname)) { int tt_format, cs_format, lp_format, i, n; #ifdef HAVE_AS_LEB128 @@ -3627,7 +3637,7 @@ output_function_exception_table (void) /* Note that varasm still thinks we're in the function's code section. The ".endp" directive that will immediately follow will take us back. */ #else - switch_to_exception_section (); + switch_to_exception_section (fnname); #endif /* If the target wants a label to begin the table, emit it here. */ diff --git a/gcc/except.h b/gcc/except.h index 1f96477..5efad71 100644 --- a/gcc/except.h +++ b/gcc/except.h @@ -68,7 +68,7 @@ extern void convert_from_eh_region_ranges (void); extern unsigned int convert_to_eh_region_ranges (void); extern void find_exception_handler_labels (void); extern bool current_function_has_exception_handlers (void); -extern void output_function_exception_table (void); +extern void output_function_exception_table (const char *); extern void expand_builtin_unwind_init (void); extern rtx expand_builtin_eh_return_data_regno (tree); diff --git a/gcc/final.c b/gcc/final.c index d64f0c3..9e35d53 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -3920,14 +3920,14 @@ rest_of_handle_final (void) #ifdef TARGET_UNWIND_INFO /* ??? The IA-64 ".handlerdata" directive must be issued before the ".endp" directive that closes the procedure descriptor. */ - output_function_exception_table (); + output_function_exception_table (fnname); #endif assemble_end_function (current_function_decl, fnname); #ifndef TARGET_UNWIND_INFO /* Otherwise, it feels unclean to switch sections in the middle. */ - output_function_exception_table (); + output_function_exception_table (fnname); #endif user_defined_section_attribute = false; |