Add c-format tags to translatable strings with more than one argument-using formattin...
[deliverable/binutils-gdb.git] / bfd / elflink.c
index 5f2fa526f0185b4cef4c428189397446fa6b0d47..76f91e93dbf78dcef87a899f11fbfc9634b5838b 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.  */
@@ -468,7 +472,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
@@ -519,7 +523,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;
     }
@@ -698,7 +702,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)];
@@ -753,7 +757,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;
 
@@ -900,6 +904,7 @@ _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,
@@ -1202,21 +1207,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;
@@ -1255,22 +1259,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);
@@ -1481,10 +1489,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;
 
@@ -1642,9 +1648,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.  */
@@ -1784,6 +1789,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.  */
@@ -1911,7 +1941,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);
     }
@@ -2083,7 +2114,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;
@@ -2173,8 +2203,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;
@@ -2204,7 +2234,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);
@@ -2292,7 +2323,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,
@@ -2303,7 +2335,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,
@@ -2493,7 +2526,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);
@@ -2775,7 +2809,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);
 
@@ -3092,9 +3126,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;
@@ -3104,15 +3138,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;
@@ -3212,14 +3256,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)
@@ -3387,7 +3431,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;
 
@@ -3419,7 +3463,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;
 
@@ -3569,16 +3613,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;
@@ -3594,8 +3638,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;
@@ -3632,6 +3675,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);
 
@@ -3960,7 +4004,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;
@@ -4039,8 +4084,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++)
        {
@@ -4272,7 +4318,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);
@@ -4308,7 +4355,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);
@@ -4380,6 +4428,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.  */
@@ -4530,7 +4583,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)
@@ -4556,13 +4610,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,
@@ -4578,7 +4634,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,
@@ -4613,7 +4670,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);
@@ -4714,7 +4772,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);
@@ -4760,7 +4819,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;
@@ -4773,9 +4834,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
@@ -4836,7 +4894,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)
        {
@@ -4907,7 +4965,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;
@@ -5097,6 +5156,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)
@@ -5278,7 +5339,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;
 
@@ -5716,11 +5777,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;
     }
@@ -5767,14 +5830,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;
@@ -5855,7 +5918,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;
        }
@@ -5869,12 +5932,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;
@@ -5884,11 +5947,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;
        }
@@ -5899,11 +5962,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;
            }
@@ -5911,22 +5974,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;
        }
@@ -6016,7 +6079,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;
@@ -6084,7 +6147,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;
@@ -6234,7 +6297,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);
@@ -6244,13 +6307,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;
            }
@@ -6469,7 +6532,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)
@@ -6482,7 +6545,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);
@@ -6501,7 +6564,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)
@@ -7280,7 +7343,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;
 };
 
@@ -7314,12 +7377,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)
@@ -7366,7 +7429,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));
 
@@ -7384,12 +7447,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;
 
@@ -7452,7 +7515,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;
 
@@ -7850,6 +7913,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);
 }
@@ -7896,6 +7960,7 @@ eval_symbol (bfd_vma *result,
 
     case 'S':
       symbol_is_section = TRUE;
+      /* Fall through.  */
     case 's':
       ++sym;
       symlen = strtol (sym, (char **) symp, 10);
@@ -8286,6 +8351,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)
 {
@@ -8344,6 +8410,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 *);
@@ -8893,7 +8962,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;
@@ -8914,8 +8984,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)
        {
@@ -8971,7 +9041,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);
@@ -9010,7 +9081,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;
@@ -9032,9 +9104,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;
@@ -9230,19 +9302,11 @@ 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)
@@ -9268,16 +9332,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;
@@ -9356,7 +9423,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);
@@ -9510,12 +9578,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;
@@ -9545,7 +9616,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;
@@ -10149,7 +10221,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);
@@ -10196,7 +10269,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);
@@ -10281,6 +10355,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);
@@ -10756,9 +10831,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;
        }
     }
@@ -10793,13 +10867,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;
        }
 
@@ -10874,6 +10944,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;
     }
@@ -10953,13 +11024,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;
        }
@@ -10997,6 +11071,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)
 {
@@ -11580,7 +11756,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);
                    }
@@ -11647,7 +11824,10 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
     {
       Elf_Internal_Sym sym;
       bfd_byte *dynsym = elf_hash_table (info)->dynsym->contents;
-      long last_local = 0;
+
+      o = elf_hash_table (info)->dynsym->output_section;
+      elf_section_data (o)->this_hdr.sh_info
+       = elf_hash_table (info)->local_dynsymcount + 1;
 
       /* Write out the section symbols for the output sections.  */
       if (bfd_link_pic (info)
@@ -11677,8 +11857,6 @@ 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);
            }
        }
@@ -11711,16 +11889,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.  */
@@ -11799,6 +11971,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)
     {
@@ -11809,10 +11988,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
@@ -11895,35 +12074,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";
@@ -11946,21 +12127,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:
@@ -12695,6 +12877,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
@@ -12890,7 +13073,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;
     }
 }
@@ -12939,7 +13123,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;
     }
 
@@ -13023,7 +13207,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
@@ -13048,8 +13232,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;
 
@@ -13296,7 +13481,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.045972 seconds and 4 git commands to generate.