daily update
[deliverable/binutils-gdb.git] / bfd / elflink.c
index ee6288ad0762846e8954d49a488e8d37087175e5..99b7ca1c2243a1a1b3a088d9f5b27ce685ea2289 100644 (file)
@@ -1,7 +1,5 @@
 /* ELF linking support for BFD.
-   Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-   2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
-   Free Software Foundation, Inc.
+   Copyright 1995-2013 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -87,7 +85,8 @@ _bfd_elf_define_linkage_sym (bfd *abfd,
   h->def_regular = 1;
   h->non_elf = 0;
   h->type = STT_OBJECT;
-  h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN;
+  if (ELF_ST_VISIBILITY (h->other) != STV_INTERNAL)
+    h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN;
 
   bed = get_elf_backend_data (abfd);
   (*bed->elf_backend_hide_symbol) (info, h, TRUE);
@@ -575,7 +574,8 @@ bfd_elf_record_link_assignment (bfd *output_bfd,
   if (hidden)
     {
       bed = get_elf_backend_data (output_bfd);
-      h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN;
+      if (ELF_ST_VISIBILITY (h->other) != STV_INTERNAL)
+       h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN;
       (*bed->elf_backend_hide_symbol) (info, h, TRUE);
     }
 
@@ -895,55 +895,30 @@ elf_merge_st_other (bfd *abfd, struct elf_link_hash_entry *h,
     }
 }
 
-/* Mark if a symbol has a definition in a dynamic object or is
-   weak in all dynamic objects.  */
+/* This function is called when we want to merge a new symbol with an
+   existing symbol.  It handles the various cases which arise when we
+   find a definition in a dynamic object, or when there is already a
+   definition in a dynamic object.  The new symbol is described by
+   NAME, SYM, PSEC, and PVALUE.  We set SYM_HASH to the hash table
+   entry.  We set POLDBFD to the old symbol's BFD.  We set POLD_WEAK
+   if the old symbol was weak.  We set POLD_ALIGNMENT to the alignment
+   of an old common symbol.  We set OVERRIDE if the old symbol is
+   overriding a new definition.  We set TYPE_CHANGE_OK if it is OK for
+   the type to change.  We set SIZE_CHANGE_OK if it is OK for the size
+   to change.  By OK to change, we mean that we shouldn't warn if the
+   type or size does change.  */
 
-static void
-_bfd_elf_mark_dynamic_def_weak (struct elf_link_hash_entry *h,
-                               asection *sec, int bind)
-{
-  if (!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;
-       }
-    }
-}
-
-/* This function is called when we want to define a new symbol.  It
-   handles the various cases which arise when we find a definition in
-   a dynamic object, or when there is already a definition in a
-   dynamic object.  The new symbol is described by NAME, SYM, PSEC,
-   and PVALUE.  We set SYM_HASH to the hash table entry.  We set
-   OVERRIDE if the old symbol is overriding a new definition.  We set
-   TYPE_CHANGE_OK if it is OK for the type to change.  We set
-   SIZE_CHANGE_OK if it is OK for the size to change.  By OK to
-   change, we mean that we shouldn't warn if the type or size does
-   change.  We set POLD_ALIGNMENT if an old common symbol in a dynamic
-   object is overridden by a regular object.  */
-
-bfd_boolean
+static bfd_boolean
 _bfd_elf_merge_symbol (bfd *abfd,
                       struct bfd_link_info *info,
                       const char *name,
                       Elf_Internal_Sym *sym,
                       asection **psec,
                       bfd_vma *pvalue,
+                      struct elf_link_hash_entry **sym_hash,
+                      bfd **poldbfd,
                       bfd_boolean *pold_weak,
                       unsigned int *pold_alignment,
-                      struct elf_link_hash_entry **sym_hash,
                       bfd_boolean *skip,
                       bfd_boolean *override,
                       bfd_boolean *type_change_ok,
@@ -965,15 +940,6 @@ _bfd_elf_merge_symbol (bfd *abfd,
   sec = *psec;
   bind = ELF_ST_BIND (sym->st_info);
 
-  /* Silently discard TLS symbols from --just-syms.  There's no way to
-     combine a static TLS block with a new TLS block for this executable.  */
-  if (ELF_ST_TYPE (sym->st_info) == STT_TLS
-      && sec->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
-    {
-      *skip = TRUE;
-      return TRUE;
-    }
-
   if (! bfd_is_und_section (sec))
     h = elf_link_hash_lookup (elf_hash_table (info), name, TRUE, FALSE, FALSE);
   else
@@ -985,11 +951,6 @@ _bfd_elf_merge_symbol (bfd *abfd,
 
   bed = get_elf_backend_data (abfd);
 
-  /* This code is for coping with dynamic objects, and is only useful
-     if we are doing an ELF link.  */
-  if (!(*bed->relocs_compatible) (abfd->xvec, info->output_bfd->xvec))
-    return TRUE;
-
   /* For merging, we only care about real symbols.  But we need to make
      sure that indirect symbol dynamic flags are updated.  */
   hi = h;
@@ -997,35 +958,19 @@ _bfd_elf_merge_symbol (bfd *abfd,
         || 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
-     symbols.  */
-  bfd_elf_link_mark_dynamic_symbol (info, h, sym);
-
-  /* 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.  */
-
-  if (h->root.type == bfd_link_hash_new)
-    {
-      h->non_elf = 0;
-      return TRUE;
-    }
-
   /* OLDBFD and OLDSEC are a BFD and an ASECTION associated with the
      existing symbol.  */
 
+  oldbfd = NULL;
+  oldsec = NULL;
   switch (h->root.type)
     {
     default:
-      oldbfd = NULL;
-      oldsec = NULL;
       break;
 
     case bfd_link_hash_undefined:
     case bfd_link_hash_undefweak:
       oldbfd = h->root.u.undef.abfd;
-      oldsec = NULL;
       break;
 
     case bfd_link_hash_defined:
@@ -1037,8 +982,12 @@ _bfd_elf_merge_symbol (bfd *abfd,
     case bfd_link_hash_common:
       oldbfd = h->root.u.c.p->section->owner;
       oldsec = h->root.u.c.p->section;
+      if (pold_alignment)
+       *pold_alignment = h->root.u.c.p->alignment_power;
       break;
     }
+  if (poldbfd && *poldbfd == NULL)
+    *poldbfd = oldbfd;
 
   /* Differentiate strong and weak symbols.  */
   newweak = bind == STB_WEAK;
@@ -1047,6 +996,55 @@ _bfd_elf_merge_symbol (bfd *abfd,
   if (pold_weak)
     *pold_weak = oldweak;
 
+  /* This code is for coping with dynamic objects, and is only useful
+     if we are doing an ELF link.  */
+  if (!(*bed->relocs_compatible) (abfd->xvec, info->output_bfd->xvec))
+    return TRUE;
+
+  /* We have to check it for every instance since the first few may be
+     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.  */
+
+  if (h->root.type == bfd_link_hash_new)
+    {
+      h->non_elf = 0;
+      return TRUE;
+    }
+
   /* In cases involving weak versioned symbols, we may wind up trying
      to merge a symbol with itself.  Catch that here, to avoid the
      confusion that results if we try to override a symbol with
@@ -1059,11 +1057,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;
@@ -1148,35 +1141,29 @@ _bfd_elf_merge_symbol (bfd *abfd,
 
       if (tdef && ntdef)
        (*_bfd_error_handler)
-         (_("%s: TLS definition in %B section %A mismatches non-TLS definition in %B section %A"),
+         (_("%s: TLS definition in %B section %A "
+            "mismatches non-TLS definition in %B section %A"),
           tbfd, tsec, ntbfd, ntsec, h->root.root.string);
       else if (!tdef && !ntdef)
        (*_bfd_error_handler)
-         (_("%s: TLS reference in %B mismatches non-TLS reference in %B"),
+         (_("%s: TLS reference in %B "
+            "mismatches non-TLS reference in %B"),
           tbfd, ntbfd, h->root.root.string);
       else if (tdef)
        (*_bfd_error_handler)
-         (_("%s: TLS definition in %B section %A mismatches non-TLS reference in %B"),
+         (_("%s: TLS definition in %B section %A "
+            "mismatches non-TLS reference in %B"),
           tbfd, tsec, ntbfd, h->root.root.string);
       else
        (*_bfd_error_handler)
-         (_("%s: TLS reference in %B mismatches non-TLS definition in %B section %A"),
+         (_("%s: TLS reference in %B "
+            "mismatches non-TLS definition in %B section %A"),
           tbfd, ntbfd, ntsec, h->root.root.string);
 
       bfd_set_error (bfd_error_bad_value);
       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)
-    {
-      _bfd_elf_mark_dynamic_def_weak (h, sec, bind);
-      if (h != hi)
-       _bfd_elf_mark_dynamic_def_weak (hi, sec, bind);
-    }
-
   /* If the old symbol has non-default visibility, we ignore the new
      definition from a dynamic object.  */
   if (newdyn
@@ -1203,7 +1190,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
       /* If the new symbol with non-default visibility comes from a
         relocatable file and the old definition comes from a dynamic
         object, we remove the old definition.  */
-      if ((*sym_hash)->root.type == bfd_link_hash_indirect)
+      if (hi->root.type == bfd_link_hash_indirect)
        {
          /* Handle the case where the old dynamic definition is
             default versioned.  We need to copy the symbol info from
@@ -1211,13 +1198,11 @@ _bfd_elf_merge_symbol (bfd *abfd,
             was referenced before.  */
          if (h->ref_regular)
            {
-             struct elf_link_hash_entry *vh = *sym_hash;
-
-             vh->root.type = h->root.type;
+             hi->root.type = h->root.type;
              h->root.type = bfd_link_hash_indirect;
-             (*bed->elf_backend_copy_indirect_symbol) (info, vh, h);
+             (*bed->elf_backend_copy_indirect_symbol) (info, hi, h);
 
-             h->root.u.i.link = (struct bfd_link_hash_entry *) vh;
+             h->root.u.i.link = (struct bfd_link_hash_entry *) hi;
              if (ELF_ST_VISIBILITY (sym->st_other) != STV_PROTECTED)
                {
                  /* If the new symbol is hidden or internal, completely undo
@@ -1230,15 +1215,14 @@ _bfd_elf_merge_symbol (bfd *abfd,
                h->ref_dynamic = 1;
 
              h->def_dynamic = 0;
-             h->dynamic_def = 0;
              /* FIXME: Should we check type and size for protected symbol?  */
              h->size = 0;
              h->type = 0;
 
-             h = vh;
+             h = hi;
            }
          else
-           h = *sym_hash;
+           h = hi;
        }
 
       /* If the old symbol was undefined before, then it will still be
@@ -1270,16 +1254,12 @@ _bfd_elf_merge_symbol (bfd *abfd,
       else
        h->ref_dynamic = 1;
       h->def_dynamic = 0;
-      h->dynamic_def = 0;
       /* FIXME: Should we check type and size for protected symbol?  */
       h->size = 0;
       h->type = 0;
       return TRUE;
     }
 
-  if (bind == STB_GNU_UNIQUE)
-    h->unique_global = 1;
-
   /* If a new weak symbol definition comes from a regular file and the
      old symbol comes from a dynamic library, we treat the new one as
      strong.  Similarly, an old weak symbol definition from a regular
@@ -1365,15 +1345,12 @@ _bfd_elf_merge_symbol (bfd *abfd,
 
   /* We now know everything about the old and new symbols.  We ask the
      backend to check if we can merge them.  */
-  if (bed->merge_symbol
-      && !bed->merge_symbol (info, sym_hash, h, sym, psec, pvalue,
-                            pold_alignment, skip, override,
-                            type_change_ok, size_change_ok,
-                            &newdyn, &newdef, &newdyncommon, &newweak,
-                            abfd, &sec,
-                            &olddyn, &olddef, &olddyncommon, &oldweak,
-                            oldbfd, &oldsec))
-    return FALSE;
+  if (bed->merge_symbol != NULL)
+    {
+      if (!bed->merge_symbol (h, sym, psec, newdef, olddef, oldbfd, oldsec))
+       return FALSE;
+      sec = *psec;
+    }
 
   /* If both the old and the new symbols look like common symbols in a
      dynamic object, set the size of the symbol to the larger of the
@@ -1522,8 +1499,8 @@ _bfd_elf_merge_symbol (bfd *abfd,
          *type_change_ok = TRUE;
        }
 
-      if ((*sym_hash)->root.type == bfd_link_hash_indirect)
-       flip = *sym_hash;
+      if (hi->root.type == bfd_link_hash_indirect)
+       flip = hi;
       else
        /* This union may have been set to be non-NULL when this symbol
           was seen in a dynamic object.  We must force the union to be
@@ -1568,8 +1545,8 @@ _bfd_elf_merge_symbol (bfd *abfd,
       *size_change_ok = TRUE;
       *type_change_ok = TRUE;
 
-      if ((*sym_hash)->root.type == bfd_link_hash_indirect)
-       flip = *sym_hash;
+      if (hi->root.type == bfd_link_hash_indirect)
+       flip = hi;
       else
        h->verinfo.vertree = NULL;
     }
@@ -1596,7 +1573,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
 
 /* This function is called to create an indirect symbol from the
    default for the symbol with the default version if needed. The
-   symbol is described by H, NAME, SYM, PSEC, VALUE, and OVERRIDE.  We
+   symbol is described by H, NAME, SYM, SEC, and VALUE.  We
    set DYNSYM if the new indirect symbol is dynamic.  */
 
 static bfd_boolean
@@ -1605,10 +1582,10 @@ _bfd_elf_add_default_symbol (bfd *abfd,
                             struct elf_link_hash_entry *h,
                             const char *name,
                             Elf_Internal_Sym *sym,
-                            asection **psec,
-                            bfd_vma *value,
-                            bfd_boolean *dynsym,
-                            bfd_boolean override)
+                            asection *sec,
+                            bfd_vma value,
+                            bfd **poldbfd,
+                            bfd_boolean *dynsym)
 {
   bfd_boolean type_change_ok;
   bfd_boolean size_change_ok;
@@ -1619,9 +1596,10 @@ _bfd_elf_add_default_symbol (bfd *abfd,
   const struct elf_backend_data *bed;
   bfd_boolean collect;
   bfd_boolean dynamic;
+  bfd_boolean override;
   char *p;
   size_t len, shortlen;
-  asection *sec;
+  asection *tmp_sec;
 
   /* If this symbol has a version, and it is the default version, we
      create an indirect symbol from the default name to the fully
@@ -1631,24 +1609,6 @@ _bfd_elf_add_default_symbol (bfd *abfd,
   if (p == NULL || p[1] != ELF_VER_CHR)
     return TRUE;
 
-  if (override)
-    {
-      /* We are overridden by an old definition. We need to check if we
-        need to create the indirect symbol from the default name.  */
-      hi = elf_link_hash_lookup (elf_hash_table (info), name, TRUE,
-                                FALSE, FALSE);
-      BFD_ASSERT (hi != NULL);
-      if (hi == h)
-       return TRUE;
-      while (hi->root.type == bfd_link_hash_indirect
-            || hi->root.type == bfd_link_hash_warning)
-       {
-         hi = (struct elf_link_hash_entry *) hi->root.u.i.link;
-         if (hi == h)
-           return TRUE;
-       }
-    }
-
   bed = get_elf_backend_data (abfd);
   collect = bed->collect;
   dynamic = (abfd->flags & DYNAMIC) != 0;
@@ -1666,9 +1626,9 @@ _bfd_elf_add_default_symbol (bfd *abfd,
      actually going to define an indirect symbol.  */
   type_change_ok = FALSE;
   size_change_ok = FALSE;
-  sec = *psec;
-  if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &sec, value,
-                             NULL, NULL, &hi, &skip, &override,
+  tmp_sec = sec;
+  if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &tmp_sec, &value,
+                             &hi, poldbfd, NULL, NULL, &skip, &override,
                              &type_change_ok, &size_change_ok))
     return FALSE;
 
@@ -1775,9 +1735,9 @@ nondefault:
   /* Once again, merge with any existing symbol.  */
   type_change_ok = FALSE;
   size_change_ok = FALSE;
-  sec = *psec;
-  if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &sec, value,
-                             NULL, NULL, &hi, &skip, &override,
+  tmp_sec = sec;
+  if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &tmp_sec, &value,
+                             &hi, NULL, NULL, NULL, &skip, &override,
                              &type_change_ok, &size_change_ok))
     return FALSE;
 
@@ -2509,7 +2469,7 @@ _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h,
       && !h->def_regular
       && h->ref_regular
       && !h->def_dynamic
-      && (h->root.u.def.section->owner->flags & DYNAMIC) == 0)
+      && (h->root.u.def.section->owner->flags & (DYNAMIC | BFD_PLUGIN)) == 0)
     h->def_regular = 1;
 
   /* If -Bsymbolic was used (which means to bind references to global
@@ -3091,19 +3051,17 @@ 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;
@@ -3351,6 +3309,18 @@ _bfd_elf_relocs_compatible (const bfd_target *input,
   return ibed->relocs_compatible == obed->relocs_compatible;
 }
 
+/* Make a special call to the linker "notice" function to tell it that
+   we are about to handle an as-needed lib, or have finished
+   processing the lib.  */ 
+
+bfd_boolean
+_bfd_elf_notice_as_needed (bfd *ibfd,
+                          struct bfd_link_info *info,
+                          enum notice_asneeded_action act)
+{
+  return (*info->callbacks->notice) (info, NULL, ibfd, NULL, act, 0, NULL);
+}
+
 /* Add symbols from an ELF object file to the linker hash table.  */
 
 static bfd_boolean
@@ -3380,14 +3350,13 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
   unsigned int old_size = 0;
   unsigned int old_count = 0;
   void *old_tab = NULL;
-  void *old_hash;
   void *old_ent;
   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;
+  asection *s;
 
   htab = elf_hash_table (info);
   bed = get_elf_backend_data (abfd);
@@ -3429,75 +3398,64 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
      symbol.  This differs from .gnu.warning sections, which generate
      warnings when they are included in an output file.  */
   /* PR 12761: Also generate this warning when building shared libraries.  */
-  if (info->executable || info->shared)
+  for (s = abfd->sections; s != NULL; s = s->next)
     {
-      asection *s;
+      const char *name;
 
-      for (s = abfd->sections; s != NULL; s = s->next)
+      name = bfd_get_section_name (abfd, s);
+      if (CONST_STRNEQ (name, ".gnu.warning."))
        {
-         const char *name;
+         char *msg;
+         bfd_size_type sz;
+
+         name += sizeof ".gnu.warning." - 1;
 
-         name = bfd_get_section_name (abfd, s);
-         if (CONST_STRNEQ (name, ".gnu.warning."))
+         /* If this is a shared object, then look up the symbol
+            in the hash table.  If it is there, and it is already
+            been defined, then we will not be using the entry
+            from this shared object, so we don't need to warn.
+            FIXME: If we see the definition in a regular object
+            later on, we will warn, but we shouldn't.  The only
+            fix is to keep track of what warnings we are supposed
+            to emit, and then handle them all at the end of the
+            link.  */
+         if (dynamic)
            {
-             char *msg;
-             bfd_size_type sz;
-
-             name += sizeof ".gnu.warning." - 1;
-
-             /* If this is a shared object, then look up the symbol
-                in the hash table.  If it is there, and it is already
-                been defined, then we will not be using the entry
-                from this shared object, so we don't need to warn.
-                FIXME: If we see the definition in a regular object
-                later on, we will warn, but we shouldn't.  The only
-                fix is to keep track of what warnings we are supposed
-                to emit, and then handle them all at the end of the
-                link.  */
-             if (dynamic)
-               {
-                 struct elf_link_hash_entry *h;
+             struct elf_link_hash_entry *h;
 
-                 h = elf_link_hash_lookup (htab, name, FALSE, FALSE, TRUE);
+             h = elf_link_hash_lookup (htab, name, FALSE, FALSE, TRUE);
 
-                 /* FIXME: What about bfd_link_hash_common?  */
-                 if (h != NULL
-                     && (h->root.type == bfd_link_hash_defined
-                         || h->root.type == bfd_link_hash_defweak))
-                   {
-                     /* We don't want to issue this warning.  Clobber
-                        the section size so that the warning does not
-                        get copied into the output file.  */
-                     s->size = 0;
-                     continue;
-                   }
-               }
+             /* FIXME: What about bfd_link_hash_common?  */
+             if (h != NULL
+                 && (h->root.type == bfd_link_hash_defined
+                     || h->root.type == bfd_link_hash_defweak))
+               continue;
+           }
 
-             sz = s->size;
-             msg = (char *) bfd_alloc (abfd, sz + 1);
-             if (msg == NULL)
-               goto error_return;
+         sz = s->size;
+         msg = (char *) bfd_alloc (abfd, sz + 1);
+         if (msg == NULL)
+           goto error_return;
 
-             if (! bfd_get_section_contents (abfd, s, msg, 0, sz))
-               goto error_return;
+         if (! bfd_get_section_contents (abfd, s, msg, 0, sz))
+           goto error_return;
 
-             msg[sz] = '\0';
+         msg[sz] = '\0';
 
-             if (! (_bfd_generic_link_add_one_symbol
-                    (info, abfd, name, BSF_WARNING, s, 0, msg,
-                     FALSE, bed->collect, NULL)))
-               goto error_return;
+         if (! (_bfd_generic_link_add_one_symbol
+                (info, abfd, name, BSF_WARNING, s, 0, msg,
+                 FALSE, bed->collect, NULL)))
+           goto error_return;
 
-             if (! info->relocatable)
-               {
-                 /* Clobber the section size so that the warning does
-                    not get copied into the output file.  */
-                 s->size = 0;
+         if (!info->relocatable && info->executable)
+           {
+             /* Clobber the section size so that the warning does
+                not get copied into the output file.  */
+             s->size = 0;
 
-                 /* Also set SEC_EXCLUDE, so that symbols defined in
-                    the warning section don't get copied to the output.  */
-                 s->flags |= SEC_EXCLUDE;
-               }
+             /* Also set SEC_EXCLUDE, so that symbols defined in
+                the warning section don't get copied to the output.  */
+             s->flags |= SEC_EXCLUDE;
            }
        }
     }
@@ -3523,7 +3481,6 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
     goto error_return;
   else
     {
-      asection *s;
       const char *soname = NULL;
       char *audit = NULL;
       struct bfd_link_needed_list *rpath = NULL, *runpath = NULL;
@@ -3742,7 +3699,7 @@ error_free_dyn:
       extsymoff = hdr->sh_info;
     }
 
-  sym_hash = NULL;
+  sym_hash = elf_sym_hashes (abfd);
   if (extsymcount != 0)
     {
       isymbuf = bfd_elf_get_elf_syms (abfd, hdr, extsymcount, extsymoff,
@@ -3750,13 +3707,16 @@ error_free_dyn:
       if (isymbuf == NULL)
        goto error_return;
 
-      /* We store a pointer to the hash table entry for each external
-        symbol.  */
-      amt = extsymcount * sizeof (struct elf_link_hash_entry *);
-      sym_hash = (struct elf_link_hash_entry **) bfd_alloc (abfd, amt);
       if (sym_hash == NULL)
-       goto error_free_sym;
-      elf_sym_hashes (abfd) = sym_hash;
+       {
+         /* We store a pointer to the hash table entry for each
+            external symbol.  */
+         amt = extsymcount * sizeof (struct elf_link_hash_entry *);
+         sym_hash = (struct elf_link_hash_entry **) bfd_zalloc (abfd, amt);
+         if (sym_hash == NULL)
+           goto error_free_sym;
+         elf_sym_hashes (abfd) = sym_hash;
+       }
     }
 
   if (dynamic)
@@ -3806,8 +3766,7 @@ error_free_dyn:
        }
 
       tabsize = htab->root.table.size * sizeof (struct bfd_hash_entry *);
-      hashsize = extsymcount * sizeof (struct elf_link_hash_entry *);
-      old_tab = bfd_malloc (tabsize + entsize + hashsize);
+      old_tab = bfd_malloc (tabsize + entsize);
       if (old_tab == NULL)
        goto error_free_vers;
 
@@ -3819,16 +3778,13 @@ error_free_dyn:
 
       /* Make a special call to the linker "notice" function to
         tell it that we are about to handle an as-needed lib.  */
-      if (!(*info->callbacks->notice) (info, NULL, abfd, NULL,
-                                      notice_as_needed, 0, NULL))
+      if (!(*bed->notice_as_needed) (abfd, info, notice_as_needed))
        goto error_free_vers;
 
-      /* Clone the symbol table and sym hashes.  Remember some
-        pointers into the symbol table, and dynamic symbol count.  */
-      old_hash = (char *) old_tab + tabsize;
-      old_ent = (char *) old_hash + hashsize;
+      /* Clone the symbol table.  Remember some pointers into the
+        symbol table, and dynamic symbol count.  */
+      old_ent = (char *) old_tab + tabsize;
       memcpy (old_tab, htab->root.table.table, tabsize);
-      memcpy (old_hash, sym_hash, hashsize);
       old_undefs = htab->root.undefs;
       old_undefs_tail = htab->root.undefs_tail;
       old_table = htab->root.table.table;
@@ -3879,14 +3835,12 @@ error_free_dyn:
       bfd_boolean common;
       unsigned int old_alignment;
       bfd *old_bfd;
-      bfd * undef_bfd = NULL;
 
       override = FALSE;
 
       flags = BSF_NO_FLAGS;
       sec = NULL;
       value = isym->st_value;
-      *sym_hash = NULL;
       common = bed->common_definition (isym);
 
       bind = ELF_ST_BIND (isym->st_info);
@@ -3999,6 +3953,13 @@ error_free_dyn:
          goto error_free_vers;
        }
 
+      /* Silently discard TLS symbols from --just-syms.  There's
+        no way to combine a static TLS block with a new TLS block
+        for this executable.  */
+      if (ELF_ST_TYPE (isym->st_info) == STT_TLS
+         && sec->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
+       continue;
+
       if (bfd_is_und_section (sec)
          || bfd_is_com_section (sec))
        definition = FALSE;
@@ -4018,20 +3979,6 @@ error_free_dyn:
          unsigned int vernum = 0;
          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.  */
-         if (! bfd_is_und_section (sec))
-           {
-             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.u.undef.abfd)
-               undef_bfd = h->root.u.undef.abfd;
-           }
-
          if (ever == NULL)
            {
              if (info->default_imported_symver)
@@ -4139,22 +4086,9 @@ error_free_dyn:
              name = newname;
            }
 
-         /* If necessary, make a second attempt to locate the bfd
-            containing an unresolved, non-weak 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);
-
-             if (h != NULL
-                 && h->root.type == bfd_link_hash_undefined
-                 && h->root.u.undef.abfd)
-               undef_bfd = h->root.u.undef.abfd;
-           }
-
-         if (!_bfd_elf_merge_symbol (abfd, info, name, isym, &sec,
-                                     &value, &old_weak, &old_alignment,
-                                     sym_hash, &skip, &override,
+         if (!_bfd_elf_merge_symbol (abfd, info, name, isym, &sec, &value,
+                                     sym_hash, &old_bfd, &old_weak,
+                                     &old_alignment, &skip, &override,
                                      &type_change_ok, &size_change_ok))
            goto error_free_vers;
 
@@ -4169,30 +4103,7 @@ error_free_dyn:
                 || h->root.type == bfd_link_hash_warning)
            h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
-         /* Remember the old alignment if this is a common symbol, so
-            that we don't reduce the alignment later on.  We can't
-            check later, because _bfd_generic_link_add_one_symbol
-            will set a default for the alignment which we want to
-            override. We also remember the old bfd where the existing
-            definition comes from.  */
-         switch (h->root.type)
-           {
-           default:
-             break;
-
-           case bfd_link_hash_defined:
-           case bfd_link_hash_defweak:
-             old_bfd = h->root.u.def.section->owner;
-             break;
-
-           case bfd_link_hash_common:
-             old_bfd = h->root.u.c.p->section->owner;
-             old_alignment = h->root.u.c.p->alignment_power;
-             break;
-           }
-
          if (elf_tdata (abfd)->verdef != NULL
-             && ! override
              && vernum > 1
              && definition)
            h->verinfo.verdef = &elf_tdata (abfd)->verdef[vernum - 1];
@@ -4212,8 +4123,6 @@ error_free_dyn:
        h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
       *sym_hash = h;
-      if (is_elf_hash_table (htab))
-       h->unique_global = (flags & BSF_GNU_UNIQUE) != 0;
 
       new_weak = (flags & BSF_WEAK) != 0;
       new_weakdef = FALSE;
@@ -4263,7 +4172,73 @@ error_free_dyn:
 
       if (is_elf_hash_table (htab))
        {
-         bfd_boolean dynsym;
+         /* Set a flag in the hash table entry indicating the type of
+            reference or definition we just found.  A dynamic symbol
+            is one which is referenced or defined by both a regular
+            object and a shared object.  */
+         bfd_boolean dynsym = FALSE;
+
+         /* Plugin symbols aren't normal.  Don't set def_regular or
+            ref_regular for them, or make them dynamic.  */
+         if ((abfd->flags & BFD_PLUGIN) != 0)
+           ;
+         else if (! dynamic)
+           {
+             if (! definition)
+               {
+                 h->ref_regular = 1;
+                 if (bind != STB_WEAK)
+                   h->ref_regular_nonweak = 1;
+               }
+             else
+               {
+                 h->def_regular = 1;
+                 if (h->def_dynamic)
+                   {
+                     h->def_dynamic = 0;
+                     h->ref_dynamic = 1;
+                   }
+               }
+
+             /* 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;
+                 hi->ref_dynamic = 1;
+               }
+             else
+               {
+                 h->def_dynamic = 1;
+                 hi->def_dynamic = 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;
+           }
+
+         /* Check to see if we need to add an indirect symbol for
+            the default name.  */
+         if (definition
+             || (!override && h->root.type == bfd_link_hash_common))
+           if (!_bfd_elf_add_default_symbol (abfd, info, h, name, isym,
+                                             sec, value, &old_bfd, &dynsym))
+             goto error_free_vers;
 
          /* Check the alignment when a common symbol is involved. This
             can change when a common symbol is overridden by a normal
@@ -4279,6 +4254,9 @@ error_free_dyn:
              bfd *normal_bfd;
              bfd *common_bfd;
 
+             BFD_ASSERT (h->root.type == bfd_link_hash_defined
+                         || h->root.type == bfd_link_hash_defweak);
+
              symbol_align = ffs (h->root.u.def.value) - 1;
              if (h->root.u.def.section->owner != NULL
                  && (h->root.u.def.section->owner->flags & DYNAMIC) == 0)
@@ -4308,8 +4286,8 @@ error_free_dyn:
                  /* PR binutils/2735 */
                  if (normal_bfd == NULL)
                    (*_bfd_error_handler)
-                     (_("Warning: alignment %u of common symbol `%s' in %B"
-                        " is greater than the alignment (%u) of its section %A"),
+                     (_("Warning: alignment %u of common symbol `%s' in %B is"
+                        " greater than the alignment (%u) of its section %A"),
                       common_bfd, h->root.u.def.section,
                       1 << common_align, name, 1 << normal_align);
                  else
@@ -4322,7 +4300,8 @@ error_free_dyn:
            }
 
          /* Remember the symbol size if it isn't undefined.  */
-         if ((isym->st_size != 0 && isym->st_shndx != SHN_UNDEF)
+         if (isym->st_size != 0
+             && isym->st_shndx != SHN_UNDEF
              && (definition || h->size == 0))
            {
              if (h->size != 0
@@ -4342,7 +4321,7 @@ error_free_dyn:
             to be the size of the common symbol.  The code just above
             won't fix the size if a common symbol becomes larger.  We
             don't warn about a size change here, because that is
-            covered by --warn-common.  Allow changed between different
+            covered by --warn-common.  Allow changes between different
             function types.  */
          if (h->root.type == bfd_link_hash_common)
            h->size = h->root.u.c.size;
@@ -4375,64 +4354,6 @@ error_free_dyn:
          /* Merge st_other field.  */
          elf_merge_st_other (abfd, h, isym, definition, dynamic);
 
-         /* Set a flag in the hash table entry indicating the type of
-            reference or definition we just found.  Keep a count of
-            the number of dynamic symbols we find.  A dynamic symbol
-            is one which is referenced or defined by both a regular
-            object and a shared object.  */
-         dynsym = FALSE;
-         if (! dynamic)
-           {
-             if (! definition)
-               {
-                 h->ref_regular = 1;
-                 if (bind != STB_WEAK)
-                   h->ref_regular_nonweak = 1;
-               }
-             else
-               {
-                 h->def_regular = 1;
-                 if (h->def_dynamic)
-                   {
-                     h->def_dynamic = 0;
-                     h->ref_dynamic = 1;
-                   }
-               }
-
-             /* 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;
-                 hi->ref_dynamic = 1;
-               }
-             else
-               {
-                 h->def_dynamic = 1;
-                 h->dynamic_def = 1;
-                 hi->def_dynamic = 1;
-                 hi->dynamic_def = 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;
-           }
-
          /* We don't want to make debug symbol dynamic.  */
          if (definition && (sec->flags & SEC_DEBUGGING) && !info->relocatable)
            dynsym = FALSE;
@@ -4442,15 +4363,10 @@ error_free_dyn:
            dynsym = FALSE;
 
          if (definition)
-           h->target_internal = isym->st_target_internal;
-
-         /* Check to see if we need to add an indirect symbol for
-            the default name.  */
-         if (definition || h->root.type == bfd_link_hash_common)
-           if (!_bfd_elf_add_default_symbol (abfd, info, h, name, isym,
-                                             &sec, &value, &dynsym,
-                                             override))
-             goto error_free_vers;
+           {
+             h->target_internal = isym->st_target_internal;
+             h->unique_global = (flags & BSF_GNU_UNIQUE) != 0;
+           }
 
          if (definition && !dynamic)
            {
@@ -4497,11 +4413,14 @@ 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_dynamic
+                  && h->ref_regular_nonweak
+                  && (old_bfd == NULL
+                      || (old_bfd->flags & BFD_PLUGIN) == 0))
+                 || (h->ref_dynamic_nonweak
                      && (elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0
                      && !on_needed_list (elf_dt_name (abfd), htab->needed))))
            {
@@ -4513,16 +4432,13 @@ error_free_dyn:
                 Add a DT_NEEDED entry for it.  Issue an error if
                 --no-add-needed is used and the reference was not
                 a weak one.  */
-             if (undef_bfd != NULL
+             if (old_bfd != NULL
                  && (elf_dyn_lib_class (abfd) & DYN_NO_NEEDED) != 0)
                {
                  (*_bfd_error_handler)
                    (_("%B: undefined reference to symbol '%s'"),
-                    undef_bfd, name);
-                 (*_bfd_error_handler)
-                   (_("note: '%s' is defined in DSO %B so try adding it to the linker command line"),
-                    abfd, name);
-                 bfd_set_error (bfd_error_invalid_operation);
+                    old_bfd, name);
+                 bfd_set_error (bfd_error_missing_dso);
                  goto error_free_vers;
                }
 
@@ -4556,19 +4472,16 @@ error_free_dyn:
       unsigned int i;
 
       /* Restore the symbol table.  */
-      if (bed->as_needed_cleanup)
-       (*bed->as_needed_cleanup) (abfd, info);
-      old_hash = (char *) old_tab + tabsize;
-      old_ent = (char *) old_hash + hashsize;
-      sym_hash = elf_sym_hashes (abfd);
+      old_ent = (char *) old_tab + tabsize;
+      memset (elf_sym_hashes (abfd), 0,
+             extsymcount * sizeof (struct elf_link_hash_entry *));
       htab->root.table.table = old_table;
       htab->root.table.size = old_size;
       htab->root.table.count = old_count;
       memcpy (htab->root.table.table, old_tab, tabsize);
-      memcpy (sym_hash, old_hash, hashsize);
       htab->root.undefs = old_undefs;
       htab->root.undefs_tail = old_undefs_tail;
-      _bfd_elf_strtab_clear_refs (htab->dynstr, old_dynstr_size);
+      _bfd_elf_strtab_restore_size (htab->dynstr, old_dynstr_size);
       for (i = 0; i < htab->root.table.size; i++)
        {
          struct bfd_hash_entry *p;
@@ -4620,8 +4533,7 @@ error_free_dyn:
 
       /* Make a special call to the linker "notice" function to
         tell it that symbols added for crefs may need to be removed.  */
-      if (!(*info->callbacks->notice) (info, NULL, abfd, NULL,
-                                      notice_not_needed, 0, NULL))
+      if (!(*bed->notice_as_needed) (abfd, info, notice_not_needed))
        goto error_free_vers;
 
       free (old_tab);
@@ -4634,8 +4546,7 @@ error_free_dyn:
 
   if (old_tab != NULL)
     {
-      if (!(*info->callbacks->notice) (info, NULL, abfd, NULL,
-                                      notice_needed, 0, NULL))
+      if (!(*bed->notice_as_needed) (abfd, info, notice_needed))
        goto error_free_vers;
       free (old_tab);
       old_tab = NULL;
@@ -4746,7 +4657,7 @@ error_free_dyn:
          struct elf_link_hash_entry *hlook;
          asection *slook;
          bfd_vma vlook;
-         size_t i, j, idx;
+         size_t i, j, idx = 0;
 
          hlook = weaks;
          weaks = hlook->u.weakdef;
@@ -5681,9 +5592,9 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
   /* 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;
+    elf_stack_flags (output_bfd) = PF_R | PF_W | PF_X;
   else if (info->noexecstack)
-    elf_tdata (output_bfd)->stack_flags = PF_R | PF_W;
+    elf_stack_flags (output_bfd) = PF_R | PF_W;
   else
     {
       bfd *inputobj;
@@ -5710,7 +5621,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
            exec = PF_X;
        }
       if (notesec || info->stacksize > 0)
-       elf_tdata (output_bfd)->stack_flags = PF_R | PF_W | exec;
+       elf_stack_flags (output_bfd) = PF_R | PF_W | exec;
       if (notesec && exec && info->relocatable
          && notesec->output_section != bfd_abs_section_ptr)
        notesec->output_section->flags |= SEC_CODE;
@@ -5750,19 +5661,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)
@@ -6931,7 +6839,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
@@ -6946,7 +6855,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;
@@ -6970,7 +6878,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;
 
@@ -6985,6 +6893,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.  */
@@ -8163,17 +8083,14 @@ elf_link_sort_cmp2 (const void *A, const void *B)
 {
   const struct elf_link_sort_rela *a = (const struct elf_link_sort_rela *) A;
   const struct elf_link_sort_rela *b = (const struct elf_link_sort_rela *) B;
-  int copya, copyb;
 
-  if (a->u.offset < b->u.offset)
+  if (a->type < b->type)
     return -1;
-  if (a->u.offset > b->u.offset)
+  if (a->type > b->type)
     return 1;
-  copya = (a->type == reloc_class_copy) * 2 + (a->type == reloc_class_plt);
-  copyb = (b->type == reloc_class_copy) * 2 + (b->type == reloc_class_plt);
-  if (copya < copyb)
+  if (a->u.offset < b->u.offset)
     return -1;
-  if (copya > copyb)
+  if (a->u.offset > b->u.offset)
     return 1;
   if (a->rela->r_offset < b->rela->r_offset)
     return -1;
@@ -8400,7 +8317,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
            struct elf_link_sort_rela *s = (struct elf_link_sort_rela *) p;
 
            (*swap_in) (abfd, erel, s->rela);
-           s->type = (*bed->elf_backend_reloc_type_class) (s->rela);
+           s->type = (*bed->elf_backend_reloc_type_class) (info, o, s->rela);
            s->u.sym_mask = r_sym_mask;
            p += sort_elt;
            erel += ext_size;
@@ -8813,7 +8730,7 @@ 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;
@@ -8891,7 +8808,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)
@@ -10454,6 +10372,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.  */
 
@@ -10751,10 +10705,10 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
   /* sh_offset is set just below.  */
   symtab_hdr->sh_addralign = (bfd_vma) 1 << bed->s->log_file_align;
 
-  off = elf_tdata (abfd)->next_file_pos;
+  off = elf_next_file_pos (abfd);
   off = _bfd_elf_assign_file_position_for_section (symtab_hdr, off, TRUE);
 
-  /* Note that at this point elf_tdata (abfd)->next_file_pos is
+  /* Note that at this point elf_next_file_pos (abfd) is
      incorrect.  We do not yet know the size of the .symtab section.
      We correct next_file_pos below, after we do know the size.  */
 
@@ -11210,7 +11164,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
   symstrtab_hdr->sh_addralign = 1;
 
   off = _bfd_elf_assign_file_position_for_section (symstrtab_hdr, off, TRUE);
-  elf_tdata (abfd)->next_file_pos = off;
+  elf_next_file_pos (abfd) = off;
 
   if (bfd_get_symcount (abfd) > 0)
     {
@@ -11501,44 +11455,12 @@ 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;
+  elf_linker (abfd) = TRUE;
 
   if (attr_section)
     {
@@ -11553,37 +11475,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
@@ -11915,23 +11807,30 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info,
     {
       asection *isec;
       bfd_boolean some_kept;
+      bfd_boolean debug_frag_seen;
 
       if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
        continue;
 
-      /* Ensure all linker created sections are kept, and see whether
-        any other section is already marked.  */
-      some_kept = FALSE;
+      /* Ensure all linker created sections are kept,
+        see if any other section is already marked,
+        and note if we have any fragmented debug sections.  */
+      debug_frag_seen = some_kept = FALSE;
       for (isec = ibfd->sections; isec != NULL; isec = isec->next)
        {
          if ((isec->flags & SEC_LINKER_CREATED) != 0)
            isec->gc_mark = 1;
          else if (isec->gc_mark)
            some_kept = TRUE;
+
+         if (debug_frag_seen == FALSE
+             && (isec->flags & SEC_DEBUGGING)
+             && CONST_STRNEQ (isec->name, ".debug_line."))
+           debug_frag_seen = TRUE;
        }
 
       /* If no section in this file will be kept, then we can
-        toss out debug sections.  */
+        toss out the debug and special sections.  */
       if (!some_kept)
        continue;
 
@@ -11943,6 +11842,45 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info,
            && ((isec->flags & SEC_DEBUGGING) != 0
                || (isec->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0))
          isec->gc_mark = 1;
+
+      if (! debug_frag_seen)
+       continue;
+
+      /* Look for CODE sections which are going to be discarded,
+        and find and discard any fragmented debug sections which
+        are associated with that code section.  */
+      for (isec = ibfd->sections; isec != NULL; isec = isec->next)
+       if ((isec->flags & SEC_CODE) != 0
+           && isec->gc_mark == 0)
+         {
+           unsigned int ilen;
+           asection *dsec;
+
+           ilen = strlen (isec->name);
+
+           /* Association is determined by the name of the debug section
+              containing the name of the code section as a suffix.  For
+              example .debug_line.text.foo is a debug section associated
+              with .text.foo.  */
+           for (dsec = ibfd->sections; dsec != NULL; dsec = dsec->next)
+             {
+               unsigned int dlen;
+
+               if (dsec->gc_mark == 0
+                   || (dsec->flags & SEC_DEBUGGING) == 0)
+                 continue;
+
+               dlen = strlen (dsec->name);
+
+               if (dlen > ilen
+                   && strncmp (dsec->name + (dlen - ilen),
+                               isec->name, ilen) == 0)
+                 {
+                   dsec->gc_mark = 0;
+                   break;
+                 }
+             }
+         }
     }
   return TRUE;
 }
@@ -13057,6 +12995,11 @@ _bfd_elf_make_dynamic_reloc_section (asection *         sec,
          reloc_sec = bfd_make_section_anyway_with_flags (dynobj, name, flags);
          if (reloc_sec != NULL)
            {
+             /* _bfd_elf_get_sec_type_attr chooses a section type by
+                name.  Override as it may be wrong, eg. for a user
+                section named "auto" we'll get ".relauto" which is
+                seen to be a .rela section.  */
+             elf_section_type (reloc_sec) = is_rela ? SHT_RELA : SHT_REL;
              if (! bfd_set_section_alignment (dynobj, reloc_sec, alignment))
                reloc_sec = NULL;
            }
This page took 0.064441 seconds and 4 git commands to generate.