2008-11-20 Tristan Gingold <gingold@adacore.com>
[binutils-gdb.git] / bfd / elfxx-ia64.c
index 6b3257afdf133e75858c64d4c5b99628b7d26c58..d662c7498cc0cf2bf507e10e0eec2eadad20927e 100644 (file)
@@ -1,5 +1,5 @@
 /* IA-64 support for 64-bit ELF
 /* IA-64 support for 64-bit ELF
-   Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
    Free Software Foundation, Inc.
    Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
 
    Free Software Foundation, Inc.
    Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
 
@@ -7,7 +7,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
 
    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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
 
 
-#include "bfd.h"
 #include "sysdep.h"
 #include "sysdep.h"
+#include "bfd.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
 #include "opcode/ia64.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
 #include "opcode/ia64.h"
@@ -189,176 +190,45 @@ struct elfNN_ia64_allocate_data
 #define elfNN_ia64_hash_table(p) \
   ((struct elfNN_ia64_link_hash_table *) ((p)->hash))
 
 #define elfNN_ia64_hash_table(p) \
   ((struct elfNN_ia64_link_hash_table *) ((p)->hash))
 
-static bfd_reloc_status_type elfNN_ia64_reloc
-  PARAMS ((bfd *abfd, arelent *reloc, asymbol *sym, PTR data,
-          asection *input_section, bfd *output_bfd, char **error_message));
-static reloc_howto_type * lookup_howto
-  PARAMS ((unsigned int rtype));
-static reloc_howto_type *elfNN_ia64_reloc_type_lookup
-  PARAMS ((bfd *abfd, bfd_reloc_code_real_type bfd_code));
-static void elfNN_ia64_info_to_howto
-  PARAMS ((bfd *abfd, arelent *bfd_reloc, Elf_Internal_Rela *elf_reloc));
-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_byte *contents, bfd_vma off));
-static bfd_boolean is_unwind_section_name
-  PARAMS ((bfd *abfd, const char *));
-static bfd_boolean elfNN_ia64_section_flags
-  PARAMS ((flagword *, const Elf_Internal_Shdr *));
-static bfd_boolean elfNN_ia64_fake_sections
-  PARAMS ((bfd *abfd, Elf_Internal_Shdr *hdr, asection *sec));
-static void elfNN_ia64_final_write_processing
-  PARAMS ((bfd *abfd, bfd_boolean linker));
-static bfd_boolean elfNN_ia64_add_symbol_hook
-  PARAMS ((bfd *abfd, struct bfd_link_info *info, Elf_Internal_Sym *sym,
-          const char **namep, flagword *flagsp, asection **secp,
-          bfd_vma *valp));
-static int elfNN_ia64_additional_program_headers
-  PARAMS ((bfd *abfd));
-static bfd_boolean elfNN_ia64_modify_segment_map
-  PARAMS ((bfd *, struct bfd_link_info *));
-static bfd_boolean elfNN_ia64_is_local_label_name
-  PARAMS ((bfd *abfd, const char *name));
+static struct elfNN_ia64_dyn_sym_info * get_dyn_sym_info
+  (struct elfNN_ia64_link_hash_table *ia64_info,
+   struct elf_link_hash_entry *h,
+   bfd *abfd, const Elf_Internal_Rela *rel, bfd_boolean create);
 static bfd_boolean elfNN_ia64_dynamic_symbol_p
 static bfd_boolean elfNN_ia64_dynamic_symbol_p
-  PARAMS ((struct elf_link_hash_entry *h, struct bfd_link_info *info, int));
-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 ((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));
-static hashval_t elfNN_ia64_local_htab_hash PARAMS ((const void *));
-static int elfNN_ia64_local_htab_eq PARAMS ((const void *ptr1,
-                                            const void *ptr2));
-static struct bfd_link_hash_table *elfNN_ia64_hash_table_create
-  PARAMS ((bfd *abfd));
-static void elfNN_ia64_hash_table_free
-  PARAMS ((struct bfd_link_hash_table *hash));
-static bfd_boolean elfNN_ia64_global_dyn_sym_thunk
-  PARAMS ((struct bfd_hash_entry *, PTR));
-static int elfNN_ia64_local_dyn_sym_thunk
-  PARAMS ((void **, PTR));
+  (struct elf_link_hash_entry *h, struct bfd_link_info *info, int);
+static bfd_reloc_status_type elfNN_ia64_install_value
+  (bfd_byte *hit_addr, bfd_vma val, unsigned int r_type);
+static bfd_boolean elfNN_ia64_choose_gp
+  (bfd *abfd, struct bfd_link_info *info);
+static void elfNN_ia64_relax_ldxmov
+  (bfd_byte *contents, bfd_vma off);
 static void elfNN_ia64_dyn_sym_traverse
 static void elfNN_ia64_dyn_sym_traverse
-  PARAMS ((struct elfNN_ia64_link_hash_table *ia64_info,
-          bfd_boolean (*func) (struct elfNN_ia64_dyn_sym_info *, PTR),
-          PTR info));
-static bfd_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, bfd_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,
-          bfd *abfd, const Elf_Internal_Rela *rel, bfd_boolean create));
-static asection *get_got
-  PARAMS ((bfd *abfd, struct bfd_link_info *info,
-          struct elfNN_ia64_link_hash_table *ia64_info));
-static asection *get_fptr
-  PARAMS ((bfd *abfd, struct bfd_link_info *info,
-          struct elfNN_ia64_link_hash_table *ia64_info));
-static asection *get_pltoff
-  PARAMS ((bfd *abfd, struct bfd_link_info *info,
-          struct elfNN_ia64_link_hash_table *ia64_info));
-static asection *get_reloc_section
-  PARAMS ((bfd *abfd, struct elfNN_ia64_link_hash_table *ia64_info,
-          asection *sec, bfd_boolean create));
-static bfd_boolean elfNN_ia64_check_relocs
-  PARAMS ((bfd *abfd, struct bfd_link_info *info, asection *sec,
-          const Elf_Internal_Rela *relocs));
-static bfd_boolean elfNN_ia64_adjust_dynamic_symbol
-  PARAMS ((struct bfd_link_info *info, struct elf_link_hash_entry *h));
-static long global_sym_index
-  PARAMS ((struct elf_link_hash_entry *h));
-static bfd_boolean allocate_fptr
-  PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
+  (struct elfNN_ia64_link_hash_table *ia64_info,
+   bfd_boolean (*func) (struct elfNN_ia64_dyn_sym_info *, PTR),
+   PTR info);
 static bfd_boolean allocate_global_data_got
 static bfd_boolean allocate_global_data_got
-  PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
+  (struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data);
 static bfd_boolean allocate_global_fptr_got
 static bfd_boolean allocate_global_fptr_got
-  PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
+  (struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data);
 static bfd_boolean allocate_local_got
 static bfd_boolean allocate_local_got
-  PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
-static bfd_boolean allocate_pltoff_entries
-  PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
-static bfd_boolean allocate_plt_entries
-  PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
-static bfd_boolean allocate_plt2_entries
-  PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
-static bfd_boolean allocate_dynrel_entries
-  PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
-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_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,
-          long dynindx, bfd_vma addend));
-static bfd_vma set_got_entry
-  PARAMS ((bfd *abfd, struct bfd_link_info *info,
-          struct elfNN_ia64_dyn_sym_info *dyn_i, long dynindx,
-          bfd_vma addend, bfd_vma value, unsigned int dyn_r_type));
-static bfd_vma set_fptr_entry
-  PARAMS ((bfd *abfd, struct bfd_link_info *info,
-          struct elfNN_ia64_dyn_sym_info *dyn_i,
-          bfd_vma value));
-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, bfd_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 bfd_boolean elfNN_ia64_choose_gp
-  PARAMS ((bfd *abfd, struct bfd_link_info *info));
-static bfd_boolean elfNN_ia64_final_link
-  PARAMS ((bfd *abfd, struct bfd_link_info *info));
-static bfd_boolean elfNN_ia64_relocate_section
-  PARAMS ((bfd *output_bfd, struct bfd_link_info *info, bfd *input_bfd,
-          asection *input_section, bfd_byte *contents,
-          Elf_Internal_Rela *relocs, Elf_Internal_Sym *local_syms,
-          asection **local_sections));
-static bfd_boolean elfNN_ia64_finish_dynamic_symbol
-  PARAMS ((bfd *output_bfd, struct bfd_link_info *info,
-          struct elf_link_hash_entry *h, Elf_Internal_Sym *sym));
-static bfd_boolean elfNN_ia64_finish_dynamic_sections
-  PARAMS ((bfd *abfd, struct bfd_link_info *info));
-static bfd_boolean elfNN_ia64_set_private_flags
-  PARAMS ((bfd *abfd, flagword flags));
-static bfd_boolean elfNN_ia64_merge_private_bfd_data
-  PARAMS ((bfd *ibfd, bfd *obfd));
-static bfd_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 *));
+  (struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data);
 static bfd_boolean elfNN_ia64_hpux_vec
 static bfd_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));
-bfd_boolean elfNN_hpux_backend_section_from_bfd_section
-  PARAMS ((bfd *abfd, asection *sec, int *retval));
+  (const bfd_target *vec);
+static bfd_boolean allocate_dynrel_entries
+  (struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data);
+static asection *get_pltoff
+  (bfd *abfd, struct bfd_link_info *info,
+   struct elfNN_ia64_link_hash_table *ia64_info);
 \f
 /* ia64-specific relocation.  */
 
 /* Perform a relocation.  Not much to do here as all the hard work is
    done in elfNN_ia64_final_link_relocate.  */
 static bfd_reloc_status_type
 \f
 /* ia64-specific relocation.  */
 
 /* Perform a relocation.  Not much to do here as all the hard work is
    done in elfNN_ia64_final_link_relocate.  */
 static bfd_reloc_status_type
-elfNN_ia64_reloc (abfd, reloc, sym, data, input_section,
-                 output_bfd, error_message)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     arelent *reloc;
-     asymbol *sym ATTRIBUTE_UNUSED;
-     PTR data ATTRIBUTE_UNUSED;
-     asection *input_section;
-     bfd *output_bfd;
-     char **error_message;
+elfNN_ia64_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc,
+                 asymbol *sym ATTRIBUTE_UNUSED,
+                 PTR data ATTRIBUTE_UNUSED, asection *input_section,
+                 bfd *output_bfd, char **error_message)
 {
   if (output_bfd)
     {
 {
   if (output_bfd)
     {
@@ -484,8 +354,7 @@ static unsigned char elf_code_to_howto_index[R_IA64_MAX_RELOC_CODE + 1];
 /* Given a BFD reloc type, return the matching HOWTO structure.  */
 
 static reloc_howto_type *
 /* Given a BFD reloc type, return the matching HOWTO structure.  */
 
 static reloc_howto_type *
-lookup_howto (rtype)
-     unsigned int rtype;
+lookup_howto (unsigned int rtype)
 {
   static int inited = 0;
   int i;
 {
   static int inited = 0;
   int i;
@@ -508,9 +377,8 @@ lookup_howto (rtype)
 }
 
 static reloc_howto_type*
 }
 
 static reloc_howto_type*
-elfNN_ia64_reloc_type_lookup (abfd, bfd_code)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     bfd_reloc_code_real_type bfd_code;
+elfNN_ia64_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+                             bfd_reloc_code_real_type bfd_code)
 {
   unsigned int rtype;
 
 {
   unsigned int rtype;
 
@@ -617,13 +485,28 @@ elfNN_ia64_reloc_type_lookup (abfd, bfd_code)
   return lookup_howto (rtype);
 }
 
   return lookup_howto (rtype);
 }
 
+static reloc_howto_type *
+elfNN_ia64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+                             const char *r_name)
+{
+  unsigned int i;
+
+  for (i = 0;
+       i < sizeof (ia64_howto_table) / sizeof (ia64_howto_table[0]);
+       i++)
+    if (ia64_howto_table[i].name != NULL
+       && strcasecmp (ia64_howto_table[i].name, r_name) == 0)
+      return &ia64_howto_table[i];
+
+  return NULL;
+}
+
 /* Given a ELF reloc, return the matching HOWTO structure.  */
 
 static void
 /* Given a ELF reloc, return the matching HOWTO structure.  */
 
 static void
-elfNN_ia64_info_to_howto (abfd, bfd_reloc, elf_reloc)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     arelent *bfd_reloc;
-     Elf_Internal_Rela *elf_reloc;
+elfNN_ia64_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
+                         arelent *bfd_reloc,
+                         Elf_Internal_Rela *elf_reloc)
 {
   bfd_reloc->howto
     = lookup_howto ((unsigned int) ELFNN_R_TYPE (elf_reloc->r_info));
 {
   bfd_reloc->howto
     = lookup_howto ((unsigned int) ELFNN_R_TYPE (elf_reloc->r_info));
@@ -791,7 +674,7 @@ elfNN_ia64_relax_br (bfd_byte *contents, bfd_vma off)
       /* It should never happen.  */
       abort ();
     }
       /* 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;
   /* 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;
@@ -873,11 +756,9 @@ elfNN_ia64_relax_brl (bfd_byte *contents, bfd_vma off)
 /* These functions do relaxation for IA-64 ELF.  */
 
 static bfd_boolean
 /* These functions do relaxation for IA-64 ELF.  */
 
 static bfd_boolean
-elfNN_ia64_relax_section (abfd, sec, link_info, again)
-     bfd *abfd;
-     asection *sec;
-     struct bfd_link_info *link_info;
-     bfd_boolean *again;
+elfNN_ia64_relax_section (bfd *abfd, asection *sec,
+                         struct bfd_link_info *link_info,
+                         bfd_boolean *again)
 {
   struct one_fixup
     {
 {
   struct one_fixup
     {
@@ -1394,9 +1275,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
 #undef skip_relax_pass_1
 
 static void
 #undef skip_relax_pass_1
 
 static void
-elfNN_ia64_relax_ldxmov (contents, off)
-     bfd_byte *contents;
-     bfd_vma off;
+elfNN_ia64_relax_ldxmov (bfd_byte *contents, bfd_vma off)
 {
   int shift, r1, r3;
   bfd_vma dword, insn;
 {
   int shift, r1, r3;
   bfd_vma dword, insn;
@@ -1428,22 +1307,15 @@ elfNN_ia64_relax_ldxmov (contents, off)
 /* Return TRUE if NAME is an unwind table section name.  */
 
 static inline bfd_boolean
 /* Return TRUE if NAME is an unwind table section name.  */
 
 static inline bfd_boolean
-is_unwind_section_name (abfd, name)
-       bfd *abfd;
-       const char *name;
+is_unwind_section_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;
 
   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;
-  return ((strncmp (name, ELF_STRING_ia64_unwind, len1) == 0
-          && strncmp (name, ELF_STRING_ia64_unwind_info, len2) != 0)
-         || strncmp (name, ELF_STRING_ia64_unwind_once, len3) == 0);
+  return ((CONST_STRNEQ (name, ELF_STRING_ia64_unwind)
+          && ! CONST_STRNEQ (name, ELF_STRING_ia64_unwind_info))
+         || CONST_STRNEQ (name, ELF_STRING_ia64_unwind_once));
 }
 
 /* Handle an IA-64 specific section when reading an object file.  This
 }
 
 /* Handle an IA-64 specific section when reading an object file.  This
@@ -1491,9 +1363,8 @@ elfNN_ia64_section_from_shdr (bfd *abfd,
    flag.  */
 
 static bfd_boolean
    flag.  */
 
 static bfd_boolean
-elfNN_ia64_section_flags (flags, hdr)
-     flagword *flags;
-     const Elf_Internal_Shdr *hdr;
+elfNN_ia64_section_flags (flagword *flags,
+                         const Elf_Internal_Shdr *hdr)
 {
   if (hdr->sh_flags & SHF_IA_64_SHORT)
     *flags |= SEC_SMALL_DATA;
 {
   if (hdr->sh_flags & SHF_IA_64_SHORT)
     *flags |= SEC_SMALL_DATA;
@@ -1505,10 +1376,8 @@ elfNN_ia64_section_flags (flags, hdr)
    section name, which is a hack, but ought to work.  */
 
 static bfd_boolean
    section name, which is a hack, but ought to work.  */
 
 static bfd_boolean
-elfNN_ia64_fake_sections (abfd, hdr, sec)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     Elf_Internal_Shdr *hdr;
-     asection *sec;
+elfNN_ia64_fake_sections (bfd *abfd, Elf_Internal_Shdr *hdr,
+                         asection *sec)
 {
   register const char *name;
 
 {
   register const char *name;
 
@@ -1559,9 +1428,8 @@ elfNN_ia64_fake_sections (abfd, hdr, sec)
    object file.  */
 
 static void
    object file.  */
 
 static void
-elfNN_ia64_final_write_processing (abfd, linker)
-     bfd *abfd;
-     bfd_boolean linker ATTRIBUTE_UNUSED;
+elfNN_ia64_final_write_processing (bfd *abfd,
+                                  bfd_boolean linker ATTRIBUTE_UNUSED)
 {
   Elf_Internal_Shdr *hdr;
   asection *s;
 {
   Elf_Internal_Shdr *hdr;
   asection *s;
@@ -1599,14 +1467,13 @@ elfNN_ia64_final_write_processing (abfd, linker)
    file.  We use it to put .comm items in .sbss, and not .bss.  */
 
 static bfd_boolean
    file.  We use it to put .comm items in .sbss, and not .bss.  */
 
 static bfd_boolean
-elfNN_ia64_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     Elf_Internal_Sym *sym;
-     const char **namep ATTRIBUTE_UNUSED;
-     flagword *flagsp ATTRIBUTE_UNUSED;
-     asection **secp;
-     bfd_vma *valp;
+elfNN_ia64_add_symbol_hook (bfd *abfd,
+                           struct bfd_link_info *info,
+                           Elf_Internal_Sym *sym,
+                           const char **namep ATTRIBUTE_UNUSED,
+                           flagword *flagsp ATTRIBUTE_UNUSED,
+                           asection **secp,
+                           bfd_vma *valp)
 {
   if (sym->st_shndx == SHN_COMMON
       && !info->relocatable
 {
   if (sym->st_shndx == SHN_COMMON
       && !info->relocatable
@@ -1637,8 +1504,8 @@ elfNN_ia64_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
 /* Return the number of additional phdrs we will need.  */
 
 static int
 /* Return the number of additional phdrs we will need.  */
 
 static int
-elfNN_ia64_additional_program_headers (abfd)
-     bfd *abfd;
+elfNN_ia64_additional_program_headers (bfd *abfd,
+                                      struct bfd_link_info *info ATTRIBUTE_UNUSED)
 {
   asection *s;
   int ret = 0;
 {
   asection *s;
   int ret = 0;
@@ -1657,9 +1524,8 @@ elfNN_ia64_additional_program_headers (abfd)
 }
 
 static bfd_boolean
 }
 
 static bfd_boolean
-elfNN_ia64_modify_segment_map (abfd, info)
-     bfd *abfd;
-     struct bfd_link_info *info ATTRIBUTE_UNUSED;
+elfNN_ia64_modify_segment_map (bfd *abfd,
+                              struct bfd_link_info *info ATTRIBUTE_UNUSED)
 {
   struct elf_segment_map *m, **pm;
   Elf_Internal_Shdr *hdr;
 {
   struct elf_segment_map *m, **pm;
   Elf_Internal_Shdr *hdr;
@@ -1742,17 +1608,30 @@ elfNN_ia64_modify_segment_map (abfd, info)
        }
     }
 
        }
     }
 
-  /* Turn on PF_IA_64_NORECOV if needed.  This involves traversing all of
-     the input sections for each output section in the segment and testing
-     for SHF_IA_64_NORECOV on each.  */
-  for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
+  return TRUE;
+}
+
+/* Turn on PF_IA_64_NORECOV if needed.  This involves traversing all of
+   the input sections for each output section in the segment and testing
+   for SHF_IA_64_NORECOV on each.  */
+
+static bfd_boolean
+elfNN_ia64_modify_program_headers (bfd *abfd,
+                                  struct bfd_link_info *info ATTRIBUTE_UNUSED)
+{
+  struct elf_obj_tdata *tdata = elf_tdata (abfd);
+  struct elf_segment_map *m;
+  Elf_Internal_Phdr *p;
+
+  for (p = tdata->phdr, m = tdata->segment_map; m != NULL; m = m->next, p++)
     if (m->p_type == PT_LOAD)
       {
        int i;
        for (i = m->count - 1; i >= 0; --i)
          {
            struct bfd_link_order *order = m->sections[i]->map_head.link_order;
     if (m->p_type == PT_LOAD)
       {
        int i;
        for (i = m->count - 1; i >= 0; --i)
          {
            struct bfd_link_order *order = m->sections[i]->map_head.link_order;
-           while (order)
+
+           while (order != NULL)
              {
                if (order->type == bfd_indirect_link_order)
                  {
              {
                if (order->type == bfd_indirect_link_order)
                  {
@@ -1760,7 +1639,7 @@ elfNN_ia64_modify_segment_map (abfd, info)
                    bfd_vma flags = elf_section_data(is)->this_hdr.sh_flags;
                    if (flags & SHF_IA_64_NORECOV)
                      {
                    bfd_vma flags = elf_section_data(is)->this_hdr.sh_flags;
                    if (flags & SHF_IA_64_NORECOV)
                      {
-                       m->p_flags |= PF_IA_64_NORECOV;
+                       p->p_flags |= PF_IA_64_NORECOV;
                        goto found;
                      }
                  }
                        goto found;
                      }
                  }
@@ -1777,9 +1656,8 @@ elfNN_ia64_modify_segment_map (abfd, info)
    '.' are local.  */
 
 static bfd_boolean
    '.' are local.  */
 
 static bfd_boolean
-elfNN_ia64_is_local_label_name (abfd, name)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     const char *name;
+elfNN_ia64_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED,
+                               const char *name)
 {
   return name[0] == '.';
 }
 {
   return name[0] == '.';
 }
@@ -1787,10 +1665,8 @@ elfNN_ia64_is_local_label_name (abfd, name)
 /* Should we do dynamic things to this symbol?  */
 
 static bfd_boolean
 /* Should we do dynamic things to this symbol?  */
 
 static bfd_boolean
-elfNN_ia64_dynamic_symbol_p (h, info, r_type)
-     struct elf_link_hash_entry *h;
-     struct bfd_link_info *info;
-     int r_type;
+elfNN_ia64_dynamic_symbol_p (struct elf_link_hash_entry *h,
+                            struct bfd_link_info *info, int r_type)
 {
   bfd_boolean ignore_protected
     = ((r_type & 0xf8) == 0x40         /* FPTR relocs */
 {
   bfd_boolean ignore_protected
     = ((r_type & 0xf8) == 0x40         /* FPTR relocs */
@@ -1800,10 +1676,9 @@ elfNN_ia64_dynamic_symbol_p (h, info, r_type)
 }
 \f
 static struct bfd_hash_entry*
 }
 \f
 static struct bfd_hash_entry*
-elfNN_ia64_new_elf_hash_entry (entry, table, string)
-     struct bfd_hash_entry *entry;
-     struct bfd_hash_table *table;
-     const char *string;
+elfNN_ia64_new_elf_hash_entry (struct bfd_hash_entry *entry,
+                              struct bfd_hash_table *table,
+                              const char *string)
 {
   struct elfNN_ia64_link_hash_entry *ret;
   ret = (struct elfNN_ia64_link_hash_entry *) entry;
 {
   struct elfNN_ia64_link_hash_entry *ret;
   ret = (struct elfNN_ia64_link_hash_entry *) entry;
@@ -1829,9 +1704,9 @@ elfNN_ia64_new_elf_hash_entry (entry, table, string)
 }
 
 static void
 }
 
 static void
-elfNN_ia64_hash_copy_indirect (info, xdir, xind)
-     struct bfd_link_info *info;
-     struct elf_link_hash_entry *xdir, *xind;
+elfNN_ia64_hash_copy_indirect (struct bfd_link_info *info,
+                              struct elf_link_hash_entry *xdir,
+                              struct elf_link_hash_entry *xind)
 {
   struct elfNN_ia64_link_hash_entry *dir, *ind;
 
 {
   struct elfNN_ia64_link_hash_entry *dir, *ind;
 
@@ -1892,10 +1767,9 @@ elfNN_ia64_hash_copy_indirect (info, xdir, xind)
 }
 
 static void
 }
 
 static void
-elfNN_ia64_hash_hide_symbol (info, xh, force_local)
-     struct bfd_link_info *info;
-     struct elf_link_hash_entry *xh;
-     bfd_boolean force_local;
+elfNN_ia64_hash_hide_symbol (struct bfd_link_info *info,
+                            struct elf_link_hash_entry *xh,
+                            bfd_boolean force_local)
 {
   struct elfNN_ia64_link_hash_entry *h;
   struct elfNN_ia64_dyn_sym_info *dyn_i;
 {
   struct elfNN_ia64_link_hash_entry *h;
   struct elfNN_ia64_dyn_sym_info *dyn_i;
@@ -1917,8 +1791,7 @@ elfNN_ia64_hash_hide_symbol (info, xh, force_local)
 /* Compute a hash of a local hash entry.  */
 
 static hashval_t
 /* Compute a hash of a local hash entry.  */
 
 static hashval_t
-elfNN_ia64_local_htab_hash (ptr)
-     const void *ptr;
+elfNN_ia64_local_htab_hash (const void *ptr)
 {
   struct elfNN_ia64_local_hash_entry *entry
     = (struct elfNN_ia64_local_hash_entry *) ptr;
 {
   struct elfNN_ia64_local_hash_entry *entry
     = (struct elfNN_ia64_local_hash_entry *) ptr;
@@ -1930,8 +1803,7 @@ elfNN_ia64_local_htab_hash (ptr)
 /* Compare local hash entries.  */
 
 static int
 /* Compare local hash entries.  */
 
 static int
-elfNN_ia64_local_htab_eq (ptr1, ptr2)
-     const void *ptr1, *ptr2;
+elfNN_ia64_local_htab_eq (const void *ptr1, const void *ptr2)
 {
   struct elfNN_ia64_local_hash_entry *entry1
     = (struct elfNN_ia64_local_hash_entry *) ptr1;
 {
   struct elfNN_ia64_local_hash_entry *entry1
     = (struct elfNN_ia64_local_hash_entry *) ptr1;
@@ -1946,8 +1818,7 @@ elfNN_ia64_local_htab_eq (ptr1, ptr2)
    linker (without using static variables).  */
 
 static struct bfd_link_hash_table*
    linker (without using static variables).  */
 
 static struct bfd_link_hash_table*
-elfNN_ia64_hash_table_create (abfd)
-     bfd *abfd;
+elfNN_ia64_hash_table_create (bfd *abfd)
 {
   struct elfNN_ia64_link_hash_table *ret;
 
 {
   struct elfNN_ia64_link_hash_table *ret;
 
@@ -2023,8 +1894,7 @@ elfNN_ia64_local_dyn_info_free (void **slot,
 /* Destroy IA-64 linker hash table.  */
 
 static void
 /* Destroy IA-64 linker hash table.  */
 
 static void
-elfNN_ia64_hash_table_free (hash)
-     struct bfd_link_hash_table *hash;
+elfNN_ia64_hash_table_free (struct bfd_link_hash_table *hash)
 {
   struct elfNN_ia64_link_hash_table *ia64_info
     = (struct elfNN_ia64_link_hash_table *) hash;
 {
   struct elfNN_ia64_link_hash_table *ia64_info
     = (struct elfNN_ia64_link_hash_table *) hash;
@@ -2045,14 +1915,13 @@ elfNN_ia64_hash_table_free (hash)
 
 struct elfNN_ia64_dyn_sym_traverse_data
 {
 
 struct elfNN_ia64_dyn_sym_traverse_data
 {
-  bfd_boolean (*func) PARAMS ((struct elfNN_ia64_dyn_sym_info *, PTR));
+  bfd_boolean (*func) (struct elfNN_ia64_dyn_sym_info *, PTR);
   PTR data;
 };
 
 static bfd_boolean
   PTR data;
 };
 
 static bfd_boolean
-elfNN_ia64_global_dyn_sym_thunk (xentry, xdata)
-     struct bfd_hash_entry *xentry;
-     PTR xdata;
+elfNN_ia64_global_dyn_sym_thunk (struct bfd_hash_entry *xentry,
+                                PTR xdata)
 {
   struct elfNN_ia64_link_hash_entry *entry
     = (struct elfNN_ia64_link_hash_entry *) xentry;
 {
   struct elfNN_ia64_link_hash_entry *entry
     = (struct elfNN_ia64_link_hash_entry *) xentry;
@@ -2073,9 +1942,7 @@ elfNN_ia64_global_dyn_sym_thunk (xentry, xdata)
 }
 
 static bfd_boolean
 }
 
 static bfd_boolean
-elfNN_ia64_local_dyn_sym_thunk (slot, xdata)
-     void **slot;
-     PTR xdata;
+elfNN_ia64_local_dyn_sym_thunk (void **slot, PTR xdata)
 {
   struct elfNN_ia64_local_hash_entry *entry
     = (struct elfNN_ia64_local_hash_entry *) *slot;
 {
   struct elfNN_ia64_local_hash_entry *entry
     = (struct elfNN_ia64_local_hash_entry *) *slot;
@@ -2093,10 +1960,9 @@ elfNN_ia64_local_dyn_sym_thunk (slot, xdata)
 }
 
 static void
 }
 
 static void
-elfNN_ia64_dyn_sym_traverse (ia64_info, func, data)
-     struct elfNN_ia64_link_hash_table *ia64_info;
-     bfd_boolean (*func) PARAMS ((struct elfNN_ia64_dyn_sym_info *, PTR));
-     PTR data;
+elfNN_ia64_dyn_sym_traverse (struct elfNN_ia64_link_hash_table *ia64_info,
+                            bfd_boolean (*func) (struct elfNN_ia64_dyn_sym_info *, PTR),
+                            PTR data)
 {
   struct elfNN_ia64_dyn_sym_traverse_data xdata;
 
 {
   struct elfNN_ia64_dyn_sym_traverse_data xdata;
 
@@ -2110,9 +1976,8 @@ elfNN_ia64_dyn_sym_traverse (ia64_info, func, data)
 }
 \f
 static bfd_boolean
 }
 \f
 static bfd_boolean
-elfNN_ia64_create_dynamic_sections (abfd, info)
-     bfd *abfd;
-     struct bfd_link_info *info;
+elfNN_ia64_create_dynamic_sections (bfd *abfd,
+                                   struct bfd_link_info *info)
 {
   struct elfNN_ia64_link_hash_table *ia64_info;
   asection *s;
 {
   struct elfNN_ia64_link_hash_table *ia64_info;
   asection *s;
@@ -2162,11 +2027,9 @@ elfNN_ia64_create_dynamic_sections (abfd, info)
 
 /* Find and/or create a hash entry for local symbol.  */
 static struct elfNN_ia64_local_hash_entry *
 
 /* 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;
-     bfd_boolean create;
+get_local_sym_hash (struct elfNN_ia64_link_hash_table *ia64_info,
+                   bfd *abfd, const Elf_Internal_Rela *rel,
+                   bfd_boolean create)
 {
   struct elfNN_ia64_local_hash_entry e, *ret;
   asection *sec = abfd->sections;
 {
   struct elfNN_ia64_local_hash_entry e, *ret;
   asection *sec = abfd->sections;
@@ -2208,7 +2071,7 @@ addend_compare (const void *xp, const void *yp)
   const struct elfNN_ia64_dyn_sym_info *y
     = (const struct elfNN_ia64_dyn_sym_info *) yp;
 
   const struct elfNN_ia64_dyn_sym_info *y
     = (const struct elfNN_ia64_dyn_sym_info *) yp;
 
-  return x->addend - y->addend;
+  return x->addend < y->addend ? -1 : x->addend > y->addend ? 1 : 0;
 }
 
 /* Sort elfNN_ia64_dyn_sym_info array and remove duplicates.  */
 }
 
 /* Sort elfNN_ia64_dyn_sym_info array and remove duplicates.  */
@@ -2217,37 +2080,62 @@ static unsigned int
 sort_dyn_sym_info (struct elfNN_ia64_dyn_sym_info *info,
                   unsigned int count)
 {
 sort_dyn_sym_info (struct elfNN_ia64_dyn_sym_info *info,
                   unsigned int count)
 {
-  bfd_vma curr, prev;
-  unsigned int i, dup, diff, dest, src, len;
+  bfd_vma curr, prev, got_offset;
+  unsigned int i, kept, dup, diff, dest, src, len;
 
   qsort (info, count, sizeof (*info), addend_compare);
 
   /* Find the first duplicate.  */
   prev = info [0].addend;
 
   qsort (info, count, sizeof (*info), addend_compare);
 
   /* Find the first duplicate.  */
   prev = info [0].addend;
+  got_offset = info [0].got_offset;
   for (i = 1; i < count; i++)
     {
       curr = info [i].addend;
       if (curr == prev)
   for (i = 1; i < count; i++)
     {
       curr = info [i].addend;
       if (curr == prev)
-       break;
+       {
+         /* For duplicates, make sure that GOT_OFFSET is valid.  */
+         if (got_offset == (bfd_vma) -1)
+           got_offset = info [i].got_offset;
+         break;
+       }
+      got_offset = info [i].got_offset;
       prev = curr;
     }
 
       prev = curr;
     }
 
+  /* We may move a block of elements to here.  */
+  dest = i++;
+
   /* Remove duplicates.  */
   if (i < count)
     {
   /* Remove duplicates.  */
   if (i < count)
     {
-      /* We need to move a block of elements to here.  */
-      dest = i++;
       while (i < count)
        {
       while (i < count)
        {
+         /* For duplicates, make sure that the kept one has a valid
+            got_offset.  */
+         kept = dest - 1;
+         if (got_offset != (bfd_vma) -1)
+           info [kept].got_offset = got_offset;
+
          curr = info [i].addend;
          curr = info [i].addend;
+         got_offset = info [i].got_offset;
 
          /* Move a block of elements whose first one is different from
             the previous.  */
          if (curr == prev)
            {
              for (src = i + 1; src < count; src++)
 
          /* Move a block of elements whose first one is different from
             the previous.  */
          if (curr == prev)
            {
              for (src = i + 1; src < count; src++)
-               if (info [src].addend != curr)
-                 break;
+               {
+                 if (info [src].addend != curr)
+                   break;
+                 /* For duplicates, make sure that GOT_OFFSET is
+                    valid.  */
+                 if (got_offset == (bfd_vma) -1)
+                   got_offset = info [src].got_offset;
+               }
+
+             /* Make sure that the kept one has a valid got_offset.  */
+             if (got_offset != (bfd_vma) -1)
+               info [kept].got_offset = got_offset;
            }
          else
            src = i;
            }
          else
            src = i;
@@ -2255,13 +2143,25 @@ sort_dyn_sym_info (struct elfNN_ia64_dyn_sym_info *info,
          if (src >= count)
            break;
 
          if (src >= count)
            break;
 
-         /* Find the next duplicate.  */
+         /* Find the next duplicate.  SRC will be kept.  */
          prev = info [src].addend;
          prev = info [src].addend;
+         got_offset = info [src].got_offset;
          for (dup = src + 1; dup < count; dup++)
            {
              curr = info [dup].addend;
              if (curr == prev)
          for (dup = src + 1; dup < count; dup++)
            {
              curr = info [dup].addend;
              if (curr == prev)
-               break;
+               {
+                 /* Make sure that got_offset is valid.  */
+                 if (got_offset == (bfd_vma) -1)
+                   got_offset = info [dup].got_offset;
+
+                 /* For duplicates, make sure that the kept one has
+                    a valid got_offset.  */
+                 if (got_offset != (bfd_vma) -1)
+                   info [dup - 1].got_offset = got_offset;
+                 break;
+               }
+             got_offset = info [dup].got_offset;
              prev = curr;
            }
 
              prev = curr;
            }
 
@@ -2272,20 +2172,41 @@ sort_dyn_sym_info (struct elfNN_ia64_dyn_sym_info *info,
          if (len == 1 && dup < count)
            {
              /* If we only move 1 element, we combine it with the next
          if (len == 1 && dup < count)
            {
              /* If we only move 1 element, we combine it with the next
-                one.  Find the next different one.  */
+                one.  There must be at least a duplicate.  Find the
+                next different one.  */
              for (diff = dup + 1, src++; diff < count; diff++, src++)
              for (diff = dup + 1, src++; diff < count; diff++, src++)
-               if (info [diff].addend != curr)
-                 break;
+               {
+                 if (info [diff].addend != curr)
+                   break;
+                 /* Make sure that got_offset is valid.  */
+                 if (got_offset == (bfd_vma) -1)
+                   got_offset = info [diff].got_offset;
+               }
+
+             /* Makre sure that the last duplicated one has an valid
+                offset.  */
+             BFD_ASSERT (curr == prev);
+             if (got_offset != (bfd_vma) -1)
+               info [diff - 1].got_offset = got_offset;
 
              if (diff < count)
                {
 
              if (diff < count)
                {
-                 /* Find the next duplicate.  */
+                 /* Find the next duplicate.  Track the current valid
+                    offset.  */
                  prev = info [diff].addend;
                  prev = info [diff].addend;
+                 got_offset = info [diff].got_offset;
                  for (dup = diff + 1; dup < count; dup++)
                    {
                      curr = info [dup].addend;
                      if (curr == prev)
                  for (dup = diff + 1; dup < count; dup++)
                    {
                      curr = info [dup].addend;
                      if (curr == prev)
-                       break;
+                       {
+                         /* For duplicates, make sure that GOT_OFFSET
+                            is valid.  */
+                         if (got_offset == (bfd_vma) -1)
+                           got_offset = info [dup].got_offset;
+                         break;
+                       }
+                     got_offset = info [dup].got_offset;
                      prev = curr;
                      diff++;
                    }
                      prev = curr;
                      diff++;
                    }
@@ -2302,6 +2223,19 @@ sort_dyn_sym_info (struct elfNN_ia64_dyn_sym_info *info,
 
       count = dest;
     }
 
       count = dest;
     }
+  else
+    {
+      /* When we get here, either there is no duplicate at all or
+        the only duplicate is the last element.  */
+      if (dest < count)
+       {
+         /* If the last element is a duplicate, make sure that the
+            kept one has a valid got_offset.  We also update count.  */
+         if (got_offset != (bfd_vma) -1)
+           info [dest - 1].got_offset = got_offset;
+         count = dest;
+       }
+    }
 
   return count;
 }
 
   return count;
 }
@@ -2323,12 +2257,9 @@ sort_dyn_sym_info (struct elfNN_ia64_dyn_sym_info *info,
    requires a copy which is O(N), but this only happens once.  */
 
 static struct elfNN_ia64_dyn_sym_info *
    requires a copy which is O(N), but this only happens once.  */
 
 static struct elfNN_ia64_dyn_sym_info *
-get_dyn_sym_info (ia64_info, h, abfd, rel, create)
-     struct elfNN_ia64_link_hash_table *ia64_info;
-     struct elf_link_hash_entry *h;
-     bfd *abfd;
-     const Elf_Internal_Rela *rel;
-     bfd_boolean create;
+get_dyn_sym_info (struct elfNN_ia64_link_hash_table *ia64_info,
+                 struct elf_link_hash_entry *h, bfd *abfd,
+                 const Elf_Internal_Rela *rel, bfd_boolean create)
 {
   struct elfNN_ia64_dyn_sym_info **info_p, *info, *dyn_i, key;
   unsigned int *count_p, *sorted_count_p, *size_p;
 {
   struct elfNN_ia64_dyn_sym_info **info_p, *info, *dyn_i, key;
   unsigned int *count_p, *sorted_count_p, *size_p;
@@ -2424,8 +2355,9 @@ has_space:
       /* Append the new one to the array.  */
       dyn_i = info + count;
       memset (dyn_i, 0, sizeof (*dyn_i));
       /* Append the new one to the array.  */
       dyn_i = info + count;
       memset (dyn_i, 0, sizeof (*dyn_i));
+      dyn_i->got_offset = (bfd_vma) -1;
       dyn_i->addend = addend;
       dyn_i->addend = addend;
-      
+
       /* We increment count only since the new ones are unsorted and
         may have duplicate.  */
       (*count_p)++;
       /* We increment count only since the new ones are unsorted and
         may have duplicate.  */
       (*count_p)++;
@@ -2464,10 +2396,8 @@ has_space:
 }
 
 static asection *
 }
 
 static asection *
-get_got (abfd, info, ia64_info)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     struct elfNN_ia64_link_hash_table *ia64_info;
+get_got (bfd *abfd, struct bfd_link_info *info,
+        struct elfNN_ia64_link_hash_table *ia64_info)
 {
   asection *got;
   bfd *dynobj;
 {
   asection *got;
   bfd *dynobj;
@@ -2504,10 +2434,8 @@ get_got (abfd, info, ia64_info)
    of a procedure, thus ensuring a unique address for each procedure.  */
 
 static asection *
    of a procedure, thus ensuring a unique address for each procedure.  */
 
 static asection *
-get_fptr (abfd, info, ia64_info)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     struct elfNN_ia64_link_hash_table *ia64_info;
+get_fptr (bfd *abfd, struct bfd_link_info *info,
+         struct elfNN_ia64_link_hash_table *ia64_info)
 {
   asection *fptr;
   bfd *dynobj;
 {
   asection *fptr;
   bfd *dynobj;
@@ -2560,10 +2488,8 @@ get_fptr (abfd, info, ia64_info)
 }
 
 static asection *
 }
 
 static asection *
-get_pltoff (abfd, info, ia64_info)
-     bfd *abfd;
-     struct bfd_link_info *info ATTRIBUTE_UNUSED;
-     struct elfNN_ia64_link_hash_table *ia64_info;
+get_pltoff (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED,
+           struct elfNN_ia64_link_hash_table *ia64_info)
 {
   asection *pltoff;
   bfd *dynobj;
 {
   asection *pltoff;
   bfd *dynobj;
@@ -2597,11 +2523,9 @@ get_pltoff (abfd, info, ia64_info)
 }
 
 static asection *
 }
 
 static asection *
-get_reloc_section (abfd, ia64_info, sec, create)
-     bfd *abfd;
-     struct elfNN_ia64_link_hash_table *ia64_info;
-     asection *sec;
-     bfd_boolean create;
+get_reloc_section (bfd *abfd,
+                  struct elfNN_ia64_link_hash_table *ia64_info,
+                  asection *sec, bfd_boolean create)
 {
   const char *srel_name;
   asection *srel;
 {
   const char *srel_name;
   asection *srel;
@@ -2613,10 +2537,10 @@ get_reloc_section (abfd, ia64_info, sec, create)
   if (srel_name == NULL)
     return NULL;
 
   if (srel_name == NULL)
     return NULL;
 
-  BFD_ASSERT ((strncmp (srel_name, ".rela", 5) == 0
+  BFD_ASSERT ((CONST_STRNEQ (srel_name, ".rela")
               && strcmp (bfd_get_section_name (abfd, sec),
                          srel_name+5) == 0)
               && strcmp (bfd_get_section_name (abfd, sec),
                          srel_name+5) == 0)
-             || (strncmp (srel_name, ".rel", 4) == 0
+             || (CONST_STRNEQ (srel_name, ".rel")
                  && strcmp (bfd_get_section_name (abfd, sec),
                             srel_name+4) == 0));
 
                  && strcmp (bfd_get_section_name (abfd, sec),
                             srel_name+4) == 0));
 
@@ -2672,11 +2596,9 @@ count_dyn_reloc (bfd *abfd, struct elfNN_ia64_dyn_sym_info *dyn_i,
 }
 
 static bfd_boolean
 }
 
 static bfd_boolean
-elfNN_ia64_check_relocs (abfd, info, sec, relocs)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     asection *sec;
-     const Elf_Internal_Rela *relocs;
+elfNN_ia64_check_relocs (bfd *abfd, struct bfd_link_info *info,
+                        asection *sec,
+                        const Elf_Internal_Rela *relocs)
 {
   struct elfNN_ia64_link_hash_table *ia64_info;
   const Elf_Internal_Rela *relend;
 {
   struct elfNN_ia64_link_hash_table *ia64_info;
   const Elf_Internal_Rela *relend;
@@ -2733,7 +2655,7 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs)
         have yet been processed.  Do something with what we know, as
         this may help reduce memory usage and processing time later.  */
       maybe_dynamic = (h && ((!info->executable
         have yet been processed.  Do something with what we know, as
         this may help reduce memory usage and processing time later.  */
       maybe_dynamic = (h && ((!info->executable
-                             && (!info->symbolic
+                             && (!SYMBOLIC_BIND (info, h)
                                  || info->unresolved_syms_in_shared_libs == RM_IGNORE))
                             || !h->def_regular
                             || h->root.type == bfd_link_hash_defweak));
                                  || info->unresolved_syms_in_shared_libs == RM_IGNORE))
                             || !h->def_regular
                             || h->root.type == bfd_link_hash_defweak));
@@ -2878,7 +2800,7 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs)
     }
 
   /* Now, we only do lookup without insertion, which is very fast
     }
 
   /* Now, we only do lookup without insertion, which is very fast
-     with the modified get_dyn_sym_info.  */ 
+     with the modified get_dyn_sym_info.  */
   for (rel = relocs; rel < relend; ++rel)
     {
       struct elfNN_ia64_dyn_sym_info *dyn_i;
   for (rel = relocs; rel < relend; ++rel)
     {
       struct elfNN_ia64_dyn_sym_info *dyn_i;
@@ -2905,7 +2827,7 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs)
         have yet been processed.  Do something with what we know, as
         this may help reduce memory usage and processing time later.  */
       maybe_dynamic = (h && ((!info->executable
         have yet been processed.  Do something with what we know, as
         this may help reduce memory usage and processing time later.  */
       maybe_dynamic = (h && ((!info->executable
-                             && (!info->symbolic
+                             && (!SYMBOLIC_BIND (info, h)
                                  || info->unresolved_syms_in_shared_libs == RM_IGNORE))
                             || !h->def_regular
                             || h->root.type == bfd_link_hash_defweak));
                                  || info->unresolved_syms_in_shared_libs == RM_IGNORE))
                             || !h->def_regular
                             || h->root.type == bfd_link_hash_defweak));
@@ -3132,9 +3054,8 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs)
    external GOT entries first.  */
 
 static bfd_boolean
    external GOT entries first.  */
 
 static bfd_boolean
-allocate_global_data_got (dyn_i, data)
-     struct elfNN_ia64_dyn_sym_info *dyn_i;
-     PTR data;
+allocate_global_data_got (struct elfNN_ia64_dyn_sym_info *dyn_i,
+                         PTR data)
 {
   struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
 
 {
   struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
 
@@ -3181,9 +3102,8 @@ allocate_global_data_got (dyn_i, data)
 /* Next, allocate all the GOT entries used by LTOFF_FPTR relocs.  */
 
 static bfd_boolean
 /* Next, allocate all the GOT entries used by LTOFF_FPTR relocs.  */
 
 static bfd_boolean
-allocate_global_fptr_got (dyn_i, data)
-     struct elfNN_ia64_dyn_sym_info *dyn_i;
-     PTR data;
+allocate_global_fptr_got (struct elfNN_ia64_dyn_sym_info *dyn_i,
+                         PTR data)
 {
   struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
 
 {
   struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
 
@@ -3200,9 +3120,8 @@ allocate_global_fptr_got (dyn_i, data)
 /* Lastly, allocate all the GOT entries for local data.  */
 
 static bfd_boolean
 /* Lastly, allocate all the GOT entries for local data.  */
 
 static bfd_boolean
-allocate_local_got (dyn_i, data)
-     struct elfNN_ia64_dyn_sym_info *dyn_i;
-     PTR data;
+allocate_local_got (struct elfNN_ia64_dyn_sym_info *dyn_i,
+                   PTR data)
 {
   struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
 
 {
   struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
 
@@ -3218,8 +3137,7 @@ allocate_local_got (dyn_i, data)
 /* Search for the index of a global symbol in it's defining object file.  */
 
 static long
 /* Search for the index of a global symbol in it's defining object file.  */
 
 static long
-global_sym_index (h)
-     struct elf_link_hash_entry *h;
+global_sym_index (struct elf_link_hash_entry *h)
 {
   struct elf_link_hash_entry **p;
   bfd *obj;
 {
   struct elf_link_hash_entry **p;
   bfd *obj;
@@ -3238,9 +3156,7 @@ global_sym_index (h)
    in a main executable that is not exported.  */
 
 static bfd_boolean
    in a main executable that is not exported.  */
 
 static bfd_boolean
-allocate_fptr (dyn_i, data)
-     struct elfNN_ia64_dyn_sym_info *dyn_i;
-     PTR data;
+allocate_fptr (struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data)
 {
   struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
 
 {
   struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
 
@@ -3286,9 +3202,8 @@ allocate_fptr (dyn_i, data)
 /* Allocate all the minimal PLT entries.  */
 
 static bfd_boolean
 /* Allocate all the minimal PLT entries.  */
 
 static bfd_boolean
-allocate_plt_entries (dyn_i, data)
-     struct elfNN_ia64_dyn_sym_info *dyn_i;
-     PTR data;
+allocate_plt_entries (struct elfNN_ia64_dyn_sym_info *dyn_i,
+                     PTR data)
 {
   struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
 
 {
   struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
 
@@ -3324,9 +3239,8 @@ allocate_plt_entries (dyn_i, data)
 /* Allocate all the full PLT entries.  */
 
 static bfd_boolean
 /* Allocate all the full PLT entries.  */
 
 static bfd_boolean
-allocate_plt2_entries (dyn_i, data)
-     struct elfNN_ia64_dyn_sym_info *dyn_i;
-     PTR data;
+allocate_plt2_entries (struct elfNN_ia64_dyn_sym_info *dyn_i,
+                      PTR data)
 {
   struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
 
 {
   struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
 
@@ -3352,9 +3266,8 @@ allocate_plt2_entries (dyn_i, data)
    ??? Relaxation might be able to determine that they are.  */
 
 static bfd_boolean
    ??? Relaxation might be able to determine that they are.  */
 
 static bfd_boolean
-allocate_pltoff_entries (dyn_i, data)
-     struct elfNN_ia64_dyn_sym_info *dyn_i;
-     PTR data;
+allocate_pltoff_entries (struct elfNN_ia64_dyn_sym_info *dyn_i,
+                        PTR data)
 {
   struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
 
 {
   struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
 
@@ -3370,9 +3283,8 @@ allocate_pltoff_entries (dyn_i, data)
    to be dynamic.  */
 
 static bfd_boolean
    to be dynamic.  */
 
 static bfd_boolean
-allocate_dynrel_entries (dyn_i, data)
-     struct elfNN_ia64_dyn_sym_info *dyn_i;
-     PTR data;
+allocate_dynrel_entries (struct elfNN_ia64_dyn_sym_info *dyn_i,
+                        PTR data)
 {
   struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
   struct elfNN_ia64_link_hash_table *ia64_info;
 {
   struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
   struct elfNN_ia64_link_hash_table *ia64_info;
@@ -3487,9 +3399,8 @@ allocate_dynrel_entries (dyn_i, data)
 }
 
 static bfd_boolean
 }
 
 static bfd_boolean
-elfNN_ia64_adjust_dynamic_symbol (info, h)
-     struct bfd_link_info *info ATTRIBUTE_UNUSED;
-     struct elf_link_hash_entry *h;
+elfNN_ia64_adjust_dynamic_symbol (struct bfd_link_info *info ATTRIBUTE_UNUSED,
+                                 struct elf_link_hash_entry *h)
 {
   /* ??? Undefined symbols with PLT entries should be re-defined
      to be the PLT entry.  */
 {
   /* ??? Undefined symbols with PLT entries should be re-defined
      to be the PLT entry.  */
@@ -3517,9 +3428,8 @@ elfNN_ia64_adjust_dynamic_symbol (info, h)
 }
 
 static bfd_boolean
 }
 
 static bfd_boolean
-elfNN_ia64_size_dynamic_sections (output_bfd, info)
-     bfd *output_bfd ATTRIBUTE_UNUSED;
-     struct bfd_link_info *info;
+elfNN_ia64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+                                 struct bfd_link_info *info)
 {
   struct elfNN_ia64_allocate_data data;
   struct elfNN_ia64_link_hash_table *ia64_info;
 {
   struct elfNN_ia64_allocate_data data;
   struct elfNN_ia64_link_hash_table *ia64_info;
@@ -3694,7 +3604,7 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info)
 
          if (strcmp (name, ".got.plt") == 0)
            strip = FALSE;
 
          if (strcmp (name, ".got.plt") == 0)
            strip = FALSE;
-         else if (strncmp (name, ".rel", 4) == 0)
+         else if (CONST_STRNEQ (name, ".rel"))
            {
              if (!strip)
                {
            {
              if (!strip)
                {
@@ -3767,10 +3677,8 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info)
 }
 
 static bfd_reloc_status_type
 }
 
 static bfd_reloc_status_type
-elfNN_ia64_install_value (hit_addr, v, r_type)
-     bfd_byte *hit_addr;
-     bfd_vma v;
-     unsigned int r_type;
+elfNN_ia64_install_value (bfd_byte *hit_addr, bfd_vma v,
+                         unsigned int r_type)
 {
   const struct ia64_operand *op;
   int bigendian = 0, shift = 0;
 {
   const struct ia64_operand *op;
   int bigendian = 0, shift = 0;
@@ -3992,16 +3900,10 @@ elfNN_ia64_install_value (hit_addr, v, r_type)
 }
 
 static void
 }
 
 static void
-elfNN_ia64_install_dyn_reloc (abfd, info, sec, srel, offset, type,
-                             dynindx, addend)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     asection *sec;
-     asection *srel;
-     bfd_vma offset;
-     unsigned int type;
-     long dynindx;
-     bfd_vma addend;
+elfNN_ia64_install_dyn_reloc (bfd *abfd, struct bfd_link_info *info,
+                             asection *sec, asection *srel,
+                             bfd_vma offset, unsigned int type,
+                             long dynindx, bfd_vma addend)
 {
   Elf_Internal_Rela outrel;
   bfd_byte *loc;
 {
   Elf_Internal_Rela outrel;
   bfd_byte *loc;
@@ -4031,14 +3933,10 @@ elfNN_ia64_install_dyn_reloc (abfd, info, sec, srel, offset, type,
    and return the gp-relative address of the linkage table entry.  */
 
 static bfd_vma
    and return the gp-relative address of the linkage table entry.  */
 
 static bfd_vma
-set_got_entry (abfd, info, dyn_i, dynindx, addend, value, dyn_r_type)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     struct elfNN_ia64_dyn_sym_info *dyn_i;
-     long dynindx;
-     bfd_vma addend;
-     bfd_vma value;
-     unsigned int dyn_r_type;
+set_got_entry (bfd *abfd, struct bfd_link_info *info,
+              struct elfNN_ia64_dyn_sym_info *dyn_i,
+              long dynindx, bfd_vma addend, bfd_vma value,
+              unsigned int dyn_r_type)
 {
   struct elfNN_ia64_link_hash_table *ia64_info;
   asection *got_sec;
 {
   struct elfNN_ia64_link_hash_table *ia64_info;
   asection *got_sec;
@@ -4175,11 +4073,9 @@ set_got_entry (abfd, info, dyn_i, dynindx, addend, value, dyn_r_type)
    address and its global pointer.  Return the descriptor's address.  */
 
 static bfd_vma
    address and its global pointer.  Return the descriptor's address.  */
 
 static bfd_vma
-set_fptr_entry (abfd, info, dyn_i, value)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     struct elfNN_ia64_dyn_sym_info *dyn_i;
-     bfd_vma value;
+set_fptr_entry (bfd *abfd, struct bfd_link_info *info,
+               struct elfNN_ia64_dyn_sym_info *dyn_i,
+               bfd_vma value)
 {
   struct elfNN_ia64_link_hash_table *ia64_info;
   asection *fptr_sec;
 {
   struct elfNN_ia64_link_hash_table *ia64_info;
   asection *fptr_sec;
@@ -4227,12 +4123,9 @@ set_fptr_entry (abfd, info, dyn_i, value)
    and its global pointer.  Return the descriptor's address.  */
 
 static bfd_vma
    and its global pointer.  Return the descriptor's address.  */
 
 static bfd_vma
-set_pltoff_entry (abfd, info, dyn_i, value, is_plt)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     struct elfNN_ia64_dyn_sym_info *dyn_i;
-     bfd_vma value;
-     bfd_boolean is_plt;
+set_pltoff_entry (bfd *abfd, struct bfd_link_info *info,
+                 struct elfNN_ia64_dyn_sym_info *dyn_i,
+                 bfd_vma value, bfd_boolean is_plt)
 {
   struct elfNN_ia64_link_hash_table *ia64_info;
   asection *pltoff_sec;
 {
   struct elfNN_ia64_link_hash_table *ia64_info;
   asection *pltoff_sec;
@@ -4292,12 +4185,9 @@ set_pltoff_entry (abfd, info, dyn_i, value, is_plt)
    is assigned offset round(2 * size of pointer, PT_TLS p_align).  */
 
 static bfd_vma
    is assigned offset round(2 * size of pointer, PT_TLS p_align).  */
 
 static bfd_vma
-elfNN_ia64_tprel_base (info)
-     struct bfd_link_info *info;
+elfNN_ia64_tprel_base (struct bfd_link_info *info)
 {
   asection *tls_sec = elf_hash_table (info)->tls_sec;
 {
   asection *tls_sec = elf_hash_table (info)->tls_sec;
-
-  BFD_ASSERT (tls_sec != NULL);
   return tls_sec->vma - align_power ((bfd_vma) ARCH_SIZE / 4,
                                     tls_sec->alignment_power);
 }
   return tls_sec->vma - align_power ((bfd_vma) ARCH_SIZE / 4,
                                     tls_sec->alignment_power);
 }
@@ -4307,10 +4197,8 @@ elfNN_ia64_tprel_base (info)
    This is PT_TLS segment p_vaddr.  */
 
 static bfd_vma
    This is PT_TLS segment p_vaddr.  */
 
 static bfd_vma
-elfNN_ia64_dtprel_base (info)
-     struct bfd_link_info *info;
+elfNN_ia64_dtprel_base (struct bfd_link_info *info)
 {
 {
-  BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
   return elf_hash_table (info)->tls_sec->vma;
 }
 
   return elf_hash_table (info)->tls_sec->vma;
 }
 
@@ -4321,9 +4209,7 @@ elfNN_ia64_dtprel_base (info)
 static bfd *elfNN_ia64_unwind_entry_compare_bfd;
 
 static int
 static bfd *elfNN_ia64_unwind_entry_compare_bfd;
 
 static int
-elfNN_ia64_unwind_entry_compare (a, b)
-     const PTR a;
-     const PTR b;
+elfNN_ia64_unwind_entry_compare (const PTR a, const PTR b)
 {
   bfd_vma av, bv;
 
 {
   bfd_vma av, bv;
 
@@ -4335,9 +4221,7 @@ elfNN_ia64_unwind_entry_compare (a, b)
 
 /* Make sure we've got ourselves a nice fat __gp value.  */
 static bfd_boolean
 
 /* Make sure we've got ourselves a nice fat __gp value.  */
 static bfd_boolean
-elfNN_ia64_choose_gp (abfd, info)
-     bfd *abfd;
-     struct bfd_link_info *info;
+elfNN_ia64_choose_gp (bfd *abfd, struct bfd_link_info *info)
 {
   bfd_vma min_vma = (bfd_vma) -1, max_vma = 0;
   bfd_vma min_short_vma = min_vma, max_short_vma = 0;
 {
   bfd_vma min_vma = (bfd_vma) -1, max_vma = 0;
   bfd_vma min_short_vma = min_vma, max_short_vma = 0;
@@ -4358,7 +4242,7 @@ elfNN_ia64_choose_gp (abfd, info)
        continue;
 
       lo = os->vma;
        continue;
 
       lo = os->vma;
-      hi = os->vma + os->size;
+      hi = os->vma + (os->rawsize ? os->rawsize : os->size);
       if (hi < lo)
        hi = (bfd_vma) -1;
 
       if (hi < lo)
        hi = (bfd_vma) -1;
 
@@ -4453,9 +4337,7 @@ elfNN_ia64_choose_gp (abfd, info)
 }
 
 static bfd_boolean
 }
 
 static bfd_boolean
-elfNN_ia64_final_link (abfd, info)
-     bfd *abfd;
-     struct bfd_link_info *info;
+elfNN_ia64_final_link (bfd *abfd, struct bfd_link_info *info)
 {
   struct elfNN_ia64_link_hash_table *ia64_info;
   asection *unwind_output_sec;
 {
   struct elfNN_ia64_link_hash_table *ia64_info;
   asection *unwind_output_sec;
@@ -4524,16 +4406,14 @@ elfNN_ia64_final_link (abfd, info)
 }
 
 static bfd_boolean
 }
 
 static bfd_boolean
-elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
-                            contents, relocs, local_syms, local_sections)
-     bfd *output_bfd;
-     struct bfd_link_info *info;
-     bfd *input_bfd;
-     asection *input_section;
-     bfd_byte *contents;
-     Elf_Internal_Rela *relocs;
-     Elf_Internal_Sym *local_syms;
-     asection **local_sections;
+elfNN_ia64_relocate_section (bfd *output_bfd,
+                            struct bfd_link_info *info,
+                            bfd *input_bfd,
+                            asection *input_section,
+                            bfd_byte *contents,
+                            Elf_Internal_Rela *relocs,
+                            Elf_Internal_Sym *local_syms,
+                            asection **local_sections)
 {
   struct elfNN_ia64_link_hash_table *ia64_info;
   Elf_Internal_Shdr *symtab_hdr;
 {
   struct elfNN_ia64_link_hash_table *ia64_info;
   Elf_Internal_Shdr *symtab_hdr;
@@ -4556,7 +4436,6 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
 
       elf_section_data(input_section->output_section)
        ->this_hdr.sh_flags |= flags;
 
       elf_section_data(input_section->output_section)
        ->this_hdr.sh_flags |= flags;
-      return TRUE;
     }
 
   gp_val = _bfd_get_gp_value (output_bfd);
     }
 
   gp_val = _bfd_get_gp_value (output_bfd);
@@ -4605,7 +4484,8 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
          sym_sec = local_sections[r_symndx];
          msec = sym_sec;
          value = _bfd_elf_rela_local_sym (output_bfd, sym, &msec, rel);
          sym_sec = local_sections[r_symndx];
          msec = sym_sec;
          value = _bfd_elf_rela_local_sym (output_bfd, sym, &msec, rel);
-         if ((sym_sec->flags & SEC_MERGE)
+         if (!info->relocatable
+             && (sym_sec->flags & SEC_MERGE) != 0
              && ELF_ST_TYPE (sym->st_info) == STT_SECTION
              && sym_sec->sec_info_type == ELF_INFO_TYPE_MERGE)
            {
              && ELF_ST_TYPE (sym->st_info) == STT_SECTION
              && sym_sec->sec_info_type == ELF_INFO_TYPE_MERGE)
            {
@@ -4634,9 +4514,15 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
                                        - sym_sec->output_section->vma
                                        - sym_sec->output_offset;
                    }
                                        - sym_sec->output_section->vma
                                        - sym_sec->output_offset;
                    }
-                 
-                 qsort (loc_h->info, loc_h->count,
-                        sizeof (*loc_h->info), addend_compare);
+
+                 /* We may have introduced duplicated entries. We need
+                    to remove them properly.  */
+                 count = sort_dyn_sym_info (loc_h->info, loc_h->count);
+                 if (count != loc_h->count)
+                   {
+                     loc_h->count = count;
+                     loc_h->sorted_count = count;
+                   }
 
                  loc_h->sec_merge_done = 1;
                }
 
                  loc_h->sec_merge_done = 1;
                }
@@ -4659,6 +4545,20 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
            continue;
        }
 
            continue;
        }
 
+      /* For relocs against symbols from removed linkonce sections,
+        or sections discarded by a linker script, we just want the
+        section contents zeroed.  Avoid any special processing.  */
+      if (sym_sec != NULL && elf_discarded_section (sym_sec))
+       {
+         _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
+         rel->r_info = 0;
+         rel->r_addend = 0;
+         continue;
+       }
+
+      if (info->relocatable)
+       continue;
+
       hit_addr = contents + rel->r_offset;
       value += rel->r_addend;
       dynamic_symbol_p = elfNN_ia64_dynamic_symbol_p (h, info, r_type);
       hit_addr = contents + rel->r_offset;
       value += rel->r_addend;
       dynamic_symbol_p = elfNN_ia64_dynamic_symbol_p (h, info, r_type);
@@ -4990,32 +4890,12 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
        case R_IA64_SEGREL32LSB:
        case R_IA64_SEGREL64MSB:
        case R_IA64_SEGREL64LSB:
        case R_IA64_SEGREL32LSB:
        case R_IA64_SEGREL64MSB:
        case R_IA64_SEGREL64LSB:
-         if (r_symndx == 0)
-           {
-             /* If the input section was discarded from the output, then
-                do nothing.  */
-             r = bfd_reloc_ok;
-           }
-         else
            {
            {
-             struct elf_segment_map *m;
-             Elf_Internal_Phdr *p;
-
              /* Find the segment that contains the output_section.  */
              /* Find the segment that contains the output_section.  */
-             for (m = elf_tdata (output_bfd)->segment_map,
-                    p = elf_tdata (output_bfd)->phdr;
-                  m != NULL;
-                  m = m->next, p++)
-               {
-                 int i;
-                 for (i = m->count - 1; i >= 0; i--)
-                   if (m->sections[i] == input_section->output_section)
-                     break;
-                 if (i >= 0)
-                   break;
-               }
+             Elf_Internal_Phdr *p = _bfd_elf_find_segment_containing_section
+               (output_bfd, input_section->output_section);
 
 
-             if (m == NULL)
+             if (p == NULL)
                {
                  r = bfd_reloc_notsupported;
                }
                {
                  r = bfd_reloc_notsupported;
                }
@@ -5088,6 +4968,8 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
        case R_IA64_TPREL14:
        case R_IA64_TPREL22:
        case R_IA64_TPREL64I:
        case R_IA64_TPREL14:
        case R_IA64_TPREL22:
        case R_IA64_TPREL64I:
+         if (elf_hash_table (info)->tls_sec == NULL)
+           goto missing_tls_sec;
          value -= elfNN_ia64_tprel_base (info);
          r = elfNN_ia64_install_value (hit_addr, value, r_type);
          break;
          value -= elfNN_ia64_tprel_base (info);
          r = elfNN_ia64_install_value (hit_addr, value, r_type);
          break;
@@ -5099,6 +4981,8 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
        case R_IA64_DTPREL32MSB:
        case R_IA64_DTPREL64LSB:
        case R_IA64_DTPREL64MSB:
        case R_IA64_DTPREL32MSB:
        case R_IA64_DTPREL64LSB:
        case R_IA64_DTPREL64MSB:
+         if (elf_hash_table (info)->tls_sec == NULL)
+           goto missing_tls_sec;
          value -= elfNN_ia64_dtprel_base (info);
          r = elfNN_ia64_install_value (hit_addr, value, r_type);
          break;
          value -= elfNN_ia64_dtprel_base (info);
          r = elfNN_ia64_install_value (hit_addr, value, r_type);
          break;
@@ -5117,6 +5001,8 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
              case R_IA64_LTOFF_TPREL22:
                if (!dynamic_symbol_p)
                  {
              case R_IA64_LTOFF_TPREL22:
                if (!dynamic_symbol_p)
                  {
+                   if (elf_hash_table (info)->tls_sec == NULL)
+                     goto missing_tls_sec;
                    if (!info->shared)
                      value -= elfNN_ia64_tprel_base (info);
                    else
                    if (!info->shared)
                      value -= elfNN_ia64_tprel_base (info);
                    else
@@ -5134,7 +5020,11 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
                break;
              case R_IA64_LTOFF_DTPREL22:
                if (!dynamic_symbol_p)
                break;
              case R_IA64_LTOFF_DTPREL22:
                if (!dynamic_symbol_p)
-                 value -= elfNN_ia64_dtprel_base (info);
+                 {
+                   if (elf_hash_table (info)->tls_sec == NULL)
+                     goto missing_tls_sec;
+                   value -= elfNN_ia64_dtprel_base (info);
+                 }
                got_r_type = R_IA64_DTPRELNNLSB;
                break;
              }
                got_r_type = R_IA64_DTPRELNNLSB;
                break;
              }
@@ -5185,6 +5075,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
        case bfd_reloc_outofrange:
        case bfd_reloc_overflow:
        default:
        case bfd_reloc_outofrange:
        case bfd_reloc_overflow:
        default:
+missing_tls_sec:
          {
            const char *name;
 
          {
            const char *name;
 
@@ -5196,6 +5087,25 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
 
            switch (r_type)
              {
 
            switch (r_type)
              {
+             case R_IA64_TPREL14:
+             case R_IA64_TPREL22:
+             case R_IA64_TPREL64I:
+             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:
+             case R_IA64_LTOFF_TPREL22:
+             case R_IA64_LTOFF_DTPMOD22:
+             case R_IA64_LTOFF_DTPREL22:
+               (*_bfd_error_handler)
+                 (_("%B: missing TLS section for relocation %s against `%s' at 0x%lx in section `%A'."),
+                  input_bfd, input_section, howto->name, name,
+                  rel->r_offset);
+               break;
+
              case R_IA64_PCREL21B:
              case R_IA64_PCREL21BI:
              case R_IA64_PCREL21M:
              case R_IA64_PCREL21B:
              case R_IA64_PCREL21BI:
              case R_IA64_PCREL21M:
@@ -5234,11 +5144,10 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
 }
 
 static bfd_boolean
 }
 
 static bfd_boolean
-elfNN_ia64_finish_dynamic_symbol (output_bfd, info, h, sym)
-     bfd *output_bfd;
-     struct bfd_link_info *info;
-     struct elf_link_hash_entry *h;
-     Elf_Internal_Sym *sym;
+elfNN_ia64_finish_dynamic_symbol (bfd *output_bfd,
+                                 struct bfd_link_info *info,
+                                 struct elf_link_hash_entry *h,
+                                 Elf_Internal_Sym *sym)
 {
   struct elfNN_ia64_link_hash_table *ia64_info;
   struct elfNN_ia64_dyn_sym_info *dyn_i;
 {
   struct elfNN_ia64_link_hash_table *ia64_info;
   struct elfNN_ia64_dyn_sym_info *dyn_i;
@@ -5323,9 +5232,8 @@ elfNN_ia64_finish_dynamic_symbol (output_bfd, info, h, sym)
 }
 
 static bfd_boolean
 }
 
 static bfd_boolean
-elfNN_ia64_finish_dynamic_sections (abfd, info)
-     bfd *abfd;
-     struct bfd_link_info *info;
+elfNN_ia64_finish_dynamic_sections (bfd *abfd,
+                                   struct bfd_link_info *info)
 {
   struct elfNN_ia64_link_hash_table *ia64_info;
   bfd *dynobj;
 {
   struct elfNN_ia64_link_hash_table *ia64_info;
   bfd *dynobj;
@@ -5411,9 +5319,7 @@ elfNN_ia64_finish_dynamic_sections (abfd, info)
 
 /* Function to keep IA-64 specific file flags.  */
 static bfd_boolean
 
 /* Function to keep IA-64 specific file flags.  */
 static bfd_boolean
-elfNN_ia64_set_private_flags (abfd, flags)
-     bfd *abfd;
-     flagword flags;
+elfNN_ia64_set_private_flags (bfd *abfd, flagword flags)
 {
   BFD_ASSERT (!elf_flags_init (abfd)
              || elf_elfheader (abfd)->e_flags == flags);
 {
   BFD_ASSERT (!elf_flags_init (abfd)
              || elf_elfheader (abfd)->e_flags == flags);
@@ -5426,8 +5332,7 @@ elfNN_ia64_set_private_flags (abfd, flags)
 /* Merge backend specific data from an object file to the output
    object file when linking.  */
 static bfd_boolean
 /* Merge backend specific data from an object file to the output
    object file when linking.  */
 static bfd_boolean
-elfNN_ia64_merge_private_bfd_data (ibfd, obfd)
-     bfd *ibfd, *obfd;
+elfNN_ia64_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
 {
   flagword out_flags;
   flagword in_flags;
 {
   flagword out_flags;
   flagword in_flags;
@@ -5515,9 +5420,7 @@ elfNN_ia64_merge_private_bfd_data (ibfd, obfd)
 }
 
 static bfd_boolean
 }
 
 static bfd_boolean
-elfNN_ia64_print_private_bfd_data (abfd, ptr)
-     bfd *abfd;
-     PTR ptr;
+elfNN_ia64_print_private_bfd_data (bfd *abfd, PTR ptr)
 {
   FILE *file = (FILE *) ptr;
   flagword flags = elf_elfheader (abfd)->e_flags;
 {
   FILE *file = (FILE *) ptr;
   flagword flags = elf_elfheader (abfd)->e_flags;
@@ -5539,8 +5442,7 @@ elfNN_ia64_print_private_bfd_data (abfd, ptr)
 }
 
 static enum elf_reloc_type_class
 }
 
 static enum elf_reloc_type_class
-elfNN_ia64_reloc_type_class (rela)
-     const Elf_Internal_Rela *rela;
+elfNN_ia64_reloc_type_class (const Elf_Internal_Rela *rela)
 {
   switch ((int) ELFNN_R_TYPE (rela->r_info))
     {
 {
   switch ((int) ELFNN_R_TYPE (rela->r_info))
     {
@@ -5561,9 +5463,9 @@ elfNN_ia64_reloc_type_class (rela)
 
 static const struct bfd_elf_special_section 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 }
+  { STRING_COMMA_LEN (".sbss"),  -1, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE + SHF_IA_64_SHORT },
+  { STRING_COMMA_LEN (".sdata"), -1, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_IA_64_SHORT },
+  { NULL,                    0,   0, 0,            0 }
 };
 
 static bfd_boolean
 };
 
 static bfd_boolean
@@ -5590,7 +5492,7 @@ elfNN_ia64_object_p (bfd *abfd)
       if (elf_sec_group (sec) == NULL
          && ((sec->flags & (SEC_LINK_ONCE | SEC_CODE | SEC_GROUP))
              == (SEC_LINK_ONCE | SEC_CODE))
       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)
+         && CONST_STRNEQ (sec->name, ".gnu.linkonce.t."))
        {
          name = sec->name + 16;
 
        {
          name = sec->name + 16;
 
@@ -5667,21 +5569,18 @@ elfNN_ia64_hpux_vec (const bfd_target *vec)
 }
 
 static void
 }
 
 static void
-elfNN_hpux_post_process_headers (abfd, info)
-       bfd *abfd;
-       struct bfd_link_info *info ATTRIBUTE_UNUSED;
+elfNN_hpux_post_process_headers (bfd *abfd,
+                                struct bfd_link_info *info ATTRIBUTE_UNUSED)
 {
   Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd);
 
 {
   Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd);
 
-  i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_HPUX;
+  i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi;
   i_ehdrp->e_ident[EI_ABIVERSION] = 1;
 }
 
   i_ehdrp->e_ident[EI_ABIVERSION] = 1;
 }
 
-bfd_boolean
-elfNN_hpux_backend_section_from_bfd_section (abfd, sec, retval)
-       bfd *abfd ATTRIBUTE_UNUSED;
-       asection *sec;
-       int *retval;
+static bfd_boolean
+elfNN_hpux_backend_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED,
+                                            asection *sec, int *retval)
 {
   if (bfd_is_com_section (sec))
     {
 {
   if (bfd_is_com_section (sec))
     {
@@ -5717,6 +5616,7 @@ elfNN_hpux_backend_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
 #define ELF_MACHINE_ALT1               1999    /* EAS2.3 */
 #define ELF_MACHINE_ALT2               1998    /* EAS2.2 */
 #define ELF_MAXPAGESIZE                        0x10000 /* 64KB */
 #define ELF_MACHINE_ALT1               1999    /* EAS2.3 */
 #define ELF_MACHINE_ALT2               1998    /* EAS2.2 */
 #define ELF_MAXPAGESIZE                        0x10000 /* 64KB */
+#define ELF_COMMONPAGESIZE             0x4000  /* 16KB */
 
 #define elf_backend_section_from_shdr \
        elfNN_ia64_section_from_shdr
 
 #define elf_backend_section_from_shdr \
        elfNN_ia64_section_from_shdr
@@ -5732,11 +5632,15 @@ elfNN_hpux_backend_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
        elfNN_ia64_additional_program_headers
 #define elf_backend_modify_segment_map \
        elfNN_ia64_modify_segment_map
        elfNN_ia64_additional_program_headers
 #define elf_backend_modify_segment_map \
        elfNN_ia64_modify_segment_map
+#define elf_backend_modify_program_headers \
+       elfNN_ia64_modify_program_headers
 #define elf_info_to_howto \
        elfNN_ia64_info_to_howto
 
 #define bfd_elfNN_bfd_reloc_type_lookup \
        elfNN_ia64_reloc_type_lookup
 #define elf_info_to_howto \
        elfNN_ia64_info_to_howto
 
 #define bfd_elfNN_bfd_reloc_type_lookup \
        elfNN_ia64_reloc_type_lookup
+#define bfd_elfNN_bfd_reloc_name_lookup \
+       elfNN_ia64_reloc_name_lookup
 #define bfd_elfNN_bfd_is_local_label_name \
        elfNN_ia64_is_local_label_name
 #define bfd_elfNN_bfd_relax_section \
 #define bfd_elfNN_bfd_is_local_label_name \
        elfNN_ia64_is_local_label_name
 #define bfd_elfNN_bfd_relax_section \
@@ -5758,6 +5662,8 @@ elfNN_hpux_backend_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
        elfNN_ia64_adjust_dynamic_symbol
 #define elf_backend_size_dynamic_sections \
        elfNN_ia64_size_dynamic_sections
        elfNN_ia64_adjust_dynamic_symbol
 #define elf_backend_size_dynamic_sections \
        elfNN_ia64_size_dynamic_sections
+#define elf_backend_omit_section_dynsym \
+  ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
 #define elf_backend_relocate_section \
        elfNN_ia64_relocate_section
 #define elf_backend_finish_dynamic_symbol \
 #define elf_backend_relocate_section \
        elfNN_ia64_relocate_section
 #define elf_backend_finish_dynamic_symbol \
@@ -5789,6 +5695,7 @@ elfNN_hpux_backend_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
 #define elf_backend_reloc_type_class   elfNN_ia64_reloc_type_class
 #define elf_backend_rela_normal                1
 #define elf_backend_special_sections   elfNN_ia64_special_sections
 #define elf_backend_reloc_type_class   elfNN_ia64_reloc_type_class
 #define elf_backend_rela_normal                1
 #define elf_backend_special_sections   elfNN_ia64_special_sections
+#define elf_backend_default_execstack  0
 
 /* 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.
 
 /* 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.
@@ -5822,8 +5729,9 @@ elfNN_hpux_backend_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
 #undef  elf_backend_want_p_paddr_set_to_zero
 #define elf_backend_want_p_paddr_set_to_zero 1
 
 #undef  elf_backend_want_p_paddr_set_to_zero
 #define elf_backend_want_p_paddr_set_to_zero 1
 
-#undef  ELF_MAXPAGESIZE
-#define ELF_MAXPAGESIZE                 0x1000  /* 1K */
+#undef ELF_COMMONPAGESIZE
+#undef ELF_OSABI
+#define ELF_OSABI                      ELFOSABI_HPUX
 
 #undef  elfNN_bed
 #define elfNN_bed elfNN_ia64_hpux_bed
 
 #undef  elfNN_bed
 #define elfNN_bed elfNN_ia64_hpux_bed