PR ld/12549
[deliverable/binutils-gdb.git] / bfd / elflink.c
index 7722fb5d8954db605de94020afdae45bf413a2b3..b652becf8c8238bf43708539aa7fa1cf49727a1e 100644 (file)
@@ -1,6 +1,6 @@
 /* ELF linking support for BFD.
    Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-   2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
+   2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
    Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -104,8 +104,8 @@ _bfd_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
   struct elf_link_hash_table *htab = elf_hash_table (info);
 
   /* This function may be called more than once.  */
-  s = bfd_get_section_by_name (abfd, ".got");
-  if (s != NULL && (s->flags & SEC_LINKER_CREATED) != 0)
+  s = bfd_get_linker_section (abfd, ".got");
+  if (s != NULL)
     return TRUE;
 
   flags = bed->dynamic_sec_flags;
@@ -187,6 +187,7 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
   flagword flags;
   asection *s;
   const struct elf_backend_data *bed;
+  struct elf_link_hash_entry *h;
 
   if (! is_elf_hash_table (info->hash))
     return FALSE;
@@ -254,7 +255,9 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
      section.  We don't want to define it if there is no .dynamic
      section, since on some ELF platforms the start up code examines it
      to decide how to initialize the process.  */
-  if (!_bfd_elf_define_linkage_sym (abfd, info, s, "_DYNAMIC"))
+  h = _bfd_elf_define_linkage_sym (abfd, info, s, "_DYNAMIC");
+  elf_hash_table (info)->hdynamic = h;
+  if (h == NULL)
     return FALSE;
 
   if (info->emit_hash)
@@ -569,7 +572,7 @@ bfd_elf_record_link_assignment (bfd *output_bfd,
 
   h->def_regular = 1;
 
-  if (provide && hidden)
+  if (hidden)
     {
       bed = get_elf_backend_data (output_bfd);
       h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN;
@@ -779,8 +782,7 @@ _bfd_elf_link_omit_section_dynsym (bfd *output_bfd ATTRIBUTE_UNUSED,
          asection *ip;
 
          if (htab->dynobj != NULL
-             && (ip = bfd_get_section_by_name (htab->dynobj, p->name)) != NULL
-             && (ip->flags & SEC_LINKER_CREATED)
+             && (ip = bfd_get_linker_section (htab->dynobj, p->name)) != NULL
              && ip->output_section == p)
            return TRUE;
        }
@@ -912,6 +914,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
                       Elf_Internal_Sym *sym,
                       asection **psec,
                       bfd_vma *pvalue,
+                      bfd_boolean *pold_weak,
                       unsigned int *pold_alignment,
                       struct elf_link_hash_entry **sym_hash,
                       bfd_boolean *skip,
@@ -921,6 +924,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
 {
   asection *sec, *oldsec;
   struct elf_link_hash_entry *h;
+  struct elf_link_hash_entry *hi;
   struct elf_link_hash_entry *flip;
   int bind;
   bfd *oldbfd;
@@ -959,17 +963,47 @@ _bfd_elf_merge_symbol (bfd *abfd,
   if (!(*bed->relocs_compatible) (abfd->xvec, info->output_bfd->xvec))
     return TRUE;
 
-  /* For merging, we only care about real symbols.  */
-
+  /* For merging, we only care about real symbols.  But we need to make
+     sure that indirect symbol dynamic flags are updated.  */
+  hi = h;
   while (h->root.type == bfd_link_hash_indirect
         || h->root.type == bfd_link_hash_warning)
     h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
   /* We have to check it for every instance since the first few may be
-     refereences and not all compilers emit symbol type for undefined
+     references and not all compilers emit symbol type for undefined
      symbols.  */
   bfd_elf_link_mark_dynamic_symbol (info, h, sym);
 
+  /* NEWDYN and OLDDYN indicate whether the new or old symbol,
+     respectively, is from a dynamic object.  */
+
+  newdyn = (abfd->flags & DYNAMIC) != 0;
+
+  /* ref_dynamic_nonweak and dynamic_def flags track actual undefined
+     syms and defined syms in dynamic libraries respectively.
+     ref_dynamic on the other hand can be set for a symbol defined in
+     a dynamic library, and def_dynamic may not be set;  When the
+     definition in a dynamic lib is overridden by a definition in the
+     executable use of the symbol in the dynamic lib becomes a
+     reference to the executable symbol.  */
+  if (newdyn)
+    {
+      if (bfd_is_und_section (sec))
+       {
+         if (bind != STB_WEAK)
+           {
+             h->ref_dynamic_nonweak = 1;
+             hi->ref_dynamic_nonweak = 1;
+           }
+       }
+      else
+       {
+         h->dynamic_def = 1;
+         hi->dynamic_def = 1;
+       }
+    }
+
   /* If we just created the symbol, mark it as being an ELF symbol.
      Other than that, there is nothing to do--there is no merge issue
      with a newly defined symbol--so we just return.  */
@@ -1012,6 +1046,8 @@ _bfd_elf_merge_symbol (bfd *abfd,
   newweak = bind == STB_WEAK;
   oldweak = (h->root.type == bfd_link_hash_defweak
             || h->root.type == bfd_link_hash_undefweak);
+  if (pold_weak)
+    *pold_weak = oldweak;
 
   /* In cases involving weak versioned symbols, we may wind up trying
      to merge a symbol with itself.  Catch that here, to avoid the
@@ -1025,11 +1061,6 @@ _bfd_elf_merge_symbol (bfd *abfd,
          || !h->def_regular))
     return TRUE;
 
-  /* NEWDYN and OLDDYN indicate whether the new or old symbol,
-     respectively, is from a dynamic object.  */
-
-  newdyn = (abfd->flags & DYNAMIC) != 0;
-
   olddyn = FALSE;
   if (oldbfd != NULL)
     olddyn = (oldbfd->flags & DYNAMIC) != 0;
@@ -1133,28 +1164,6 @@ _bfd_elf_merge_symbol (bfd *abfd,
       return FALSE;
     }
 
-  /* We need to remember if a symbol has a definition in a dynamic
-     object or is weak in all dynamic objects. Internal and hidden
-     visibility will make it unavailable to dynamic objects.  */
-  if (newdyn && !h->dynamic_def)
-    {
-      if (!bfd_is_und_section (sec))
-       h->dynamic_def = 1;
-      else
-       {
-         /* Check if this symbol is weak in all dynamic objects. If it
-            is the first time we see it in a dynamic object, we mark
-            if it is weak. Otherwise, we clear it.  */
-         if (!h->ref_dynamic)
-           {
-             if (bind == STB_WEAK)
-               h->dynamic_weak = 1;
-           }
-         else if (bind != STB_WEAK)
-           h->dynamic_weak = 0;
-       }
-    }
-
   /* If the old symbol has non-default visibility, we ignore the new
      definition from a dynamic object.  */
   if (newdyn
@@ -1164,6 +1173,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
       *skip = TRUE;
       /* Make sure this symbol is dynamic.  */
       h->ref_dynamic = 1;
+      hi->ref_dynamic = 1;
       /* A protected symbol has external availability. Make sure it is
         recorded as dynamic.
 
@@ -1193,38 +1203,39 @@ _bfd_elf_merge_symbol (bfd *abfd,
              vh->root.type = h->root.type;
              h->root.type = bfd_link_hash_indirect;
              (*bed->elf_backend_copy_indirect_symbol) (info, vh, h);
-             /* Protected symbols will override the dynamic definition
-                with default version.  */
-             if (ELF_ST_VISIBILITY (sym->st_other) == STV_PROTECTED)
+
+             h->root.u.i.link = (struct bfd_link_hash_entry *) vh;
+             if (ELF_ST_VISIBILITY (sym->st_other) != STV_PROTECTED)
                {
-                 h->root.u.i.link = (struct bfd_link_hash_entry *) vh;
-                 vh->dynamic_def = 1;
-                 vh->ref_dynamic = 1;
+                 /* If the new symbol is hidden or internal, completely undo
+                    any dynamic link state.  */
+                 (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+                 h->forced_local = 0;
+                 h->ref_dynamic = 0;
                }
              else
-               {
-                 h->root.type = vh->root.type;
-                 vh->ref_dynamic = 0;
-                 /* We have to hide it here since it was made dynamic
-                    global with extra bits when the symbol info was
-                    copied from the old dynamic definition.  */
-                 (*bed->elf_backend_hide_symbol) (info, vh, TRUE);
-               }
+               h->ref_dynamic = 1;
+
+             h->def_dynamic = 0;
+             /* FIXME: Should we check type and size for protected symbol?  */
+             h->size = 0;
+             h->type = 0;
+
              h = vh;
            }
          else
            h = *sym_hash;
        }
 
-      if ((h->root.u.undef.next || info->hash->undefs_tail == &h->root)
-         && bfd_is_und_section (sec))
+      /* If the old symbol was undefined before, then it will still be
+        on the undefs list.  If the new symbol is undefined or
+        common, we can't make it bfd_link_hash_new here, because new
+        undefined or common symbols will be added to the undefs list
+        by _bfd_generic_link_add_one_symbol.  Symbols may not be
+        added twice to the undefs list.  Also, if the new symbol is
+        undefweak then we don't want to lose the strong undef.  */
+      if (h->root.u.undef.next || info->hash->undefs_tail == &h->root)
        {
-         /* If the new symbol is undefined and the old symbol was
-            also undefined before, we need to make sure
-            _bfd_generic_link_add_one_symbol doesn't mess
-            up the linker hash table undefs list.  Since the old
-            definition came from a dynamic object, it is still on the
-            undefs list.  */
          h->root.type = bfd_link_hash_undefined;
          h->root.u.undef.abfd = abfd;
        }
@@ -1234,11 +1245,17 @@ _bfd_elf_merge_symbol (bfd *abfd,
          h->root.u.undef.abfd = NULL;
        }
 
-      if (h->def_dynamic)
+      if (ELF_ST_VISIBILITY (sym->st_other) != STV_PROTECTED)
        {
-         h->def_dynamic = 0;
-         h->ref_dynamic = 1;
+         /* If the new symbol is hidden or internal, completely undo
+            any dynamic link state.  */
+         (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+         h->forced_local = 0;
+         h->ref_dynamic = 0;
        }
+      else
+       h->ref_dynamic = 1;
+      h->def_dynamic = 0;
       /* FIXME: Should we check type and size for protected symbol?  */
       h->size = 0;
       h->type = 0;
@@ -1636,7 +1653,7 @@ _bfd_elf_add_default_symbol (bfd *abfd,
   size_change_ok = FALSE;
   sec = *psec;
   if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &sec, value,
-                             NULL, &hi, &skip, &override,
+                             NULL, NULL, &hi, &skip, &override,
                              &type_change_ok, &size_change_ok))
     return FALSE;
 
@@ -1717,6 +1734,7 @@ _bfd_elf_add_default_symbol (bfd *abfd,
          if (! dynamic)
            {
              if (! info->executable
+                 || hi->def_dynamic
                  || hi->ref_dynamic)
                *dynsym = TRUE;
            }
@@ -1744,7 +1762,7 @@ nondefault:
   size_change_ok = FALSE;
   sec = *psec;
   if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &sec, value,
-                             NULL, &hi, &skip, &override,
+                             NULL, NULL, &hi, &skip, &override,
                              &type_change_ok, &size_change_ok))
     return FALSE;
 
@@ -3029,7 +3047,7 @@ _bfd_elf_add_dynamic_entry (struct bfd_link_info *info,
     return FALSE;
 
   bed = get_elf_backend_data (hash_table->dynobj);
-  s = bfd_get_section_by_name (hash_table->dynobj, ".dynamic");
+  s = bfd_get_linker_section (hash_table->dynobj, ".dynamic");
   BFD_ASSERT (s != NULL);
 
   newsize = s->size + bed->s->sizeof_dyn;
@@ -3058,26 +3076,24 @@ elf_add_dt_needed_tag (bfd *abfd,
                       bfd_boolean do_it)
 {
   struct elf_link_hash_table *hash_table;
-  bfd_size_type oldsize;
   bfd_size_type strindex;
 
   if (!_bfd_elf_link_create_dynstrtab (abfd, info))
     return -1;
 
   hash_table = elf_hash_table (info);
-  oldsize = _bfd_elf_strtab_size (hash_table->dynstr);
   strindex = _bfd_elf_strtab_add (hash_table->dynstr, soname, FALSE);
   if (strindex == (bfd_size_type) -1)
     return -1;
 
-  if (oldsize == _bfd_elf_strtab_size (hash_table->dynstr))
+  if (_bfd_elf_strtab_refcount (hash_table->dynstr, strindex) != 1)
     {
       asection *sdyn;
       const struct elf_backend_data *bed;
       bfd_byte *extdyn;
 
       bed = get_elf_backend_data (hash_table->dynobj);
-      sdyn = bfd_get_section_by_name (hash_table->dynobj, ".dynamic");
+      sdyn = bfd_get_linker_section (hash_table->dynobj, ".dynamic");
       if (sdyn != NULL)
        for (extdyn = sdyn->contents;
             extdyn < sdyn->contents + sdyn->size;
@@ -3120,7 +3136,7 @@ on_needed_list (const char *soname, struct bfd_link_needed_list *needed)
   return FALSE;
 }
 
-/* Sort symbol by value and section.  */
+/* Sort symbol by value, section, and size.  */
 static int
 elf_sort_symbol (const void *arg1, const void *arg2)
 {
@@ -3139,7 +3155,8 @@ elf_sort_symbol (const void *arg1, const void *arg2)
       if (sdiff != 0)
        return sdiff > 0 ? 1 : -1;
     }
-  return 0;
+  vdiff = h1->size - h2->size;
+  return vdiff == 0 ? 0 : vdiff > 0 ? 1 : -1;
 }
 
 /* This function is used to adjust offsets into .dynstr for
@@ -3174,7 +3191,7 @@ elf_finalize_dynstr (bfd *output_bfd, struct bfd_link_info *info)
   size = _bfd_elf_strtab_size (dynstr);
 
   bed = get_elf_backend_data (dynobj);
-  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+  sdyn = bfd_get_linker_section (dynobj, ".dynamic");
   BFD_ASSERT (sdyn != NULL);
 
   /* Update all .dynamic entries referencing .dynstr strings.  */
@@ -3223,7 +3240,7 @@ elf_finalize_dynstr (bfd *output_bfd, struct bfd_link_info *info)
       Elf_Internal_Verdef def;
       Elf_Internal_Verdaux defaux;
 
-      s = bfd_get_section_by_name (dynobj, ".gnu.version_d");
+      s = bfd_get_linker_section (dynobj, ".gnu.version_d");
       p = s->contents;
       do
        {
@@ -3255,7 +3272,7 @@ elf_finalize_dynstr (bfd *output_bfd, struct bfd_link_info *info)
       Elf_Internal_Verneed need;
       Elf_Internal_Vernaux needaux;
 
-      s = bfd_get_section_by_name (dynobj, ".gnu.version_r");
+      s = bfd_get_linker_section (dynobj, ".gnu.version_r");
       p = s->contents;
       do
        {
@@ -3351,6 +3368,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
   struct bfd_link_hash_entry *old_undefs = NULL;
   struct bfd_link_hash_entry *old_undefs_tail = NULL;
   long old_dynsymcount = 0;
+  bfd_size_type old_dynstr_size = 0;
   size_t tabsize = 0;
   size_t hashsize = 0;
 
@@ -3678,7 +3696,7 @@ error_free_dyn:
        return TRUE;
 
       /* Save the DT_AUDIT entry for the linker emulation code. */
-      elf_dt_audit (abfd) = audit; 
+      elf_dt_audit (abfd) = audit;
     }
 
   /* If this is a dynamic object, we always link against the .dynsym
@@ -3800,6 +3818,7 @@ error_free_dyn:
       old_size = htab->root.table.size;
       old_count = htab->root.table.count;
       old_dynsymcount = htab->dynsymcount;
+      old_dynstr_size = _bfd_elf_strtab_size (htab->dynstr);
 
       for (i = 0; i < htab->root.table.size; i++)
        {
@@ -3832,10 +3851,13 @@ error_free_dyn:
       flagword flags;
       const char *name;
       struct elf_link_hash_entry *h;
+      struct elf_link_hash_entry *hi;
       bfd_boolean definition;
       bfd_boolean size_change_ok;
       bfd_boolean type_change_ok;
       bfd_boolean new_weakdef;
+      bfd_boolean new_weak;
+      bfd_boolean old_weak;
       bfd_boolean override;
       bfd_boolean common;
       unsigned int old_alignment;
@@ -3968,6 +3990,7 @@ error_free_dyn:
 
       size_change_ok = FALSE;
       type_change_ok = bed->type_change_ok;
+      old_weak = FALSE;
       old_alignment = 0;
       old_bfd = NULL;
       new_sec = sec;
@@ -3979,19 +4002,21 @@ error_free_dyn:
          bfd_boolean skip;
 
          /* If this is a definition of a symbol which was previously
-            referenced in a non-weak manner then make a note of the bfd
-            that contained the reference.  This is used if we need to
-            refer to the source of the reference later on.  */
+            referenced, then make a note of the bfd that contained the
+            reference.  This is used if we need to refer to the source
+            of the reference later on.  */
          if (! bfd_is_und_section (sec))
            {
-             h = elf_link_hash_lookup (elf_hash_table (info), name, FALSE, FALSE, FALSE);
+             h = elf_link_hash_lookup (elf_hash_table (info), name,
+                                       FALSE, FALSE, FALSE);
 
              if (h != NULL
-                 && h->root.type == bfd_link_hash_undefined
+                 && (h->root.type == bfd_link_hash_undefined
+                     || h->root.type == bfd_link_hash_undefweak)
                  && h->root.u.undef.abfd)
                undef_bfd = h->root.u.undef.abfd;
            }
-         
+
          if (ever == NULL)
            {
              if (info->default_imported_symver)
@@ -4100,20 +4125,21 @@ error_free_dyn:
            }
 
          /* If necessary, make a second attempt to locate the bfd
-            containing an unresolved, non-weak reference to the
-            current symbol.  */
+            containing an unresolved reference to the current symbol.  */
          if (! bfd_is_und_section (sec) && undef_bfd == NULL)
            {
-             h = elf_link_hash_lookup (elf_hash_table (info), name, FALSE, FALSE, FALSE);
+             h = elf_link_hash_lookup (elf_hash_table (info), name,
+                                       FALSE, FALSE, FALSE);
 
              if (h != NULL
-                 && h->root.type == bfd_link_hash_undefined
+                 && (h->root.type == bfd_link_hash_undefined
+                     || h->root.type == bfd_link_hash_undefweak)
                  && h->root.u.undef.abfd)
                undef_bfd = h->root.u.undef.abfd;
            }
 
          if (!_bfd_elf_merge_symbol (abfd, info, name, isym, &sec,
-                                     &value, &old_alignment,
+                                     &value, &old_weak, &old_alignment,
                                      sym_hash, &skip, &override,
                                      &type_change_ok, &size_change_ok))
            goto error_free_vers;
@@ -4152,7 +4178,6 @@ error_free_dyn:
            }
 
          if (elf_tdata (abfd)->verdef != NULL
-             && ! override
              && vernum > 1
              && definition)
            h->verinfo.verdef = &elf_tdata (abfd)->verdef[vernum - 1];
@@ -4164,6 +4189,9 @@ error_free_dyn:
        goto error_free_vers;
 
       h = *sym_hash;
+      /* We need to make sure that indirect symbol dynamic flags are
+        updated.  */
+      hi = h;
       while (h->root.type == bfd_link_hash_indirect
             || h->root.type == bfd_link_hash_warning)
        h = (struct elf_link_hash_entry *) h->root.u.i.link;
@@ -4172,10 +4200,11 @@ error_free_dyn:
       if (is_elf_hash_table (htab))
        h->unique_global = (flags & BSF_GNU_UNIQUE) != 0;
 
+      new_weak = (flags & BSF_WEAK) != 0;
       new_weakdef = FALSE;
       if (dynamic
          && definition
-         && (flags & BSF_WEAK) != 0
+         && new_weak
          && !bed->is_function_type (ELF_ST_TYPE (isym->st_info))
          && is_elf_hash_table (htab)
          && h->u.weakdef == NULL)
@@ -4304,7 +4333,9 @@ error_free_dyn:
            h->size = h->root.u.c.size;
 
          if (ELF_ST_TYPE (isym->st_info) != STT_NOTYPE
-             && (definition || h->type == STT_NOTYPE))
+             && ((definition && !new_weak)
+                 || (old_weak && h->root.type == bfd_link_hash_common)
+                 || h->type == STT_NOTYPE))
            {
              unsigned int type = ELF_ST_TYPE (isym->st_info);
 
@@ -4352,25 +4383,36 @@ error_free_dyn:
                      h->ref_dynamic = 1;
                    }
                }
-             if (! info->executable
-                 || h->def_dynamic
-                 || h->ref_dynamic)
+
+             /* If the indirect symbol has been forced local, don't
+                make the real symbol dynamic.  */
+             if ((h == hi || !hi->forced_local)
+                 && (! info->executable
+                     || h->def_dynamic
+                     || h->ref_dynamic))
                dynsym = TRUE;
            }
          else
            {
              if (! definition)
-               h->ref_dynamic = 1;
+               {
+                 h->ref_dynamic = 1;
+                 hi->ref_dynamic = 1;
+               }
              else
                {
                  h->def_dynamic = 1;
-                 h->dynamic_def = 1;
+                 hi->def_dynamic = 1;
                }
-             if (h->def_regular
-                 || h->ref_regular
-                 || (h->u.weakdef != NULL
-                     && ! new_weakdef
-                     && h->u.weakdef->dynindx != -1))
+
+             /* If the indirect symbol has been forced local, don't
+                make the real symbol dynamic.  */
+             if ((h == hi || !hi->forced_local)
+                 && (h->def_regular
+                     || h->ref_regular
+                     || (h->u.weakdef != NULL
+                         && ! new_weakdef
+                         && h->u.weakdef->dynindx != -1)))
                dynsym = TRUE;
            }
 
@@ -4438,10 +4480,13 @@ error_free_dyn:
                break;
              }
 
+         /* Don't add DT_NEEDED for references from the dummy bfd.  */
          if (!add_needed
              && definition
              && ((dynsym
-                  && h->ref_regular)
+                  && h->ref_regular
+                  && (undef_bfd == NULL
+                      || (undef_bfd->flags & BFD_PLUGIN) == 0))
                  || (h->ref_dynamic
                      && (elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0
                      && !on_needed_list (elf_dt_name (abfd), htab->needed))))
@@ -4509,6 +4554,7 @@ error_free_dyn:
       memcpy (sym_hash, old_hash, hashsize);
       htab->root.undefs = old_undefs;
       htab->root.undefs_tail = old_undefs_tail;
+      _bfd_elf_strtab_restore_size (htab->dynstr, old_dynstr_size);
       for (i = 0; i < htab->root.table.size; i++)
        {
          struct bfd_hash_entry *p;
@@ -4521,12 +4567,13 @@ error_free_dyn:
              h = (struct elf_link_hash_entry *) p;
              if (h->root.type == bfd_link_hash_warning)
                h = (struct elf_link_hash_entry *) h->root.u.i.link;
-             if (h->dynindx >= old_dynsymcount)
+             if (h->dynindx >= old_dynsymcount
+                 && h->dynstr_index < old_dynstr_size)
                _bfd_elf_strtab_delref (htab->dynstr, h->dynstr_index);
 
              /* Preserve the maximum alignment and size for common
                 symbols even if this dynamic lib isn't on DT_NEEDED
-                since it can still be loaded at the run-time by another
+                since it can still be loaded at run time by another
                 dynamic lib.  */
              if (h->root.type == bfd_link_hash_common)
                {
@@ -4545,8 +4592,9 @@ error_free_dyn:
                {
                  memcpy (h->root.u.i.link, old_ent, htab->root.table.entsize);
                  old_ent = (char *) old_ent + htab->root.table.entsize;
+                 h = (struct elf_link_hash_entry *) h->root.u.i.link;
                }
-             else if (h->root.type == bfd_link_hash_common)
+             if (h->root.type == bfd_link_hash_common)
                {
                  if (size > h->root.u.c.size)
                    h->root.u.c.size = size;
@@ -4684,7 +4732,6 @@ error_free_dyn:
          struct elf_link_hash_entry *hlook;
          asection *slook;
          bfd_vma vlook;
-         long ilook;
          size_t i, j, idx;
 
          hlook = weaks;
@@ -4698,14 +4745,13 @@ error_free_dyn:
          slook = hlook->root.u.def.section;
          vlook = hlook->root.u.def.value;
 
-         ilook = -1;
          i = 0;
          j = sym_count;
-         while (i < j)
+         while (i != j)
            {
              bfd_signed_vma vdiff;
              idx = (i + j) / 2;
-             h = sorted_sym_hash [idx];
+             h = sorted_sym_hash[idx];
              vdiff = vlook - h->root.u.def.value;
              if (vdiff < 0)
                j = idx;
@@ -4719,24 +4765,36 @@ error_free_dyn:
                  else if (sdiff > 0)
                    i = idx + 1;
                  else
-                   {
-                     ilook = idx;
-                     break;
-                   }
+                   break;
                }
            }
 
          /* We didn't find a value/section match.  */
-         if (ilook == -1)
+         if (i == j)
            continue;
 
-         for (i = ilook; i < sym_count; i++)
+         /* With multiple aliases, or when the weak symbol is already
+            strongly defined, we have multiple matching symbols and
+            the binary search above may land on any of them.  Step
+            one past the matching symbol(s).  */
+         while (++idx != j)
            {
-             h = sorted_sym_hash [i];
+             h = sorted_sym_hash[idx];
+             if (h->root.u.def.section != slook
+                 || h->root.u.def.value != vlook)
+               break;
+           }
+
+         /* Now look back over the aliases.  Since we sorted by size
+            as well as value and section, we'll choose the one with
+            the largest size.  */
+         while (idx-- != i)
+           {
+             h = sorted_sym_hash[idx];
 
              /* Stop if value or section doesn't match.  */
-             if (h->root.u.def.value != vlook
-                 || h->root.u.def.section != slook)
+             if (h->root.u.def.section != slook
+                 || h->root.u.def.value != vlook)
                break;
              else if (h != hlook)
                {
@@ -5500,6 +5558,65 @@ _bfd_elf_size_group_sections (struct bfd_link_info *info)
   return TRUE;
 }
 
+/* Set a default stack segment size.  The value in INFO wins.  If it
+   is unset, LEGACY_SYMBOL's value is used, and if that symbol is
+   undefined it is initialized.  */
+
+bfd_boolean
+bfd_elf_stack_segment_size (bfd *output_bfd,
+                           struct bfd_link_info *info,
+                           const char *legacy_symbol,
+                           bfd_vma default_size)
+{
+  struct elf_link_hash_entry *h = NULL;
+
+  /* Look for legacy symbol.  */
+  if (legacy_symbol)
+    h = elf_link_hash_lookup (elf_hash_table (info), legacy_symbol,
+                             FALSE, FALSE, FALSE);
+  if (h && (h->root.type == bfd_link_hash_defined
+           || h->root.type == bfd_link_hash_defweak)
+      && h->def_regular
+      && (h->type == STT_NOTYPE || h->type == STT_OBJECT))
+    {
+      /* The symbol has no type if specified on the command line.  */
+      h->type = STT_OBJECT;
+      if (info->stacksize)
+       (*_bfd_error_handler) (_("%B: stack size specified and %s set"),
+                              output_bfd, legacy_symbol);
+      else if (h->root.u.def.section != bfd_abs_section_ptr)
+       (*_bfd_error_handler) (_("%B: %s not absolute"),
+                              output_bfd, legacy_symbol);
+      else
+       info->stacksize = h->root.u.def.value;
+    }
+
+  if (!info->stacksize)
+    /* If the user didn't set a size, or explicitly inhibit the
+       size, set it now.  */
+    info->stacksize = default_size;
+
+  /* Provide the legacy symbol, if it is referenced.  */
+  if (h && (h->root.type == bfd_link_hash_undefined
+           || h->root.type == bfd_link_hash_undefweak))
+    {
+      struct bfd_link_hash_entry *bh = NULL;
+
+      if (!(_bfd_generic_link_add_one_symbol
+           (info, output_bfd, legacy_symbol,
+            BSF_GLOBAL, bfd_abs_section_ptr,
+            info->stacksize >= 0 ? info->stacksize : 0,
+            NULL, FALSE, get_elf_backend_data (output_bfd)->collect, &bh)))
+       return FALSE;
+
+      h = (struct elf_link_hash_entry *) bh;
+      h->def_regular = 1;
+      h->type = STT_OBJECT;
+    }
+
+  return TRUE;
+}
+
 /* Set up the sizes and contents of the ELF dynamic sections.  This is
    called by the ELF linker emulation before_allocation routine.  We
    must set the sizes of the sections before the linker sets the
@@ -5529,6 +5646,26 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
     return TRUE;
 
   bed = get_elf_backend_data (output_bfd);
+
+  /* Any syms created from now on start with -1 in
+     got.refcount/offset and plt.refcount/offset.  */
+  elf_hash_table (info)->init_got_refcount
+    = elf_hash_table (info)->init_got_offset;
+  elf_hash_table (info)->init_plt_refcount
+    = elf_hash_table (info)->init_plt_offset;
+
+  if (info->relocatable
+      && !_bfd_elf_size_group_sections (info))
+    return FALSE;
+
+  /* The backend may have to create some sections regardless of whether
+     we're dynamic or not.  */
+  if (bed->elf_backend_always_size_sections
+      && ! (*bed->elf_backend_always_size_sections) (output_bfd, info))
+    return FALSE;
+
+  /* Determine any GNU_STACK segment requirements, after the backend
+     has had a chance to set a default segment size.  */
   if (info->execstack)
     elf_tdata (output_bfd)->stack_flags = PF_R | PF_W | PF_X;
   else if (info->noexecstack)
@@ -5558,43 +5695,16 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
          else if (bed->default_execstack)
            exec = PF_X;
        }
-      if (notesec)
-       {
-         elf_tdata (output_bfd)->stack_flags = PF_R | PF_W | exec;
-         if (exec && info->relocatable
-             && notesec->output_section != bfd_abs_section_ptr)
-           notesec->output_section->flags |= SEC_CODE;
-       }
+      if (notesec || info->stacksize > 0)
+       elf_tdata (output_bfd)->stack_flags = PF_R | PF_W | exec;
+      if (notesec && exec && info->relocatable
+         && notesec->output_section != bfd_abs_section_ptr)
+       notesec->output_section->flags |= SEC_CODE;
     }
 
-  /* Any syms created from now on start with -1 in
-     got.refcount/offset and plt.refcount/offset.  */
-  elf_hash_table (info)->init_got_refcount
-    = elf_hash_table (info)->init_got_offset;
-  elf_hash_table (info)->init_plt_refcount
-    = elf_hash_table (info)->init_plt_offset;
-
-  if (info->relocatable
-      && !_bfd_elf_size_group_sections (info))
-    return FALSE;
-
-  /* The backend may have to create some sections regardless of whether
-     we're dynamic or not.  */
-  if (bed->elf_backend_always_size_sections
-      && ! (*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;
@@ -5604,7 +5714,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
       asection *s;
       bfd_boolean all_defined;
 
-      *sinterpptr = bfd_get_section_by_name (dynobj, ".interp");
+      *sinterpptr = bfd_get_linker_section (dynobj, ".interp");
       BFD_ASSERT (*sinterpptr != NULL || !info->executable);
 
       if (soname != NULL)
@@ -5626,19 +5736,16 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
       if (rpath != NULL)
        {
          bfd_size_type indx;
+         bfd_vma tag;
 
          indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, rpath,
                                      TRUE);
-         if (indx == (bfd_size_type) -1
-             || !_bfd_elf_add_dynamic_entry (info, DT_RPATH, indx))
+         if (indx == (bfd_size_type) -1)
            return FALSE;
 
-         if  (info->new_dtags)
-           {
-             _bfd_elf_strtab_addref (elf_hash_table (info)->dynstr, indx);
-             if (!_bfd_elf_add_dynamic_entry (info, DT_RUNPATH, indx))
-               return FALSE;
-           }
+         tag = info->new_dtags ? DT_RUNPATH : DT_RPATH;
+         if (!_bfd_elf_add_dynamic_entry (info, tag, indx))
+           return FALSE;
        }
 
       if (filter_shlib != NULL)
@@ -5872,7 +5979,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
            return FALSE;
        }
 
-      dynstr = bfd_get_section_by_name (dynobj, ".dynstr");
+      dynstr = bfd_get_linker_section (dynobj, ".dynstr");
       /* If .dynstr is excluded from the link, we don't want any of
         these tags.  Strictly, we should be checking each section
         individually;  This quick check covers for the case where
@@ -5897,18 +6004,22 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
 
   /* 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;
       asection *s;
 
       /* Set up the version definition section.  */
-      s = bfd_get_section_by_name (dynobj, ".gnu.version_d");
+      s = bfd_get_linker_section (dynobj, ".gnu.version_d");
       BFD_ASSERT (s != NULL);
 
       /* We may have created additional version definitions if we are
@@ -6171,7 +6282,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
 
       /* Work out the size of the version reference section.  */
 
-      s = bfd_get_section_by_name (dynobj, ".gnu.version_r");
+      s = bfd_get_linker_section (dynobj, ".gnu.version_r");
       BFD_ASSERT (s != NULL);
       {
        struct elf_find_verdep_info sinfo;
@@ -6283,7 +6394,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
          || _bfd_elf_link_renumber_dynsyms (output_bfd, info,
                                             &section_sym_count) == 0)
        {
-         s = bfd_get_section_by_name (dynobj, ".gnu.version");
+         s = bfd_get_linker_section (dynobj, ".gnu.version");
          s->flags |= SEC_EXCLUDE;
        }
     }
@@ -6367,7 +6478,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
                                                    &section_sym_count);
 
       /* Work out the size of the symbol version section.  */
-      s = bfd_get_section_by_name (dynobj, ".gnu.version");
+      s = bfd_get_linker_section (dynobj, ".gnu.version");
       BFD_ASSERT (s != NULL);
       if (dynsymcount != 0
          && (s->flags & SEC_EXCLUDE) == 0)
@@ -6387,7 +6498,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
         the final symbol table, because until then we do not know the
         correct value to give the symbols.  We built the .dynstr
         section as we went along in elf_link_add_object_symbols.  */
-      s = bfd_get_section_by_name (dynobj, ".dynsym");
+      s = bfd_get_linker_section (dynobj, ".dynsym");
       BFD_ASSERT (s != NULL);
       s->size = dynsymcount * bed->s->sizeof_sym;
 
@@ -6445,7 +6556,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
 
          elf_hash_table (info)->bucketcount = bucketcount;
 
-         s = bfd_get_section_by_name (dynobj, ".hash");
+         s = bfd_get_linker_section (dynobj, ".hash");
          BFD_ASSERT (s != NULL);
          hash_entry_size = elf_section_data (s)->this_hdr.sh_entsize;
          s->size = ((2 + bucketcount + dynsymcount) * hash_entry_size);
@@ -6499,7 +6610,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
              return FALSE;
            }
 
-         s = bfd_get_section_by_name (dynobj, ".gnu.hash");
+         s = bfd_get_linker_section (dynobj, ".gnu.hash");
          BFD_ASSERT (s != NULL);
 
          if (cinfo.nsyms == 0)
@@ -6627,7 +6738,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
            }
        }
 
-      s = bfd_get_section_by_name (dynobj, ".dynstr");
+      s = bfd_get_linker_section (dynobj, ".dynstr");
       BFD_ASSERT (s != NULL);
 
       elf_finalize_dynstr (output_bfd, info);
@@ -6803,7 +6914,8 @@ _bfd_elf_link_hash_hide_symbol (struct bfd_link_info *info,
     }
 }
 
-/* Initialize an ELF linker hash table.  */
+/* Initialize an ELF linker hash table.  *TABLE has been zeroed by our
+   caller.  */
 
 bfd_boolean
 _bfd_elf_link_hash_table_init
@@ -6818,7 +6930,6 @@ _bfd_elf_link_hash_table_init
   bfd_boolean ret;
   int can_refcount = get_elf_backend_data (abfd)->can_refcount;
 
-  memset (table, 0, sizeof * table);
   table->init_got_refcount.refcount = can_refcount - 1;
   table->init_plt_refcount.refcount = can_refcount - 1;
   table->init_got_offset.offset = -(bfd_vma) 1;
@@ -6842,7 +6953,7 @@ _bfd_elf_link_hash_table_create (bfd *abfd)
   struct elf_link_hash_table *ret;
   bfd_size_type amt = sizeof (struct elf_link_hash_table);
 
-  ret = (struct elf_link_hash_table *) bfd_malloc (amt);
+  ret = (struct elf_link_hash_table *) bfd_zmalloc (amt);
   if (ret == NULL)
     return NULL;
 
@@ -6857,6 +6968,18 @@ _bfd_elf_link_hash_table_create (bfd *abfd)
   return &ret->root;
 }
 
+/* Destroy an ELF linker hash table.  */
+
+void
+_bfd_elf_link_hash_table_free (struct bfd_link_hash_table *hash)
+{
+  struct elf_link_hash_table *htab = (struct elf_link_hash_table *) hash;
+  if (htab->dynstr != NULL)
+    _bfd_elf_strtab_free (htab->dynstr);
+  _bfd_merge_sections_free (htab->merge_info);
+  _bfd_generic_link_hash_table_free (hash);
+}
+
 /* This is a hook for the ELF emulation code in the generic linker to
    tell the backend linker what file name to use for the DT_NEEDED
    entry for a dynamic object.  */
@@ -7400,6 +7523,8 @@ struct elf_final_link_info
   size_t symbuf_size;
   /* And same for symshndxbuf.  */
   size_t shndxbuf_size;
+  /* Number of STT_FILE syms seen.  */
+  size_t filesym_count;
 };
 
 /* This struct is used to pass information to elf_link_output_extsym.  */
@@ -7408,6 +7533,8 @@ struct elf_outext_info
 {
   bfd_boolean failed;
   bfd_boolean localsyms;
+  bfd_boolean need_second_pass;
+  bfd_boolean second_pass;
   struct elf_final_link_info *flinfo;
 };
 
@@ -7790,31 +7917,49 @@ get_value (bfd_vma size,
           bfd *input_bfd,
           bfd_byte *location)
 {
+  int shift;
   bfd_vma x = 0;
 
+  /* Sanity checks.  */
+  BFD_ASSERT (chunksz <= sizeof (x)
+             && size >= chunksz
+             && chunksz != 0
+             && (size % chunksz) == 0
+             && input_bfd != NULL
+             && location != NULL);
+
+  if (chunksz == sizeof (x))
+    {
+      BFD_ASSERT (size == chunksz);
+
+      /* Make sure that we do not perform an undefined shift operation.
+        We know that size == chunksz so there will only be one iteration
+        of the loop below.  */
+      shift = 0;
+    }
+  else
+    shift = 8 * chunksz;
+
   for (; size; size -= chunksz, location += chunksz)
     {
       switch (chunksz)
        {
-       default:
-       case 0:
-         abort ();
        case 1:
-         x = (x << (8 * chunksz)) | bfd_get_8 (input_bfd, location);
+         x = (x << shift) | bfd_get_8 (input_bfd, location);
          break;
        case 2:
-         x = (x << (8 * chunksz)) | bfd_get_16 (input_bfd, location);
+         x = (x << shift) | bfd_get_16 (input_bfd, location);
          break;
        case 4:
-         x = (x << (8 * chunksz)) | bfd_get_32 (input_bfd, location);
+         x = (x << shift) | bfd_get_32 (input_bfd, location);
          break;
-       case 8:
 #ifdef BFD64
-         x = (x << (8 * chunksz)) | bfd_get_64 (input_bfd, location);
-#else
-         abort ();
-#endif
+       case 8:
+         x = (x << shift) | bfd_get_64 (input_bfd, location);
          break;
+#endif
+       default:
+         abort ();
        }
     }
   return x;
@@ -8435,6 +8580,10 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info,
   if (!is_elf_hash_table (info->hash))
     return FALSE;
 
+  /* Check indirect symbol.  */
+  while (h->root.type == bfd_link_hash_indirect)
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
   switch (h->root.type)
     {
     default:
@@ -8602,6 +8751,11 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
     {
       if (!h->forced_local)
        return TRUE;
+      if (eoinfo->second_pass
+         && !((h->root.type == bfd_link_hash_defined
+               || h->root.type == bfd_link_hash_defweak)
+              && h->root.u.def.section->output_section != NULL))
+       return TRUE;
     }
   else
     {
@@ -8654,11 +8808,16 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
       && h->ref_dynamic
       && h->def_regular
       && !h->dynamic_def
-      && !h->dynamic_weak
+      && h->ref_dynamic_nonweak
       && !elf_link_check_versioned_symbol (flinfo->info, bed, h))
     {
       bfd *def_bfd;
       const char *msg;
+      struct elf_link_hash_entry *hi = h;
+
+      /* Check indirect symbol.  */
+      while (hi->root.type == bfd_link_hash_indirect)
+       hi = (struct elf_link_hash_entry *) hi->root.u.i.link;
 
       if (ELF_ST_VISIBILITY (h->other) == STV_INTERNAL)
        msg = _("%B: internal symbol `%s' in %B is referenced by DSO");
@@ -8667,8 +8826,8 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
       else
        msg = _("%B: local symbol `%s' in %B is referenced by DSO");
       def_bfd = flinfo->output_bfd;
-      if (h->root.u.def.section != bfd_abs_section_ptr)
-       def_bfd = h->root.u.def.section->owner;
+      if (hi->root.u.def.section != bfd_abs_section_ptr)
+       def_bfd = hi->root.u.def.section->owner;
       (*_bfd_error_handler) (msg, flinfo->output_bfd, def_bfd,
                             h->root.root.string);
       bfd_set_error (bfd_error_bad_value);
@@ -8727,7 +8886,8 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
       /* Turn off visibility on local symbol.  */
       sym.st_other &= ~ELF_ST_VISIBILITY (-1);
     }
-  else if (h->unique_global)
+  /* Set STB_GNU_UNIQUE only if symbol is defined in regular object.  */
+  else if (h->unique_global && h->def_regular)
     sym.st_info = ELF_ST_INFO (STB_GNU_UNIQUE, h->type);
   else if (h->root.type == bfd_link_hash_undefweak
           || h->root.type == bfd_link_hash_defweak)
@@ -8756,6 +8916,19 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
        input_sec = h->root.u.def.section;
        if (input_sec->output_section != NULL)
          {
+           if (eoinfo->localsyms && flinfo->filesym_count == 1)
+             {
+               bfd_boolean second_pass_sym
+                 = (input_sec->owner == flinfo->output_bfd
+                    || input_sec->owner == NULL
+                    || (input_sec->flags & SEC_LINKER_CREATED) != 0
+                    || (input_sec->owner->flags & BFD_LINKER_CREATED) != 0);
+
+               eoinfo->need_second_pass |= second_pass_sym;
+               if (eoinfo->second_pass != second_pass_sym)
+                 return TRUE;
+             }
+
            sym.st_shndx =
              _bfd_elf_section_from_bfd_section (flinfo->output_bfd,
                                                 input_sec->output_section);
@@ -8905,6 +9078,23 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
     {
       bfd_byte *esym;
 
+      /* Since there is no version information in the dynamic string,
+        if there is no version info in symbol version section, we will
+        have a run-time problem.  */
+      if (h->verinfo.verdef == NULL)
+       {
+         char *p = strrchr (h->root.root.string, ELF_VER_CHR);
+
+         if (p && p [1] != '\0')
+           {
+             (*_bfd_error_handler)
+               (_("%B: No symbol version section for versioned symbol `%s'"),
+                flinfo->output_bfd, h->root.root.string);
+             eoinfo->failed = TRUE;
+             return FALSE;
+           }
+       }
+
       sym.st_name = h->dynstr_index;
       esym = flinfo->dynsym_sec->contents + h->dynindx * bed->s->sizeof_sym;
       if (!check_dynsym (flinfo->output_bfd, &sym))
@@ -9108,6 +9298,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
   bfd_size_type address_size;
   bfd_vma r_type_mask;
   int r_sym_shift;
+  bfd_boolean have_file_sym = FALSE;
 
   output_bfd = flinfo->output_bfd;
   bed = get_elf_backend_data (output_bfd);
@@ -9243,6 +9434,29 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
              && bfd_is_local_label_name (input_bfd, name)))
        continue;
 
+      if (ELF_ST_TYPE (isym->st_info) == STT_FILE)
+       {
+         have_file_sym = TRUE;
+         flinfo->filesym_count += 1;
+       }
+      if (!have_file_sym)
+       {
+         /* In the absence of debug info, bfd_find_nearest_line uses
+            FILE symbols to determine the source file for local
+            function symbols.  Provide a FILE symbol here if input
+            files lack such, so that their symbols won't be
+            associated with a previous input file.  It's not the
+            source file, but the best we can do.  */
+         have_file_sym = TRUE;
+         flinfo->filesym_count += 1;
+         memset (&osym, 0, sizeof (osym));
+         osym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FILE);
+         osym.st_shndx = SHN_ABS;
+         if (!elf_link_output_sym (flinfo, input_bfd->filename, &osym,
+                                   bfd_abs_section_ptr, NULL))
+           return FALSE;
+       }
+
       osym = *isym;
 
       /* Adjust the section index for the output file.  */
@@ -10236,6 +10450,42 @@ elf_fixup_link_order (bfd *abfd, asection *o)
   return TRUE;
 }
 
+static void
+elf_final_link_free (bfd *obfd, struct elf_final_link_info *flinfo)
+{
+  asection *o;
+
+  if (flinfo->symstrtab != NULL)
+    _bfd_stringtab_free (flinfo->symstrtab);
+  if (flinfo->contents != NULL)
+    free (flinfo->contents);
+  if (flinfo->external_relocs != NULL)
+    free (flinfo->external_relocs);
+  if (flinfo->internal_relocs != NULL)
+    free (flinfo->internal_relocs);
+  if (flinfo->external_syms != NULL)
+    free (flinfo->external_syms);
+  if (flinfo->locsym_shndx != NULL)
+    free (flinfo->locsym_shndx);
+  if (flinfo->internal_syms != NULL)
+    free (flinfo->internal_syms);
+  if (flinfo->indices != NULL)
+    free (flinfo->indices);
+  if (flinfo->sections != NULL)
+    free (flinfo->sections);
+  if (flinfo->symbuf != NULL)
+    free (flinfo->symbuf);
+  if (flinfo->symshndxbuf != NULL)
+    free (flinfo->symshndxbuf);
+  for (o = obfd->sections; o != NULL; o = o->next)
+    {
+      struct bfd_elf_section_data *esdo = elf_section_data (o);
+      if ((o->flags & SEC_RELOC) != 0 && esdo->rel.hashes != NULL)
+       free (esdo->rel.hashes);
+      if ((o->flags & SEC_RELOC) != 0 && esdo->rela.hashes != NULL)
+       free (esdo->rela.hashes);
+    }
+}
 
 /* Do the final step of an ELF link.  */
 
@@ -10296,10 +10546,10 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
     }
   else
     {
-      flinfo.dynsym_sec = bfd_get_section_by_name (dynobj, ".dynsym");
-      flinfo.hash_sec = bfd_get_section_by_name (dynobj, ".hash");
+      flinfo.dynsym_sec = bfd_get_linker_section (dynobj, ".dynsym");
+      flinfo.hash_sec = bfd_get_linker_section (dynobj, ".hash");
       /* Note that dynsym_sec can be NULL (on VMS).  */
-      flinfo.symver_sec = bfd_get_section_by_name (dynobj, ".gnu.version");
+      flinfo.symver_sec = bfd_get_linker_section (dynobj, ".gnu.version");
       /* Note that it is OK if symver_sec is NULL.  */
     }
 
@@ -10315,6 +10565,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
   flinfo.symshndxbuf = NULL;
   flinfo.symbuf_count = 0;
   flinfo.shndxbuf_size = 0;
+  flinfo.filesym_count = 0;
 
   /* The object attributes have been merged.  Remove the input
      sections from the link, and set the contents of the output
@@ -10789,6 +11040,17 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
          }
     }
 
+  /* Output a FILE symbol so that following locals are not associated
+     with the wrong input file.  */
+  memset (&elfsym, 0, sizeof (elfsym));
+  elfsym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FILE);
+  elfsym.st_shndx = SHN_ABS;
+
+  if (flinfo.filesym_count > 1
+      && !elf_link_output_sym (&flinfo, NULL, &elfsym,
+                              bfd_und_section_ptr, NULL))
+    return FALSE;
+
   /* Output any global symbols that got converted to local in a
      version script or due to symbol visibility.  We do this in a
      separate step since ELF requires all local symbols to appear
@@ -10798,10 +11060,25 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
   eoinfo.failed = FALSE;
   eoinfo.flinfo = &flinfo;
   eoinfo.localsyms = TRUE;
+  eoinfo.need_second_pass = FALSE;
+  eoinfo.second_pass = FALSE;
   bfd_hash_traverse (&info->hash->table, elf_link_output_extsym, &eoinfo);
   if (eoinfo.failed)
     return FALSE;
 
+  if (flinfo.filesym_count == 1
+      && !elf_link_output_sym (&flinfo, NULL, &elfsym,
+                              bfd_und_section_ptr, NULL))
+    return FALSE;
+
+  if (eoinfo.need_second_pass)
+    {
+      eoinfo.second_pass = TRUE;
+      bfd_hash_traverse (&info->hash->table, elf_link_output_extsym, &eoinfo);
+      if (eoinfo.failed)
+       return FALSE;
+    }
+
   /* If backend needs to output some local symbols not present in the hash
      table, do it now.  */
   if (bed->elf_backend_output_arch_local_syms)
@@ -11001,7 +11278,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
       bfd_byte *dyncon, *dynconend;
 
       /* Fix up .dynamic entries.  */
-      o = bfd_get_section_by_name (dynobj, ".dynamic");
+      o = bfd_get_linker_section (dynobj, ".dynamic");
       BFD_ASSERT (o != NULL);
 
       dyncon = o->contents;
@@ -11177,7 +11454,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
       /* Check for DT_TEXTREL (late, in case the backend removes it).  */
       if (((info->warn_shared_textrel && info->shared)
           || info->error_textrel)
-         && (o = bfd_get_section_by_name (dynobj, ".dynamic")) != NULL)
+         && (o = bfd_get_linker_section (dynobj, ".dynamic")) != NULL)
        {
          bfd_byte *dyncon, *dynconend;
 
@@ -11218,9 +11495,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
            continue;
          if (elf_hash_table (info)->eh_info.hdr_sec == o)
            continue;
-         if ((elf_section_data (o->output_section)->this_hdr.sh_type
-              != SHT_STRTAB)
-             && (strcmp (bfd_get_section_name (abfd, o), ".dynstr") != 0))
+         if (strcmp (o->name, ".dynstr") != 0)
            {
              /* FIXME: octets_per_byte.  */
              if (! bfd_set_section_contents (abfd, o->output_section,
@@ -11258,42 +11533,10 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
        goto error_return;
     }
 
-  if (info->eh_frame_hdr)
-    {
-      if (! _bfd_elf_write_section_eh_frame_hdr (abfd, info))
-       goto error_return;
-    }
+  if (! _bfd_elf_write_section_eh_frame_hdr (abfd, info))
+    goto error_return;
 
-  if (flinfo.symstrtab != NULL)
-    _bfd_stringtab_free (flinfo.symstrtab);
-  if (flinfo.contents != NULL)
-    free (flinfo.contents);
-  if (flinfo.external_relocs != NULL)
-    free (flinfo.external_relocs);
-  if (flinfo.internal_relocs != NULL)
-    free (flinfo.internal_relocs);
-  if (flinfo.external_syms != NULL)
-    free (flinfo.external_syms);
-  if (flinfo.locsym_shndx != NULL)
-    free (flinfo.locsym_shndx);
-  if (flinfo.internal_syms != NULL)
-    free (flinfo.internal_syms);
-  if (flinfo.indices != NULL)
-    free (flinfo.indices);
-  if (flinfo.sections != NULL)
-    free (flinfo.sections);
-  if (flinfo.symbuf != NULL)
-    free (flinfo.symbuf);
-  if (flinfo.symshndxbuf != NULL)
-    free (flinfo.symshndxbuf);
-  for (o = abfd->sections; o != NULL; o = o->next)
-    {
-      struct bfd_elf_section_data *esdo = elf_section_data (o);
-      if ((o->flags & SEC_RELOC) != 0 && esdo->rel.hashes != NULL)
-       free (esdo->rel.hashes);
-      if ((o->flags & SEC_RELOC) != 0 && esdo->rela.hashes != NULL)
-       free (esdo->rela.hashes);
-    }
+  elf_final_link_free (abfd, &flinfo);
 
   elf_tdata (abfd)->linker = TRUE;
 
@@ -11310,37 +11553,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
   return TRUE;
 
  error_return:
-  if (flinfo.symstrtab != NULL)
-    _bfd_stringtab_free (flinfo.symstrtab);
-  if (flinfo.contents != NULL)
-    free (flinfo.contents);
-  if (flinfo.external_relocs != NULL)
-    free (flinfo.external_relocs);
-  if (flinfo.internal_relocs != NULL)
-    free (flinfo.internal_relocs);
-  if (flinfo.external_syms != NULL)
-    free (flinfo.external_syms);
-  if (flinfo.locsym_shndx != NULL)
-    free (flinfo.locsym_shndx);
-  if (flinfo.internal_syms != NULL)
-    free (flinfo.internal_syms);
-  if (flinfo.indices != NULL)
-    free (flinfo.indices);
-  if (flinfo.sections != NULL)
-    free (flinfo.sections);
-  if (flinfo.symbuf != NULL)
-    free (flinfo.symbuf);
-  if (flinfo.symshndxbuf != NULL)
-    free (flinfo.symshndxbuf);
-  for (o = abfd->sections; o != NULL; o = o->next)
-    {
-      struct bfd_elf_section_data *esdo = elf_section_data (o);
-      if ((o->flags & SEC_RELOC) != 0 && esdo->rel.hashes != NULL)
-       free (esdo->rel.hashes);
-      if ((o->flags & SEC_RELOC) != 0 && esdo->rela.hashes != NULL)
-       free (esdo->rela.hashes);
-    }
-
+  elf_final_link_free (abfd, &flinfo);
   return FALSE;
 }
 \f
@@ -11518,7 +11731,7 @@ _bfd_elf_gc_mark_hook (asection *sec,
          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);
@@ -12002,12 +12215,14 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
       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);
@@ -12273,7 +12488,7 @@ bfd_elf_lookup_section_flags (struct bfd_link_info *info,
            }
          if (!tf->valid)
            {
-             info->callbacks->einfo 
+             info->callbacks->einfo
                (_("Unrecognized INPUT_SECTION_FLAG %s\n"), tf->name);
              return FALSE;
            }
@@ -12741,7 +12956,7 @@ get_dynamic_reloc_section_name (bfd *       abfd,
     return NULL;
 
   name = bfd_alloc (abfd, strlen (prefix) + strlen (old_name) + 1);
-  sprintf (name, "%s%s", prefix, old_name); 
+  sprintf (name, "%s%s", prefix, old_name);
 
   return name;
 }
@@ -12764,7 +12979,7 @@ _bfd_elf_get_dynamic_reloc_section (bfd *       abfd,
 
       if (name != NULL)
        {
-         reloc_sec = bfd_get_section_by_name (abfd, name);
+         reloc_sec = bfd_get_linker_section (abfd, name);
 
          if (reloc_sec != NULL)
            elf_section_data (sec)->sreloc = reloc_sec;
@@ -12800,17 +13015,16 @@ _bfd_elf_make_dynamic_reloc_section (asection *         sec,
       if (name == NULL)
        return NULL;
 
-      reloc_sec = bfd_get_section_by_name (dynobj, name);
+      reloc_sec = bfd_get_linker_section (dynobj, name);
 
       if (reloc_sec == NULL)
        {
-         flagword flags;
-
-         flags = (SEC_HAS_CONTENTS | SEC_READONLY | SEC_IN_MEMORY | SEC_LINKER_CREATED);
+         flagword flags = (SEC_HAS_CONTENTS | SEC_READONLY
+                           | SEC_IN_MEMORY | SEC_LINKER_CREATED);
          if ((sec->flags & SEC_ALLOC) != 0)
            flags |= SEC_ALLOC | SEC_LOAD;
 
-         reloc_sec = bfd_make_section_with_flags (dynobj, name, flags);
+         reloc_sec = bfd_make_section_anyway_with_flags (dynobj, name, flags);
          if (reloc_sec != NULL)
            {
              if (! bfd_set_section_alignment (dynobj, reloc_sec, alignment))
@@ -12856,5 +13070,5 @@ elf_append_rel (bfd *abfd, asection *s, Elf_Internal_Rela *rel)
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   bfd_byte *loc = s->contents + (s->reloc_count++ * bed->s->sizeof_rel);
   BFD_ASSERT (loc + bed->s->sizeof_rel <= s->contents + s->size);
-  bed->s->swap_reloca_out (abfd, rel, loc);
+  bed->s->swap_reloc_out (abfd, rel, loc);
 }
This page took 0.045827 seconds and 4 git commands to generate.