This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils 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] More aggressive --gc-sections


Hi,

This is the minimal set of patches needed in order to make --gc-sections 
works for dynamically linked Ada programs using DWARF-2 EH on x86/Linux.

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

The GCC part was bootstrapped/regtested on mainline, the binutils part was 
tested on mainline, with no new regressions.  I ran the ACATS and libstdc++ 
testsuites with -function-sections -fdata-sections -Wl,--gc-sections too.

I don't expect these patches to be accepted, rather to serve as a starting 
point for the discussion.  What do you think about the approach?  What 
criteria should the patches meet to be accepted both in GCC and binutils?

Thanks in advance.


GCC:

	* except.h (output_function_exception_table): New prototype.
	* output.h (default_exception_section): New prototype.
	* target.h (struct gcc_target) <exception_section>: New prototype.
	* except.c (PTR_SIZE): New macro.
	(default_exception_section): New prototype.
	If named sections are supported and flag_function_sections is set,
	use a function-specific section.
	(output_function_exception_table): New prototype.
	Adjust call to targetm.asm_out.exception_section.  Keep track of the LDSA
	label.  If 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.
	* Makefile.in (LIBGCC2_CFLAGS): Add -ffunction-sections -fdata-sections.
	* ada/Makefile.in (GNATLIBCFLAGS): Likewise.
	* ada/Make-lang.in (GNATLIBCFLAGS): Likewise.

BFD:

	* elflink.h (elf_gc_mark_dynamic_ref_symbol): New function.
	(elf_gc_sections): Do not gracefully fail if dynamic sections have
	been created.  Instead call elf_gc_mark_dynamic_ref_symbol to
	mark dynamically referenced symbols.  Do not mark the whole graph
	rooted at .eh_frame, only the section proper.

LD:

	* scripttempl/elf.sc (.text): Add KEEP for .text.*personality*.
	(.data): Add KEEP for .gnu.linkonce.d.*personality*.
	(.gcc_except_table): Add KEEP for self and accept .gcc_except_table.*.


-- 
Eric Botcazou
Index: except.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/except.c,v
retrieving revision 1.261
diff -u -p -r1.261 except.c
--- except.c	7 Mar 2004 22:29:28 -0000	1.261
+++ except.c	9 Mar 2004 12:58:43 -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;
@@ -3667,7 +3672,7 @@ sjlj_output_call_site_table (void)
    table.  */
 
 void
-default_exception_section (void)
+default_exception_section (const char *fnname)
 {
   if (targetm.have_named_sections)
     {
@@ -3682,7 +3687,15 @@ default_exception_section (void)
 #else
       flags = SECTION_WRITE;
 #endif
-      named_section_flags (".gcc_except_table", flags);
+      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
+	named_section_flags (".gcc_except_table", flags);
     }
   else if (flag_pic)
     data_section ();
@@ -3691,9 +3704,10 @@ default_exception_section (void)
 }
 
 void
-output_function_exception_table (void)
+output_function_exception_table (const char *fnname)
 {
   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];
@@ -3715,7 +3729,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
@@ -3736,8 +3750,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.  */
 
@@ -3891,6 +3906,14 @@ output_function_exception_table (void)
 			 (i ? NULL : "Exception specification table"));
 
   function_section (current_function_decl);
+
+  /* Make the function reference its exception table so that the latter
+     cannot be discarded by the linker unless the function itself is
+     discarded.  */
+  if (flag_function_sections)
+    dw2_asm_output_addr (PTR_SIZE,
+			 llsda_label,
+			 "Explicit reference to the table");
 }
 
 #include "gt-except.h"
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	9 Mar 2004 12:58:43 -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.137
diff -u -p -r1.137 output.h
--- output.h	27 Feb 2004 08:54:30 -0000	1.137
+++ output.h	9 Mar 2004 12:58:47 -0000
@@ -453,7 +453,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: passes.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/passes.c,v
retrieving revision 2.3
diff -u -p -r2.3 passes.c
--- passes.c	3 Mar 2004 16:32:38 -0000	2.3
+++ passes.c	9 Mar 2004 12:58:53 -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: target.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/target.h,v
retrieving revision 1.82
diff -u -p -r1.82 target.h
--- target.h	3 Mar 2004 23:55:51 -0000	1.82
+++ target.h	9 Mar 2004 12:58:57 -0000
@@ -98,7 +98,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: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.1261
diff -u -p -r1.1261 Makefile.in
--- Makefile.in	9 Mar 2004 01:53:24 -0000	1.1261
+++ Makefile.in	9 Mar 2004 12:59:17 -0000
@@ -494,7 +494,7 @@ INSTALL_LIBGCC = install-libgcc
 # Options to use when compiling libgcc2.a.
 #
 LIBGCC2_DEBUG_CFLAGS = -g
-LIBGCC2_CFLAGS = -O2 $(LIBGCC2_INCLUDES) $(GCC_CFLAGS) $(TARGET_LIBGCC2_CFLAGS) $(LIBGCC2_DEBUG_CFLAGS) $(GTHREAD_FLAGS) -DIN_LIBGCC2 -D__GCC_FLOAT_NOT_NEEDED @inhibit_libc@
+LIBGCC2_CFLAGS = -O2 -ffunction-sections -fdata-sections $(LIBGCC2_INCLUDES) $(GCC_CFLAGS) $(TARGET_LIBGCC2_CFLAGS) $(LIBGCC2_DEBUG_CFLAGS) $(GTHREAD_FLAGS) -DIN_LIBGCC2 -D__GCC_FLOAT_NOT_NEEDED @inhibit_libc@
 
 # Additional options to use when compiling libgcc2.a.
 # Some targets override this to -isystem include
Index: ada/Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ada/Makefile.in,v
retrieving revision 1.73
diff -u -p -r1.73 Makefile.in
--- ada/Makefile.in	25 Feb 2004 15:59:03 -0000	1.73
+++ ada/Makefile.in	9 Mar 2004 12:59:21 -0000
@@ -123,7 +123,7 @@ ADAFLAGS = -W -Wall -gnatpg -gnata
 SOME_ADAFLAGS =-gnata
 FORCE_DEBUG_ADAFLAGS = -g
 GNATLIBFLAGS = -gnatpg
-GNATLIBCFLAGS = -g -O2
+GNATLIBCFLAGS = -g -O2 -ffunction-sections -fdata-sections
 GNATLIBCFLAGS_FOR_C = $(GNATLIBCFLAGS) $(TARGET_LIBGCC2_CFLAGS) -fexceptions \
 	-DIN_RTS
 ALL_ADA_CFLAGS = $(X_ADA_CFLAGS) $(T_ADA_CFLAGS) $(ADA_CFLAGS)
Index: ada/Make-lang.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ada/Make-lang.in,v
retrieving revision 1.77
diff -u -p -r1.77 Make-lang.in
--- ada/Make-lang.in	5 Mar 2004 10:58:57 -0000	1.77
+++ ada/Make-lang.in	9 Mar 2004 12:59:28 -0000
@@ -57,7 +57,7 @@ ADA_CFLAGS =
 ALL_ADA_CFLAGS = $(X_ADA_CFLAGS) $(T_ADA_CFLAGS) $(ADA_CFLAGS)
 ADA_INCLUDES = -I- -I. -Iada -I$(srcdir)/ada
 GNATLIBFLAGS= -W -Wall -gnatpg
-GNATLIBCFLAGS= -g -O2
+GNATLIBCFLAGS= -g -O2 -ffunction-sections -fdata-sections
 ADA_INCLUDE_DIR = $(libsubdir)/adainclude
 ADA_RTL_OBJ_DIR = $(libsubdir)/adalib
 THREAD_KIND=native
Index: bfd/elflink.h
===================================================================
RCS file: /cvs/src/src/bfd/elflink.h,v
retrieving revision 1.254
diff -u -p -r1.254 elflink.h
--- bfd/elflink.h	29 Feb 2004 06:11:52 -0000	1.254
+++ bfd/elflink.h	17 Mar 2004 09:18:01 -0000
@@ -5535,6 +5538,24 @@ elf_gc_smash_unused_vtentry_relocs (stru
   return TRUE;
 }
 
+/* Mark sections containing dynamically referenced symbols.  This is called
+   through elf_link_hash_traverse.  */
+
+static bfd_boolean
+elf_gc_mark_dynamic_ref_symbol (struct elf_link_hash_entry *h,
+				void *okp ATTRIBUTE_UNUSED)
+{
+  if (h->root.type == bfd_link_hash_warning)
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+  if ((h->root.type == bfd_link_hash_defined
+       || h->root.type == bfd_link_hash_defweak)
+      && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC))
+    h->root.u.def.section->flags |= SEC_KEEP;
+
+  return TRUE;
+}
+
 /* Do mark and sweep of unused sections.  */
 
 bfd_boolean
@@ -5549,8 +5570,7 @@ elf_gc_sections (bfd *abfd, struct bfd_l
   if (!get_elf_backend_data (abfd)->can_gc_sections
       || info->relocatable
       || info->emitrelocations
-      || !is_elf_hash_table (info->hash)
-      || elf_hash_table (info)->dynamic_sections_created)
+      || !is_elf_hash_table (info->hash))
     {
       (*_bfd_error_handler)(_("Warning: gc-sections option ignored"));
       return TRUE;
@@ -5570,8 +5590,15 @@ elf_gc_sections (bfd *abfd, struct bfd_l
   if (!ok)
     return FALSE;
 
-  /* Grovel through relocs to find out who stays ...  */
+  /* Mark dynamically referenced symbols.  */
+  if (elf_hash_table (info)->dynamic_sections_created)
+    elf_link_hash_traverse (elf_hash_table (info),
+			    elf_gc_mark_dynamic_ref_symbol,
+			    &ok);
+  if (!ok)
+    return FALSE;
 
+  /* Grovel through relocs to find out who stays ...  */
   gc_mark_hook = get_elf_backend_data (abfd)->gc_mark_hook;
   for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
     {
@@ -5583,8 +5610,15 @@ elf_gc_sections (bfd *abfd, struct bfd_l
       for (o = sub->sections; o != NULL; o = o->next)
 	{
 	  if (o->flags & SEC_KEEP)
-	    if (!elf_gc_mark (info, o, gc_mark_hook))
-	      return FALSE;
+	    {
+	      /* _bfd_elf_discard_section_eh_frame knows how to discard
+		 orphaned FDEs so don't mark sections referenced by the
+		 EH frame section.  */  
+	      if (strcmp (o->name, ".eh_frame") == 0)
+		o->gc_mark = 1;
+	      else if (!elf_gc_mark (info, o, gc_mark_hook))
+		return FALSE;
+	    }
 	}
     }
 
Index: ld/scripttempl/elf.sc
===================================================================
RCS file: /cvs/src/src/ld/scripttempl/elf.sc,v
retrieving revision 1.41
diff -u -p -r1.41 elf.sc
--- ld/scripttempl/elf.sc	10 Oct 2003 01:36:36 -0000	1.41
+++ ld/scripttempl/elf.sc	17 Mar 2004 09:18:02 -0000
@@ -264,6 +264,7 @@ cat <<EOF
   {
     ${RELOCATING+${TEXT_START_SYMBOLS}}
     *(.text .stub${RELOCATING+ .text.* .gnu.linkonce.t.*})
+    KEEP (*(.text.*personality*))
     /* .gnu.warning sections are handled specially by elf32.em.  */
     *(.gnu.warning)
     ${RELOCATING+${OTHER_TEXT_SECTIONS}}
@@ -311,13 +312,14 @@ cat <<EOF
   {
     ${RELOCATING+${DATA_START_SYMBOLS}}
     *(.data${RELOCATING+ .data.* .gnu.linkonce.d.*})
+    KEEP (*(.gnu.linkonce.d.*personality*))
     ${CONSTRUCTING+SORT(CONSTRUCTORS)}
   }
   .data1        ${RELOCATING-0} : { *(.data1) }
   .tdata	${RELOCATING-0} : { *(.tdata${RELOCATING+ .tdata.* .gnu.linkonce.td.*}) }
   .tbss		${RELOCATING-0} : { *(.tbss${RELOCATING+ .tbss.* .gnu.linkonce.tb.*})${RELOCATING+ *(.tcommon)} }
   .eh_frame     ${RELOCATING-0} : { KEEP (*(.eh_frame)) }
-  .gcc_except_table ${RELOCATING-0} : { *(.gcc_except_table) }
+  .gcc_except_table ${RELOCATING-0} : { KEEP(*(.gcc_except_table)) *(.gcc_except_table.*) }
   ${WRITABLE_RODATA+${RODATA}}
   ${OTHER_READWRITE_SECTIONS}
   ${TEXT_DYNAMIC-${DYNAMIC}}

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