daily update
[deliverable/binutils-gdb.git] / bfd / elflink.c
index e404d3b644f174d4a724e1fe9287bc599b9a21b2..1fcfce352d8989abc781b6dd48cd0dd40880cdfe 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
@@ -433,8 +424,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)
 {
@@ -745,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
@@ -781,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;
@@ -860,59 +852,32 @@ _bfd_elf_merge_symbol (bfd *abfd,
   /* NEWDYN and OLDDYN indicate whether the new or old symbol,
      respectively, is from a dynamic object.  */
 
-  if ((abfd->flags & DYNAMIC) != 0)
-    newdyn = TRUE;
-  else
-    newdyn = FALSE;
+  newdyn = (abfd->flags & DYNAMIC) != 0;
 
+  olddyn = FALSE;
   if (oldbfd != NULL)
     olddyn = (oldbfd->flags & DYNAMIC) != 0;
-  else
+  else if (oldsec != NULL)
     {
-      asection *hsec;
-
-      /* This code handles the special SHN_MIPS_{TEXT,DATA} section
+      /* This handles the special SHN_MIPS_{TEXT,DATA} section
         indices used by MIPS ELF.  */
-      switch (h->root.type)
-       {
-       default:
-         hsec = NULL;
-         break;
-
-       case bfd_link_hash_defined:
-       case bfd_link_hash_defweak:
-         hsec = h->root.u.def.section;
-         break;
-
-       case bfd_link_hash_common:
-         hsec = h->root.u.c.p->section;
-         break;
-       }
-
-      if (hsec == NULL)
-       olddyn = FALSE;
-      else
-       olddyn = (hsec->symbol->flags & BSF_DYNAMIC) != 0;
+      olddyn = (oldsec->symbol->flags & BSF_DYNAMIC) != 0;
     }
 
   /* NEWDEF and OLDDEF indicate whether the new or old symbol,
      respectively, appear to be a definition rather than reference.  */
 
-  if (bfd_is_und_section (sec) || bfd_is_com_section (sec))
-    newdef = FALSE;
-  else
-    newdef = TRUE;
+  newdef = !bfd_is_und_section (sec) && !bfd_is_com_section (sec);
 
-  if (h->root.type == bfd_link_hash_undefined
-      || h->root.type == bfd_link_hash_undefweak
-      || h->root.type == bfd_link_hash_common)
-    olddef = FALSE;
-  else
-    olddef = TRUE;
+  olddef = (h->root.type != bfd_link_hash_undefined
+           && h->root.type != bfd_link_hash_undefweak
+           && h->root.type != bfd_link_hash_common);
 
-  /* Check TLS symbol.  */
+  /* Check TLS symbol.  We don't check undefined symbol introduced by
+     "ld -u".  */
   if ((ELF_ST_TYPE (sym->st_info) == STT_TLS || h->type == STT_TLS)
-      && ELF_ST_TYPE (sym->st_info) != h->type)
+      && ELF_ST_TYPE (sym->st_info) != h->type
+      && oldbfd != NULL)
     {
       bfd *ntbfd, *tbfd;
       bfd_boolean ntdef, tdef;
@@ -1122,6 +1087,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.  */
@@ -1198,12 +1176,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
@@ -1305,7 +1283,7 @@ _bfd_elf_merge_symbol (bfd *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;
-      (*bed->elf_backend_copy_indirect_symbol) (bed, flip, h);
+      (*bed->elf_backend_copy_indirect_symbol) (info, flip, h);
       flip->root.u.undef.abfd = h->root.u.undef.abfd;
       if (h->def_dynamic)
        {
@@ -1459,7 +1437,7 @@ _bfd_elf_add_default_symbol (bfd *abfd,
       struct elf_link_hash_entry *ht;
 
       ht = (struct elf_link_hash_entry *) hi->root.u.i.link;
-      (*bed->elf_backend_copy_indirect_symbol) (bed, ht, hi);
+      (*bed->elf_backend_copy_indirect_symbol) (info, ht, hi);
 
       /* See if the new flags lead us to realize that the symbol must
         be dynamic.  */
@@ -1528,7 +1506,7 @@ nondefault:
 
       if (hi->root.type == bfd_link_hash_indirect)
        {
-         (*bed->elf_backend_copy_indirect_symbol) (bed, h, hi);
+         (*bed->elf_backend_copy_indirect_symbol) (info, h, hi);
 
          /* See if the new flags lead us to realize that the symbol
             must be dynamic.  */
@@ -2339,7 +2317,7 @@ _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h,
          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);
+         (*bed->elf_backend_copy_indirect_symbol) (eif->info, weakdef, h);
        }
     }
 
@@ -2642,6 +2620,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)
@@ -2657,7 +2637,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
@@ -3281,11 +3262,10 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
       int ret;
 
       /* ld --just-symbols and dynamic objects don't mix very well.
-        Test for --just-symbols by looking at info set up by
-        _bfd_elf_link_just_syms.  */
+        ld shouldn't allow it.  */
       if ((s = abfd->sections) != NULL
          && s->sec_info_type == ELF_INFO_TYPE_JUST_SYMS)
-       goto error_return;
+       abort ();
 
       /* If this dynamic lib was specified on the command line with
         --as-needed in effect, then we don't want to add a DT_NEEDED
@@ -3549,6 +3529,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;
 
@@ -3558,6 +3539,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)
@@ -3570,8 +3552,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)
@@ -3688,11 +3669,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;
@@ -3861,13 +3843,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
            {
@@ -3893,7 +3874,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;
@@ -4158,7 +4139,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
              (*bed->elf_backend_hide_symbol) (info, hi, TRUE);
              hi->root.type = bfd_link_hash_indirect;
              hi->root.u.i.link = (struct bfd_link_hash_entry *) h;
-             (*bed->elf_backend_copy_indirect_symbol) (bed, h, hi);
+             (*bed->elf_backend_copy_indirect_symbol) (info, h, hi);
              sym_hash = elf_sym_hashes (abfd);
              if (sym_hash)
                for (symidx = 0; symidx < extsymcount; ++symidx)
@@ -5015,6 +4996,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");
@@ -5218,7 +5200,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)
@@ -5246,13 +5229,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))
@@ -6498,7 +6483,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;
 
@@ -6673,12 +6658,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
@@ -6688,8 +6667,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;
@@ -6700,12 +6679,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;
 }
 
@@ -6854,8 +6827,10 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
        isec = bfd_com_section_ptr;
       else
        {
-         /* Who knows?  */
-         isec = NULL;
+         /* Don't attempt to output symbols with st_shnx in the
+            reserved range other than SHN_ABS and SHN_COMMON.  */
+         *ppsection = NULL;
+         continue;
        }
 
       *ppsection = isec;
@@ -6886,20 +6861,12 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
        continue;
 
       /* If this symbol is defined in a section which we are
-        discarding, we don't need to keep it, but note that
-        linker_mark is only reliable for sections that have contents.
-        For the benefit of the MIPS ELF linker, we check SEC_EXCLUDE
-        as well as linker_mark.  */
-      if ((isym->st_shndx < SHN_LORESERVE || isym->st_shndx > SHN_HIRESERVE)
+        discarding, we don't need to keep it.  */
+      if (isym->st_shndx != SHN_UNDEF
+         && (isym->st_shndx < SHN_LORESERVE || isym->st_shndx > SHN_HIRESERVE)
          && (isec == NULL
-             || (! isec->linker_mark && (isec->flags & SEC_HAS_CONTENTS) != 0)
-             || (! finfo->info->relocatable
-                 && (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))
+             || bfd_section_removed_from_list (output_bfd,
+                                               isec->output_section)))
        continue;
 
       /* Get the name of the symbol.  */
@@ -7025,7 +6992,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;
@@ -7089,7 +7056,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
@@ -7427,7 +7394,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
 }
 
 /* Generate a reloc when linking an ELF file.  This is a reloc
-   requested by the linker, and does come from any input file.  This
+   requested by the linker, and does not come from any input file.  This
    is used to build constructor and destructor tables when linking
    with -Ur.  */
 
@@ -7609,7 +7576,7 @@ elf_get_linked_section_vma (struct bfd_link_order *p)
   elfsec = elf_shdrp[elfsec]->sh_link;
   /* PR 290:
      The Intel C compiler generates SHT_IA_64_UNWIND with
-     SHF_LINK_ORDER.  But it doesn't set theh sh_link or
+     SHF_LINK_ORDER.  But it doesn't set the sh_link or
      sh_info fields.  Hence we could get the situation
      where elfsec is 0.  */
   if (elfsec == 0)
@@ -7662,41 +7629,54 @@ elf_fixup_link_order (bfd *abfd, asection *o)
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   int elfsec;
   struct bfd_link_order **sections;
-  asection *s;
+  asection *s, *other_sec, *linkorder_sec;
   bfd_vma offset;
 
+  other_sec = NULL;
+  linkorder_sec = NULL;
   seen_other = 0;
   seen_linkorder = 0;
   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))
-             == bfd_target_elf_flavour)
-         && elf_elfheader (sub)->e_ident[EI_CLASS] == bed->s->elfclass)
+      if (p->type == bfd_indirect_link_order)
        {
          s = p->u.indirect.section;
-         elfsec = _bfd_elf_section_from_bfd_section (sub, s);
-         if (elfsec != -1
+         sub = s->owner;
+         if (bfd_get_flavour (sub) == bfd_target_elf_flavour
+             && elf_elfheader (sub)->e_ident[EI_CLASS] == bed->s->elfclass
+             && (elfsec = _bfd_elf_section_from_bfd_section (sub, s)) != -1
              && elf_elfsections (sub)[elfsec]->sh_flags & SHF_LINK_ORDER)
-           seen_linkorder++;
+           {
+             seen_linkorder++;
+             linkorder_sec = s;
+           }
          else
-           seen_other++;
+           {
+             seen_other++;
+             other_sec = s;
+           }
        }
       else
        seen_other++;
+
+      if (seen_other && seen_linkorder)
+       {
+         if (other_sec && linkorder_sec)
+           (*_bfd_error_handler) (_("%A has both ordered [`%A' in %B] and unordered [`%A' in %B] sections"),
+                                  o, linkorder_sec,
+                                  linkorder_sec->owner, other_sec,
+                                  other_sec->owner);
+         else
+           (*_bfd_error_handler) (_("%A has both ordered and unordered sections"),
+                                  o);
+         bfd_set_error (bfd_error_bad_value);
+         return FALSE;
+       }
     }
 
   if (!seen_linkorder)
     return TRUE;
 
-  if (seen_other && seen_linkorder)
-    {
-      (*_bfd_error_handler) (_("%A has both ordered and unordered sections"),
-                            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;
@@ -8149,15 +8129,14 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
           sec && (sec->flags & SEC_THREAD_LOCAL);
           sec = sec->next)
        {
-         bfd_vma size = sec->size;
+         bfd_size_type size = sec->size;
 
-         if (size == 0 && (sec->flags & SEC_HAS_CONTENTS) == 0)
+         if (size == 0
+             && (sec->flags & SEC_HAS_CONTENTS) == 0)
            {
-             struct bfd_link_order *o;
-
-             for (o = sec->map_head.link_order; o != NULL; o = o->next)
-               if (size < o->offset + o->size)
-                 size = o->offset + o->size;
+             struct bfd_link_order *o = sec->map_tail.link_order;
+             if (o != NULL)
+               size = o->offset + o->size;
            }
          end = sec->vma + size;
        }
@@ -8733,6 +8712,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;
@@ -8745,6 +8725,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;
@@ -8821,6 +8802,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;
@@ -8847,19 +8830,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;
 }
@@ -8870,9 +8860,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)
     {
@@ -8902,7 +8896,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;
@@ -8927,14 +8923,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;
 }
 
@@ -9049,19 +9043,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;
@@ -9078,13 +9078,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)
-    return bfd_generic_gc_sections (abfd, 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"));
@@ -9109,9 +9105,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;
@@ -9123,25 +9117,55 @@ 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;
     }
 
-  /* ... 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.  */
@@ -9791,85 +9815,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)
+bfd_boolean
+_bfd_elf_common_definition (Elf_Internal_Sym *sym)
 {
-  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;
+  return sym->st_shndx == SHN_COMMON;
 }
 
-/* Set NAME to VAL if the symbol exists and is undefined.  */
-
-void
-_bfd_elf_provide_symbol (struct bfd_link_info *info, const char *name,
-                        bfd_vma val)
+unsigned int
+_bfd_elf_common_section_index (asection *sec ATTRIBUTE_UNUSED)
 {
-  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_undefweak))
-    bfd_elf_set_symbol (h, val);
+  return SHN_COMMON;
 }
 
-/* Set START and END to boundaries of SEC if they exist and are
-   undefined.  */
-
-void
-_bfd_elf_provide_section_bound_symbols (struct bfd_link_info *info,
-                                       asection *sec,
-                                       const char *start,
-                                       const char *end)
+asection *
+_bfd_elf_common_section (asection *sec ATTRIBUTE_UNUSED)
 {
-  struct elf_link_hash_entry *hs, *he;
-  bfd_vma start_val, end_val;
-  bfd_boolean do_start, do_end;
-
-  /* Check if we need them or not first.  */
-  hs = elf_link_hash_lookup (elf_hash_table (info), start, FALSE,
-                            FALSE, FALSE);
-  do_start = (hs != NULL
-             && (hs->root.type == bfd_link_hash_undefined
-                 || hs->root.type == bfd_link_hash_undefweak));
-
-  he = elf_link_hash_lookup (elf_hash_table (info), end, FALSE,
-                            FALSE, FALSE);
-  do_end = (he != NULL
-           && (he->root.type == bfd_link_hash_undefined
-               || he->root.type == bfd_link_hash_undefweak));
-
-  if (!do_start && !do_end)
-    return;
-
-  if (sec != NULL)
-    {
-      start_val = sec->vma;
-      end_val = start_val + sec->size;
-    }
-  else
-    {
-      /* We have to choose those values very carefully.  Some targets,
-        like alpha, may have relocation overflow with 0. "__bss_start"
-        should be defined in all cases.  */
-      struct elf_link_hash_entry *h
-       = elf_link_hash_lookup (elf_hash_table (info), "__bss_start",
-                               FALSE, FALSE, FALSE);
-      if (h != NULL && h->root.type == bfd_link_hash_defined)
-       start_val = h->root.u.def.value;
-      else
-       start_val = 0;
-      end_val = start_val;
-    }
-
-  if (do_start)
-    bfd_elf_set_symbol (hs, start_val);
-
-  if (do_end)
-    bfd_elf_set_symbol (he, end_val);
+  return bfd_com_section_ptr;
 }
This page took 0.040258 seconds and 4 git commands to generate.