gc sections and .eh_frame

Alan Modra amodra@bigpond.net.au
Wed Jun 29 13:54:00 GMT 2005


On Wed, Jun 29, 2005 at 10:54:01AM +0930, Alan Modra wrote:
> I think we can do without it by marking sections
> referenced from .eh_frame specially, and keeping them iff the associated
> .text section is marked.

Committing mainline.

bfd/
	* elflink.c (_bfd_elf_gc_mark): Mark sections referenced by
	.eh_frame specially..
	(bfd_elf_gc_sections): ..rather than totally ignoring .eh_frame.
	Don't recheck sections we have already marked.
	(elf_gc_sweep): Keep non-code sections referenced from .eh_frame.
	* section.c (struct bfd_section): Add gc_mark_from_eh.
	(STD_SECTION): Adjust.
	* ecoff.c (bfd_debug_section): Adjust.
	* bfd-in2.h: Regenerate.

ld/
	* scripttempl/elf.sc (.gcc_except_table): Don't KEEP.

Index: bfd/elflink.c
===================================================================
RCS file: /cvs/src/src/bfd/elflink.c,v
retrieving revision 1.168
diff -u -p -r1.168 elflink.c
--- bfd/elflink.c	14 Jun 2005 19:25:45 -0000	1.168
+++ bfd/elflink.c	29 Jun 2005 13:02:15 -0000
@@ -8733,6 +8733,7 @@ _bfd_elf_gc_mark (struct bfd_link_info *
 		  gc_mark_hook_fn gc_mark_hook)
 {
   bfd_boolean ret;
+  bfd_boolean is_eh;
   asection *group_sec;
 
   sec->gc_mark = 1;
@@ -8745,6 +8746,7 @@ _bfd_elf_gc_mark (struct bfd_link_info *
 
   /* Look through the section relocs.  */
   ret = TRUE;
+  is_eh = strcmp (sec->name, ".eh_frame") == 0;
   if ((sec->flags & SEC_RELOC) != 0 && sec->reloc_count > 0)
     {
       Elf_Internal_Rela *relstart, *rel, *relend;
@@ -8821,6 +8823,8 @@ _bfd_elf_gc_mark (struct bfd_link_info *
 	    {
 	      if (bfd_get_flavour (rsec->owner) != bfd_target_elf_flavour)
 		rsec->gc_mark = 1;
+	      else if (is_eh)
+		rsec->gc_mark_from_eh = 1;
 	      else if (!_bfd_elf_gc_mark (info, rsec, gc_mark_hook))
 		{
 		  ret = FALSE;
@@ -8891,6 +8895,41 @@ elf_gc_sweep (struct bfd_link_info *info
 	  if (o->gc_mark)
 	    continue;
 
+	  /* Keep .gcc_except_table.* if the associated .text.* is
+	     marked.  This isn't very nice, but the proper solution,
+	     splitting .eh_frame up and using comdat doesn't pan out 
+	     easily due to needing special relocs to handle the
+	     difference of two symbols in separate sections.
+	     Don't keep code sections referenced by .eh_frame.  */
+	  if (o->gc_mark_from_eh && (o->flags & SEC_CODE) == 0)
+	    {
+	      if (strncmp (o->name, ".gcc_except_table.", 18) == 0)
+		{
+		  unsigned long len;
+		  char *fn_name;
+		  asection *fn_text;
+
+		  len = strlen (o->name + 18) + 1;
+		  fn_name = bfd_malloc (len + 6);
+		  if (fn_name == NULL)
+		    return FALSE;
+		  memcpy (fn_name, ".text.", 6);
+		  memcpy (fn_name + 6, o->name + 18, len);
+		  fn_text = bfd_get_section_by_name (sub, fn_name);
+		  free (fn_name);
+		  if (fn_text != NULL && fn_text->gc_mark)
+		    o->gc_mark = 1;
+		}
+
+	      /* If not using specially named exception table section,
+		 then keep whatever we are using.  */
+	      else
+		o->gc_mark = 1;
+
+	      if (o->gc_mark)
+		continue;
+	    }
+
 	  /* Skip sweeping sections already excluded.  */
 	  if (o->flags & SEC_EXCLUDE)
 	    continue;
@@ -9123,18 +9164,9 @@ bfd_elf_gc_sections (bfd *abfd, struct b
 	continue;
 
       for (o = sub->sections; o != NULL; o = o->next)
-	{
-	  if (o->flags & SEC_KEEP)
-	    {
-	      /* _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 (!_bfd_elf_gc_mark (info, o, gc_mark_hook))
-		return FALSE;
-	    }
-	}
+	if ((o->flags & SEC_KEEP) != 0 && !o->gc_mark)
+	  if (!_bfd_elf_gc_mark (info, o, gc_mark_hook))
+	    return FALSE;
     }
 
   /* ... and mark SEC_EXCLUDE for those that go.  */
Index: bfd/section.c
===================================================================
RCS file: /cvs/src/src/bfd/section.c,v
retrieving revision 1.88
diff -u -p -r1.88 section.c
--- bfd/section.c	17 May 2005 19:44:55 -0000	1.88
+++ bfd/section.c	29 Jun 2005 13:02:16 -0000
@@ -354,8 +354,9 @@ CODE_FRAGMENT
 .     output sections that have an input section.  *}
 .  unsigned int linker_has_input : 1;
 .
-.  {* A mark flag used by some linker backends for garbage collection.  *}
+.  {* Mark flags used by some linker backends for garbage collection.  *}
 .  unsigned int gc_mark : 1;
+.  unsigned int gc_mark_from_eh : 1;
 .
 .  {* The following flags are used by the ELF linker. *}
 .
@@ -661,18 +662,18 @@ static const asymbol global_syms[] =
 
 #define STD_SECTION(SEC, FLAGS, SYM, NAME, IDX)				\
   const asymbol * const SYM = (asymbol *) &global_syms[IDX]; 		\
-  asection SEC = 							\
+  asection SEC =							\
     /* name, id,  index, next, prev, flags, user_set_vma,            */	\
     { NAME,  IDX, 0,     NULL, NULL, FLAGS, 0,				\
 									\
-    /* linker_mark, linker_has_input, gc_mark, segment_mark,         */	\
+    /* linker_mark, linker_has_input, gc_mark, gc_mark_from_eh,      */	\
        0,           0,                1,       0,			\
 									\
-    /* sec_info_type, use_rela_p, has_tls_reloc, has_gp_reloc,       */ \
-       0,	      0,	  0,		 0,			\
+    /* segment_mark, sec_info_type, use_rela_p, has_tls_reloc,       */	\
+       0,            0,             0,          0,			\
 									\
-    /* need_finalize_relax, reloc_done,                              */ \
-       0,		    0,						\
+    /* has_gp_reloc, need_finalize_relax, reloc_done,                */	\
+       0,            0,                   0,				\
 									\
     /* vma, lma, size, rawsize                                       */	\
        0,   0,   0,    0,						\
@@ -686,8 +687,8 @@ static const asymbol global_syms[] =
     /* line_filepos, userdata, contents, lineno, lineno_count,       */	\
        0,            NULL,     NULL,     NULL,   0,			\
 									\
-    /* entsize, kept_section, moving_line_filepos,	           */	\
-       0,       NULL,	      0,					\
+    /* entsize, kept_section, moving_line_filepos,                   */	\
+       0,       NULL,         0,					\
 									\
     /* target_index, used_by_bfd, constructor_chain, owner,          */	\
        0,            NULL,        NULL,              NULL,		\
Index: bfd/ecoff.c
===================================================================
RCS file: /cvs/src/src/bfd/ecoff.c,v
retrieving revision 1.45
diff -u -p -r1.45 ecoff.c
--- bfd/ecoff.c	4 May 2005 15:53:07 -0000	1.45
+++ bfd/ecoff.c	29 Jun 2005 13:02:04 -0000
@@ -54,12 +54,12 @@ static asection bfd_debug_section =
 {
   /* name,      id,  index, next, prev, flags, user_set_vma,       */
      "*DEBUG*", 0,   0,     NULL, NULL, 0,     0,
-  /* linker_mark, linker_has_input, gc_mark, segment_mark,         */
-     0,           0,                0,       0,
-  /* sec_info_type, use_rela_p, has_tls_reloc, has_gp_reloc,       */
-     0,		    0,		0,	       0,
-  /* need_finalize_relax, reloc_done,                              */
-     0,			  0,
+  /* linker_mark, linker_has_input, gc_mark, gc_mark_from_eh,      */
+     0,           0,                1,       0,
+  /* segment_mark, sec_info_type, use_rela_p, has_tls_reloc,       */
+     0,            0,             0,          0,
+  /* has_gp_reloc, need_finalize_relax, reloc_done,                */
+     0,            0,                   0,
   /* vma, lma, size, rawsize,                                      */
      0,   0,   0,    0,
   /* output_offset, output_section, alignment_power,               */
@@ -68,7 +68,7 @@ static asection bfd_debug_section =
      NULL,       NULL,        0,           0,       0,
   /* line_filepos, userdata, contents, lineno, lineno_count,       */
      0,            NULL,     NULL,     NULL,   0,
-  /* entsize, kept_section, moving_line_filepos,	           */
+  /* entsize, kept_section, moving_line_filepos,                   */
      0,       NULL,         0,
   /* target_index, used_by_bfd, constructor_chain, owner,          */
      0,            NULL,        NULL,              NULL,
Index: ld/scripttempl/elf.sc
===================================================================
RCS file: /cvs/src/src/ld/scripttempl/elf.sc,v
retrieving revision 1.59
diff -u -p -r1.59 elf.sc
--- ld/scripttempl/elf.sc	10 Jun 2005 00:39:56 -0000	1.59
+++ ld/scripttempl/elf.sc	29 Jun 2005 13:02:21 -0000
@@ -329,7 +329,7 @@ cat <<EOF
   ${OTHER_READONLY_SECTIONS}
   .eh_frame_hdr : { *(.eh_frame_hdr) }
   .eh_frame     ${RELOCATING-0} : ONLY_IF_RO { KEEP (*(.eh_frame)) }
-  .gcc_except_table ${RELOCATING-0} : ONLY_IF_RO { KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) }
+  .gcc_except_table ${RELOCATING-0} : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
 
   /* Adjust the address for the data segment.  We want to adjust up to
      the same address within the page on the next page up.  */
@@ -339,7 +339,7 @@ cat <<EOF
 
   /* Exception handling  */
   .eh_frame     ${RELOCATING-0} : ONLY_IF_RW { KEEP (*(.eh_frame)) }
-  .gcc_except_table ${RELOCATING-0} : ONLY_IF_RW { KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) }
+  .gcc_except_table ${RELOCATING-0} : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
 
   /* Thread Local Storage sections  */
   .tdata	${RELOCATING-0} : { *(.tdata${RELOCATING+ .tdata.* .gnu.linkonce.td.*}) }

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre



More information about the Binutils mailing list