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]

Re: gc sections and .eh_frame


> None of the proposed solutions is right.  If you take a look at a
> typical .eh_frame, you'll see relocs pointing at text sections and
> .gcc_except_table (or .rodata for broken ppc compilers).  Changing
> garbage collection to process .rela.eh_frame thus runs into the problem
> of distinguishing the two types of reloc:  You need to ignore the
> former, and mark sections for the latter.

That's exactly what I proposed in my last message, but I suggested passing a 
parameter to _bfd_elf_gc_mark to make it "forget" code sections.  It seems 
autodetecting .eh_frame is more straightforward.

> Try the following totally untested patch.
>
> 	* elflink.c (_bfd_elf_gc_mark): Handle .eh_frame relocs specially..
> 	(bfd_elf_gc_sections): ..rather than totally ignoring .eh_frame.
> 	Don't recheck sections we have already marked.

I think it doesn't work (alone) either, because you unconditionally mark 
all .gcc_except_table* sections, which themselves point to the functions.

In normal mode (i.e. with a non broken ppc compiler), we really need avoid 
marking any sections referenced by .eh_frame, them being code or data.  So I 
think that, before invoking _bfd_elf_gc_mark on .eh_frame, we need to make 
sure that it doesn't reference .gcc_except_table* sections.  Hence the 
attached patch.


	* elflink.c (_bfd_elf_gc_mark): Don't mark code sections referenced
	by .eh_frame.
	(bfd_elf_gc_sections): Mark again the sections referenced by .eh_frame
	if the EH tables are not in .gcc_except_table* sections.


-- 
Eric Botcazou
Index: elflink.c
===================================================================
RCS file: /cvs/src/src/bfd/elflink.c,v
retrieving revision 1.136.2.3
diff -u -p -r1.136.2.3 elflink.c
--- elflink.c	27 Apr 2005 16:47:24 -0000	1.136.2.3
+++ elflink.c	27 Jun 2005 11:47:06 -0000
@@ -8687,6 +8687,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;
@@ -8699,6 +8700,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;
@@ -8771,7 +8773,11 @@ _bfd_elf_gc_mark (struct bfd_link_info *
 	      rsec = (*gc_mark_hook) (sec, info, rel, NULL, &isym[r_symndx]);
 	    }
 
-	  if (rsec && !rsec->gc_mark)
+	  if (rsec
+	      && !rsec->gc_mark
+	      /* elf-eh-frame.c knows how to discard orphaned FDEs so don't
+		 mark code sections referenced by the .eh_frame section.  */  
+	      && !(is_eh && (rsec->flags & SEC_CODE) != 0))
 	    {
 	      if (bfd_get_flavour (rsec->owner) != bfd_target_elf_flavour)
 		rsec->gc_mark = 1;
@@ -9068,6 +9074,8 @@ bfd_elf_gc_sections (bfd *abfd, struct b
   gc_mark_hook = get_elf_backend_data (abfd)->gc_mark_hook;
   for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
     {
+      bfd_boolean has_gcc_except_table = FALSE;
+      asection *eh_frame = NULL;
       asection *o;
 
       if (bfd_get_flavour (sub) != bfd_target_elf_flavour)
@@ -9077,15 +9085,41 @@ bfd_elf_gc_sections (bfd *abfd, struct b
 	{
 	  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.  */  
+	      /* Marking all sections referenced by .eh_frame effectively
+		 disables GC because FDEs contain relocs against both the
+		 functions' code and exception table.  So we mark none,
+		 relying on elf-eh-frame.c to deal with the former type of
+		 relocs (it will discard orphaned FDEs) and on the linker
+		 script to deal with the latter type if necessary.  */
 	      if (strcmp (o->name, ".eh_frame") == 0)
-		o->gc_mark = 1;
+	        {
+		  o->gc_mark = 1;
+		  eh_frame = o;
+		}
 	      else if (!_bfd_elf_gc_mark (info, o, gc_mark_hook))
 		return FALSE;
 	    }
-	}
+
+#define GCC_EXCEPT_TABLE_PREFIX  ".gcc_except_table"
+
+	  /* Detect .gcc_except_table* sections in the input file.  */
+	  if (!has_gcc_except_table
+	      && strncmp (o->name,
+			  GCC_EXCEPT_TABLE_PREFIX,
+			  strlen (GCC_EXCEPT_TABLE_PREFIX)) == 0)
+	    has_gcc_except_table = TRUE;
+	}
+
+      /* If we have not detected .gcc_except_table* sections in the input
+	 file, that can mean the target uses a specific section for the
+	 EH tables.  Play safe and let .eh_frame mark the non-code
+	 sections it really needs, since we will presumably not be able
+	 to do so explicitly via the linker script if necessary.  */
+      if (eh_frame && !has_gcc_except_table)
+        {
+	  if (!_bfd_elf_gc_mark (info, eh_frame, gc_mark_hook))
+	    return FALSE;
+        }
     }
 
   /* ... and mark SEC_EXCLUDE for those that go.  */

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