PR ld/1021
[external/binutils.git] / bfd / elflink.c
index 8870857..d030b92 100644 (file)
@@ -433,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)
 {
@@ -3688,11 +3687,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;
@@ -9119,9 +9119,6 @@ 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
@@ -9836,8 +9833,9 @@ bfd_elf_set_symbol (struct elf_link_hash_entry *h, bfd_vma val,
   h->forced_local = 1;
 }
 
-/* Set NAME to VAL if the symbol exists and is undefined.  If val is NULL
-   it is an absolute symbol, otherwise it is relative to that section.  */
+/* 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,
@@ -9845,15 +9843,18 @@ _bfd_elf_provide_symbol (struct bfd_link_info *info, const char *name,
 {
   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_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
-   undefined.  */
+/* 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,
@@ -9861,49 +9862,41 @@ _bfd_elf_provide_section_bound_symbols (struct bfd_link_info *info,
                                        const char *start,
                                        const char *end)
 {
-  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;
-
+  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);
+}
+
+/* Convert symbols in excluded output sections to absolute.  */
+
+static bfd_boolean
+fix_syms (struct bfd_link_hash_entry *h, void *data)
+{
+  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)
     {
-      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;
+      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;
+       }
     }
 
-  if (do_start)
-    bfd_elf_set_symbol (hs, start_val, NULL);
+  return TRUE;
+}
 
-  if (do_end)
-    bfd_elf_set_symbol (he, end_val, NULL);
+void
+_bfd_elf_fix_excluded_sec_syms (bfd *obfd, struct bfd_link_info *info)
+{
+  bfd_link_hash_traverse (info->hash, fix_syms, obfd);
 }