bfd/
[deliverable/binutils-gdb.git] / bfd / elflink.c
index 8134834cd914c2b99646ede486676e9878ec188a..457ba8e6213209f8480ae8d628d6cd9484e406a8 100644 (file)
@@ -16,7 +16,7 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
 
 #include "bfd.h"
 #include "sysdep.h"
@@ -59,17 +59,15 @@ _bfd_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
 
   flags = bed->dynamic_sec_flags;
 
-  s = bfd_make_section (abfd, ".got");
+  s = bfd_make_section_with_flags (abfd, ".got", flags);
   if (s == NULL
-      || !bfd_set_section_flags (abfd, s, flags)
       || !bfd_set_section_alignment (abfd, s, ptralign))
     return FALSE;
 
   if (bed->want_got_plt)
     {
-      s = bfd_make_section (abfd, ".got.plt");
+      s = bfd_make_section_with_flags (abfd, ".got.plt", flags);
       if (s == NULL
-         || !bfd_set_section_flags (abfd, s, flags)
          || !bfd_set_section_alignment (abfd, s, ptralign))
        return FALSE;
     }
@@ -83,7 +81,7 @@ _bfd_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
       bh = NULL;
       if (!(_bfd_generic_link_add_one_symbol
            (info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, s,
-            bed->got_symbol_offset, NULL, FALSE, bed->collect, &bh)))
+            0, NULL, FALSE, bed->collect, &bh)))
        return FALSE;
       h = (struct elf_link_hash_entry *) bh;
       h->def_regular = 1;
@@ -98,7 +96,7 @@ _bfd_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
     }
 
   /* The first bit of the global offset table is the header.  */
-  s->size += bed->got_header_size + bed->got_symbol_offset;
+  s->size += bed->got_header_size;
 
   return TRUE;
 }
@@ -156,17 +154,17 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
      shared library does not.  */
   if (info->executable)
     {
-      s = bfd_make_section (abfd, ".interp");
-      if (s == NULL
-         || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY))
+      s = bfd_make_section_with_flags (abfd, ".interp",
+                                      flags | SEC_READONLY);
+      if (s == NULL)
        return FALSE;
     }
 
   if (! info->traditional_format)
     {
-      s = bfd_make_section (abfd, ".eh_frame_hdr");
+      s = bfd_make_section_with_flags (abfd, ".eh_frame_hdr",
+                                      flags | SEC_READONLY);
       if (s == NULL
-         || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
          || ! bfd_set_section_alignment (abfd, s, 2))
        return FALSE;
       elf_hash_table (info)->eh_info.hdr_sec = s;
@@ -174,38 +172,37 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
 
   /* Create sections to hold version informations.  These are removed
      if they are not needed.  */
-  s = bfd_make_section (abfd, ".gnu.version_d");
+  s = bfd_make_section_with_flags (abfd, ".gnu.version_d",
+                                  flags | SEC_READONLY);
   if (s == NULL
-      || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
       || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
     return FALSE;
 
-  s = bfd_make_section (abfd, ".gnu.version");
+  s = bfd_make_section_with_flags (abfd, ".gnu.version",
+                                  flags | SEC_READONLY);
   if (s == NULL
-      || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
       || ! bfd_set_section_alignment (abfd, s, 1))
     return FALSE;
 
-  s = bfd_make_section (abfd, ".gnu.version_r");
+  s = bfd_make_section_with_flags (abfd, ".gnu.version_r",
+                                  flags | SEC_READONLY);
   if (s == NULL
-      || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
       || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
     return FALSE;
 
-  s = bfd_make_section (abfd, ".dynsym");
+  s = bfd_make_section_with_flags (abfd, ".dynsym",
+                                  flags | SEC_READONLY);
   if (s == NULL
-      || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
       || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
     return FALSE;
 
-  s = bfd_make_section (abfd, ".dynstr");
-  if (s == NULL
-      || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY))
+  s = bfd_make_section_with_flags (abfd, ".dynstr",
+                                  flags | SEC_READONLY);
+  if (s == NULL)
     return FALSE;
 
-  s = bfd_make_section (abfd, ".dynamic");
+  s = bfd_make_section_with_flags (abfd, ".dynamic", flags);
   if (s == NULL
-      || ! bfd_set_section_flags (abfd, s, flags)
       || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
     return FALSE;
 
@@ -238,9 +235,9 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
       && ! bfd_elf_link_record_dynamic_symbol (info, h))
     return FALSE;
 
-  s = bfd_make_section (abfd, ".hash");
+  s = bfd_make_section_with_flags (abfd, ".hash",
+                                  flags | SEC_READONLY);
   if (s == NULL
-      || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
       || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
     return FALSE;
   elf_section_data (s)->this_hdr.sh_entsize = bed->s->sizeof_hash_entry;
@@ -280,9 +277,8 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
   if (bed->plt_readonly)
     pltflags |= SEC_READONLY;
 
-  s = bfd_make_section (abfd, ".plt");
+  s = bfd_make_section_with_flags (abfd, ".plt", pltflags);
   if (s == NULL
-      || ! bfd_set_section_flags (abfd, s, pltflags)
       || ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
     return FALSE;
 
@@ -306,10 +302,11 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
        return FALSE;
     }
 
-  s = bfd_make_section (abfd,
-                       bed->default_use_rela_p ? ".rela.plt" : ".rel.plt");
+  s = bfd_make_section_with_flags (abfd,
+                                  (bed->default_use_rela_p
+                                   ? ".rela.plt" : ".rel.plt"),
+                                  flags | SEC_READONLY);
   if (s == NULL
-      || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
       || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
     return FALSE;
 
@@ -324,9 +321,10 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
         image and use a R_*_COPY reloc to tell the dynamic linker to
         initialize them at run time.  The linker script puts the .dynbss
         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 | SEC_LINKER_CREATED))
+      s = bfd_make_section_with_flags (abfd, ".dynbss",
+                                      (SEC_ALLOC
+                                       | SEC_LINKER_CREATED));
+      if (s == NULL)
        return FALSE;
 
       /* The .rel[a].bss section holds copy relocs.  This section is not
@@ -342,11 +340,11 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
         copy relocs.  */
       if (! info->shared)
        {
-         s = bfd_make_section (abfd,
-                               (bed->default_use_rela_p
-                                ? ".rela.bss" : ".rel.bss"));
+         s = bfd_make_section_with_flags (abfd,
+                                          (bed->default_use_rela_p
+                                           ? ".rela.bss" : ".rel.bss"),
+                                          flags | SEC_READONLY);
          if (s == NULL
-             || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
              || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
            return FALSE;
        }
@@ -435,8 +433,7 @@ bfd_elf_link_record_dynamic_symbol (struct bfd_link_info *info,
    this in case some dynamic object refers to this symbol.  */
 
 bfd_boolean
-bfd_elf_record_link_assignment (bfd *output_bfd ATTRIBUTE_UNUSED,
-                               struct bfd_link_info *info,
+bfd_elf_record_link_assignment (struct bfd_link_info *info,
                                const char *name,
                                bfd_boolean provide)
 {
@@ -783,6 +780,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
   bfd *oldbfd;
   bfd_boolean newdyn, olddyn, olddef, newdef, newdyncommon, olddyncommon;
   bfd_boolean newweak, oldweak;
+  const struct elf_backend_data *bed;
 
   *skip = FALSE;
   *override = FALSE;
@@ -922,7 +920,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
 
       if (h->type == STT_TLS)
        {
-         ntbfd = abfd; 
+         ntbfd = abfd;
          ntsec = sec;
          ntdef = newdef;
          tbfd = oldbfd;
@@ -1124,6 +1122,19 @@ _bfd_elf_merge_symbol (bfd *abfd,
   else
     olddyncommon = FALSE;
 
+  /* We now know everything about the old and new symbols.  We ask the
+     backend to check if we can merge them.  */
+  bed = get_elf_backend_data (abfd);
+  if (bed->merge_symbol
+      && !bed->merge_symbol (info, sym_hash, h, sym, psec, pvalue,
+                            pold_alignment, skip, override,
+                            type_change_ok, size_change_ok,
+                            &newdyn, &newdef, &newdyncommon, &newweak,
+                            abfd, &sec,
+                            &olddyn, &olddef, &olddyncommon, &oldweak,
+                            oldbfd, &oldsec))
+    return FALSE;
+
   /* If both the old and the new symbols look like common symbols in a
      dynamic object, set the size of the symbol to the larger of the
      two.  */
@@ -1190,8 +1201,8 @@ _bfd_elf_merge_symbol (bfd *abfd,
   /* Handle the special case of an old common symbol merging with a
      new symbol which looks like a common symbol in a shared object.
      We change *PSEC and *PVALUE to make the new symbol look like a
-     common symbol, and let _bfd_generic_link_add_one_symbol will do
-     the right thing.  */
+     common symbol, and let _bfd_generic_link_add_one_symbol do the
+     right thing.  */
 
   if (newdyncommon
       && h->root.type == bfd_link_hash_common)
@@ -1200,10 +1211,14 @@ _bfd_elf_merge_symbol (bfd *abfd,
       newdef = FALSE;
       newdyncommon = FALSE;
       *pvalue = sym->st_size;
-      *psec = sec = bfd_com_section_ptr;
+      *psec = sec = bed->common_section (oldsec);
       *size_change_ok = TRUE;
     }
 
+  /* Skip weak definitions of symbols that are already defined.  */
+  if (newdef && olddef && newweak)
+    *skip = TRUE;
+
   /* If the old symbol is from a dynamic object, and the new symbol is
      a definition which is not from a dynamic object, then the new
      symbol overrides the old symbol.  Symbols from regular files
@@ -1774,7 +1789,6 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
                  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);
                }
@@ -1901,7 +1915,6 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
        {
          h->verinfo.vertree = local_ver;
          if (h->dynindx != -1
-             && info->shared
              && ! info->export_dynamic)
            {
              (*bed->elf_backend_hide_symbol) (info, h, TRUE);
@@ -2134,7 +2147,9 @@ bfd_boolean
 _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 *internal_relocs,
+                            struct elf_link_hash_entry **rel_hash
+                              ATTRIBUTE_UNUSED)
 {
   Elf_Internal_Rela *irela;
   Elf_Internal_Rela *irelaend;
@@ -2360,8 +2375,8 @@ _bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data)
 
   if (h->root.type == bfd_link_hash_warning)
     {
-      h->plt = elf_hash_table (eif->info)->init_offset;
-      h->got = elf_hash_table (eif->info)->init_offset;
+      h->got = elf_hash_table (eif->info)->init_got_offset;
+      h->plt = elf_hash_table (eif->info)->init_plt_offset;
 
       /* When warning symbols are created, they **replace** the "real"
         entry in the hash table, thus we never get to see the real
@@ -2390,7 +2405,7 @@ _bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data)
          || (!h->ref_regular
              && (h->u.weakdef == NULL || h->u.weakdef->dynindx == -1))))
     {
-      h->plt = elf_hash_table (eif->info)->init_offset;
+      h->plt = elf_hash_table (eif->info)->init_plt_offset;
       return TRUE;
     }
 
@@ -2640,6 +2655,8 @@ static bfd_boolean
 is_global_data_symbol_definition (bfd *abfd ATTRIBUTE_UNUSED,
                                  Elf_Internal_Sym *sym)
 {
+  const struct elf_backend_data *bed;
+
   /* Local symbols do not count, but target specific ones might.  */
   if (ELF_ST_BIND (sym->st_info) != STB_GLOBAL
       && ELF_ST_BIND (sym->st_info) < STB_LOOS)
@@ -2655,7 +2672,8 @@ is_global_data_symbol_definition (bfd *abfd ATTRIBUTE_UNUSED,
 
   /* If the symbol is defined in the common section, then
      it is a common definition and so does not count.  */
-  if (sym->st_shndx == SHN_COMMON)
+  bed = get_elf_backend_data (abfd);
+  if (bed->common_definition (sym))
     return FALSE;
 
   /* If the symbol is in a target specific section then we
@@ -2935,8 +2953,11 @@ elf_smash_syms (struct elf_link_hash_entry *h, void *data)
   if (h->ref_regular)
     abort ();
 
-  /* Set sym back to newly created state, but keep undefs list pointer.  */
+  /* Set sym back to newly created state, but keep undef.next if it is
+     being used as a list pointer.  */
   bh = h->root.u.undef.next;
+  if (bh == &h->root)
+    bh = NULL;
   if (bh != NULL || inf->htab->root.undefs_tail == &h->root)
     inf->twiddled = TRUE;
   (*inf->htab->root.table.newfunc) (&h->root.root,
@@ -3544,6 +3565,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
       bfd_boolean type_change_ok;
       bfd_boolean new_weakdef;
       bfd_boolean override;
+      bfd_boolean common;
       unsigned int old_alignment;
       bfd *old_bfd;
 
@@ -3553,6 +3575,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
       sec = NULL;
       value = isym->st_value;
       *sym_hash = NULL;
+      common = bed->common_definition (isym);
 
       bind = ELF_ST_BIND (isym->st_info);
       if (bind == STB_LOCAL)
@@ -3565,8 +3588,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
        }
       else if (bind == STB_GLOBAL)
        {
-         if (isym->st_shndx != SHN_UNDEF
-             && isym->st_shndx != SHN_COMMON)
+         if (isym->st_shndx != SHN_UNDEF && !common)
            flags = BSF_GLOBAL;
        }
       else if (bind == STB_WEAK)
@@ -3586,7 +3608,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
          else if (sec->kept_section)
            {
              /* Symbols from discarded section are undefined, and have
-                default visibility.  */
+                default visibility.  */
              sec = bfd_und_section_ptr;
              isym->st_shndx = SHN_UNDEF;
              isym->st_other = STV_DEFAULT
@@ -3621,12 +3643,12 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
 
          if (tcomm == NULL)
            {
-             tcomm = bfd_make_section (abfd, ".tcommon");
-             if (tcomm == NULL
-                 || !bfd_set_section_flags (abfd, tcomm, (SEC_ALLOC
-                                                          | SEC_IS_COMMON
-                                                          | SEC_LINKER_CREATED
-                                                          | SEC_THREAD_LOCAL)))
+             tcomm = bfd_make_section_with_flags (abfd, ".tcommon",
+                                                  (SEC_ALLOC
+                                                   | SEC_IS_COMMON
+                                                   | SEC_LINKER_CREATED
+                                                   | SEC_THREAD_LOCAL));
+             if (tcomm == NULL)
                goto error_free_vers;
            }
          sec = tcomm;
@@ -3683,11 +3705,12 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
 
          /* 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?  */
+            However, we do not modify a non-hidden absolute symbol
+            if it is not a function, 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)))
+             || (vernum > 1 && (! bfd_is_abs_section (sec)
+                                || ELF_ST_TYPE (isym->st_info) == STT_FUNC)))
            {
              const char *verstr;
              size_t namelen, verlen, newlen;
@@ -3856,13 +3879,12 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
        }
 
       /* Set the alignment of a common symbol.  */
-      if ((isym->st_shndx == SHN_COMMON
-          || bfd_is_com_section (sec))
+      if ((common || bfd_is_com_section (sec))
          && h->root.type == bfd_link_hash_common)
        {
          unsigned int align;
 
-         if (isym->st_shndx == SHN_COMMON)
+         if (common)
            align = bfd_log2 (isym->st_value);
          else
            {
@@ -3888,7 +3910,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
             definition or a common symbol is ignored due to the old
             normal definition. We need to make sure the maximum
             alignment is maintained.  */
-         if ((old_alignment || isym->st_shndx == SHN_COMMON)
+         if ((old_alignment || common)
              && h->root.type != bfd_link_hash_common)
            {
              unsigned int common_align;
@@ -4981,7 +5003,10 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
 
   /* Any syms created from now on start with -1 in
      got.refcount/offset and plt.refcount/offset.  */
-  elf_hash_table (info)->init_refcount = elf_hash_table (info)->init_offset;
+  elf_hash_table (info)->init_got_refcount
+    = elf_hash_table (info)->init_got_offset;
+  elf_hash_table (info)->init_plt_refcount
+    = elf_hash_table (info)->init_plt_offset;
 
   /* The backend may have to create some sections regardless of whether
      we're dynamic or not.  */
@@ -5279,12 +5304,8 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
 
   if (elf_hash_table (info)->dynamic_sections_created)
     {
-      bfd_size_type dynsymcount;
       unsigned long section_sym_count;
       asection *s;
-      size_t bucketcount = 0;
-      size_t hash_entry_size;
-      unsigned int dtagcount;
 
       /* Set up the version definition section.  */
       s = bfd_get_section_by_name (dynobj, ".gnu.version_d");
@@ -5299,7 +5320,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
        verdefs = verdefs->next;
 
       if (verdefs == NULL && !info->create_default_symver)
-       _bfd_strip_section_from_output (info, s);
+       s->flags |= SEC_EXCLUDE;
       else
        {
          unsigned int cdefs;
@@ -5376,7 +5397,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
            {
              bfd_size_type indx;
 
-             name = basename (output_bfd->filename);
+             name = lbasename (output_bfd->filename);
              def.vd_hash = bfd_elf_hash (name);
              indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
                                          name, FALSE);
@@ -5553,7 +5574,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
                                &sinfo);
 
        if (elf_tdata (output_bfd)->verref == NULL)
-         _bfd_strip_section_from_output (info, s);
+         s->flags |= SEC_EXCLUDE;
        else
          {
            Elf_Internal_Verneed *t;
@@ -5599,7 +5620,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
                indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
                                            elf_dt_name (t->vn_bfd) != NULL
                                            ? elf_dt_name (t->vn_bfd)
-                                           : basename (t->vn_bfd->filename),
+                                           : lbasename (t->vn_bfd->filename),
                                            FALSE);
                if (indx == (bfd_size_type) -1)
                  return FALSE;
@@ -5642,6 +5663,37 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
          }
       }
 
+      if ((elf_tdata (output_bfd)->cverrefs == 0
+          && elf_tdata (output_bfd)->cverdefs == 0)
+         || _bfd_elf_link_renumber_dynsyms (output_bfd, info,
+                                            &section_sym_count) == 0)
+       {
+         s = bfd_get_section_by_name (dynobj, ".gnu.version");
+         s->flags |= SEC_EXCLUDE;
+       }
+    }
+  return TRUE;
+}
+
+bfd_boolean
+bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
+{
+  if (!is_elf_hash_table (info->hash))
+    return TRUE;
+
+  if (elf_hash_table (info)->dynamic_sections_created)
+    {
+      bfd *dynobj;
+      const struct elf_backend_data *bed;
+      asection *s;
+      bfd_size_type dynsymcount;
+      unsigned long section_sym_count;
+      size_t bucketcount = 0;
+      size_t hash_entry_size;
+      unsigned int dtagcount;
+
+      dynobj = elf_hash_table (info)->dynobj;
+
       /* Assign dynsym indicies.  In a shared library we generate a
         section symbol for each output section, which come first.
         Next come all of the back-end allocated local dynamic syms,
@@ -5653,17 +5705,8 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
       /* Work out the size of the symbol version section.  */
       s = bfd_get_section_by_name (dynobj, ".gnu.version");
       BFD_ASSERT (s != NULL);
-      if (dynsymcount == 0
-         || (verdefs == NULL && elf_tdata (output_bfd)->verref == NULL
-             && !info->create_default_symver))
-       {
-         _bfd_strip_section_from_output (info, s);
-         /* The DYNSYMCOUNT might have changed if we were going to
-            output a dynamic symbol table entry for S.  */
-         dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info,
-                                                       &section_sym_count);
-       }
-      else
+      if (dynsymcount != 0
+         && (s->flags & SEC_EXCLUDE) == 0)
        {
          s->size = dynsymcount * sizeof (Elf_External_Versym);
          s->contents = bfd_zalloc (output_bfd, s->size);
@@ -5682,6 +5725,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
         section as we went along in elf_link_add_object_symbols.  */
       s = bfd_get_section_by_name (dynobj, ".dynsym");
       BFD_ASSERT (s != NULL);
+      bed = get_elf_backend_data (output_bfd);
       s->size = dynsymcount * bed->s->sizeof_sym;
 
       if (dynsymcount != 0)
@@ -5947,7 +5991,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
   count = reldyn->size / ext_size;
 
   size = 0;
-  for (lo = reldyn->link_order_head; lo != NULL; lo = lo->next)
+  for (lo = reldyn->map_head.link_order; lo != NULL; lo = lo->next)
     if (lo->type == bfd_indirect_link_order)
       {
        asection *o = lo->u.indirect.section;
@@ -5972,7 +6016,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
   else
     r_sym_mask = ~(bfd_vma) 0xffffffff;
 
-  for (lo = reldyn->link_order_head; lo != NULL; lo = lo->next)
+  for (lo = reldyn->map_head.link_order; lo != NULL; lo = lo->next)
     if (lo->type == bfd_indirect_link_order)
       {
        bfd_byte *erel, *erelend;
@@ -6022,7 +6066,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
 
   qsort (s_non_relative, count - ret, sort_elt, elf_link_sort_cmp2);
 
-  for (lo = reldyn->link_order_head; lo != NULL; lo = lo->next)
+  for (lo = reldyn->map_head.link_order; lo != NULL; lo = lo->next)
     if (lo->type == bfd_indirect_link_order)
       {
        bfd_byte *erel, *erelend;
@@ -6355,7 +6399,9 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
     {
       (*_bfd_error_handler)
        (_("%B: %s symbol `%s' in %B is referenced by DSO"),
-        finfo->output_bfd, h->root.u.def.section->owner,
+        finfo->output_bfd,
+        h->root.u.def.section == bfd_abs_section_ptr
+        ? finfo->output_bfd : h->root.u.def.section->owner,
         ELF_ST_VISIBILITY (h->other) == STV_INTERNAL
         ? "internal"
         : ELF_ST_VISIBILITY (h->other) == STV_HIDDEN
@@ -6469,7 +6515,7 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
 
     case bfd_link_hash_common:
       input_sec = h->root.u.c.p->section;
-      sym.st_shndx = SHN_COMMON;
+      sym.st_shndx = bed->common_section_index (input_sec);
       sym.st_value = 1 << h->root.u.c.p->alignment_power;
       break;
 
@@ -6644,12 +6690,6 @@ elf_section_ignore_discarded_relocs (asection *sec)
   return FALSE;
 }
 
-enum action_discarded
-  {
-    COMPLAIN = 1,
-    PRETEND = 2
-  };
-
 /* Return a mask saying how ld should treat relocations in SEC against
    symbols defined in discarded sections.  If this function returns
    COMPLAIN set, ld will issue a warning message.  If this function
@@ -6659,8 +6699,8 @@ enum action_discarded
    zero the reloc (at least that is the intent, but some cooperation by
    the target dependent code is needed, particularly for REL targets).  */
 
-static unsigned int
-elf_action_discarded (asection *sec)
+unsigned int
+_bfd_elf_default_action_discarded (asection *sec)
 {
   if (sec->flags & SEC_DEBUGGING)
     return PRETEND;
@@ -6671,12 +6711,6 @@ elf_action_discarded (asection *sec)
   if (strcmp (".gcc_except_table", sec->name) == 0)
     return 0;
 
-  if (strcmp (".PARISC.unwind", sec->name) == 0)
-    return 0;
-
-  if (strcmp (".fixup", sec->name) == 0)
-    return 0;
-
   return COMPLAIN | PRETEND;
 }
 
@@ -6700,6 +6734,26 @@ match_group_member (asection *sec, asection *group)
   return NULL;
 }
 
+/* Check if the kept section of a discarded section SEC can be used
+   to replace it. Return the replacement if it is OK. Otherwise return
+   NULL. */
+
+asection *
+_bfd_elf_check_kept_section (asection *sec)
+{
+  asection *kept;
+
+  kept = sec->kept_section;
+  if (kept != NULL)
+    {
+      if (elf_sec_group (sec) != NULL)
+       kept = match_group_member (sec, kept);
+      if (kept != NULL && sec->size != kept->size)
+       kept = NULL;
+    }
+  return kept;
+}
+
 /* Link an input file into the linker output file.  This function
    handles all the sections and relocations of the input file at once.
    This is so that we only have to read the local symbols once, and
@@ -6736,8 +6790,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
     return TRUE;
 
   emit_relocs = (finfo->info->relocatable
-                || finfo->info->emitrelocations
-                || bed->elf_backend_emit_relocs);
+                || finfo->info->emitrelocations);
 
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
   if (elf_bad_symtab (input_bfd))
@@ -6849,6 +6902,11 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
                  && (isec->flags & SEC_EXCLUDE) != 0)))
        continue;
 
+      /* If the section is not in the output BFD's section list, it is not
+        being output.  */
+      if (bfd_section_removed_from_list (output_bfd, isec->output_section))
+       continue;
+
       /* Get the name of the symbol.  */
       name = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link,
                                              isym->st_name);
@@ -6972,7 +7030,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
          if (!elf_section_ignore_discarded_relocs (o))
            {
              Elf_Internal_Rela *rel, *relend;
-             unsigned int action = elf_action_discarded (o);
+             unsigned int action = (*bed->action_discarded) (o);
 
              rel = internal_relocs;
              relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel;
@@ -6991,6 +7049,23 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
                          && finfo->sections[r_symndx] == NULL))
                    {
                      h = sym_hashes[r_symndx - extsymoff];
+
+                     /* Badly formatted input files can contain relocs that
+                        reference non-existant symbols.  Check here so that
+                        we do not seg fault.  */
+                     if (h == NULL)
+                       {
+                         char buffer [32];
+
+                         sprintf_vma (buffer, rel->r_info);
+                         (*_bfd_error_handler)
+                           (_("error: %B contains a reloc (0x%s) for section %A "
+                              "that references a non-existent global symbol"),
+                            input_bfd, o, buffer);
+                         bfd_set_error (bfd_error_bad_value);
+                         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;
@@ -7006,23 +7081,21 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
                    {
                      Elf_Internal_Sym *sym = isymbuf + r_symndx;
                      ps = &finfo->sections[r_symndx];
-                     sym_name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym);
+                     sym_name = bfd_elf_sym_name (input_bfd,
+                                                  symtab_hdr,
+                                                  sym, *ps);
                    }
 
                  /* Complain if the definition comes from a
                     discarded section.  */
                  if ((sec = *ps) != NULL && elf_discarded_section (sec))
                    {
-                     asection *kept;
-
                      BFD_ASSERT (r_symndx != 0);
                      if (action & COMPLAIN)
-                       {
-                         (*_bfd_error_handler)
-                           (_("`%s' referenced in section `%A' of %B: "
-                              "defined in discarded section `%A' of %B"),
-                            o, input_bfd, sec, sec->owner, sym_name);
-                       }
+                       (*finfo->info->callbacks->einfo)
+                         (_("%X`%s' referenced in section `%A' of %B: "
+                            "defined in discarded section `%A' of %B\n"),
+                          sym_name, o, input_bfd, sec, sec->owner);
 
                      /* Try to do the best we can to support buggy old
                         versions of gcc.  If we've warned, or this is
@@ -7035,13 +7108,12 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
                         is that we warn in non-debug sections, and
                         debug sections tend to come after other
                         sections.  */
-                     kept = sec->kept_section;
-                     if (kept != NULL && (action & PRETEND))
+                     if (action & PRETEND)
                        {
-                         if (elf_sec_group (sec) != NULL)
-                           kept = match_group_member (sec, kept);
-                         if (kept != NULL
-                             && sec->size == kept->size)
+                         asection *kept;
+
+                         kept = _bfd_elf_check_kept_section (sec);
+                         if (kept != NULL)
                            {
                              *ps = kept;
                              continue;
@@ -7094,10 +7166,9 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
              Elf_Internal_Rela *irelaend;
              bfd_vma last_offset;
              struct elf_link_hash_entry **rel_hash;
+             struct elf_link_hash_entry **rel_hash_list;
              Elf_Internal_Shdr *input_rel_hdr, *input_rel_hdr2;
              unsigned int next_erel;
-             bfd_boolean (*reloc_emitter)
-               (bfd *, asection *, Elf_Internal_Shdr *, Elf_Internal_Rela *);
              bfd_boolean rela_normal;
 
              input_rel_hdr = &elf_section_data (o)->rel_hdr;
@@ -7112,6 +7183,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
              rel_hash = (elf_section_data (o->output_section)->rel_hashes
                          + elf_section_data (o->output_section)->rel_count
                          + elf_section_data (o->output_section)->rel_count2);
+             rel_hash_list = rel_hash;
              last_offset = o->output_offset;
              if (!finfo->info->relocatable)
                last_offset += o->output_section->vma;
@@ -7294,16 +7366,11 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
                }
 
              /* Swap out the relocs.  */
-             if (bed->elf_backend_emit_relocs
-                 && !(finfo->info->relocatable
-                      || finfo->info->emitrelocations))
-               reloc_emitter = bed->elf_backend_emit_relocs;
-             else
-               reloc_emitter = _bfd_elf_link_output_relocs;
-
              if (input_rel_hdr->sh_size != 0
-                 && ! (*reloc_emitter) (output_bfd, o, input_rel_hdr,
-                                        internal_relocs))
+                 && !bed->elf_backend_emit_relocs (output_bfd, o,
+                                                   input_rel_hdr,
+                                                   internal_relocs,
+                                                   rel_hash_list))
                return FALSE;
 
              input_rel_hdr2 = elf_section_data (o)->rel_hdr2;
@@ -7311,8 +7378,11 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
                {
                  internal_relocs += (NUM_SHDR_ENTRIES (input_rel_hdr)
                                      * bed->s->int_rels_per_ext_rel);
-                 if (! (*reloc_emitter) (output_bfd, o, input_rel_hdr2,
-                                         internal_relocs))
+                 rel_hash_list += NUM_SHDR_ENTRIES (input_rel_hdr);
+                 if (!bed->elf_backend_emit_relocs (output_bfd, o,
+                                                    input_rel_hdr2,
+                                                    internal_relocs,
+                                                    rel_hash_list))
                    return FALSE;
                }
            }
@@ -7599,10 +7669,10 @@ elf_fixup_link_order (bfd *abfd, asection *o)
   struct bfd_link_order **sections;
   asection *s;
   bfd_vma offset;
-  
+
   seen_other = 0;
   seen_linkorder = 0;
-  for (p = o->link_order_head; p != NULL; p = p->next)
+  for (p = o->map_head.link_order; p != NULL; p = p->next)
     {
       if (p->type == bfd_indirect_link_order
          && (bfd_get_flavour ((sub = p->u.indirect.section->owner))
@@ -7631,12 +7701,12 @@ elf_fixup_link_order (bfd *abfd, asection *o)
       bfd_set_error (bfd_error_bad_value);
       return FALSE;
     }
-  
+
   sections = (struct bfd_link_order **)
     xmalloc (seen_linkorder * sizeof (struct bfd_link_order *));
   seen_linkorder = 0;
-  
-  for (p = o->link_order_head; p != NULL; p = p->next)
+
+  for (p = o->map_head.link_order; p != NULL; p = p->next)
     {
       sections[seen_linkorder++] = p;
     }
@@ -7750,7 +7820,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
       struct bfd_elf_section_data *esdo = elf_section_data (o);
       o->reloc_count = 0;
 
-      for (p = o->link_order_head; p != NULL; p = p->next)
+      for (p = o->map_head.link_order; p != NULL; p = p->next)
        {
          unsigned int reloc_count = 0;
          struct bfd_elf_section_data *esdi = NULL;
@@ -8090,7 +8160,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
            {
              struct bfd_link_order *o;
 
-             for (o = sec->link_order_head; o != NULL; o = o->next)
+             for (o = sec->map_head.link_order; o != NULL; o = o->next)
                if (size < o->offset + o->size)
                  size = o->offset + o->size;
            }
@@ -8132,7 +8202,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
     sub->output_has_begun = FALSE;
   for (o = abfd->sections; o != NULL; o = o->next)
     {
-      for (p = o->link_order_head; p != NULL; p = p->next)
+      for (p = o->map_head.link_order; p != NULL; p = p->next)
        {
          if (p->type == bfd_indirect_link_order
              && (bfd_get_flavour ((sub = p->u.indirect.section->owner))
@@ -8668,6 +8738,7 @@ _bfd_elf_gc_mark (struct bfd_link_info *info,
                  gc_mark_hook_fn gc_mark_hook)
 {
   bfd_boolean ret;
+  bfd_boolean is_eh;
   asection *group_sec;
 
   sec->gc_mark = 1;
@@ -8680,6 +8751,7 @@ _bfd_elf_gc_mark (struct bfd_link_info *info,
 
   /* Look through the section relocs.  */
   ret = TRUE;
+  is_eh = strcmp (sec->name, ".eh_frame") == 0;
   if ((sec->flags & SEC_RELOC) != 0 && sec->reloc_count > 0)
     {
       Elf_Internal_Rela *relstart, *rel, *relend;
@@ -8756,6 +8828,8 @@ _bfd_elf_gc_mark (struct bfd_link_info *info,
            {
              if (bfd_get_flavour (rsec->owner) != bfd_target_elf_flavour)
                rsec->gc_mark = 1;
+             else if (is_eh)
+               rsec->gc_mark_from_eh = 1;
              else if (!_bfd_elf_gc_mark (info, rsec, gc_mark_hook))
                {
                  ret = FALSE;
@@ -8837,7 +8911,9 @@ elf_gc_sweep (struct bfd_link_info *info, gc_sweep_hook_fn gc_sweep_hook)
          /* But we also have to update some of the relocation
             info we collected before.  */
          if (gc_sweep_hook
-             && (o->flags & SEC_RELOC) && o->reloc_count > 0)
+             && (o->flags & SEC_RELOC) != 0
+             && o->reloc_count > 0
+             && !bfd_is_abs_section (o->output_section))
            {
              Elf_Internal_Rela *internal_relocs;
              bfd_boolean r;
@@ -8867,6 +8943,12 @@ elf_gc_sweep (struct bfd_link_info *info, gc_sweep_hook_fn gc_sweep_hook)
 
     elf_link_hash_traverse (elf_hash_table (info), elf_gc_sweep_symbol, &i);
 
+    /* There is an unused NULL entry at the head of the table which
+       we must account for in our count.  Unless there weren't any
+       symbols, which means we'll have no table at all.  */
+    if (i != 0)
+      ++i;
+
     elf_hash_table (info)->dynsymcount = i;
   }
 
@@ -8984,45 +9066,30 @@ elf_gc_smash_unused_vtentry_relocs (struct elf_link_hash_entry *h, void *okp)
   return TRUE;
 }
 
-/* Mark sections containing dynamically referenced symbols.  This is called
-   through elf_link_hash_traverse.  */
+/* Mark sections containing dynamically referenced symbols.  When
+   building shared libraries, we must assume that any visible symbol is
+   referenced.  */
 
 static bfd_boolean
-elf_gc_mark_dynamic_ref_symbol (struct elf_link_hash_entry *h,
-                               void *okp ATTRIBUTE_UNUSED)
+elf_gc_mark_dynamic_ref_symbol (struct elf_link_hash_entry *h, void *inf)
 {
+  struct bfd_link_info *info = (struct bfd_link_info *) inf;
+
   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)
-      && h->ref_dynamic)
+      && (h->ref_dynamic
+         || (info->shared
+             && h->def_regular
+             && ELF_ST_VISIBILITY (h->other) != STV_INTERNAL
+             && ELF_ST_VISIBILITY (h->other) != STV_HIDDEN)))
     h->root.u.def.section->flags |= SEC_KEEP;
 
   return TRUE;
 }
-/* Mark sections containing global symbols.  This is called through
-   elf_link_hash_traverse.  */
-
-static bfd_boolean
-elf_mark_used_section (struct elf_link_hash_entry *h,
-                      void *data ATTRIBUTE_UNUSED)
-{
-  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)
-    {
-      asection *s = h->root.u.def.section;
-      if (s != NULL && s->output_section != NULL)
-       s->output_section->flags |= SEC_KEEP;
-    }
-
-  return TRUE;
-}
 /* Do mark and sweep of unused sections.  */
 
 bfd_boolean
@@ -9034,21 +9101,9 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
     (asection *, struct bfd_link_info *, Elf_Internal_Rela *,
      struct elf_link_hash_entry *h, Elf_Internal_Sym *);
 
-  if (!info->gc_sections)
-    {
-      /* If we are called when info->gc_sections is 0, we will mark
-        all sections containing global symbols for non-relocatable
-        link.  */
-      if (!info->relocatable)
-       elf_link_hash_traverse (elf_hash_table (info),
-                               elf_mark_used_section, NULL);
-      return TRUE;
-    }
-
   if (!get_elf_backend_data (abfd)->can_gc_sections
       || info->relocatable
       || info->emitrelocations
-      || info->shared
       || !is_elf_hash_table (info->hash))
     {
       (*_bfd_error_handler)(_("Warning: gc-sections option ignored"));
@@ -9073,9 +9128,7 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
   if (elf_hash_table (info)->dynamic_sections_created)
     elf_link_hash_traverse (elf_hash_table (info),
                            elf_gc_mark_dynamic_ref_symbol,
-                           &ok);
-  if (!ok)
-    return FALSE;
+                           info);
 
   /* Grovel through relocs to find out who stays ...  */
   gc_mark_hook = get_elf_backend_data (abfd)->gc_mark_hook;
@@ -9087,18 +9140,51 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
        continue;
 
       for (o = sub->sections; o != NULL; o = o->next)
-       {
-         if (o->flags & SEC_KEEP)
-           {
-             /* _bfd_elf_discard_section_eh_frame knows how to discard
-                orphaned FDEs so don't mark sections referenced by the
-                EH frame section.  */  
-             if (strcmp (o->name, ".eh_frame") == 0)
-               o->gc_mark = 1;
-             else if (!_bfd_elf_gc_mark (info, o, gc_mark_hook))
-               return FALSE;
-           }
-       }
+       if ((o->flags & SEC_KEEP) != 0 && !o->gc_mark)
+         if (!_bfd_elf_gc_mark (info, o, gc_mark_hook))
+           return FALSE;
+    }
+
+  /* ... again for sections marked from eh_frame.  */
+  for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+    {
+      asection *o;
+
+      if (bfd_get_flavour (sub) != bfd_target_elf_flavour)
+       continue;
+
+      /* Keep .gcc_except_table.* if the associated .text.* is
+        marked.  This isn't very nice, but the proper solution,
+        splitting .eh_frame up and using comdat doesn't pan out 
+        easily due to needing special relocs to handle the
+        difference of two symbols in separate sections.
+        Don't keep code sections referenced by .eh_frame.  */
+      for (o = sub->sections; o != NULL; o = o->next)
+       if (!o->gc_mark && o->gc_mark_from_eh && (o->flags & SEC_CODE) == 0)
+         {
+           if (strncmp (o->name, ".gcc_except_table.", 18) == 0)
+             {
+               unsigned long len;
+               char *fn_name;
+               asection *fn_text;
+
+               len = strlen (o->name + 18) + 1;
+               fn_name = bfd_malloc (len + 6);
+               if (fn_name == NULL)
+                 return FALSE;
+               memcpy (fn_name, ".text.", 6);
+               memcpy (fn_name + 6, o->name + 18, len);
+               fn_text = bfd_get_section_by_name (sub, fn_name);
+               free (fn_name);
+               if (fn_text == NULL || !fn_text->gc_mark)
+                 continue;
+             }
+
+           /* If not using specially named exception table section,
+              then keep whatever we are using.  */
+           if (!_bfd_elf_gc_mark (info, o, gc_mark_hook))
+             return FALSE;
+         }
     }
 
   /* ... and mark SEC_EXCLUDE for those that go.  */
@@ -9689,7 +9775,7 @@ _bfd_elf_section_already_linked (bfd *abfd, struct bfd_section * sec)
             which we are really going to use.  */
          sec->output_section = bfd_abs_section_ptr;
          sec->kept_section = l->sec;
-         
+
          if (flags & SEC_GROUP)
            {
              asection *first = elf_next_in_group (sec);
@@ -9755,23 +9841,69 @@ _bfd_elf_section_already_linked (bfd *abfd, struct bfd_section * sec)
   bfd_section_already_linked_table_insert (already_linked_list, sec);
 }
 
-/* Set NAME to VAL if the symbol exists and is undefined.  */
+static void
+bfd_elf_set_symbol (struct elf_link_hash_entry *h, bfd_vma val,
+                   struct bfd_section *s)
+{
+  h->root.type = bfd_link_hash_defined;
+  h->root.u.def.section = s ? s : bfd_abs_section_ptr;
+  h->root.u.def.value = val;
+  h->def_regular = 1;
+  h->type = STT_OBJECT;
+  h->other = STV_HIDDEN | (h->other & ~ ELF_ST_VISIBILITY (-1));
+  h->forced_local = 1;
+}
+
+/* Set NAME to VAL if the symbol exists and is not defined in a regular
+   object file.  If S is NULL it is an absolute symbol, otherwise it is
+   relative to that section.  */
 
 void
 _bfd_elf_provide_symbol (struct bfd_link_info *info, const char *name,
-                        bfd_vma val)
+                        bfd_vma val, struct bfd_section *s)
 {
   struct elf_link_hash_entry *h;
-  h = elf_link_hash_lookup (elf_hash_table (info), name, FALSE, FALSE,
-                           FALSE);
-  if (h != NULL && h->root.type == bfd_link_hash_undefined)
-    {
-      h->root.type = bfd_link_hash_defined;
-      h->root.u.def.section = bfd_abs_section_ptr;
-      h->root.u.def.value = val;
-      h->def_regular = 1;
-      h->type = STT_OBJECT;
-      h->other = STV_HIDDEN | (h->other & ~ ELF_ST_VISIBILITY (-1));
-      h->forced_local = 1;
-    }
+
+  bfd_elf_record_link_assignment (info, name, TRUE);
+
+  h = elf_link_hash_lookup (elf_hash_table (info), name, FALSE, FALSE, FALSE);
+  if (h != NULL
+      && !(h->root.type == bfd_link_hash_defined
+          && h->root.u.def.section != NULL
+          && h->root.u.def.section != h->root.u.def.section->output_section))
+    bfd_elf_set_symbol (h, val, s);
+}
+
+/* Set START and END to boundaries of SEC if they exist and are not
+   defined in regular object files.  */
+
+void
+_bfd_elf_provide_section_bound_symbols (struct bfd_link_info *info,
+                                       asection *sec,
+                                       const char *start,
+                                       const char *end)
+{
+  bfd_vma val = 0;
+  _bfd_elf_provide_symbol (info, start, val, sec);
+  if (sec != NULL)
+    val = sec->size;
+  _bfd_elf_provide_symbol (info, end, val, sec);
+}
+
+bfd_boolean
+_bfd_elf_common_definition (Elf_Internal_Sym *sym)
+{
+  return sym->st_shndx == SHN_COMMON;
+}
+
+unsigned int
+_bfd_elf_common_section_index (asection *sec ATTRIBUTE_UNUSED)
+{
+  return SHN_COMMON;
+}
+
+asection *
+_bfd_elf_common_section (asection *sec ATTRIBUTE_UNUSED)
+{
+  return bfd_com_section_ptr;
 }
This page took 0.039799 seconds and 4 git commands to generate.