This is the mail archive of the binutils-cvs@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]

[binutils-gdb] Handle __start_* and __stop_* symbols in --gc-sections


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=1cce69b9dc8c58884c3cc4a8928fb234294e6886

commit 1cce69b9dc8c58884c3cc4a8928fb234294e6886
Author: Alan Modra <amodra@gmail.com>
Date:   Fri Oct 23 22:23:05 2015 +1030

    Handle __start_* and __stop_* symbols in --gc-sections
    
    	PR ld/11133
    	PR ld/19161
    	PR ld/19167
    	* elflink.c (_bfd_elf_gc_mark_hook): Delete code handling __start_*
    	and __stop_* symbol refs.
    	(_bfd_elf_gc_mark_rsec): Add start_stop parameter.  Handle __start_*
    	and __stop_* symbol refs here..
    	(_bfd_elf_gc_mark_reloc): ..and here.
    	* elf-bfd.h (_bfd_elf_gc_mark_hook): Update prototype.
    	* elf-eh-frame.c (_bfd_elf_parse_eh_frame): Update
    	_bfd_elf_gc_mark_rsec call.

Diff:
---
 bfd/ChangeLog      |  14 ++++++++
 bfd/elf-bfd.h      |   2 +-
 bfd/elf-eh-frame.c |   3 +-
 bfd/elflink.c      | 102 ++++++++++++++++++++++++++++++++++-------------------
 4 files changed, 82 insertions(+), 39 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 481d972..19723d2 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -2,6 +2,20 @@
 
 	PR ld/11133
 	PR ld/19161
+	PR ld/19167
+	* elflink.c (_bfd_elf_gc_mark_hook): Delete code handling __start_*
+	and __stop_* symbol refs.
+	(_bfd_elf_gc_mark_rsec): Add start_stop parameter.  Handle __start_*
+	and __stop_* symbol refs here..
+	(_bfd_elf_gc_mark_reloc): ..and here.
+	* elf-bfd.h (_bfd_elf_gc_mark_hook): Update prototype.
+	* elf-eh-frame.c (_bfd_elf_parse_eh_frame): Update
+	_bfd_elf_gc_mark_rsec call.
+
+2015-10-23  Alan Modra  <amodra@gmail.com>
+
+	PR ld/11133
+	PR ld/19161
 	* elflink.c (elf_gc_sweep): Revert last patch.
 	(_bfd_elf_gc_mark_hook): Don't set SEC_KEEP here.
 
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index b7ca2d0..2b05089 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -2296,7 +2296,7 @@ extern asection *_bfd_elf_gc_mark_hook
 
 extern asection *_bfd_elf_gc_mark_rsec
   (struct bfd_link_info *, asection *, elf_gc_mark_hook_fn,
-   struct elf_reloc_cookie *);
+   struct elf_reloc_cookie *, bfd_boolean *);
 
 extern bfd_boolean _bfd_elf_gc_mark_reloc
   (struct bfd_link_info *, asection *, elf_gc_mark_hook_fn,
diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c
index 7d65dae..e303189 100644
--- a/bfd/elf-eh-frame.c
+++ b/bfd/elf-eh-frame.c
@@ -902,7 +902,8 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info,
 	      REQUIRE (GET_RELOC (buf));
 
 	      /* Chain together the FDEs for each section.  */
-	      rsec = _bfd_elf_gc_mark_rsec (info, sec, gc_mark_hook, cookie);
+	      rsec = _bfd_elf_gc_mark_rsec (info, sec, gc_mark_hook,
+					    cookie, NULL);
 	      /* RSEC will be NULL if FDE was cleared out as it was belonging to
 		 a discarded SHT_GROUP.  */
 	      if (rsec)
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 6dcc431..1cfdd31 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -12066,8 +12066,6 @@ _bfd_elf_gc_mark_hook (asection *sec,
 		       struct elf_link_hash_entry *h,
 		       Elf_Internal_Sym *sym)
 {
-  const char *sec_name;
-
   if (h != NULL)
     {
       switch (h->root.type)
@@ -12079,33 +12077,6 @@ _bfd_elf_gc_mark_hook (asection *sec,
 	case bfd_link_hash_common:
 	  return h->root.u.c.p->section;
 
-	case bfd_link_hash_undefined:
-	case bfd_link_hash_undefweak:
-	  /* To work around a glibc bug, keep all XXX input sections
-	     when there is an as yet undefined reference to __start_XXX
-	     or __stop_XXX symbols.  The linker will later define such
-	     symbols for orphan input sections that have a name
-	     representable as a C identifier.  */
-	  if (strncmp (h->root.root.string, "__start_", 8) == 0)
-	    sec_name = h->root.root.string + 8;
-	  else if (strncmp (h->root.root.string, "__stop_", 7) == 0)
-	    sec_name = h->root.root.string + 7;
-	  else
-	    sec_name = NULL;
-
-	  if (sec_name && *sec_name != '\0')
-	    {
-	      bfd *i;
-
-	      for (i = info->input_bfds; i; i = i->link.next)
-		{
-		  sec = bfd_get_section_by_name (i, sec_name);
-		  if (sec)
-		    return sec;
-		}
-	    }
-	  break;
-
 	default:
 	  break;
 	}
@@ -12123,7 +12094,8 @@ _bfd_elf_gc_mark_hook (asection *sec,
 asection *
 _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec,
 		       elf_gc_mark_hook_fn gc_mark_hook,
-		       struct elf_reloc_cookie *cookie)
+		       struct elf_reloc_cookie *cookie,
+		       bfd_boolean *start_stop)
 {
   unsigned long r_symndx;
   struct elf_link_hash_entry *h;
@@ -12152,6 +12124,38 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec,
 	 handling copy relocs.  */
       if (h->u.weakdef != NULL)
 	h->u.weakdef->mark = 1;
+
+      if (start_stop != NULL
+	  && (h->root.type == bfd_link_hash_undefined
+	      || h->root.type == bfd_link_hash_undefweak))
+	{
+	  /* To work around a glibc bug, mark all XXX input sections
+	     when there is an as yet undefined reference to __start_XXX
+	     or __stop_XXX symbols.  The linker will later define such
+	     symbols for orphan input sections that have a name
+	     representable as a C identifier.  */
+	  const char *sec_name = NULL;
+	  if (strncmp (h->root.root.string, "__start_", 8) == 0)
+	    sec_name = h->root.root.string + 8;
+	  else if (strncmp (h->root.root.string, "__stop_", 7) == 0)
+	    sec_name = h->root.root.string + 7;
+
+	  if (sec_name != NULL && *sec_name != '\0')
+	    {
+	      bfd *i;
+
+	      for (i = info->input_bfds; i != NULL; i = i->link.next)
+		{
+		  asection *s = bfd_get_section_by_name (i, sec_name);
+		  if (s != NULL && !s->gc_mark)
+		    {
+		      *start_stop = TRUE;
+		      return s;
+		    }
+		}
+	    }
+	}
+
       return (*gc_mark_hook) (sec, info, cookie->rel, h, NULL);
     }
 
@@ -12170,15 +12174,39 @@ _bfd_elf_gc_mark_reloc (struct bfd_link_info *info,
 			struct elf_reloc_cookie *cookie)
 {
   asection *rsec;
+  bfd_boolean start_stop = FALSE;
 
-  rsec = _bfd_elf_gc_mark_rsec (info, sec, gc_mark_hook, cookie);
-  if (rsec && !rsec->gc_mark)
+  rsec = _bfd_elf_gc_mark_rsec (info, sec, gc_mark_hook, cookie, &start_stop);
+  while (rsec != NULL)
     {
-      if (bfd_get_flavour (rsec->owner) != bfd_target_elf_flavour
-	  || (rsec->owner->flags & DYNAMIC) != 0)
-	rsec->gc_mark = 1;
-      else if (!_bfd_elf_gc_mark (info, rsec, gc_mark_hook))
-	return FALSE;
+      asection *s;
+
+      if (!rsec->gc_mark)
+	{
+	  if (bfd_get_flavour (rsec->owner) != bfd_target_elf_flavour
+	      || (rsec->owner->flags & DYNAMIC) != 0)
+	    rsec->gc_mark = 1;
+	  else if (!_bfd_elf_gc_mark (info, rsec, gc_mark_hook))
+	    return FALSE;
+	}
+      if (!start_stop)
+	break;
+      s = bfd_get_next_section_by_name (rsec);
+      if (s == NULL)
+	{
+	  bfd *i = rsec->owner;
+
+	  if (i != NULL)
+	    {
+	      while ((i = i->link.next) != NULL)
+		{
+		  s = bfd_get_section_by_name (i, rsec->name);
+		  if (s != NULL)
+		    break;
+		}
+	    }
+	}
+      rsec = s;
     }
   return TRUE;
 }


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