* config/tc-mips.c (mips_set_options): Add ase_dsp for DSP instructions.
[deliverable/binutils-gdb.git] / bfd / elflink.c
index 7307c15a4f87461eaaf3bd70a63efa17ee023b30..4414f0df61b4a2ddbe4cbc7a60f076b6d1e0135a 100644 (file)
 #include "safe-ctype.h"
 #include "libiberty.h"
 
+/* Define a symbol in a dynamic linkage section.  */
+
+struct elf_link_hash_entry *
+_bfd_elf_define_linkage_sym (bfd *abfd,
+                            struct bfd_link_info *info,
+                            asection *sec,
+                            const char *name)
+{
+  struct elf_link_hash_entry *h;
+  struct bfd_link_hash_entry *bh;
+  const struct elf_backend_data *bed;
+
+  h = elf_link_hash_lookup (elf_hash_table (info), name, FALSE, FALSE, FALSE);
+  if (h != NULL)
+    {
+      /* Zap symbol defined in an as-needed lib that wasn't linked.
+        This is a symptom of a larger problem:  Absolute symbols
+        defined in shared libraries can't be overridden, because we
+        lose the link to the bfd which is via the symbol section.  */
+      h->root.type = bfd_link_hash_new;
+    }
+
+  bh = &h->root;
+  if (!_bfd_generic_link_add_one_symbol (info, abfd, name, BSF_GLOBAL,
+                                        sec, 0, NULL, FALSE,
+                                        get_elf_backend_data (abfd)->collect,
+                                        &bh))
+    return NULL;
+  h = (struct elf_link_hash_entry *) bh;
+  h->def_regular = 1;
+  h->type = STT_OBJECT;
+  h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN;
+
+  bed = get_elf_backend_data (abfd);
+  (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+  return h;
+}
+
 bfd_boolean
 _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;
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   int ptralign;
 
@@ -78,21 +115,10 @@ _bfd_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
         (or .got.plt) section.  We don't do this in the linker script
         because we don't want to define the symbol if we are not creating
         a global offset table.  */
-      bh = NULL;
-      if (!(_bfd_generic_link_add_one_symbol
-           (info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, s,
-            0, NULL, FALSE, bed->collect, &bh)))
-       return FALSE;
-      h = (struct elf_link_hash_entry *) bh;
-      h->def_regular = 1;
-      h->type = STT_OBJECT;
-      h->other = STV_HIDDEN;
-
-      if (! info->executable
-         && ! bfd_elf_link_record_dynamic_symbol (info, h))
-       return FALSE;
-
+      h = _bfd_elf_define_linkage_sym (abfd, info, s, "_GLOBAL_OFFSET_TABLE_");
       elf_hash_table (info)->hgot = h;
+      if (h == NULL)
+       return FALSE;
     }
 
   /* The first bit of the global offset table is the header.  */
@@ -132,8 +158,6 @@ _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;
   const struct elf_backend_data *bed;
 
   if (! is_elf_hash_table (info->hash))
@@ -212,27 +236,7 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
      section.  We don't want to define it if there is no .dynamic
      section, since on some ELF platforms the start up code examines it
      to decide how to initialize the process.  */
-  h = elf_link_hash_lookup (elf_hash_table (info), "_DYNAMIC",
-                           FALSE, FALSE, FALSE);
-  if (h != NULL)
-    {
-      /* Zap symbol defined in an as-needed lib that wasn't linked.
-        This is a symptom of a larger problem:  Absolute symbols
-        defined in shared libraries can't be overridden, because we
-        lose the link to the bfd which is via the symbol section.  */
-      h->root.type = bfd_link_hash_new;
-    }
-  bh = &h->root;
-  if (! (_bfd_generic_link_add_one_symbol
-        (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->def_regular = 1;
-  h->type = STT_OBJECT;
-
-  if (! info->executable
-      && ! bfd_elf_link_record_dynamic_symbol (info, h))
+  if (!_bfd_elf_define_linkage_sym (abfd, info, s, "_DYNAMIC"))
     return FALSE;
 
   s = bfd_make_section_with_flags (abfd, ".hash",
@@ -282,25 +286,12 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
       || ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
     return FALSE;
 
-  if (bed->want_plt_sym)
-    {
-      /* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the
-        .plt section.  */
-      struct elf_link_hash_entry *h;
-      struct bfd_link_hash_entry *bh = NULL;
-
-      if (! (_bfd_generic_link_add_one_symbol
-            (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->def_regular = 1;
-      h->type = STT_OBJECT;
-
-      if (! info->executable
-         && ! bfd_elf_link_record_dynamic_symbol (info, h))
-       return FALSE;
-    }
+  /* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the
+     .plt section.  */
+  if (bed->want_plt_sym
+      && !_bfd_elf_define_linkage_sym (abfd, info, s,
+                                      "_PROCEDURE_LINKAGE_TABLE_"))
+    return FALSE;
 
   s = bfd_make_section_with_flags (abfd,
                                   (bed->default_use_rela_p
@@ -744,7 +735,8 @@ _bfd_elf_link_renumber_dynsyms (bfd *output_bfd,
   if (dynsymcount != 0)
     ++dynsymcount;
 
-  return elf_hash_table (info)->dynsymcount = dynsymcount;
+  elf_hash_table (info)->dynsymcount = dynsymcount;
+  return dynsymcount;
 }
 
 /* This function is called when we want to define a new symbol.  It
@@ -780,6 +772,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;
@@ -1121,6 +1114,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.  */
@@ -1197,12 +1203,12 @@ _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 && !oldweak)
+  if (newdef && olddef && newweak)
     *skip = TRUE;
 
   /* If the old symbol is from a dynamic object, and the new symbol is
@@ -2641,6 +2647,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)
@@ -2656,7 +2664,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
@@ -3548,6 +3557,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;
 
@@ -3557,6 +3567,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)
@@ -3569,8 +3580,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)
@@ -3687,11 +3697,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;
@@ -3860,13 +3871,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
            {
@@ -3892,7 +3902,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;
@@ -5014,6 +5024,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
       asection *dynstr;
       struct bfd_elf_version_tree *t;
       struct bfd_elf_version_expr *d;
+      asection *s;
       bfd_boolean all_defined;
 
       *sinterpptr = bfd_get_section_by_name (dynobj, ".interp");
@@ -5217,7 +5228,8 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
            return FALSE;
        }
 
-      if (bfd_get_section_by_name (output_bfd, ".preinit_array") != NULL)
+      s = bfd_get_section_by_name (output_bfd, ".preinit_array");
+      if (s != NULL && s->linker_has_input)
        {
          /* DT_PREINIT_ARRAY is not allowed in shared library.  */
          if (! info->executable)
@@ -5245,13 +5257,15 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
              || !_bfd_elf_add_dynamic_entry (info, DT_PREINIT_ARRAYSZ, 0))
            return FALSE;
        }
-      if (bfd_get_section_by_name (output_bfd, ".init_array") != NULL)
+      s = bfd_get_section_by_name (output_bfd, ".init_array");
+      if (s != NULL && s->linker_has_input)
        {
          if (!_bfd_elf_add_dynamic_entry (info, DT_INIT_ARRAY, 0)
              || !_bfd_elf_add_dynamic_entry (info, DT_INIT_ARRAYSZ, 0))
            return FALSE;
        }
-      if (bfd_get_section_by_name (output_bfd, ".fini_array") != NULL)
+      s = bfd_get_section_by_name (output_bfd, ".fini_array");
+      if (s != NULL && s->linker_has_input)
        {
          if (!_bfd_elf_add_dynamic_entry (info, DT_FINI_ARRAY, 0)
              || !_bfd_elf_add_dynamic_entry (info, DT_FINI_ARRAYSZ, 0))
@@ -6497,7 +6511,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;
 
@@ -6672,12 +6686,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
@@ -6687,8 +6695,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;
@@ -6699,12 +6707,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;
 }
 
@@ -7024,7 +7026,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;
@@ -7088,7 +7090,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
                      if (action & COMPLAIN)
                        (*finfo->info->callbacks->einfo)
                          (_("%X`%s' referenced in section `%A' of %B: "
-                            "defined in discarded 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
@@ -8850,19 +8852,26 @@ _bfd_elf_gc_mark (struct bfd_link_info *info,
 
 /* Sweep symbols in swept sections.  Called via elf_link_hash_traverse.  */
 
+struct elf_gc_sweep_symbol_info {
+  struct bfd_link_info *info;
+  void (*hide_symbol) (struct bfd_link_info *, struct elf_link_hash_entry *,
+                      bfd_boolean);
+};
+
 static bfd_boolean
-elf_gc_sweep_symbol (struct elf_link_hash_entry *h, void *idxptr)
+elf_gc_sweep_symbol (struct elf_link_hash_entry *h, void *data)
 {
-  int *idx = idxptr;
-
   if (h->root.type == bfd_link_hash_warning)
     h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
-  if (h->dynindx != -1
-      && ((h->root.type != bfd_link_hash_defined
-          && h->root.type != bfd_link_hash_defweak)
-         || h->root.u.def.section->gc_mark))
-    h->dynindx = (*idx)++;
+  if ((h->root.type == bfd_link_hash_defined
+       || h->root.type == bfd_link_hash_defweak)
+      && !h->root.u.def.section->gc_mark
+      && !(h->root.u.def.section->owner->flags & DYNAMIC))
+    {
+      struct elf_gc_sweep_symbol_info *inf = data;
+      (*inf->hide_symbol) (inf->info, h, TRUE);
+    }
 
   return TRUE;
 }
@@ -8873,9 +8882,13 @@ typedef bfd_boolean (*gc_sweep_hook_fn)
   (bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *);
 
 static bfd_boolean
-elf_gc_sweep (struct bfd_link_info *info, gc_sweep_hook_fn gc_sweep_hook)
+elf_gc_sweep (bfd *abfd, struct bfd_link_info *info)
 {
   bfd *sub;
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  gc_sweep_hook_fn gc_sweep_hook = bed->gc_sweep_hook;
+  unsigned long section_sym_count;
+  struct elf_gc_sweep_symbol_info sweep_info;
 
   for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
     {
@@ -8894,41 +8907,6 @@ elf_gc_sweep (struct bfd_link_info *info, gc_sweep_hook_fn gc_sweep_hook)
          if (o->gc_mark)
            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.  */
-         if (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)
-                   o->gc_mark = 1;
-               }
-
-             /* If not using specially named exception table section,
-                then keep whatever we are using.  */
-             else
-               o->gc_mark = 1;
-
-             if (o->gc_mark)
-               continue;
-           }
-
          /* Skip sweeping sections already excluded.  */
          if (o->flags & SEC_EXCLUDE)
            continue;
@@ -8967,14 +8945,12 @@ elf_gc_sweep (struct bfd_link_info *info, gc_sweep_hook_fn gc_sweep_hook)
   /* Remove the symbols that were in the swept sections from the dynamic
      symbol table.  GCFIXME: Anyone know how to get them out of the
      static symbol table as well?  */
-  {
-    int i = 0;
-
-    elf_link_hash_traverse (elf_hash_table (info), elf_gc_sweep_symbol, &i);
-
-    elf_hash_table (info)->dynsymcount = i;
-  }
+  sweep_info.info = info;
+  sweep_info.hide_symbol = bed->elf_backend_hide_symbol;
+  elf_link_hash_traverse (elf_hash_table (info), elf_gc_sweep_symbol,
+                         &sweep_info);
 
+  _bfd_elf_link_renumber_dynsyms (abfd, info, &section_sym_count);
   return TRUE;
 }
 
@@ -9089,19 +9065,25 @@ 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;
@@ -9121,7 +9103,6 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
   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"));
@@ -9146,9 +9127,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;
@@ -9165,11 +9144,50 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
            return FALSE;
     }
 
-  /* ... and mark SEC_EXCLUDE for those that go.  */
-  if (!elf_gc_sweep (info, get_elf_backend_data (abfd)->gc_sweep_hook))
-    return FALSE;
+  /* ... again for sections marked from eh_frame.  */
+  for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+    {
+      asection *o;
 
-  return TRUE;
+      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.  */
+  return elf_gc_sweep (abfd, info);
 }
 \f
 /* Called from check_relocs to record the existence of a VTINHERIT reloc.  */
@@ -9819,83 +9837,20 @@ _bfd_elf_section_already_linked (bfd *abfd, struct bfd_section * sec)
   bfd_section_already_linked_table_insert (already_linked_list, sec);
 }
 
-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, struct bfd_section *s)
-{
-  struct elf_link_hash_entry *h;
-
-  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_boolean
+_bfd_elf_common_definition (Elf_Internal_Sym *sym)
 {
-  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);
+  return sym->st_shndx == SHN_COMMON;
 }
 
-/* Convert symbols in excluded output sections to absolute.  */
-
-static bfd_boolean
-fix_syms (struct bfd_link_hash_entry *h, void *data)
+unsigned int
+_bfd_elf_common_section_index (asection *sec ATTRIBUTE_UNUSED)
 {
-  bfd *obfd = (bfd *) data;
-
-  if (h->type == bfd_link_hash_warning)
-    h = h->u.i.link;
-
-  if (h->type == bfd_link_hash_defined
-      || h->type == bfd_link_hash_defweak)
-    {
-      asection *s = h->u.def.section;
-      if (s != NULL
-         && s == s->output_section
-         && bfd_section_removed_from_list (obfd, s))
-       {
-         h->u.def.value += s->vma;
-         h->u.def.section = bfd_abs_section_ptr;
-       }
-    }
-
-  return TRUE;
+  return SHN_COMMON;
 }
 
-void
-_bfd_elf_fix_excluded_sec_syms (bfd *obfd, struct bfd_link_info *info)
+asection *
+_bfd_elf_common_section (asection *sec ATTRIBUTE_UNUSED)
 {
-  bfd_link_hash_traverse (info->hash, fix_syms, obfd);
+  return bfd_com_section_ptr;
 }
This page took 0.032634 seconds and 4 git commands to generate.