* elf.c (assign_file_positions_for_segments): Split into..
[deliverable/binutils-gdb.git] / bfd / elf32-i386.c
index 3dd28e44637895e45ef851aae0ee3b3b17b96b44..754aa52254d5509d8b13a296884c54fc7f860ced 100644 (file)
@@ -582,6 +582,10 @@ struct elf_i386_link_hash_entry
 #define GOT_TLS_IE_NEG 6
 #define GOT_TLS_IE_BOTH 7
 #define GOT_TLS_GDESC  8
+#define GOT_TLS_MASK   0x0f
+#define GOT_TLS_IE_IE  0x10
+#define GOT_TLS_IE_GD  0x20
+#define GOT_TLS_IE_MASK        0x30
 #define GOT_TLS_GD_BOTH_P(type)                                                \
   ((type) == (GOT_TLS_GD | GOT_TLS_GDESC))
 #define GOT_TLS_GD_P(type)                                             \
@@ -653,6 +657,9 @@ struct elf_i386_link_hash_table
   /* Value used to fill the last word of the first plt entry.  */
   bfd_byte plt0_pad_byte;
 
+  /* The index of the next unused R_386_TLS_DESC slot in .rel.plt.  */
+  bfd_vma next_tls_desc_index;
+
   union {
     bfd_signed_vma refcount;
     bfd_vma offset;
@@ -672,7 +679,7 @@ struct elf_i386_link_hash_table
   ((struct elf_i386_link_hash_table *) ((p)->hash))
 
 #define elf_i386_compute_jump_table_size(htab) \
-  ((htab)->srelplt->reloc_count * 4)
+  ((htab)->next_tls_desc_index * 4)
 
 /* Create an entry in an i386 ELF linker hash table.  */
 
@@ -718,7 +725,8 @@ elf_i386_link_hash_table_create (bfd *abfd)
   if (ret == NULL)
     return NULL;
 
-  if (! _bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc))
+  if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc,
+                                     sizeof (struct elf_i386_link_hash_entry)))
     {
       free (ret);
       return NULL;
@@ -732,6 +740,7 @@ elf_i386_link_hash_table_create (bfd *abfd)
   ret->sdynbss = NULL;
   ret->srelbss = NULL;
   ret->tls_ldm_got.refcount = 0;
+  ret->next_tls_desc_index = 0;
   ret->sgotplt_jump_table_size = 0;
   ret->sym_sec.abfd = NULL;
   ret->is_vxworks = 0;
@@ -778,9 +787,6 @@ static bfd_boolean
 elf_i386_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
 {
   struct elf_i386_link_hash_table *htab;
-  asection * s;
-  int flags;
-  const struct elf_backend_data *bed = get_elf_backend_data (dynobj);
 
   htab = elf_i386_hash_table (info);
   if (!htab->sgot && !create_got_section (dynobj, info))
@@ -799,17 +805,9 @@ elf_i386_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
       || (!info->shared && !htab->srelbss))
     abort ();
 
-  if (htab->is_vxworks && !info->shared)
-    {
-      s = bfd_make_section (dynobj, ".rel.plt.unloaded");
-      flags = (SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_READONLY
-             | SEC_LINKER_CREATED);
-      if (s == NULL
-        || ! bfd_set_section_flags (dynobj, s, flags)
-        || ! bfd_set_section_alignment (dynobj, s, bed->s->log_file_align))
-       return FALSE;
-      htab->srelplt2 = s;
-    }
+  if (htab->is_vxworks
+      && !elf_vxworks_create_dynamic_sections (dynobj, info, &htab->srelplt2))
+    return FALSE;
 
   return TRUE;
 }
@@ -1013,12 +1011,25 @@ elf_i386_check_relocs (bfd *abfd,
              case R_386_TLS_IE_32:
                if (ELF32_R_TYPE (rel->r_info) == r_type)
                  tls_type = GOT_TLS_IE_NEG;
+               else if (h
+                        && ELF32_R_TYPE (rel->r_info) == R_386_TLS_GD)
+                 /* If this is a GD->IE transition, we may use either
+                    of R_386_TLS_TPOFF and R_386_TLS_TPOFF32.  But if
+                    we may have both R_386_TLS_IE and R_386_TLS_GD,
+                    we can't share the same R_386_TLS_TPOFF since
+                    they require different offsets. So we remember
+                    it comes from R_386_TLS_GD.  */
+                 tls_type = GOT_TLS_IE | GOT_TLS_IE_GD;
                else
-                 /* If this is a GD->IE transition, we may use either of
-                    R_386_TLS_TPOFF and R_386_TLS_TPOFF32.  */
                  tls_type = GOT_TLS_IE;
                break;
              case R_386_TLS_IE:
+               if (h)
+                 {
+                   /* We remember it comes from R_386_TLS_IE.  */
+                   tls_type = GOT_TLS_IE_POS | GOT_TLS_IE_IE;
+                   break;
+                 }
              case R_386_TLS_GOTIE:
                tls_type = GOT_TLS_IE_POS; break;
              }
@@ -1058,7 +1069,8 @@ elf_i386_check_relocs (bfd *abfd,
              tls_type |= old_tls_type;
            /* If a TLS symbol is accessed using IE at least once,
               there is no point to use dynamic model for it.  */
-           else if (old_tls_type != tls_type && old_tls_type != GOT_UNKNOWN
+           else if (old_tls_type != tls_type
+                    && old_tls_type != GOT_UNKNOWN
                     && (! GOT_TLS_GD_ANY_P (old_tls_type)
                         || (tls_type & GOT_TLS_IE) == 0))
              {
@@ -1639,7 +1651,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 
          /* We also need to make an entry in the .rel.plt section.  */
          htab->srelplt->size += sizeof (Elf32_External_Rel);
-         htab->srelplt->reloc_count++;
+         htab->next_tls_desc_index++;
 
          if (htab->is_vxworks && !info->shared)
            {
@@ -1688,6 +1700,14 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
       asection *s;
       bfd_boolean dyn;
       int tls_type = elf_i386_hash_entry(h)->tls_type;
+      
+      /* If we have both R_386_TLS_IE and R_386_TLS_GD, GOT_TLS_IE_BOTH
+        should be used.  */
+      if ((tls_type & GOT_TLS_IE_MASK)
+         == (GOT_TLS_IE_IE | GOT_TLS_IE_GD))
+       tls_type = GOT_TLS_IE_BOTH;
+      else
+       tls_type &= GOT_TLS_MASK;
 
       /* Make sure this symbol is output as a dynamic symbol.
         Undefined weak syms won't yet be marked as dynamic.  */
@@ -1996,21 +2016,6 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
   else
     htab->tls_ldm_got.offset = -1;
 
-  if (htab->is_vxworks)
-    {
-      /* Mark the GOT and PLT symbols as having relocations; they might
-        not, but we won't know for sure until we build the GOT in
-        finish_dynamic_symbol.  */
-      if (htab->elf.hgot)
-       htab->elf.hgot->indx = -2;
-      if (htab->elf.hplt)
-       {
-         htab->elf.hplt->indx = -2;
-         if (htab->splt->flags & SEC_CODE)
-           htab->elf.hplt->type = STT_FUNC;
-       }
-    }
-
   /* Allocate global sym .plt and .got entries, and space for global
      sym dynamic relocs.  */
   elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info);
@@ -2021,7 +2026,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
      for them, it suffices to multiply the reloc count by the jump
      slot size.  */
   if (htab->srelplt)
-    htab->sgotplt_jump_table_size = htab->srelplt->reloc_count * 4;
+    htab->sgotplt_jump_table_size = htab->next_tls_desc_index * 4;
 
   /* We now have determined the sizes of the various dynamic sections.
      Allocate memory for them.  */
@@ -2054,8 +2059,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 
          /* We use the reloc_count field as a counter if we need
             to copy relocs into the output file.  */
-         if (s != htab->srelplt)
-           s->reloc_count = 0;
+         s->reloc_count = 0;
        }
       else
        {
@@ -2707,6 +2711,13 @@ elf_i386_relocate_section (bfd *output_bfd,
          else if (h != NULL)
            {
              tls_type = elf_i386_hash_entry(h)->tls_type;
+             /* If we have both R_386_TLS_IE and R_386_TLS_GD,
+                GOT_TLS_IE_BOTH should be used.  */
+             if ((tls_type & GOT_TLS_IE_MASK)
+                 == (GOT_TLS_IE_IE | GOT_TLS_IE_GD))
+               tls_type = GOT_TLS_IE_BOTH;
+             else
+               tls_type &= GOT_TLS_MASK;
              if (!info->shared && h->dynindx == -1 && (tls_type & GOT_TLS_IE))
                r_type = R_386_TLS_LE_32;
            }
@@ -2997,8 +3008,8 @@ elf_i386_relocate_section (bfd *output_bfd,
                                     + htab->sgotplt_jump_table_size);
                  sreloc = htab->srelplt;
                  loc = sreloc->contents;
-                 loc += sreloc->reloc_count++
-                   * sizeof (Elf32_External_Rel);
+                 loc += (htab->next_tls_desc_index++
+                         * sizeof (Elf32_External_Rel));
                  BFD_ASSERT (loc + sizeof (Elf32_External_Rel)
                              <= sreloc->contents + sreloc->size);
                  bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
@@ -3966,23 +3977,6 @@ elf_i386_vxworks_link_hash_table_create (bfd *abfd)
 }
 
 
-/* Tweak magic VxWorks symbols as they are written to the output file.  */
-static bfd_boolean
-elf_i386_vxworks_link_output_symbol_hook (struct bfd_link_info *info
-                                           ATTRIBUTE_UNUSED,
-                                         const char *name,
-                                         Elf_Internal_Sym *sym,
-                                         asection *input_sec ATTRIBUTE_UNUSED,
-                                         struct elf_link_hash_entry *h
-                                           ATTRIBUTE_UNUSED)
-{
-  /* Ignore the first dummy symbol.  */
-  if (!name)
-    return TRUE;
-
-  return elf_vxworks_link_output_symbol_hook (name, sym);
-}
-
 #undef elf_backend_post_process_headers
 #undef bfd_elf32_bfd_link_hash_table_create
 #define bfd_elf32_bfd_link_hash_table_create \
@@ -3992,7 +3986,7 @@ elf_i386_vxworks_link_output_symbol_hook (struct bfd_link_info *info
   elf_vxworks_add_symbol_hook
 #undef elf_backend_link_output_symbol_hook
 #define elf_backend_link_output_symbol_hook \
-  elf_i386_vxworks_link_output_symbol_hook
+  elf_vxworks_link_output_symbol_hook
 #undef elf_backend_emit_relocs
 #define elf_backend_emit_relocs                        elf_vxworks_emit_relocs
 #undef elf_backend_final_write_processing
This page took 0.076991 seconds and 4 git commands to generate.