This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] EH-compatible -ffunction-sections


Hi,

Now that the linker patch has been installed in the binutils tree, here's the 
GCC patch needed to let the -ffunction-sections -fdata-sections 
-Wl,--gc-sections mechanism work with Ada programs.

For a description of the mechanism, see:
http://gcc.gnu.org/ml/gcc/2004-03/msg00506.html

Bootstrapped/regtested with and without the enhanced linker on 
i586-redhat-linux-gnu.  OK for mainline?


2004-04-26  Eric Botcazou  <ebotcazou@act-europe.fr>

        * except.h (output_function_exception_table): Add
	'const char *' parameter.
        * output.h (default_exception_section): Likewise.
        * target.h (struct gcc_target) <exception_section>: Likewise.
        * except.c (PTR_SIZE): New macro.
        (default_exception_section): Add 'const char *' parameter.
        If named sections are supported, 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 *' parameter.
	Adjust call to targetm.asm_out.exception_section.  Keep track
	of the LDSA label.
	If HAVE_LD_EH_GC_SECTIONS is defined, named sections are
	supported and flag_function_sections is set, emit a reference
	to the LDSA label in the function section.
	* passes.c (rest_of_handle_final): Adjust calls to
	output_function_exception_table.
	* configure.ac (HAVE_LD_EH_GC_SECTIONS): New check.
	* configure.in: Regenerate.
	* configure: Likewise.


-- 
Eric Botcazou
Index: except.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/except.h,v
retrieving revision 1.74
diff -u -p -r1.74 except.h
--- except.h	18 Feb 2004 15:05:03 -0000	1.74
+++ except.h	26 Apr 2004 20:37:24 -0000
@@ -107,7 +107,7 @@ extern void convert_from_eh_region_range
 extern void 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);
Index: output.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/output.h,v
retrieving revision 1.139
diff -u -p -r1.139 output.h
--- output.h	9 Apr 2004 19:57:42 -0000	1.139
+++ output.h	26 Apr 2004 20:37:28 -0000
@@ -459,7 +459,7 @@ extern const char *user_label_prefix;
 extern void default_function_pro_epilogue (FILE *, HOST_WIDE_INT);
 
 /* Tell assembler to switch to the section for the exception table.  */
-extern void default_exception_section (void);
+extern void default_exception_section (const char *);
 
 /* Tell assembler to switch to the section for the EH frames.  */
 extern void named_section_eh_frame_section (void);
Index: target.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/target.h,v
retrieving revision 1.85
diff -u -p -r1.85 target.h
--- target.h	24 Mar 2004 00:13:20 -0000	1.85
+++ target.h	26 Apr 2004 20:37:29 -0000
@@ -104,7 +104,7 @@ struct gcc_target
     void (* named_section) (const char *, unsigned int);
 
     /* Switch to the section that holds the exception table.  */
-    void (* exception_section) (void);
+    void (* exception_section) (const char *);
 
     /* Switch to the section that holds the exception frames.  */
     void (* eh_frame_section) (void);
Index: except.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/except.c,v
retrieving revision 1.266
diff -u -p -r1.266 except.c
--- except.c	20 Mar 2004 04:52:53 -0000	1.266
+++ except.c	26 Apr 2004 20:37:38 -0000
@@ -81,6 +81,11 @@ Software Foundation, 59 Temple Place - S
 #define EH_RETURN_DATA_REGNO(N) INVALID_REGNUM
 #endif
 
+/* The size of the target's pointer type.  */
+#ifndef PTR_SIZE
+#define PTR_SIZE (POINTER_SIZE / BITS_PER_UNIT)
+#endif
+
 
 /* Nonzero means enable synchronous exceptions for non-call instructions.  */
 int flag_non_call_exceptions;
@@ -3690,7 +3695,7 @@ sjlj_output_call_site_table (void)
    table.  */
 
 void
-default_exception_section (void)
+default_exception_section (const char *fnname ATTRIBUTE_UNUSED)
 {
   if (targetm.have_named_sections)
     {
@@ -3705,7 +3710,17 @@ default_exception_section (void)
 #else
       flags = SECTION_WRITE;
 #endif
-      named_section_flags (".gcc_except_table", flags);
+#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);
+	  named_section_flags (section_name, flags);
+	  free (section_name);
+	}
+      else
+#endif
+	named_section_flags (".gcc_except_table", flags);
     }
   else if (flag_pic)
     data_section ();
@@ -3714,9 +3729,10 @@ default_exception_section (void)
 }
 
 void
-output_function_exception_table (void)
+output_function_exception_table (const char *fnname ATTRIBUTE_UNUSED)
 {
   int tt_format, cs_format, lp_format, i, n;
+  char llsda_label[32];
 #ifdef HAVE_AS_LEB128
   char ttype_label[32];
   char cs_after_size_label[32];
@@ -3738,7 +3754,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
-  targetm.asm_out.exception_section ();
+  targetm.asm_out.exception_section (fnname);
 #endif
 
   have_tt_data = (VARRAY_ACTIVE_SIZE (cfun->eh->ttype_data) > 0
@@ -3759,8 +3775,9 @@ output_function_exception_table (void)
       assemble_align (tt_format_size * BITS_PER_UNIT);
     }
 
-  targetm.asm_out.internal_label (asm_out_file, "LLSDA",
-			     current_function_funcdef_no);
+  ASM_GENERATE_INTERNAL_LABEL (llsda_label, "LLSDA",
+			       current_function_funcdef_no);
+  ASM_OUTPUT_LABEL (asm_out_file, llsda_label);
 
   /* The LSDA header.  */
 
@@ -3914,6 +3931,16 @@ output_function_exception_table (void)
 			 (i ? NULL : "Exception specification table"));
 
   function_section (current_function_decl);
+
+#ifdef HAVE_LD_EH_GC_SECTIONS
+  /* Make the function reference its exception table so that the latter
+     cannot be discarded by the linker unless the function itself is
+     discarded.  */
+  if (targetm.have_named_sections && flag_function_sections)
+    dw2_asm_output_addr (PTR_SIZE,
+			 llsda_label,
+			 "Explicit reference to the table");
+#endif
 }
 
 #include "gt-except.h"
Index: passes.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/passes.c,v
retrieving revision 2.10
diff -u -p -r2.10 passes.c
--- passes.c	9 Apr 2004 19:57:42 -0000	2.10
+++ passes.c	26 Apr 2004 20:37:43 -0000
@@ -451,14 +451,14 @@ rest_of_handle_final (tree decl, rtx ins
 #ifdef IA64_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 (decl, fnname);
 
 #ifndef IA64_UNWIND_INFO
     /* Otherwise, it feels unclean to switch sections in the middle.  */
-    output_function_exception_table ();
+    output_function_exception_table (fnname);
 #endif
 
     if (! quiet_flag)
Index: configure.ac
===================================================================
RCS file: /cvs/gcc/gcc/gcc/configure.ac,v
retrieving revision 2.32
diff -u -p -r2.32 configure.ac
--- configure.ac	17 Apr 2004 06:06:52 -0000	2.32
+++ configure.ac	26 Apr 2004 20:37:51 -0000
@@ -2750,10 +2750,6 @@ if test x"$gcc_cv_ld_pie" = xyes; then
 fi
 AC_MSG_RESULT($gcc_cv_ld_pie)
 
-# --------
-# UNSORTED
-# --------
-
 AC_CACHE_CHECK(linker --as-needed support,
 gcc_cv_ld_as_needed,
 [gcc_cv_ld_as_needed=no
@@ -2773,6 +2769,39 @@ if test x"$gcc_cv_ld_as_needed" = xyes; 
 	AC_DEFINE(HAVE_LD_AS_NEEDED, 1,
 [Define if your linker supports --as-needed and --no-as-needed options.])
 fi
+
+AC_MSG_CHECKING(linker EH-compatible garbage collection of sections)
+gcc_cv_ld_eh_gc_sections=unknown
+if test $in_tree_ld = yes ; then
+  if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 16 -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
+  echo '.section .gcc_except_table.foo, "a"' > conftest.s
+  echo '.byte 0' >> conftest.s
+  if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1 \
+     && $gcc_cv_ld -shared -o conftest.so conftest.o > /dev/null 2>&1; then
+    if $gcc_cv_objdump -h conftest.so | grep .gcc_except_table.foo > /dev/null; then
+      gcc_cv_ld_eh_gc_sections=no
+    else
+      gcc_cv_ld_eh_gc_sections=yes
+    fi
+  fi
+changequote(,)dnl
+  rm -f conftest.*
+changequote([,])dnl
+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
+# --------
 
 if test x$with_sysroot = x && test x$host = x$target \
    && test "$prefix" != "/usr" && test "x$prefix" != "x$local_prefix" ; then

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]