Don't resolve size relocation against non-zero TLS symbol
[deliverable/binutils-gdb.git] / bfd / elflink.c
index 6d80109c47bbadf97ddc61c5816e51aa045571ae..d336730e07897a247e272c604f1aa041572158c2 100644 (file)
@@ -895,33 +895,6 @@ elf_merge_st_other (bfd *abfd, struct elf_link_hash_entry *h,
     }
 }
 
-/* Mark if a symbol has a definition in a dynamic object or is
-   weak in all dynamic objects.  */
-
-static void
-_bfd_elf_mark_dynamic_def_weak (struct elf_link_hash_entry *h,
-                               asection *sec, int bind)
-{
-  if (!h->dynamic_def)
-    {
-      if (!bfd_is_und_section (sec))
-       h->dynamic_def = 1;
-      else
-       {
-         /* Check if this symbol is weak in all dynamic objects. If it
-            is the first time we see it in a dynamic object, we mark
-            if it is weak. Otherwise, we clear it.  */
-         if (!h->ref_dynamic)
-           {
-             if (bind == STB_WEAK)
-               h->dynamic_weak = 1;
-           }
-         else if (bind != STB_WEAK)
-           h->dynamic_weak = 0;
-       }
-    }
-}
-
 /* This function is called when we want to define a new symbol.  It
    handles the various cases which arise when we find a definition in
    a dynamic object, or when there is already a definition in a
@@ -998,10 +971,39 @@ _bfd_elf_merge_symbol (bfd *abfd,
     h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
   /* We have to check it for every instance since the first few may be
-     refereences and not all compilers emit symbol type for undefined
+     references and not all compilers emit symbol type for undefined
      symbols.  */
   bfd_elf_link_mark_dynamic_symbol (info, h, sym);
 
+  /* NEWDYN and OLDDYN indicate whether the new or old symbol,
+     respectively, is from a dynamic object.  */
+
+  newdyn = (abfd->flags & DYNAMIC) != 0;
+
+  /* ref_dynamic_nonweak and dynamic_def flags track actual undefined
+     syms and defined syms in dynamic libraries respectively.
+     ref_dynamic on the other hand can be set for a symbol defined in
+     a dynamic library, and def_dynamic may not be set;  When the
+     definition in a dynamic lib is overridden by a definition in the
+     executable use of the symbol in the dynamic lib becomes a
+     reference to the executable symbol.  */
+  if (newdyn)
+    {
+      if (bfd_is_und_section (sec))
+       {
+         if (bind != STB_WEAK)
+           {
+             h->ref_dynamic_nonweak = 1;
+             hi->ref_dynamic_nonweak = 1;
+           }
+       }
+      else
+       {
+         h->dynamic_def = 1;
+         hi->dynamic_def = 1;
+       }
+    }
+
   /* If we just created the symbol, mark it as being an ELF symbol.
      Other than that, there is nothing to do--there is no merge issue
      with a newly defined symbol--so we just return.  */
@@ -1059,11 +1061,6 @@ _bfd_elf_merge_symbol (bfd *abfd,
          || !h->def_regular))
     return TRUE;
 
-  /* NEWDYN and OLDDYN indicate whether the new or old symbol,
-     respectively, is from a dynamic object.  */
-
-  newdyn = (abfd->flags & DYNAMIC) != 0;
-
   olddyn = FALSE;
   if (oldbfd != NULL)
     olddyn = (oldbfd->flags & DYNAMIC) != 0;
@@ -1167,16 +1164,6 @@ _bfd_elf_merge_symbol (bfd *abfd,
       return FALSE;
     }
 
-  /* We need to remember if a symbol has a definition in a dynamic
-     object or is weak in all dynamic objects. Internal and hidden
-     visibility will make it unavailable to dynamic objects.  */
-  if (newdyn)
-    {
-      _bfd_elf_mark_dynamic_def_weak (h, sec, bind);
-      if (h != hi)
-       _bfd_elf_mark_dynamic_def_weak (hi, sec, bind);
-    }
-
   /* If the old symbol has non-default visibility, we ignore the new
      definition from a dynamic object.  */
   if (newdyn
@@ -1230,7 +1217,6 @@ _bfd_elf_merge_symbol (bfd *abfd,
                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;
@@ -1270,7 +1256,6 @@ _bfd_elf_merge_symbol (bfd *abfd,
       else
        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;
@@ -3091,19 +3076,17 @@ elf_add_dt_needed_tag (bfd *abfd,
                       bfd_boolean do_it)
 {
   struct elf_link_hash_table *hash_table;
-  bfd_size_type oldsize;
   bfd_size_type strindex;
 
   if (!_bfd_elf_link_create_dynstrtab (abfd, info))
     return -1;
 
   hash_table = elf_hash_table (info);
-  oldsize = _bfd_elf_strtab_size (hash_table->dynstr);
   strindex = _bfd_elf_strtab_add (hash_table->dynstr, soname, FALSE);
   if (strindex == (bfd_size_type) -1)
     return -1;
 
-  if (oldsize == _bfd_elf_strtab_size (hash_table->dynstr))
+  if (_bfd_elf_strtab_refcount (hash_table->dynstr, strindex) != 1)
     {
       asection *sdyn;
       const struct elf_backend_data *bed;
@@ -3385,6 +3368,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
   struct bfd_link_hash_entry *old_undefs = NULL;
   struct bfd_link_hash_entry *old_undefs_tail = NULL;
   long old_dynsymcount = 0;
+  bfd_size_type old_dynstr_size = 0;
   size_t tabsize = 0;
   size_t hashsize = 0;
 
@@ -3712,7 +3696,7 @@ error_free_dyn:
        return TRUE;
 
       /* Save the DT_AUDIT entry for the linker emulation code. */
-      elf_dt_audit (abfd) = audit; 
+      elf_dt_audit (abfd) = audit;
     }
 
   /* If this is a dynamic object, we always link against the .dynsym
@@ -3834,6 +3818,7 @@ error_free_dyn:
       old_size = htab->root.table.size;
       old_count = htab->root.table.count;
       old_dynsymcount = htab->dynsymcount;
+      old_dynstr_size = _bfd_elf_strtab_size (htab->dynstr);
 
       for (i = 0; i < htab->root.table.size; i++)
        {
@@ -4029,7 +4014,7 @@ error_free_dyn:
                  && h->root.u.undef.abfd)
                undef_bfd = h->root.u.undef.abfd;
            }
-         
+
          if (ever == NULL)
            {
              if (info->default_imported_symver)
@@ -4190,7 +4175,6 @@ error_free_dyn:
            }
 
          if (elf_tdata (abfd)->verdef != NULL
-             && ! override
              && vernum > 1
              && definition)
            h->verinfo.verdef = &elf_tdata (abfd)->verdef[vernum - 1];
@@ -4415,9 +4399,7 @@ error_free_dyn:
              else
                {
                  h->def_dynamic = 1;
-                 h->dynamic_def = 1;
                  hi->def_dynamic = 1;
-                 hi->dynamic_def = 1;
                }
 
              /* If the indirect symbol has been forced local, don't
@@ -4566,6 +4548,7 @@ error_free_dyn:
       memcpy (sym_hash, old_hash, hashsize);
       htab->root.undefs = old_undefs;
       htab->root.undefs_tail = old_undefs_tail;
+      _bfd_elf_strtab_clear_refs (htab->dynstr, old_dynstr_size);
       for (i = 0; i < htab->root.table.size; i++)
        {
          struct bfd_hash_entry *p;
@@ -4578,12 +4561,13 @@ error_free_dyn:
              h = (struct elf_link_hash_entry *) p;
              if (h->root.type == bfd_link_hash_warning)
                h = (struct elf_link_hash_entry *) h->root.u.i.link;
-             if (h->dynindx >= old_dynsymcount)
+             if (h->dynindx >= old_dynsymcount
+                 && h->dynstr_index < old_dynstr_size)
                _bfd_elf_strtab_delref (htab->dynstr, h->dynstr_index);
 
              /* Preserve the maximum alignment and size for common
                 symbols even if this dynamic lib isn't on DT_NEEDED
-                since it can still be loaded at the run-time by another
+                since it can still be loaded at run time by another
                 dynamic lib.  */
              if (h->root.type == bfd_link_hash_common)
                {
@@ -4602,8 +4586,9 @@ error_free_dyn:
                {
                  memcpy (h->root.u.i.link, old_ent, htab->root.table.entsize);
                  old_ent = (char *) old_ent + htab->root.table.entsize;
+                 h = (struct elf_link_hash_entry *) h->root.u.i.link;
                }
-             else if (h->root.type == bfd_link_hash_common)
+             if (h->root.type == bfd_link_hash_common)
                {
                  if (size > h->root.u.c.size)
                    h->root.u.c.size = size;
@@ -5745,19 +5730,16 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
       if (rpath != NULL)
        {
          bfd_size_type indx;
+         bfd_vma tag;
 
          indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, rpath,
                                      TRUE);
-         if (indx == (bfd_size_type) -1
-             || !_bfd_elf_add_dynamic_entry (info, DT_RPATH, indx))
+         if (indx == (bfd_size_type) -1)
            return FALSE;
 
-         if  (info->new_dtags)
-           {
-             _bfd_elf_strtab_addref (elf_hash_table (info)->dynstr, indx);
-             if (!_bfd_elf_add_dynamic_entry (info, DT_RUNPATH, indx))
-               return FALSE;
-           }
+         tag = info->new_dtags ? DT_RUNPATH : DT_RPATH;
+         if (!_bfd_elf_add_dynamic_entry (info, tag, indx))
+           return FALSE;
        }
 
       if (filter_shlib != NULL)
@@ -8808,7 +8790,7 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
       && h->ref_dynamic
       && h->def_regular
       && !h->dynamic_def
-      && !h->dynamic_weak
+      && h->ref_dynamic_nonweak
       && !elf_link_check_versioned_symbol (flinfo->info, bed, h))
     {
       bfd *def_bfd;
@@ -11756,7 +11738,7 @@ _bfd_elf_gc_mark_hook (asection *sec,
          if (sec_name && *sec_name != '\0')
            {
              bfd *i;
-             
+
              for (i = info->input_bfds; i; i = i->link_next)
                {
                  sec = bfd_get_section_by_name (i, sec_name);
@@ -12513,7 +12495,7 @@ bfd_elf_lookup_section_flags (struct bfd_link_info *info,
            }
          if (!tf->valid)
            {
-             info->callbacks->einfo 
+             info->callbacks->einfo
                (_("Unrecognized INPUT_SECTION_FLAG %s\n"), tf->name);
              return FALSE;
            }
@@ -12981,7 +12963,7 @@ get_dynamic_reloc_section_name (bfd *       abfd,
     return NULL;
 
   name = bfd_alloc (abfd, strlen (prefix) + strlen (old_name) + 1);
-  sprintf (name, "%s%s", prefix, old_name); 
+  sprintf (name, "%s%s", prefix, old_name);
 
   return name;
 }
This page took 0.02879 seconds and 4 git commands to generate.