* elfxx-ia64.c (elfNN_ia64_fake_sections): Set SHF_IA_64_HP_TLS
[deliverable/binutils-gdb.git] / bfd / elfxx-ia64.c
index 20d90831f124e538444e432fc8f7c84bb9e29c40..81e683c81fe879c4f0a7f12ee5bf5feda4c40058 100644 (file)
@@ -1,5 +1,5 @@
 /* IA-64 support for 64-bit ELF
-   Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004
+   Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
    Free Software Foundation, Inc.
    Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
 
@@ -17,7 +17,7 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
 
 #include "bfd.h"
 #include "sysdep.h"
 #include "objalloc.h"
 #include "hashtab.h"
 
+#define ARCH_SIZE      NN
+
+#if ARCH_SIZE == 64
+#define        LOG_SECTION_ALIGN       3
+#endif
+
+#if ARCH_SIZE == 32
+#define        LOG_SECTION_ALIGN       2
+#endif
+
 /* THE RULES for all the stuff the linker creates --
 
   GOT          Entries created in response to LTOFF or LTOFF_FPTR
@@ -162,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) \
@@ -180,11 +191,9 @@ static bfd_boolean elfNN_ia64_relax_section
   PARAMS((bfd *abfd, asection *sec, struct bfd_link_info *link_info,
          bfd_boolean *again));
 static void elfNN_ia64_relax_ldxmov
-  PARAMS((bfd *abfd, bfd_byte *contents, bfd_vma off));
+  PARAMS((bfd_byte *contents, bfd_vma off));
 static bfd_boolean is_unwind_section_name
   PARAMS ((bfd *abfd, const char *));
-static bfd_boolean elfNN_ia64_section_from_shdr
-  PARAMS ((bfd *, Elf_Internal_Shdr *, const char *));
 static bfd_boolean elfNN_ia64_section_flags
   PARAMS ((flagword *, const Elf_Internal_Shdr *));
 static bfd_boolean elfNN_ia64_fake_sections
@@ -207,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));
@@ -273,7 +282,7 @@ static bfd_boolean allocate_dynrel_entries
 static bfd_boolean elfNN_ia64_size_dynamic_sections
   PARAMS ((bfd *output_bfd, struct bfd_link_info *info));
 static bfd_reloc_status_type elfNN_ia64_install_value
-  PARAMS ((bfd *abfd, bfd_byte *hit_addr, bfd_vma val, unsigned int r_type));
+  PARAMS ((bfd_byte *hit_addr, bfd_vma val, unsigned int r_type));
 static void elfNN_ia64_install_dyn_reloc
   PARAMS ((bfd *abfd, struct bfd_link_info *info, asection *sec,
           asection *srel, bfd_vma offset, unsigned int type,
@@ -445,8 +454,8 @@ static reloc_howto_type ia64_howto_table[] =
     IA64_HOWTO (R_IA64_TPREL64LSB,  "TPREL64LSB",  4, FALSE, FALSE),
     IA64_HOWTO (R_IA64_LTOFF_TPREL22, "LTOFF_TPREL22",  0, FALSE, FALSE),
 
-    IA64_HOWTO (R_IA64_DTPMOD64MSB, "TPREL64MSB",  4, FALSE, FALSE),
-    IA64_HOWTO (R_IA64_DTPMOD64LSB, "TPREL64LSB",  4, FALSE, FALSE),
+    IA64_HOWTO (R_IA64_DTPMOD64MSB, "DTPMOD64MSB",  4, FALSE, FALSE),
+    IA64_HOWTO (R_IA64_DTPMOD64LSB, "DTPMOD64LSB",  4, FALSE, FALSE),
     IA64_HOWTO (R_IA64_LTOFF_DTPMOD22, "LTOFF_DTPMOD22", 0, FALSE, FALSE),
 
     IA64_HOWTO (R_IA64_DTPREL14,    "DTPREL14",           0, FALSE, FALSE),
@@ -479,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;
@@ -673,8 +683,146 @@ bfd_elfNN_ia64_after_parse (int itanium)
   oor_branch_size = itanium ? sizeof (oor_ip) : sizeof (oor_brl);
 }
 
+#define BTYPE_SHIFT    6
+#define Y_SHIFT                26
+#define X6_SHIFT       27
+#define X4_SHIFT       27
+#define X3_SHIFT       33
+#define X2_SHIFT       31
+#define X_SHIFT                33
+#define OPCODE_SHIFT   37
+
+#define OPCODE_BITS    (0xfLL << OPCODE_SHIFT)
+#define X6_BITS                (0x3fLL << X6_SHIFT)
+#define X4_BITS                (0xfLL << X4_SHIFT)
+#define X3_BITS                (0x7LL << X3_SHIFT)
+#define X2_BITS                (0x3LL << X2_SHIFT)
+#define X_BITS         (0x1LL << X_SHIFT)
+#define Y_BITS         (0x1LL << Y_SHIFT)
+#define BTYPE_BITS     (0x7LL << BTYPE_SHIFT)
+#define PREDICATE_BITS (0x3fLL)
+
+#define IS_NOP_B(i) \
+  (((i) & (OPCODE_BITS | X6_BITS)) == (2LL << OPCODE_SHIFT))
+#define IS_NOP_F(i) \
+  (((i) & (OPCODE_BITS | X_BITS | X6_BITS | Y_BITS)) \
+   == (0x1LL << X6_SHIFT))
+#define IS_NOP_I(i) \
+  (((i) & (OPCODE_BITS | X3_BITS | X6_BITS | Y_BITS)) \
+   == (0x1LL << X6_SHIFT))
+#define IS_NOP_M(i) \
+  (((i) & (OPCODE_BITS | X3_BITS | X2_BITS | X4_BITS | Y_BITS)) \
+   == (0x1LL << X4_SHIFT))
+#define IS_BR_COND(i) \
+  (((i) & (OPCODE_BITS | BTYPE_BITS)) == (0x4LL << OPCODE_SHIFT))
+#define IS_BR_CALL(i) \
+  (((i) & OPCODE_BITS) == (0x5LL << OPCODE_SHIFT))
+
+static bfd_boolean
+elfNN_ia64_relax_br (bfd_byte *contents, bfd_vma off)
+{
+  unsigned int template, mlx;
+  bfd_vma t0, t1, s0, s1, s2, br_code;
+  long br_slot;
+  bfd_byte *hit_addr;
+
+  hit_addr = (bfd_byte *) (contents + off);
+  br_slot = (long) hit_addr & 0x3;
+  hit_addr -= br_slot;
+  t0 = bfd_getl64 (hit_addr + 0);
+  t1 = bfd_getl64 (hit_addr + 8);
+
+  /* Check if we can turn br into brl.  A label is always at the start
+     of the bundle.  Even if there are predicates on NOPs, we still
+     perform this optimization.  */
+  template = t0 & 0x1e;
+  s0 = (t0 >> 5) & 0x1ffffffffffLL;
+  s1 = ((t0 >> 46) | (t1 << 18)) & 0x1ffffffffffLL;
+  s2 = (t1 >> 23) & 0x1ffffffffffLL;
+  switch (br_slot)
+    {
+    case 0:
+      /* Check if slot 1 and slot 2 are NOPs. Possible template is
+         BBB.  We only need to check nop.b.  */
+      if (!(IS_NOP_B (s1) && IS_NOP_B (s2)))
+       return FALSE;
+      br_code = s0;
+      break;
+    case 1:
+      /* Check if slot 2 is NOP. Possible templates are MBB and BBB.
+        For BBB, slot 0 also has to be nop.b.  */
+      if (!((template == 0x12                          /* MBB */
+            && IS_NOP_B (s2))
+           || (template == 0x16                        /* BBB */
+               && IS_NOP_B (s0)
+               && IS_NOP_B (s2))))
+       return FALSE;
+      br_code = s1;
+      break;
+    case 2:
+      /* Check if slot 1 is NOP. Possible templates are MIB, MBB, BBB,
+        MMB and MFB. For BBB, slot 0 also has to be nop.b.  */
+      if (!((template == 0x10                          /* MIB */
+            && IS_NOP_I (s1))
+           || (template == 0x12                        /* MBB */
+               && IS_NOP_B (s1))
+           || (template == 0x16                        /* BBB */
+               && IS_NOP_B (s0)
+               && IS_NOP_B (s1))
+           || (template == 0x18                        /* MMB */
+               && IS_NOP_M (s1))
+           || (template == 0x1c                        /* MFB */
+               && IS_NOP_F (s1))))
+       return FALSE;
+      br_code = s2;
+      break;
+    default:
+      /* It should never happen.  */
+      abort ();
+    }
+  
+  /* We can turn br.cond/br.call into brl.cond/brl.call.  */
+  if (!(IS_BR_COND (br_code) || IS_BR_CALL (br_code)))
+    return FALSE;
+
+  /* Turn br into brl by setting bit 40.  */
+  br_code |= 0x1LL << 40;
+
+  /* Turn the old bundle into a MLX bundle with the same stop-bit
+     variety.  */
+  if (t0 & 0x1)
+    mlx = 0x5;
+  else
+    mlx = 0x4;
+
+  if (template == 0x16)
+    {
+      /* 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
+    {
+      /* Keep the original instruction in slot 0.  */
+      t0 &= 0x1ffffffffffLL << 5;
+    }
+
+  t0 |= mlx;
+
+  /* Put brl in slot 1.  */
+  t1 = br_code << 23;
+
+  bfd_putl64 (t0, hit_addr);
+  bfd_putl64 (t1, hit_addr + 8);
+  return TRUE;
+}
+
 static void
-elfNN_ia64_relax_brl (bfd *abfd, bfd_byte *contents, bfd_vma off)
+elfNN_ia64_relax_brl (bfd_byte *contents, bfd_vma off)
 {
   int template;
   bfd_byte *hit_addr;
@@ -682,8 +830,8 @@ elfNN_ia64_relax_brl (bfd *abfd, bfd_byte *contents, bfd_vma off)
 
   hit_addr = (bfd_byte *) (contents + off);
   hit_addr -= (long) hit_addr & 0x3;
-  t0 = bfd_get_64 (abfd, hit_addr);
-  t1 = bfd_get_64 (abfd, hit_addr + 8);
+  t0 = bfd_getl64 (hit_addr);
+  t1 = bfd_getl64 (hit_addr + 8);
 
   /* Keep the instruction in slot 0. */
   i0 = (t0 >> 5) & 0x1ffffffffffLL;
@@ -694,14 +842,15 @@ elfNN_ia64_relax_brl (bfd *abfd, bfd_byte *contents, bfd_vma off)
 
   /* Turn a MLX bundle into a MBB bundle with the same stop-bit
      variety.  */
-  template = 0x12;
-  if ((t0 & 0x1fLL) == 5)
-    template += 1;
+  if (t0 & 0x1)
+    template = 0x13;
+  else
+    template = 0x12;
   t0 = (i1 << 46) | (i0 << 5) | template;
   t1 = (i2 << 23) | (i1 >> 18);
 
-  bfd_put_64 (abfd, t0, hit_addr);
-  bfd_put_64 (abfd, t1, hit_addr + 8);
+  bfd_putl64 (t0, hit_addr);
+  bfd_putl64 (t1, hit_addr + 8);
 }
 \f
 /* These functions do relaxation for IA-64 ELF.  */
@@ -749,11 +898,6 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
          && sec->need_finalize_relax == 0))
     return TRUE;
 
-  /* If this is the first time we have been called for this section,
-     initialize the cooked size.  */
-  if (sec->_cooked_size == 0)
-    sec->_cooked_size = sec->_raw_size;
-
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
 
   /* Load the relocations for this section.  */
@@ -771,12 +915,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
     contents = elf_section_data (sec)->this_hdr.contents;
   else
     {
-      contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
-      if (contents == NULL)
-       goto error_return;
-
-      if (! bfd_get_section_contents (abfd, sec, contents,
-                                     (file_ptr) 0, sec->_raw_size))
+      if (!bfd_malloc_and_get_section (abfd, sec, &contents))
        goto error_return;
     }
 
@@ -789,6 +928,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
       bfd_size_type amt;
       bfd_boolean is_branch;
       struct elfNN_ia64_dyn_sym_info *dyn_i;
+      char symtype;
 
       switch (r_type)
        {
@@ -864,6 +1004,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
 
          toff = isym->st_value;
          dyn_i = get_dyn_sym_info (ia64_info, NULL, abfd, irel, FALSE);
+         symtype = ELF_ST_TYPE (isym->st_info);
        }
       else
        {
@@ -908,13 +1049,38 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
              tsec = h->root.u.def.section;
              toff = h->root.u.def.value;
            }
+
+         symtype = h->type;
        }
 
       if (tsec->sec_info_type == ELF_INFO_TYPE_MERGE)
-       toff = _bfd_merged_section_offset (abfd, &tsec,
-                                          elf_section_data (tsec)->sec_info,
-                                          toff + irel->r_addend,
-                                          (bfd_vma) 0);
+       {
+         /* At this stage in linking, no SEC_MERGE symbol has been
+            adjusted, so all references to such symbols need to be
+            passed through _bfd_merged_section_offset.  (Later, in
+            relocate_section, all SEC_MERGE symbols *except* for
+            section symbols have been adjusted.)
+
+            gas may reduce relocations against symbols in SEC_MERGE
+            sections to a relocation against the section symbol when
+            the original addend was zero.  When the reloc is against
+            a section symbol we should include the addend in the
+            offset passed to _bfd_merged_section_offset, since the
+            location of interest is the original symbol.  On the
+            other hand, an access to "sym+addend" where "sym" is not
+            a section symbol should not include the addend;  Such an
+            access is presumed to be an offset from "sym";  The
+            location of interest is just "sym".  */
+          if (symtype == STT_SECTION)
+            toff += irel->r_addend;
+
+          toff = _bfd_merged_section_offset (abfd, &tsec,
+                                             elf_section_data (tsec)->sec_info,
+                                             toff);
+
+          if (symtype != STT_SECTION)
+            toff += irel->r_addend;
+       }
       else
        toff += irel->r_addend;
 
@@ -937,10 +1103,10 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
              /* If the 60-bit branch is in 21-bit range, optimize it. */
              if (r_type == R_IA64_PCREL60B)
                {
-                 elfNN_ia64_relax_brl (abfd, contents, roff);
+                 elfNN_ia64_relax_brl (contents, roff);
 
                  irel->r_info
-                   = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
+                   = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info),
                                    R_IA64_PCREL21B);
 
                  /* If the original relocation offset points to slot
@@ -953,11 +1119,34 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
            }
          else if (r_type == R_IA64_PCREL60B)
            continue;
+         else if (elfNN_ia64_relax_br (contents, roff))
+           {
+             irel->r_info
+               = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info),
+                               R_IA64_PCREL60B);
+
+             /* Make the relocation offset point to slot 1.  */
+             irel->r_offset = (irel->r_offset & ~((bfd_vma) 0x3)) + 1;
+             continue;
+           }
+
+         /* We can't put a trampoline in a .init/.fini section. Issue
+            an error.  */
+         if (strcmp (sec->output_section->name, ".init") == 0
+             || strcmp (sec->output_section->name, ".fini") == 0)
+           {
+             (*_bfd_error_handler)
+               (_("%B: Can't relax br at 0x%lx in section `%A'. Please use brl or indirect branch."),
+                sec->owner, sec, (unsigned long) roff);
+             bfd_set_error (bfd_error_bad_value);
+             goto error_return;
+           }
 
          /* If the branch and target are in the same section, you've
-            got one honking big section and we can't help you.  You'll
-            get an error message later.  */
-         if (tsec == sec)
+            got one honking big section and we can't help you unless
+            you are branching backwards.  You'll get an error message
+            later.  */
+         if (tsec == sec && toff > roff)
            continue;
 
          /* Look for an existing fixup to this address.  */
@@ -979,7 +1168,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
                size = oor_branch_size;
 
              /* Resize the current section to make room for the new branch. */
-             trampoff = (sec->_cooked_size + 15) & (bfd_vma) -16;
+             trampoff = (sec->size + 15) & (bfd_vma) -16;
 
              /* If trampoline is out of range, there is nothing we
                 can do.  */
@@ -991,7 +1180,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
              contents = (bfd_byte *) bfd_realloc (contents, amt);
              if (contents == NULL)
                goto error_return;
-             sec->_cooked_size = amt;
+             sec->size = amt;
 
              if (tsec == ia64_info->plt_sec)
                {
@@ -1044,8 +1233,8 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
            }
 
          /* Fix up the existing branch to hit the trampoline.  */
-         if (elfNN_ia64_install_value (abfd, contents + roff, offset,
-                                       r_type) != bfd_reloc_ok)
+         if (elfNN_ia64_install_value (contents + roff, offset, r_type)
+             != bfd_reloc_ok)
            goto error_return;
 
          changed_contents = TRUE;
@@ -1084,7 +1273,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
            }
          else
            {
-             elfNN_ia64_relax_ldxmov (abfd, contents, roff);
+             elfNN_ia64_relax_ldxmov (contents, roff);
              irel->r_info = ELFNN_R_INFO (0, R_IA64_NONE);
              changed_contents = TRUE;
              changed_relocs = TRUE;
@@ -1096,7 +1285,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
      enough that the data segment moves, which will change the GP.
      Reset the GP so that we re-calculate next round.  We need to
      do this at the _beginning_ of the next round; now will not do.  */
-      
+
   /* Clean up and go home.  */
   while (fixups)
     {
@@ -1147,10 +1336,20 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
       elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_data_got, &data);
       elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_fptr_got, &data);
       elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_local_got, &data);
-      ia64_info->got_sec->_raw_size = data.ofs;
-      ia64_info->got_sec->_cooked_size = data.ofs;
+      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)
@@ -1172,8 +1371,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
 }
 
 static void
-elfNN_ia64_relax_ldxmov (abfd, contents, off)
-     bfd *abfd;
+elfNN_ia64_relax_ldxmov (contents, off)
      bfd_byte *contents;
      bfd_vma off;
 {
@@ -1189,7 +1387,7 @@ elfNN_ia64_relax_ldxmov (abfd, contents, off)
       abort ();
     }
 
-  dword = bfd_get_64 (abfd, contents + off);
+  dword = bfd_getl64 (contents + off);
   insn = (dword >> shift) & 0x1ffffffffffLL;
 
   r1 = (insn >> 6) & 127;
@@ -1201,7 +1399,7 @@ elfNN_ia64_relax_ldxmov (abfd, contents, off)
 
   dword &= ~(0x1ffffffffffLL << shift);
   dword |= (insn << shift);
-  bfd_put_64 (abfd, dword, contents + off);
+  bfd_putl64 (dword, contents + off);
 }
 \f
 /* Return TRUE if NAME is an unwind table section name.  */
@@ -1226,13 +1424,14 @@ is_unwind_section_name (abfd, name)
 }
 
 /* Handle an IA-64 specific section when reading an object file.  This
-   is called when elfcode.h finds a section with an unknown type.  */
+   is called when bfd_section_from_shdr finds a section with an unknown
+   type.  */
 
 static bfd_boolean
-elfNN_ia64_section_from_shdr (abfd, hdr, name)
-     bfd *abfd;
-     Elf_Internal_Shdr *hdr;
-     const char *name;
+elfNN_ia64_section_from_shdr (bfd *abfd,
+                             Elf_Internal_Shdr *hdr,
+                             const char *name,
+                             int shindex)
 {
   asection *newsect;
 
@@ -1256,7 +1455,7 @@ elfNN_ia64_section_from_shdr (abfd, hdr, name)
       return FALSE;
     }
 
-  if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
+  if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
     return FALSE;
   newsect = hdr->bfd_section;
 
@@ -1325,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;
 }
 
@@ -1337,9 +1541,7 @@ elfNN_ia64_final_write_processing (abfd, linker)
      bfd_boolean linker ATTRIBUTE_UNUSED;
 {
   Elf_Internal_Shdr *hdr;
-  const char *sname;
-  asection *text_sect, *s;
-  size_t len;
+  asection *s;
 
   for (s = abfd->sections; s; s = s->next)
     {
@@ -1347,64 +1549,11 @@ elfNN_ia64_final_write_processing (abfd, linker)
       switch (hdr->sh_type)
        {
        case SHT_IA_64_UNWIND:
-         /* See comments in gas/config/tc-ia64.c:dot_endp on why we
-            have to do this.  */
-         sname = bfd_get_section_name (abfd, s);
-         len = sizeof (ELF_STRING_ia64_unwind) - 1;
-         if (sname && strncmp (sname, ELF_STRING_ia64_unwind, len) == 0)
-           {
-             sname += len;
-
-             if (sname[0] == '\0')
-               /* .IA_64.unwind -> .text */
-               text_sect = bfd_get_section_by_name (abfd, ".text");
-             else
-               /* .IA_64.unwindFOO -> FOO */
-               text_sect = bfd_get_section_by_name (abfd, sname);
-           }
-         else if (sname
-                  && (len = sizeof (ELF_STRING_ia64_unwind_once) - 1,
-                      strncmp (sname, ELF_STRING_ia64_unwind_once, len)) == 0)
-           {
-             /* .gnu.linkonce.ia64unw.FOO -> .gnu.linkonce.t.FOO */
-             size_t len2 = sizeof (".gnu.linkonce.t.") - 1;
-             char *once_name = bfd_malloc (len2 + strlen (sname + len) + 1);
-
-             if (once_name != NULL)
-               {
-                 memcpy (once_name, ".gnu.linkonce.t.", len2);
-                 strcpy (once_name + len2, sname + len);
-                 text_sect = bfd_get_section_by_name (abfd, once_name);
-                 free (once_name);
-               }
-             else
-               /* Should only happen if we run out of memory, in
-                  which case we're probably toast anyway.  Try to
-                  cope by finding the section the slow way.  */
-               for (text_sect = abfd->sections;
-                    text_sect != NULL;
-                    text_sect = text_sect->next)
-                 {
-                   if (strncmp (bfd_section_name (abfd, text_sect),
-                                ".gnu.linkonce.t.", len2) == 0
-                       && strcmp (bfd_section_name (abfd, text_sect) + len2,
-                                  sname + len) == 0)
-                     break;
-                 }
-           }
-         else
-           /* last resort: fall back on .text */
-           text_sect = bfd_get_section_by_name (abfd, ".text");
-
-         if (text_sect)
-           {
-             /* The IA-64 processor-specific ABI requires setting
-                sh_link to the unwind section, whereas HP-UX requires
-                sh_info to do so.  For maximum compatibility, we'll
-                set both for now... */
-             hdr->sh_link = elf_section_data (text_sect)->this_idx;
-             hdr->sh_info = elf_section_data (text_sect)->this_idx;
-           }
+         /* The IA-64 processor-specific ABI requires setting sh_link
+            to the unwind section, whereas HP-UX requires sh_info to
+            do so.  For maximum compatibility, we'll set both for
+            now... */
+         hdr->sh_info = hdr->sh_link;
          break;
        }
     }
@@ -1447,11 +1596,11 @@ elfNN_ia64_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
 
       if (scomm == NULL)
        {
-         scomm = bfd_make_section (abfd, ".scommon");
-         if (scomm == NULL
-             || !bfd_set_section_flags (abfd, scomm, (SEC_ALLOC
-                                                      | SEC_IS_COMMON
-                                                      | SEC_LINKER_CREATED)))
+         scomm = bfd_make_section_with_flags (abfd, ".scommon",
+                                              (SEC_ALLOC
+                                               | SEC_IS_COMMON
+                                               | SEC_LINKER_CREATED));
+         if (scomm == NULL)
            return FALSE;
        }
 
@@ -1579,7 +1728,7 @@ elfNN_ia64_modify_segment_map (abfd, info)
        int i;
        for (i = m->count - 1; i >= 0; --i)
          {
-           struct bfd_link_order *order = m->sections[i]->link_order_head;
+           struct bfd_link_order *order = m->sections[i]->map_head.link_order;
            while (order)
              {
                if (order->type == bfd_indirect_link_order)
@@ -1644,21 +1793,18 @@ elfNN_ia64_new_elf_hash_entry (entry, table, string)
   if (!ret)
     return 0;
 
-  /* Initialize our local data.  All zeros, and definitely easier
-     than setting a handful of bit fields.  */
-  memset (ret, 0, sizeof (*ret));
-
   /* Call the allocation method of the superclass.  */
   ret = ((struct elfNN_ia64_link_hash_entry *)
         _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret,
                                     table, string));
 
+  ret->info = NULL;
   return (struct bfd_hash_entry *) ret;
 }
 
 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;
@@ -1669,12 +1815,10 @@ elfNN_ia64_hash_copy_indirect (bed, xdir, xind)
   /* Copy down any references that we may have already seen to the
      symbol which just became indirect.  */
 
-  dir->root.elf_link_hash_flags |=
-    (ind->root.elf_link_hash_flags
-     & (ELF_LINK_HASH_REF_DYNAMIC
-        | ELF_LINK_HASH_REF_REGULAR
-        | ELF_LINK_HASH_REF_REGULAR_NONWEAK
-        | ELF_LINK_HASH_NEEDS_PLT));
+  dir->root.ref_dynamic |= ind->root.ref_dynamic;
+  dir->root.ref_regular |= ind->root.ref_regular;
+  dir->root.ref_regular_nonweak |= ind->root.ref_regular_nonweak;
+  dir->root.needs_plt |= ind->root.needs_plt;
 
   if (ind->root.root.type != bfd_link_hash_indirect)
     return;
@@ -1682,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
@@ -1890,25 +2039,25 @@ elfNN_ia64_create_dynamic_sections (abfd, info)
   if (!get_pltoff (abfd, info, ia64_info))
     return FALSE;
 
-  s = bfd_make_section(abfd, ".rela.IA_64.pltoff");
+  s = bfd_make_section_with_flags (abfd, ".rela.IA_64.pltoff",
+                                  (SEC_ALLOC | SEC_LOAD
+                                   | SEC_HAS_CONTENTS
+                                   | SEC_IN_MEMORY
+                                   | SEC_LINKER_CREATED
+                                   | SEC_READONLY));
   if (s == NULL
-      || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
-                                          | SEC_HAS_CONTENTS
-                                          | SEC_IN_MEMORY
-                                          | SEC_LINKER_CREATED
-                                          | SEC_READONLY))
-      || !bfd_set_section_alignment (abfd, s, 3))
+      || !bfd_set_section_alignment (abfd, s, LOG_SECTION_ALIGN))
     return FALSE;
   ia64_info->rel_pltoff_sec = s;
 
-  s = bfd_make_section(abfd, ".rela.got");
+  s = bfd_make_section_with_flags (abfd, ".rela.got",
+                                  (SEC_ALLOC | SEC_LOAD
+                                   | SEC_HAS_CONTENTS
+                                   | SEC_IN_MEMORY
+                                   | SEC_LINKER_CREATED
+                                   | SEC_READONLY));
   if (s == NULL
-      || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
-                                          | SEC_HAS_CONTENTS
-                                          | SEC_IN_MEMORY
-                                          | SEC_LINKER_CREATED
-                                          | SEC_READONLY))
-      || !bfd_set_section_alignment (abfd, s, 3))
+      || !bfd_set_section_alignment (abfd, s, LOG_SECTION_ALIGN))
     return FALSE;
   ia64_info->rel_got_sec = s;
 
@@ -2054,15 +2203,14 @@ get_fptr (abfd, info, ia64_info)
       if (!dynobj)
        ia64_info->root.dynobj = dynobj = abfd;
 
-      fptr = bfd_make_section (dynobj, ".opd");
+      fptr = bfd_make_section_with_flags (dynobj, ".opd",
+                                         (SEC_ALLOC
+                                          | SEC_LOAD
+                                          | SEC_HAS_CONTENTS
+                                          | SEC_IN_MEMORY
+                                          | (info->pie ? 0 : SEC_READONLY)
+                                          | SEC_LINKER_CREATED));
       if (!fptr
-         || !bfd_set_section_flags (dynobj, fptr,
-                                    (SEC_ALLOC
-                                     | SEC_LOAD
-                                     | SEC_HAS_CONTENTS
-                                     | SEC_IN_MEMORY
-                                     | (info->pie ? 0 : SEC_READONLY)
-                                     | SEC_LINKER_CREATED))
          || !bfd_set_section_alignment (abfd, fptr, 4))
        {
          BFD_ASSERT (0);
@@ -2074,15 +2222,15 @@ get_fptr (abfd, info, ia64_info)
       if (info->pie)
        {
          asection *fptr_rel;
-         fptr_rel = bfd_make_section(dynobj, ".rela.opd");
+         fptr_rel = bfd_make_section_with_flags (dynobj, ".rela.opd",
+                                                 (SEC_ALLOC | SEC_LOAD
+                                                  | SEC_HAS_CONTENTS
+                                                  | SEC_IN_MEMORY
+                                                  | SEC_LINKER_CREATED
+                                                  | SEC_READONLY));
          if (fptr_rel == NULL
-             || !bfd_set_section_flags (dynobj, fptr_rel,
-                                        (SEC_ALLOC | SEC_LOAD
-                                         | SEC_HAS_CONTENTS
-                                         | SEC_IN_MEMORY
-                                         | SEC_LINKER_CREATED
-                                         | SEC_READONLY))
-             || !bfd_set_section_alignment (abfd, fptr_rel, 3))
+             || !bfd_set_section_alignment (abfd, fptr_rel,
+                                            LOG_SECTION_ALIGN))
            {
              BFD_ASSERT (0);
              return NULL;
@@ -2111,15 +2259,15 @@ get_pltoff (abfd, info, ia64_info)
       if (!dynobj)
        ia64_info->root.dynobj = dynobj = abfd;
 
-      pltoff = bfd_make_section (dynobj, ELF_STRING_ia64_pltoff);
+      pltoff = bfd_make_section_with_flags (dynobj,
+                                           ELF_STRING_ia64_pltoff,
+                                           (SEC_ALLOC
+                                            | SEC_LOAD
+                                            | SEC_HAS_CONTENTS
+                                            | SEC_IN_MEMORY
+                                            | SEC_SMALL_DATA
+                                            | SEC_LINKER_CREATED));
       if (!pltoff
-         || !bfd_set_section_flags (dynobj, pltoff,
-                                    (SEC_ALLOC
-                                     | SEC_LOAD
-                                     | SEC_HAS_CONTENTS
-                                     | SEC_IN_MEMORY
-                                     | SEC_SMALL_DATA
-                                     | SEC_LINKER_CREATED))
          || !bfd_set_section_alignment (abfd, pltoff, 4))
        {
          BFD_ASSERT (0);
@@ -2163,16 +2311,15 @@ get_reloc_section (abfd, ia64_info, sec, create)
   srel = bfd_get_section_by_name (dynobj, srel_name);
   if (srel == NULL && create)
     {
-      srel = bfd_make_section (dynobj, srel_name);
+      srel = bfd_make_section_with_flags (dynobj, srel_name,
+                                         (SEC_ALLOC | SEC_LOAD
+                                          | SEC_HAS_CONTENTS
+                                          | SEC_IN_MEMORY
+                                          | SEC_LINKER_CREATED
+                                          | SEC_READONLY));
       if (srel == NULL
-         || !bfd_set_section_flags (dynobj, srel,
-                                    (SEC_ALLOC
-                                     | SEC_LOAD
-                                     | SEC_HAS_CONTENTS
-                                     | SEC_IN_MEMORY
-                                     | SEC_LINKER_CREATED
-                                     | SEC_READONLY))
-         || !bfd_set_section_alignment (dynobj, srel, 3))
+         || !bfd_set_section_alignment (dynobj, srel,
+                                        LOG_SECTION_ALIGN))
        return NULL;
     }
 
@@ -2219,7 +2366,7 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs)
   const Elf_Internal_Rela *relend;
   Elf_Internal_Shdr *symtab_hdr;
   const Elf_Internal_Rela *rel;
-  asection *got, *fptr, *srel;
+  asection *got, *fptr, *srel, *pltoff;
 
   if (info->relocatable)
     return TRUE;
@@ -2227,7 +2374,7 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs)
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   ia64_info = elfNN_ia64_hash_table (info);
 
-  got = fptr = srel = NULL;
+  got = fptr = srel = pltoff = NULL;
 
   relend = relocs + sec->reloc_count;
   for (rel = relocs; rel < relend; ++rel)
@@ -2263,7 +2410,7 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs)
                 || h->root.type == bfd_link_hash_warning)
            h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
-         h->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR;
+         h->ref_regular = 1;
        }
 
       /* We can only get preliminary data on whether a symbol is
@@ -2272,8 +2419,9 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs)
         this may help reduce memory usage and processing time later.  */
       maybe_dynamic = FALSE;
       if (h && ((!info->executable
-                && (!info->symbolic || info->unresolved_syms_in_shared_libs == RM_IGNORE))
-               || ! (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)
+                && (!info->symbolic
+                    || info->unresolved_syms_in_shared_libs == RM_IGNORE))
+               || !h->def_regular
                || h->root.type == bfd_link_hash_defweak))
        maybe_dynamic = TRUE;
 
@@ -2295,11 +2443,13 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs)
            info->flags |= DF_STATIC_TLS;
          break;
 
+       case R_IA64_DTPREL32MSB:
+       case R_IA64_DTPREL32LSB:
        case R_IA64_DTPREL64MSB:
        case R_IA64_DTPREL64LSB:
          if (info->shared || maybe_dynamic)
            need_entry = NEED_DYNREL;
-         dynrel_type = R_IA64_DTPREL64LSB;
+         dynrel_type = R_IA64_DTPRELNNLSB;
          break;
 
        case R_IA64_LTOFF_DTPREL22:
@@ -2335,7 +2485,7 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs)
            need_entry = NEED_FPTR | NEED_DYNREL;
          else
            need_entry = NEED_FPTR;
-         dynrel_type = R_IA64_FPTR64LSB;
+         dynrel_type = R_IA64_FPTRNNLSB;
          break;
 
        case R_IA64_LTOFF22:
@@ -2385,7 +2535,7 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs)
          /* Shared objects will always need at least a REL relocation.  */
          if (info->shared || maybe_dynamic)
            need_entry = NEED_DYNREL;
-         dynrel_type = R_IA64_DIR64LSB;
+         dynrel_type = R_IA64_DIRNNLSB;
          break;
 
        case R_IA64_IPLTMSB:
@@ -2404,7 +2554,7 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs)
        case R_IA64_PCREL64LSB:
          if (maybe_dynamic)
            need_entry = NEED_DYNREL;
-         dynrel_type = R_IA64_PCREL64LSB;
+         dynrel_type = R_IA64_PCRELNNLSB;
          break;
        }
 
@@ -2472,13 +2622,24 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs)
        {
           if (!ia64_info->root.dynobj)
            ia64_info->root.dynobj = abfd;
-         h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
+         h->needs_plt = 1;
          dyn_i->want_plt = 1;
        }
       if (need_entry & NEED_FULL_PLT)
        dyn_i->want_plt2 = 1;
       if (need_entry & NEED_PLTOFF)
-       dyn_i->want_pltoff = 1;
+       {
+         /* This is needed here, in case @pltoff is used in a non-shared
+            link.  */
+         if (!pltoff)
+           {
+             pltoff = get_pltoff (abfd, info, ia64_info);
+             if (!pltoff)
+               return FALSE;
+           }
+
+         dyn_i->want_pltoff = 1;
+       }
       if ((need_entry & NEED_DYNREL) && (sec->flags & SEC_ALLOC))
        {
          if (!srel)
@@ -2557,7 +2718,7 @@ allocate_global_fptr_got (dyn_i, data)
 
   if (dyn_i->want_got
       && dyn_i->want_fptr
-      && elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info, R_IA64_FPTR64LSB))
+      && elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info, R_IA64_FPTRNNLSB))
     {
       dyn_i->got_offset = x->ofs;
       x->ofs += 8;
@@ -2624,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)
            {
@@ -2668,7 +2830,7 @@ allocate_plt_entries (dyn_i, data)
               || h->root.type == bfd_link_hash_warning)
          h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
-      /* ??? Versioned symbols seem to lose ELF_LINK_HASH_NEEDS_PLT.  */
+      /* ??? Versioned symbols seem to lose NEEDS_PLT.  */
       if (elfNN_ia64_dynamic_symbol_p (h, x->info, 0))
        {
          bfd_size_type offset = x->ofs;
@@ -2756,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)
@@ -2764,6 +2972,7 @@ allocate_dynrel_entries (dyn_i, data)
 
       switch (rent->type)
        {
+       case R_IA64_FPTR32LSB:
        case R_IA64_FPTR64LSB:
          /* Allocate one iff !want_fptr and not PIE, which by this point
             will be true only if we're actually allocating one statically
@@ -2772,10 +2981,12 @@ allocate_dynrel_entries (dyn_i, data)
          if (dyn_i->want_fptr && !x->info->pie)
            continue;
          break;
+       case R_IA64_PCREL32LSB:
        case R_IA64_PCREL64LSB:
          if (!dynamic_symbol)
            continue;
          break;
+       case R_IA64_DIR32LSB:
        case R_IA64_DIR64LSB:
          if (!dynamic_symbol && !shared)
            continue;
@@ -2788,6 +2999,7 @@ allocate_dynrel_entries (dyn_i, data)
          if (!dynamic_symbol)
            count *= 2;
          break;
+       case R_IA64_DTPREL32LSB:
        case R_IA64_TPREL64LSB:
        case R_IA64_DTPREL64LSB:
        case R_IA64_DTPMOD64LSB:
@@ -2797,49 +3009,7 @@ allocate_dynrel_entries (dyn_i, data)
        }
       if (rent->reltext)
        ia64_info->reltext = 1;
-      rent->srel->_raw_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->_raw_size += sizeof (ElfNN_External_Rela);
-    }
-  if ((dynamic_symbol || shared) && dyn_i->want_tprel)
-    ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
-  if (dynamic_symbol && dyn_i->want_dtpmod)
-    ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
-  if (dynamic_symbol && dyn_i->want_dtprel)
-    ia64_info->rel_got_sec->_raw_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->_raw_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->_raw_size += t;
+      rent->srel->size += sizeof (ElfNN_External_Rela) * count;
     }
 
   return TRUE;
@@ -2856,12 +3026,12 @@ elfNN_ia64_adjust_dynamic_symbol (info, h)
   /* If this is a weak symbol, and there is a real definition, the
      processor independent code will have arranged for us to see the
      real definition first, and we can just use the same value.  */
-  if (h->weakdef != NULL)
+  if (h->u.weakdef != NULL)
     {
-      BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
-                  || h->weakdef->root.type == bfd_link_hash_defweak);
-      h->root.u.def.section = h->weakdef->root.u.def.section;
-      h->root.u.def.value = h->weakdef->root.u.def.value;
+      BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
+                  || h->u.weakdef->root.type == bfd_link_hash_defweak);
+      h->root.u.def.section = h->u.weakdef->root.u.def.section;
+      h->root.u.def.value = h->u.weakdef->root.u.def.value;
       return TRUE;
     }
 
@@ -2899,7 +3069,7 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info)
       sec = bfd_get_section_by_name (dynobj, ".interp");
       BFD_ASSERT (sec != NULL);
       sec->contents = (bfd_byte *) ELF_DYNAMIC_INTERPRETER;
-      sec->_raw_size = strlen (ELF_DYNAMIC_INTERPRETER) + 1;
+      sec->size = strlen (ELF_DYNAMIC_INTERPRETER) + 1;
     }
 
   /* Allocate the GOT entries.  */
@@ -2910,7 +3080,7 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info)
       elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_data_got, &data);
       elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_fptr_got, &data);
       elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_local_got, &data);
-      ia64_info->got_sec->_raw_size = data.ofs;
+      ia64_info->got_sec->size = data.ofs;
     }
 
   /* Allocate the FPTR entries.  */
@@ -2919,7 +3089,7 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info)
     {
       data.ofs = 0;
       elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_fptr, &data);
-      ia64_info->fptr_sec->_raw_size = data.ofs;
+      ia64_info->fptr_sec->size = data.ofs;
     }
 
   /* Now that we've seen all of the input files, we can decide which
@@ -2949,12 +3119,12 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info)
 
       BFD_ASSERT (ia64_info->root.dynamic_sections_created);
 
-      ia64_info->plt_sec->_raw_size = data.ofs;
+      ia64_info->plt_sec->size = data.ofs;
 
       /* If we've got a .plt, we need some extra memory for the dynamic
         linker.  We stuff these in .got.plt.  */
       sec = bfd_get_section_by_name (dynobj, ".got.plt");
-      sec->_raw_size = 8 * PLT_RESERVED_WORDS;
+      sec->size = 8 * PLT_RESERVED_WORDS;
     }
 
   /* Allocate the PLTOFF entries.  */
@@ -2963,7 +3133,7 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info)
     {
       data.ofs = 0;
       elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_pltoff_entries, &data);
-      ia64_info->pltoff_sec->_raw_size = data.ofs;
+      ia64_info->pltoff_sec->size = data.ofs;
     }
 
   if (ia64_info->root.dynamic_sections_created)
@@ -2972,7 +3142,8 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info)
         required.  */
 
       if (info->shared && ia64_info->self_dtpmod_offset != (bfd_vma) -1)
-       ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
+       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);
     }
 
@@ -2993,7 +3164,7 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info)
         function which decides whether anything needs to go into
         these sections.  */
 
-      strip = (sec->_raw_size == 0);
+      strip = (sec->size == 0);
 
       if (sec == ia64_info->got_sec)
        strip = FALSE;
@@ -3066,12 +3237,12 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info)
        }
 
       if (strip)
-       _bfd_strip_section_from_output (info, sec);
+       sec->flags |= SEC_EXCLUDE;
       else
        {
          /* Allocate memory for the section contents.  */
-         sec->contents = (bfd_byte *) bfd_zalloc (dynobj, sec->_raw_size);
-         if (sec->contents == NULL && sec->_raw_size != 0)
+         sec->contents = (bfd_byte *) bfd_zalloc (dynobj, sec->size);
+         if (sec->contents == NULL && sec->size != 0)
            return FALSE;
        }
     }
@@ -3125,15 +3296,15 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info)
 }
 
 static bfd_reloc_status_type
-elfNN_ia64_install_value (abfd, hit_addr, v, r_type)
-     bfd *abfd;
+elfNN_ia64_install_value (hit_addr, v, r_type)
      bfd_byte *hit_addr;
      bfd_vma v;
      unsigned int r_type;
 {
   const struct ia64_operand *op;
   int bigendian = 0, shift = 0;
-  bfd_vma t0, t1, insn, dword;
+  bfd_vma t0, t1, dword;
+  ia64_insn insn;
   enum ia64_opnd opnd;
   const char *err;
   size_t size = 8;
@@ -3258,8 +3429,8 @@ elfNN_ia64_install_value (abfd, hit_addr, v, r_type)
     {
     case IA64_OPND_IMMU64:
       hit_addr -= (long) hit_addr & 0x3;
-      t0 = bfd_get_64 (abfd, hit_addr);
-      t1 = bfd_get_64 (abfd, hit_addr + 8);
+      t0 = bfd_getl64 (hit_addr);
+      t1 = bfd_getl64 (hit_addr + 8);
 
       /* tmpl/s: bits  0.. 5 in t0
         slot 0: bits  5..45 in t0
@@ -3281,14 +3452,14 @@ elfNN_ia64_install_value (abfd, hit_addr, v, r_type)
               | (((val >> 21) & 0x001) << 21)          /* ic */
               | (((val >> 63) & 0x001) << 36)) << 23;  /* i */
 
-      bfd_put_64 (abfd, t0, hit_addr);
-      bfd_put_64 (abfd, t1, hit_addr + 8);
+      bfd_putl64 (t0, hit_addr);
+      bfd_putl64 (t1, hit_addr + 8);
       break;
 
     case IA64_OPND_TGT64:
       hit_addr -= (long) hit_addr & 0x3;
-      t0 = bfd_get_64 (abfd, hit_addr);
-      t1 = bfd_get_64 (abfd, hit_addr + 8);
+      t0 = bfd_getl64 (hit_addr);
+      t1 = bfd_getl64 (hit_addr + 8);
 
       /* tmpl/s: bits  0.. 5 in t0
         slot 0: bits  5..45 in t0
@@ -3306,8 +3477,8 @@ elfNN_ia64_install_value (abfd, hit_addr, v, r_type)
       t1 |= ((((val >> 0) & 0xfffffLL) << 13)          /* imm20b */
              | (((val >> 59) & 0x1LL) << 36)) << 23;   /* i */
 
-      bfd_put_64 (abfd, t0, hit_addr);
-      bfd_put_64 (abfd, t1, hit_addr + 8);
+      bfd_putl64 (t0, hit_addr);
+      bfd_putl64 (t1, hit_addr + 8);
       break;
 
     default:
@@ -3318,17 +3489,17 @@ elfNN_ia64_install_value (abfd, hit_addr, v, r_type)
        case 2: shift = 23; hit_addr += 6; break;
        case 3: return bfd_reloc_notsupported; /* shouldn't happen...  */
        }
-      dword = bfd_get_64 (abfd, hit_addr);
+      dword = bfd_getl64 (hit_addr);
       insn = (dword >> shift) & 0x1ffffffffffLL;
 
       op = elf64_ia64_operands + opnd;
-      err = (*op->insert) (op, val, (ia64_insn *)& insn);
+      err = (*op->insert) (op, val, &insn);
       if (err)
        return bfd_reloc_overflow;
 
       dword &= ~(0x1ffffffffffLL << shift);
       dword |= (insn << shift);
-      bfd_put_64 (abfd, dword, hit_addr);
+      bfd_putl64 (dword, hit_addr);
       break;
 
     case IA64_OPND_NIL:
@@ -3382,8 +3553,7 @@ elfNN_ia64_install_dyn_reloc (abfd, info, sec, srel, offset, type,
   loc = srel->contents;
   loc += srel->reloc_count++ * sizeof (ElfNN_External_Rela);
   bfd_elfNN_swap_reloca_out (abfd, &outrel, loc);
-  BFD_ASSERT (sizeof (ElfNN_External_Rela) * srel->reloc_count
-             <= srel->_cooked_size);
+  BFD_ASSERT (sizeof (ElfNN_External_Rela) * srel->reloc_count <= srel->size);
 }
 
 /* Store an entry for target address TARGET_ADDR in the linkage table
@@ -3428,6 +3598,7 @@ set_got_entry (abfd, info, dyn_i, dynindx, addend, value, dyn_r_type)
        }
       got_offset = dyn_i->dtpmod_offset;
       break;
+    case R_IA64_DTPREL32LSB:
     case R_IA64_DTPREL64LSB:
       done = dyn_i->dtprel_done;
       dyn_i->dtprel_done = TRUE;
@@ -3452,9 +3623,12 @@ set_got_entry (abfd, info, dyn_i, dynindx, addend, value, dyn_r_type)
            && (!dyn_i->h
                || ELF_ST_VISIBILITY (dyn_i->h->other) == STV_DEFAULT
                || dyn_i->h->root.type != bfd_link_hash_undefweak)
+           && dyn_r_type != R_IA64_DTPREL32LSB
            && dyn_r_type != R_IA64_DTPREL64LSB)
            || elfNN_ia64_dynamic_symbol_p (dyn_i->h, info, dyn_r_type)
-          || (dynindx != -1 && dyn_r_type == R_IA64_FPTR64LSB))
+          || (dynindx != -1
+              && (dyn_r_type == R_IA64_FPTR32LSB
+                  || dyn_r_type == R_IA64_FPTR64LSB)))
          && (!dyn_i->want_ltoff_fptr
              || !info->pie
              || !dyn_i->h
@@ -3463,9 +3637,10 @@ set_got_entry (abfd, info, dyn_i, dynindx, addend, value, dyn_r_type)
          if (dynindx == -1
              && dyn_r_type != R_IA64_TPREL64LSB
              && dyn_r_type != R_IA64_DTPMOD64LSB
+             && dyn_r_type != R_IA64_DTPREL32LSB
              && dyn_r_type != R_IA64_DTPREL64LSB)
            {
-             dyn_r_type = R_IA64_REL64LSB;
+             dyn_r_type = R_IA64_RELNNLSB;
              dynindx = 0;
              addend = value;
            }
@@ -3474,6 +3649,18 @@ set_got_entry (abfd, info, dyn_i, dynindx, addend, value, dyn_r_type)
            {
              switch (dyn_r_type)
                {
+               case R_IA64_REL32LSB:
+                 dyn_r_type = R_IA64_REL32MSB;
+                 break;
+               case R_IA64_DIR32LSB:
+                 dyn_r_type = R_IA64_DIR32MSB;
+                 break;
+               case R_IA64_FPTR32LSB:
+                 dyn_r_type = R_IA64_FPTR32MSB;
+                 break;
+               case R_IA64_DTPREL32LSB:
+                 dyn_r_type = R_IA64_DTPREL32MSB;
+                 break;
                case R_IA64_REL64LSB:
                  dyn_r_type = R_IA64_REL64MSB;
                  break;
@@ -3603,9 +3790,9 @@ set_pltoff_entry (abfd, info, dyn_i, value, is_plt)
          unsigned int dyn_r_type;
 
          if (bfd_big_endian (abfd))
-           dyn_r_type = R_IA64_REL64MSB;
+           dyn_r_type = R_IA64_RELNNMSB;
          else
-           dyn_r_type = R_IA64_REL64LSB;
+           dyn_r_type = R_IA64_RELNNLSB;
 
          elfNN_ia64_install_dyn_reloc (abfd, NULL, pltoff_sec,
                                        ia64_info->rel_pltoff_sec,
@@ -3613,7 +3800,7 @@ set_pltoff_entry (abfd, info, dyn_i, value, is_plt)
                                        dyn_r_type, 0, value);
          elfNN_ia64_install_dyn_reloc (abfd, NULL, pltoff_sec,
                                        ia64_info->rel_pltoff_sec,
-                                       dyn_i->pltoff_offset + 8,
+                                       dyn_i->pltoff_offset + ARCH_SIZE / 8,
                                        dyn_r_type, 0, gp);
        }
 
@@ -3631,7 +3818,7 @@ set_pltoff_entry (abfd, info, dyn_i, value, is_plt)
 /* Return the base VMA address which should be subtracted from real addresses
    when resolving @tprel() relocation.
    Main program TLS (whose template starts at PT_TLS p_vaddr)
-   is assigned offset round(16, PT_TLS p_align).  */
+   is assigned offset round(2 * size of pointer, PT_TLS p_align).  */
 
 static bfd_vma
 elfNN_ia64_tprel_base (info)
@@ -3640,7 +3827,8 @@ elfNN_ia64_tprel_base (info)
   asection *tls_sec = elf_hash_table (info)->tls_sec;
 
   BFD_ASSERT (tls_sec != NULL);
-  return tls_sec->vma - align_power ((bfd_vma) 16, tls_sec->alignment_power);
+  return tls_sec->vma - align_power ((bfd_vma) ARCH_SIZE / 4,
+                                    tls_sec->alignment_power);
 }
 
 /* Return the base VMA address which should be subtracted from real addresses
@@ -3699,7 +3887,7 @@ elfNN_ia64_choose_gp (abfd, info)
        continue;
 
       lo = os->vma;
-      hi = os->vma + os->_raw_size;
+      hi = os->vma + os->size;
       if (hi < lo)
        hi = (bfd_vma) -1;
 
@@ -3804,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);
@@ -3835,7 +4023,7 @@ elfNN_ia64_final_link (abfd, info)
        {
          unwind_output_sec = s->output_section;
          unwind_output_sec->contents
-           = bfd_malloc (unwind_output_sec->_raw_size);
+           = bfd_malloc (unwind_output_sec->size);
          if (unwind_output_sec->contents == NULL)
            return FALSE;
        }
@@ -3849,13 +4037,13 @@ elfNN_ia64_final_link (abfd, info)
     {
       elfNN_ia64_unwind_entry_compare_bfd = abfd;
       qsort (unwind_output_sec->contents,
-            (size_t) (unwind_output_sec->_raw_size / 24),
+            (size_t) (unwind_output_sec->size / 24),
             24,
             elfNN_ia64_unwind_entry_compare);
 
       if (! bfd_set_section_contents (abfd, unwind_output_sec,
                                      unwind_output_sec->contents, (bfd_vma) 0,
-                                     unwind_output_sec->_raw_size))
+                                     unwind_output_sec->size))
        return FALSE;
     }
 
@@ -3922,8 +4110,8 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
       if (r_type > R_IA64_MAX_RELOC_CODE)
        {
          (*_bfd_error_handler)
-           (_("%s: unknown relocation type %d"),
-            bfd_archive_filename (input_bfd), (int)r_type);
+           (_("%B: unknown relocation type %d"),
+            input_bfd, (int) r_type);
          bfd_set_error (bfd_error_bad_value);
          ret_val = FALSE;
          continue;
@@ -3963,8 +4151,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
                                                    elf_section_data (msec)->
                                                    sec_info,
                                                    sym->st_value
-                                                   + dynent->addend,
-                                                   (bfd_vma) 0);
+                                                   + dynent->addend);
                      dynent->addend -= sym->st_value;
                      dynent->addend += msec->output_section->vma
                                        + msec->output_offset
@@ -4028,9 +4215,11 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
                  /* ??? People shouldn't be doing non-pic code in
                     shared libraries nor dynamic executables.  */
                  (*_bfd_error_handler)
-                   (_("%s: non-pic code with imm relocation against dynamic symbol `%s'"),
-                    bfd_archive_filename (input_bfd),
-                    h->root.root.string);
+                   (_("%B: non-pic code with imm relocation against dynamic symbol `%s'"),
+                    input_bfd,
+                    h ? h->root.root.string
+                      : bfd_elf_sym_name (input_bfd, symtab_hdr, sym,
+                                          sym_sec));
                  ret_val = FALSE;
                  continue;
 
@@ -4081,7 +4270,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
        case R_IA64_LTV32LSB:
        case R_IA64_LTV64MSB:
        case R_IA64_LTV64LSB:
-         r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
+         r = elfNN_ia64_install_value (hit_addr, value, r_type);
          break;
 
        case R_IA64_GPREL22:
@@ -4093,13 +4282,16 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
          if (dynamic_symbol_p)
            {
              (*_bfd_error_handler)
-               (_("%s: @gprel relocation against dynamic symbol %s"),
-                bfd_archive_filename (input_bfd), h->root.root.string);
+               (_("%B: @gprel relocation against dynamic symbol %s"),
+                input_bfd,
+                h ? h->root.root.string
+                  : bfd_elf_sym_name (input_bfd, symtab_hdr, sym,
+                                      sym_sec));
              ret_val = FALSE;
              continue;
            }
          value -= gp_val;
-         r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
+         r = elfNN_ia64_install_value (hit_addr, value, r_type);
          break;
 
        case R_IA64_LTOFF22:
@@ -4107,9 +4299,9 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
        case R_IA64_LTOFF64I:
           dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
          value = set_got_entry (input_bfd, info, dyn_i, (h ? h->dynindx : -1),
-                                rel->r_addend, value, R_IA64_DIR64LSB);
+                                rel->r_addend, value, R_IA64_DIRNNLSB);
          value -= gp_val;
-         r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
+         r = elfNN_ia64_install_value (hit_addr, value, r_type);
          break;
 
        case R_IA64_PLTOFF22:
@@ -4119,7 +4311,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
           dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
          value = set_pltoff_entry (output_bfd, info, dyn_i, value, FALSE);
          value -= gp_val;
-         r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
+         r = elfNN_ia64_install_value (hit_addr, value, r_type);
          break;
 
        case R_IA64_FPTR64I:
@@ -4153,14 +4345,14 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
                      /* ??? People shouldn't be doing non-pic code in
                         shared libraries.  Hork.  */
                      (*_bfd_error_handler)
-                       (_("%s: linking non-pic code in a position independent executable"),
-                        bfd_archive_filename (input_bfd));
+                       (_("%B: linking non-pic code in a position independent executable"),
+                        input_bfd);
                      ret_val = FALSE;
                      continue;
                    }
                  dynindx = 0;
                  addend = value;
-                 dyn_r_type = r_type + R_IA64_REL64LSB - R_IA64_FPTR64LSB;
+                 dyn_r_type = r_type + R_IA64_RELNNLSB - R_IA64_FPTRNNLSB;
                }
              else if (h)
                {
@@ -4184,7 +4376,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
                                            dynindx, addend);
            }
 
-         r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
+         r = elfNN_ia64_install_value (hit_addr, value, r_type);
          break;
 
        case R_IA64_LTOFF_FPTR22:
@@ -4199,7 +4391,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
            dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
            if (dyn_i->want_fptr)
              {
-               BFD_ASSERT (h == NULL || h->dynindx == -1)
+               BFD_ASSERT (h == NULL || h->dynindx == -1);
                if (!undef_weak_ref)
                  value = set_fptr_entry (output_bfd, info, dyn_i, value);
                dynindx = -1;
@@ -4224,9 +4416,9 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
              }
 
            value = set_got_entry (output_bfd, info, dyn_i, dynindx,
-                                  rel->r_addend, value, R_IA64_FPTR64LSB);
+                                  rel->r_addend, value, R_IA64_FPTRNNLSB);
            value -= gp_val;
-           r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
+           r = elfNN_ia64_install_value (hit_addr, value, r_type);
          }
          break;
 
@@ -4283,20 +4475,24 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
        case R_IA64_PCREL64I:
          /* The PCREL21BI reloc is specifically not intended for use with
             dynamic relocs.  PCREL21F and PCREL21M are used for speculation
-            fixup code, and thus probably ought not be dynamic.  The 
+            fixup code, and thus probably ought not be dynamic.  The
             PCREL22 and PCREL64I relocs aren't emitted as dynamic relocs.  */
          if (dynamic_symbol_p)
            {
              const char *msg;
 
              if (r_type == R_IA64_PCREL21BI)
-               msg = _("%s: @internal branch to dynamic symbol %s");
+               msg = _("%B: @internal branch to dynamic symbol %s");
              else if (r_type == R_IA64_PCREL21F || r_type == R_IA64_PCREL21M)
-               msg = _("%s: speculation fixup to dynamic symbol %s");
+               msg = _("%B: speculation fixup to dynamic symbol %s");
              else
-               msg = _("%s: @pcrel relocation against dynamic symbol %s");
-             (*_bfd_error_handler) (msg, bfd_archive_filename (input_bfd),
-                                    h->root.root.string);
+               msg = _("%B: @pcrel relocation against dynamic symbol %s");
+             (*_bfd_error_handler) (msg, input_bfd,
+                                    h ? h->root.root.string
+                                      : bfd_elf_sym_name (input_bfd,
+                                                          symtab_hdr,
+                                                          sym,
+                                                          sym_sec));
              ret_val = FALSE;
              continue;
            }
@@ -4307,7 +4503,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
          value -= (input_section->output_section->vma
                    + input_section->output_offset
                    + rel->r_offset) & ~ (bfd_vma) 0x3;
-         r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
+         r = elfNN_ia64_install_value (hit_addr, value, r_type);
          break;
 
        case R_IA64_SEGREL32MSB:
@@ -4351,8 +4547,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
                    value -= p->p_vaddr;
                  else
                    value = 0;
-                 r = elfNN_ia64_install_value (output_bfd, hit_addr, value,
-                                               r_type);
+                 r = elfNN_ia64_install_value (hit_addr, value, r_type);
                }
              break;
            }
@@ -4361,12 +4556,11 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
        case R_IA64_SECREL32LSB:
        case R_IA64_SECREL64MSB:
        case R_IA64_SECREL64LSB:
-         /* Make output-section relative.  */
-         if (value > input_section->output_section->vma)
-           value -= input_section->output_section->vma;
-         else
-           value = 0;
-         r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
+         /* Make output-section relative to section where the symbol
+            is defined. PR 475  */
+         if (sym_sec)
+           value -= sym_sec->output_section->vma;
+         r = elfNN_ia64_install_value (hit_addr, value, r_type);
          break;
 
        case R_IA64_IPLTMSB:
@@ -4407,25 +4601,26 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
            r_type = R_IA64_DIR64MSB;
          else
            r_type = R_IA64_DIR64LSB;
-         elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
-         r = elfNN_ia64_install_value (output_bfd, hit_addr + 8, gp_val,
-                                       r_type);
+         elfNN_ia64_install_value (hit_addr, value, r_type);
+         r = elfNN_ia64_install_value (hit_addr + 8, gp_val, r_type);
          break;
 
        case R_IA64_TPREL14:
        case R_IA64_TPREL22:
        case R_IA64_TPREL64I:
          value -= elfNN_ia64_tprel_base (info);
-         r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
+         r = elfNN_ia64_install_value (hit_addr, value, r_type);
          break;
 
        case R_IA64_DTPREL14:
        case R_IA64_DTPREL22:
        case R_IA64_DTPREL64I:
+       case R_IA64_DTPREL32LSB:
+       case R_IA64_DTPREL32MSB:
        case R_IA64_DTPREL64LSB:
        case R_IA64_DTPREL64MSB:
          value -= elfNN_ia64_dtprel_base (info);
-         r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
+         r = elfNN_ia64_install_value (hit_addr, value, r_type);
          break;
 
        case R_IA64_LTOFF_TPREL22:
@@ -4460,15 +4655,14 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
              case R_IA64_LTOFF_DTPREL22:
                if (!dynamic_symbol_p)
                  value -= elfNN_ia64_dtprel_base (info);
-               got_r_type = R_IA64_DTPREL64LSB;
+               got_r_type = R_IA64_DTPRELNNLSB;
                break;
              }
            dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
            value = set_got_entry (input_bfd, info, dyn_i, dynindx, r_addend,
                                   value, got_r_type);
            value -= gp_val;
-           r = elfNN_ia64_install_value (output_bfd, hit_addr, value,
-                                         r_type);
+           r = elfNN_ia64_install_value (hit_addr, value, r_type);
          }
          break;
 
@@ -4497,15 +4691,8 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
            if (h)
              name = h->root.root.string;
            else
-             {
-               name = bfd_elf_string_from_elf_section (input_bfd,
-                                                       symtab_hdr->sh_link,
-                                                       sym->st_name);
-               if (name == NULL)
-                 return FALSE;
-               if (*name == '\0')
-                 name = bfd_section_name (input_bfd, input_section);
-             }
+             name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym,
+                                      sym_sec);
            if (!(*info->callbacks->warning) (info, _("unsupported reloc"),
                                              name, input_bfd,
                                              input_section, rel->r_offset))
@@ -4524,22 +4711,39 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
            if (h)
              name = h->root.root.string;
            else
+             name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym,
+                                      sym_sec);
+
+           switch (r_type)
              {
-               name = bfd_elf_string_from_elf_section (input_bfd,
-                                                       symtab_hdr->sh_link,
-                                                       sym->st_name);
-               if (name == NULL)
+             case R_IA64_PCREL21B:
+             case R_IA64_PCREL21BI:
+             case R_IA64_PCREL21M:
+             case R_IA64_PCREL21F:
+               if (is_elf_hash_table (info->hash))
+                 {
+                   /* Relaxtion is always performed for ELF output.
+                      Overflow failures for those relocations mean
+                      that the section is too big to relax.  */
+                   (*_bfd_error_handler)
+                     (_("%B: Can't relax br (%s) to `%s' at 0x%lx in section `%A' with size 0x%lx (> 0x1000000)."),
+                      input_bfd, input_section, howto->name, name,
+                      rel->r_offset, input_section->size);
+                   break;
+                 }
+             default:
+               if (!(*info->callbacks->reloc_overflow) (info,
+                                                        &h->root,
+                                                        name,
+                                                        howto->name,
+                                                        (bfd_vma) 0,
+                                                        input_bfd,
+                                                        input_section,
+                                                        rel->r_offset))
                  return FALSE;
-               if (*name == '\0')
-                 name = bfd_section_name (input_bfd, input_section);
+               break;
              }
-           if (!(*info->callbacks->reloc_overflow) (info, name,
-                                                    howto->name,
-                                                    (bfd_vma) 0,
-                                                    input_bfd,
-                                                    input_section,
-                                                    rel->r_offset))
-             return FALSE;
+
            ret_val = FALSE;
          }
          break;
@@ -4579,9 +4783,8 @@ elfNN_ia64_finish_dynamic_symbol (output_bfd, info, h, sym)
       loc = plt_sec->contents + dyn_i->plt_offset;
 
       memcpy (loc, plt_min_entry, PLT_MIN_ENTRY_SIZE);
-      elfNN_ia64_install_value (output_bfd, loc, index, R_IA64_IMM22);
-      elfNN_ia64_install_value (output_bfd, loc+2, -dyn_i->plt_offset,
-                               R_IA64_PCREL21B);
+      elfNN_ia64_install_value (loc, index, R_IA64_IMM22);
+      elfNN_ia64_install_value (loc+2, -dyn_i->plt_offset, R_IA64_PCREL21B);
 
       plt_addr = (plt_sec->output_section->vma
                  + plt_sec->output_offset
@@ -4594,14 +4797,13 @@ elfNN_ia64_finish_dynamic_symbol (output_bfd, info, h, sym)
          loc = plt_sec->contents + dyn_i->plt2_offset;
 
          memcpy (loc, plt_full_entry, PLT_FULL_ENTRY_SIZE);
-         elfNN_ia64_install_value (output_bfd, loc, pltoff_addr - gp_val,
-                                   R_IA64_IMM22);
+         elfNN_ia64_install_value (loc, pltoff_addr - gp_val, R_IA64_IMM22);
 
          /* Mark the symbol as undefined, rather than as defined in the
             plt section.  Leave the value alone.  */
          /* ??? We didn't redefine it in adjust_dynamic_symbol in the
             first place.  But perhaps elflink.c did some for us.  */
-         if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+         if (!h->def_regular)
            sym->st_shndx = SHN_UNDEF;
        }
 
@@ -4661,7 +4863,7 @@ elfNN_ia64_finish_dynamic_sections (abfd, info)
       sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
       BFD_ASSERT (sdyn != NULL);
       dyncon = (ElfNN_External_Dyn *) sdyn->contents;
-      dynconend = (ElfNN_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
+      dynconend = (ElfNN_External_Dyn *) (sdyn->contents + sdyn->size);
 
       gp_val = _bfd_get_gp_value (abfd);
 
@@ -4718,7 +4920,7 @@ elfNN_ia64_finish_dynamic_sections (abfd, info)
                    + sgotplt->output_offset
                    - gp_val);
 
-         elfNN_ia64_install_value (abfd, loc+1, pltres, R_IA64_GPREL22);
+         elfNN_ia64_install_value (loc+1, pltres, R_IA64_GPREL22);
        }
     }
 
@@ -4785,8 +4987,8 @@ elfNN_ia64_merge_private_bfd_data (ibfd, obfd)
   if ((in_flags & EF_IA_64_TRAPNIL) != (out_flags & EF_IA_64_TRAPNIL))
     {
       (*_bfd_error_handler)
-       (_("%s: linking trap-on-NULL-dereference with non-trapping files"),
-        bfd_archive_filename (ibfd));
+       (_("%B: linking trap-on-NULL-dereference with non-trapping files"),
+        ibfd);
 
       bfd_set_error (bfd_error_bad_value);
       ok = FALSE;
@@ -4794,8 +4996,8 @@ elfNN_ia64_merge_private_bfd_data (ibfd, obfd)
   if ((in_flags & EF_IA_64_BE) != (out_flags & EF_IA_64_BE))
     {
       (*_bfd_error_handler)
-       (_("%s: linking big-endian files with little-endian files"),
-        bfd_archive_filename (ibfd));
+       (_("%B: linking big-endian files with little-endian files"),
+        ibfd);
 
       bfd_set_error (bfd_error_bad_value);
       ok = FALSE;
@@ -4803,8 +5005,8 @@ elfNN_ia64_merge_private_bfd_data (ibfd, obfd)
   if ((in_flags & EF_IA_64_ABI64) != (out_flags & EF_IA_64_ABI64))
     {
       (*_bfd_error_handler)
-       (_("%s: linking 64-bit files with 32-bit files"),
-        bfd_archive_filename (ibfd));
+       (_("%B: linking 64-bit files with 32-bit files"),
+        ibfd);
 
       bfd_set_error (bfd_error_bad_value);
       ok = FALSE;
@@ -4812,8 +5014,8 @@ elfNN_ia64_merge_private_bfd_data (ibfd, obfd)
   if ((in_flags & EF_IA_64_CONS_GP) != (out_flags & EF_IA_64_CONS_GP))
     {
       (*_bfd_error_handler)
-       (_("%s: linking constant-gp files with non-constant-gp files"),
-        bfd_archive_filename (ibfd));
+       (_("%B: linking constant-gp files with non-constant-gp files"),
+        ibfd);
 
       bfd_set_error (bfd_error_bad_value);
       ok = FALSE;
@@ -4822,8 +5024,8 @@ elfNN_ia64_merge_private_bfd_data (ibfd, obfd)
       != (out_flags & EF_IA_64_NOFUNCDESC_CONS_GP))
     {
       (*_bfd_error_handler)
-       (_("%s: linking auto-pic files with non-auto-pic files"),
-        bfd_archive_filename (ibfd));
+       (_("%B: linking auto-pic files with non-auto-pic files"),
+        ibfd);
 
       bfd_set_error (bfd_error_bad_value);
       ok = FALSE;
@@ -4877,13 +5079,106 @@ elfNN_ia64_reloc_type_class (rela)
     }
 }
 
-static struct bfd_elf_special_section const elfNN_ia64_special_sections[]=
+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 }
+  { NULL,        0, 0, 0,            0 }
 };
 
+static bfd_boolean
+elfNN_ia64_object_p (bfd *abfd)
+{
+  asection *sec;
+  asection *group, *unwi, *unw;
+  flagword flags;
+  const char *name;
+  char *unwi_name, *unw_name;
+  bfd_size_type amt;
+
+  if (abfd->flags & DYNAMIC)
+    return TRUE;
+
+  /* Flags for fake group section.  */
+  flags = (SEC_LINKER_CREATED | SEC_GROUP | SEC_LINK_ONCE
+          | SEC_EXCLUDE);
+
+  /* We add a fake section group for each .gnu.linkonce.t.* section,
+     which isn't in a section group, and its unwind sections.  */
+  for (sec = abfd->sections; sec != NULL; sec = sec->next)
+    {
+      if (elf_sec_group (sec) == NULL
+         && ((sec->flags & (SEC_LINK_ONCE | SEC_CODE | SEC_GROUP))
+             == (SEC_LINK_ONCE | SEC_CODE))
+         && strncmp (sec->name, ".gnu.linkonce.t.", 16) == 0)
+       {
+         name = sec->name + 16;
+
+         amt = strlen (name) + sizeof (".gnu.linkonce.ia64unwi.");
+         unwi_name = bfd_alloc (abfd, amt);
+         if (!unwi_name)
+           return FALSE;
+
+         strcpy (stpcpy (unwi_name, ".gnu.linkonce.ia64unwi."), name);
+         unwi = bfd_get_section_by_name (abfd, unwi_name);
+
+         amt = strlen (name) + sizeof (".gnu.linkonce.ia64unw.");
+         unw_name = bfd_alloc (abfd, amt);
+         if (!unw_name)
+           return FALSE;
+
+         strcpy (stpcpy (unw_name, ".gnu.linkonce.ia64unw."), name);
+         unw = bfd_get_section_by_name (abfd, unw_name);
+
+         /* We need to create a fake group section for it and its
+            unwind sections.  */
+         group = bfd_make_section_anyway_with_flags (abfd, name,
+                                                     flags);
+         if (group == NULL)
+           return FALSE;
+
+         /* Move the fake group section to the beginning.  */
+         bfd_section_list_remove (abfd, group);
+         bfd_section_list_prepend (abfd, group);
+
+         elf_next_in_group (group) = sec;
+
+         elf_group_name (sec) = name;
+         elf_next_in_group (sec) = sec;
+         elf_sec_group (sec) = group;
+
+         if (unwi)
+           {
+             elf_group_name (unwi) = name;
+             elf_next_in_group (unwi) = sec;
+             elf_next_in_group (sec) = unwi;
+             elf_sec_group (unwi) = group;
+           }
+
+          if (unw)
+            {
+              elf_group_name (unw) = name;
+              if (unwi)
+                {
+                  elf_next_in_group (unw) = elf_next_in_group (unwi);
+                  elf_next_in_group (unwi) = unw;
+                }
+              else
+                {
+                  elf_next_in_group (unw) = sec;
+                  elf_next_in_group (sec) = unw;
+                }
+              elf_sec_group (unw) = group;
+            }
+
+          /* Fake SHT_GROUP section header.  */
+         elf_section_data (group)->this_hdr.bfd_section = group;
+         elf_section_data (group)->this_hdr.sh_type = SHT_GROUP;
+       }
+    }
+  return TRUE;
+}
+
 static bfd_boolean
 elfNN_ia64_hpux_vec (const bfd_target *vec)
 {
@@ -4920,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)
     {
@@ -4967,6 +5262,9 @@ elfNN_hpux_backend_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
 #define bfd_elfNN_bfd_relax_section \
        elfNN_ia64_relax_section
 
+#define elf_backend_object_p \
+       elfNN_ia64_object_p
+
 /* Stuff for the BFD linker: */
 #define bfd_elfNN_bfd_link_hash_table_create \
        elfNN_ia64_hash_table_create
@@ -5011,6 +5309,13 @@ elfNN_hpux_backend_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
 #define elf_backend_rela_normal                1
 #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 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.   */
+#define elf_backend_link_order_error_handler NULL
+
 #include "elfNN-target.h"
 
 /* HPUX-specific vectors.  */
This page took 0.053726 seconds and 4 git commands to generate.