link_hash_copy_indirect and symbol flags
[deliverable/binutils-gdb.git] / bfd / elflink.c
index b432384bd7d93a2f442269506a15a3f440a189dc..81cd236961abadf362c17839ed223003583d53bd 100644 (file)
 #include "safe-ctype.h"
 #include "libiberty.h"
 #include "objalloc.h"
+#if BFD_SUPPORTS_PLUGINS
+#include "plugin-api.h"
+#include "plugin.h"
+#endif
 
 /* This struct is used to pass information to routines called via
    elf_link_hash_traverse which must return failure.  */
@@ -145,8 +149,7 @@ _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_linker_section (abfd, ".got");
-  if (s != NULL)
+  if (htab->sgot != NULL)
     return TRUE;
 
   flags = bed->dynamic_sec_flags;
@@ -204,7 +207,24 @@ _bfd_elf_link_create_dynstrtab (bfd *abfd, struct bfd_link_info *info)
 
   hash_table = elf_hash_table (info);
   if (hash_table->dynobj == NULL)
-    hash_table->dynobj = abfd;
+    {
+      /* We may not set dynobj, an input file holding linker created
+        dynamic sections to abfd, which may be a dynamic object with
+        its own dynamic sections.  We need to find a normal input file
+        to hold linker created sections if possible.  */
+      if ((abfd->flags & (DYNAMIC | BFD_PLUGIN)) != 0)
+       {
+         bfd *ibfd;
+         for (ibfd = info->input_bfds; ibfd; ibfd = ibfd->link.next)
+           if ((ibfd->flags
+                & (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0)
+             {
+               abfd = ibfd;
+               break;
+             }
+       }
+      hash_table->dynobj = abfd;
+    }
 
   if (hash_table->dynstr == NULL)
     {
@@ -407,6 +427,20 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
                                              (SEC_ALLOC | SEC_LINKER_CREATED));
       if (s == NULL)
        return FALSE;
+      htab->sdynbss = s;
+
+      if (bed->want_dynrelro)
+       {
+         /* Similarly, but for symbols that were originally in read-only
+            sections.  */
+         s = bfd_make_section_anyway_with_flags (abfd, ".data.rel.ro",
+                                                 (SEC_ALLOC | SEC_READONLY
+                                                  | SEC_HAS_CONTENTS
+                                                  | SEC_LINKER_CREATED));
+         if (s == NULL)
+           return FALSE;
+         htab->sdynrelro = s;
+       }
 
       /* The .rel[a].bss section holds copy relocs.  This section is not
         normally needed.  We need to create it here, though, so that the
@@ -419,7 +453,7 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
         be needed, we can discard it later.  We will never need this
         section when generating a shared object, since they do not use
         copy relocs.  */
-      if (! bfd_link_pic (info))
+      if (bfd_link_executable (info))
        {
          s = bfd_make_section_anyway_with_flags (abfd,
                                                  (bed->rela_plts_and_copies_p
@@ -428,6 +462,20 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
          if (s == NULL
              || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
            return FALSE;
+         htab->srelbss = s;
+
+         if (bed->want_dynrelro)
+           {
+             s = (bfd_make_section_anyway_with_flags
+                  (abfd, (bed->rela_plts_and_copies_p
+                          ? ".rela.data.rel.ro" : ".rel.data.rel.ro"),
+                   flags | SEC_READONLY));
+             if (s == NULL
+                 || ! bfd_set_section_alignment (abfd, s,
+                                                 bed->s->log_file_align))
+               return FALSE;
+             htab->sreldynrelro = s;
+           }
        }
     }
 
@@ -451,7 +499,7 @@ bfd_elf_link_record_dynamic_symbol (struct bfd_link_info *info,
       struct elf_strtab_hash *dynstr;
       char *p;
       const char *name;
-      bfd_size_type indx;
+      size_t indx;
 
       /* XXX: The ABI draft says the linker must turn hidden and
         internal symbols into STB_LOCAL symbols when producing the
@@ -502,7 +550,7 @@ bfd_elf_link_record_dynamic_symbol (struct bfd_link_info *info,
       if (p != NULL)
        *p = ELF_VER_CHR;
 
-      if (indx == (bfd_size_type) -1)
+      if (indx == (size_t) -1)
        return FALSE;
       h->dynstr_index = indx;
     }
@@ -557,6 +605,9 @@ bfd_elf_record_link_assignment (bfd *output_bfd,
   if (h == NULL)
     return provide;
 
+  if (h->root.type == bfd_link_hash_warning)
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
   if (h->versioned == unknown)
     {
       /* Set versioned if symbol version is unknown.  */
@@ -604,9 +655,9 @@ bfd_elf_record_link_assignment (bfd *output_bfd,
       hv->root.u.i.link = (struct bfd_link_hash_entry *) h;
       (*bed->elf_backend_copy_indirect_symbol) (info, h, hv);
       break;
-    case bfd_link_hash_warning:
-      abort ();
-      break;
+    default:
+      BFD_FAIL ();
+      return FALSE;
     }
 
   /* If this symbol is being provided by the linker script, and it is
@@ -681,7 +732,7 @@ bfd_elf_link_record_local_dynamic_symbol (struct bfd_link_info *info,
   struct elf_link_local_dynamic_entry *entry;
   struct elf_link_hash_table *eht;
   struct elf_strtab_hash *dynstr;
-  unsigned long dynstr_index;
+  size_t dynstr_index;
   char *name;
   Elf_External_Sym_Shndx eshndx;
   char esym[sizeof (Elf64_External_Sym)];
@@ -736,7 +787,7 @@ bfd_elf_link_record_local_dynamic_symbol (struct bfd_link_info *info,
     }
 
   dynstr_index = _bfd_elf_strtab_add (dynstr, name, FALSE);
-  if (dynstr_index == (unsigned long) -1)
+  if (dynstr_index == (size_t) -1)
     return 0;
   entry->isym.st_name = dynstr_index;
 
@@ -883,16 +934,17 @@ _bfd_elf_link_renumber_dynsyms (bfd *output_bfd,
       for (p = elf_hash_table (info)->dynlocal; p ; p = p->next)
        p->dynindx = ++dynsymcount;
     }
+  elf_hash_table (info)->local_dynsymcount = dynsymcount;
 
   elf_link_hash_traverse (elf_hash_table (info),
                          elf_link_renumber_hash_table_dynsyms,
                          &dynsymcount);
 
-  /* There is an unused NULL entry at the head of the table which
-     we must account for in our count.  We always create the dynsym
-     section, even if it is empty, with dynamic sections.  */
-  if (elf_hash_table (info)->dynamic_sections_created)
-    ++dynsymcount;
+  /* There is an unused NULL entry at the head of the table which we
+     must account for in our count even if the table is empty since it
+     is intended for the mandatory DT_SYMTAB tag (.dynsym section) in
+     .dynamic section.  */
+  dynsymcount++;
 
   elf_hash_table (info)->dynsymcount = dynsymcount;
   return dynsymcount;
@@ -1185,21 +1237,20 @@ _bfd_elf_merge_symbol (bfd *abfd,
   oldfunc = (h->type != STT_NOTYPE
             && bed->is_function_type (h->type));
 
-  /* When we try to create a default indirect symbol from the dynamic
-     definition with the default version, we skip it if its type and
-     the type of existing regular definition mismatch.  */
+  /* If creating a default indirect symbol ("foo" or "foo@") from a
+     dynamic versioned definition ("foo@@") skip doing so if there is
+     an existing regular definition with a different type.  We don't
+     want, for example, a "time" variable in the executable overriding
+     a "time" function in a shared library.  */
   if (pold_alignment == NULL
       && newdyn
       && newdef
       && !olddyn
-      && (((olddef || h->root.type == bfd_link_hash_common)
-          && ELF_ST_TYPE (sym->st_info) != h->type
-          && ELF_ST_TYPE (sym->st_info) != STT_NOTYPE
-          && h->type != STT_NOTYPE
-          && !(newfunc && oldfunc))
-         || (olddef
-             && ((h->type == STT_GNU_IFUNC)
-                 != (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)))))
+      && (olddef || h->root.type == bfd_link_hash_common)
+      && ELF_ST_TYPE (sym->st_info) != h->type
+      && ELF_ST_TYPE (sym->st_info) != STT_NOTYPE
+      && h->type != STT_NOTYPE
+      && !(newfunc && oldfunc))
     {
       *skip = TRUE;
       return TRUE;
@@ -1238,22 +1289,26 @@ _bfd_elf_merge_symbol (bfd *abfd,
        }
 
       if (tdef && ntdef)
-       (*_bfd_error_handler)
+       _bfd_error_handler
+         /* xgettext:c-format */
          (_("%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)
+       _bfd_error_handler
+         /* xgettext:c-format */
          (_("%s: TLS reference in %B "
             "mismatches non-TLS reference in %B"),
           tbfd, ntbfd, h->root.root.string);
       else if (tdef)
-       (*_bfd_error_handler)
+       _bfd_error_handler
+         /* xgettext:c-format */
          (_("%s: TLS definition in %B section %A "
             "mismatches non-TLS reference in %B"),
           tbfd, tsec, ntbfd, h->root.root.string);
       else
-       (*_bfd_error_handler)
+       _bfd_error_handler
+         /* xgettext:c-format */
          (_("%s: TLS reference in %B "
             "mismatches non-TLS definition in %B section %A"),
           tbfd, ntbfd, ntsec, h->root.root.string);
@@ -1464,10 +1519,8 @@ _bfd_elf_merge_symbol (bfd *abfd,
         the old symbol override the new one as normally happens with
         symbols defined in dynamic objects.  */
 
-      if (! ((*info->callbacks->multiple_common)
-            (info, &h->root, abfd, bfd_link_hash_common, sym->st_size)))
-       return FALSE;
-
+      (*info->callbacks->multiple_common) (info, &h->root, abfd,
+                                          bfd_link_hash_common, sym->st_size);
       if (sym->st_size > h->size)
        h->size = sym->st_size;
 
@@ -1625,9 +1678,8 @@ _bfd_elf_merge_symbol (bfd *abfd,
       /* It would be best if we could set the hash table entry to a
         common symbol, but we don't know what to use for the section
         or the alignment.  */
-      if (! ((*info->callbacks->multiple_common)
-            (info, &h->root, abfd, bfd_link_hash_common, sym->st_size)))
-       return FALSE;
+      (*info->callbacks->multiple_common) (info, &h->root, abfd,
+                                          bfd_link_hash_common, sym->st_size);
 
       /* If the presumed common symbol in the dynamic object is
         larger, pretend that the new symbol has its size.  */
@@ -1767,6 +1819,31 @@ _bfd_elf_add_default_symbol (bfd *abfd,
   if (skip)
     goto nondefault;
 
+  if (hi->def_regular)
+    {
+      /* If the undecorated symbol will have a version added by a
+        script different to H, then don't indirect to/from the
+        undecorated symbol.  This isn't ideal because we may not yet
+        have seen symbol versions, if given by a script on the
+        command line rather than via --version-script.  */
+      if (hi->verinfo.vertree == NULL && info->version_info != NULL)
+       {
+         bfd_boolean hide;
+
+         hi->verinfo.vertree
+           = bfd_find_version_for_sym (info->version_info,
+                                       hi->root.root.string, &hide);
+         if (hi->verinfo.vertree != NULL && hide)
+           {
+             (*bed->elf_backend_hide_symbol) (info, hi, TRUE);
+             goto nondefault;
+           }
+       }
+      if (hi->verinfo.vertree != NULL
+         && strcmp (p + 1 + (p[1] == '@'), hi->verinfo.vertree->name) != 0)
+       goto nondefault;
+    }
+
   if (! override)
     {
       /* Add the default symbol if not performing a relocatable link.  */
@@ -1894,7 +1971,8 @@ nondefault:
         overridden by a versioned definition.  */
       if (hi->root.type != bfd_link_hash_defined
          && hi->root.type != bfd_link_hash_defweak)
-       (*_bfd_error_handler)
+       _bfd_error_handler
+         /* xgettext:c-format */
          (_("%B: unexpected redefinition of indirect versioned symbol `%s'"),
           abfd, shortname);
     }
@@ -2066,7 +2144,6 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
   const struct elf_backend_data *bed;
   struct elf_info_failed eif;
   char *p;
-  bfd_size_type amt;
 
   sinfo = (struct elf_info_failed *) data;
   info = sinfo->info;
@@ -2156,8 +2233,8 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
          if (h->dynindx == -1)
            return TRUE;
 
-         amt = sizeof *t;
-         t = (struct bfd_elf_version_tree *) bfd_zalloc (info->output_bfd, amt);
+         t = (struct bfd_elf_version_tree *) bfd_zalloc (info->output_bfd,
+                                                         sizeof *t);
          if (t == NULL)
            {
              sinfo->failed = TRUE;
@@ -2187,7 +2264,8 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
        {
          /* We could not find the version for a symbol when
             generating a shared archive.  Return an error.  */
-         (*_bfd_error_handler)
+         _bfd_error_handler
+           /* xgettext:c-format */
            (_("%B: version node not found for symbol %s"),
             info->output_bfd, h->root.root.string);
          bfd_set_error (bfd_error_bad_value);
@@ -2275,7 +2353,8 @@ elf_link_read_relocs_from_section (bfd *abfd,
        {
          if ((size_t) r_symndx >= nsyms)
            {
-             (*_bfd_error_handler)
+             _bfd_error_handler
+               /* xgettext:c-format */
                (_("%B: bad reloc symbol index (0x%lx >= 0x%lx)"
                   " for offset 0x%lx in section `%A'"),
                 abfd, sec,
@@ -2286,7 +2365,8 @@ elf_link_read_relocs_from_section (bfd *abfd,
        }
       else if (r_symndx != STN_UNDEF)
        {
-         (*_bfd_error_handler)
+         _bfd_error_handler
+           /* xgettext:c-format */
            (_("%B: non-zero symbol index (0x%lx) for offset 0x%lx in section `%A'"
               " when the object file has no symbol table"),
             abfd, sec,
@@ -2476,7 +2556,8 @@ _bfd_elf_link_output_relocs (bfd *output_bfd,
     }
   else
     {
-      (*_bfd_error_handler)
+      _bfd_error_handler
+       /* xgettext:c-format */
        (_("%B: relocation size mismatch in %B section %A"),
         output_bfd, input_section->owner, input_section);
       bfd_set_error (bfd_error_wrong_format);
@@ -2604,18 +2685,35 @@ _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h,
       && (h->root.u.def.section->owner->flags & (DYNAMIC | BFD_PLUGIN)) == 0)
     h->def_regular = 1;
 
+  /* If a weak undefined symbol has non-default visibility, we also
+     hide it from the dynamic linker.  */
+  if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+      && h->root.type == bfd_link_hash_undefweak)
+    (*bed->elf_backend_hide_symbol) (eif->info, h, TRUE);
+
+  /* A hidden versioned symbol in executable should be forced local if
+     it is is locally defined, not referenced by shared library and not
+     exported.  */
+  else if (bfd_link_executable (eif->info)
+          && h->versioned == versioned_hidden
+          && !eif->info->export_dynamic
+          && !h->dynamic
+          && !h->ref_dynamic
+          && h->def_regular)
+    (*bed->elf_backend_hide_symbol) (eif->info, h, TRUE);
+
   /* If -Bsymbolic was used (which means to bind references to global
      symbols to the definition within the shared object), and this
      symbol was defined in a regular object, then it actually doesn't
      need a PLT entry.  Likewise, if the symbol has non-default
      visibility.  If the symbol has hidden or internal visibility, we
      will force it local.  */
-  if (h->needs_plt
-      && bfd_link_pic (eif->info)
-      && is_elf_hash_table (eif->info->hash)
-      && (SYMBOLIC_BIND (eif->info, h)
-         || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
-      && h->def_regular)
+  else if (h->needs_plt
+          && bfd_link_pic (eif->info)
+          && is_elf_hash_table (eif->info->hash)
+          && (SYMBOLIC_BIND (eif->info, h)
+              || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+          && h->def_regular)
     {
       bfd_boolean force_local;
 
@@ -2624,12 +2722,6 @@ _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h,
       (*bed->elf_backend_hide_symbol) (eif->info, h, force_local);
     }
 
-  /* If a weak undefined symbol has non-default visibility, we also
-     hide it from the dynamic linker.  */
-  if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
-      && h->root.type == bfd_link_hash_undefweak)
-    (*bed->elf_backend_hide_symbol) (eif->info, h, TRUE);
-
   /* If this is a weak defined symbol in a dynamic object, and we know
      the real definition in the dynamic object, copy interesting flags
      over to the real definition.  */
@@ -2758,7 +2850,7 @@ _bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data)
   if (h->size == 0
       && h->type == STT_NOTYPE
       && !h->needs_plt)
-    (*_bfd_error_handler)
+    _bfd_error_handler
       (_("warning: type and size of dynamic symbol `%s' are not defined"),
        h->root.root.string);
 
@@ -3075,9 +3167,9 @@ static bfd_boolean
 elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef)
 {
   Elf_Internal_Shdr * hdr;
-  bfd_size_type symcount;
-  bfd_size_type extsymcount;
-  bfd_size_type extsymoff;
+  size_t symcount;
+  size_t extsymcount;
+  size_t extsymoff;
   Elf_Internal_Sym *isymbuf;
   Elf_Internal_Sym *isym;
   Elf_Internal_Sym *isymend;
@@ -3087,15 +3179,25 @@ elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef)
   if (abfd == NULL)
     return FALSE;
 
-  /* Return FALSE if the object has been claimed by plugin.  */
-  if (abfd->plugin_format == bfd_plugin_yes)
-    return FALSE;
-
   if (! bfd_check_format (abfd, bfd_object))
     return FALSE;
 
-  /* Select the appropriate symbol table.  */
-  if ((abfd->flags & DYNAMIC) == 0 || elf_dynsymtab (abfd) == 0)
+  /* Select the appropriate symbol table.  If we don't know if the
+     object file is an IR object, give linker LTO plugin a chance to
+     get the correct symbol table.  */
+  if (abfd->plugin_format == bfd_plugin_yes
+#if BFD_SUPPORTS_PLUGINS
+      || (abfd->plugin_format == bfd_plugin_unknown
+         && bfd_link_plugin_object_p (abfd))
+#endif
+      )
+    {
+      /* Use the IR symbol table if the object has been claimed by
+        plugin.  */
+      abfd = abfd->plugin_dummy_bfd;
+      hdr = &elf_tdata (abfd)->symtab_hdr;
+    }
+  else if ((abfd->flags & DYNAMIC) == 0 || elf_dynsymtab (abfd) == 0)
     hdr = &elf_tdata (abfd)->symtab_hdr;
   else
     hdr = &elf_tdata (abfd)->dynsymtab_hdr;
@@ -3195,14 +3297,14 @@ elf_add_dt_needed_tag (bfd *abfd,
                       bfd_boolean do_it)
 {
   struct elf_link_hash_table *hash_table;
-  bfd_size_type strindex;
+  size_t strindex;
 
   if (!_bfd_elf_link_create_dynstrtab (abfd, info))
     return -1;
 
   hash_table = elf_hash_table (info);
   strindex = _bfd_elf_strtab_add (hash_table->dynstr, soname, FALSE);
-  if (strindex == (bfd_size_type) -1)
+  if (strindex == (size_t) -1)
     return -1;
 
   if (_bfd_elf_strtab_refcount (hash_table->dynstr, strindex) != 1)
@@ -3370,7 +3472,7 @@ elf_finalize_dynstr (bfd *output_bfd, struct bfd_link_info *info)
     {
       asection *s;
       bfd_byte *p;
-      bfd_size_type i;
+      size_t i;
       Elf_Internal_Verdef def;
       Elf_Internal_Verdaux defaux;
 
@@ -3402,7 +3504,7 @@ elf_finalize_dynstr (bfd *output_bfd, struct bfd_link_info *info)
     {
       asection *s;
       bfd_byte *p;
-      bfd_size_type i;
+      size_t i;
       Elf_Internal_Verneed need;
       Elf_Internal_Vernaux needaux;
 
@@ -3552,16 +3654,16 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
 {
   Elf_Internal_Ehdr *ehdr;
   Elf_Internal_Shdr *hdr;
-  bfd_size_type symcount;
-  bfd_size_type extsymcount;
-  bfd_size_type extsymoff;
+  size_t symcount;
+  size_t extsymcount;
+  size_t extsymoff;
   struct elf_link_hash_entry **sym_hash;
   bfd_boolean dynamic;
   Elf_External_Versym *extversym = NULL;
   Elf_External_Versym *ever;
   struct elf_link_hash_entry *weaks;
   struct elf_link_hash_entry **nondeflt_vers = NULL;
-  bfd_size_type nondeflt_vers_cnt = 0;
+  size_t nondeflt_vers_cnt = 0;
   Elf_Internal_Sym *isymbuf = NULL;
   Elf_Internal_Sym *isym;
   Elf_Internal_Sym *isymend;
@@ -3577,8 +3679,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
   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;
+  void *old_strtab = NULL;
   size_t tabsize = 0;
   asection *s;
   bfd_boolean just_syms;
@@ -3615,6 +3716,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
          || (bed->elf_machine_alt2 != 0
              && ehdr->e_machine == bed->elf_machine_alt2)))
     info->callbacks->einfo
+      /* xgettext:c-format */
       (_("%P: alternate ELF machine code found (%d) in %B, expecting %d\n"),
        ehdr->e_machine, abfd, bed->elf_machine_code);
 
@@ -3717,6 +3819,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
       const char *soname = NULL;
       char *audit = NULL;
       struct bfd_link_needed_list *rpath = NULL, *runpath = NULL;
+      const Elf_Internal_Phdr *phdr;
       int ret;
 
       /* ld --just-symbols and dynamic objects don't mix very well.
@@ -3866,6 +3969,21 @@ error_free_dyn:
          *pn = rpath;
        }
 
+      /* If we have a PT_GNU_RELRO program header, mark as read-only
+        all sections contained fully therein.  This makes relro
+        shared library sections appear as they will at run-time.  */
+      phdr = elf_tdata (abfd)->phdr + elf_elfheader (abfd)->e_phnum;
+      while (--phdr >= elf_tdata (abfd)->phdr)
+       if (phdr->p_type == PT_GNU_RELRO)
+         {
+           for (s = abfd->sections; s != NULL; s = s->next)
+             if ((s->flags & SEC_ALLOC) != 0
+                 && s->vma >= phdr->p_vaddr
+                 && s->vma + s->size <= phdr->p_vaddr + phdr->p_memsz)
+               s->flags |= SEC_READONLY;
+           break;
+         }
+
       /* We do not want to include any of the sections in a dynamic
         object in the output file.  We hack by simply clobbering the
         list of sections in the BFD.  This could be handled more
@@ -3943,7 +4061,8 @@ error_free_dyn:
        {
          /* We store a pointer to the hash table entry for each
             external symbol.  */
-         amt = extsymcount * sizeof (struct elf_link_hash_entry *);
+         amt = extsymcount;
+         amt *= 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;
@@ -4022,8 +4141,9 @@ error_free_dyn:
       old_table = htab->root.table.table;
       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);
+      old_strtab = _bfd_elf_strtab_save (htab->dynstr);
+      if (old_strtab == NULL)
+       goto error_free_vers;
 
       for (i = 0; i < htab->root.table.size; i++)
        {
@@ -4065,6 +4185,7 @@ error_free_dyn:
       bfd_boolean old_weak;
       bfd_boolean override;
       bfd_boolean common;
+      bfd_boolean discarded;
       unsigned int old_alignment;
       bfd *old_bfd;
       bfd_boolean matched;
@@ -4075,6 +4196,7 @@ error_free_dyn:
       sec = NULL;
       value = isym->st_value;
       common = bed->common_definition (isym);
+      discarded = FALSE;
 
       bind = ELF_ST_BIND (isym->st_info);
       switch (bind)
@@ -4125,6 +4247,7 @@ error_free_dyn:
              /* Symbols from discarded section are undefined.  We keep
                 its visibility.  */
              sec = bfd_und_section_ptr;
+             discarded = TRUE;
              isym->st_shndx = SHN_UNDEF;
            }
          else if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
@@ -4252,7 +4375,8 @@ error_free_dyn:
 
                  if (verstr == NULL)
                    {
-                     (*_bfd_error_handler)
+                     _bfd_error_handler
+                       /* xgettext:c-format */
                        (_("%B: %s: invalid version %u (max %d)"),
                         abfd, name, vernum,
                         elf_tdata (abfd)->cverdefs);
@@ -4288,7 +4412,8 @@ error_free_dyn:
                    }
                  if (verstr == NULL)
                    {
-                     (*_bfd_error_handler)
+                     _bfd_error_handler
+                       /* xgettext:c-format */
                        (_("%B: %s: invalid needed version %d"),
                         abfd, name, vernum);
                      bfd_set_error (bfd_error_bad_value);
@@ -4360,6 +4485,11 @@ error_free_dyn:
              (struct bfd_link_hash_entry **) sym_hash)))
        goto error_free_vers;
 
+      if ((flags & BSF_GNU_UNIQUE)
+         && (abfd->flags & DYNAMIC) == 0
+         && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour)
+       elf_tdata (info->output_bfd)->has_gnu_symbols |= elf_gnu_symbol_unique;
+
       h = *sym_hash;
       /* We need to make sure that indirect symbol dynamic flags are
         updated.  */
@@ -4368,6 +4498,11 @@ error_free_dyn:
             || h->root.type == bfd_link_hash_warning)
        h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
+      /* Setting the index to -3 tells elf_link_output_extsym that
+        this symbol is defined in a discarded section.  */
+      if (discarded)
+       h->indx = -3;
+
       *sym_hash = h;
 
       new_weak = (flags & BSF_WEAK) != 0;
@@ -4505,7 +4640,8 @@ error_free_dyn:
 
              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)
+                 && (h->root.u.def.section->owner->flags
+                      & (DYNAMIC | BFD_PLUGIN)) == 0)
                {
                  normal_align = h->root.u.def.section->alignment_power;
                  if (normal_align > symbol_align)
@@ -4531,13 +4667,15 @@ error_free_dyn:
                {
                  /* PR binutils/2735 */
                  if (normal_bfd == NULL)
-                   (*_bfd_error_handler)
+                   _bfd_error_handler
+                     /* xgettext:c-format */
                      (_("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
-                   (*_bfd_error_handler)
+                   _bfd_error_handler
+                     /* xgettext:c-format */
                      (_("Warning: alignment %u of symbol `%s' in %B"
                         " is smaller than %u in %B"),
                       normal_bfd, common_bfd,
@@ -4553,7 +4691,8 @@ error_free_dyn:
              if (h->size != 0
                  && h->size != isym->st_size
                  && ! size_change_ok)
-               (*_bfd_error_handler)
+               _bfd_error_handler
+                 /* xgettext:c-format */
                  (_("Warning: size of symbol `%s' changed"
                     " from %lu in %B to %lu in %B"),
                   old_bfd, abfd,
@@ -4588,7 +4727,8 @@ error_free_dyn:
              if (h->type != type)
                {
                  if (h->type != STT_NOTYPE && ! type_change_ok)
-                   (*_bfd_error_handler)
+                   /* xgettext:c-format */
+                   _bfd_error_handler
                      (_("Warning: type of symbol `%s' changed"
                         " from %d to %d in %B"),
                       abfd, name, h->type, type);
@@ -4689,7 +4829,8 @@ error_free_dyn:
              if (old_bfd != NULL
                  && (elf_dyn_lib_class (abfd) & DYN_NO_NEEDED) != 0)
                {
-                 (*_bfd_error_handler)
+                 _bfd_error_handler
+                   /* xgettext:c-format */
                    (_("%B: undefined reference to symbol '%s'"),
                     old_bfd, name);
                  bfd_set_error (bfd_error_missing_dso);
@@ -4735,7 +4876,9 @@ error_free_dyn:
       memcpy (htab->root.table.table, old_tab, tabsize);
       htab->root.undefs = old_undefs;
       htab->root.undefs_tail = old_undefs_tail;
-      _bfd_elf_strtab_restore_size (htab->dynstr, old_dynstr_size);
+      _bfd_elf_strtab_restore (htab->dynstr, old_strtab);
+      free (old_strtab);
+      old_strtab = NULL;
       for (i = 0; i < htab->root.table.size; i++)
        {
          struct bfd_hash_entry *p;
@@ -4748,9 +4891,6 @@ 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
-                 && 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
@@ -4811,7 +4951,7 @@ error_free_dyn:
      such that any relocs against foo become foo@BAR.  */
   if (!bfd_link_relocatable (info) && nondeflt_vers != NULL)
     {
-      bfd_size_type cnt, symidx;
+      size_t cnt, symidx;
 
       for (cnt = 0; cnt < nondeflt_vers_cnt; ++cnt)
        {
@@ -4882,7 +5022,8 @@ error_free_dyn:
       /* Since we have to search the whole symbol list for each weak
         defined symbol, search time for N weak defined symbols will be
         O(N^2). Binary search will cut it down to O(NlogN).  */
-      amt = extsymcount * sizeof (struct elf_link_hash_entry *);
+      amt = extsymcount;
+      amt *= sizeof (struct elf_link_hash_entry *);
       sorted_sym_hash = (struct elf_link_hash_entry **) bfd_malloc (amt);
       if (sorted_sym_hash == NULL)
        goto error_return;
@@ -5072,6 +5213,8 @@ error_free_dyn:
  error_free_vers:
   if (old_tab != NULL)
     free (old_tab);
+  if (old_strtab != NULL)
+    free (old_strtab);
   if (nondeflt_vers != NULL)
     free (nondeflt_vers);
   if (extversym != NULL)
@@ -5253,7 +5396,7 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
 
          if (!(*info->callbacks
                ->add_archive_element) (info, element, symdef->name, &element))
-           goto error_return;
+           continue;
          if (!bfd_link_add_symbols (element, info))
            goto error_return;
 
@@ -5691,11 +5834,13 @@ bfd_elf_stack_segment_size (bfd *output_bfd,
       /* 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);
+       /* xgettext:c-format */
+       _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);
+       /* xgettext:c-format */
+       _bfd_error_handler (_("%B: %s not absolute"),
+                           output_bfd, legacy_symbol);
       else
        info->stacksize = h->root.u.def.value;
     }
@@ -5742,14 +5887,14 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
                               struct bfd_link_info *info,
                               asection **sinterpptr)
 {
-  bfd_size_type soname_indx;
+  size_t soname_indx;
   bfd *dynobj;
   const struct elf_backend_data *bed;
   struct elf_info_failed asvinfo;
 
   *sinterpptr = NULL;
 
-  soname_indx = (bfd_size_type) -1;
+  soname_indx = (size_t) -1;
 
   if (!is_elf_hash_table (info->hash))
     return TRUE;
@@ -5830,7 +5975,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
        {
          soname_indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
                                             soname, TRUE);
-         if (soname_indx == (bfd_size_type) -1
+         if (soname_indx == (size_t) -1
              || !_bfd_elf_add_dynamic_entry (info, DT_SONAME, soname_indx))
            return FALSE;
        }
@@ -5844,12 +5989,12 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
 
       if (rpath != NULL)
        {
-         bfd_size_type indx;
+         size_t indx;
          bfd_vma tag;
 
          indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, rpath,
                                      TRUE);
-         if (indx == (bfd_size_type) -1)
+         if (indx == (size_t) -1)
            return FALSE;
 
          tag = info->new_dtags ? DT_RUNPATH : DT_RPATH;
@@ -5859,11 +6004,11 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
 
       if (filter_shlib != NULL)
        {
-         bfd_size_type indx;
+         size_t indx;
 
          indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
                                      filter_shlib, TRUE);
-         if (indx == (bfd_size_type) -1
+         if (indx == (size_t) -1
              || !_bfd_elf_add_dynamic_entry (info, DT_FILTER, indx))
            return FALSE;
        }
@@ -5874,11 +6019,11 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
 
          for (p = auxiliary_filters; *p != NULL; p++)
            {
-             bfd_size_type indx;
+             size_t indx;
 
              indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
                                          *p, TRUE);
-             if (indx == (bfd_size_type) -1
+             if (indx == (size_t) -1
                  || !_bfd_elf_add_dynamic_entry (info, DT_AUXILIARY, indx))
                return FALSE;
            }
@@ -5886,22 +6031,22 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
 
       if (audit != NULL)
        {
-         bfd_size_type indx;
+         size_t indx;
 
          indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, audit,
                                      TRUE);
-         if (indx == (bfd_size_type) -1
+         if (indx == (size_t) -1
              || !_bfd_elf_add_dynamic_entry (info, DT_AUDIT, indx))
            return FALSE;
        }
 
       if (depaudit != NULL)
        {
-         bfd_size_type indx;
+         size_t indx;
 
          indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, depaudit,
                                      TRUE);
-         if (indx == (bfd_size_type) -1
+         if (indx == (size_t) -1
              || !_bfd_elf_add_dynamic_entry (info, DT_DEPAUDIT, indx))
            return FALSE;
        }
@@ -5991,7 +6136,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
            for (d = t->globals.list; d != NULL; d = d->next)
              if (d->literal && !d->symver && !d->script)
                {
-                 (*_bfd_error_handler)
+                 _bfd_error_handler
                    (_("%s: undefined version: %s"),
                     d->pattern, t->name);
                  all_defined = FALSE;
@@ -6059,7 +6204,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
                    if (elf_section_data (o)->this_hdr.sh_type
                        == SHT_PREINIT_ARRAY)
                      {
-                       (*_bfd_error_handler)
+                       _bfd_error_handler
                          (_("%B: .preinit_array section is not allowed in DSO"),
                           sub);
                        break;
@@ -6209,7 +6354,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
                             + sizeof (Elf_External_Verdaux));
            }
 
-         if (soname_indx != (bfd_size_type) -1)
+         if (soname_indx != (size_t) -1)
            {
              _bfd_elf_strtab_addref (elf_hash_table (info)->dynstr,
                                      soname_indx);
@@ -6219,13 +6364,13 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
            }
          else
            {
-             bfd_size_type indx;
+             size_t indx;
 
              name = lbasename (output_bfd->filename);
              def.vd_hash = bfd_elf_hash (name);
              indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
                                          name, FALSE);
-             if (indx == (bfd_size_type) -1)
+             if (indx == (size_t) -1)
                return FALSE;
              defaux.vda_name = indx;
            }
@@ -6444,7 +6589,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
              {
                unsigned int caux;
                Elf_Internal_Vernaux *a;
-               bfd_size_type indx;
+               size_t indx;
 
                caux = 0;
                for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
@@ -6457,7 +6602,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
                                            ? elf_dt_name (t->vn_bfd)
                                            : lbasename (t->vn_bfd->filename),
                                            FALSE);
-               if (indx == (bfd_size_type) -1)
+               if (indx == (size_t) -1)
                  return FALSE;
                t->vn_file = indx;
                t->vn_aux = sizeof (Elf_External_Verneed);
@@ -6476,7 +6621,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
                    a->vna_hash = bfd_elf_hash (a->vna_nodename);
                    indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
                                                a->vna_nodename, FALSE);
-                   if (indx == (bfd_size_type) -1)
+                   if (indx == (size_t) -1)
                      return FALSE;
                    a->vna_name = indx;
                    if (a->vna_nextptr == NULL)
@@ -6589,8 +6734,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
       /* Work out the size of the symbol version section.  */
       s = bfd_get_linker_section (dynobj, ".gnu.version");
       BFD_ASSERT (s != NULL);
-      if (dynsymcount != 0
-         && (s->flags & SEC_EXCLUDE) == 0)
+      if ((s->flags & SEC_EXCLUDE) == 0)
        {
          s->size = dynsymcount * sizeof (Elf_External_Versym);
          s->contents = (unsigned char *) bfd_zalloc (output_bfd, s->size);
@@ -6611,17 +6755,14 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
       BFD_ASSERT (s != NULL);
       s->size = dynsymcount * bed->s->sizeof_sym;
 
-      if (dynsymcount != 0)
-       {
-         s->contents = (unsigned char *) bfd_alloc (output_bfd, s->size);
-         if (s->contents == NULL)
-           return FALSE;
+      s->contents = (unsigned char *) bfd_alloc (output_bfd, s->size);
+      if (s->contents == NULL)
+       return FALSE;
 
-         /* The first entry in .dynsym is a dummy symbol.
-            Clear all the section syms, in case we don't output them all.  */
-         ++section_sym_count;
-         memset (s->contents, 0, section_sym_count * bed->s->sizeof_sym);
-       }
+      /* The first entry in .dynsym is a dummy symbol.  Clear all the
+        section syms, in case we don't output them all.  */
+      ++section_sym_count;
+      memset (s->contents, 0, section_sym_count * bed->s->sizeof_sym);
 
       elf_hash_table (info)->bucketcount = 0;
 
@@ -6961,18 +7102,15 @@ _bfd_elf_link_hash_copy_indirect (struct bfd_link_info *info,
   struct elf_link_hash_table *htab;
 
   /* Copy down any references that we may have already seen to the
-     symbol which just became indirect if DIR isn't a hidden versioned
-     symbol.  */
+     symbol which just became indirect.  */
 
   if (dir->versioned != versioned_hidden)
-    {
-      dir->ref_dynamic |= ind->ref_dynamic;
-      dir->ref_regular |= ind->ref_regular;
-      dir->ref_regular_nonweak |= ind->ref_regular_nonweak;
-      dir->non_got_ref |= ind->non_got_ref;
-      dir->needs_plt |= ind->needs_plt;
-      dir->pointer_equality_needed |= ind->pointer_equality_needed;
-    }
+    dir->ref_dynamic |= ind->ref_dynamic;
+  dir->ref_regular |= ind->ref_regular;
+  dir->ref_regular_nonweak |= ind->ref_regular_nonweak;
+  dir->non_got_ref |= ind->non_got_ref;
+  dir->needs_plt |= ind->needs_plt;
+  dir->pointer_equality_needed |= ind->pointer_equality_needed;
 
   if (ind->root.type != bfd_link_hash_indirect)
     return;
@@ -7259,7 +7397,7 @@ struct elf_symbuf_symbol
 struct elf_symbuf_head
 {
   struct elf_symbuf_symbol *ssym;
-  bfd_size_type count;
+  size_t count;
   unsigned int st_shndx;
 };
 
@@ -7293,12 +7431,12 @@ elf_sym_name_compare (const void *arg1, const void *arg2)
 }
 
 static struct elf_symbuf_head *
-elf_create_symbuf (bfd_size_type symcount, Elf_Internal_Sym *isymbuf)
+elf_create_symbuf (size_t symcount, Elf_Internal_Sym *isymbuf)
 {
   Elf_Internal_Sym **ind, **indbufend, **indbuf;
   struct elf_symbuf_symbol *ssym;
   struct elf_symbuf_head *ssymbuf, *ssymhead;
-  bfd_size_type i, shndx_count, total_size;
+  size_t i, shndx_count, total_size;
 
   indbuf = (Elf_Internal_Sym **) bfd_malloc2 (symcount, sizeof (*indbuf));
   if (indbuf == NULL)
@@ -7345,7 +7483,7 @@ elf_create_symbuf (bfd_size_type symcount, Elf_Internal_Sym *isymbuf)
       ssym->st_other = (*ind)->st_other;
       ssymhead->count++;
     }
-  BFD_ASSERT ((bfd_size_type) (ssymhead - ssymbuf) == shndx_count
+  BFD_ASSERT ((size_t) (ssymhead - ssymbuf) == shndx_count
              && (((bfd_hostptr_t) ssym - (bfd_hostptr_t) ssymbuf)
                  == total_size));
 
@@ -7363,12 +7501,12 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
   bfd *bfd1, *bfd2;
   const struct elf_backend_data *bed1, *bed2;
   Elf_Internal_Shdr *hdr1, *hdr2;
-  bfd_size_type symcount1, symcount2;
+  size_t symcount1, symcount2;
   Elf_Internal_Sym *isymbuf1, *isymbuf2;
   struct elf_symbuf_head *ssymbuf1, *ssymbuf2;
   Elf_Internal_Sym *isym, *isymend;
   struct elf_symbol *symtable1 = NULL, *symtable2 = NULL;
-  bfd_size_type count1, count2, i;
+  size_t count1, count2, i;
   unsigned int shndx1, shndx2;
   bfd_boolean result;
 
@@ -7431,7 +7569,7 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
   if (ssymbuf1 != NULL && ssymbuf2 != NULL)
     {
       /* Optimized faster version.  */
-      bfd_size_type lo, hi, mid;
+      size_t lo, hi, mid;
       struct elf_symbol *symp;
       struct elf_symbuf_symbol *ssym, *ssymend;
 
@@ -7829,6 +7967,7 @@ resolve_section (const char *name,
 static void
 undefined_reference (const char *reftype, const char *name)
 {
+  /* xgettext:c-format */
   _bfd_error_handler (_("undefined %s reference in complex symbol: %s"),
                      reftype, name);
 }
@@ -7875,6 +8014,7 @@ eval_symbol (bfd_vma *result,
 
     case 'S':
       symbol_is_section = TRUE;
+      /* Fall through.  */
     case 's':
       ++sym;
       symlen = strtol (sym, (char **) symp, 10);
@@ -8265,6 +8405,7 @@ ext64b_r_offset (const void *p)
 
 static bfd_boolean
 elf_link_adjust_relocs (bfd *abfd,
+                       asection *sec,
                        struct bfd_elf_section_reloc_data *reldata,
                        bfd_boolean sort)
 {
@@ -8323,6 +8464,9 @@ elf_link_adjust_relocs (bfd *abfd,
       (*swap_out) (abfd, irela, erela);
     }
 
+  if (bed->elf_backend_update_relocs)
+    (*bed->elf_backend_update_relocs) (sec, reldata);
+
   if (sort && count != 0)
     {
       bfd_vma (*ext_r_off) (const void *);
@@ -8505,6 +8649,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
   struct elf_link_sort_rela *sq;
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   int i2e = bed->s->int_rels_per_ext_rel;
+  unsigned int opb = bfd_octets_per_byte (abfd);
   void (*swap_in) (bfd *, const bfd_byte *, Elf_Internal_Rela *);
   void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *);
   struct bfd_link_order *lo;
@@ -8520,7 +8665,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
       bfd_boolean use_rela_initialised = FALSE;
 
       /* This is just here to stop gcc from complaining.
-        It's initialization checking code is not perfect.  */
+        Its initialization checking code is not perfect.  */
       use_rela = TRUE;
 
       /* Both sections are present.  Examine the sizes
@@ -8541,8 +8686,9 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
                    /* Section size is only divisible by rela.  */
                    if (use_rela_initialised && (use_rela == FALSE))
                      {
-                       _bfd_error_handler
-                         (_("%B: Unable to sort relocs - they are in more than one size"), abfd);
+                       _bfd_error_handler (_("%B: Unable to sort relocs - "
+                                             "they are in more than one size"),
+                                           abfd);
                        bfd_set_error (bfd_error_invalid_operation);
                        return 0;
                      }
@@ -8558,8 +8704,9 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
                /* Section size is only divisible by rel.  */
                if (use_rela_initialised && (use_rela == TRUE))
                  {
-                   _bfd_error_handler
-                     (_("%B: Unable to sort relocs - they are in more than one size"), abfd);
+                   _bfd_error_handler (_("%B: Unable to sort relocs - "
+                                         "they are in more than one size"),
+                                       abfd);
                    bfd_set_error (bfd_error_invalid_operation);
                    return 0;
                  }
@@ -8571,9 +8718,10 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
              }
            else
              {
-               /* The section size is not divisible by either - something is wrong.  */
-               _bfd_error_handler
-                 (_("%B: Unable to sort relocs - they are of an unknown size"), abfd);
+               /* The section size is not divisible by either -
+                  something is wrong.  */
+               _bfd_error_handler (_("%B: Unable to sort relocs - "
+                                     "they are of an unknown size"), abfd);
                bfd_set_error (bfd_error_invalid_operation);
                return 0;
              }
@@ -8595,8 +8743,9 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
                    /* Section size is only divisible by rela.  */
                    if (use_rela_initialised && (use_rela == FALSE))
                      {
-                       _bfd_error_handler
-                         (_("%B: Unable to sort relocs - they are in more than one size"), abfd);
+                       _bfd_error_handler (_("%B: Unable to sort relocs - "
+                                             "they are in more than one size"),
+                                           abfd);
                        bfd_set_error (bfd_error_invalid_operation);
                        return 0;
                      }
@@ -8612,8 +8761,9 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
                /* Section size is only divisible by rel.  */
                if (use_rela_initialised && (use_rela == TRUE))
                  {
-                   _bfd_error_handler
-                     (_("%B: Unable to sort relocs - they are in more than one size"), abfd);
+                   _bfd_error_handler (_("%B: Unable to sort relocs - "
+                                         "they are in more than one size"),
+                                       abfd);
                    bfd_set_error (bfd_error_invalid_operation);
                    return 0;
                  }
@@ -8625,9 +8775,10 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
              }
            else
              {
-               /* The section size is not divisible by either - something is wrong.  */
-               _bfd_error_handler
-                 (_("%B: Unable to sort relocs - they are of an unknown size"), abfd);
+               /* The section size is not divisible by either -
+                  something is wrong.  */
+               _bfd_error_handler (_("%B: Unable to sort relocs - "
+                                     "they are of an unknown size"), abfd);
                bfd_set_error (bfd_error_invalid_operation);
                return 0;
              }
@@ -8703,8 +8854,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
          }
        erel = o->contents;
        erelend = o->contents + o->size;
-       /* FIXME: octets_per_byte.  */
-       p = sort + o->output_offset / ext_size * sort_elt;
+       p = sort + o->output_offset * opb / ext_size * sort_elt;
 
        while (erel < erelend)
          {
@@ -8740,6 +8890,35 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
 
   qsort (s_non_relative, count - ret, sort_elt, elf_link_sort_cmp2);
 
+  struct elf_link_hash_table *htab = elf_hash_table (info);
+  if (htab->srelplt && htab->srelplt->output_section == dynamic_relocs)
+    {
+      /* We have plt relocs in .rela.dyn.  */
+      sq = (struct elf_link_sort_rela *) sort;
+      for (i = 0; i < count; i++)
+       if (sq[count - i - 1].type != reloc_class_plt)
+         break;
+      if (i != 0 && htab->srelplt->size == i * ext_size)
+       {
+         struct bfd_link_order **plo;
+         /* Put srelplt link_order last.  This is so the output_offset
+            set in the next loop is correct for DT_JMPREL.  */
+         for (plo = &dynamic_relocs->map_head.link_order; *plo != NULL; )
+           if ((*plo)->type == bfd_indirect_link_order
+               && (*plo)->u.indirect.section == htab->srelplt)
+             {
+               lo = *plo;
+               *plo = lo->next;
+             }
+           else
+             plo = &(*plo)->next;
+         *plo = lo;
+         lo->next = NULL;
+         dynamic_relocs->map_tail.link_order = lo;
+       }
+    }
+
+  p = sort;
   for (lo = dynamic_relocs->map_head.link_order; lo != NULL; lo = lo->next)
     if (lo->type == bfd_indirect_link_order)
       {
@@ -8748,8 +8927,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
 
        erel = o->contents;
        erelend = o->contents + o->size;
-       /* FIXME: octets_per_byte.  */
-       p = sort + o->output_offset / ext_size * sort_elt;
+       o->output_offset = (p - sort) / sort_elt * ext_size / opb;
        while (erel < erelend)
          {
            struct elf_link_sort_rela *s = (struct elf_link_sort_rela *) p;
@@ -8838,7 +9016,8 @@ static bfd_boolean
 elf_link_swap_symbols_out (struct elf_final_link_info *flinfo)
 {
   struct elf_link_hash_table *hash_table = elf_hash_table (flinfo->info);
-  bfd_size_type amt, i;
+  bfd_size_type amt;
+  size_t i;
   const struct elf_backend_data *bed;
   bfd_byte *symbuf;
   Elf_Internal_Shdr *hdr;
@@ -8859,8 +9038,8 @@ elf_link_swap_symbols_out (struct elf_final_link_info *flinfo)
 
   if (flinfo->symshndxbuf)
     {
-      amt = (sizeof (Elf_External_Sym_Shndx)
-            * (bfd_get_symcount (flinfo->output_bfd)));
+      amt = sizeof (Elf_External_Sym_Shndx);
+      amt *= bfd_get_symcount (flinfo->output_bfd);
       flinfo->symshndxbuf = (Elf_External_Sym_Shndx *) bfd_zmalloc (amt);
       if (flinfo->symshndxbuf == NULL)
        {
@@ -8916,7 +9095,8 @@ check_dynsym (bfd *abfd, Elf_Internal_Sym *sym)
     {
       /* The gABI doesn't support dynamic symbols in output sections
         beyond 64k.  */
-      (*_bfd_error_handler)
+      _bfd_error_handler
+       /* xgettext:c-format */
        (_("%B: Too many sections: %d (>= %d)"),
         abfd, bfd_count_sections (abfd), SHN_LORESERVE & 0xffff);
       bfd_set_error (bfd_error_nonrepresentable_section);
@@ -8955,7 +9135,8 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info,
     case bfd_link_hash_undefined:
     case bfd_link_hash_undefweak:
       abfd = h->root.u.undef.abfd;
-      if ((abfd->flags & DYNAMIC) == 0
+      if (abfd == NULL
+         || (abfd->flags & DYNAMIC) == 0
          || (elf_dyn_lib_class (abfd) & DYN_DT_NEEDED) == 0)
        return FALSE;
       break;
@@ -8977,9 +9158,9 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info,
     {
       bfd *input;
       Elf_Internal_Shdr *hdr;
-      bfd_size_type symcount;
-      bfd_size_type extsymcount;
-      bfd_size_type extsymoff;
+      size_t symcount;
+      size_t extsymcount;
+      size_t extsymoff;
       Elf_Internal_Shdr *versymhdr;
       Elf_Internal_Sym *isym;
       Elf_Internal_Sym *isymend;
@@ -9123,16 +9304,6 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
   long indx;
   int ret;
   unsigned int type;
-  /* A symbol is bound locally if it is forced local or it is locally
-     defined, hidden versioned, not referenced by shared library and
-     not exported when linking executable.  */
-  bfd_boolean local_bind = (h->forced_local
-                           || (bfd_link_executable (flinfo->info)
-                               && !flinfo->info->export_dynamic
-                               && !h->dynamic
-                               && !h->ref_dynamic
-                               && h->def_regular
-                               && h->versioned == versioned_hidden));
 
   if (h->root.type == bfd_link_hash_warning)
     {
@@ -9144,12 +9315,12 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
   /* Decide whether to output this symbol in this pass.  */
   if (eoinfo->localsyms)
     {
-      if (!local_bind)
+      if (!h->forced_local)
        return TRUE;
     }
   else
     {
-      if (local_bind)
+      if (h->forced_local)
        return TRUE;
     }
 
@@ -9175,19 +9346,15 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
          && (!h->ref_regular || flinfo->info->gc_sections)
          && !elf_link_check_versioned_symbol (flinfo->info, bed, h)
          && flinfo->info->unresolved_syms_in_shared_libs != RM_IGNORE)
-       {
-         if (!(flinfo->info->callbacks->undefined_symbol
-               (flinfo->info, h->root.root.string,
-                h->ref_regular ? NULL : h->root.u.undef.abfd,
-                NULL, 0,
-                (flinfo->info->unresolved_syms_in_shared_libs
-                 == RM_GENERATE_ERROR))))
-           {
-             bfd_set_error (bfd_error_bad_value);
-             eoinfo->failed = TRUE;
-             return FALSE;
-           }
-       }
+       (*flinfo->info->callbacks->undefined_symbol)
+         (flinfo->info, h->root.root.string,
+          h->ref_regular ? NULL : h->root.u.undef.abfd,
+          NULL, 0,
+          flinfo->info->unresolved_syms_in_shared_libs == RM_GENERATE_ERROR);
+
+      /* Strip a global symbol defined in a discarded section.  */
+      if (h->indx == -3)
+       return TRUE;
     }
 
   /* We should also warn if a forced local symbol is referenced from
@@ -9209,16 +9376,19 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
        hi = (struct elf_link_hash_entry *) hi->root.u.i.link;
 
       if (ELF_ST_VISIBILITY (h->other) == STV_INTERNAL)
+       /* xgettext:c-format */
        msg = _("%B: internal symbol `%s' in %B is referenced by DSO");
       else if (ELF_ST_VISIBILITY (h->other) == STV_HIDDEN)
+       /* xgettext:c-format */
        msg = _("%B: hidden symbol `%s' in %B is referenced by DSO");
       else
+       /* xgettext:c-format */
        msg = _("%B: local symbol `%s' in %B is referenced by DSO");
       def_bfd = flinfo->output_bfd;
       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_error_handler (msg, flinfo->output_bfd, def_bfd,
+                         h->root.root.string);
       bfd_set_error (bfd_error_bad_value);
       eoinfo->failed = TRUE;
       return FALSE;
@@ -9297,7 +9467,8 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
                                                 input_sec->output_section);
            if (sym.st_shndx == SHN_BAD)
              {
-               (*_bfd_error_handler)
+               _bfd_error_handler
+                 /* xgettext:c-format */
                  (_("%B: could not find output section %A for input section %A"),
                   flinfo->output_bfd, input_sec->output_section, input_sec);
                bfd_set_error (bfd_error_nonrepresentable_section);
@@ -9366,7 +9537,7 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
        abort ();
       }
 
-  if (local_bind)
+  if (h->forced_local)
     {
       sym.st_info = ELF_ST_INFO (STB_LOCAL, type);
       /* Turn off visibility on local symbol.  */
@@ -9451,12 +9622,15 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
       const char *msg;
 
       if (ELF_ST_VISIBILITY (sym.st_other) == STV_PROTECTED)
+       /* xgettext:c-format */
        msg = _("%B: protected symbol `%s' isn't defined");
       else if (ELF_ST_VISIBILITY (sym.st_other) == STV_INTERNAL)
+       /* xgettext:c-format */
        msg = _("%B: internal symbol `%s' isn't defined");
       else
+       /* xgettext:c-format */
        msg = _("%B: hidden symbol `%s' isn't defined");
-      (*_bfd_error_handler) (msg, flinfo->output_bfd, h->root.root.string);
+      _bfd_error_handler (msg, flinfo->output_bfd, h->root.root.string);
       bfd_set_error (bfd_error_bad_value);
       eoinfo->failed = TRUE;
       return FALSE;
@@ -9474,10 +9648,8 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
       /* 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 not linking executable, referenced
-        by shared library, not locally defined, or not bound locally.
-      */
+        by shared library, or not bound locally.  */
       if (h->verinfo.verdef == NULL
-         && !local_bind
          && (!bfd_link_executable (flinfo->info)
              || h->ref_dynamic
              || !h->def_regular))
@@ -9486,7 +9658,8 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
 
          if (p && p [1] != '\0')
            {
-             (*_bfd_error_handler)
+             _bfd_error_handler
+               /* xgettext:c-format */
                (_("%B: No symbol version section for versioned symbol `%s'"),
                 flinfo->output_bfd, h->root.root.string);
              eoinfo->failed = TRUE;
@@ -10090,7 +10263,8 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
            {
              if (o->size != o->reloc_count * address_size)
                {
-                 (*_bfd_error_handler)
+                 _bfd_error_handler
+                   /* xgettext:c-format */
                    (_("error: %B: size of section %A is not "
                       "multiple of address size"),
                     input_bfd, o);
@@ -10137,7 +10311,8 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                      char buffer [32];
 
                      sprintf_vma (buffer, rel->r_info);
-                     (*_bfd_error_handler)
+                     _bfd_error_handler
+                       /* xgettext:c-format */
                        (_("error: %B contains a reloc (0x%s) for section %A "
                           "that references a non-existent global symbol"),
                         input_bfd, o, buffer);
@@ -10222,6 +10397,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                      BFD_ASSERT (r_symndx != STN_UNDEF);
                      if (action_discarded & COMPLAIN)
                        (*flinfo->info->callbacks->einfo)
+                         /* xgettext:c-format */
                          (_("%X`%s' referenced in section `%A' of %B: "
                             "defined in discarded section `%A' of %B\n"),
                           sym_name, o, input_bfd, sec, sec->owner);
@@ -10697,9 +10873,8 @@ elf_reloc_link_order (bfd *output_bfd,
        }
       else
        {
-         if (! ((*info->callbacks->unattached_reloc)
-                (info, link_order->u.reloc.p->u.name, NULL, NULL, 0)))
-           return FALSE;
+         (*info->callbacks->unattached_reloc)
+           (info, link_order->u.reloc.p->u.name, NULL, NULL, 0);
          indx = 0;
        }
     }
@@ -10734,13 +10909,9 @@ elf_reloc_link_order (bfd *output_bfd,
                                         link_order->u.reloc.p->u.section);
          else
            sym_name = link_order->u.reloc.p->u.name;
-         if (! ((*info->callbacks->reloc_overflow)
-                (info, NULL, sym_name, howto->name, addend, NULL,
-                 NULL, (bfd_vma) 0)))
-           {
-             free (buf);
-             return FALSE;
-           }
+         (*info->callbacks->reloc_overflow) (info, NULL, sym_name,
+                                             howto->name, addend, NULL, NULL,
+                                             (bfd_vma) 0);
          break;
        }
 
@@ -10815,6 +10986,7 @@ elf_get_linked_section_vma (struct bfd_link_order *p)
        = get_elf_backend_data (s->owner);
       if (bed->link_order_error_handler)
        bed->link_order_error_handler
+         /* xgettext:c-format */
          (_("%B: warning: sh_link not set for section `%A'"), s->owner, s);
       return 0;
     }
@@ -10894,13 +11066,16 @@ elf_fixup_link_order (bfd *abfd, asection *o)
       if (seen_other && seen_linkorder)
        {
          if (other_sec && linkorder_sec)
-           (*_bfd_error_handler) (_("%A has both ordered [`%A' in %B] and unordered [`%A' in %B] sections"),
-                                  o, linkorder_sec,
-                                  linkorder_sec->owner, other_sec,
-                                  other_sec->owner);
+           _bfd_error_handler
+             /* xgettext:c-format */
+             (_("%A has both ordered [`%A' in %B] "
+                "and unordered [`%A' in %B] sections"),
+              o, linkorder_sec,
+              linkorder_sec->owner, other_sec,
+              other_sec->owner);
          else
-           (*_bfd_error_handler) (_("%A has both ordered and unordered sections"),
-                                  o);
+           _bfd_error_handler
+             (_("%A has both ordered and unordered sections"), o);
          bfd_set_error (bfd_error_bad_value);
          return FALSE;
        }
@@ -10938,6 +11113,108 @@ elf_fixup_link_order (bfd *abfd, asection *o)
   return TRUE;
 }
 
+/* Generate an import library in INFO->implib_bfd from symbols in ABFD.
+   Returns TRUE upon success, FALSE otherwise.  */
+
+static bfd_boolean
+elf_output_implib (bfd *abfd, struct bfd_link_info *info)
+{
+  bfd_boolean ret = FALSE;
+  bfd *implib_bfd;
+  const struct elf_backend_data *bed;
+  flagword flags;
+  enum bfd_architecture arch;
+  unsigned int mach;
+  asymbol **sympp = NULL;
+  long symsize;
+  long symcount;
+  long src_count;
+  elf_symbol_type *osymbuf;
+
+  implib_bfd = info->out_implib_bfd;
+  bed = get_elf_backend_data (abfd);
+
+  if (!bfd_set_format (implib_bfd, bfd_object))
+    return FALSE;
+
+  flags = bfd_get_file_flags (abfd);
+  flags &= ~HAS_RELOC;
+  if (!bfd_set_start_address (implib_bfd, 0)
+      || !bfd_set_file_flags (implib_bfd, flags))
+    return FALSE;
+
+  /* Copy architecture of output file to import library file.  */
+  arch = bfd_get_arch (abfd);
+  mach = bfd_get_mach (abfd);
+  if (!bfd_set_arch_mach (implib_bfd, arch, mach)
+      && (abfd->target_defaulted
+         || bfd_get_arch (abfd) != bfd_get_arch (implib_bfd)))
+    return FALSE;
+
+  /* Get symbol table size.  */
+  symsize = bfd_get_symtab_upper_bound (abfd);
+  if (symsize < 0)
+    return FALSE;
+
+  /* Read in the symbol table.  */
+  sympp = (asymbol **) xmalloc (symsize);
+  symcount = bfd_canonicalize_symtab (abfd, sympp);
+  if (symcount < 0)
+    goto free_sym_buf;
+
+  /* Allow the BFD backend to copy any private header data it
+     understands from the output BFD to the import library BFD.  */
+  if (! bfd_copy_private_header_data (abfd, implib_bfd))
+    goto free_sym_buf;
+
+  /* Filter symbols to appear in the import library.  */
+  if (bed->elf_backend_filter_implib_symbols)
+    symcount = bed->elf_backend_filter_implib_symbols (abfd, info, sympp,
+                                                      symcount);
+  else
+    symcount = _bfd_elf_filter_global_symbols (abfd, info, sympp, symcount);
+  if (symcount == 0)
+    {
+      bfd_set_error (bfd_error_no_symbols);
+      _bfd_error_handler (_("%B: no symbol found for import library"),
+                         implib_bfd);
+      goto free_sym_buf;
+    }
+
+
+  /* Make symbols absolute.  */
+  osymbuf = (elf_symbol_type *) bfd_alloc2 (implib_bfd, symcount,
+                                           sizeof (*osymbuf));
+  for (src_count = 0; src_count < symcount; src_count++)
+    {
+      memcpy (&osymbuf[src_count], (elf_symbol_type *) sympp[src_count],
+             sizeof (*osymbuf));
+      osymbuf[src_count].symbol.section = bfd_abs_section_ptr;
+      osymbuf[src_count].internal_elf_sym.st_shndx = SHN_ABS;
+      osymbuf[src_count].symbol.value += sympp[src_count]->section->vma;
+      osymbuf[src_count].internal_elf_sym.st_value =
+       osymbuf[src_count].symbol.value;
+      sympp[src_count] = &osymbuf[src_count].symbol;
+    }
+
+  bfd_set_symtab (implib_bfd, sympp, symcount);
+
+  /* Allow the BFD backend to copy any private data it understands
+     from the output BFD to the import library BFD.  This is done last
+     to permit the routine to look at the filtered symbol table.  */
+  if (! bfd_copy_private_bfd_data (abfd, implib_bfd))
+    goto free_sym_buf;
+
+  if (!bfd_close (implib_bfd))
+    goto free_sym_buf;
+
+  ret = TRUE;
+
+free_sym_buf:
+  free (sympp);
+  return ret;
+}
+
 static void
 elf_final_link_free (bfd *obfd, struct elf_final_link_info *flinfo)
 {
@@ -11003,15 +11280,16 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
   asection *attr_section = NULL;
   bfd_vma attr_size = 0;
   const char *std_attrs_section;
+  struct elf_link_hash_table *htab = elf_hash_table (info);
 
-  if (! is_elf_hash_table (info->hash))
+  if (!is_elf_hash_table (htab))
     return FALSE;
 
   if (bfd_link_pic (info))
     abfd->flags |= DYNAMIC;
 
-  dynamic = elf_hash_table (info)->dynamic_sections_created;
-  dynobj = elf_hash_table (info)->dynobj;
+  dynamic = htab->dynamic_sections_created;
+  dynobj = htab->dynobj;
 
   emit_relocs = (bfd_link_relocatable (info)
                 || info->emitrelocations);
@@ -11108,7 +11386,6 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
              asection *sec;
 
              sec = p->u.indirect.section;
-             esdi = elf_section_data (sec);
 
              /* Mark all sections which are to be included in the
                 link.  This will normally be every section.  We need
@@ -11119,37 +11396,18 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
              if (sec->flags & SEC_MERGE)
                merged = TRUE;
 
-             if (esdo->this_hdr.sh_type == SHT_REL
-                 || esdo->this_hdr.sh_type == SHT_RELA)
-               /* Some backends use reloc_count in relocation sections
-                  to count particular types of relocs.  Of course,
-                  reloc sections themselves can't have relocations.  */
-               reloc_count = 0;
-             else if (emit_relocs)
-               {
-                 reloc_count = sec->reloc_count;
-                 if (bed->elf_backend_count_additional_relocs)
-                   {
-                     int c;
-                     c = (*bed->elf_backend_count_additional_relocs) (sec);
-                     additional_reloc_count += c;
-                   }
-               }
-             else if (bed->elf_backend_count_relocs)
-               reloc_count = (*bed->elf_backend_count_relocs) (info, sec);
-
              if (sec->rawsize > max_contents_size)
                max_contents_size = sec->rawsize;
              if (sec->size > max_contents_size)
                max_contents_size = sec->size;
 
-             /* We are interested in just local symbols, not all
-                symbols.  */
              if (bfd_get_flavour (sec->owner) == bfd_target_elf_flavour
                  && (sec->owner->flags & DYNAMIC) == 0)
                {
                  size_t sym_count;
 
+                 /* We are interested in just local symbols, not all
+                    symbols.  */
                  if (elf_bad_symtab (sec->owner))
                    sym_count = (elf_tdata (sec->owner)->symtab_hdr.sh_size
                                 / bed->s->sizeof_sym);
@@ -11163,6 +11421,27 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
                      && elf_symtab_shndx_list (sec->owner) != NULL)
                    max_sym_shndx_count = sym_count;
 
+                 if (esdo->this_hdr.sh_type == SHT_REL
+                     || esdo->this_hdr.sh_type == SHT_RELA)
+                   /* Some backends use reloc_count in relocation sections
+                      to count particular types of relocs.  Of course,
+                      reloc sections themselves can't have relocations.  */
+                   ;
+                 else if (emit_relocs)
+                   {
+                     reloc_count = sec->reloc_count;
+                     if (bed->elf_backend_count_additional_relocs)
+                       {
+                         int c;
+                         c = (*bed->elf_backend_count_additional_relocs) (sec);
+                         additional_reloc_count += c;
+                       }
+                   }
+                 else if (bed->elf_backend_count_relocs)
+                   reloc_count = (*bed->elf_backend_count_relocs) (info, sec);
+
+                 esdi = elf_section_data (sec);
+
                  if ((sec->flags & SEC_RELOC) != 0)
                    {
                      size_t ext_size = 0;
@@ -11228,8 +11507,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
     }
 
   if (! bfd_link_relocatable (info) && merged)
-    elf_link_hash_traverse (elf_hash_table (info),
-                           _bfd_elf_link_sec_merge_syms, abfd);
+    elf_link_hash_traverse (htab, _bfd_elf_link_sec_merge_syms, abfd);
 
   /* Figure out the file positions for everything but the symbol table
      and the relocs.  We set symcount to force assign_section_numbers
@@ -11292,11 +11570,10 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 
   if (max_sym_count < 20)
     max_sym_count = 20;
-  elf_hash_table (info)->strtabsize = max_sym_count;
+  htab->strtabsize = max_sym_count;
   amt = max_sym_count * sizeof (struct elf_sym_strtab);
-  elf_hash_table (info)->strtab
-    = (struct elf_sym_strtab *) bfd_malloc (amt);
-  if (elf_hash_table (info)->strtab == NULL)
+  htab->strtab = (struct elf_sym_strtab *) bfd_malloc (amt);
+  if (htab->strtab == NULL)
     goto error_return;
   /* The real buffer will be allocated in elf_link_swap_symbols_out.  */
   flinfo.symshndxbuf
@@ -11408,12 +11685,12 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
        goto error_return;
     }
 
-  if (elf_hash_table (info)->tls_sec)
+  if (htab->tls_sec)
     {
       bfd_vma base, end = 0;
       asection *sec;
 
-      for (sec = elf_hash_table (info)->tls_sec;
+      for (sec = htab->tls_sec;
           sec && (sec->flags & SEC_THREAD_LOCAL);
           sec = sec->next)
        {
@@ -11429,13 +11706,12 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
            }
          end = sec->vma + size;
        }
-      base = elf_hash_table (info)->tls_sec->vma;
+      base = htab->tls_sec->vma;
       /* Only align end of TLS section if static TLS doesn't have special
         alignment requirements.  */
       if (bed->static_tls_alignment == 1)
-       end = align_power (end,
-                          elf_hash_table (info)->tls_sec->alignment_power);
-      elf_hash_table (info)->tls_size = end - base;
+       end = align_power (end, htab->tls_sec->alignment_power);
+      htab->tls_size = end - base;
     }
 
   /* Reorder SHF_LINK_ORDER sections.  */
@@ -11521,7 +11797,8 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
                        }
 
                      bfd_set_error (bfd_error_wrong_format);
-                     (*_bfd_error_handler)
+                     _bfd_error_handler
+                       /* xgettext:c-format */
                        (_("%B: file class %s incompatible with %s"),
                         sub, iclass, oclass);
                    }
@@ -11582,17 +11859,18 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
   symtab_hdr->sh_info = bfd_get_symcount (abfd);
 
   if (dynamic
-      && elf_hash_table (info)->dynsym != NULL
-      && (elf_hash_table (info)->dynsym->output_section
-         != bfd_abs_section_ptr))
+      && htab->dynsym != NULL
+      && htab->dynsym->output_section != bfd_abs_section_ptr)
     {
       Elf_Internal_Sym sym;
-      bfd_byte *dynsym = elf_hash_table (info)->dynsym->contents;
-      long last_local = 0;
+      bfd_byte *dynsym = htab->dynsym->contents;
+
+      o = htab->dynsym->output_section;
+      elf_section_data (o)->this_hdr.sh_info = htab->local_dynsymcount + 1;
 
       /* Write out the section symbols for the output sections.  */
       if (bfd_link_pic (info)
-         || elf_hash_table (info)->is_relocatable_executable)
+         || htab->is_relocatable_executable)
        {
          asection *s;
 
@@ -11618,17 +11896,15 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
                return FALSE;
              sym.st_value = s->vma;
              dest = dynsym + dynindx * bed->s->sizeof_sym;
-             if (last_local < dynindx)
-               last_local = dynindx;
              bed->s->swap_symbol_out (abfd, &sym, dest, 0);
            }
        }
 
       /* Write out the local dynsyms.  */
-      if (elf_hash_table (info)->dynlocal)
+      if (htab->dynlocal)
        {
          struct elf_link_local_dynamic_entry *e;
-         for (e = elf_hash_table (info)->dynlocal; e ; e = e->next)
+         for (e = htab->dynlocal; e ; e = e->next)
            {
              asection *s;
              bfd_byte *dest;
@@ -11652,16 +11928,10 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
                                  + e->isym.st_value);
                }
 
-             if (last_local < e->dynindx)
-               last_local = e->dynindx;
-
              dest = dynsym + e->dynindx * bed->s->sizeof_sym;
              bed->s->swap_symbol_out (abfd, &sym, dest, 0);
            }
        }
-
-      elf_section_data (elf_hash_table (info)->dynsym->output_section)->this_hdr.sh_info =
-       last_local + 1;
     }
 
   /* We get the global symbols from the hash table.  */
@@ -11740,6 +12010,13 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
        return FALSE;
     }
 
+  if (info->out_implib_bfd && !elf_output_implib (abfd, info))
+    {
+      _bfd_error_handler (_("%B: failed to generate import library"),
+                         info->out_implib_bfd);
+      return FALSE;
+    }
+
   /* Adjust the relocs to have the correct symbol indices.  */
   for (o = abfd->sections; o != NULL; o = o->next)
     {
@@ -11750,10 +12027,10 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 
       sort = bed->sort_relocs_p == NULL || (*bed->sort_relocs_p) (o);
       if (esdo->rel.hdr != NULL
-         && !elf_link_adjust_relocs (abfd, &esdo->rel, sort))
+         && !elf_link_adjust_relocs (abfd, o, &esdo->rel, sort))
        return FALSE;
       if (esdo->rela.hdr != NULL
-         && !elf_link_adjust_relocs (abfd, &esdo->rela, sort))
+         && !elf_link_adjust_relocs (abfd, o, &esdo->rela, sort))
        return FALSE;
 
       /* Set the reloc_count field to 0 to prevent write_relocs from
@@ -11812,8 +12089,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
              {
                struct elf_link_hash_entry *h;
 
-               h = elf_link_hash_lookup (elf_hash_table (info), name,
-                                         FALSE, FALSE, TRUE);
+               h = elf_link_hash_lookup (htab, name, FALSE, FALSE, TRUE);
                if (h != NULL
                    && (h->root.type == bfd_link_hash_defined
                        || h->root.type == bfd_link_hash_defweak))
@@ -11836,35 +12112,37 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 
            case DT_PREINIT_ARRAYSZ:
              name = ".preinit_array";
-             goto get_size;
+             goto get_out_size;
            case DT_INIT_ARRAYSZ:
              name = ".init_array";
-             goto get_size;
+             goto get_out_size;
            case DT_FINI_ARRAYSZ:
              name = ".fini_array";
-           get_size:
+           get_out_size:
              o = bfd_get_section_by_name (abfd, name);
              if (o == NULL)
                {
-                 (*_bfd_error_handler)
-                   (_("%B: could not find output section %s"), abfd, name);
+                 _bfd_error_handler
+                   (_("could not find section %s"), name);
                  goto error_return;
                }
              if (o->size == 0)
-               (*_bfd_error_handler)
+               _bfd_error_handler
                  (_("warning: %s section has zero size"), name);
              dyn.d_un.d_val = o->size;
              break;
 
            case DT_PREINIT_ARRAY:
              name = ".preinit_array";
-             goto get_vma;
+             goto get_out_vma;
            case DT_INIT_ARRAY:
              name = ".init_array";
-             goto get_vma;
+             goto get_out_vma;
            case DT_FINI_ARRAY:
              name = ".fini_array";
-             goto get_vma;
+           get_out_vma:
+             o = bfd_get_section_by_name (abfd, name);
+             goto do_vma;
 
            case DT_HASH:
              name = ".hash";
@@ -11887,21 +12165,22 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
            case DT_VERSYM:
              name = ".gnu.version";
            get_vma:
-             o = bfd_get_section_by_name (abfd, name);
+             o = bfd_get_linker_section (dynobj, name);
+           do_vma:
              if (o == NULL)
                {
-                 (*_bfd_error_handler)
-                   (_("%B: could not find output section %s"), abfd, name);
+                 _bfd_error_handler
+                   (_("could not find section %s"), name);
                  goto error_return;
                }
              if (elf_section_data (o->output_section)->this_hdr.sh_type == SHT_NOTE)
                {
-                 (*_bfd_error_handler)
+                 _bfd_error_handler
                    (_("warning: section '%s' is being made into a note"), name);
                  bfd_set_error (bfd_error_nonrepresentable_section);
                  goto error_return;
                }
-             dyn.d_un.d_ptr = o->vma;
+             dyn.d_un.d_ptr = o->output_section->vma + o->output_offset;
              break;
 
            case DT_REL:
@@ -11932,6 +12211,18 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
                        }
                    }
                }
+             if (bed->dtrel_excludes_plt && htab->srelplt != NULL)
+               {
+                 /* Don't count procedure linkage table relocs in the
+                    overall reloc count.  */
+                 if (dyn.d_tag == DT_RELSZ || dyn.d_tag == DT_RELASZ)
+                   dyn.d_un.d_val -= htab->srelplt->size;
+                 /* If .rela.plt is the first .rela section, exclude
+                    it from DT_RELA.  */
+                 else if (dyn.d_un.d_ptr == (htab->srelplt->output_section->vma
+                                             + htab->srelplt->output_offset))
+                   dyn.d_un.d_ptr += htab->srelplt->size;
+               }
              break;
            }
          bed->s->swap_dyn_out (dynobj, &dyn, dyncon);
@@ -11984,9 +12275,9 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
                 created by _bfd_elf_link_create_dynamic_sections.  */
              continue;
            }
-         if (elf_hash_table (info)->stab_info.stabstr == o)
+         if (htab->stab_info.stabstr == o)
            continue;
-         if (elf_hash_table (info)->eh_info.hdr_sec == o)
+         if (htab->eh_info.hdr_sec == o)
            continue;
          if (strcmp (o->name, ".dynstr") != 0)
            {
@@ -12005,8 +12296,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 
              off = elf_section_data (o->output_section)->this_hdr.sh_offset;
              if (bfd_seek (abfd, off, SEEK_SET) != 0
-                 || ! _bfd_elf_strtab_emit (abfd,
-                                            elf_hash_table (info)->dynstr))
+                 || !_bfd_elf_strtab_emit (abfd, htab->dynstr))
                goto error_return;
            }
        }
@@ -12022,9 +12312,9 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
     }
 
   /* If we have optimized stabs strings, output them.  */
-  if (elf_hash_table (info)->stab_info.stabstr != NULL)
+  if (htab->stab_info.stabstr != NULL)
     {
-      if (! _bfd_write_stab_strings (abfd, &elf_hash_table (info)->stab_info))
+      if (!_bfd_write_stab_strings (abfd, &htab->stab_info))
        goto error_return;
     }
 
@@ -12217,6 +12507,55 @@ _bfd_elf_gc_mark_hook (asection *sec,
   return NULL;
 }
 
+/* For undefined __start_<name> and __stop_<name> symbols, return the
+   first input section matching <name>.  Return NULL otherwise.  */
+
+asection *
+_bfd_elf_is_start_stop (const struct bfd_link_info *info,
+                       struct elf_link_hash_entry *h)
+{
+  asection *s;
+  const char *sec_name;
+
+  if (h->root.type != bfd_link_hash_undefined
+      && h->root.type != bfd_link_hash_undefweak)
+    return NULL;
+
+  s = h->root.u.undef.section;
+  if (s != NULL)
+    {
+      if (s == (asection *) 0 - 1)
+       return NULL;
+      return s;
+    }
+
+  sec_name = NULL;
+  if (strncmp (h->root.root.string, "__start_", 8) == 0)
+    sec_name = h->root.root.string + 8;
+  else if (strncmp (h->root.root.string, "__stop_", 7) == 0)
+    sec_name = h->root.root.string + 7;
+
+  if (sec_name != NULL && *sec_name != '\0')
+    {
+      bfd *i;
+
+      for (i = info->input_bfds; i != NULL; i = i->link.next)
+       {
+         s = bfd_get_section_by_name (i, sec_name);
+         if (s != NULL)
+           {
+             h->root.u.undef.section = s;
+             break;
+           }
+       }
+    }
+
+  if (s == NULL)
+    h->root.u.undef.section = (asection *) 0 - 1;
+
+  return s;
+}
+
 /* COOKIE->rel describes a relocation against section SEC, which is
    a section we've decided to keep.  Return the section that contains
    the relocation symbol, or NULL if no section contains it.  */
@@ -12255,34 +12594,19 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec,
       if (h->u.weakdef != NULL)
        h->u.weakdef->mark = 1;
 
-      if (start_stop != NULL
-         && (h->root.type == bfd_link_hash_undefined
-             || h->root.type == bfd_link_hash_undefweak))
+      if (start_stop != NULL)
        {
          /* To work around a glibc bug, mark all XXX input sections
             when there is an as yet undefined reference to __start_XXX
             or __stop_XXX symbols.  The linker will later define such
             symbols for orphan input sections that have a name
             representable as a C identifier.  */
-         const char *sec_name = NULL;
-         if (strncmp (h->root.root.string, "__start_", 8) == 0)
-           sec_name = h->root.root.string + 8;
-         else if (strncmp (h->root.root.string, "__stop_", 7) == 0)
-           sec_name = h->root.root.string + 7;
+         asection *s = _bfd_elf_is_start_stop (info, h);
 
-         if (sec_name != NULL && *sec_name != '\0')
+         if (s != NULL)
            {
-             bfd *i;
-
-             for (i = info->input_bfds; i != NULL; i = i->link.next)
-               {
-                 asection *s = bfd_get_section_by_name (i, sec_name);
-                 if (s != NULL && !s->gc_mark)
-                   {
-                     *start_stop = TRUE;
-                     return s;
-                   }
-               }
+             *start_stop = !s->gc_mark;
+             return s;
            }
        }
 
@@ -12602,6 +12926,7 @@ elf_gc_sweep (bfd *abfd, struct bfd_link_info *info)
          o->flags |= SEC_EXCLUDE;
 
          if (info->print_gc_sections && o->size != 0)
+           /* xgettext:c-format */
            _bfd_error_handler (_("Removing unused section '%s' in file '%B'"), sub, o->name);
 
          /* But we also have to update some of the relocation
@@ -12767,6 +13092,7 @@ bfd_elf_gc_mark_dynamic_ref_symbol (struct elf_link_hash_entry *h, void *inf)
              && ELF_ST_VISIBILITY (h->other) != STV_INTERNAL
              && ELF_ST_VISIBILITY (h->other) != STV_HIDDEN
              && (!bfd_link_executable (info)
+                 || info->gc_keep_exported
                  || info->export_dynamic
                  || (h->dynamic
                      && d != NULL
@@ -12797,7 +13123,8 @@ _bfd_elf_gc_keep (struct bfd_link_info *info)
       if (h != NULL
          && (h->root.type == bfd_link_hash_defined
              || h->root.type == bfd_link_hash_defweak)
-         && !bfd_is_abs_section (h->root.u.def.section))
+         && !bfd_is_abs_section (h->root.u.def.section)
+         && !bfd_is_und_section (h->root.u.def.section))
        h->root.u.def.section->flags |= SEC_KEEP;
     }
 }
@@ -12846,7 +13173,7 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
   if (!bed->can_gc_sections
       || !is_elf_hash_table (info->hash))
     {
-      (*_bfd_error_handler)(_("Warning: gc-sections option ignored"));
+      _bfd_error_handler(_("Warning: gc-sections option ignored"));
       return TRUE;
     }
 
@@ -12885,7 +13212,7 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
     return FALSE;
 
   /* Mark dynamically referenced symbols.  */
-  if (htab->dynamic_sections_created)
+  if (htab->dynamic_sections_created || info->gc_keep_exported)
     elf_link_hash_traverse (htab, bed->gc_mark_dynamic_ref, info);
 
   /* Grovel through relocs to find out who stays ...  */
@@ -12930,7 +13257,7 @@ bfd_elf_gc_record_vtinherit (bfd *abfd,
 {
   struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
   struct elf_link_hash_entry **search, *child;
-  bfd_size_type extsymcount;
+  size_t extsymcount;
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
   /* The sh_info field of the symtab header tells us where the
@@ -12955,8 +13282,9 @@ bfd_elf_gc_record_vtinherit (bfd *abfd,
        goto win;
     }
 
-  (*_bfd_error_handler) ("%B: %A+%lu: No symbol found for INHERIT",
-                        abfd, sec, (unsigned long) offset);
+  /* xgettext:c-format */
+  _bfd_error_handler (_("%B: %A+%lu: No symbol found for INHERIT"),
+                     abfd, sec, (unsigned long) offset);
   bfd_set_error (bfd_error_invalid_operation);
   return FALSE;
 
@@ -13203,7 +13531,7 @@ bfd_elf_gc_common_finalize_got_offsets (bfd *abfd,
   for (i = info->input_bfds; i; i = i->link.next)
     {
       bfd_signed_vma *local_got;
-      bfd_size_type j, locsymcount;
+      size_t j, locsymcount;
       Elf_Internal_Shdr *symtab_hdr;
 
       if (bfd_get_flavour (i) != bfd_target_elf_flavour)
This page took 0.056322 seconds and 4 git commands to generate.