* Makefile.am (libbfd.h): Add "Extracted from.." comment.
[deliverable/binutils-gdb.git] / bfd / elfxx-ia64.c
index 05ae66840d0c58b7587b5390e75b97f26e58a197..bfa6391e76055cbba58e97ee6cf60db21cf028ae 100644 (file)
@@ -1,5 +1,5 @@
 /* IA-64 support for 64-bit ELF
-   Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+   Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
    Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
 
 This file is part of BFD, the Binary File Descriptor library.
@@ -79,6 +79,9 @@ struct elfNN_ia64_dyn_sym_info
   bfd_vma pltoff_offset;
   bfd_vma plt_offset;
   bfd_vma plt2_offset;
+  bfd_vma tprel_offset;
+  bfd_vma dtpmod_offset;
+  bfd_vma dtprel_offset;
 
   /* The symbol table entry, if any, that this was derrived from.  */
   struct elf_link_hash_entry *h;
@@ -97,6 +100,9 @@ struct elfNN_ia64_dyn_sym_info
   unsigned got_done : 1;
   unsigned fptr_done : 1;
   unsigned pltoff_done : 1;
+  unsigned tprel_done : 1;
+  unsigned dtpmod_done : 1;
+  unsigned dtprel_done : 1;
 
   /* True for the different kinds of linker data we want created.  */
   unsigned want_got : 1;
@@ -105,12 +111,19 @@ struct elfNN_ia64_dyn_sym_info
   unsigned want_plt : 1;
   unsigned want_plt2 : 1;
   unsigned want_pltoff : 1;
+  unsigned want_tprel : 1;
+  unsigned want_dtpmod : 1;
+  unsigned want_dtprel : 1;
 };
 
 struct elfNN_ia64_local_hash_entry
 {
   struct bfd_hash_entry root;
   struct elfNN_ia64_dyn_sym_info *info;
+
+  /* True if this hash entry's addends was translated for
+     SHF_MERGE optimization.  */
+  unsigned sec_merge_done : 1;
 };
 
 struct elfNN_ia64_local_hash_table
@@ -159,9 +172,9 @@ static boolean elfNN_ia64_relax_section
   PARAMS((bfd *abfd, asection *sec, struct bfd_link_info *link_info,
          boolean *again));
 static boolean is_unwind_section_name
-  PARAMS ((const char *));
+  PARAMS ((bfd *abfd, const char *));
 static boolean elfNN_ia64_section_from_shdr
-  PARAMS ((bfd *, ElfNN_Internal_Shdr *, char *));
+  PARAMS ((bfd *, ElfNN_Internal_Shdr *, const char *));
 static boolean elfNN_ia64_section_flags
   PARAMS ((flagword *, ElfNN_Internal_Shdr *));
 static boolean elfNN_ia64_fake_sections
@@ -200,7 +213,7 @@ static struct bfd_hash_entry *elfNN_ia64_new_elf_hash_entry
 static void elfNN_ia64_hash_copy_indirect
   PARAMS ((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 *));
+  PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *, boolean));
 static struct bfd_link_hash_table *elfNN_ia64_hash_table_create
   PARAMS ((bfd *abfd));
 static struct elfNN_ia64_local_hash_entry *elfNN_ia64_local_hash_lookup
@@ -216,6 +229,9 @@ static void elfNN_ia64_dyn_sym_traverse
           PTR info));
 static boolean elfNN_ia64_create_dynamic_sections
   PARAMS ((bfd *abfd, struct bfd_link_info *info));
+static struct elfNN_ia64_local_hash_entry * get_local_sym_hash
+  PARAMS ((struct elfNN_ia64_link_hash_table *ia64_info,
+          bfd *abfd, const Elf_Internal_Rela *rel, boolean create));
 static struct elfNN_ia64_dyn_sym_info * get_dyn_sym_info
   PARAMS ((struct elfNN_ia64_link_hash_table *ia64_info,
           struct elf_link_hash_entry *h,
@@ -278,6 +294,10 @@ static bfd_vma set_pltoff_entry
   PARAMS ((bfd *abfd, struct bfd_link_info *info,
           struct elfNN_ia64_dyn_sym_info *dyn_i,
           bfd_vma value, boolean));
+static bfd_vma elfNN_ia64_tprel_base
+  PARAMS ((struct bfd_link_info *info));
+static bfd_vma elfNN_ia64_dtprel_base
+  PARAMS ((struct bfd_link_info *info));
 static int elfNN_ia64_unwind_entry_compare
   PARAMS ((const PTR, const PTR));
 static boolean elfNN_ia64_final_link
@@ -294,14 +314,18 @@ static boolean elfNN_ia64_finish_dynamic_sections
   PARAMS ((bfd *abfd, struct bfd_link_info *info));
 static boolean elfNN_ia64_set_private_flags
   PARAMS ((bfd *abfd, flagword flags));
-static boolean elfNN_ia64_copy_private_bfd_data
-  PARAMS ((bfd *ibfd, bfd *obfd));
 static boolean elfNN_ia64_merge_private_bfd_data
   PARAMS ((bfd *ibfd, bfd *obfd));
 static boolean elfNN_ia64_print_private_bfd_data
   PARAMS ((bfd *abfd, PTR ptr));
 static enum elf_reloc_type_class elfNN_ia64_reloc_type_class
   PARAMS ((const Elf_Internal_Rela *));
+static boolean elfNN_ia64_hpux_vec
+  PARAMS ((const bfd_target *vec));
+static void elfNN_hpux_post_process_headers
+  PARAMS ((bfd *abfd, struct bfd_link_info *info));
+boolean elfNN_hpux_backend_section_from_bfd_section
+  PARAMS ((bfd *abfd, asection *sec, int *retval));
 \f
 /* ia64-specific relocation */
 
@@ -412,10 +436,25 @@ static reloc_howto_type ia64_howto_table[] =
     IA64_HOWTO (R_IA64_LTOFF22X,    "LTOFF22X",           0, false, true),
     IA64_HOWTO (R_IA64_LDXMOV,     "LDXMOV",      0, false, true),
 
+    IA64_HOWTO (R_IA64_TPREL14,            "TPREL14",     0, false, false),
     IA64_HOWTO (R_IA64_TPREL22,            "TPREL22",     0, false, false),
+    IA64_HOWTO (R_IA64_TPREL64I,    "TPREL64I",           0, false, false),
     IA64_HOWTO (R_IA64_TPREL64MSB,  "TPREL64MSB",  8, false, false),
     IA64_HOWTO (R_IA64_TPREL64LSB,  "TPREL64LSB",  8, false, false),
-    IA64_HOWTO (R_IA64_LTOFF_TP22,  "LTOFF_TP22",  0, false, false),
+    IA64_HOWTO (R_IA64_LTOFF_TPREL22, "LTOFF_TPREL22",  0, false, false),
+
+    IA64_HOWTO (R_IA64_DTPMOD64MSB, "TPREL64MSB",  8, false, false),
+    IA64_HOWTO (R_IA64_DTPMOD64LSB, "TPREL64LSB",  8, false, false),
+    IA64_HOWTO (R_IA64_LTOFF_DTPMOD22, "LTOFF_DTPMOD22", 0, false, false),
+
+    IA64_HOWTO (R_IA64_DTPREL14,    "DTPREL14",           0, false, false),
+    IA64_HOWTO (R_IA64_DTPREL22,    "DTPREL22",           0, false, false),
+    IA64_HOWTO (R_IA64_DTPREL64I,   "DTPREL64I",   0, false, false),
+    IA64_HOWTO (R_IA64_DTPREL32MSB, "DTPREL32MSB", 4, false, false),
+    IA64_HOWTO (R_IA64_DTPREL32LSB, "DTPREL32LSB", 4, false, false),
+    IA64_HOWTO (R_IA64_DTPREL64MSB, "DTPREL64MSB", 8, false, false),
+    IA64_HOWTO (R_IA64_DTPREL64LSB, "DTPREL64LSB", 8, false, false),
+    IA64_HOWTO (R_IA64_LTOFF_DTPREL22, "LTOFF_DTPREL22", 0, false, false),
   };
 
 static unsigned char elf_code_to_howto_index[R_IA64_MAX_RELOC_CODE + 1];
@@ -530,10 +569,25 @@ elfNN_ia64_reloc_type_lookup (abfd, bfd_code)
     case BFD_RELOC_IA64_LTOFF22X:      rtype = R_IA64_LTOFF22X; break;
     case BFD_RELOC_IA64_LDXMOV:                rtype = R_IA64_LDXMOV; break;
 
+    case BFD_RELOC_IA64_TPREL14:       rtype = R_IA64_TPREL14; break;
     case BFD_RELOC_IA64_TPREL22:       rtype = R_IA64_TPREL22; break;
+    case BFD_RELOC_IA64_TPREL64I:      rtype = R_IA64_TPREL64I; break;
     case BFD_RELOC_IA64_TPREL64MSB:    rtype = R_IA64_TPREL64MSB; break;
     case BFD_RELOC_IA64_TPREL64LSB:    rtype = R_IA64_TPREL64LSB; break;
-    case BFD_RELOC_IA64_LTOFF_TP22:    rtype = R_IA64_LTOFF_TP22; break;
+    case BFD_RELOC_IA64_LTOFF_TPREL22: rtype = R_IA64_LTOFF_TPREL22; break;
+
+    case BFD_RELOC_IA64_DTPMOD64MSB:   rtype = R_IA64_DTPMOD64MSB; break;
+    case BFD_RELOC_IA64_DTPMOD64LSB:   rtype = R_IA64_DTPMOD64LSB; break;
+    case BFD_RELOC_IA64_LTOFF_DTPMOD22:        rtype = R_IA64_LTOFF_DTPMOD22; break;
+
+    case BFD_RELOC_IA64_DTPREL14:      rtype = R_IA64_DTPREL14; break;
+    case BFD_RELOC_IA64_DTPREL22:      rtype = R_IA64_DTPREL22; break;
+    case BFD_RELOC_IA64_DTPREL64I:     rtype = R_IA64_DTPREL64I; break;
+    case BFD_RELOC_IA64_DTPREL32MSB:   rtype = R_IA64_DTPREL32MSB; break;
+    case BFD_RELOC_IA64_DTPREL32LSB:   rtype = R_IA64_DTPREL32LSB; break;
+    case BFD_RELOC_IA64_DTPREL64MSB:   rtype = R_IA64_DTPREL64MSB; break;
+    case BFD_RELOC_IA64_DTPREL64LSB:   rtype = R_IA64_DTPREL64LSB; break;
+    case BFD_RELOC_IA64_LTOFF_DTPREL22:        rtype = R_IA64_LTOFF_DTPREL22; break;
 
     default: return 0;
     }
@@ -637,6 +691,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
     };
 
   Elf_Internal_Shdr *symtab_hdr;
+  Elf_Internal_Shdr *shndx_hdr;
   Elf_Internal_Rela *internal_relocs;
   Elf_Internal_Rela *free_relocs = NULL;
   Elf_Internal_Rela *irel, *irelend;
@@ -644,6 +699,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
   bfd_byte *free_contents = NULL;
   ElfNN_External_Sym *extsyms;
   ElfNN_External_Sym *free_extsyms = NULL;
+  Elf_External_Sym_Shndx *shndx_buf = NULL;
   struct elfNN_ia64_link_hash_table *ia64_info;
   struct one_fixup *fixups = NULL;
   boolean changed_contents = false;
@@ -705,18 +761,34 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
        goto error_return;
     }
 
-  /* Read this BFD's symbols.  */
+  /* Read this BFD's local symbols.  */
   if (symtab_hdr->contents != NULL)
     extsyms = (ElfNN_External_Sym *) symtab_hdr->contents;
   else
     {
-      extsyms = (ElfNN_External_Sym *) bfd_malloc (symtab_hdr->sh_size);
+      bfd_size_type amt;
+
+      amt = symtab_hdr->sh_info * sizeof (ElfNN_External_Sym);
+      extsyms = (ElfNN_External_Sym *) bfd_malloc (amt);
       if (extsyms == NULL)
        goto error_return;
       free_extsyms = extsyms;
       if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-         || (bfd_bread (extsyms, symtab_hdr->sh_size, abfd)
-             != symtab_hdr->sh_size))
+         || bfd_bread (extsyms, amt, abfd) != amt)
+       goto error_return;
+    }
+
+  shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
+  if (shndx_hdr->sh_size != 0)
+    {
+      bfd_size_type amt;
+
+      amt = symtab_hdr->sh_info * sizeof (Elf_External_Sym_Shndx);
+      shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
+      if (shndx_buf == NULL)
+       goto error_return;
+      if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0
+         || bfd_bread (shndx_buf, amt, abfd) != amt)
        goto error_return;
     }
 
@@ -734,20 +806,23 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
       /* Get the value of the symbol referred to by the reloc.  */
       if (ELFNN_R_SYM (irel->r_info) < symtab_hdr->sh_info)
        {
+         ElfNN_External_Sym *esym;
+         Elf_External_Sym_Shndx *shndx;
+
          /* A local symbol.  */
-         bfd_elfNN_swap_symbol_in (abfd,
-                                   extsyms + ELFNN_R_SYM (irel->r_info),
-                                   &isym);
+         esym = extsyms + ELFNN_R_SYM (irel->r_info);
+         shndx = shndx_buf + (shndx_buf ? ELFNN_R_SYM (irel->r_info) : 0);
+         bfd_elfNN_swap_symbol_in (abfd, esym, shndx, &isym);
          if (isym.st_shndx == SHN_UNDEF)
            continue;   /* We can't do anthing with undefined symbols.  */
          else if (isym.st_shndx == SHN_ABS)
            tsec = bfd_abs_section_ptr;
          else if (isym.st_shndx == SHN_COMMON)
            tsec = bfd_com_section_ptr;
-         else if (isym.st_shndx > 0 && isym.st_shndx < SHN_LORESERVE)
-           tsec = bfd_section_from_elf_index (abfd, isym.st_shndx);
+         else if (isym.st_shndx == SHN_IA_64_ANSI_COMMON)
+           tsec = bfd_com_section_ptr;
          else
-           continue;   /* who knows.  */
+           tsec = bfd_section_from_elf_index (abfd, isym.st_shndx);
 
          toff = isym.st_value;
        }
@@ -915,6 +990,9 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
        }
     }
 
+  if (shndx_buf != NULL)
+    free (shndx_buf);
+
   if (free_extsyms != NULL)
     {
       if (! link_info->keep_memory)
@@ -934,6 +1012,8 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
     free (free_relocs);
   if (free_contents != NULL)
     free (free_contents);
+  if (shndx_buf != NULL)
+    free (shndx_buf);
   if (free_extsyms != NULL)
     free (free_extsyms);
   return false;
@@ -942,11 +1022,16 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
 /* Return true if NAME is an unwind table section name.  */
 
 static inline boolean
-is_unwind_section_name (name)
+is_unwind_section_name (abfd, name)
+       bfd *abfd;
        const char *name;
 {
   size_t len1, len2, len3;
 
+  if (elfNN_ia64_hpux_vec (abfd->xvec)
+      && !strcmp (name, ELF_STRING_ia64_unwind_hdr))
+    return false;
+
   len1 = sizeof (ELF_STRING_ia64_unwind) - 1;
   len2 = sizeof (ELF_STRING_ia64_unwind_info) - 1;
   len3 = sizeof (ELF_STRING_ia64_unwind_once) - 1;
@@ -962,7 +1047,7 @@ static boolean
 elfNN_ia64_section_from_shdr (abfd, hdr, name)
      bfd *abfd;
      ElfNN_Internal_Shdr *hdr;
-     char *name;
+     const char *name;
 {
   asection *newsect;
 
@@ -974,6 +1059,7 @@ elfNN_ia64_section_from_shdr (abfd, hdr, name)
   switch (hdr->sh_type)
     {
     case SHT_IA_64_UNWIND:
+    case SHT_IA_64_HP_OPT_ANOT:
       break;
 
     case SHT_IA_64_EXT:
@@ -1021,7 +1107,7 @@ elfNN_ia64_fake_sections (abfd, hdr, sec)
 
   name = bfd_get_section_name (abfd, sec);
 
-  if (is_unwind_section_name (name))
+  if (is_unwind_section_name (abfd, name))
     {
       /* We don't have the sections numbered at this point, so sh_info
         is set later, in elfNN_ia64_final_write_processing.  */
@@ -1030,6 +1116,8 @@ elfNN_ia64_fake_sections (abfd, hdr, sec)
     }
   else if (strcmp (name, ELF_STRING_ia64_archext) == 0)
     hdr->sh_type = SHT_IA_64_EXT;
+  else if (strcmp (name, ".HP.opt_annot") == 0)
+    hdr->sh_type = SHT_IA_64_HP_OPT_ANOT;
   else if (strcmp (name, ".reloc") == 0)
     /*
      * This is an ugly, but unfortunately necessary hack that is
@@ -1097,11 +1185,29 @@ elfNN_ia64_final_write_processing (abfd, linker)
            {
              /* .gnu.linkonce.ia64unw.FOO -> .gnu.linkonce.t.FOO */
              size_t len2 = sizeof (".gnu.linkonce.t.") - 1;
-             char *once_name = alloca (len2 + strlen (sname) - len + 1);
+             char *once_name = bfd_malloc (len2 + strlen (sname + len) + 1);
 
-             memcpy (once_name, ".gnu.linkonce.t.", len2);
-             strcpy (once_name + len2, sname + len);
-             text_sect = bfd_get_section_by_name (abfd, once_name);
+             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 */
@@ -1218,15 +1324,15 @@ elfNN_ia64_aix_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
     }
   else if (sym->st_shndx == SHN_LOOS)
     {
-      int i;
+      unsigned int i;
 
       /* SHN_AIX_SYSCALL: Treat this as any other symbol.  The special symbol
         is only relevant when compiling code for extended system calls.
         Replace the "special" section with .text, if possible.
         Note that these symbols are always assumed to be in .text. */
-      for (i = 1; i < elf_elfheader (abfd)->e_shnum; i++)
+      for (i = 1; i < elf_numsections (abfd); i++)
        {
-         asection * sec = bfd_section_from_elf_index (abfd, (unsigned) i);
+         asection * sec = bfd_section_from_elf_index (abfd, i);
 
          if (sec && strcmp (sec->name, ".text") == 0)
            {
@@ -1282,7 +1388,7 @@ elfNN_ia64_additional_program_headers (abfd)
 
   /* Count how many PT_IA_64_UNWIND segments we need.  */
   for (s = abfd->sections; s; s = s->next)
-    if (is_unwind_section_name(s->name) && (s->flags & SEC_LOAD))
+    if (is_unwind_section_name (abfd, s->name) && (s->flags & SEC_LOAD))
       ++ret;
 
   return ret;
@@ -1295,6 +1401,8 @@ elfNN_ia64_modify_segment_map (abfd)
   struct elf_segment_map *m, **pm;
   Elf_Internal_Shdr *hdr;
   asection *s;
+  boolean unwind_found;
+  asection *unwind_sec;
 
   /* If we need a PT_IA_64_ARCHEXT segment, it must come before
      all PT_LOAD segments.  */
@@ -1337,8 +1445,24 @@ elfNN_ia64_modify_segment_map (abfd)
       if (s && (s->flags & SEC_LOAD))
        {
          for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
-           if (m->p_type == PT_IA_64_UNWIND && m->sections[0] == s)
-             break;
+           if (m->p_type == PT_IA_64_UNWIND)
+             {
+               /* Look through all sections in the unwind segment
+                  for a match since there may be multiple sections
+                  to a segment.  */
+
+               unwind_sec = m->sections[0];
+               unwind_found = false;
+               while (unwind_sec != NULL && !unwind_found)
+                 {
+                   if (unwind_sec == s)
+                     unwind_found = true;
+                   else
+                     unwind_sec = unwind_sec -> next;
+                 }
+               if (unwind_found)
+                 break;
+             }
 
          if (m == NULL)
            {
@@ -1556,18 +1680,17 @@ elfNN_ia64_hash_copy_indirect (xdir, xind)
 }
 
 static void
-elfNN_ia64_hash_hide_symbol (info, xh)
-     struct bfd_link_info *info ATTRIBUTE_UNUSED;
+elfNN_ia64_hash_hide_symbol (info, xh, force_local)
+     struct bfd_link_info *info;
      struct elf_link_hash_entry *xh;
+     boolean force_local;
 {
   struct elfNN_ia64_link_hash_entry *h;
   struct elfNN_ia64_dyn_sym_info *dyn_i;
 
   h = (struct elfNN_ia64_link_hash_entry *)xh;
 
-  h->root.elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
-  if ((h->root.elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)
-    h->root.dynindx = -1;
+  _bfd_elf_link_hash_hide_symbol (info, &h->root, force_local);
 
   for (dyn_i = h->info; dyn_i; dyn_i = dyn_i->next)
     dyn_i->want_plt2 = 0;
@@ -1630,6 +1753,9 @@ elfNN_ia64_global_dyn_sym_thunk (xentry, xdata)
     = (struct elfNN_ia64_dyn_sym_traverse_data *) xdata;
   struct elfNN_ia64_dyn_sym_info *dyn_i;
 
+  if (entry->root.root.type == bfd_link_hash_warning)
+    entry = (struct elfNN_ia64_link_hash_entry *) entry->root.root.u.i.link;
+
   for (dyn_i = entry->info; dyn_i; dyn_i = dyn_i->next)
     if (! (*data->func) (dyn_i, data->data))
       return false;
@@ -1719,6 +1845,37 @@ elfNN_ia64_create_dynamic_sections (abfd, info)
   return true;
 }
 
+/* Find and/or create a hash entry for local symbol.  */
+static struct elfNN_ia64_local_hash_entry *
+get_local_sym_hash (ia64_info, abfd, rel, create)
+     struct elfNN_ia64_link_hash_table *ia64_info;
+     bfd *abfd;
+     const Elf_Internal_Rela *rel;
+     boolean create;
+{
+  char *addr_name;
+  size_t len;
+  struct elfNN_ia64_local_hash_entry *ret;
+
+  /* Construct a string for use in the elfNN_ia64_local_hash_table.
+     name describes what was once anonymous memory.  */
+
+  len = sizeof (void*)*2 + 1 + sizeof (bfd_vma)*4 + 1 + 1;
+  len += 10;   /* %p slop */
+
+  addr_name = bfd_malloc (len);
+  if (addr_name == NULL)
+    return 0;
+  sprintf (addr_name, "%p:%lx",
+          (void *) abfd, (unsigned long) ELFNN_R_SYM (rel->r_info));
+
+  /* Collect the canonical entry data for this address.  */
+  ret = elfNN_ia64_local_hash_lookup (&ia64_info->loc_hash_table,
+                                     addr_name, create, create);
+  free (addr_name);
+  return ret;
+}
+
 /* Find and/or create a descriptor for dynamic symbol info.  This will
    vary based on global or local symbol, and the addend to the reloc.  */
 
@@ -1739,22 +1896,8 @@ get_dyn_sym_info (ia64_info, h, abfd, rel, create)
   else
     {
       struct elfNN_ia64_local_hash_entry *loc_h;
-      char *addr_name;
-      size_t len;
-
-      /* Construct a string for use in the elfNN_ia64_local_hash_table.
-         The name describes what was once anonymous memory.  */
 
-      len = sizeof (void*)*2 + 1 + sizeof (bfd_vma)*4 + 1 + 1;
-      len += 10;       /* %p slop */
-
-      addr_name = alloca (len);
-      sprintf (addr_name, "%p:%lx",
-              (void *) abfd, (unsigned long) ELFNN_R_SYM (rel->r_info));
-
-      /* Collect the canonical entry data for this address.  */
-      loc_h = elfNN_ia64_local_hash_lookup (&ia64_info->loc_hash_table,
-                                           addr_name, create, create);
+      loc_h = get_local_sym_hash (ia64_info, abfd, rel, create);
       BFD_ASSERT (loc_h);
 
       pp = &loc_h->info;
@@ -1997,6 +2140,9 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs)
        NEED_FULL_PLT = 16,
        NEED_DYNREL = 32,
        NEED_LTOFF_FPTR = 64,
+       NEED_TPREL = 128,
+       NEED_DTPMOD = 256,
+       NEED_DTPREL = 512
       };
 
       struct elf_link_hash_entry *h = NULL;
@@ -2034,11 +2180,42 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs)
       need_entry = 0;
       switch (ELFNN_R_TYPE (rel->r_info))
        {
-       case R_IA64_TPREL22:
        case R_IA64_TPREL64MSB:
        case R_IA64_TPREL64LSB:
-       case R_IA64_LTOFF_TP22:
-         return false;
+         if (info->shared || maybe_dynamic)
+           need_entry = NEED_DYNREL;
+         dynrel_type = R_IA64_TPREL64LSB;
+         if (info->shared)
+           info->flags |= DF_STATIC_TLS;
+         break;
+
+       case R_IA64_LTOFF_TPREL22:
+         need_entry = NEED_TPREL;
+         if (info->shared)
+           info->flags |= DF_STATIC_TLS;
+         break;
+
+       case R_IA64_DTPREL64MSB:
+       case R_IA64_DTPREL64LSB:
+         if (info->shared || maybe_dynamic)
+           need_entry = NEED_DYNREL;
+         dynrel_type = R_IA64_DTPREL64LSB;
+         break;
+
+       case R_IA64_LTOFF_DTPREL22:
+         need_entry = NEED_DTPREL;
+         break;
+
+       case R_IA64_DTPMOD64MSB:
+       case R_IA64_DTPMOD64LSB:
+         if (info->shared || maybe_dynamic)
+           need_entry = NEED_DYNREL;
+         dynrel_type = R_IA64_DTPMOD64LSB;
+         break;
+
+       case R_IA64_LTOFF_DTPMOD22:
+         need_entry = NEED_DTPMOD;
+         break;
 
        case R_IA64_LTOFF_FPTR22:
        case R_IA64_LTOFF_FPTR64I:
@@ -2148,7 +2325,7 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs)
       dyn_i->h = h;
 
       /* Create what's needed.  */
-      if (need_entry & NEED_GOT)
+      if (need_entry & (NEED_GOT | NEED_TPREL | NEED_DTPMOD | NEED_DTPREL))
        {
          if (!got)
            {
@@ -2156,7 +2333,14 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs)
              if (!got)
                return false;
            }
-         dyn_i->want_got = 1;
+         if (need_entry & NEED_GOT)
+           dyn_i->want_got = 1;
+         if (need_entry & NEED_TPREL)
+           dyn_i->want_tprel = 1;
+         if (need_entry & NEED_DTPMOD)
+           dyn_i->want_dtpmod = 1;
+         if (need_entry & NEED_DTPREL)
+           dyn_i->want_dtprel = 1;
        }
       if (need_entry & NEED_FPTR)
        {
@@ -2236,6 +2420,21 @@ allocate_global_data_got (dyn_i, data)
        dyn_i->got_offset = x->ofs;
        x->ofs += 8;
      }
+  if (dyn_i->want_tprel)
+    {
+      dyn_i->tprel_offset = x->ofs;
+      x->ofs += 8;
+    }
+  if (dyn_i->want_dtpmod)
+    {
+      dyn_i->dtpmod_offset = x->ofs;
+      x->ofs += 8;
+    }
+  if (dyn_i->want_dtprel)
+    {
+      dyn_i->dtprel_offset = x->ofs;
+      x->ofs += 8;
+    }
   return true;
 }
 
@@ -2482,6 +2681,10 @@ allocate_dynrel_entries (dyn_i, data)
          if (!dynamic_symbol)
            count *= 2;
          break;
+       case R_IA64_TPREL64LSB:
+       case R_IA64_DTPREL64LSB:
+       case R_IA64_DTPMOD64LSB:
+         break;
        default:
          abort ();
        }
@@ -2493,6 +2696,12 @@ allocate_dynrel_entries (dyn_i, data)
   if (((dynamic_symbol || shared) && dyn_i->want_got)
       || (dyn_i->want_ltoff_fptr && dyn_i->h && dyn_i->h->dynindx != -1))
     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 || shared) && 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 (dyn_i->want_pltoff)
     {
@@ -2803,7 +3012,11 @@ elfNN_ia64_install_value (abfd, hit_addr, v, r_type)
 
       /* Instruction relocations.  */
 
-    case R_IA64_IMM14:         opnd = IA64_OPND_IMM14; break;
+    case R_IA64_IMM14:
+    case R_IA64_TPREL14:
+    case R_IA64_DTPREL14:
+      opnd = IA64_OPND_IMM14;
+      break;
 
     case R_IA64_PCREL21F:      opnd = IA64_OPND_TGT25; break;
     case R_IA64_PCREL21M:      opnd = IA64_OPND_TGT25b; break;
@@ -2820,6 +3033,11 @@ elfNN_ia64_install_value (abfd, hit_addr, v, r_type)
     case R_IA64_PLTOFF22:
     case R_IA64_PCREL22:
     case R_IA64_LTOFF_FPTR22:
+    case R_IA64_TPREL22:
+    case R_IA64_DTPREL22:
+    case R_IA64_LTOFF_TPREL22:
+    case R_IA64_LTOFF_DTPMOD22:
+    case R_IA64_LTOFF_DTPREL22:
       opnd = IA64_OPND_IMM22;
       break;
 
@@ -2830,6 +3048,8 @@ elfNN_ia64_install_value (abfd, hit_addr, v, r_type)
     case R_IA64_PCREL64I:
     case R_IA64_FPTR64I:
     case R_IA64_LTOFF_FPTR64I:
+    case R_IA64_TPREL64I:
+    case R_IA64_DTPREL64I:
       opnd = IA64_OPND_IMMU64;
       break;
 
@@ -2843,6 +3063,7 @@ elfNN_ia64_install_value (abfd, hit_addr, v, r_type)
     case R_IA64_SEGREL32MSB:
     case R_IA64_SECREL32MSB:
     case R_IA64_LTV32MSB:
+    case R_IA64_DTPREL32MSB:
       size = 4; bigendian = 1;
       break;
 
@@ -2854,6 +3075,7 @@ elfNN_ia64_install_value (abfd, hit_addr, v, r_type)
     case R_IA64_SEGREL32LSB:
     case R_IA64_SECREL32LSB:
     case R_IA64_LTV32LSB:
+    case R_IA64_DTPREL32LSB:
       size = 4; bigendian = 0;
       break;
 
@@ -2866,6 +3088,9 @@ elfNN_ia64_install_value (abfd, hit_addr, v, r_type)
     case R_IA64_SEGREL64MSB:
     case R_IA64_SECREL64MSB:
     case R_IA64_LTV64MSB:
+    case R_IA64_TPREL64MSB:
+    case R_IA64_DTPMOD64MSB:
+    case R_IA64_DTPREL64MSB:
       size = 8; bigendian = 1;
       break;
 
@@ -2878,6 +3103,9 @@ elfNN_ia64_install_value (abfd, hit_addr, v, r_type)
     case R_IA64_SEGREL64LSB:
     case R_IA64_SECREL64LSB:
     case R_IA64_LTV64LSB:
+    case R_IA64_TPREL64LSB:
+    case R_IA64_DTPMOD64LSB:
+    case R_IA64_DTPREL64LSB:
       size = 8; bigendian = 0;
       break;
 
@@ -2995,33 +3223,19 @@ elfNN_ia64_install_dyn_reloc (abfd, info, sec, srel, offset, type,
 {
   Elf_Internal_Rela outrel;
 
-  outrel.r_offset = (sec->output_section->vma
-                    + sec->output_offset
-                    + offset);
+  offset += sec->output_section->vma + sec->output_offset;
 
   BFD_ASSERT (dynindx != -1);
   outrel.r_info = ELFNN_R_INFO (dynindx, type);
   outrel.r_addend = addend;
-
-  if (elf_section_data (sec)->stab_info != NULL)
+  outrel.r_offset = _bfd_elf_section_offset (abfd, info, sec, offset);
+  if ((outrel.r_offset | 1) == (bfd_vma) -1)
     {
-      /* This may be NULL for linker-generated relocations, as it is
-        inconvenient to pass all the bits around.  And this shouldn't
-        happen.  */
-      BFD_ASSERT (info != NULL);
-
-      offset = (_bfd_stab_section_offset
-               (abfd, &elf_hash_table (info)->stab_info, sec,
-                &elf_section_data (sec)->stab_info, offset));
-      if (offset == (bfd_vma) -1)
-       {
-         /* Run for the hills.  We shouldn't be outputting a relocation
-            for this.  So do what everyone else does and output a no-op.  */
-         outrel.r_info = ELFNN_R_INFO (0, R_IA64_NONE);
-         outrel.r_addend = 0;
-         offset = 0;
-       }
-      outrel.r_offset = offset;
+      /* Run for the hills.  We shouldn't be outputting a relocation
+        for this.  So do what everyone else does and output a no-op.  */
+      outrel.r_info = ELFNN_R_INFO (0, R_IA64_NONE);
+      outrel.r_addend = 0;
+      outrel.r_offset = 0;
     }
 
   bfd_elfNN_swap_reloca_out (abfd, &outrel,
@@ -3046,26 +3260,53 @@ set_got_entry (abfd, info, dyn_i, dynindx, addend, value, dyn_r_type)
 {
   struct elfNN_ia64_link_hash_table *ia64_info;
   asection *got_sec;
+  boolean done;
+  bfd_vma got_offset;
 
   ia64_info = elfNN_ia64_hash_table (info);
   got_sec = ia64_info->got_sec;
 
-  BFD_ASSERT ((dyn_i->got_offset & 7) == 0);
-
-  if (! dyn_i->got_done)
+  switch (dyn_r_type)
     {
+    case R_IA64_TPREL64LSB:
+      done = dyn_i->tprel_done;
+      dyn_i->tprel_done = true;
+      got_offset = dyn_i->tprel_offset;
+      break;
+    case R_IA64_DTPMOD64LSB:
+      done = dyn_i->dtpmod_done;
+      dyn_i->dtpmod_done = true;
+      got_offset = dyn_i->dtpmod_offset;
+      break;
+    case R_IA64_DTPREL64LSB:
+      done = dyn_i->dtprel_done;
+      dyn_i->dtprel_done = true;
+      got_offset = dyn_i->dtprel_offset;
+      break;
+    default:
+      done = dyn_i->got_done;
       dyn_i->got_done = true;
+      got_offset = dyn_i->got_offset;
+      break;
+    }
 
+  BFD_ASSERT ((got_offset & 7) == 0);
+
+  if (! done)
+    {
       /* Store the target address in the linkage table entry.  */
-      bfd_put_64 (abfd, value, got_sec->contents + dyn_i->got_offset);
+      bfd_put_64 (abfd, value, got_sec->contents + got_offset);
 
       /* Install a dynamic relocation if needed.  */
-      if (info->shared
+      if ((info->shared && dyn_r_type != R_IA64_DTPREL64LSB)
           || elfNN_ia64_dynamic_symbol_p (dyn_i->h, info)
          || elfNN_ia64_aix_vec (abfd->xvec)
          || (dynindx != -1 && dyn_r_type == R_IA64_FPTR64LSB))
        {
-         if (dynindx == -1)
+         if (dynindx == -1
+             && dyn_r_type != R_IA64_TPREL64LSB
+             && dyn_r_type != R_IA64_DTPMOD64LSB
+             && dyn_r_type != R_IA64_DTPREL64LSB)
            {
              dyn_r_type = R_IA64_REL64LSB;
              dynindx = 0;
@@ -3085,6 +3326,15 @@ set_got_entry (abfd, info, dyn_i, dynindx, addend, value, dyn_r_type)
                case R_IA64_FPTR64LSB:
                  dyn_r_type = R_IA64_FPTR64MSB;
                  break;
+               case R_IA64_TPREL64LSB:
+                 dyn_r_type = R_IA64_TPREL64MSB;
+                 break;
+               case R_IA64_DTPMOD64LSB:
+                 dyn_r_type = R_IA64_DTPMOD64MSB;
+                 break;
+               case R_IA64_DTPREL64LSB:
+                 dyn_r_type = R_IA64_DTPREL64MSB;
+                 break;
                default:
                  BFD_ASSERT (false);
                  break;
@@ -3093,7 +3343,7 @@ set_got_entry (abfd, info, dyn_i, dynindx, addend, value, dyn_r_type)
 
          elfNN_ia64_install_dyn_reloc (abfd, NULL, got_sec,
                                        ia64_info->rel_got_sec,
-                                       dyn_i->got_offset, dyn_r_type,
+                                       got_offset, dyn_r_type,
                                        dynindx, addend);
        }
     }
@@ -3101,7 +3351,7 @@ set_got_entry (abfd, info, dyn_i, dynindx, addend, value, dyn_r_type)
   /* Return the address of the linkage table entry.  */
   value = (got_sec->output_section->vma
           + got_sec->output_offset
-          + dyn_i->got_offset);
+          + got_offset);
 
   return value;
 }
@@ -3199,6 +3449,35 @@ set_pltoff_entry (abfd, info, dyn_i, value, is_plt)
   return value;
 }
 
+/* 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).  */
+
+static bfd_vma
+elfNN_ia64_tprel_base (info)
+     struct bfd_link_info *info;
+{
+  struct elf_link_tls_segment *tls_segment
+    = elf_hash_table (info)->tls_segment;
+
+  BFD_ASSERT (tls_segment != NULL);
+  return (tls_segment->start
+         - align_power ((bfd_vma) 16, tls_segment->align));
+}
+
+/* Return the base VMA address which should be subtracted from real addresses
+   when resolving @dtprel() relocation.
+   This is PT_TLS segment p_vaddr.  */
+
+static bfd_vma
+elfNN_ia64_dtprel_base (info)
+     struct bfd_link_info *info;
+{
+  BFD_ASSERT (elf_hash_table (info)->tls_segment != NULL);
+  return elf_hash_table (info)->tls_segment->start;
+}
+
 /* Called through qsort to sort the .IA_64.unwind section during a
    non-relocatable link.  Set elfNN_ia64_unwind_entry_compare_bfd
    to the output bfd so we can do proper endianness frobbing.  */
@@ -3416,6 +3695,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
 
       elf_section_data(input_section->output_section)
        ->this_hdr.sh_flags |= flags;
+      return true;
     }
 
   gp_val = _bfd_get_gp_value (output_bfd);
@@ -3448,29 +3728,9 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
          ret_val = false;
          continue;
        }
+
       howto = lookup_howto (r_type);
       r_symndx = ELFNN_R_SYM (rel->r_info);
-
-      if (info->relocateable)
-       {
-         /* This is a relocateable link.  We don't have to change
-            anything, unless the reloc is against a section symbol,
-            in which case we have to adjust according to where the
-            section symbol winds up in the output section.  */
-         if (r_symndx < symtab_hdr->sh_info)
-           {
-             sym = local_syms + r_symndx;
-             if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
-               {
-                 sym_sec = local_sections[r_symndx];
-                 rel->r_addend += sym_sec->output_offset;
-               }
-           }
-         continue;
-       }
-
-      /* This is a final link.  */
-
       h = NULL;
       sym = NULL;
       sym_sec = NULL;
@@ -3481,9 +3741,39 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
          /* Reloc against local symbol.  */
          sym = local_syms + r_symndx;
          sym_sec = local_sections[r_symndx];
-         value  = (sym_sec->output_section->vma
-                   + sym_sec->output_offset
-                   + sym->st_value);
+         value = _bfd_elf_rela_local_sym (output_bfd, sym, sym_sec, rel);
+         if ((sym_sec->flags & SEC_MERGE)
+             && ELF_ST_TYPE (sym->st_info) == STT_SECTION
+             && (elf_section_data (sym_sec)->sec_info_type
+                 == ELF_INFO_TYPE_MERGE))
+           {
+             struct elfNN_ia64_local_hash_entry *loc_h;
+      
+             loc_h = get_local_sym_hash (ia64_info, input_bfd, rel, false);
+             if (loc_h && ! loc_h->sec_merge_done)
+               {
+                 struct elfNN_ia64_dyn_sym_info *dynent;
+                 asection *msec;
+
+                 for (dynent = loc_h->info; dynent; dynent = dynent->next)
+                   {
+                     msec = sym_sec;
+                     dynent->addend =
+                       _bfd_merged_section_offset (output_bfd, &msec,
+                                                   elf_section_data (msec)->
+                                                   sec_info,
+                                                   sym->st_value
+                                                   + dynent->addend,
+                                                   (bfd_vma) 0);
+                     dynent->addend -= sym->st_value;
+                     dynent->addend += msec->output_section->vma
+                                       + msec->output_offset
+                                       - sym_sec->output_section->vma
+                                       - sym_sec->output_offset;
+                   }
+                 loc_h->sec_merge_done = 1;
+               }
+           }
        }
       else
        {
@@ -3933,6 +4223,55 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
                                        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);
+         break;
+
+       case R_IA64_DTPREL14:
+       case R_IA64_DTPREL22:
+       case R_IA64_DTPREL64I:
+         value -= elfNN_ia64_dtprel_base (info);
+         r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
+         break;
+
+       case R_IA64_LTOFF_TPREL22:
+       case R_IA64_LTOFF_DTPMOD22:
+       case R_IA64_LTOFF_DTPREL22:
+         {
+           int got_r_type;
+
+           switch (r_type)
+             {
+             default:
+             case R_IA64_LTOFF_TPREL22:
+               if (!dynamic_symbol_p && !info->shared)
+                 value -= elfNN_ia64_tprel_base (info);
+               got_r_type = R_IA64_TPREL64LSB;
+               break;
+             case R_IA64_LTOFF_DTPMOD22:
+               if (!dynamic_symbol_p && !info->shared)
+                 value = 1;
+               got_r_type = R_IA64_DTPMOD64LSB;
+               break;
+             case R_IA64_LTOFF_DTPREL22:
+               if (!dynamic_symbol_p)
+                 value -= elfNN_ia64_dtprel_base (info);
+               got_r_type = R_IA64_DTPREL64LSB;
+               break;
+             }
+           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, got_r_type);
+           value -= gp_val;
+           r = elfNN_ia64_install_value (output_bfd, hit_addr, value,
+                                         r_type);
+         }
+         break;
+
        default:
          r = bfd_reloc_notsupported;
          break;
@@ -4203,24 +4542,6 @@ elfNN_ia64_set_private_flags (abfd, flags)
   return true;
 }
 
-/* Copy backend specific data from one object module to another */
-static boolean
-elfNN_ia64_copy_private_bfd_data (ibfd, obfd)
-     bfd *ibfd, *obfd;
-{
-  if (   bfd_get_flavour (ibfd) != bfd_target_elf_flavour
-      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
-    return true;
-
-  BFD_ASSERT (!elf_flags_init (obfd)
-             || (elf_elfheader (obfd)->e_flags
-                 == elf_elfheader (ibfd)->e_flags));
-
-  elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
-  elf_flags_init (obfd) = true;
-  return true;
-}
-
 /* Merge backend specific data from an object file to the output
    object file when linking.  */
 static boolean
@@ -4356,6 +4677,38 @@ elfNN_ia64_reloc_type_class (rela)
       return reloc_class_normal;
     }
 }
+
+static boolean
+elfNN_ia64_hpux_vec (const bfd_target *vec)
+{
+  extern const bfd_target bfd_elfNN_ia64_hpux_big_vec;
+  return (vec == & bfd_elfNN_ia64_hpux_big_vec);
+}
+
+static void
+elfNN_hpux_post_process_headers (abfd, info)
+       bfd *abfd;
+       struct bfd_link_info *info ATTRIBUTE_UNUSED;
+{
+  Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd);
+
+  i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_HPUX;
+  i_ehdrp->e_ident[EI_ABIVERSION] = 1;
+}
+
+boolean
+elfNN_hpux_backend_section_from_bfd_section (abfd, sec, retval)
+       bfd *abfd ATTRIBUTE_UNUSED;
+       asection *sec;
+       int *retval;
+{
+  if (bfd_is_com_section (sec))
+    {
+      *retval = SHN_IA_64_ANSI_COMMON;
+      return true;
+    }
+  return false;
+}
 \f
 #define TARGET_LITTLE_SYM              bfd_elfNN_ia64_little_vec
 #define TARGET_LITTLE_NAME             "elfNN-ia64-little"
@@ -4411,8 +4764,6 @@ elfNN_ia64_reloc_type_class (rela)
 #define bfd_elfNN_bfd_final_link \
        elfNN_ia64_final_link
 
-#define bfd_elfNN_bfd_copy_private_bfd_data \
-       elfNN_ia64_copy_private_bfd_data
 #define bfd_elfNN_bfd_merge_private_bfd_data \
        elfNN_ia64_merge_private_bfd_data
 #define bfd_elfNN_bfd_set_private_flags \
@@ -4433,6 +4784,7 @@ elfNN_ia64_reloc_type_class (rela)
 #define elf_backend_copy_indirect_symbol elfNN_ia64_hash_copy_indirect
 #define elf_backend_hide_symbol                elfNN_ia64_hash_hide_symbol
 #define elf_backend_reloc_type_class   elfNN_ia64_reloc_type_class
+#define elf_backend_rela_normal                1
 
 #include "elfNN-target.h"
 
@@ -4456,3 +4808,36 @@ elfNN_ia64_reloc_type_class (rela)
 #define elfNN_bed elfNN_ia64_aix_bed
 
 #include "elfNN-target.h"
+
+/* HPUX-specific vectors.  */
+
+#undef  TARGET_LITTLE_SYM
+#undef  TARGET_LITTLE_NAME
+#undef  TARGET_BIG_SYM
+#define TARGET_BIG_SYM                  bfd_elfNN_ia64_hpux_big_vec
+#undef  TARGET_BIG_NAME
+#define TARGET_BIG_NAME                 "elfNN-ia64-hpux-big"
+
+/* We need to undo the AIX specific functions.  */
+
+#undef  elf_backend_add_symbol_hook
+#define elf_backend_add_symbol_hook    elfNN_ia64_add_symbol_hook
+
+#undef  bfd_elfNN_bfd_link_add_symbols
+#define bfd_elfNN_bfd_link_add_symbols _bfd_generic_link_add_symbols
+
+/* These are HP-UX specific functions.  */
+
+#undef  elf_backend_post_process_headers
+#define elf_backend_post_process_headers elfNN_hpux_post_process_headers
+
+#undef  elf_backend_section_from_bfd_section
+#define elf_backend_section_from_bfd_section elfNN_hpux_backend_section_from_bfd_section
+
+#undef  ELF_MAXPAGESIZE
+#define ELF_MAXPAGESIZE                 0x1000  /* 1K */
+
+#undef  elfNN_bed
+#define elfNN_bed elfNN_ia64_hpux_bed
+
+#include "elfNN-target.h"
This page took 0.060115 seconds and 4 git commands to generate.