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: [RFC][PATCH] Check ELF relocs after opening all all input files


On Tue, Apr 26, 2016 at 07:25:01AM -0700, H.J. Lu wrote:
> Another problem is when check_relocs is run, linker defined symbols
> haven't been processed yet.

__start_<section> and __stop_<section>?  Yes, they are a pain.

Perhaps this piece of infrastructure will help.

include/
	* bfdlink.h (struct bfd_link_hash_entry): Add "section" field to
	undef.  Formatting.
bfd/
	* elflink.c (_bfd_elf_is_start_stop): New function.
	(_bfd_elf_gc_mark_rsec): Use it.
	* elf-bfd.h (_bfd_elf_is_start_stop): Declare.

diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 7447629..6c05b55 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -2336,6 +2336,9 @@ extern bfd_boolean bfd_elf_gc_common_finalize_got_offsets
 extern bfd_boolean bfd_elf_gc_common_final_link
   (bfd *, struct bfd_link_info *);
 
+extern asection *_bfd_elf_is_start_stop
+  (const struct bfd_link_info *, struct elf_link_hash_entry *);
+
 extern bfd_boolean bfd_elf_reloc_symbol_deleted_p
   (bfd_vma, void *);
 
diff --git a/bfd/elflink.c b/bfd/elflink.c
index a6b3c94..b6ff6b6 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -12230,6 +12230,55 @@ _bfd_elf_gc_mark_hook (asection *sec,
   return NULL;
 }
 
+/* For undefined __start_<name> and __stop_<name> symbols, return the
+   first input section matching <name>.  Return NULL otherwise.  */
+
+asection *
+_bfd_elf_is_start_stop (const struct bfd_link_info *info,
+			struct elf_link_hash_entry *h)
+{
+  asection *s;
+  const char *sec_name;
+
+  if (h->root.type != bfd_link_hash_undefined
+      && h->root.type != bfd_link_hash_undefweak)
+    return NULL;
+
+  s = h->root.u.undef.section;
+  if (s != NULL)
+    {
+      if (s == (asection *) 0 - 1)
+	return NULL;
+      return s;
+    }
+
+  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)
+	{
+	  s = bfd_get_section_by_name (i, sec_name);
+	  if (s != NULL)
+	    {
+	      h->root.u.undef.section = s;
+	      break;
+	    }
+	}
+    }
+
+  if (s == NULL)
+    h->root.u.undef.section = (asection *) 0 - 1;
+
+  return s;
+}
+
 /* COOKIE->rel describes a relocation against section SEC, which is
    a section we've decided to keep.  Return the section that contains
    the relocation symbol, or NULL if no section contains it.  */
@@ -12268,34 +12317,19 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec,
       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))
+      if (start_stop != NULL)
 	{
 	  /* 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;
+	  asection *s = _bfd_elf_is_start_stop (info, h);
 
-	  if (sec_name != NULL && *sec_name != '\0')
+	  if (s != NULL)
 	    {
-	      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;
-		    }
-		}
+	      *start_stop = !s->gc_mark;
+	      return s;
 	    }
 	}
 
diff --git a/include/bfdlink.h b/include/bfdlink.h
index 728fbe7..56ab038 100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -135,21 +135,29 @@ struct bfd_link_hash_entry
 	     automatically be non-NULL since the symbol will have been on the
 	     undefined symbol list.  */
 	  struct bfd_link_hash_entry *next;
-	  bfd *abfd;		/* BFD symbol was found in.  */
+	  /* BFD symbol was found in.  */
+	  bfd *abfd;
+	  /* For __start_<name> and __stop_<name> symbols, the first
+	     input section matching the name.  */
+	  asection *section;
 	} undef;
       /* bfd_link_hash_defined, bfd_link_hash_defweak.  */
       struct
 	{
 	  struct bfd_link_hash_entry *next;
-	  asection *section;	/* Symbol section.  */
-	  bfd_vma value;	/* Symbol value.  */
+	  /* Symbol section.  */
+	  asection *section;
+	  /* Symbol value.  */
+	  bfd_vma value;
 	} def;
       /* bfd_link_hash_indirect, bfd_link_hash_warning.  */
       struct
 	{
 	  struct bfd_link_hash_entry *next;
-	  struct bfd_link_hash_entry *link;	/* Real symbol.  */
-	  const char *warning;	/* Warning (bfd_link_hash_warning only).  */
+	  /* Real symbol.  */
+	  struct bfd_link_hash_entry *link;
+	  /* Warning message (bfd_link_hash_warning only).  */
+	  const char *warning;
 	} i;
       /* bfd_link_hash_common.  */
       struct
@@ -165,7 +173,8 @@ struct bfd_link_hash_entry
 	     the union; this structure is a major space user in the
 	     linker.  */
 	  struct bfd_link_hash_common_entry *p;
-	  bfd_size_type size;	/* Common symbol size.  */
+	  /* Common symbol size.  */
+	  bfd_size_type size;
 	} c;
     } u;
 };

-- 
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]