2004-01-12 Michael Chastain <mec.gnu@mindspring.com>
[deliverable/binutils-gdb.git] / bfd / elflink.c
index 05194591b4af1ce01515636c150640febd939a2b..f58a67aade2f1818671afbe913cf383bcaf283f4 100644 (file)
@@ -25,19 +25,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #define ARCH_SIZE 0
 #include "elf-bfd.h"
 
-static bfd_boolean elf_link_read_relocs_from_section
-  PARAMS ((bfd *, Elf_Internal_Shdr *, PTR, Elf_Internal_Rela *));
-
 bfd_boolean
-_bfd_elf_create_got_section (abfd, info)
-     bfd *abfd;
-     struct bfd_link_info *info;
+_bfd_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
 {
   flagword flags;
   asection *s;
   struct elf_link_hash_entry *h;
   struct bfd_link_hash_entry *bh;
-  struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   int ptralign;
 
   /* This function may be called more than once.  */
@@ -87,14 +82,13 @@ _bfd_elf_create_got_section (abfd, info)
       bh = NULL;
       if (!(_bfd_generic_link_add_one_symbol
            (info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, s,
-            bed->got_symbol_offset, (const char *) NULL, FALSE,
-            bed->collect, &bh)))
+            bed->got_symbol_offset, NULL, FALSE, bed->collect, &bh)))
        return FALSE;
       h = (struct elf_link_hash_entry *) bh;
       h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
       h->type = STT_OBJECT;
 
-      if (info->shared
+      if (! info->executable
          && ! _bfd_elf_link_record_dynamic_symbol (info, h))
        return FALSE;
 
@@ -115,17 +109,15 @@ _bfd_elf_create_got_section (abfd, info)
    actual contents and size of these sections later.  */
 
 bfd_boolean
-_bfd_elf_link_create_dynamic_sections (abfd, info)
-     bfd *abfd;
-     struct bfd_link_info *info;
+_bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
 {
   flagword flags;
   register asection *s;
   struct elf_link_hash_entry *h;
   struct bfd_link_hash_entry *bh;
-  struct elf_backend_data *bed;
+  const struct elf_backend_data *bed;
 
-  if (! is_elf_hash_table (info))
+  if (! is_elf_hash_table (info->hash))
     return FALSE;
 
   if (elf_hash_table (info)->dynamic_sections_created)
@@ -144,7 +136,7 @@ _bfd_elf_link_create_dynamic_sections (abfd, info)
 
   /* A dynamically linked executable has a .interp section, but a
      shared library does not.  */
-  if (! info->shared)
+  if (info->executable)
     {
       s = bfd_make_section (abfd, ".interp");
       if (s == NULL
@@ -152,8 +144,7 @@ _bfd_elf_link_create_dynamic_sections (abfd, info)
        return FALSE;
     }
 
-  if (! info->traditional_format
-      && info->hash->creator->flavour == bfd_target_elf_flavour)
+  if (! info->traditional_format)
     {
       s = bfd_make_section (abfd, ".eh_frame_hdr");
       if (s == NULL
@@ -220,14 +211,14 @@ _bfd_elf_link_create_dynamic_sections (abfd, info)
      code examines it to decide how to initialize the process.  */
   bh = NULL;
   if (! (_bfd_generic_link_add_one_symbol
-        (info, abfd, "_DYNAMIC", BSF_GLOBAL, s, (bfd_vma) 0,
-         (const char *) 0, FALSE, get_elf_backend_data (abfd)->collect, &bh)))
+        (info, abfd, "_DYNAMIC", BSF_GLOBAL, s, 0, NULL, FALSE,
+         get_elf_backend_data (abfd)->collect, &bh)))
     return FALSE;
   h = (struct elf_link_hash_entry *) bh;
   h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
   h->type = STT_OBJECT;
 
-  if (info->shared
+  if (! info->executable
       && ! _bfd_elf_link_record_dynamic_symbol (info, h))
     return FALSE;
 
@@ -252,13 +243,11 @@ _bfd_elf_link_create_dynamic_sections (abfd, info)
 /* Create dynamic sections when linking against a dynamic object.  */
 
 bfd_boolean
-_bfd_elf_create_dynamic_sections (abfd, info)
-     bfd *abfd;
-     struct bfd_link_info *info;
+_bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
 {
   flagword flags, pltflags;
   asection *s;
-  struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
   /* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and
      .rel[a].bss sections.  */
@@ -287,15 +276,14 @@ _bfd_elf_create_dynamic_sections (abfd, info)
       struct bfd_link_hash_entry *bh = NULL;
 
       if (! (_bfd_generic_link_add_one_symbol
-            (info, abfd, "_PROCEDURE_LINKAGE_TABLE_", BSF_GLOBAL, s,
-             (bfd_vma) 0, (const char *) NULL, FALSE,
-             get_elf_backend_data (abfd)->collect, &bh)))
+            (info, abfd, "_PROCEDURE_LINKAGE_TABLE_", BSF_GLOBAL, s, 0, NULL,
+             FALSE, get_elf_backend_data (abfd)->collect, &bh)))
        return FALSE;
       h = (struct elf_link_hash_entry *) bh;
       h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
       h->type = STT_OBJECT;
 
-      if (info->shared
+      if (! info->executable
          && ! _bfd_elf_link_record_dynamic_symbol (info, h))
        return FALSE;
     }
@@ -320,7 +308,7 @@ _bfd_elf_create_dynamic_sections (abfd, info)
         section into the .bss section of the final image.  */
       s = bfd_make_section (abfd, ".dynbss");
       if (s == NULL
-         || ! bfd_set_section_flags (abfd, s, SEC_ALLOC))
+         || ! bfd_set_section_flags (abfd, s, SEC_ALLOC | SEC_LINKER_CREATED))
        return FALSE;
 
       /* The .rel[a].bss section holds copy relocs.  This section is not
@@ -358,16 +346,14 @@ _bfd_elf_create_dynamic_sections (abfd, info)
    one.  */
 
 bfd_boolean
-_bfd_elf_link_record_dynamic_symbol (info, h)
-     struct bfd_link_info *info;
-     struct elf_link_hash_entry *h;
+_bfd_elf_link_record_dynamic_symbol (struct bfd_link_info *info,
+                                    struct elf_link_hash_entry *h)
 {
   if (h->dynindx == -1)
     {
       struct elf_strtab_hash *dynstr;
-      char *p, *alc;
+      char *p;
       const char *name;
-      bfd_boolean copy;
       bfd_size_type indx;
 
       /* XXX: The ABI draft says the linker must turn hidden and
@@ -405,28 +391,18 @@ _bfd_elf_link_record_dynamic_symbol (info, h)
         table.  */
       name = h->root.root.string;
       p = strchr (name, ELF_VER_CHR);
-      if (p == NULL)
-       {
-         alc = NULL;
-         copy = FALSE;
-       }
-      else
-       {
-         size_t len = p - name + 1;
-
-         alc = bfd_malloc ((bfd_size_type) len);
-         if (alc == NULL)
-           return FALSE;
-         memcpy (alc, name, len - 1);
-         alc[len - 1] = '\0';
-         name = alc;
-         copy = TRUE;
-       }
+      if (p != NULL)
+       /* We know that the p points into writable memory.  In fact,
+          there are only a few symbols that have read-only names, being
+          those like _GLOBAL_OFFSET_TABLE_ that are created specially
+          by the backends.  Most symbols will have names pointing into
+          an ELF string table read from a file, or to objalloc memory.  */
+       *p = 0;
 
-      indx = _bfd_elf_strtab_add (dynstr, name, copy);
+      indx = _bfd_elf_strtab_add (dynstr, name, p != NULL);
 
-      if (alc != NULL)
-       free (alc);
+      if (p != NULL)
+       *p = ELF_VER_CHR;
 
       if (indx == (bfd_size_type) -1)
        return FALSE;
@@ -440,15 +416,14 @@ _bfd_elf_link_record_dynamic_symbol (info, h)
    this in case some dynamic object refers to this symbol.  */
 
 bfd_boolean
-bfd_elf_record_link_assignment (output_bfd, info, name, provide)
-     bfd *output_bfd ATTRIBUTE_UNUSED;
-     struct bfd_link_info *info;
-     const char *name;
-     bfd_boolean provide;
+bfd_elf_record_link_assignment (bfd *output_bfd ATTRIBUTE_UNUSED,
+                               struct bfd_link_info *info,
+                               const char *name,
+                               bfd_boolean provide)
 {
   struct elf_link_hash_entry *h;
 
-  if (info->hash->creator->flavour != bfd_target_elf_flavour)
+  if (!is_elf_hash_table (info->hash))
     return TRUE;
 
   h = elf_link_hash_lookup (elf_hash_table (info), name, TRUE, TRUE, FALSE);
@@ -505,10 +480,9 @@ bfd_elf_record_link_assignment (output_bfd, info, name, provide)
    in a discarded section, eg. a discarded link-once section symbol.  */
 
 int
-elf_link_record_local_dynamic_symbol (info, input_bfd, input_indx)
-     struct bfd_link_info *info;
-     bfd *input_bfd;
-     long input_indx;
+elf_link_record_local_dynamic_symbol (struct bfd_link_info *info,
+                                     bfd *input_bfd,
+                                     long input_indx)
 {
   bfd_size_type amt;
   struct elf_link_local_dynamic_entry *entry;
@@ -519,7 +493,7 @@ elf_link_record_local_dynamic_symbol (info, input_bfd, input_indx)
   Elf_External_Sym_Shndx eshndx;
   char esym[sizeof (Elf64_External_Sym)];
 
-  if (! is_elf_hash_table (info))
+  if (! is_elf_hash_table (info->hash))
     return 0;
 
   /* See if the entry exists already.  */
@@ -528,14 +502,13 @@ elf_link_record_local_dynamic_symbol (info, input_bfd, input_indx)
       return 1;
 
   amt = sizeof (*entry);
-  entry = (struct elf_link_local_dynamic_entry *) bfd_alloc (input_bfd, amt);
+  entry = bfd_alloc (input_bfd, amt);
   if (entry == NULL)
     return 0;
 
   /* Go find the symbol, so that we can find it's name.  */
   if (!bfd_elf_get_elf_syms (input_bfd, &elf_tdata (input_bfd)->symtab_hdr,
-                            (size_t) 1, (size_t) input_indx,
-                            &entry->isym, esym, &eshndx))
+                            1, input_indx, &entry->isym, esym, &eshndx))
     {
       bfd_release (input_bfd, entry);
       return 0;
@@ -595,10 +568,9 @@ elf_link_record_local_dynamic_symbol (info, input_bfd, input_indx)
 /* Return the dynindex of a local dynamic symbol.  */
 
 long
-_bfd_elf_link_lookup_local_dynindx (info, input_bfd, input_indx)
-     struct bfd_link_info *info;
-     bfd *input_bfd;
-     long input_indx;
+_bfd_elf_link_lookup_local_dynindx (struct bfd_link_info *info,
+                                   bfd *input_bfd,
+                                   long input_indx)
 {
   struct elf_link_local_dynamic_entry *e;
 
@@ -612,15 +584,11 @@ _bfd_elf_link_lookup_local_dynindx (info, input_bfd, input_indx)
    them are removed because they are marked as local.  This is called
    via elf_link_hash_traverse.  */
 
-static bfd_boolean elf_link_renumber_hash_table_dynsyms
-  PARAMS ((struct elf_link_hash_entry *, PTR));
-
 static bfd_boolean
-elf_link_renumber_hash_table_dynsyms (h, data)
-     struct elf_link_hash_entry *h;
-     PTR data;
+elf_link_renumber_hash_table_dynsyms (struct elf_link_hash_entry *h,
+                                     void *data)
 {
-  size_t *count = (size_t *) data;
+  size_t *count = data;
 
   if (h->root.type == bfd_link_hash_warning)
     h = (struct elf_link_hash_entry *) h->root.u.i.link;
@@ -637,9 +605,7 @@ elf_link_renumber_hash_table_dynsyms (h, data)
    the global symbols.  */
 
 unsigned long
-_bfd_elf_link_renumber_dynsyms (output_bfd, info)
-     bfd *output_bfd;
-     struct bfd_link_info *info;
+_bfd_elf_link_renumber_dynsyms (bfd *output_bfd, struct bfd_link_info *info)
 {
   unsigned long dynsymcount = 0;
 
@@ -684,20 +650,18 @@ _bfd_elf_link_renumber_dynsyms (output_bfd, info)
    a shared object.  */
 
 bfd_boolean
-_bfd_elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash, skip,
-                      override, type_change_ok, size_change_ok, dt_needed)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     const char *name;
-     Elf_Internal_Sym *sym;
-     asection **psec;
-     bfd_vma *pvalue;
-     struct elf_link_hash_entry **sym_hash;
-     bfd_boolean *skip;
-     bfd_boolean *override;
-     bfd_boolean *type_change_ok;
-     bfd_boolean *size_change_ok;
-     bfd_boolean dt_needed;
+_bfd_elf_merge_symbol (bfd *abfd,
+                      struct bfd_link_info *info,
+                      const char *name,
+                      Elf_Internal_Sym *sym,
+                      asection **psec,
+                      bfd_vma *pvalue,
+                      struct elf_link_hash_entry **sym_hash,
+                      bfd_boolean *skip,
+                      bfd_boolean *override,
+                      bfd_boolean *type_change_ok,
+                      bfd_boolean *size_change_ok,
+                      bfd_boolean dt_needed)
 {
   asection *sec;
   struct elf_link_hash_entry *h;
@@ -830,7 +794,7 @@ _bfd_elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash, skip,
   else
     olddef = TRUE;
 
-  /* We need to rememeber if a symbol has a definition in a dynamic
+  /* We need to remember if a symbol has a definition in a dynamic
      object or is weak in all dynamic objects. Internal and hidden
      visibility will make it unavailable to dynamic objects.  */
   if (newdyn && (h->elf_link_hash_flags & ELF_LINK_DYNAMIC_DEF) == 0)
@@ -855,7 +819,7 @@ _bfd_elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash, skip,
   /* If the old symbol has non-default visibility, we ignore the new
      definition from a dynamic object.  */
   if (newdyn
-      && ELF_ST_VISIBILITY (h->other)
+      && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
       && !bfd_is_und_section (sec))
     {
       *skip = TRUE;
@@ -871,7 +835,7 @@ _bfd_elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash, skip,
        return TRUE;
     }
   else if (!newdyn
-          && ELF_ST_VISIBILITY (sym->st_other)
+          && ELF_ST_VISIBILITY (sym->st_other) != STV_DEFAULT
           && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0)
     {
       /* If the new symbol with non-default visibility comes from a
@@ -884,7 +848,8 @@ _bfd_elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash, skip,
       if (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC)
        {
          h->elf_link_hash_flags &= ~ELF_LINK_HASH_DEF_DYNAMIC;
-         h->elf_link_hash_flags |= ELF_LINK_HASH_REF_DYNAMIC;
+         h->elf_link_hash_flags |= (ELF_LINK_HASH_REF_DYNAMIC
+                                    | ELF_LINK_DYNAMIC_DEF);
        }
       /* FIXME: Should we check type and size for protected symbol?  */
       h->size = 0;
@@ -892,7 +857,7 @@ _bfd_elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash, skip,
       return TRUE;
     }
 
-  /* We need to treat weak definiton right, depending on if there is a
+  /* We need to treat weak definition right, depending on if there is a
      definition from a dynamic object.  */
   if (bind == STB_WEAK)
     {
@@ -985,12 +950,16 @@ _bfd_elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash, skip,
   /* It's OK to change the type if either the existing symbol or the
      new symbol is weak unless it comes from a DT_NEEDED entry of
      a shared object, in which case, the DT_NEEDED entry may not be
-     required at the run time.  */
+     required at the run time. The type change is also OK if the
+     old symbol is undefined and the new symbol is defined.  */
 
   if ((! dt_needed && oldweakdef)
       || oldweakundef
       || newweakdef
-      || newweakundef)
+      || newweakundef
+      || (newdef
+         && (h->root.type == bfd_link_hash_undefined
+             || h->root.type == bfd_link_hash_undefweak)))
     *type_change_ok = TRUE;
 
   /* It's OK to change the size if either the existing symbol or the
@@ -1157,7 +1126,7 @@ _bfd_elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash, skip,
              h->size, abfd, bfd_link_hash_common, sym->st_size)))
        return FALSE;
 
-      /* If the predumed common symbol in the dynamic object is
+      /* If the presumed common symbol in the dynamic object is
         larger, pretend that the new symbol has its size.  */
 
       if (h->size > *pvalue)
@@ -1187,7 +1156,7 @@ _bfd_elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash, skip,
       /* Handle the case where we had a versioned symbol in a dynamic
         library and now find a definition in a normal object.  In this
         case, we make the versioned symbol point to the normal one.  */
-      struct elf_backend_data *bed = get_elf_backend_data (abfd);
+      const struct elf_backend_data *bed = get_elf_backend_data (abfd);
       flip->root.type = h->root.type;
       h->root.type = bfd_link_hash_indirect;
       h->root.u.i.link = (struct bfd_link_hash_entry *) flip;
@@ -1253,18 +1222,16 @@ _bfd_elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash, skip,
    indicates if it comes from a DT_NEEDED entry of a shared object.  */
 
 bfd_boolean
-_bfd_elf_add_default_symbol (abfd, info, h, name, sym, psec, value,
-                            dynsym, override, dt_needed)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     struct elf_link_hash_entry *h;
-     const char *name;
-     Elf_Internal_Sym *sym;
-     asection **psec;
-     bfd_vma *value;
-     bfd_boolean *dynsym;
-     bfd_boolean override;
-     bfd_boolean dt_needed;
+_bfd_elf_add_default_symbol (bfd *abfd,
+                            struct bfd_link_info *info,
+                            struct elf_link_hash_entry *h,
+                            const char *name,
+                            Elf_Internal_Sym *sym,
+                            asection **psec,
+                            bfd_vma *value,
+                            bfd_boolean *dynsym,
+                            bfd_boolean override,
+                            bfd_boolean dt_needed)
 {
   bfd_boolean type_change_ok;
   bfd_boolean size_change_ok;
@@ -1272,7 +1239,7 @@ _bfd_elf_add_default_symbol (abfd, info, h, name, sym, psec, value,
   char *shortname;
   struct elf_link_hash_entry *hi;
   struct bfd_link_hash_entry *bh;
-  struct elf_backend_data *bed;
+  const struct elf_backend_data *bed;
   bfd_boolean collect;
   bfd_boolean dynamic;
   char *p;
@@ -1289,7 +1256,7 @@ _bfd_elf_add_default_symbol (abfd, info, h, name, sym, psec, value,
 
   if (override)
     {
-      /* We are overridden by an old defition. We need to check if we
+      /* We are overridden by an old definition. We need to check if we
         need to create the indirect symbol from the default name.  */
       hi = elf_link_hash_lookup (elf_hash_table (info), name, TRUE,
                                 FALSE, FALSE);
@@ -1336,7 +1303,7 @@ _bfd_elf_add_default_symbol (abfd, info, h, name, sym, psec, value,
       bh = &hi->root;
       if (! (_bfd_generic_link_add_one_symbol
             (info, abfd, shortname, BSF_INDIRECT, bfd_ind_section_ptr,
-             (bfd_vma) 0, name, FALSE, collect, &bh)))
+             0, name, FALSE, collect, &bh)))
        return FALSE;
       hi = (struct elf_link_hash_entry *) bh;
     }
@@ -1448,7 +1415,7 @@ nondefault:
     {
       /* Here SHORTNAME is a versioned name, so we don't expect to see
         the type of override we do in the case above unless it is
-        overridden by a versioned definiton.  */
+        overridden by a versioned definition.  */
       if (hi->root.type != bfd_link_hash_defined
          && hi->root.type != bfd_link_hash_defweak)
        (*_bfd_error_handler)
@@ -1460,7 +1427,7 @@ nondefault:
       bh = &hi->root;
       if (! (_bfd_generic_link_add_one_symbol
             (info, abfd, shortname, BSF_INDIRECT,
-             bfd_ind_section_ptr, (bfd_vma) 0, name, FALSE, collect, &bh)))
+             bfd_ind_section_ptr, 0, name, FALSE, collect, &bh)))
        return FALSE;
       hi = (struct elf_link_hash_entry *) bh;
 
@@ -1506,11 +1473,9 @@ nondefault:
    symbol table.  It is called via elf_link_hash_traverse.  */
 
 bfd_boolean
-_bfd_elf_export_symbol (h, data)
-     struct elf_link_hash_entry *h;
-     PTR data;
+_bfd_elf_export_symbol (struct elf_link_hash_entry *h, void *data)
 {
-  struct elf_info_failed *eif = (struct elf_info_failed *) data;
+  struct elf_info_failed *eif = data;
 
   /* Ignore indirect symbols.  These are added by the versioning code.  */
   if (h->root.type == bfd_link_hash_indirect)
@@ -1528,22 +1493,18 @@ _bfd_elf_export_symbol (h, data)
 
       for (t = eif->verdefs; t != NULL; t = t->next)
        {
-         if (t->globals != NULL)
+         if (t->globals.list != NULL)
            {
-             for (d = t->globals; d != NULL; d = d->next)
-               {
-                 if ((*d->match) (d, h->root.root.string))
-                   goto doit;
-               }
+             d = (*t->match) (&t->globals, NULL, h->root.root.string);
+             if (d != NULL)
+               goto doit;
            }
 
-         if (t->locals != NULL)
+         if (t->locals.list != NULL)
            {
-             for (d = t->locals ; d != NULL; d = d->next)
-               {
-                 if ((*d->match) (d, h->root.root.string))
-                   return TRUE;
-               }
+             d = (*t->match) (&t->locals, NULL, h->root.root.string);
+             if (d != NULL)
+               return TRUE;
            }
        }
 
@@ -1567,11 +1528,10 @@ _bfd_elf_export_symbol (h, data)
    This function is called via elf_link_hash_traverse.  */
 
 bfd_boolean
-_bfd_elf_link_find_version_dependencies (h, data)
-     struct elf_link_hash_entry *h;
-     PTR data;
+_bfd_elf_link_find_version_dependencies (struct elf_link_hash_entry *h,
+                                        void *data)
 {
-  struct elf_find_verdep_info *rinfo = (struct elf_find_verdep_info *) data;
+  struct elf_find_verdep_info *rinfo = data;
   Elf_Internal_Verneed *t;
   Elf_Internal_Vernaux *a;
   bfd_size_type amt;
@@ -1605,7 +1565,7 @@ _bfd_elf_link_find_version_dependencies (h, data)
   if (t == NULL)
     {
       amt = sizeof *t;
-      t = (Elf_Internal_Verneed *) bfd_zalloc (rinfo->output_bfd, amt);
+      t = bfd_zalloc (rinfo->output_bfd, amt);
       if (t == NULL)
        {
          rinfo->failed = TRUE;
@@ -1618,7 +1578,7 @@ _bfd_elf_link_find_version_dependencies (h, data)
     }
 
   amt = sizeof *a;
-  a = (Elf_Internal_Vernaux *) bfd_zalloc (rinfo->output_bfd, amt);
+  a = bfd_zalloc (rinfo->output_bfd, amt);
 
   /* Note that we are copying a string pointer here, and testing it
      above.  If bfd_elf_string_from_elf_section is ever changed to
@@ -1645,18 +1605,16 @@ _bfd_elf_link_find_version_dependencies (h, data)
    local.  This function is called via elf_link_hash_traverse.  */
 
 bfd_boolean
-_bfd_elf_link_assign_sym_version (h, data)
-     struct elf_link_hash_entry *h;
-     PTR data;
+_bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
 {
   struct elf_assign_sym_version_info *sinfo;
   struct bfd_link_info *info;
-  struct elf_backend_data *bed;
+  const struct elf_backend_data *bed;
   struct elf_info_failed eif;
   char *p;
   bfd_size_type amt;
 
-  sinfo = (struct elf_assign_sym_version_info *) data;
+  sinfo = data;
   info = sinfo->info;
 
   if (h->root.type == bfd_link_hash_warning)
@@ -1713,7 +1671,7 @@ _bfd_elf_link_assign_sym_version (h, data)
              struct bfd_elf_version_expr *d;
 
              len = p - h->root.root.string;
-             alc = bfd_malloc ((bfd_size_type) len);
+             alc = bfd_malloc (len);
              if (alc == NULL)
                return FALSE;
              memcpy (alc, h->root.root.string, len - 1);
@@ -1725,31 +1683,19 @@ _bfd_elf_link_assign_sym_version (h, data)
              t->used = TRUE;
              d = NULL;
 
-             if (t->globals != NULL)
-               {
-                 for (d = t->globals; d != NULL; d = d->next)
-                   if ((*d->match) (d, alc))
-                     break;
-               }
+             if (t->globals.list != NULL)
+               d = (*t->match) (&t->globals, NULL, alc);
 
              /* See if there is anything to force this symbol to
                 local scope.  */
-             if (d == NULL && t->locals != NULL)
+             if (d == NULL && t->locals.list != NULL)
                {
-                 for (d = t->locals; d != NULL; d = d->next)
-                   {
-                     if ((*d->match) (d, alc))
-                       {
-                         if (h->dynindx != -1
-                             && info->shared
-                             && ! info->export_dynamic)
-                           {
-                             (*bed->elf_backend_hide_symbol) (info, h, TRUE);
-                           }
-
-                         break;
-                       }
-                   }
+                 d = (*t->match) (&t->locals, NULL, alc);
+                 if (d != NULL
+                     && h->dynindx != -1
+                     && info->shared
+                     && ! info->export_dynamic)
+                   (*bed->elf_backend_hide_symbol) (info, h, TRUE);
                }
 
              free (alc);
@@ -1759,7 +1705,7 @@ _bfd_elf_link_assign_sym_version (h, data)
 
       /* If we are building an application, we need to create a
         version node for this version.  */
-      if (t == NULL && ! info->shared)
+      if (t == NULL && info->executable)
        {
          struct bfd_elf_version_tree **pp;
          int version_index;
@@ -1770,19 +1716,14 @@ _bfd_elf_link_assign_sym_version (h, data)
            return TRUE;
 
          amt = sizeof *t;
-         t = ((struct bfd_elf_version_tree *)
-              bfd_alloc (sinfo->output_bfd, amt));
+         t = bfd_zalloc (sinfo->output_bfd, amt);
          if (t == NULL)
            {
              sinfo->failed = TRUE;
              return FALSE;
            }
 
-         t->next = NULL;
          t->name = p;
-         t->globals = NULL;
-         t->locals = NULL;
-         t->deps = NULL;
          t->name_indx = (unsigned int) -1;
          t->used = TRUE;
 
@@ -1828,30 +1769,26 @@ _bfd_elf_link_assign_sym_version (h, data)
       local_ver = NULL;
       for (t = sinfo->verdefs; t != NULL; t = t->next)
        {
-         if (t->globals != NULL)
+         if (t->globals.list != NULL)
            {
              bfd_boolean matched;
 
              matched = FALSE;
-             for (d = t->globals; d != NULL; d = d->next)
-               {
-                 if ((*d->match) (d, h->root.root.string))
-                   {
-                     if (d->symver)
-                       matched = TRUE;
-                     else
-                       {
-                         /* There is a version without definition.  Make
-                            the symbol the default definition for this
-                            version.  */
-                         h->verinfo.vertree = t;
-                         local_ver = NULL;
-                         d->script = 1;
-                         break;
-                       }
-                   }
-               }
-
+             d = NULL;
+             while ((d = (*t->match) (&t->globals, d,
+                                      h->root.root.string)) != NULL)
+               if (d->symver)
+                 matched = TRUE;
+               else
+                 {
+                   /* There is a version without definition.  Make
+                      the symbol the default definition for this
+                      version.  */
+                   h->verinfo.vertree = t;
+                   local_ver = NULL;
+                   d->script = 1;
+                   break;
+                 }
              if (d != NULL)
                break;
              else if (matched)
@@ -1860,19 +1797,18 @@ _bfd_elf_link_assign_sym_version (h, data)
                (*bed->elf_backend_hide_symbol) (info, h, TRUE);
            }
 
-         if (t->locals != NULL)
+         if (t->locals.list != NULL)
            {
-             for (d = t->locals; d != NULL; d = d->next)
+             d = NULL;
+             while ((d = (*t->match) (&t->locals, d,
+                                      h->root.root.string)) != NULL)
                {
+                 local_ver = t;
                  /* If the match is "*", keep looking for a more
-                    explicit, perhaps even global, match.  */
-                 if (d->pattern[0] == '*' && d->pattern[1] == '\0')
-                   local_ver = t;
-                 else if ((*d->match) (d, h->root.root.string))
-                   {
-                     local_ver = t;
-                     break;
-                   }
+                    explicit, perhaps even global, match.
+                    XXX: Shouldn't this be !d->wildcard instead?  */
+                 if (d->pattern[0] != '*' || d->pattern[1] != '\0')
+                   break;
                }
 
              if (d != NULL)
@@ -1895,179 +1831,6 @@ _bfd_elf_link_assign_sym_version (h, data)
   return TRUE;
 }
 \f
-/* Create a special linker section, or return a pointer to a linker
-   section already created */
-
-elf_linker_section_t *
-_bfd_elf_create_linker_section (abfd, info, which, defaults)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     enum elf_linker_section_enum which;
-     elf_linker_section_t *defaults;
-{
-  bfd *dynobj = elf_hash_table (info)->dynobj;
-  elf_linker_section_t *lsect;
-
-  /* Record the first bfd section that needs the special section */
-  if (!dynobj)
-    dynobj = elf_hash_table (info)->dynobj = abfd;
-
-  /* If this is the first time, create the section */
-  lsect = elf_linker_section (dynobj, which);
-  if (!lsect)
-    {
-      asection *s;
-      bfd_size_type amt = sizeof (elf_linker_section_t);
-
-      lsect = (elf_linker_section_t *) bfd_alloc (dynobj, amt);
-
-      *lsect = *defaults;
-      elf_linker_section (dynobj, which) = lsect;
-      lsect->which = which;
-      lsect->hole_written_p = FALSE;
-
-      /* See if the sections already exist */
-      lsect->section = s = bfd_get_section_by_name (dynobj, lsect->name);
-      if (!s || (s->flags & defaults->flags) != defaults->flags)
-       {
-         lsect->section = s = bfd_make_section_anyway (dynobj, lsect->name);
-
-         if (s == NULL)
-           return (elf_linker_section_t *)0;
-
-         bfd_set_section_flags (dynobj, s, defaults->flags);
-         bfd_set_section_alignment (dynobj, s, lsect->alignment);
-       }
-      else if (bfd_get_section_alignment (dynobj, s) < lsect->alignment)
-       bfd_set_section_alignment (dynobj, s, lsect->alignment);
-
-      s->_raw_size = align_power (s->_raw_size, lsect->alignment);
-
-      /* Is there a hole we have to provide?  If so check whether the
-        segment is too big already */
-      if (lsect->hole_size)
-       {
-         lsect->hole_offset = s->_raw_size;
-         s->_raw_size += lsect->hole_size;
-         if (lsect->hole_offset > lsect->max_hole_offset)
-           {
-             (*_bfd_error_handler)
-               (_("%s: Section %s is too large to add hole of %ld bytes"),
-                bfd_get_filename (abfd),
-                lsect->name,
-                (long) lsect->hole_size);
-
-             bfd_set_error (bfd_error_bad_value);
-             return (elf_linker_section_t *)0;
-           }
-       }
-
-#ifdef DEBUG
-      fprintf (stderr, "Creating section %s, current size = %ld\n",
-              lsect->name, (long)s->_raw_size);
-#endif
-
-      if (lsect->sym_name)
-       {
-         struct elf_link_hash_entry *h;
-         struct bfd_link_hash_entry *bh;
-
-#ifdef DEBUG
-         fprintf (stderr, "Adding %s to section %s\n",
-                  lsect->sym_name,
-                  lsect->name);
-#endif
-         bh = bfd_link_hash_lookup (info->hash, lsect->sym_name,
-                                    FALSE, FALSE, FALSE);
-
-         if ((bh == NULL || bh->type == bfd_link_hash_undefined)
-             && !(_bfd_generic_link_add_one_symbol
-                  (info, abfd, lsect->sym_name, BSF_GLOBAL, s,
-                   (lsect->hole_size
-                    ? s->_raw_size - lsect->hole_size + lsect->sym_offset
-                    : lsect->sym_offset),
-                   (const char *) NULL, FALSE,
-                   get_elf_backend_data (abfd)->collect, &bh)))
-           return (elf_linker_section_t *) 0;
-         h = (struct elf_link_hash_entry *) bh;
-
-         if ((defaults->which != LINKER_SECTION_SDATA)
-             && (defaults->which != LINKER_SECTION_SDATA2))
-           h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_DYNAMIC;
-
-         h->type = STT_OBJECT;
-         lsect->sym_hash = h;
-
-         if (info->shared
-             && ! _bfd_elf_link_record_dynamic_symbol (info, h))
-           return (elf_linker_section_t *) 0;
-       }
-    }
-
-#if 0
-  /* This does not make sense.  The sections which may exist in the
-     object file have nothing to do with the sections we want to
-     create.  */
-
-  /* Find the related sections if they have been created */
-  if (lsect->bss_name && !lsect->bss_section)
-    lsect->bss_section = bfd_get_section_by_name (dynobj, lsect->bss_name);
-
-  if (lsect->rel_name && !lsect->rel_section)
-    lsect->rel_section = bfd_get_section_by_name (dynobj, lsect->rel_name);
-#endif
-
-  return lsect;
-}
-\f
-/* Find a linker generated pointer with a given addend and type.  */
-
-elf_linker_section_pointers_t *
-_bfd_elf_find_pointer_linker_section (linker_pointers, addend, which)
-     elf_linker_section_pointers_t *linker_pointers;
-     bfd_vma addend;
-     elf_linker_section_enum_t which;
-{
-  for ( ; linker_pointers != NULL; linker_pointers = linker_pointers->next)
-    {
-      if (which == linker_pointers->which && addend == linker_pointers->addend)
-       return linker_pointers;
-    }
-
-  return (elf_linker_section_pointers_t *)0;
-}
-\f
-/* Make the .rela section corresponding to the generated linker section.  */
-
-bfd_boolean
-_bfd_elf_make_linker_section_rela (dynobj, lsect, alignment)
-     bfd *dynobj;
-     elf_linker_section_t *lsect;
-     int alignment;
-{
-  if (lsect->rel_section)
-    return TRUE;
-
-  lsect->rel_section = bfd_get_section_by_name (dynobj, lsect->rel_name);
-  if (lsect->rel_section == NULL)
-    {
-      lsect->rel_section = bfd_make_section (dynobj, lsect->rel_name);
-      if (lsect->rel_section == NULL
-         || ! bfd_set_section_flags (dynobj,
-                                     lsect->rel_section,
-                                     (SEC_ALLOC
-                                      | SEC_LOAD
-                                      | SEC_HAS_CONTENTS
-                                      | SEC_IN_MEMORY
-                                      | SEC_LINKER_CREATED
-                                      | SEC_READONLY))
-         || ! bfd_set_section_alignment (dynobj, lsect->rel_section, alignment))
-       return FALSE;
-    }
-
-  return TRUE;
-}
-\f
 /* Read and swap the relocs from the section indicated by SHDR.  This
    may be either a REL or a RELA section.  The relocations are
    translated into RELA relocations and stored in INTERNAL_RELOCS,
@@ -2078,18 +1841,19 @@ _bfd_elf_make_linker_section_rela (dynobj, lsect, alignment)
    Returns FALSE if something goes wrong.  */
 
 static bfd_boolean
-elf_link_read_relocs_from_section (abfd, shdr, external_relocs,
-                                  internal_relocs)
-     bfd *abfd;
-     Elf_Internal_Shdr *shdr;
-     PTR external_relocs;
-     Elf_Internal_Rela *internal_relocs;
+elf_link_read_relocs_from_section (bfd *abfd,
+                                  asection *sec,
+                                  Elf_Internal_Shdr *shdr,
+                                  void *external_relocs,
+                                  Elf_Internal_Rela *internal_relocs)
 {
-  struct elf_backend_data *bed;
-  void (*swap_in) PARAMS ((bfd *, const bfd_byte *, Elf_Internal_Rela *));
+  const struct elf_backend_data *bed;
+  void (*swap_in) (bfd *, const bfd_byte *, Elf_Internal_Rela *);
   const bfd_byte *erela;
   const bfd_byte *erelaend;
   Elf_Internal_Rela *irela;
+  Elf_Internal_Shdr *symtab_hdr;
+  size_t nsyms;
 
   /* If there aren't any relocations, that's OK.  */
   if (!shdr)
@@ -2103,6 +1867,9 @@ elf_link_read_relocs_from_section (abfd, shdr, external_relocs,
   if (bfd_bread (external_relocs, shdr->sh_size, abfd) != shdr->sh_size)
     return FALSE;
 
+  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+  nsyms = symtab_hdr->sh_size / symtab_hdr->sh_entsize;
+
   bed = get_elf_backend_data (abfd);
 
   /* Convert the external relocations to the internal format.  */
@@ -2121,7 +1888,21 @@ elf_link_read_relocs_from_section (abfd, shdr, external_relocs,
   irela = internal_relocs;
   while (erela < erelaend)
     {
+      bfd_vma r_symndx;
+
       (*swap_in) (abfd, erela, irela);
+      r_symndx = ELF32_R_SYM (irela->r_info);
+      if (bed->s->arch_size == 64)
+       r_symndx >>= 24;
+      if ((size_t) r_symndx >= nsyms)
+       {
+         (*_bfd_error_handler)
+           (_("%s: bad reloc symbol index (0x%lx >= 0x%lx) for offset 0x%lx in section `%s'"),
+            bfd_archive_filename (abfd), (unsigned long) r_symndx,
+            (unsigned long) nsyms, irela->r_offset, sec->name);
+         bfd_set_error (bfd_error_bad_value);
+         return FALSE;
+       }
       irela += bed->s->int_rels_per_ext_rel;
       erela += shdr->sh_entsize;
     }
@@ -2140,18 +1921,16 @@ elf_link_read_relocs_from_section (abfd, shdr, external_relocs,
    REL_HDR2 relocations.  */
 
 Elf_Internal_Rela *
-_bfd_elf_link_read_relocs (abfd, o, external_relocs, internal_relocs,
-                          keep_memory)
-     bfd *abfd;
-     asection *o;
-     PTR external_relocs;
-     Elf_Internal_Rela *internal_relocs;
-     bfd_boolean keep_memory;
+_bfd_elf_link_read_relocs (bfd *abfd,
+                          asection *o,
+                          void *external_relocs,
+                          Elf_Internal_Rela *internal_relocs,
+                          bfd_boolean keep_memory)
 {
   Elf_Internal_Shdr *rel_hdr;
-  PTR alloc1 = NULL;
+  void *alloc1 = NULL;
   Elf_Internal_Rela *alloc2 = NULL;
-  struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
   if (elf_section_data (o)->relocs != NULL)
     return elf_section_data (o)->relocs;
@@ -2168,9 +1947,9 @@ _bfd_elf_link_read_relocs (abfd, o, external_relocs, internal_relocs,
       size = o->reloc_count;
       size *= bed->s->int_rels_per_ext_rel * sizeof (Elf_Internal_Rela);
       if (keep_memory)
-       internal_relocs = (Elf_Internal_Rela *) bfd_alloc (abfd, size);
+       internal_relocs = bfd_alloc (abfd, size);
       else
-       internal_relocs = alloc2 = (Elf_Internal_Rela *) bfd_malloc (size);
+       internal_relocs = alloc2 = bfd_malloc (size);
       if (internal_relocs == NULL)
        goto error_return;
     }
@@ -2181,18 +1960,18 @@ _bfd_elf_link_read_relocs (abfd, o, external_relocs, internal_relocs,
 
       if (elf_section_data (o)->rel_hdr2)
        size += elf_section_data (o)->rel_hdr2->sh_size;
-      alloc1 = (PTR) bfd_malloc (size);
+      alloc1 = bfd_malloc (size);
       if (alloc1 == NULL)
        goto error_return;
       external_relocs = alloc1;
     }
 
-  if (!elf_link_read_relocs_from_section (abfd, rel_hdr,
+  if (!elf_link_read_relocs_from_section (abfd, o, rel_hdr,
                                          external_relocs,
                                          internal_relocs))
     goto error_return;
   if (!elf_link_read_relocs_from_section
-      (abfd,
+      (abfd, o,
        elf_section_data (o)->rel_hdr2,
        ((bfd_byte *) external_relocs) + rel_hdr->sh_size,
        internal_relocs + (NUM_SHDR_ENTRIES (rel_hdr)
@@ -2223,10 +2002,9 @@ _bfd_elf_link_read_relocs (abfd, o, external_relocs, internal_relocs,
    section header for a section containing relocations for O.  */
 
 bfd_boolean
-_bfd_elf_link_size_reloc_section (abfd, rel_hdr, o)
-     bfd *abfd;
-     Elf_Internal_Shdr *rel_hdr;
-     asection *o;
+_bfd_elf_link_size_reloc_section (bfd *abfd,
+                                 Elf_Internal_Shdr *rel_hdr,
+                                 asection *o)
 {
   bfd_size_type reloc_count;
   bfd_size_type num_rel_hashes;
@@ -2248,7 +2026,7 @@ _bfd_elf_link_size_reloc_section (abfd, rel_hdr, o)
      allocate it with bfd_alloc rather than malloc.  Also since we
      cannot be sure that the contents will actually be filled in,
      we zero the allocated space.  */
-  rel_hdr->contents = (PTR) bfd_zalloc (abfd, rel_hdr->sh_size);
+  rel_hdr->contents = bfd_zalloc (abfd, rel_hdr->sh_size);
   if (rel_hdr->contents == NULL && rel_hdr->sh_size != 0)
     return FALSE;
 
@@ -2259,9 +2037,7 @@ _bfd_elf_link_size_reloc_section (abfd, rel_hdr, o)
     {
       struct elf_link_hash_entry **p;
 
-      p = ((struct elf_link_hash_entry **)
-          bfd_zmalloc (num_rel_hashes
-                       * sizeof (struct elf_link_hash_entry *)));
+      p = bfd_zmalloc (num_rel_hashes * sizeof (struct elf_link_hash_entry *));
       if (p == NULL)
        return FALSE;
 
@@ -2276,12 +2052,10 @@ _bfd_elf_link_size_reloc_section (abfd, rel_hdr, o)
    OUTPUT_BFD.  */
 
 bfd_boolean
-_bfd_elf_link_output_relocs (output_bfd, input_section, input_rel_hdr,
-                            internal_relocs)
-     bfd *output_bfd;
-     asection *input_section;
-     Elf_Internal_Shdr *input_rel_hdr;
-     Elf_Internal_Rela *internal_relocs;
+_bfd_elf_link_output_relocs (bfd *output_bfd,
+                            asection *input_section,
+                            Elf_Internal_Shdr *input_rel_hdr,
+                            Elf_Internal_Rela *internal_relocs)
 {
   Elf_Internal_Rela *irela;
   Elf_Internal_Rela *irelaend;
@@ -2289,8 +2063,8 @@ _bfd_elf_link_output_relocs (output_bfd, input_section, input_rel_hdr,
   Elf_Internal_Shdr *output_rel_hdr;
   asection *output_section;
   unsigned int *rel_countp = NULL;
-  struct elf_backend_data *bed;
-  void (*swap_out) PARAMS ((bfd *, const Elf_Internal_Rela *, bfd_byte *));
+  const struct elf_backend_data *bed;
+  void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *);
 
   output_section = input_section->output_section;
   output_rel_hdr = NULL;
@@ -2353,9 +2127,8 @@ _bfd_elf_link_output_relocs (output_bfd, input_section, input_rel_hdr,
    the face of future changes.  */
 
 bfd_boolean
-_bfd_elf_fix_symbol_flags (h, eif)
-     struct elf_link_hash_entry *h;
-     struct elf_info_failed *eif;
+_bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h,
+                          struct elf_info_failed *eif)
 {
   /* If this symbol was mentioned in a non-ELF file, try to set
      DEF_REGULAR and REF_REGULAR correctly.  This is the only way to
@@ -2427,20 +2200,17 @@ _bfd_elf_fix_symbol_flags (h, eif)
   /* If -Bsymbolic was used (which means to bind references to global
      symbols to the definition within the shared object), and this
      symbol was defined in a regular object, then it actually doesn't
-     need a PLT entry, and we can accomplish that by forcing it local.
-     Likewise, if the symbol has hidden or internal visibility.
-     FIXME: It might be that we also do not need a PLT for other
-     non-hidden visibilities, but we would have to tell that to the
-     backend specifically; we can't just clear PLT-related data here.  */
+     need a PLT entry.  Likewise, if the symbol has non-default
+     visibility.  If the symbol has hidden or internal visibility, we
+     will force it local.  */
   if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0
       && eif->info->shared
-      && is_elf_hash_table (eif->info)
+      && is_elf_hash_table (eif->info->hash)
       && (eif->info->symbolic
-         || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL
-         || ELF_ST_VISIBILITY (h->other) == STV_HIDDEN)
+         || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
       && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0)
     {
-      struct elf_backend_data *bed;
+      const struct elf_backend_data *bed;
       bfd_boolean force_local;
 
       bed = get_elf_backend_data (elf_hash_table (eif->info)->dynobj);
@@ -2452,10 +2222,10 @@ _bfd_elf_fix_symbol_flags (h, eif)
 
   /* If a weak undefined symbol has non-default visibility, we also
      hide it from the dynamic linker.  */
-  if (ELF_ST_VISIBILITY (h->other)
+  if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
       && h->root.type == bfd_link_hash_undefweak)
     {
-      struct elf_backend_data *bed;
+      const struct elf_backend_data *bed;
       bed = get_elf_backend_data (elf_hash_table (eif->info)->dynobj);
       (*bed->elf_backend_hide_symbol) (eif->info, h, TRUE);
     }
@@ -2484,7 +2254,7 @@ _bfd_elf_fix_symbol_flags (h, eif)
        h->weakdef = NULL;
       else
        {
-         struct elf_backend_data *bed;
+         const struct elf_backend_data *bed;
 
          bed = get_elf_backend_data (elf_hash_table (eif->info)->dynobj);
          (*bed->elf_backend_copy_indirect_symbol) (bed, weakdef, h);
@@ -2499,15 +2269,13 @@ _bfd_elf_fix_symbol_flags (h, eif)
    recursively.  */
 
 bfd_boolean
-_bfd_elf_adjust_dynamic_symbol (h, data)
-     struct elf_link_hash_entry *h;
-     PTR data;
+_bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data)
 {
-  struct elf_info_failed *eif = (struct elf_info_failed *) data;
+  struct elf_info_failed *eif = data;
   bfd *dynobj;
-  struct elf_backend_data *bed;
+  const struct elf_backend_data *bed;
 
-  if (! is_elf_hash_table (eif->info))
+  if (! is_elf_hash_table (eif->info->hash))
     return FALSE;
 
   if (h->root.type == bfd_link_hash_warning)
@@ -2593,7 +2361,7 @@ _bfd_elf_adjust_dynamic_symbol (h, data)
         H->WEAKDEF before it finds H?  */
       h->weakdef->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR;
 
-      if (! _bfd_elf_adjust_dynamic_symbol (h->weakdef, (PTR) eif))
+      if (! _bfd_elf_adjust_dynamic_symbol (h->weakdef, eif))
        return FALSE;
     }
 
@@ -2624,9 +2392,7 @@ _bfd_elf_adjust_dynamic_symbol (h, data)
    to reflect the object merging within the sections.  */
 
 bfd_boolean
-_bfd_elf_link_sec_merge_syms (h, data)
-     struct elf_link_hash_entry *h;
-     PTR data;
+_bfd_elf_link_sec_merge_syms (struct elf_link_hash_entry *h, void *data)
 {
   asection *sec;
 
@@ -2638,14 +2404,145 @@ _bfd_elf_link_sec_merge_syms (h, data)
       && ((sec = h->root.u.def.section)->flags & SEC_MERGE)
       && sec->sec_info_type == ELF_INFO_TYPE_MERGE)
     {
-      bfd *output_bfd = (bfd *) data;
+      bfd *output_bfd = data;
 
       h->root.u.def.value =
        _bfd_merged_section_offset (output_bfd,
                                    &h->root.u.def.section,
                                    elf_section_data (sec)->sec_info,
-                                   h->root.u.def.value, (bfd_vma) 0);
+                                   h->root.u.def.value, 0);
     }
 
   return TRUE;
 }
+
+/* Returns false if the symbol referred to by H should be considered
+   to resolve local to the current module, and true if it should be
+   considered to bind dynamically.  */
+
+bfd_boolean
+_bfd_elf_dynamic_symbol_p (struct elf_link_hash_entry *h,
+                          struct bfd_link_info *info,
+                          bfd_boolean ignore_protected)
+{
+  bfd_boolean binding_stays_local_p;
+
+  if (h == NULL)
+    return FALSE;
+
+  while (h->root.type == bfd_link_hash_indirect
+        || h->root.type == bfd_link_hash_warning)
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+  /* If it was forced local, then clearly it's not dynamic.  */
+  if (h->dynindx == -1)
+    return FALSE;
+  if (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL)
+    return FALSE;
+
+  /* Identify the cases where name binding rules say that a
+     visible symbol resolves locally.  */
+  binding_stays_local_p = info->executable || info->symbolic;
+
+  switch (ELF_ST_VISIBILITY (h->other))
+    {
+    case STV_INTERNAL:
+    case STV_HIDDEN:
+      return FALSE;
+
+    case STV_PROTECTED:
+      /* Proper resolution for function pointer equality may require
+        that these symbols perhaps be resolved dynamically, even though
+        we should be resolving them to the current module.  */
+      if (!ignore_protected)
+       binding_stays_local_p = TRUE;
+      break;
+
+    default:
+      break;
+    }
+
+  /* If it isn't defined locally, then clearly it's dynamic.  */
+  if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+    return TRUE;
+
+  /* Otherwise, the symbol is dynamic if binding rules don't tell
+     us that it remains local.  */
+  return !binding_stays_local_p;
+}
+
+/* Return true if the symbol referred to by H should be considered
+   to resolve local to the current module, and false otherwise.  Differs
+   from (the inverse of) _bfd_elf_dynamic_symbol_p in the treatment of
+   undefined symbols and weak symbols.  */
+
+bfd_boolean
+_bfd_elf_symbol_refs_local_p (struct elf_link_hash_entry *h,
+                             struct bfd_link_info *info,
+                             bfd_boolean local_protected)
+{
+  /* If it's a local sym, of course we resolve locally.  */
+  if (h == NULL)
+    return TRUE;
+
+  /* If we don't have a definition in a regular file, then we can't
+     resolve locally.  The sym is either undefined or dynamic.  */
+  if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+    return FALSE;
+
+  /* Forced local symbols resolve locally.  */
+  if ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)
+    return TRUE;
+
+  /* As do non-dynamic symbols.  */
+  if (h->dynindx == -1)
+    return TRUE;
+
+  /* At this point, we know the symbol is defined and dynamic.  In an
+     executable it must resolve locally, likewise when building symbolic
+     shared libraries.  */
+  if (info->executable || info->symbolic)
+    return TRUE;
+
+  /* Now deal with defined dynamic symbols in shared libraries.  Ones
+     with default visibility might not resolve locally.  */
+  if (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
+    return FALSE;
+
+  /* However, STV_HIDDEN or STV_INTERNAL ones must be local.  */
+  if (ELF_ST_VISIBILITY (h->other) != STV_PROTECTED)
+    return TRUE;
+
+  /* Function pointer equality tests may require that STV_PROTECTED
+     symbols be treated as dynamic symbols, even when we know that the
+     dynamic linker will resolve them locally.  */
+  return local_protected;
+}
+
+/* Caches some TLS segment info, and ensures that the TLS segment vma is
+   aligned.  Returns the first TLS output section.  */
+
+struct bfd_section *
+_bfd_elf_tls_setup (bfd *obfd, struct bfd_link_info *info)
+{
+  struct bfd_section *sec, *tls;
+  unsigned int align = 0;
+
+  for (sec = obfd->sections; sec != NULL; sec = sec->next)
+    if ((sec->flags & SEC_THREAD_LOCAL) != 0)
+      break;
+  tls = sec;
+
+  for (; sec != NULL && (sec->flags & SEC_THREAD_LOCAL) != 0; sec = sec->next)
+    if (sec->alignment_power > align)
+      align = sec->alignment_power;
+
+  elf_hash_table (info)->tls_sec = tls;
+
+  /* Ensure the alignment of the first section is the largest alignment,
+     so that the tls segment starts aligned.  */
+  if (tls != NULL)
+    tls->alignment_power = align;
+
+  return tls;
+}
This page took 0.043683 seconds and 4 git commands to generate.