* elf-bfd.h (elf_backend_emit_relocs): Change prototype to return
[deliverable/binutils-gdb.git] / bfd / elflink.h
index 47927d3830e46e6468cc415b1c5fe573b8415b8b..4c5661b4505fca05dd39eb1d57ac56997ab534d3 100644 (file)
@@ -1,5 +1,5 @@
 /* ELF linker support.
-   Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001
+   Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
    Free Software Foundation, Inc.
 
 This file is part of BFD, the Binary File Descriptor library.
@@ -57,8 +57,6 @@ static boolean elf_adjust_dynamic_symbol
   PARAMS ((struct elf_link_hash_entry *, PTR));
 static boolean elf_link_find_version_dependencies
   PARAMS ((struct elf_link_hash_entry *, PTR));
-static boolean elf_link_find_version_dependencies
-  PARAMS ((struct elf_link_hash_entry *, PTR));
 static boolean elf_link_assign_sym_version
   PARAMS ((struct elf_link_hash_entry *, PTR));
 static boolean elf_collect_hash_codes
@@ -67,7 +65,7 @@ static boolean elf_link_read_relocs_from_section
   PARAMS ((bfd *, Elf_Internal_Shdr *, PTR, Elf_Internal_Rela *));
 static size_t compute_bucket_count
   PARAMS ((struct bfd_link_info *));
-static void elf_link_output_relocs
+static boolean elf_link_output_relocs
   PARAMS ((bfd *, asection *, Elf_Internal_Shdr *, Elf_Internal_Rela *));
 static boolean elf_link_size_reloc_section
   PARAMS ((bfd *, Elf_Internal_Shdr *, asection *));
@@ -592,7 +590,7 @@ elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash,
       asection *hsec;
 
       /* This code handles the special SHN_MIPS_{TEXT,DATA} section
-         indices used by MIPS ELF.  */
+        indices used by MIPS ELF.  */
       switch (h->root.type)
        {
        default:
@@ -702,10 +700,10 @@ elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash,
       && sym->st_size != h->size)
     {
       /* Since we think we have two common symbols, issue a multiple
-         common warning if desired.  Note that we only warn if the
-         size is different.  If the size is the same, we simply let
-         the old symbol override the new one as normally happens with
-         symbols defined in dynamic objects.  */
+        common warning if desired.  Note that we only warn if the
+        size is different.  If the size is the same, we simply let
+        the old symbol override the new one as normally happens with
+        symbols defined in dynamic objects.  */
 
       if (! ((*info->callbacks->multiple_common)
             (info, h->root.root.string, oldbfd, bfd_link_hash_common,
@@ -755,10 +753,10 @@ elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash,
       *size_change_ok = true;
 
       /* If we get here when the old symbol is a common symbol, then
-         we are explicitly letting it override a weak symbol or
-         function in a dynamic object, and we don't want to warn about
-         a type change.  If the old symbol is a defined symbol, a type
-         change warning may still be appropriate.  */
+        we are explicitly letting it override a weak symbol or
+        function in a dynamic object, and we don't want to warn about
+        a type change.  If the old symbol is a defined symbol, a type
+        change warning may still be appropriate.  */
 
       if (h->root.type == bfd_link_hash_common)
        *type_change_ok = true;
@@ -817,7 +815,7 @@ elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash,
       olddyncommon = false;
 
       /* We again permit a type change when a common symbol may be
-         overriding a function.  */
+        overriding a function.  */
 
       if (bfd_is_com_section (sec))
        *type_change_ok = true;
@@ -829,11 +827,11 @@ elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash,
       h->verinfo.vertree = NULL;
 
       /* In this special case, if H is the target of an indirection,
-         we want the caller to frob with H rather than with the
-         indirect symbol.  That will permit the caller to redefine the
-         target of the indirection, rather than the indirect symbol
-         itself.  FIXME: This will break the -y option if we store a
-         symbol with a different name.  */
+        we want the caller to frob with H rather than with the
+        indirect symbol.  That will permit the caller to redefine the
+        target of the indirection, rather than the indirect symbol
+        itself.  FIXME: This will break the -y option if we store a
+        symbol with a different name.  */
       *sym_hash = h;
     }
 
@@ -856,7 +854,7 @@ elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash,
        return false;
 
       /* If the predumed common symbol in the dynamic object is
-         larger, pretend that the new symbol has its size.  */
+        larger, pretend that the new symbol has its size.  */
 
       if (h->size > *pvalue)
        *pvalue = h->size;
@@ -890,8 +888,8 @@ elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash,
       && bind != STB_WEAK)
     {
       /* To make this work we have to frob the flags so that the rest
-         of the code does not think we are using the regular
-         definition.  */
+        of the code does not think we are using the regular
+        definition.  */
       if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0)
        h->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR;
       else if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0)
@@ -900,9 +898,9 @@ elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash,
                                   | ELF_LINK_HASH_DEF_DYNAMIC);
 
       /* If H is the target of an indirection, we want the caller to
-         use H rather than the indirect symbol.  Otherwise if we are
-         defining a new indirect symbol we will wind up attaching it
-         to the entry we are overriding.  */
+        use H rather than the indirect symbol.  Otherwise if we are
+        defining a new indirect symbol we will wind up attaching it
+        to the entry we are overriding.  */
       *sym_hash = h;
     }
 
@@ -1047,7 +1045,7 @@ elf_add_default_symbol (abfd, info, h, name, sym, sec, value,
        }
 
       /* Now set HI to H, so that the following code will set the
-         other fields correctly.  */
+        other fields correctly.  */
       hi = h;
     }
 
@@ -1133,7 +1131,7 @@ elf_add_default_symbol (abfd, info, h, name, sym, sec, value,
                       & (ELF_LINK_HASH_DEF_DYNAMIC
                          | ELF_LINK_HASH_DEF_REGULAR)) == 0);
 
-          (*bed->elf_backend_copy_indirect_symbol) (h, hi);
+         (*bed->elf_backend_copy_indirect_symbol) (h, hi);
 
          /* See if the new flags lead us to realize that the symbol
             must be dynamic.  */
@@ -1259,8 +1257,8 @@ elf_link_add_object_symbols (abfd, info)
                          || h->root.type == bfd_link_hash_defweak))
                    {
                      /* We don't want to issue this warning.  Clobber
-                         the section size so that the warning does not
-                         get copied into the output file.  */
+                        the section size so that the warning does not
+                        get copied into the output file.  */
                      s->_raw_size = 0;
                      continue;
                    }
@@ -1284,7 +1282,7 @@ elf_link_add_object_symbols (abfd, info)
              if (! info->relocateable)
                {
                  /* Clobber the section size so that the warning does
-                     not get copied into the output file.  */
+                    not get copied into the output file.  */
                  s->_raw_size = 0;
                }
            }
@@ -1315,7 +1313,7 @@ elf_link_add_object_symbols (abfd, info)
        goto error_return;
 
       /* Read in the symbol versions, but don't bother to convert them
-         to internal format.  */
+        to internal format.  */
       if (elf_dynversym (abfd) != 0)
        {
          Elf_Internal_Shdr *versymhdr;
@@ -1373,10 +1371,10 @@ elf_link_add_object_symbols (abfd, info)
   if (! dynamic)
     {
       /* If we are creating a shared library, create all the dynamic
-         sections immediately.  We need to attach them to something,
-         so we attach them to this BFD, provided it is the right
-         format.  FIXME: If there are no input BFD's of the same
-         format as the output, we can't make a shared library.  */
+        sections immediately.  We need to attach them to something,
+        so we attach them to this BFD, provided it is the right
+        format.  FIXME: If there are no input BFD's of the same
+        format as the output, we can't make a shared library.  */
       if (info->shared
          && is_elf_hash_table (info)
          && ! hash_table->dynamic_sections_created
@@ -1411,7 +1409,7 @@ elf_link_add_object_symbols (abfd, info)
          if (*name == '\0')
            {
              if (elf_dt_soname (abfd) != NULL)
-               dt_needed = true;
+               dt_needed = true;
 
              add_needed = false;
            }
@@ -1531,7 +1529,7 @@ elf_link_add_object_symbols (abfd, info)
                }
              /* Ignore DT_RPATH if we have seen DT_RUNPATH.  */
              if (!runpath && dyn.d_tag == DT_RPATH)
-               {
+               {
                  struct bfd_link_needed_list *n, **pn;
                  char *fnm, *anm;
                  unsigned int tagv = dyn.d_un.d_val;
@@ -1623,7 +1621,7 @@ elf_link_add_object_symbols (abfd, info)
        }
 
       /* Save the SONAME, if there is one, because sometimes the
-         linker emulation code will need to know it.  */
+        linker emulation code will need to know it.  */
       if (*name == '\0')
        name = basename (bfd_get_filename (abfd));
       elf_dt_name (abfd) = name;
@@ -1764,10 +1762,10 @@ elf_link_add_object_symbols (abfd, info)
              vernum = iver.vs_vers & VERSYM_VERSION;
 
              /* If this is a hidden symbol, or if it is not version
-                 1, we append the version name to the symbol name.
-                 However, we do not modify a non-hidden absolute
-                 symbol, because it might be the version symbol
-                 itself.  FIXME: What if it isn't?  */
+                1, we append the version name to the symbol name.
+                However, we do not modify a non-hidden absolute
+                symbol, because it might be the version symbol
+                itself.  FIXME: What if it isn't?  */
              if ((iver.vs_vers & VERSYM_HIDDEN) != 0
                  || (vernum > 1 && ! bfd_is_abs_section (sec)))
                {
@@ -1866,10 +1864,10 @@ elf_link_add_object_symbols (abfd, info)
            h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
          /* Remember the old alignment if this is a common symbol, so
-             that we don't reduce the alignment later on.  We can't
-             check later, because _bfd_generic_link_add_one_symbol
-             will set a default for the alignment which we want to
-             override.  */
+            that we don't reduce the alignment later on.  We can't
+            check later, because _bfd_generic_link_add_one_symbol
+            will set a default for the alignment which we want to
+            override.  */
          if (h->root.type == bfd_link_hash_common)
            old_alignment = h->root.u.c.p->alignment_power;
 
@@ -1950,10 +1948,10 @@ elf_link_add_object_symbols (abfd, info)
            }
 
          /* If this is a common symbol, then we always want H->SIZE
-             to be the size of the common symbol.  The code just above
-             won't fix the size if a common symbol becomes larger.  We
-             don't warn about a size change here, because that is
-             covered by --warn-common.  */
+            to be the size of the common symbol.  The code just above
+            won't fix the size if a common symbol becomes larger.  We
+            don't warn about a size change here, because that is
+            covered by --warn-common.  */
          if (h->root.type == bfd_link_hash_common)
            h->size = h->root.u.c.size;
 
@@ -1983,8 +1981,8 @@ elf_link_add_object_symbols (abfd, info)
                h->other = sym.st_other;
 
              /* If neither has visibility, use the st_other of the
-                definition.  This is an arbitrary choice, since the
-                other bits have no general meaning.  */
+                definition.  This is an arbitrary choice, since the
+                other bits have no general meaning.  */
              if (!symvis && !hvis
                  && (definition || h->other == 0))
                h->other = sym.st_other;
@@ -2071,7 +2069,7 @@ elf_link_add_object_symbols (abfd, info)
                goto error_return;
 
              /* The symbol from a DT_NEEDED object is referenced from
-                the regular object to create a dynamic executable. We
+                the regular object to create a dynamic executable. We
                 have to make sure there is a DT_NEEDED entry for it.  */
 
              dt_needed = false;
@@ -2167,10 +2165,10 @@ elf_link_add_object_symbols (abfd, info)
                }
 
              /* If the real definition is in the list of dynamic
-                 symbols, make sure the weak definition is put there
-                 as well.  If we don't do this, then the dynamic
-                 loader might not merge the entries for the real
-                 definition and the weak definition.  */
+                symbols, make sure the weak definition is put there
+                as well.  If we don't do this, then the dynamic
+                loader might not merge the entries for the real
+                definition and the weak definition.  */
              if (h->dynindx != -1
                  && hlook->dynindx == -1)
                {
@@ -2260,7 +2258,9 @@ elf_link_add_object_symbols (abfd, info)
       asection *stab, *stabstr;
 
       stab = bfd_get_section_by_name (abfd, ".stab");
-      if (stab != NULL && !(stab->flags & SEC_MERGE))
+      if (stab != NULL
+         && (stab->flags & SEC_MERGE) == 0
+         && !bfd_is_abs_section (stab->output_section))
        {
          stabstr = bfd_get_section_by_name (abfd, ".stabstr");
 
@@ -2286,7 +2286,8 @@ elf_link_add_object_symbols (abfd, info)
       asection *s;
 
       for (s = abfd->sections; s != NULL; s = s->next)
-       if (s->flags & SEC_MERGE)
+       if ((s->flags & SEC_MERGE) != 0
+           && !bfd_is_abs_section (s->output_section))
          {
            struct bfd_elf_section_data *secdata;
 
@@ -2795,10 +2796,6 @@ NAME(bfd_elf,record_link_assignment) (output_bfd, info, name, provide)
 
   h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
 
-  /* When possible, keep the original type of the symbol.  */
-  if (h->type == STT_NOTYPE)
-    h->type = STT_OBJECT;
-
   if (((h->elf_link_hash_flags & (ELF_LINK_HASH_DEF_DYNAMIC
                                  | ELF_LINK_HASH_REF_DYNAMIC)) != 0
        || info->shared)
@@ -3140,11 +3137,11 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
       eif.failed = false;
 
       /* If we are supposed to export all symbols into the dynamic symbol
-         table (this is not the normal case), then do so.  */
+        table (this is not the normal case), then do so.  */
       if (info->export_dynamic)
        {
          elf_link_hash_traverse (elf_hash_table (info), elf_export_symbol,
-                                 (PTR) &eif);
+                                 (PTR) &eif);
          if (eif.failed)
            return false;
        }
@@ -3200,6 +3197,53 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
            return false;
        }
 
+      if (bfd_get_section_by_name (output_bfd, ".preinit_array") != NULL)
+       {
+         /* DT_PREINIT_ARRAY is not allowed in shared library.  */
+         if (info->shared)
+           {
+             bfd *sub;
+             asection *o;
+
+             for (sub = info->input_bfds; sub != NULL;
+                  sub = sub->link_next)
+               for (o = sub->sections; o != NULL; o = o->next)
+                 if (elf_section_data (o)->this_hdr.sh_type
+                     == SHT_PREINIT_ARRAY)
+                   {
+                     (*_bfd_error_handler)
+                       (_("%s: .preinit_array section is not allowed in DSO"),
+                         bfd_archive_filename (sub));
+                     break;
+                   }
+
+             bfd_set_error (bfd_error_nonrepresentable_section);
+             return false;
+           }
+
+         if (!elf_add_dynamic_entry (info, (bfd_vma) DT_PREINIT_ARRAY,
+                                     (bfd_vma) 0)
+             || !elf_add_dynamic_entry (info, (bfd_vma) DT_PREINIT_ARRAYSZ,
+                                        (bfd_vma) 0))
+           return false;
+       }
+      if (bfd_get_section_by_name (output_bfd, ".init_array") != NULL)
+       {
+         if (!elf_add_dynamic_entry (info, (bfd_vma) DT_INIT_ARRAY,
+                                     (bfd_vma) 0)
+             || !elf_add_dynamic_entry (info, (bfd_vma) DT_INIT_ARRAYSZ,
+                                        (bfd_vma) 0))
+           return false;
+       }
+      if (bfd_get_section_by_name (output_bfd, ".fini_array") != NULL)
+       {
+         if (!elf_add_dynamic_entry (info, (bfd_vma) DT_FINI_ARRAY,
+                                     (bfd_vma) 0)
+             || !elf_add_dynamic_entry (info, (bfd_vma) DT_FINI_ARRAYSZ,
+                                        (bfd_vma) 0))
+           return false;
+       }
+
       dynstr = bfd_get_section_by_name (dynobj, ".dynstr");
       /* If .dynstr is excluded from the link, we don't want any of
         these tags.  Strictly, we should be checking each section
@@ -3239,7 +3283,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
       BFD_ASSERT (s != NULL);
 
       /* We may have created additional version definitions if we are
-         just linking a regular application.  */
+        just linking a regular application.  */
       verdefs = asvinfo.verdefs;
 
       /* Skip anonymous version tag.  */
@@ -3633,10 +3677,10 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
 \f
 /* This function is used to adjust offsets into .dynstr for
    dynamic symbols.  This is called via elf_link_hash_traverse.  */
-      
+
 static boolean elf_adjust_dynstr_offsets
 PARAMS ((struct elf_link_hash_entry *, PTR));
-        
+
 static boolean
 elf_adjust_dynstr_offsets (h, data)
      struct elf_link_hash_entry *h;
@@ -3644,6 +3688,9 @@ elf_adjust_dynstr_offsets (h, data)
 {
   struct elf_strtab_hash *dynstr = (struct elf_strtab_hash *) data;
 
+  if (h->root.type == bfd_link_hash_warning)
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
   if (h->dynindx != -1)
     h->dynstr_index = _bfd_elf_strtab_offset (dynstr, h->dynstr_index);
   return true;
@@ -3716,7 +3763,7 @@ elf_finalize_dynstr (output_bfd, info)
       bfd_size_type i;
       Elf_Internal_Verdef def;
       Elf_Internal_Verdaux defaux;
-                    
+
       s = bfd_get_section_by_name (dynobj, ".gnu.version_d");
       p = (bfd_byte *) s->contents;
       do
@@ -3746,7 +3793,7 @@ elf_finalize_dynstr (output_bfd, info)
       bfd_size_type i;
       Elf_Internal_Verneed need;
       Elf_Internal_Vernaux needaux;
-                    
+
       s = bfd_get_section_by_name (dynobj, ".gnu.version_r");
       p = (bfd_byte *) s->contents;
       do
@@ -3824,11 +3871,11 @@ elf_fix_symbol_flags (h, eif)
   else
     {
       /* Unfortunately, ELF_LINK_NON_ELF is only correct if the symbol
-         was first seen in a non-ELF file.  Fortunately, if the symbol
-         was first seen in an ELF file, we're probably OK unless the
-         symbol was defined in a non-ELF file.  Catch that case here.
-         FIXME: We're still in trouble if the symbol was first seen in
-         a dynamic object, and then later in a non-ELF regular object.  */
+        was first seen in a non-ELF file.  Fortunately, if the symbol
+        was first seen in an ELF file, we're probably OK unless the
+        symbol was defined in a non-ELF file.  Catch that case here.
+        FIXME: We're still in trouble if the symbol was first seen in
+        a dynamic object, and then later in a non-ELF regular object.  */
       if ((h->root.type == bfd_link_hash_defined
           || h->root.type == bfd_link_hash_defweak)
          && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0
@@ -3923,6 +3970,17 @@ elf_adjust_dynamic_symbol (h, data)
   bfd *dynobj;
   struct elf_backend_data *bed;
 
+  if (h->root.type == bfd_link_hash_warning)
+    {
+      h->plt.offset = (bfd_vma) -1;
+      h->got.offset = (bfd_vma) -1;
+
+      /* When warning symbols are created, they **replace** the "real"
+        entry in the hash table, thus we never get to see the real
+        symbol in a hash traversal.  So look at it now.  */
+      h = (struct elf_link_hash_entry *) h->root.u.i.link;
+    }
+
   /* Ignore indirect symbols.  These are added by the versioning code.  */
   if (h->root.type == bfd_link_hash_indirect)
     return true;
@@ -4039,6 +4097,9 @@ elf_export_symbol (h, data)
   if (h->root.type == bfd_link_hash_indirect)
     return true;
 
+  if (h->root.type == bfd_link_hash_warning)
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
   if (h->dynindx == -1
       && (h->elf_link_hash_flags
          & (ELF_LINK_HASH_DEF_REGULAR | ELF_LINK_HASH_REF_REGULAR)) != 0)
@@ -4068,14 +4129,14 @@ elf_export_symbol (h, data)
        }
 
       if (!eif->verdefs)
-        {
+       {
 doit:
          if (! _bfd_elf_link_record_dynamic_symbol (eif->info, h))
            {
              eif->failed = true;
              return false;
            }
-        }
+       }
     }
 
   return true;
@@ -4096,6 +4157,9 @@ elf_link_find_version_dependencies (h, data)
   Elf_Internal_Vernaux *a;
   bfd_size_type amt;
 
+  if (h->root.type == bfd_link_hash_warning)
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
   /* We only care about symbols defined in shared objects with version
      information.  */
   if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0
@@ -4176,6 +4240,9 @@ elf_link_assign_sym_version (h, data)
   sinfo = (struct elf_assign_sym_version_info *) data;
   info = sinfo->info;
 
+  if (h->root.type == bfd_link_hash_warning)
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
   /* Fix the symbol flags.  */
   eif.failed = false;
   eif.info = info;
@@ -4201,7 +4268,7 @@ elf_link_assign_sym_version (h, data)
       hidden = true;
 
       /* There are two consecutive ELF_VER_CHR characters if this is
-         not a hidden symbol.  */
+        not a hidden symbol.  */
       ++p;
       if (*p == ELF_VER_CHR)
        {
@@ -4229,11 +4296,11 @@ elf_link_assign_sym_version (h, data)
              len = p - h->root.root.string;
              alc = bfd_malloc ((bfd_size_type) len);
              if (alc == NULL)
-               return false;
+               return false;
              strncpy (alc, h->root.root.string, len - 1);
              alc[len - 1] = '\0';
              if (alc[len - 2] == ELF_VER_CHR)
-               alc[len - 2] = '\0';
+               alc[len - 2] = '\0';
 
              h->verinfo.vertree = t;
              t->used = true;
@@ -4247,7 +4314,7 @@ elf_link_assign_sym_version (h, data)
                }
 
              /* See if there is anything to force this symbol to
-                 local scope.  */
+                local scope.  */
              if (d == NULL && t->locals != NULL)
                {
                  for (d = t->locals; d != NULL; d = d->next)
@@ -4272,14 +4339,14 @@ elf_link_assign_sym_version (h, data)
        }
 
       /* If we are building an application, we need to create a
-         version node for this version.  */
+        version node for this version.  */
       if (t == NULL && ! info->shared)
        {
          struct bfd_elf_version_tree **pp;
          int version_index;
 
          /* If we aren't going to export this symbol, we don't need
-             to worry about it.  */
+            to worry about it.  */
          if (h->dynindx == -1)
            return true;
 
@@ -4315,7 +4382,7 @@ elf_link_assign_sym_version (h, data)
       else if (t == NULL)
        {
          /* We could not find the version for a symbol when
-             generating a shared archive.  Return an error.  */
+            generating a shared archive.  Return an error.  */
          (*_bfd_error_handler)
            (_("%s: undefined versioned symbol name %s"),
             bfd_get_filename (sinfo->output_bfd), h->root.root.string);
@@ -4337,8 +4404,8 @@ elf_link_assign_sym_version (h, data)
       struct bfd_elf_version_expr *d;
 
       /* See if can find what version this symbol is in.  If the
-         symbol is supposed to be local, then don't actually register
-         it.  */
+        symbol is supposed to be local, then don't actually register
+        it.  */
       deflt = NULL;
       for (t = sinfo->verdefs; t != NULL; t = t->next)
        {
@@ -4858,8 +4925,8 @@ elf_bfd_final_link (abfd, info)
   dynobj = elf_hash_table (info)->dynobj;
 
   emit_relocs = (info->relocateable
-                 || info->emitrelocations
-                 || bed->elf_backend_emit_relocs);
+                || info->emitrelocations
+                || bed->elf_backend_emit_relocs);
 
   finfo.info = info;
   finfo.output_bfd = abfd;
@@ -4929,7 +4996,7 @@ elf_bfd_final_link (abfd, info)
 
              if (info->relocateable || info->emitrelocations)
                o->reloc_count += sec->reloc_count;
-              else if (bed->elf_backend_count_relocs)
+             else if (bed->elf_backend_count_relocs)
                {
                  Elf_Internal_Rela * relocs;
 
@@ -4937,8 +5004,8 @@ elf_bfd_final_link (abfd, info)
                            (abfd, sec, (PTR) NULL,
                             (Elf_Internal_Rela *) NULL, info->keep_memory));
 
-                 o->reloc_count += (*bed->elf_backend_count_relocs)
-                                     (sec, relocs);
+                 o->reloc_count
+                   += (*bed->elf_backend_count_relocs) (sec, relocs);
 
                  if (!info->keep_memory)
                    free (relocs);
@@ -5040,10 +5107,20 @@ elf_bfd_final_link (abfd, info)
                = elf_section_data (output_section);
              unsigned int *rel_count;
              unsigned int *rel_count2;
+             bfd_size_type entsize;
+             bfd_size_type entsize2;
 
-             /* We must be careful to add the relocation froms the
+             /* We must be careful to add the relocations from the
                 input section to the right output count.  */
-             if (esdi->rel_hdr.sh_entsize == esdo->rel_hdr.sh_entsize)
+             entsize = esdi->rel_hdr.sh_entsize;
+             entsize2 = esdi->rel_hdr2 ? esdi->rel_hdr2->sh_entsize : 0;
+             BFD_ASSERT ((entsize == sizeof (Elf_External_Rel)
+                          || entsize == sizeof (Elf_External_Rela))
+                         && entsize2 != entsize
+                         && (entsize2 == 0
+                             || entsize2 == sizeof (Elf_External_Rel)
+                             || entsize2 == sizeof (Elf_External_Rela)));
+             if (entsize == esdo->rel_hdr.sh_entsize)
                {
                  rel_count = &esdo->rel_count;
                  rel_count2 = &esdo->rel_count2;
@@ -5274,10 +5351,10 @@ elf_bfd_final_link (abfd, info)
       for (p = o->link_order_head; p != NULL; p = p->next)
        {
          if (p->type == bfd_indirect_link_order
-             && (bfd_get_flavour (p->u.indirect.section->owner)
-                 == bfd_target_elf_flavour))
+             && (bfd_get_flavour ((sub = p->u.indirect.section->owner))
+                 == bfd_target_elf_flavour)
+             && elf_elfheader (sub)->e_ident[EI_CLASS] == bed->s->elfclass)
            {
-             sub = p->u.indirect.section->owner;
              if (! sub->output_has_begun)
                {
                  if (! elf_link_input_bfd (&finfo, sub))
@@ -5299,28 +5376,25 @@ elf_bfd_final_link (abfd, info)
        }
     }
 
+  /* Output any global symbols that got converted to local in a
+     version script or due to symbol visibility.  We do this in a
+     separate step since ELF requires all local symbols to appear
+     prior to any global symbols.  FIXME: We should only do this if
+     some global symbols were, in fact, converted to become local.
+     FIXME: Will this work correctly with the Irix 5 linker?  */
+  eoinfo.failed = false;
+  eoinfo.finfo = &finfo;
+  eoinfo.localsyms = true;
+  elf_link_hash_traverse (elf_hash_table (info), elf_link_output_extsym,
+                         (PTR) &eoinfo);
+  if (eoinfo.failed)
+    return false;
+
   /* That wrote out all the local symbols.  Finish up the symbol table
      with the global symbols. Even if we want to strip everything we
      can, we still need to deal with those global symbols that got
      converted to local in a version script.  */
 
-  if (info->shared)
-    {
-      /* Output any global symbols that got converted to local in a
-         version script.  We do this in a separate step since ELF
-         requires all local symbols to appear prior to any global
-         symbols.  FIXME: We should only do this if some global
-         symbols were, in fact, converted to become local.  FIXME:
-         Will this work correctly with the Irix 5 linker?  */
-      eoinfo.failed = false;
-      eoinfo.finfo = &finfo;
-      eoinfo.localsyms = true;
-      elf_link_hash_traverse (elf_hash_table (info), elf_link_output_extsym,
-                             (PTR) &eoinfo);
-      if (eoinfo.failed)
-       return false;
-    }
-
   /* The sh_info field records the index of the first non local symbol.  */
   symtab_hdr->sh_info = bfd_get_symcount (abfd);
 
@@ -5372,11 +5446,12 @@ elf_bfd_final_link (abfd, info)
 
              /* Copy the internal symbol as is.
                 Note that we saved a word of storage and overwrote
-                 the original st_name with the dynstr_index.  */
-              sym = e->isym;
+                the original st_name with the dynstr_index.  */
+             sym = e->isym;
 
-             if (e->isym.st_shndx < SHN_LORESERVE
-                 || e->isym.st_shndx > SHN_HIRESERVE)
+             if (e->isym.st_shndx != SHN_UNDEF
+                  && (e->isym.st_shndx < SHN_LORESERVE
+                      || e->isym.st_shndx > SHN_HIRESERVE))
                {
                  s = bfd_section_from_elf_index (e->input_bfd,
                                                  e->isym.st_shndx);
@@ -5549,6 +5624,34 @@ elf_bfd_final_link (abfd, info)
              }
              break;
 
+           case DT_PREINIT_ARRAYSZ:
+             name = ".preinit_array";
+             goto get_size;
+           case DT_INIT_ARRAYSZ:
+             name = ".init_array";
+             goto get_size;
+           case DT_FINI_ARRAYSZ:
+             name = ".fini_array";
+           get_size:
+             o = bfd_get_section_by_name (abfd, name);
+             BFD_ASSERT (o != NULL);
+             if (o->_raw_size == 0)
+               (*_bfd_error_handler)
+                 (_("warning: %s section has zero size"), name);
+             dyn.d_un.d_val = o->_raw_size;
+             elf_swap_dyn_out (dynobj, &dyn, dyncon);
+             break;
+
+           case DT_PREINIT_ARRAY:
+             name = ".preinit_array";
+             goto get_vma;
+           case DT_INIT_ARRAY:
+             name = ".init_array";
+             goto get_vma;
+           case DT_FINI_ARRAY:
+             name = ".fini_array";
+             goto get_vma;
+
            case DT_HASH:
              name = ".hash";
              goto get_vma;
@@ -5621,7 +5724,7 @@ elf_bfd_final_link (abfd, info)
          if ((o->flags & SEC_LINKER_CREATED) == 0)
            {
              /* At this point, we are only interested in sections
-                 created by elf_link_create_dynamic_sections.  */
+                created by elf_link_create_dynamic_sections.  */
              continue;
            }
          if ((elf_section_data (o->output_section)->this_hdr.sh_type
@@ -5637,7 +5740,7 @@ elf_bfd_final_link (abfd, info)
          else
            {
              /* The contents of the .dynstr section are actually in a
-                 stringtab.  */
+                stringtab.  */
              off = elf_section_data (o->output_section)->this_hdr.sh_offset;
              if (bfd_seek (abfd, off, SEEK_SET) != 0
                  || ! _bfd_elf_strtab_emit (abfd,
@@ -5693,7 +5796,7 @@ elf_bfd_final_link (abfd, info)
     {
       if ((o->flags & SEC_RELOC) != 0
          && elf_section_data (o)->rel_hashes != NULL)
-        free (elf_section_data (o)->rel_hashes);
+       free (elf_section_data (o)->rel_hashes);
     }
 
   elf_tdata (abfd)->linker = true;
@@ -5744,7 +5847,7 @@ elf_link_output_sym (finfo, name, elfsym, input_sec)
 {
   Elf_External_Sym *dest;
   Elf_External_Sym_Shndx *destshndx;
-  
+
   boolean (*output_symbol_hook) PARAMS ((bfd *,
                                         struct bfd_link_info *info,
                                         const char *,
@@ -5840,6 +5943,9 @@ elf_link_sec_merge_syms (h, data)
 {
   asection *sec;
 
+  if (h->root.type == bfd_link_hash_warning)
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
   if ((h->root.type == bfd_link_hash_defined
        || h->root.type == bfd_link_hash_defweak)
       && ((sec = h->root.u.def.section)->flags & SEC_MERGE)
@@ -5875,6 +5981,13 @@ elf_link_output_extsym (h, data)
   Elf_Internal_Sym sym;
   asection *input_sec;
 
+  if (h->root.type == bfd_link_hash_warning)
+    {
+      h = (struct elf_link_hash_entry *) h->root.u.i.link;
+      if (h->root.type == bfd_link_hash_new)
+       return true;
+    }
+
   /* Decide whether to output this symbol in this pass.  */
   if (eoinfo->localsyms)
     {
@@ -5952,14 +6065,11 @@ elf_link_output_extsym (h, data)
     {
     default:
     case bfd_link_hash_new:
+    case bfd_link_hash_warning:
       abort ();
       return false;
 
     case bfd_link_hash_undefined:
-      input_sec = bfd_und_section_ptr;
-      sym.st_shndx = SHN_UNDEF;
-      break;
-
     case bfd_link_hash_undefweak:
       input_sec = bfd_und_section_ptr;
       sym.st_shndx = SHN_UNDEF;
@@ -6010,29 +6120,22 @@ elf_link_output_extsym (h, data)
 
     case bfd_link_hash_indirect:
       /* These symbols are created by symbol versioning.  They point
-         to the decorated version of the name.  For example, if the
-         symbol foo@@GNU_1.2 is the default, which should be used when
-         foo is used with no version, then we add an indirect symbol
-         foo which points to foo@@GNU_1.2.  We ignore these symbols,
-         since the indirected symbol is already in the hash table.  */
+        to the decorated version of the name.  For example, if the
+        symbol foo@@GNU_1.2 is the default, which should be used when
+        foo is used with no version, then we add an indirect symbol
+        foo which points to foo@@GNU_1.2.  We ignore these symbols,
+        since the indirected symbol is already in the hash table.  */
       return true;
-
-    case bfd_link_hash_warning:
-      /* We can't represent these symbols in ELF, although a warning
-         symbol may have come from a .gnu.warning.SYMBOL section.  We
-         just put the target symbol in the hash table.  If the target
-         symbol does not really exist, don't do anything.  */
-      if (h->root.u.i.link->type == bfd_link_hash_new)
-       return true;
-      return (elf_link_output_extsym
-             ((struct elf_link_hash_entry *) h->root.u.i.link, data));
     }
 
   /* Give the processor backend a chance to tweak the symbol value,
      and also to finish up anything that needs to be done for this
-     symbol.  */
+     symbol.  FIXME: Not calling elf_backend_finish_dynamic_symbol for
+     forced local syms when non-shared is due to a historical quirk.  */
   if ((h->dynindx != -1
        || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)
+      && (finfo->info->shared
+         || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
       && elf_hash_table (finfo->info)->dynamic_sections_created)
     {
       struct elf_backend_data *bed;
@@ -6151,7 +6254,7 @@ elf_link_output_extsym (h, data)
    originated from the section given by INPUT_REL_HDR) to the
    OUTPUT_BFD.  */
 
-static void
+static boolean
 elf_link_output_relocs (output_bfd, input_section, input_rel_hdr,
                        internal_relocs)
      bfd *output_bfd;
@@ -6183,8 +6286,16 @@ elf_link_output_relocs (output_bfd, input_section, input_rel_hdr,
       output_rel_hdr = elf_section_data (output_section)->rel_hdr2;
       rel_countp = &elf_section_data (output_section)->rel_count2;
     }
-
-  BFD_ASSERT (output_rel_hdr != NULL);
+  else
+    {
+      (*_bfd_error_handler) (
+        _("%s: relocation size mismatch in %s section %s"),
+        bfd_get_filename (output_bfd),
+        bfd_archive_filename (input_section->owner),
+        input_section->name);
+      bfd_set_error (bfd_error_wrong_object_format);
+      return false;
+    }
 
   bed = get_elf_backend_data (output_bfd);
   irela = internal_relocs;
@@ -6241,6 +6352,8 @@ elf_link_output_relocs (output_bfd, input_section, input_rel_hdr,
   /* Bump the counter, so that we know where to add the next set of
      relocations.  */
   *rel_countp += NUM_SHDR_ENTRIES (input_rel_hdr);
+
+  return true;
 }
 
 /* Link an input file into the linker output file.  This function
@@ -6286,8 +6399,8 @@ elf_link_input_bfd (finfo, input_bfd)
     return true;
 
   emit_relocs = (finfo->info->relocateable
-                 || finfo->info->emitrelocations
-                 || bed->elf_backend_emit_relocs);
+                || finfo->info->emitrelocations
+                || bed->elf_backend_emit_relocs);
 
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
   if (elf_bad_symtab (input_bfd))
@@ -6403,10 +6516,10 @@ elf_link_input_bfd (finfo, input_bfd)
        continue;
 
       /* If this symbol is defined in a section which we are
-         discarding, we don't need to keep it, but note that
-         linker_mark is only reliable for sections that have contents.
-         For the benefit of the MIPS ELF linker, we check SEC_EXCLUDE
-         as well as linker_mark.  */
+        discarding, we don't need to keep it, but note that
+        linker_mark is only reliable for sections that have contents.
+        For the benefit of the MIPS ELF linker, we check SEC_EXCLUDE
+        as well as linker_mark.  */
       if ((isym->st_shndx < SHN_LORESERVE || isym->st_shndx > SHN_HIRESERVE)
          && isec != NULL
          && ((! isec->linker_mark && (isec->flags & SEC_HAS_CONTENTS) != 0)
@@ -6481,9 +6594,9 @@ elf_link_input_bfd (finfo, input_bfd)
        }
 
       /* Get the contents of the section.  They have been cached by a
-         relaxation routine.  Note that o is a section in an input
-         file, so the contents field will not have been set by any of
-         the routines which work on output files.  */
+        relaxation routine.  Note that o is a section in an input
+        file, so the contents field will not have been set by any of
+        the routines which work on output files.  */
       if (elf_section_data (o)->this_hdr.contents != NULL)
        contents = elf_section_data (o)->this_hdr.contents;
       else
@@ -6651,9 +6764,15 @@ elf_link_input_bfd (finfo, input_bfd)
              struct elf_link_hash_entry **rel_hash;
              Elf_Internal_Shdr *input_rel_hdr;
              unsigned int next_erel;
-             void (*reloc_emitter) PARAMS ((bfd *, asection *,
-                                            Elf_Internal_Shdr *,
-                                            Elf_Internal_Rela *));
+             boolean (*reloc_emitter) PARAMS ((bfd *, asection *,
+                                               Elf_Internal_Shdr *,
+                                               Elf_Internal_Rela *));
+             boolean rela_normal;
+
+             input_rel_hdr = &elf_section_data (o)->rel_hdr;
+             rela_normal = (bed->rela_normal
+                            && (input_rel_hdr->sh_entsize
+                                == sizeof (Elf_External_Rela)));
 
              /* Adjust the reloc addresses and symbol indices.  */
 
@@ -6676,7 +6795,7 @@ elf_link_input_bfd (finfo, input_bfd)
                  irela->r_offset += o->output_offset;
 
                  /* Relocs in an executable have to be virtual addresses.  */
-                 if (finfo->info->emitrelocations)
+                 if (!finfo->info->relocateable)
                    irela->r_offset += o->output_section->vma;
 
                  r_symndx = ELF_R_SYM (irela->r_info);
@@ -6727,10 +6846,9 @@ elf_link_input_bfd (finfo, input_bfd)
                         processor specific section.  If we have
                         discarded a section, the output_section will
                         be the absolute section.  */
-                     if (sec != NULL
-                         && (bfd_is_abs_section (sec)
-                             || (sec->output_section != NULL
-                                 && bfd_is_abs_section (sec->output_section))))
+                     if (bfd_is_abs_section (sec)
+                         || (sec != NULL
+                             && bfd_is_abs_section (sec->output_section)))
                        r_symndx = 0;
                      else if (sec == NULL || sec->owner == NULL)
                        {
@@ -6742,6 +6860,11 @@ elf_link_input_bfd (finfo, input_bfd)
                          r_symndx = sec->output_section->target_index;
                          BFD_ASSERT (r_symndx != 0);
                        }
+
+                     /* Adjust the addend according to where the
+                        section winds up in the output section.  */ 
+                     if (rela_normal)
+                       irela->r_addend += sec->output_offset;
                    }
                  else
                    {
@@ -6793,23 +6916,26 @@ elf_link_input_bfd (finfo, input_bfd)
                }
 
              /* Swap out the relocs.  */
-              if (bed->elf_backend_emit_relocs
-                  && !(finfo->info->relocateable
+             if (bed->elf_backend_emit_relocs
+                 && !(finfo->info->relocateable
                       || finfo->info->emitrelocations))
-                reloc_emitter = bed->elf_backend_emit_relocs;
-              else
-                reloc_emitter = elf_link_output_relocs;
+               reloc_emitter = bed->elf_backend_emit_relocs;
+             else
+               reloc_emitter = elf_link_output_relocs;
 
-             input_rel_hdr = &elf_section_data (o)->rel_hdr;
-              (*reloc_emitter) (output_bfd, o, input_rel_hdr, internal_relocs);
+             if (! (*reloc_emitter) (output_bfd, o, input_rel_hdr,
+                                     internal_relocs))
+               return false;
 
              input_rel_hdr = elf_section_data (o)->rel_hdr2;
-              if (input_rel_hdr)
-                {
-                  internal_relocs += (NUM_SHDR_ENTRIES (input_rel_hdr)
+             if (input_rel_hdr)
+               {
+                 internal_relocs += (NUM_SHDR_ENTRIES (input_rel_hdr)
                                      * bed->s->int_rels_per_ext_rel);
-                  reloc_emitter (output_bfd, o, input_rel_hdr, internal_relocs);
-                }
+                 if (! (*reloc_emitter) (output_bfd, o, input_rel_hdr,
+                                         internal_relocs))
+                   return false;
+               }
 
            }
        }
@@ -6909,7 +7035,7 @@ elf_reloc_link_order (output_bfd, info, output_section, link_order)
       struct elf_link_hash_entry *h;
 
       /* Treat a reloc against a defined symbol as though it were
-         actually against the section.  */
+        actually against the section.  */
       h = ((struct elf_link_hash_entry *)
           bfd_wrapped_link_hash_lookup (output_bfd, info,
                                         link_order->u.reloc.p->u.name,
@@ -6924,8 +7050,8 @@ elf_reloc_link_order (output_bfd, info, output_section, link_order)
          indx = section->output_section->target_index;
          *rel_hash_ptr = NULL;
          /* It seems that we ought to add the symbol value to the
-             addend here, but in practice it has already been added
-             because it was passed to constructor_callback.  */
+            addend here, but in practice it has already been added
+            because it was passed to constructor_callback.  */
          addend += section->output_section->vma + section->output_offset;
        }
       else if (h != NULL)
@@ -7398,7 +7524,7 @@ elf_gc_mark (info, sec, gc_mark_hook)
       if (elf_bad_symtab (input_bfd))
        {
          nlocsyms = symtab_hdr->sh_size / sizeof (Elf_External_Sym);
-          extsymoff = 0;
+         extsymoff = 0;
        }
       else
        extsymoff = nlocsyms = symtab_hdr->sh_info;
@@ -7460,11 +7586,11 @@ elf_gc_mark (info, sec, gc_mark_hook)
                                  locsym_shndx + (locsym_shndx ? r_symndx : 0),
                                  &s);
              if (ELF_ST_BIND (s.st_info) == STB_LOCAL)
-               rsec = (*gc_mark_hook) (sec->owner, info, rel, NULL, &s);
+               rsec = (*gc_mark_hook) (sec->owner, info, rel, NULL, &s);
              else
                {
-                 h = sym_hashes[r_symndx - extsymoff];
-                 rsec = (*gc_mark_hook) (sec->owner, info, rel, h, NULL);
+                 h = sym_hashes[r_symndx - extsymoff];
+                 rsec = (*gc_mark_hook) (sec->owner, info, rel, h, NULL);
                }
            }
          else if (r_symndx >= nlocsyms)
@@ -7482,11 +7608,15 @@ elf_gc_mark (info, sec, gc_mark_hook)
            }
 
          if (rsec && !rsec->gc_mark)
-           if (!elf_gc_mark (info, rsec, gc_mark_hook))
-             {
-               ret = false;
-               goto out2;
-             }
+           {
+             if (bfd_get_flavour (rsec->owner) != bfd_target_elf_flavour)
+               rsec->gc_mark = 1;
+             else if (!elf_gc_mark (info, rsec, gc_mark_hook))
+               {
+                 ret = false;
+                 goto out2;
+               }
+           }
        }
 
     out2:
@@ -7585,6 +7715,9 @@ elf_gc_sweep_symbol (h, idxptr)
 {
   int *idx = (int *) idxptr;
 
+  if (h->root.type == bfd_link_hash_warning)
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
   if (h->dynindx != -1
       && ((h->root.type != bfd_link_hash_defined
           && h->root.type != bfd_link_hash_defweak)
@@ -7602,6 +7735,9 @@ elf_gc_propagate_vtable_entries_used (h, okp)
      struct elf_link_hash_entry *h;
      PTR okp;
 {
+  if (h->root.type == bfd_link_hash_warning)
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
   /* Those that are not vtables.  */
   if (h->vtable_parent == NULL)
     return true;
@@ -7635,9 +7771,9 @@ elf_gc_propagate_vtable_entries_used (h, okp)
       pu = h->vtable_parent->vtable_entries_used;
       if (pu != NULL)
        {
-          asection *sec = h->root.u.def.section;
-          struct elf_backend_data *bed = get_elf_backend_data (sec->owner);
-          int file_align = bed->s->file_align;
+         asection *sec = h->root.u.def.section;
+         struct elf_backend_data *bed = get_elf_backend_data (sec->owner);
+         int file_align = bed->s->file_align;
 
          n = h->vtable_parent->vtable_entries_size / file_align;
          while (n--)
@@ -7664,6 +7800,9 @@ elf_gc_smash_unused_vtentry_relocs (h, okp)
   struct elf_backend_data *bed;
   int file_align;
 
+  if (h->root.type == bfd_link_hash_warning)
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
   /* Take care of both those symbols that do not describe vtables as
      well as those that are not loaded.  */
   if (h->vtable_parent == NULL)
@@ -7714,7 +7853,7 @@ elf_gc_sections (abfd, info)
   bfd *sub;
   asection * (*gc_mark_hook)
     PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
-             struct elf_link_hash_entry *h, Elf_Internal_Sym *));
+            struct elf_link_hash_entry *h, Elf_Internal_Sym *));
 
   if (!get_elf_backend_data (abfd)->can_gc_sections
       || info->relocateable || info->emitrelocations
@@ -7748,7 +7887,7 @@ elf_gc_sections (abfd, info)
       for (o = sub->sections; o != NULL; o = o->next)
        {
          if (o->flags & SEC_KEEP)
-           if (!elf_gc_mark (info, o, gc_mark_hook))
+           if (!elf_gc_mark (info, o, gc_mark_hook))
              return false;
        }
     }
@@ -7951,6 +8090,9 @@ elf_gc_allocate_got_offsets (h, offarg)
 {
   bfd_vma *off = (bfd_vma *) offarg;
 
+  if (h->root.type == bfd_link_hash_warning)
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
   if (h->got.refcount > 0)
     {
       h->got.offset = off[0];
@@ -7991,6 +8133,9 @@ elf_collect_hash_codes (h, data)
   unsigned long ha;
   char *alc = NULL;
 
+  if (h->root.type == bfd_link_hash_warning)
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
   /* Ignore indirect symbols.  These are added by the versioning code.  */
   if (h->dynindx == -1)
     return true;
@@ -8138,12 +8283,21 @@ elf_bfd_discard_info (output_bfd, info)
       if (ehdr)
        {
          eh = bfd_get_section_by_name (abfd, ".eh_frame");
-         if (eh && eh->_raw_size == 0)
+         if (eh && (eh->_raw_size == 0
+                    || bfd_is_abs_section (eh->output_section)))
            eh = NULL;
        }
 
-      stab = strip ? NULL : bfd_get_section_by_name (abfd, ".stab");
-      if ((! stab || elf_section_data(stab)->sec_info_type != ELF_INFO_TYPE_STABS)
+      stab = NULL;
+      if (!strip)
+       {
+         stab = bfd_get_section_by_name (abfd, ".stab");
+         if (stab && (stab->_raw_size == 0
+                      || bfd_is_abs_section (stab->output_section)))
+           stab = NULL;
+       }
+      if ((! stab
+          || elf_section_data(stab)->sec_info_type != ELF_INFO_TYPE_STABS)
          && ! eh
          && (strip || ! bed->elf_backend_discard_info))
        continue;
@@ -8168,24 +8322,24 @@ elf_bfd_discard_info (output_bfd, info)
 
       freesyms = NULL;
       if (symtab_hdr->contents)
-        cookie.locsyms = (void *) symtab_hdr->contents;
+       cookie.locsyms = (void *) symtab_hdr->contents;
       else if (cookie.locsymcount == 0)
-        cookie.locsyms = NULL;
+       cookie.locsyms = NULL;
       else
-        {
-          bfd_size_type amt = cookie.locsymcount * sizeof (Elf_External_Sym);
-          cookie.locsyms = bfd_malloc (amt);
-          if (cookie.locsyms == NULL)
+       {
+         bfd_size_type amt = cookie.locsymcount * sizeof (Elf_External_Sym);
+         cookie.locsyms = bfd_malloc (amt);
+         if (cookie.locsyms == NULL)
            return false;
          freesyms = cookie.locsyms;
          if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-              || bfd_bread (cookie.locsyms, amt, abfd) != amt)
+             || bfd_bread (cookie.locsyms, amt, abfd) != amt)
            {
            error_ret_free_loc:
              free (cookie.locsyms);
              return false;
-            }
-        }
+           }
+       }
 
       cookie.locsym_shndx = NULL;
       if (shndx_hdr->sh_size != 0 && cookie.locsymcount != 0)
@@ -8231,8 +8385,7 @@ elf_bfd_discard_info (output_bfd, info)
          cookie.relend = NULL;
          if (eh->reloc_count)
            cookie.rels = (NAME(_bfd_elf,link_read_relocs)
-                          (abfd, eh, (PTR) NULL,
-                           (Elf_Internal_Rela *) NULL,
+                          (abfd, eh, (PTR) NULL, (Elf_Internal_Rela *) NULL,
                            info->keep_memory));
          if (cookie.rels)
            {
@@ -8261,9 +8414,7 @@ elf_bfd_discard_info (output_bfd, info)
        free (freesyms);
     }
 
-  if (ehdr
-      && _bfd_elf_discard_section_eh_frame_hdr (output_bfd,
-                                               info, ehdr))
+  if (ehdr && _bfd_elf_discard_section_eh_frame_hdr (output_bfd, info, ehdr))
     ret = true;
   return ret;
 }
@@ -8272,6 +8423,8 @@ static boolean
 elf_section_ignore_discarded_relocs (sec)
      asection *sec;
 {
+  struct elf_backend_data *bed;
+
   switch (elf_section_data (sec)->sec_info_type)
     {
     case ELF_INFO_TYPE_STABS:
@@ -8280,10 +8433,10 @@ elf_section_ignore_discarded_relocs (sec)
     default:
       break;
     }
-  if ((get_elf_backend_data (sec->owner)->elf_backend_ignore_discarded_relocs
-       != NULL)
-      && (*get_elf_backend_data (sec->owner)
-          ->elf_backend_ignore_discarded_relocs) (sec))
+
+  bed = get_elf_backend_data (sec->owner);
+  if (bed->elf_backend_ignore_discarded_relocs != NULL
+      && (*bed->elf_backend_ignore_discarded_relocs) (sec))
     return true;
 
   return false;
This page took 0.044868 seconds and 4 git commands to generate.