Cache result of scan for __start_* and __stop_* sections
authorAlan Modra <amodra@gmail.com>
Wed, 27 Apr 2016 03:23:05 +0000 (12:53 +0930)
committerAlan Modra <amodra@gmail.com>
Wed, 27 Apr 2016 07:35:26 +0000 (17:05 +0930)
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.

bfd/ChangeLog
bfd/elf-bfd.h
bfd/elflink.c
include/ChangeLog
include/bfdlink.h

index 8f4de696d0a1828ab08b47d4e42cec8daba45734..f67db84c21238fd89351e45ec2dd7d761e3abfe8 100644 (file)
@@ -1,3 +1,9 @@
+2016-04-27  Alan Modra  <amodra@gmail.com>
+
+       * 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.
+
 2016-04-26  Trevor Saunders  <tbsaunde+binutils@tbsaunde.org>
 
        * elf32-rx.c (rx_set_section_contents): Avoid arithmetic on void *.
index 7447629b0e76f1262d50c2d8d1deb749f526aa6f..6c05b55b641f554a11f825a4219dbba9860aa420 100644 (file)
@@ -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 *);
 
index a6b3c944080339c300badc18ace995a218a2572c..b6ff6b650a96e897de5ac771175625fae584fbc8 100644 (file)
@@ -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;
            }
        }
 
index c73bdf42615ec9b94dc8fe2af89e87084367261d..1390d42da64fa603d40f6ea6231f8286efe6a989 100644 (file)
@@ -1,3 +1,8 @@
+2016-04-27  Alan Modra  <amodra@gmail.com>
+
+       * bfdlink.h (struct bfd_link_hash_entry): Add "section" field to
+       undef.  Formatting.
+
 2016-04-21  Nick Clifton  <nickc@redhat.com>
 
        * bfdlink.h: Add prototype for bfd_link_check_relocs.
index 728fbe71075675e355fd343940813b6f846bbf6b..56ab03872baa958a232a575f1082b44e4b559d56 100644 (file)
@@ -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;
 };