bfd/
[deliverable/binutils-gdb.git] / bfd / elflink.c
index d7c9ded0b18412dfd401b7bc2dea3d5577f742d1..cd9131ef3805d301d0afc7c0e954fe502e26e3eb 100644 (file)
@@ -386,7 +386,8 @@ bfd_elf_link_record_dynamic_symbol (struct bfd_link_info *info,
              && h->root.type != bfd_link_hash_undefweak)
            {
              h->forced_local = 1;
-             return TRUE;
+             if (!elf_hash_table (info)->is_relocatable_executable)
+               return TRUE;
            }
 
        default:
@@ -484,9 +485,18 @@ bfd_elf_record_link_assignment (bfd *output_bfd ATTRIBUTE_UNUSED,
 
   h->def_regular = 1;
 
+  /* STV_HIDDEN and STV_INTERNAL symbols must be STB_LOCAL in shared objects
+     and executables.  */
+  if (!info->relocatable
+      && h->dynindx != -1
+      && (ELF_ST_VISIBILITY (h->other) == STV_HIDDEN
+         || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL))
+    h->forced_local = 1;
+
   if ((h->def_dynamic
        || h->ref_dynamic
-       || info->shared)
+       || info->shared
+       || (info->executable && elf_hash_table (info)->is_relocatable_executable))
       && h->dynindx == -1)
     {
       if (! bfd_elf_link_record_dynamic_symbol (info, h))
@@ -624,6 +634,31 @@ elf_link_renumber_hash_table_dynsyms (struct elf_link_hash_entry *h,
   if (h->root.type == bfd_link_hash_warning)
     h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
+  if (h->forced_local)
+    return TRUE;
+
+  if (h->dynindx != -1)
+    h->dynindx = ++(*count);
+
+  return TRUE;
+}
+
+
+/* Like elf_link_renumber_hash_table_dynsyms, but just number symbols with
+   STB_LOCAL binding.  */
+
+static bfd_boolean
+elf_link_renumber_local_hash_table_dynsyms (struct elf_link_hash_entry *h,
+                                           void *data)
+{
+  size_t *count = data;
+
+  if (h->root.type == bfd_link_hash_warning)
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+  if (!h->forced_local)
+    return TRUE;
+
   if (h->dynindx != -1)
     h->dynindx = ++(*count);
 
@@ -667,16 +702,19 @@ _bfd_elf_link_omit_section_dynsym (bfd *output_bfd ATTRIBUTE_UNUSED,
 }
 
 /* Assign dynsym indices.  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, followed by the rest of
-   the global symbols.  */
+   symbol for each output section, which come first.  Next come symbols
+   which have been forced to local binding.  Then all of the back-end
+   allocated local dynamic syms, followed by the rest of the global
+   symbols.  */
 
-unsigned long
-_bfd_elf_link_renumber_dynsyms (bfd *output_bfd, struct bfd_link_info *info)
+static unsigned long
+_bfd_elf_link_renumber_dynsyms (bfd *output_bfd,
+                               struct bfd_link_info *info,
+                               unsigned long *section_sym_count)
 {
   unsigned long dynsymcount = 0;
 
-  if (info->shared)
+  if (info->shared || elf_hash_table (info)->is_relocatable_executable)
     {
       const struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
       asection *p;
@@ -686,6 +724,11 @@ _bfd_elf_link_renumber_dynsyms (bfd *output_bfd, struct bfd_link_info *info)
            && !(*bed->elf_backend_omit_section_dynsym) (output_bfd, info, p))
          elf_section_data (p)->dynindx = ++dynsymcount;
     }
+  *section_sym_count = dynsymcount;
+
+  elf_link_hash_traverse (elf_hash_table (info),
+                         elf_link_renumber_local_hash_table_dynsyms,
+                         &dynsymcount);
 
   if (elf_hash_table (info)->dynlocal)
     {
@@ -716,7 +759,8 @@ _bfd_elf_link_renumber_dynsyms (bfd *output_bfd, struct bfd_link_info *info)
    TYPE_CHANGE_OK if it is OK for the type to change.  We set
    SIZE_CHANGE_OK if it is OK for the size to change.  By OK to
    change, we mean that we shouldn't warn if the type or size does
-   change.  */
+   change.  We set POLD_ALIGNMENT if an old common symbol in a dynamic
+   object is overridden by a regular object.  */
 
 bfd_boolean
 _bfd_elf_merge_symbol (bfd *abfd,
@@ -725,6 +769,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
                       Elf_Internal_Sym *sym,
                       asection **psec,
                       bfd_vma *pvalue,
+                      unsigned int *pold_alignment,
                       struct elf_link_hash_entry **sym_hash,
                       bfd_boolean *skip,
                       bfd_boolean *override,
@@ -1229,9 +1274,10 @@ _bfd_elf_merge_symbol (bfd *abfd,
       if (h->size > *pvalue)
        *pvalue = h->size;
 
-      /* FIXME: We no longer know the alignment required by the symbol
-        in the dynamic object, so we just wind up using the one from
-        the regular object.  */
+      /* We need to remember the alignment required by the symbol
+        in the dynamic object.  */
+      BFD_ASSERT (pold_alignment);
+      *pold_alignment = h->root.u.def.section->alignment_power;
 
       olddef = FALSE;
       olddyncommon = FALSE;
@@ -1343,8 +1389,8 @@ _bfd_elf_add_default_symbol (bfd *abfd,
   size_change_ok = FALSE;
   sec = *psec;
   if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &sec, value,
-                             &hi, &skip, &override, &type_change_ok,
-                             &size_change_ok))
+                             NULL, &hi, &skip, &override,
+                             &type_change_ok, &size_change_ok))
     return FALSE;
 
   if (skip)
@@ -1447,8 +1493,8 @@ nondefault:
   size_change_ok = FALSE;
   sec = *psec;
   if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &sec, value,
-                             &hi, &skip, &override, &type_change_ok,
-                             &size_change_ok))
+                             NULL, &hi, &skip, &override,
+                             &type_change_ok, &size_change_ok))
     return FALSE;
 
   if (skip)
@@ -2889,8 +2935,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,
@@ -3194,6 +3243,10 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
                  /* Clobber the section size so that the warning does
                     not get copied into the output file.  */
                  s->size = 0;
+
+                 /* Also set SEC_EXCLUDE, so that symbols defined in
+                    the warning section don't get copied to the output.  */
+                 s->flags |= SEC_EXCLUDE;
                }
            }
        }
@@ -3485,7 +3538,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
     {
       int bind;
       bfd_vma value;
-      asection *sec;
+      asection *sec, *new_sec;
       flagword flags;
       const char *name;
       struct elf_link_hash_entry *h;
@@ -3535,9 +3588,12 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
            sec = bfd_abs_section_ptr;
          else if (sec->kept_section)
            {
-             /* Symbols from discarded section are undefined.  */
+             /* Symbols from discarded section are undefined, and have
+                default visibility.  */
              sec = bfd_und_section_ptr;
              isym->st_shndx = SHN_UNDEF;
+             isym->st_other = STV_DEFAULT
+                              | (isym->st_other & ~ ELF_ST_VISIBILITY(-1));
            }
          else if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
            value -= sec->vma;
@@ -3607,6 +3663,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
       type_change_ok = get_elf_backend_data (abfd)->type_change_ok;
       old_alignment = 0;
       old_bfd = NULL;
+      new_sec = sec;
 
       if (is_elf_hash_table (hash_table))
        {
@@ -3719,7 +3776,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
              name = newname;
            }
 
-         if (!_bfd_elf_merge_symbol (abfd, info, name, isym, &sec, &value,
+         if (!_bfd_elf_merge_symbol (abfd, info, name, isym, &sec,
+                                     &value, &old_alignment,
                                      sym_hash, &skip, &override,
                                      &type_change_ok, &size_change_ok))
            goto error_free_vers;
@@ -3801,12 +3859,20 @@ 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
+      if ((isym->st_shndx == SHN_COMMON
+          || bfd_is_com_section (sec))
          && h->root.type == bfd_link_hash_common)
        {
          unsigned int align;
 
-         align = bfd_log2 (isym->st_value);
+         if (isym->st_shndx == SHN_COMMON)
+           align = bfd_log2 (isym->st_value);
+         else
+           {
+             /* The new symbol is a common symbol in a shared object.
+                We need to get the alignment from the section.  */
+             align = new_sec->alignment_power;
+           }
          if (align > old_alignment
              /* Permit an alignment power of zero if an alignment of one
                 is specified and no other alignments have been specified.  */
@@ -4895,7 +4961,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
        {
          asection *s;
 
-         if (inputobj->flags & DYNAMIC)
+         if (inputobj->flags & (DYNAMIC | BFD_LINKER_CREATED))
            continue;
          s = bfd_get_section_by_name (inputobj, ".note.GNU-stack");
          if (s)
@@ -5217,6 +5283,7 @@ 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;
@@ -5583,7 +5650,8 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
         Next come all of the back-end allocated local dynamic syms,
         followed by the rest of the global symbols.  */
 
-      dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info);
+      dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info,
+                                                   &section_sym_count);
 
       /* Work out the size of the symbol version section.  */
       s = bfd_get_section_by_name (dynobj, ".gnu.version");
@@ -5595,7 +5663,8 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
          _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);
+         dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info,
+                                                       &section_sym_count);
        }
       else
        {
@@ -5617,22 +5686,17 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
       s = bfd_get_section_by_name (dynobj, ".dynsym");
       BFD_ASSERT (s != NULL);
       s->size = dynsymcount * bed->s->sizeof_sym;
-      s->contents = bfd_alloc (output_bfd, s->size);
-      if (s->contents == NULL && s->size != 0)
-       return FALSE;
 
       if (dynsymcount != 0)
        {
-         Elf_Internal_Sym isym;
+         s->contents = bfd_alloc (output_bfd, s->size);
+         if (s->contents == NULL)
+           return FALSE;
 
-         /* The first entry in .dynsym is a dummy symbol.  */
-         isym.st_value = 0;
-         isym.st_size = 0;
-         isym.st_name = 0;
-         isym.st_info = 0;
-         isym.st_other = 0;
-         isym.st_shndx = 0;
-         bed->s->swap_symbol_out (output_bfd, &isym, s->contents, 0);
+         /* The first entry in .dynsym is a dummy symbol.
+            Clear all the section syms, in case we don't output them all.  */
+         ++section_sym_count;
+         memset (s->contents, 0, section_sym_count * bed->s->sizeof_sym);
        }
 
       /* Compute the size of the hashing table.  As a side effect this
@@ -6639,6 +6703,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
@@ -6782,12 +6866,17 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
         For the benefit of the MIPS ELF linker, we check SEC_EXCLUDE
         as well as linker_mark.  */
       if ((isym->st_shndx < SHN_LORESERVE || isym->st_shndx > SHN_HIRESERVE)
-         && isec != NULL
-         && ((! isec->linker_mark && (isec->flags & SEC_HAS_CONTENTS) != 0)
+         && (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))
+       continue;
+
       /* Get the name of the symbol.  */
       name = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link,
                                              isym->st_name);
@@ -6952,15 +7041,15 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
                     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\n"),
+                              "defined in discarded section `%A' of %B"),
                             o, input_bfd, sec, sec->owner, sym_name);
+                         bfd_set_error (bfd_error_bad_value);
+                         return FALSE;
                        }
 
                      /* Try to do the best we can to support buggy old
@@ -6974,13 +7063,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;
@@ -8129,7 +8217,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
       long last_local = 0;
 
       /* Write out the section symbols for the output sections.  */
-      if (info->shared)
+      if (info->shared || elf_hash_table (info)->is_relocatable_executable)
        {
          asection *s;
 
@@ -8940,7 +9028,28 @@ elf_gc_mark_dynamic_ref_symbol (struct elf_link_hash_entry *h,
 
   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
@@ -8952,6 +9061,17 @@ 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
@@ -9547,21 +9667,21 @@ _bfd_elf_section_already_linked (bfd *abfd, struct bfd_section * sec)
 
            case SEC_LINK_DUPLICATES_ONE_ONLY:
              (*_bfd_error_handler)
-               (_("%B: ignoring duplicate section `%A'\n"),
+               (_("%B: ignoring duplicate section `%A'"),
                 abfd, sec);
              break;
 
            case SEC_LINK_DUPLICATES_SAME_SIZE:
              if (sec->size != l->sec->size)
                (*_bfd_error_handler)
-                 (_("%B: duplicate section `%A' has different size\n"),
+                 (_("%B: duplicate section `%A' has different size"),
                   abfd, sec);
              break;
 
            case SEC_LINK_DUPLICATES_SAME_CONTENTS:
              if (sec->size != l->sec->size)
                (*_bfd_error_handler)
-                 (_("%B: duplicate section `%A' has different size\n"),
+                 (_("%B: duplicate section `%A' has different size"),
                   abfd, sec);
              else if (sec->size != 0)
                {
@@ -9569,16 +9689,16 @@ _bfd_elf_section_already_linked (bfd *abfd, struct bfd_section * sec)
 
                  if (!bfd_malloc_and_get_section (abfd, sec, &sec_contents))
                    (*_bfd_error_handler)
-                     (_("%B: warning: could not read contents of section `%A'\n"),
+                     (_("%B: warning: could not read contents of section `%A'"),
                       abfd, sec);
                  else if (!bfd_malloc_and_get_section (l->sec->owner, l->sec,
                                                        &l_sec_contents))
                    (*_bfd_error_handler)
-                     (_("%B: warning: could not read contents of section `%A'\n"),
+                     (_("%B: warning: could not read contents of section `%A'"),
                       l->sec->owner, l->sec);
                  else if (memcmp (sec_contents, l_sec_contents, sec->size) != 0)
                    (*_bfd_error_handler)
-                     (_("%B: warning: duplicate section `%A' has different contents\n"),
+                     (_("%B: warning: duplicate section `%A' has different contents"),
                       abfd, sec);
 
                  if (sec_contents)
@@ -9661,3 +9781,24 @@ _bfd_elf_section_already_linked (bfd *abfd, struct bfd_section * sec)
   /* This is the first section with this name.  Record it.  */
   bfd_section_already_linked_table_insert (already_linked_list, sec);
 }
+
+/* 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)
+{
+  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;
+    }
+}
This page took 0.032959 seconds and 4 git commands to generate.