Rotate gdb's ChangeLog file.
[deliverable/binutils-gdb.git] / bfd / elflink.c
index 7679b9a75557bd149acf50eb32819533782d305e..661b2eb19693e2432a0c9ebacdb0b118ca050afe 100644 (file)
@@ -187,6 +187,7 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
   flagword flags;
   asection *s;
   const struct elf_backend_data *bed;
+  struct elf_link_hash_entry *h;
 
   if (! is_elf_hash_table (info->hash))
     return FALSE;
@@ -254,7 +255,9 @@ _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.  */
-  if (!_bfd_elf_define_linkage_sym (abfd, info, s, "_DYNAMIC"))
+  h = _bfd_elf_define_linkage_sym (abfd, info, s, "_DYNAMIC");
+  elf_hash_table (info)->hdynamic = h;
+  if (h == NULL)
     return FALSE;
 
   if (info->emit_hash)
@@ -569,7 +572,7 @@ bfd_elf_record_link_assignment (bfd *output_bfd,
 
   h->def_regular = 1;
 
-  if (provide && hidden)
+  if (hidden)
     {
       bed = get_elf_backend_data (output_bfd);
       h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN;
@@ -938,6 +941,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
                       Elf_Internal_Sym *sym,
                       asection **psec,
                       bfd_vma *pvalue,
+                      bfd_boolean *pold_weak,
                       unsigned int *pold_alignment,
                       struct elf_link_hash_entry **sym_hash,
                       bfd_boolean *skip,
@@ -1040,6 +1044,8 @@ _bfd_elf_merge_symbol (bfd *abfd,
   newweak = bind == STB_WEAK;
   oldweak = (h->root.type == bfd_link_hash_defweak
             || h->root.type == bfd_link_hash_undefweak);
+  if (pold_weak)
+    *pold_weak = oldweak;
 
   /* In cases involving weak versioned symbols, we may wind up trying
      to merge a symbol with itself.  Catch that here, to avoid the
@@ -1210,23 +1216,25 @@ _bfd_elf_merge_symbol (bfd *abfd,
              vh->root.type = h->root.type;
              h->root.type = bfd_link_hash_indirect;
              (*bed->elf_backend_copy_indirect_symbol) (info, vh, h);
-             /* Protected symbols will override the dynamic definition
-                with default version.  */
-             if (ELF_ST_VISIBILITY (sym->st_other) == STV_PROTECTED)
+
+             h->root.u.i.link = (struct bfd_link_hash_entry *) vh;
+             if (ELF_ST_VISIBILITY (sym->st_other) != STV_PROTECTED)
                {
-                 h->root.u.i.link = (struct bfd_link_hash_entry *) vh;
-                 vh->dynamic_def = 1;
-                 vh->ref_dynamic = 1;
+                 /* If the new symbol is hidden or internal, completely undo
+                    any dynamic link state.  */
+                 (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+                 h->forced_local = 0;
+                 h->ref_dynamic = 0;
                }
              else
-               {
-                 h->root.type = vh->root.type;
-                 vh->ref_dynamic = 0;
-                 /* We have to hide it here since it was made dynamic
-                    global with extra bits when the symbol info was
-                    copied from the old dynamic definition.  */
-                 (*bed->elf_backend_hide_symbol) (info, vh, TRUE);
-               }
+               h->ref_dynamic = 1;
+
+             h->def_dynamic = 0;
+             h->dynamic_def = 0;
+             /* FIXME: Should we check type and size for protected symbol?  */
+             h->size = 0;
+             h->type = 0;
+
              h = vh;
            }
          else
@@ -1660,7 +1668,7 @@ _bfd_elf_add_default_symbol (bfd *abfd,
   size_change_ok = FALSE;
   sec = *psec;
   if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &sec, value,
-                             NULL, &hi, &skip, &override,
+                             NULL, NULL, &hi, &skip, &override,
                              &type_change_ok, &size_change_ok))
     return FALSE;
 
@@ -1769,7 +1777,7 @@ nondefault:
   size_change_ok = FALSE;
   sec = *psec;
   if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &sec, value,
-                             NULL, &hi, &skip, &override,
+                             NULL, NULL, &hi, &skip, &override,
                              &type_change_ok, &size_change_ok))
     return FALSE;
 
@@ -3145,7 +3153,7 @@ on_needed_list (const char *soname, struct bfd_link_needed_list *needed)
   return FALSE;
 }
 
-/* Sort symbol by value and section.  */
+/* Sort symbol by value, section, and size.  */
 static int
 elf_sort_symbol (const void *arg1, const void *arg2)
 {
@@ -3164,7 +3172,8 @@ elf_sort_symbol (const void *arg1, const void *arg2)
       if (sdiff != 0)
        return sdiff > 0 ? 1 : -1;
     }
-  return 0;
+  vdiff = h1->size - h2->size;
+  return vdiff == 0 ? 0 : vdiff > 0 ? 1 : -1;
 }
 
 /* This function is used to adjust offsets into .dynstr for
@@ -3862,6 +3871,8 @@ error_free_dyn:
       bfd_boolean size_change_ok;
       bfd_boolean type_change_ok;
       bfd_boolean new_weakdef;
+      bfd_boolean new_weak;
+      bfd_boolean old_weak;
       bfd_boolean override;
       bfd_boolean common;
       unsigned int old_alignment;
@@ -3994,6 +4005,7 @@ error_free_dyn:
 
       size_change_ok = FALSE;
       type_change_ok = bed->type_change_ok;
+      old_weak = FALSE;
       old_alignment = 0;
       old_bfd = NULL;
       new_sec = sec;
@@ -4139,7 +4151,7 @@ error_free_dyn:
            }
 
          if (!_bfd_elf_merge_symbol (abfd, info, name, isym, &sec,
-                                     &value, &old_alignment,
+                                     &value, &old_weak, &old_alignment,
                                      sym_hash, &skip, &override,
                                      &type_change_ok, &size_change_ok))
            goto error_free_vers;
@@ -4201,10 +4213,11 @@ error_free_dyn:
       if (is_elf_hash_table (htab))
        h->unique_global = (flags & BSF_GNU_UNIQUE) != 0;
 
+      new_weak = (flags & BSF_WEAK) != 0;
       new_weakdef = FALSE;
       if (dynamic
          && definition
-         && (flags & BSF_WEAK) != 0
+         && new_weak
          && !bed->is_function_type (ELF_ST_TYPE (isym->st_info))
          && is_elf_hash_table (htab)
          && h->u.weakdef == NULL)
@@ -4333,7 +4346,9 @@ error_free_dyn:
            h->size = h->root.u.c.size;
 
          if (ELF_ST_TYPE (isym->st_info) != STT_NOTYPE
-             && (definition || h->type == STT_NOTYPE))
+             && ((definition && !new_weak)
+                 || (old_weak && h->root.type == bfd_link_hash_common)
+                 || h->type == STT_NOTYPE))
            {
              unsigned int type = ELF_ST_TYPE (isym->st_info);
 
@@ -4726,7 +4741,6 @@ error_free_dyn:
          struct elf_link_hash_entry *hlook;
          asection *slook;
          bfd_vma vlook;
-         long ilook;
          size_t i, j, idx;
 
          hlook = weaks;
@@ -4740,14 +4754,13 @@ error_free_dyn:
          slook = hlook->root.u.def.section;
          vlook = hlook->root.u.def.value;
 
-         ilook = -1;
          i = 0;
          j = sym_count;
-         while (i < j)
+         while (i != j)
            {
              bfd_signed_vma vdiff;
              idx = (i + j) / 2;
-             h = sorted_sym_hash [idx];
+             h = sorted_sym_hash[idx];
              vdiff = vlook - h->root.u.def.value;
              if (vdiff < 0)
                j = idx;
@@ -4761,24 +4774,36 @@ error_free_dyn:
                  else if (sdiff > 0)
                    i = idx + 1;
                  else
-                   {
-                     ilook = idx;
-                     break;
-                   }
+                   break;
                }
            }
 
          /* We didn't find a value/section match.  */
-         if (ilook == -1)
+         if (i == j)
            continue;
 
-         for (i = ilook; i < sym_count; i++)
+         /* With multiple aliases, or when the weak symbol is already
+            strongly defined, we have multiple matching symbols and
+            the binary search above may land on any of them.  Step
+            one past the matching symbol(s).  */
+         while (++idx != j)
            {
-             h = sorted_sym_hash [i];
+             h = sorted_sym_hash[idx];
+             if (h->root.u.def.section != slook
+                 || h->root.u.def.value != vlook)
+               break;
+           }
+
+         /* Now look back over the aliases.  Since we sorted by size
+            as well as value and section, we'll choose the one with
+            the largest size.  */
+         while (idx-- != i)
+           {
+             h = sorted_sym_hash[idx];
 
              /* Stop if value or section doesn't match.  */
-             if (h->root.u.def.value != vlook
-                 || h->root.u.def.section != slook)
+             if (h->root.u.def.section != slook
+                 || h->root.u.def.value != vlook)
                break;
              else if (h != hlook)
                {
@@ -5542,6 +5567,65 @@ _bfd_elf_size_group_sections (struct bfd_link_info *info)
   return TRUE;
 }
 
+/* Set a default stack segment size.  The value in INFO wins.  If it
+   is unset, LEGACY_SYMBOL's value is used, and if that symbol is
+   undefined it is initialized.  */
+
+bfd_boolean
+bfd_elf_stack_segment_size (bfd *output_bfd,
+                           struct bfd_link_info *info,
+                           const char *legacy_symbol,
+                           bfd_vma default_size)
+{
+  struct elf_link_hash_entry *h = NULL;
+
+  /* Look for legacy symbol.  */
+  if (legacy_symbol)
+    h = elf_link_hash_lookup (elf_hash_table (info), legacy_symbol,
+                             FALSE, FALSE, FALSE);
+  if (h && (h->root.type == bfd_link_hash_defined
+           || h->root.type == bfd_link_hash_defweak)
+      && h->def_regular
+      && (h->type == STT_NOTYPE || h->type == STT_OBJECT))
+    {
+      /* The symbol has no type if specified on the command line.  */
+      h->type = STT_OBJECT;
+      if (info->stacksize)
+       (*_bfd_error_handler) (_("%B: stack size specified and %s set"),
+                              output_bfd, legacy_symbol);
+      else if (h->root.u.def.section != bfd_abs_section_ptr)
+       (*_bfd_error_handler) (_("%B: %s not absolute"),
+                              output_bfd, legacy_symbol);
+      else
+       info->stacksize = h->root.u.def.value;
+    }
+
+  if (!info->stacksize)
+    /* If the user didn't set a size, or explicitly inhibit the
+       size, set it now.  */
+    info->stacksize = default_size;
+
+  /* Provide the legacy symbol, if it is referenced.  */
+  if (h && (h->root.type == bfd_link_hash_undefined
+           || h->root.type == bfd_link_hash_undefweak))
+    {
+      struct bfd_link_hash_entry *bh = NULL;
+
+      if (!(_bfd_generic_link_add_one_symbol
+           (info, output_bfd, legacy_symbol,
+            BSF_GLOBAL, bfd_abs_section_ptr,
+            info->stacksize >= 0 ? info->stacksize : 0,
+            NULL, FALSE, get_elf_backend_data (output_bfd)->collect, &bh)))
+       return FALSE;
+
+      h = (struct elf_link_hash_entry *) bh;
+      h->def_regular = 1;
+      h->type = STT_OBJECT;
+    }
+
+  return TRUE;
+}
+
 /* Set up the sizes and contents of the ELF dynamic sections.  This is
    called by the ELF linker emulation before_allocation routine.  We
    must set the sizes of the sections before the linker sets the
@@ -5571,6 +5655,26 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
     return TRUE;
 
   bed = get_elf_backend_data (output_bfd);
+
+  /* Any syms created from now on start with -1 in
+     got.refcount/offset and plt.refcount/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;
+
+  if (info->relocatable
+      && !_bfd_elf_size_group_sections (info))
+    return FALSE;
+
+  /* The backend may have to create some sections regardless of whether
+     we're dynamic or not.  */
+  if (bed->elf_backend_always_size_sections
+      && ! (*bed->elf_backend_always_size_sections) (output_bfd, info))
+    return FALSE;
+
+  /* Determine any GNU_STACK segment requirements, after the backend
+     has had a chance to set a default segment size.  */
   if (info->execstack)
     elf_tdata (output_bfd)->stack_flags = PF_R | PF_W | PF_X;
   else if (info->noexecstack)
@@ -5600,32 +5704,13 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
          else if (bed->default_execstack)
            exec = PF_X;
        }
-      if (notesec)
-       {
-         elf_tdata (output_bfd)->stack_flags = PF_R | PF_W | exec;
-         if (exec && info->relocatable
-             && notesec->output_section != bfd_abs_section_ptr)
-           notesec->output_section->flags |= SEC_CODE;
-       }
+      if (notesec || info->stacksize > 0)
+       elf_tdata (output_bfd)->stack_flags = PF_R | PF_W | exec;
+      if (notesec && exec && info->relocatable
+         && notesec->output_section != bfd_abs_section_ptr)
+       notesec->output_section->flags |= SEC_CODE;
     }
 
-  /* Any syms created from now on start with -1 in
-     got.refcount/offset and plt.refcount/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;
-
-  if (info->relocatable
-      && !_bfd_elf_size_group_sections (info))
-    return FALSE;
-
-  /* The backend may have to create some sections regardless of whether
-     we're dynamic or not.  */
-  if (bed->elf_backend_always_size_sections
-      && ! (*bed->elf_backend_always_size_sections) (output_bfd, info))
-    return FALSE;
-
   dynobj = elf_hash_table (info)->dynobj;
 
   if (dynobj != NULL && elf_hash_table (info)->dynamic_sections_created)
@@ -12992,5 +13077,5 @@ elf_append_rel (bfd *abfd, asection *s, Elf_Internal_Rela *rel)
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   bfd_byte *loc = s->contents + (s->reloc_count++ * bed->s->sizeof_rel);
   BFD_ASSERT (loc + bed->s->sizeof_rel <= s->contents + s->size);
-  bed->s->swap_reloca_out (abfd, rel, loc);
+  bed->s->swap_reloc_out (abfd, rel, loc);
 }
This page took 0.028352 seconds and 4 git commands to generate.