This is the mail archive of the binutils@sourceware.org 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: PATCH: PR ld/13909: PR ld/12570 causes eh_frame_hdr section to be sometimes too large


On Thu, May 24, 2012 at 12:01:26AM +0930, Alan Modra wrote:
> PowerPC has a problem with ordering too, in that .eh_frame_hdr is
> stripped when only PLT/glink has eh_frame info.  I want to allow
> sizing of the PLT/glink .eh_frame in elf_backend_size_dynamic_sections,
> rather than sizing and filling in some data early like x86 does.

HJ, how does this look to you?  Moving _bfd_elf_maybe_strip_eh_frame_hdr
later in bfd_elf_size_dynamic_sections allows us to treat the linker
created PLT .eh_frame section like most other linker created sections.
We don't need to set it up as early, nor do we rely on elf-eh-frame.c
stripping the section by cunningly leaving an FDE range as zero.

bfd/
	* elf-eh-frame.c (_bfd_elf_eh_frame_present): New function.
	(_bfd_elf_maybe_strip_eh_frame_hdr): Use it here.
	* elf-bfd.h (_bfd_elf_eh_frame_present): Declare.
	* elflink.c (bfd_elf_size_dynamic_sections): Let the backend
	size dynamic sections before stripping eh_frame_hdr.
	(bfd_elf_gc_sections): Handle multiple .eh_frame sections.
	* elf32-ppc.c (ppc_elf_size_dynamic_sections): Drop glink_eh_frame
	if no other .eh_frame sections exist.
	* elf64-ppc.c (ppc64_elf_size_stubs): Likewise.
	* elf32-i386.c (elf_i386_create_dynamic_sections): Don't size
	or alloc plt_eh_frame here..
	(elf_i386_size_dynamic_sections): ..do it here instead.  Don't
	specially keep sgotplt, iplt, tgotplt, sdynbss for symbols.
	(elf_i386_finish_dynamic_sections): Check plt_eh_frame->contents
	before writing plt offset.
	* elf64-x86-64.c (elf_x86_64_create_dynamic_sections): Don't size
	or alloc plt_eh_frame here..
	(elf_x86_64_size_dynamic_sections): ..do it here instead.
	(elf_x86_64_finish_dynamic_sections): Check plt_eh_frame->contents
	before writing plt offset.
ld/
	* emultempl/elf32.em (gld${EMULATION_NAME}_after_open): Handle
	multiple .eh_frame sections attached to bfd.

Index: bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.338
diff -u -p -r1.338 elf-bfd.h
--- bfd/elf-bfd.h	14 May 2012 19:45:17 -0000	1.338
+++ bfd/elf-bfd.h	24 May 2012 04:49:46 -0000
@@ -1950,6 +1950,8 @@ extern bfd_boolean _bfd_elf_write_sectio
   (bfd *, struct bfd_link_info *, asection *, bfd_byte *);
 extern bfd_boolean _bfd_elf_write_section_eh_frame_hdr
   (bfd *, struct bfd_link_info *);
+extern bfd_boolean _bfd_elf_eh_frame_present
+  (struct bfd_link_info *);
 extern bfd_boolean _bfd_elf_maybe_strip_eh_frame_hdr
   (struct bfd_link_info *);
 
Index: bfd/elf-eh-frame.c
===================================================================
RCS file: /cvs/src/src/bfd/elf-eh-frame.c,v
retrieving revision 1.89
diff -u -p -r1.89 elf-eh-frame.c
--- bfd/elf-eh-frame.c	23 May 2012 04:38:08 -0000	1.89
+++ bfd/elf-eh-frame.c	24 May 2012 07:44:31 -0000
@@ -1247,6 +1247,26 @@ _bfd_elf_discard_section_eh_frame_hdr (b
   return TRUE;
 }
 
+/* Return true if there is at least one non-empty .eh_frame section in
+   input files.  Can only be called after ld has mapped input to
+   output sections, and before sections are stripped.  */
+bfd_boolean
+_bfd_elf_eh_frame_present (struct bfd_link_info *info)
+{
+  asection *eh = bfd_get_section_by_name (info->output_bfd, ".eh_frame");
+
+  if (eh == NULL)
+    return FALSE;
+
+  /* Count only sections which have at least a single CIE or FDE.
+     There cannot be any CIE or FDE <= 8 bytes.  */
+  for (eh = eh->map_head.s; eh != NULL; eh = eh->map_head.s)
+    if (eh->size > 8)
+      return TRUE;
+
+  return FALSE;
+}
+
 /* This function is called from size_dynamic_sections.
    It needs to decide whether .eh_frame_hdr should be output or not,
    because when the dynamic symbol table has been sized it is too late
@@ -1255,8 +1275,6 @@ _bfd_elf_discard_section_eh_frame_hdr (b
 bfd_boolean
 _bfd_elf_maybe_strip_eh_frame_hdr (struct bfd_link_info *info)
 {
-  asection *o;
-  bfd *abfd;
   struct elf_link_hash_table *htab;
   struct eh_frame_hdr_info *hdr_info;
 
@@ -1265,28 +1283,9 @@ _bfd_elf_maybe_strip_eh_frame_hdr (struc
   if (hdr_info->hdr_sec == NULL)
     return TRUE;
 
-  if (bfd_is_abs_section (hdr_info->hdr_sec->output_section))
-    {
-      hdr_info->hdr_sec = NULL;
-      return TRUE;
-    }
-
-  abfd = NULL;
-  if (info->eh_frame_hdr)
-    for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link_next)
-      {
-	/* Count only sections which have at least a single CIE or FDE.
-	   There cannot be any CIE or FDE <= 8 bytes.  */
-	o = bfd_get_section_by_name (abfd, ".eh_frame");
-	while (o != NULL
-	       && (o->size <= 8
-		   || bfd_is_abs_section (o->output_section)))
-	  o = bfd_get_next_section_by_name (o);
-	if (o != NULL)
-	  break;
-      }
-
-  if (abfd == NULL)
+  if (bfd_is_abs_section (hdr_info->hdr_sec->output_section)
+      || !info->eh_frame_hdr
+      || !_bfd_elf_eh_frame_present (info))
     {
       hdr_info->hdr_sec->flags |= SEC_EXCLUDE;
       hdr_info->hdr_sec = NULL;
Index: bfd/elf32-i386.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-i386.c,v
retrieving revision 1.276
diff -u -p -r1.276 elf32-i386.c
--- bfd/elf32-i386.c	22 May 2012 15:54:58 -0000	1.276
+++ bfd/elf32-i386.c	24 May 2012 04:49:51 -0000
@@ -1027,12 +1027,6 @@ elf_i386_create_dynamic_sections (bfd *d
       if (htab->plt_eh_frame == NULL
 	  || !bfd_set_section_alignment (dynobj, htab->plt_eh_frame, 2))
 	return FALSE;
-
-      htab->plt_eh_frame->size = sizeof (elf_i386_eh_frame_plt);
-      htab->plt_eh_frame->contents
-	= bfd_alloc (dynobj, htab->plt_eh_frame->size);
-      memcpy (htab->plt_eh_frame->contents, elf_i386_eh_frame_plt,
-	      sizeof (elf_i386_eh_frame_plt));
     }
 
   return TRUE;
@@ -2726,7 +2720,7 @@ elf_i386_size_dynamic_sections (bfd *out
 				  FALSE, FALSE, FALSE);
 
       /* Don't allocate .got.plt section if there are no GOT nor PLT
-         entries and there is no refeence to _GLOBAL_OFFSET_TABLE_.  */
+         entries and there is no reference to _GLOBAL_OFFSET_TABLE_.  */
       if ((got == NULL
 	   || !got->ref_regular_nonweak)
 	  && (htab->elf.sgotplt->size
@@ -2742,6 +2736,14 @@ elf_i386_size_dynamic_sections (bfd *out
 	htab->elf.sgotplt->size = 0;
     }
 
+
+  if (htab->plt_eh_frame != NULL
+      && htab->elf.splt != NULL
+      && htab->elf.splt->size != 0
+      && !bfd_is_abs_section (htab->elf.splt->output_section)
+      && _bfd_elf_eh_frame_present (info))
+    htab->plt_eh_frame->size = sizeof (elf_i386_eh_frame_plt);
+
   /* We now have determined the sizes of the various dynamic sections.
      Allocate memory for them.  */
   relocs = FALSE;
@@ -2753,11 +2755,7 @@ elf_i386_size_dynamic_sections (bfd *out
 	continue;
 
       if (s == htab->elf.splt
-	  || s == htab->elf.sgot
-	  || s == htab->elf.sgotplt
-	  || s == htab->elf.iplt
-	  || s == htab->elf.igotplt
-	  || s == htab->sdynbss)
+	  || s == htab->elf.sgot)
 	{
 	  /* Strip this section if we don't need it; see the
 	     comment below.  */
@@ -2768,6 +2766,14 @@ elf_i386_size_dynamic_sections (bfd *out
 	  if (htab->elf.hplt != NULL)
 	    strip_section = FALSE;
 	}
+      else if (s == htab->elf.sgotplt
+	       || s == htab->elf.iplt
+	       || s == htab->elf.igotplt
+	       || s == htab->plt_eh_frame
+	       || s == htab->sdynbss)
+	{
+	  /* Strip these too.  */
+	}
       else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rel"))
 	{
 	  if (s->size != 0
@@ -2815,11 +2821,13 @@ elf_i386_size_dynamic_sections (bfd *out
     }
 
   if (htab->plt_eh_frame != NULL
-      && htab->elf.splt != NULL
-      && htab->elf.splt->size != 0
-      && (htab->elf.splt->flags & SEC_EXCLUDE) == 0)
-    bfd_put_32 (dynobj, htab->elf.splt->size,
-		htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET);
+      && htab->plt_eh_frame->contents != NULL)
+    {
+      memcpy (htab->plt_eh_frame->contents, elf_i386_eh_frame_plt,
+	      sizeof (elf_i386_eh_frame_plt));
+      bfd_put_32 (dynobj, htab->elf.splt->size,
+		  htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET);
+    }
 
   if (htab->elf.dynamic_sections_created)
     {
@@ -4840,7 +4848,8 @@ elf_i386_finish_dynamic_sections (bfd *o
     }
 
   /* Adjust .eh_frame for .plt section.  */
-  if (htab->plt_eh_frame != NULL)
+  if (htab->plt_eh_frame != NULL
+      && htab->plt_eh_frame->contents != NULL)
     {
       if (htab->elf.splt != NULL
 	  && htab->elf.splt->size != 0
Index: bfd/elf32-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.c,v
retrieving revision 1.316
diff -u -p -r1.316 elf32-ppc.c
--- bfd/elf32-ppc.c	22 May 2012 14:58:15 -0000	1.316
+++ bfd/elf32-ppc.c	24 May 2012 04:49:52 -0000
@@ -6244,7 +6244,8 @@ ppc_elf_size_dynamic_sections (bfd *outp
   if (htab->glink != NULL
       && htab->glink->size != 0
       && htab->glink_eh_frame != NULL
-      && !bfd_is_abs_section (htab->glink_eh_frame->output_section))
+      && !bfd_is_abs_section (htab->glink_eh_frame->output_section)
+      && _bfd_elf_eh_frame_present (info))
     {
       s = htab->glink_eh_frame;
       s->size = sizeof (glink_eh_frame_cie) + 20;
Index: bfd/elf64-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-ppc.c,v
retrieving revision 1.384
diff -u -p -r1.384 elf64-ppc.c
--- bfd/elf64-ppc.c	24 May 2012 06:20:52 -0000	1.384
+++ bfd/elf64-ppc.c	24 May 2012 07:10:52 -0000
@@ -11662,7 +11662,7 @@ ppc64_elf_size_stubs (struct bfd_link_in
 
       if (htab->glink_eh_frame != NULL
 	  && !bfd_is_abs_section (htab->glink_eh_frame->output_section)
-	  && (htab->glink_eh_frame->flags & SEC_EXCLUDE) == 0)
+	  && htab->glink_eh_frame->output_section->size != 0)
 	{
 	  size_t size = 0, align;
 
Index: bfd/elf64-x86-64.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-x86-64.c,v
retrieving revision 1.266
diff -u -p -r1.266 elf64-x86-64.c
--- bfd/elf64-x86-64.c	22 May 2012 15:54:58 -0000	1.266
+++ bfd/elf64-x86-64.c	24 May 2012 04:49:56 -0000
@@ -982,8 +982,6 @@ elf_x86_64_create_dynamic_sections (bfd 
       && htab->plt_eh_frame == NULL
       && htab->elf.splt != NULL)
     {
-      const struct elf_x86_64_backend_data *const abed
-	= get_elf_x86_64_backend_data (dynobj);
       flagword flags = get_elf_backend_data (dynobj)->dynamic_sec_flags;
       htab->plt_eh_frame
 	= bfd_make_section_anyway_with_flags (dynobj, ".eh_frame",
@@ -993,12 +991,6 @@ elf_x86_64_create_dynamic_sections (bfd 
       if (htab->plt_eh_frame == NULL
 	  || !bfd_set_section_alignment (dynobj, htab->plt_eh_frame, 3))
 	return FALSE;
-
-      htab->plt_eh_frame->size = abed->eh_frame_plt_size;
-      htab->plt_eh_frame->contents
-	= bfd_alloc (dynobj, htab->plt_eh_frame->size);
-      memcpy (htab->plt_eh_frame->contents,
-	      abed->eh_frame_plt, abed->eh_frame_plt_size);
     }
   return TRUE;
 }
@@ -2797,6 +2789,17 @@ elf_x86_64_size_dynamic_sections (bfd *o
 	htab->elf.sgotplt->size = 0;
     }
 
+  if (htab->plt_eh_frame != NULL
+      && htab->elf.splt != NULL
+      && htab->elf.splt->size != 0
+      && !bfd_is_abs_section (htab->elf.splt->output_section)
+      && _bfd_elf_eh_frame_present (info))
+    {
+      const struct elf_x86_64_backend_data *arch_data
+	= (const struct elf_x86_64_backend_data *) bed->arch_data;
+      htab->plt_eh_frame->size = arch_data->eh_frame_plt_size;
+    }
+
   /* We now have determined the sizes of the various dynamic sections.
      Allocate memory for them.  */
   relocs = FALSE;
@@ -2810,6 +2813,7 @@ elf_x86_64_size_dynamic_sections (bfd *o
 	  || s == htab->elf.sgotplt
 	  || s == htab->elf.iplt
 	  || s == htab->elf.igotplt
+	  || s == htab->plt_eh_frame
 	  || s == htab->sdynbss)
 	{
 	  /* Strip this section if we don't need it; see the
@@ -2861,11 +2865,16 @@ elf_x86_64_size_dynamic_sections (bfd *o
     }
 
   if (htab->plt_eh_frame != NULL
-      && htab->elf.splt != NULL
-      && htab->elf.splt->size != 0
-      && (htab->elf.splt->flags & SEC_EXCLUDE) == 0)
-    bfd_put_32 (dynobj, htab->elf.splt->size,
-		htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET);
+      && htab->plt_eh_frame->contents != NULL)
+    {
+      const struct elf_x86_64_backend_data *arch_data
+	= (const struct elf_x86_64_backend_data *) bed->arch_data;
+
+      memcpy (htab->plt_eh_frame->contents,
+	      arch_data->eh_frame_plt, htab->plt_eh_frame->size);
+      bfd_put_32 (dynobj, htab->elf.splt->size,
+		  htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET);
+    }
 
   if (htab->elf.dynamic_sections_created)
     {
@@ -4725,7 +4734,8 @@ elf_x86_64_finish_dynamic_sections (bfd 
     }
 
   /* Adjust .eh_frame for .plt section.  */
-  if (htab->plt_eh_frame != NULL)
+  if (htab->plt_eh_frame != NULL
+      && htab->plt_eh_frame->contents != NULL)
     {
       if (htab->elf.splt != NULL
 	  && htab->elf.splt->size != 0
Index: bfd/elflink.c
===================================================================
RCS file: /cvs/src/src/bfd/elflink.c,v
retrieving revision 1.444
diff -u -p -r1.444 elflink.c
--- bfd/elflink.c	23 May 2012 04:35:31 -0000	1.444
+++ bfd/elflink.c	24 May 2012 04:49:58 -0000
@@ -5584,17 +5584,9 @@ bfd_elf_size_dynamic_sections (bfd *outp
       && ! (*bed->elf_backend_always_size_sections) (output_bfd, info))
     return FALSE;
 
-  if (! _bfd_elf_maybe_strip_eh_frame_hdr (info))
-    return FALSE;
-
   dynobj = elf_hash_table (info)->dynobj;
 
-  /* If there were no dynamic objects in the link, there is nothing to
-     do here.  */
-  if (dynobj == NULL)
-    return TRUE;
-
-  if (elf_hash_table (info)->dynamic_sections_created)
+  if (dynobj != NULL && elf_hash_table (info)->dynamic_sections_created)
     {
       struct elf_info_failed eif;
       struct elf_link_hash_entry *h;
@@ -5897,11 +5889,15 @@ bfd_elf_size_dynamic_sections (bfd *outp
 
   /* The backend must work out the sizes of all the other dynamic
      sections.  */
-  if (bed->elf_backend_size_dynamic_sections
+  if (dynobj != NULL
+      && bed->elf_backend_size_dynamic_sections != NULL
       && ! (*bed->elf_backend_size_dynamic_sections) (output_bfd, info))
     return FALSE;
 
-  if (elf_hash_table (info)->dynamic_sections_created)
+  if (! _bfd_elf_maybe_strip_eh_frame_hdr (info))
+    return FALSE;
+
+  if (dynobj != NULL && elf_hash_table (info)->dynamic_sections_created)
     {
       unsigned long section_sym_count;
       struct bfd_elf_version_tree *verdefs;
@@ -12002,12 +11998,14 @@ bfd_elf_gc_sections (bfd *abfd, struct b
       struct elf_reloc_cookie cookie;
 
       sec = bfd_get_section_by_name (sub, ".eh_frame");
-      if (sec && init_reloc_cookie_for_section (&cookie, info, sec))
+      while (sec && init_reloc_cookie_for_section (&cookie, info, sec))
 	{
 	  _bfd_elf_parse_eh_frame (sub, info, sec, &cookie);
-	  if (elf_section_data (sec)->sec_info)
+	  if (elf_section_data (sec)->sec_info
+	      && (sec->flags & SEC_LINKER_CREATED) == 0)
 	    elf_eh_frame_section (sub) = sec;
 	  fini_reloc_cookie_for_section (&cookie, sec);
+	  sec = bfd_get_next_section_by_name (sec);
 	}
     }
   _bfd_elf_end_eh_frame_parsing (info);
Index: ld/emultempl/elf32.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/elf32.em,v
retrieving revision 1.227
diff -u -p -r1.227 elf32.em
--- ld/emultempl/elf32.em	16 May 2012 10:43:41 -0000	1.227
+++ ld/emultempl/elf32.em	24 May 2012 04:50:21 -0000
@@ -1142,10 +1142,11 @@ gld${EMULATION_NAME}_after_open (void)
 	  if (!warn_eh_frame)
 	    {
 	      s = bfd_get_section_by_name (abfd, ".eh_frame");
-	      warn_eh_frame
-		= (s
-		   && s->size > 8
-		   && !bfd_is_abs_section (s->output_section));
+	      while (s != NULL
+		     && (s->size <= 8
+			 || bfd_is_abs_section (s->output_section)))
+		s = bfd_get_next_section_by_name (s);
+	      warn_eh_frame = s != NULL;
 	    }
 	  if (elfbfd && warn_eh_frame)
 	    break;

-- 
Alan Modra
Australia Development Lab, IBM


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