* elfxx-ia64.c (elfNN_ia64_fake_sections): Set SHF_IA_64_HP_TLS
[deliverable/binutils-gdb.git] / bfd / elfxx-ia64.c
index cc8e5beebe31348a346d0a4ab7c308898daa34f8..81e683c81fe879c4f0a7f12ee5bf5feda4c40058 100644 (file)
@@ -172,6 +172,7 @@ struct elfNN_ia64_allocate_data
 {
   struct bfd_link_info *info;
   bfd_size_type ofs;
+  bfd_boolean only_got;
 };
 
 #define elfNN_ia64_hash_table(p) \
@@ -215,7 +216,7 @@ static struct bfd_hash_entry *elfNN_ia64_new_elf_hash_entry
   PARAMS ((struct bfd_hash_entry *entry, struct bfd_hash_table *table,
           const char *string));
 static void elfNN_ia64_hash_copy_indirect
-  PARAMS ((const struct elf_backend_data *, struct elf_link_hash_entry *,
+  PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *,
           struct elf_link_hash_entry *));
 static void elfNN_ia64_hash_hide_symbol
   PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *, bfd_boolean));
@@ -487,7 +488,8 @@ lookup_howto (rtype)
        elf_code_to_howto_index[ia64_howto_table[i].type] = i;
     }
 
-  BFD_ASSERT (rtype <= R_IA64_MAX_RELOC_CODE);
+  if (rtype > R_IA64_MAX_RELOC_CODE)
+    return 0;
   i = elf_code_to_howto_index[rtype];
   if (i >= NELEMS (ia64_howto_table))
     return 0;
@@ -795,9 +797,12 @@ elfNN_ia64_relax_br (bfd_byte *contents, bfd_vma off)
 
   if (template == 0x16)
     {
-      /* For BBB, we need to put nop.m in slot 0 and keep the original
-        predicate.  */
-      t0 &= PREDICATE_BITS << 5;
+      /* For BBB, we need to put nop.m in slot 0.  We keep the original
+        predicate only if slot 0 isn't br.  */
+      if (br_slot == 0)
+       t0 = 0LL;
+      else
+       t0 &= PREDICATE_BITS << 5;
       t0 |= 0x1LL << (X4_SHIFT + 5);
     }
   else
@@ -819,39 +824,33 @@ elfNN_ia64_relax_br (bfd_byte *contents, bfd_vma off)
 static void
 elfNN_ia64_relax_brl (bfd_byte *contents, bfd_vma off)
 {
-  unsigned int template, t0, t1, t2, t3;
+  int template;
   bfd_byte *hit_addr;
+  bfd_vma t0, t1, i0, i1, i2;
 
   hit_addr = (bfd_byte *) (contents + off);
   hit_addr -= (long) hit_addr & 0x3;
-  t0 = bfd_getl32 (hit_addr + 0);
-  t1 = bfd_getl32 (hit_addr + 4);
-  t2 = bfd_getl32 (hit_addr + 8);
-  t3 = bfd_getl32 (hit_addr + 12);
-
-  /* Turn a MLX bundle into a MBB bundle with the same stop-bit
-     variety.  */
-  template = 0x12;
-  if ((t0 & 0x1f) == 5)
-    template += 1;
+  t0 = bfd_getl64 (hit_addr);
+  t1 = bfd_getl64 (hit_addr + 8);
 
   /* Keep the instruction in slot 0. */
-  t0 &= 0xffffffe0;
-  t1 &= 0x3fff;
-
-  t0 |= template;
-
+  i0 = (t0 >> 5) & 0x1ffffffffffLL;
+  /* Use nop.b for slot 1. */
+  i1 = 0x4000000000LL;
   /* For slot 2, turn brl into br by masking out bit 40.  */
-  t2 &= 0xff800000;
-  t3 &= 0x7fffffff;
+  i2 = (t1 >> 23) & 0x0ffffffffffLL;
 
-  /* Use nop.b for slot 1. */
-  t2 |= 0x100000;
+  /* Turn a MLX bundle into a MBB bundle with the same stop-bit
+     variety.  */
+  if (t0 & 0x1)
+    template = 0x13;
+  else
+    template = 0x12;
+  t0 = (i1 << 46) | (i0 << 5) | template;
+  t1 = (i2 << 23) | (i1 >> 18);
 
-  bfd_putl32 (t0, hit_addr);
-  bfd_putl32 (t1, hit_addr + 4);
-  bfd_putl32 (t2, hit_addr + 8);
-  bfd_putl32 (t3, hit_addr + 12);
+  bfd_putl64 (t0, hit_addr);
+  bfd_putl64 (t1, hit_addr + 8);
 }
 \f
 /* These functions do relaxation for IA-64 ELF.  */
@@ -1339,7 +1338,18 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
       elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_local_got, &data);
       ia64_info->got_sec->size = data.ofs;
 
-      /* ??? Resize .rela.got too.  */
+      if (ia64_info->root.dynamic_sections_created
+         && ia64_info->rel_got_sec != NULL)
+       {
+         /* Resize .rela.got.  */
+         ia64_info->rel_got_sec->size = 0;
+         if (link_info->shared
+             && ia64_info->self_dtpmod_offset != (bfd_vma) -1)
+           ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela);
+         data.only_got = TRUE;
+         elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_dynrel_entries,
+                                      &data);
+       }
     }
 
   if (!link_info->need_relax_finalize)
@@ -1514,6 +1524,11 @@ elfNN_ia64_fake_sections (abfd, hdr, sec)
   if (sec->flags & SEC_SMALL_DATA)
     hdr->sh_flags |= SHF_IA_64_SHORT;
 
+  /* Some HP linkers look for the SHF_IA_64_HP_TLS flag instead of SHF_TLS. */
+
+  if (elfNN_ia64_hpux_vec (abfd->xvec) && (sec->flags & SHF_TLS))
+    hdr->sh_flags |= SHF_IA_64_HP_TLS;
+
   return TRUE;
 }
 
@@ -1788,8 +1803,8 @@ elfNN_ia64_new_elf_hash_entry (entry, table, string)
 }
 
 static void
-elfNN_ia64_hash_copy_indirect (bed, xdir, xind)
-     const struct elf_backend_data *bed ATTRIBUTE_UNUSED;
+elfNN_ia64_hash_copy_indirect (info, xdir, xind)
+     struct bfd_link_info *info;
      struct elf_link_hash_entry *xdir, *xind;
 {
   struct elfNN_ia64_link_hash_entry *dir, *ind;
@@ -1811,29 +1826,34 @@ elfNN_ia64_hash_copy_indirect (bed, xdir, xind)
   /* Copy over the got and plt data.  This would have been done
      by check_relocs.  */
 
-  if (dir->info == NULL)
+  if (ind->info != NULL)
     {
       struct elfNN_ia64_dyn_sym_info *dyn_i;
+      struct elfNN_ia64_dyn_sym_info **pdyn;
 
-      dir->info = dyn_i = ind->info;
+      pdyn = &dir->info;
+      while ((dyn_i = *pdyn) != NULL)
+       pdyn = &dyn_i->next;
+      *pdyn = dyn_i = ind->info;
       ind->info = NULL;
 
       /* Fix up the dyn_sym_info pointers to the global symbol.  */
       for (; dyn_i; dyn_i = dyn_i->next)
        dyn_i->h = &dir->root;
     }
-  BFD_ASSERT (ind->info == NULL);
 
   /* Copy over the dynindx.  */
 
-  if (dir->root.dynindx == -1)
+  if (ind->root.dynindx != -1)
     {
+      if (dir->root.dynindx != -1)
+       _bfd_elf_strtab_delref (elf_hash_table (info)->dynstr,
+                               dir->root.dynstr_index);
       dir->root.dynindx = ind->root.dynindx;
       dir->root.dynstr_index = ind->root.dynstr_index;
       ind->root.dynindx = -1;
       ind->root.dynstr_index = 0;
     }
-  BFD_ASSERT (ind->root.dynindx == -1);
 }
 
 static void
@@ -2765,7 +2785,8 @@ allocate_fptr (dyn_i, data)
       if (!x->info->executable
          && (!h
              || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
-             || h->root.type != bfd_link_hash_undefweak))
+             || (h->root.type != bfd_link_hash_undefweak
+                 && h->root.type != bfd_link_hash_undefined)))
        {
          if (h && h->dynindx == -1)
            {
@@ -2897,6 +2918,52 @@ allocate_dynrel_entries (dyn_i, data)
                   && ELF_ST_VISIBILITY (dyn_i->h->other)
                   && dyn_i->h->root.type == bfd_link_hash_undefweak);
 
+  /* Take care of the GOT and PLT relocations.  */
+
+  if ((!resolved_zero
+       && (dynamic_symbol || shared)
+       && (dyn_i->want_got || dyn_i->want_gotx))
+      || (dyn_i->want_ltoff_fptr
+         && dyn_i->h
+         && dyn_i->h->dynindx != -1))
+    {
+      if (!dyn_i->want_ltoff_fptr
+         || !x->info->pie
+         || dyn_i->h == NULL
+         || dyn_i->h->root.type != bfd_link_hash_undefweak)
+       ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela);
+    }
+  if ((dynamic_symbol || shared) && dyn_i->want_tprel)
+    ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela);
+  if (dynamic_symbol && dyn_i->want_dtpmod)
+    ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela);
+  if (dynamic_symbol && dyn_i->want_dtprel)
+    ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela);
+
+  if (x->only_got)
+    return TRUE;
+
+  if (ia64_info->rel_fptr_sec && dyn_i->want_fptr)
+    {
+      if (dyn_i->h == NULL || dyn_i->h->root.type != bfd_link_hash_undefweak)
+       ia64_info->rel_fptr_sec->size += sizeof (ElfNN_External_Rela);
+    }
+
+  if (!resolved_zero && dyn_i->want_pltoff)
+    {
+      bfd_size_type t = 0;
+
+      /* Dynamic symbols get one IPLT relocation.  Local symbols in
+        shared libraries get two REL relocations.  Local symbols in
+        main applications get nothing.  */
+      if (dynamic_symbol)
+       t = sizeof (ElfNN_External_Rela);
+      else if (shared)
+       t = 2 * sizeof (ElfNN_External_Rela);
+
+      ia64_info->rel_pltoff_sec->size += t;
+    }
+
   /* Take care of the normal data relocations.  */
 
   for (rent = dyn_i->reloc_entries; rent; rent = rent->next)
@@ -2945,48 +3012,6 @@ allocate_dynrel_entries (dyn_i, data)
       rent->srel->size += sizeof (ElfNN_External_Rela) * count;
     }
 
-  /* Take care of the GOT and PLT relocations.  */
-
-  if ((!resolved_zero
-       && (dynamic_symbol || shared)
-       && (dyn_i->want_got || dyn_i->want_gotx))
-      || (dyn_i->want_ltoff_fptr
-         && dyn_i->h
-         && dyn_i->h->dynindx != -1))
-    {
-      if (!dyn_i->want_ltoff_fptr
-         || !x->info->pie
-         || dyn_i->h == NULL
-         || dyn_i->h->root.type != bfd_link_hash_undefweak)
-       ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela);
-    }
-  if ((dynamic_symbol || shared) && dyn_i->want_tprel)
-    ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela);
-  if (dynamic_symbol && dyn_i->want_dtpmod)
-    ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela);
-  if (dynamic_symbol && dyn_i->want_dtprel)
-    ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela);
-  if (ia64_info->rel_fptr_sec && dyn_i->want_fptr)
-    {
-      if (dyn_i->h == NULL || dyn_i->h->root.type != bfd_link_hash_undefweak)
-       ia64_info->rel_fptr_sec->size += sizeof (ElfNN_External_Rela);
-    }
-
-  if (!resolved_zero && dyn_i->want_pltoff)
-    {
-      bfd_size_type t = 0;
-
-      /* Dynamic symbols get one IPLT relocation.  Local symbols in
-        shared libraries get two REL relocations.  Local symbols in
-        main applications get nothing.  */
-      if (dynamic_symbol)
-       t = sizeof (ElfNN_External_Rela);
-      else if (shared)
-       t = 2 * sizeof (ElfNN_External_Rela);
-
-      ia64_info->rel_pltoff_sec->size += t;
-    }
-
   return TRUE;
 }
 
@@ -3118,6 +3143,7 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info)
 
       if (info->shared && ia64_info->self_dtpmod_offset != (bfd_vma) -1)
        ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela);
+      data.only_got = FALSE;
       elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_dynrel_entries, &data);
     }
 
@@ -3966,15 +3992,15 @@ elfNN_ia64_final_link (abfd, info)
   /* Make sure we've got ourselves a nice fat __gp value.  */
   if (!info->relocatable)
     {
-      bfd_vma gp_val = _bfd_get_gp_value (abfd);
+      bfd_vma gp_val;
       struct elf_link_hash_entry *gp;
 
-      if (gp_val == 0)
-       {
-         if (! elfNN_ia64_choose_gp (abfd, info))
-           return FALSE;
-         gp_val = _bfd_get_gp_value (abfd);
-       }
+      /* We assume after gp is set, section size will only decrease. We
+        need to adjust gp for it.  */
+      _bfd_set_gp_value (abfd, 0);
+      if (! elfNN_ia64_choose_gp (abfd, info))
+       return FALSE;
+      gp_val = _bfd_get_gp_value (abfd);
 
       gp = elf_link_hash_lookup (elf_hash_table (info), "__gp", FALSE,
                                 FALSE, FALSE);
@@ -5053,46 +5079,13 @@ elfNN_ia64_reloc_type_class (rela)
     }
 }
 
-static struct bfd_elf_special_section const
-  ia64_special_sections_s[]=
+static const struct bfd_elf_special_section elfNN_ia64_special_sections[] =
 {
   { ".sbss",  5, -1, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE + SHF_IA_64_SHORT },
   { ".sdata", 6, -1, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_IA_64_SHORT },
   { NULL,        0, 0, 0,            0 }
 };
 
-static struct bfd_elf_special_section const *
-  elfNN_ia64_special_sections[27] =
-{
-  NULL,                                /* 'a' */
-  NULL,                                /* 'b' */
-  NULL,                                /* 'c' */
-  NULL,                                /* 'd' */
-  NULL,                                /* 'e' */
-  NULL,                                /* 'f' */
-  NULL,                                /* 'g' */
-  NULL,                                /* 'h' */
-  NULL,                                /* 'i' */
-  NULL,                                /* 'j' */
-  NULL,                                /* 'k' */
-  NULL,                                /* 'l' */
-  NULL,                                /* 'm' */
-  NULL,                                /* 'n' */
-  NULL,                                /* 'o' */
-  NULL,                                /* 'p' */
-  NULL,                                /* 'q' */
-  NULL,                                /* 'r' */
-  ia64_special_sections_s,     /* 's' */
-  NULL,                                /* 't' */
-  NULL,                                /* 'u' */
-  NULL,                                /* 'v' */
-  NULL,                                /* 'w' */
-  NULL,                                /* 'x' */
-  NULL,                                /* 'y' */
-  NULL,                                /* 'z' */
-  NULL                         /* other */
-};
-
 static bfd_boolean
 elfNN_ia64_object_p (bfd *abfd)
 {
@@ -5222,7 +5215,7 @@ static void
 elfNN_hpux_backend_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
                                      asymbol *asym)
 {
-  elf_symbol_type *elfsym = (elf_symbol_type *) asym;;
+  elf_symbol_type *elfsym = (elf_symbol_type *) asym;
 
   switch (elfsym->internal_elf_sym.st_shndx)
     {
@@ -5317,7 +5310,7 @@ elfNN_hpux_backend_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
 #define elf_backend_special_sections   elfNN_ia64_special_sections
 
 /* FIXME: PR 290: The Intel C compiler generates SHT_IA_64_UNWIND with
-   SHF_LINK_ORDER. But it doesn't set theh sh_link or sh_info fields.
+   SHF_LINK_ORDER. But it doesn't set the sh_link or sh_info fields.
    We don't want to flood users with so many error messages. We turn
    off the warning for now. It will be turned on later when the Intel
    compiler is fixed.   */
This page took 0.034718 seconds and 4 git commands to generate.