Back to index

cell-binutils  2.17cvs20070401
elfxx-ia64.c
Go to the documentation of this file.
00001 /* IA-64 support for 64-bit ELF
00002    Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
00003    Free Software Foundation, Inc.
00004    Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
00005 
00006    This file is part of BFD, the Binary File Descriptor library.
00007 
00008    This program is free software; you can redistribute it and/or modify
00009    it under the terms of the GNU General Public License as published by
00010    the Free Software Foundation; either version 2 of the License, or
00011    (at your option) any later version.
00012 
00013    This program is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016    GNU General Public License for more details.
00017 
00018    You should have received a copy of the GNU General Public License
00019    along with this program; if not, write to the Free Software
00020    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00021 
00022 #include "bfd.h"
00023 #include "sysdep.h"
00024 #include "libbfd.h"
00025 #include "elf-bfd.h"
00026 #include "opcode/ia64.h"
00027 #include "elf/ia64.h"
00028 #include "objalloc.h"
00029 #include "hashtab.h"
00030 
00031 #define ARCH_SIZE    NN
00032 
00033 #if ARCH_SIZE == 64
00034 #define       LOG_SECTION_ALIGN    3
00035 #endif
00036 
00037 #if ARCH_SIZE == 32
00038 #define       LOG_SECTION_ALIGN    2
00039 #endif
00040 
00041 /* THE RULES for all the stuff the linker creates --
00042 
00043   GOT         Entries created in response to LTOFF or LTOFF_FPTR
00044               relocations.  Dynamic relocs created for dynamic
00045               symbols in an application; REL relocs for locals
00046               in a shared library.
00047 
00048   FPTR        The canonical function descriptor.  Created for local
00049               symbols in applications.  Descriptors for dynamic symbols
00050               and local symbols in shared libraries are created by
00051               ld.so.  Thus there are no dynamic relocs against these
00052               objects.  The FPTR relocs for such _are_ passed through
00053               to the dynamic relocation tables.
00054 
00055   FULL_PLT    Created for a PCREL21B relocation against a dynamic symbol.
00056               Requires the creation of a PLTOFF entry.  This does not
00057               require any dynamic relocations.
00058 
00059   PLTOFF      Created by PLTOFF relocations.  For local symbols, this
00060               is an alternate function descriptor, and in shared libraries
00061               requires two REL relocations.  Note that this cannot be
00062               transformed into an FPTR relocation, since it must be in
00063               range of the GP.  For dynamic symbols, this is a function
00064               descriptor for a MIN_PLT entry, and requires one IPLT reloc.
00065 
00066   MIN_PLT     Created by PLTOFF entries against dynamic symbols.  This
00067               does not require dynamic relocations.  */
00068 
00069 #define NELEMS(a)    ((int) (sizeof (a) / sizeof ((a)[0])))
00070 
00071 typedef struct bfd_hash_entry *(*new_hash_entry_func)
00072   PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
00073 
00074 /* In dynamically (linker-) created sections, we generally need to keep track
00075    of the place a symbol or expression got allocated to. This is done via hash
00076    tables that store entries of the following type.  */
00077 
00078 struct elfNN_ia64_dyn_sym_info
00079 {
00080   /* The addend for which this entry is relevant.  */
00081   bfd_vma addend;
00082 
00083   bfd_vma got_offset;
00084   bfd_vma fptr_offset;
00085   bfd_vma pltoff_offset;
00086   bfd_vma plt_offset;
00087   bfd_vma plt2_offset;
00088   bfd_vma tprel_offset;
00089   bfd_vma dtpmod_offset;
00090   bfd_vma dtprel_offset;
00091 
00092   /* The symbol table entry, if any, that this was derived from.  */
00093   struct elf_link_hash_entry *h;
00094 
00095   /* Used to count non-got, non-plt relocations for delayed sizing
00096      of relocation sections.  */
00097   struct elfNN_ia64_dyn_reloc_entry
00098   {
00099     struct elfNN_ia64_dyn_reloc_entry *next;
00100     asection *srel;
00101     int type;
00102     int count;
00103 
00104     /* Is this reloc against readonly section? */
00105     bfd_boolean reltext;
00106   } *reloc_entries;
00107 
00108   /* TRUE when the section contents have been updated.  */
00109   unsigned got_done : 1;
00110   unsigned fptr_done : 1;
00111   unsigned pltoff_done : 1;
00112   unsigned tprel_done : 1;
00113   unsigned dtpmod_done : 1;
00114   unsigned dtprel_done : 1;
00115 
00116   /* TRUE for the different kinds of linker data we want created.  */
00117   unsigned want_got : 1;
00118   unsigned want_gotx : 1;
00119   unsigned want_fptr : 1;
00120   unsigned want_ltoff_fptr : 1;
00121   unsigned want_plt : 1;
00122   unsigned want_plt2 : 1;
00123   unsigned want_pltoff : 1;
00124   unsigned want_tprel : 1;
00125   unsigned want_dtpmod : 1;
00126   unsigned want_dtprel : 1;
00127 };
00128 
00129 struct elfNN_ia64_local_hash_entry
00130 {
00131   int id;
00132   unsigned int r_sym;
00133   /* The number of elements in elfNN_ia64_dyn_sym_info array.  */
00134   unsigned int count;
00135   /* The number of sorted elements in elfNN_ia64_dyn_sym_info array.  */
00136   unsigned int sorted_count;
00137   /* The size of elfNN_ia64_dyn_sym_info array.  */
00138   unsigned int size;
00139   /* The array of elfNN_ia64_dyn_sym_info.  */
00140   struct elfNN_ia64_dyn_sym_info *info;
00141 
00142   /* TRUE if this hash entry's addends was translated for
00143      SHF_MERGE optimization.  */
00144   unsigned sec_merge_done : 1;
00145 };
00146 
00147 struct elfNN_ia64_link_hash_entry
00148 {
00149   struct elf_link_hash_entry root;
00150   /* The number of elements in elfNN_ia64_dyn_sym_info array.  */
00151   unsigned int count;
00152   /* The number of sorted elements in elfNN_ia64_dyn_sym_info array.  */
00153   unsigned int sorted_count;
00154   /* The size of elfNN_ia64_dyn_sym_info array.  */
00155   unsigned int size;
00156   /* The array of elfNN_ia64_dyn_sym_info.  */
00157   struct elfNN_ia64_dyn_sym_info *info;
00158 };
00159 
00160 struct elfNN_ia64_link_hash_table
00161 {
00162   /* The main hash table.  */
00163   struct elf_link_hash_table root;
00164 
00165   asection *got_sec;        /* the linkage table section (or NULL) */
00166   asection *rel_got_sec;    /* dynamic relocation section for same */
00167   asection *fptr_sec;              /* function descriptor table (or NULL) */
00168   asection *rel_fptr_sec;   /* dynamic relocation section for same */
00169   asection *plt_sec;        /* the primary plt section (or NULL) */
00170   asection *pltoff_sec;            /* private descriptors for plt (or NULL) */
00171   asection *rel_pltoff_sec; /* dynamic relocation section for same */
00172 
00173   bfd_size_type minplt_entries;    /* number of minplt entries */
00174   unsigned reltext : 1;            /* are there relocs against readonly sections? */
00175   unsigned self_dtpmod_done : 1;/* has self DTPMOD entry been finished? */
00176   bfd_vma self_dtpmod_offset;      /* .got offset to self DTPMOD entry */
00177 
00178   htab_t loc_hash_table;
00179   void *loc_hash_memory;
00180 };
00181 
00182 struct elfNN_ia64_allocate_data
00183 {
00184   struct bfd_link_info *info;
00185   bfd_size_type ofs;
00186   bfd_boolean only_got;
00187 };
00188 
00189 #define elfNN_ia64_hash_table(p) \
00190   ((struct elfNN_ia64_link_hash_table *) ((p)->hash))
00191 
00192 static bfd_reloc_status_type elfNN_ia64_reloc
00193   PARAMS ((bfd *abfd, arelent *reloc, asymbol *sym, PTR data,
00194           asection *input_section, bfd *output_bfd, char **error_message));
00195 static reloc_howto_type * lookup_howto
00196   PARAMS ((unsigned int rtype));
00197 static reloc_howto_type *elfNN_ia64_reloc_type_lookup
00198   PARAMS ((bfd *abfd, bfd_reloc_code_real_type bfd_code));
00199 static void elfNN_ia64_info_to_howto
00200   PARAMS ((bfd *abfd, arelent *bfd_reloc, Elf_Internal_Rela *elf_reloc));
00201 static bfd_boolean elfNN_ia64_relax_section
00202   PARAMS((bfd *abfd, asection *sec, struct bfd_link_info *link_info,
00203          bfd_boolean *again));
00204 static void elfNN_ia64_relax_ldxmov
00205   PARAMS((bfd_byte *contents, bfd_vma off));
00206 static bfd_boolean is_unwind_section_name
00207   PARAMS ((bfd *abfd, const char *));
00208 static bfd_boolean elfNN_ia64_section_flags
00209   PARAMS ((flagword *, const Elf_Internal_Shdr *));
00210 static bfd_boolean elfNN_ia64_fake_sections
00211   PARAMS ((bfd *abfd, Elf_Internal_Shdr *hdr, asection *sec));
00212 static void elfNN_ia64_final_write_processing
00213   PARAMS ((bfd *abfd, bfd_boolean linker));
00214 static bfd_boolean elfNN_ia64_add_symbol_hook
00215   PARAMS ((bfd *abfd, struct bfd_link_info *info, Elf_Internal_Sym *sym,
00216           const char **namep, flagword *flagsp, asection **secp,
00217           bfd_vma *valp));
00218 static bfd_boolean elfNN_ia64_is_local_label_name
00219   PARAMS ((bfd *abfd, const char *name));
00220 static bfd_boolean elfNN_ia64_dynamic_symbol_p
00221   PARAMS ((struct elf_link_hash_entry *h, struct bfd_link_info *info, int));
00222 static struct bfd_hash_entry *elfNN_ia64_new_elf_hash_entry
00223   PARAMS ((struct bfd_hash_entry *entry, struct bfd_hash_table *table,
00224           const char *string));
00225 static void elfNN_ia64_hash_copy_indirect
00226   PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *,
00227           struct elf_link_hash_entry *));
00228 static void elfNN_ia64_hash_hide_symbol
00229   PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *, bfd_boolean));
00230 static hashval_t elfNN_ia64_local_htab_hash PARAMS ((const void *));
00231 static int elfNN_ia64_local_htab_eq PARAMS ((const void *ptr1,
00232                                         const void *ptr2));
00233 static struct bfd_link_hash_table *elfNN_ia64_hash_table_create
00234   PARAMS ((bfd *abfd));
00235 static void elfNN_ia64_hash_table_free
00236   PARAMS ((struct bfd_link_hash_table *hash));
00237 static bfd_boolean elfNN_ia64_global_dyn_sym_thunk
00238   PARAMS ((struct bfd_hash_entry *, PTR));
00239 static int elfNN_ia64_local_dyn_sym_thunk
00240   PARAMS ((void **, PTR));
00241 static void elfNN_ia64_dyn_sym_traverse
00242   PARAMS ((struct elfNN_ia64_link_hash_table *ia64_info,
00243           bfd_boolean (*func) (struct elfNN_ia64_dyn_sym_info *, PTR),
00244           PTR info));
00245 static bfd_boolean elfNN_ia64_create_dynamic_sections
00246   PARAMS ((bfd *abfd, struct bfd_link_info *info));
00247 static struct elfNN_ia64_local_hash_entry * get_local_sym_hash
00248   PARAMS ((struct elfNN_ia64_link_hash_table *ia64_info,
00249           bfd *abfd, const Elf_Internal_Rela *rel, bfd_boolean create));
00250 static struct elfNN_ia64_dyn_sym_info * get_dyn_sym_info
00251   PARAMS ((struct elfNN_ia64_link_hash_table *ia64_info,
00252           struct elf_link_hash_entry *h,
00253           bfd *abfd, const Elf_Internal_Rela *rel, bfd_boolean create));
00254 static asection *get_got
00255   PARAMS ((bfd *abfd, struct bfd_link_info *info,
00256           struct elfNN_ia64_link_hash_table *ia64_info));
00257 static asection *get_fptr
00258   PARAMS ((bfd *abfd, struct bfd_link_info *info,
00259           struct elfNN_ia64_link_hash_table *ia64_info));
00260 static asection *get_pltoff
00261   PARAMS ((bfd *abfd, struct bfd_link_info *info,
00262           struct elfNN_ia64_link_hash_table *ia64_info));
00263 static asection *get_reloc_section
00264   PARAMS ((bfd *abfd, struct elfNN_ia64_link_hash_table *ia64_info,
00265           asection *sec, bfd_boolean create));
00266 static bfd_boolean elfNN_ia64_check_relocs
00267   PARAMS ((bfd *abfd, struct bfd_link_info *info, asection *sec,
00268           const Elf_Internal_Rela *relocs));
00269 static bfd_boolean elfNN_ia64_adjust_dynamic_symbol
00270   PARAMS ((struct bfd_link_info *info, struct elf_link_hash_entry *h));
00271 static long global_sym_index
00272   PARAMS ((struct elf_link_hash_entry *h));
00273 static bfd_boolean allocate_fptr
00274   PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
00275 static bfd_boolean allocate_global_data_got
00276   PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
00277 static bfd_boolean allocate_global_fptr_got
00278   PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
00279 static bfd_boolean allocate_local_got
00280   PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
00281 static bfd_boolean allocate_pltoff_entries
00282   PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
00283 static bfd_boolean allocate_plt_entries
00284   PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
00285 static bfd_boolean allocate_plt2_entries
00286   PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
00287 static bfd_boolean allocate_dynrel_entries
00288   PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
00289 static bfd_boolean elfNN_ia64_size_dynamic_sections
00290   PARAMS ((bfd *output_bfd, struct bfd_link_info *info));
00291 static bfd_reloc_status_type elfNN_ia64_install_value
00292   PARAMS ((bfd_byte *hit_addr, bfd_vma val, unsigned int r_type));
00293 static void elfNN_ia64_install_dyn_reloc
00294   PARAMS ((bfd *abfd, struct bfd_link_info *info, asection *sec,
00295           asection *srel, bfd_vma offset, unsigned int type,
00296           long dynindx, bfd_vma addend));
00297 static bfd_vma set_got_entry
00298   PARAMS ((bfd *abfd, struct bfd_link_info *info,
00299           struct elfNN_ia64_dyn_sym_info *dyn_i, long dynindx,
00300           bfd_vma addend, bfd_vma value, unsigned int dyn_r_type));
00301 static bfd_vma set_fptr_entry
00302   PARAMS ((bfd *abfd, struct bfd_link_info *info,
00303           struct elfNN_ia64_dyn_sym_info *dyn_i,
00304           bfd_vma value));
00305 static bfd_vma set_pltoff_entry
00306   PARAMS ((bfd *abfd, struct bfd_link_info *info,
00307           struct elfNN_ia64_dyn_sym_info *dyn_i,
00308           bfd_vma value, bfd_boolean));
00309 static bfd_vma elfNN_ia64_tprel_base
00310   PARAMS ((struct bfd_link_info *info));
00311 static bfd_vma elfNN_ia64_dtprel_base
00312   PARAMS ((struct bfd_link_info *info));
00313 static int elfNN_ia64_unwind_entry_compare
00314   PARAMS ((const PTR, const PTR));
00315 static bfd_boolean elfNN_ia64_choose_gp
00316   PARAMS ((bfd *abfd, struct bfd_link_info *info));
00317 static bfd_boolean elfNN_ia64_final_link
00318   PARAMS ((bfd *abfd, struct bfd_link_info *info));
00319 static bfd_boolean elfNN_ia64_relocate_section
00320   PARAMS ((bfd *output_bfd, struct bfd_link_info *info, bfd *input_bfd,
00321           asection *input_section, bfd_byte *contents,
00322           Elf_Internal_Rela *relocs, Elf_Internal_Sym *local_syms,
00323           asection **local_sections));
00324 static bfd_boolean elfNN_ia64_finish_dynamic_symbol
00325   PARAMS ((bfd *output_bfd, struct bfd_link_info *info,
00326           struct elf_link_hash_entry *h, Elf_Internal_Sym *sym));
00327 static bfd_boolean elfNN_ia64_finish_dynamic_sections
00328   PARAMS ((bfd *abfd, struct bfd_link_info *info));
00329 static bfd_boolean elfNN_ia64_set_private_flags
00330   PARAMS ((bfd *abfd, flagword flags));
00331 static bfd_boolean elfNN_ia64_merge_private_bfd_data
00332   PARAMS ((bfd *ibfd, bfd *obfd));
00333 static bfd_boolean elfNN_ia64_print_private_bfd_data
00334   PARAMS ((bfd *abfd, PTR ptr));
00335 static enum elf_reloc_type_class elfNN_ia64_reloc_type_class
00336   PARAMS ((const Elf_Internal_Rela *));
00337 static bfd_boolean elfNN_ia64_hpux_vec
00338   PARAMS ((const bfd_target *vec));
00339 static void elfNN_hpux_post_process_headers
00340   PARAMS ((bfd *abfd, struct bfd_link_info *info));
00341 bfd_boolean elfNN_hpux_backend_section_from_bfd_section
00342   PARAMS ((bfd *abfd, asection *sec, int *retval));
00343 
00344 /* ia64-specific relocation.  */
00345 
00346 /* Perform a relocation.  Not much to do here as all the hard work is
00347    done in elfNN_ia64_final_link_relocate.  */
00348 static bfd_reloc_status_type
00349 elfNN_ia64_reloc (abfd, reloc, sym, data, input_section,
00350                 output_bfd, error_message)
00351      bfd *abfd ATTRIBUTE_UNUSED;
00352      arelent *reloc;
00353      asymbol *sym ATTRIBUTE_UNUSED;
00354      PTR data ATTRIBUTE_UNUSED;
00355      asection *input_section;
00356      bfd *output_bfd;
00357      char **error_message;
00358 {
00359   if (output_bfd)
00360     {
00361       reloc->address += input_section->output_offset;
00362       return bfd_reloc_ok;
00363     }
00364 
00365   if (input_section->flags & SEC_DEBUGGING)
00366     return bfd_reloc_continue;
00367 
00368   *error_message = "Unsupported call to elfNN_ia64_reloc";
00369   return bfd_reloc_notsupported;
00370 }
00371 
00372 #define IA64_HOWTO(TYPE, NAME, SIZE, PCREL, IN)                \
00373   HOWTO (TYPE, 0, SIZE, 0, PCREL, 0, complain_overflow_signed, \
00374         elfNN_ia64_reloc, NAME, FALSE, 0, -1, IN)
00375 
00376 /* This table has to be sorted according to increasing number of the
00377    TYPE field.  */
00378 static reloc_howto_type ia64_howto_table[] =
00379   {
00380     IA64_HOWTO (R_IA64_NONE,           "NONE",      0, FALSE, TRUE),
00381 
00382     IA64_HOWTO (R_IA64_IMM14,          "IMM14",     0, FALSE, TRUE),
00383     IA64_HOWTO (R_IA64_IMM22,          "IMM22",     0, FALSE, TRUE),
00384     IA64_HOWTO (R_IA64_IMM64,          "IMM64",     0, FALSE, TRUE),
00385     IA64_HOWTO (R_IA64_DIR32MSB,    "DIR32MSB",     2, FALSE, TRUE),
00386     IA64_HOWTO (R_IA64_DIR32LSB,    "DIR32LSB",     2, FALSE, TRUE),
00387     IA64_HOWTO (R_IA64_DIR64MSB,    "DIR64MSB",     4, FALSE, TRUE),
00388     IA64_HOWTO (R_IA64_DIR64LSB,    "DIR64LSB",     4, FALSE, TRUE),
00389 
00390     IA64_HOWTO (R_IA64_GPREL22,        "GPREL22",          0, FALSE, TRUE),
00391     IA64_HOWTO (R_IA64_GPREL64I,    "GPREL64I",     0, FALSE, TRUE),
00392     IA64_HOWTO (R_IA64_GPREL32MSB,  "GPREL32MSB",  2, FALSE, TRUE),
00393     IA64_HOWTO (R_IA64_GPREL32LSB,  "GPREL32LSB",  2, FALSE, TRUE),
00394     IA64_HOWTO (R_IA64_GPREL64MSB,  "GPREL64MSB",  4, FALSE, TRUE),
00395     IA64_HOWTO (R_IA64_GPREL64LSB,  "GPREL64LSB",  4, FALSE, TRUE),
00396 
00397     IA64_HOWTO (R_IA64_LTOFF22,        "LTOFF22",          0, FALSE, TRUE),
00398     IA64_HOWTO (R_IA64_LTOFF64I,    "LTOFF64I",     0, FALSE, TRUE),
00399 
00400     IA64_HOWTO (R_IA64_PLTOFF22,    "PLTOFF22",     0, FALSE, TRUE),
00401     IA64_HOWTO (R_IA64_PLTOFF64I,   "PLTOFF64I",   0, FALSE, TRUE),
00402     IA64_HOWTO (R_IA64_PLTOFF64MSB, "PLTOFF64MSB", 4, FALSE, TRUE),
00403     IA64_HOWTO (R_IA64_PLTOFF64LSB, "PLTOFF64LSB", 4, FALSE, TRUE),
00404 
00405     IA64_HOWTO (R_IA64_FPTR64I,        "FPTR64I",          0, FALSE, TRUE),
00406     IA64_HOWTO (R_IA64_FPTR32MSB,   "FPTR32MSB",   2, FALSE, TRUE),
00407     IA64_HOWTO (R_IA64_FPTR32LSB,   "FPTR32LSB",   2, FALSE, TRUE),
00408     IA64_HOWTO (R_IA64_FPTR64MSB,   "FPTR64MSB",   4, FALSE, TRUE),
00409     IA64_HOWTO (R_IA64_FPTR64LSB,   "FPTR64LSB",   4, FALSE, TRUE),
00410 
00411     IA64_HOWTO (R_IA64_PCREL60B,    "PCREL60B",     0, TRUE, TRUE),
00412     IA64_HOWTO (R_IA64_PCREL21B,    "PCREL21B",     0, TRUE, TRUE),
00413     IA64_HOWTO (R_IA64_PCREL21M,    "PCREL21M",     0, TRUE, TRUE),
00414     IA64_HOWTO (R_IA64_PCREL21F,    "PCREL21F",     0, TRUE, TRUE),
00415     IA64_HOWTO (R_IA64_PCREL32MSB,  "PCREL32MSB",  2, TRUE, TRUE),
00416     IA64_HOWTO (R_IA64_PCREL32LSB,  "PCREL32LSB",  2, TRUE, TRUE),
00417     IA64_HOWTO (R_IA64_PCREL64MSB,  "PCREL64MSB",  4, TRUE, TRUE),
00418     IA64_HOWTO (R_IA64_PCREL64LSB,  "PCREL64LSB",  4, TRUE, TRUE),
00419 
00420     IA64_HOWTO (R_IA64_LTOFF_FPTR22, "LTOFF_FPTR22", 0, FALSE, TRUE),
00421     IA64_HOWTO (R_IA64_LTOFF_FPTR64I, "LTOFF_FPTR64I", 0, FALSE, TRUE),
00422     IA64_HOWTO (R_IA64_LTOFF_FPTR32MSB, "LTOFF_FPTR32MSB", 2, FALSE, TRUE),
00423     IA64_HOWTO (R_IA64_LTOFF_FPTR32LSB, "LTOFF_FPTR32LSB", 2, FALSE, TRUE),
00424     IA64_HOWTO (R_IA64_LTOFF_FPTR64MSB, "LTOFF_FPTR64MSB", 4, FALSE, TRUE),
00425     IA64_HOWTO (R_IA64_LTOFF_FPTR64LSB, "LTOFF_FPTR64LSB", 4, FALSE, TRUE),
00426 
00427     IA64_HOWTO (R_IA64_SEGREL32MSB, "SEGREL32MSB", 2, FALSE, TRUE),
00428     IA64_HOWTO (R_IA64_SEGREL32LSB, "SEGREL32LSB", 2, FALSE, TRUE),
00429     IA64_HOWTO (R_IA64_SEGREL64MSB, "SEGREL64MSB", 4, FALSE, TRUE),
00430     IA64_HOWTO (R_IA64_SEGREL64LSB, "SEGREL64LSB", 4, FALSE, TRUE),
00431 
00432     IA64_HOWTO (R_IA64_SECREL32MSB, "SECREL32MSB", 2, FALSE, TRUE),
00433     IA64_HOWTO (R_IA64_SECREL32LSB, "SECREL32LSB", 2, FALSE, TRUE),
00434     IA64_HOWTO (R_IA64_SECREL64MSB, "SECREL64MSB", 4, FALSE, TRUE),
00435     IA64_HOWTO (R_IA64_SECREL64LSB, "SECREL64LSB", 4, FALSE, TRUE),
00436 
00437     IA64_HOWTO (R_IA64_REL32MSB,    "REL32MSB",     2, FALSE, TRUE),
00438     IA64_HOWTO (R_IA64_REL32LSB,    "REL32LSB",     2, FALSE, TRUE),
00439     IA64_HOWTO (R_IA64_REL64MSB,    "REL64MSB",     4, FALSE, TRUE),
00440     IA64_HOWTO (R_IA64_REL64LSB,    "REL64LSB",     4, FALSE, TRUE),
00441 
00442     IA64_HOWTO (R_IA64_LTV32MSB,    "LTV32MSB",     2, FALSE, TRUE),
00443     IA64_HOWTO (R_IA64_LTV32LSB,    "LTV32LSB",     2, FALSE, TRUE),
00444     IA64_HOWTO (R_IA64_LTV64MSB,    "LTV64MSB",     4, FALSE, TRUE),
00445     IA64_HOWTO (R_IA64_LTV64LSB,    "LTV64LSB",     4, FALSE, TRUE),
00446 
00447     IA64_HOWTO (R_IA64_PCREL21BI,   "PCREL21BI",   0, TRUE, TRUE),
00448     IA64_HOWTO (R_IA64_PCREL22,     "PCREL22",     0, TRUE, TRUE),
00449     IA64_HOWTO (R_IA64_PCREL64I,    "PCREL64I",    0, TRUE, TRUE),
00450 
00451     IA64_HOWTO (R_IA64_IPLTMSB,        "IPLTMSB",          4, FALSE, TRUE),
00452     IA64_HOWTO (R_IA64_IPLTLSB,        "IPLTLSB",          4, FALSE, TRUE),
00453     IA64_HOWTO (R_IA64_COPY,           "COPY",      4, FALSE, TRUE),
00454     IA64_HOWTO (R_IA64_LTOFF22X,    "LTOFF22X",     0, FALSE, TRUE),
00455     IA64_HOWTO (R_IA64_LDXMOV,         "LDXMOV",    0, FALSE, TRUE),
00456 
00457     IA64_HOWTO (R_IA64_TPREL14,        "TPREL14",          0, FALSE, FALSE),
00458     IA64_HOWTO (R_IA64_TPREL22,        "TPREL22",          0, FALSE, FALSE),
00459     IA64_HOWTO (R_IA64_TPREL64I,    "TPREL64I",     0, FALSE, FALSE),
00460     IA64_HOWTO (R_IA64_TPREL64MSB,  "TPREL64MSB",  4, FALSE, FALSE),
00461     IA64_HOWTO (R_IA64_TPREL64LSB,  "TPREL64LSB",  4, FALSE, FALSE),
00462     IA64_HOWTO (R_IA64_LTOFF_TPREL22, "LTOFF_TPREL22",  0, FALSE, FALSE),
00463 
00464     IA64_HOWTO (R_IA64_DTPMOD64MSB, "DTPMOD64MSB",  4, FALSE, FALSE),
00465     IA64_HOWTO (R_IA64_DTPMOD64LSB, "DTPMOD64LSB",  4, FALSE, FALSE),
00466     IA64_HOWTO (R_IA64_LTOFF_DTPMOD22, "LTOFF_DTPMOD22", 0, FALSE, FALSE),
00467 
00468     IA64_HOWTO (R_IA64_DTPREL14,    "DTPREL14",     0, FALSE, FALSE),
00469     IA64_HOWTO (R_IA64_DTPREL22,    "DTPREL22",     0, FALSE, FALSE),
00470     IA64_HOWTO (R_IA64_DTPREL64I,   "DTPREL64I",   0, FALSE, FALSE),
00471     IA64_HOWTO (R_IA64_DTPREL32MSB, "DTPREL32MSB", 2, FALSE, FALSE),
00472     IA64_HOWTO (R_IA64_DTPREL32LSB, "DTPREL32LSB", 2, FALSE, FALSE),
00473     IA64_HOWTO (R_IA64_DTPREL64MSB, "DTPREL64MSB", 4, FALSE, FALSE),
00474     IA64_HOWTO (R_IA64_DTPREL64LSB, "DTPREL64LSB", 4, FALSE, FALSE),
00475     IA64_HOWTO (R_IA64_LTOFF_DTPREL22, "LTOFF_DTPREL22", 0, FALSE, FALSE),
00476   };
00477 
00478 static unsigned char elf_code_to_howto_index[R_IA64_MAX_RELOC_CODE + 1];
00479 
00480 /* Given a BFD reloc type, return the matching HOWTO structure.  */
00481 
00482 static reloc_howto_type *
00483 lookup_howto (rtype)
00484      unsigned int rtype;
00485 {
00486   static int inited = 0;
00487   int i;
00488 
00489   if (!inited)
00490     {
00491       inited = 1;
00492 
00493       memset (elf_code_to_howto_index, 0xff, sizeof (elf_code_to_howto_index));
00494       for (i = 0; i < NELEMS (ia64_howto_table); ++i)
00495        elf_code_to_howto_index[ia64_howto_table[i].type] = i;
00496     }
00497 
00498   if (rtype > R_IA64_MAX_RELOC_CODE)
00499     return 0;
00500   i = elf_code_to_howto_index[rtype];
00501   if (i >= NELEMS (ia64_howto_table))
00502     return 0;
00503   return ia64_howto_table + i;
00504 }
00505 
00506 static reloc_howto_type*
00507 elfNN_ia64_reloc_type_lookup (abfd, bfd_code)
00508      bfd *abfd ATTRIBUTE_UNUSED;
00509      bfd_reloc_code_real_type bfd_code;
00510 {
00511   unsigned int rtype;
00512 
00513   switch (bfd_code)
00514     {
00515     case BFD_RELOC_NONE:           rtype = R_IA64_NONE; break;
00516 
00517     case BFD_RELOC_IA64_IMM14:            rtype = R_IA64_IMM14; break;
00518     case BFD_RELOC_IA64_IMM22:            rtype = R_IA64_IMM22; break;
00519     case BFD_RELOC_IA64_IMM64:            rtype = R_IA64_IMM64; break;
00520 
00521     case BFD_RELOC_IA64_DIR32MSB:  rtype = R_IA64_DIR32MSB; break;
00522     case BFD_RELOC_IA64_DIR32LSB:  rtype = R_IA64_DIR32LSB; break;
00523     case BFD_RELOC_IA64_DIR64MSB:  rtype = R_IA64_DIR64MSB; break;
00524     case BFD_RELOC_IA64_DIR64LSB:  rtype = R_IA64_DIR64LSB; break;
00525 
00526     case BFD_RELOC_IA64_GPREL22:   rtype = R_IA64_GPREL22; break;
00527     case BFD_RELOC_IA64_GPREL64I:  rtype = R_IA64_GPREL64I; break;
00528     case BFD_RELOC_IA64_GPREL32MSB:       rtype = R_IA64_GPREL32MSB; break;
00529     case BFD_RELOC_IA64_GPREL32LSB:       rtype = R_IA64_GPREL32LSB; break;
00530     case BFD_RELOC_IA64_GPREL64MSB:       rtype = R_IA64_GPREL64MSB; break;
00531     case BFD_RELOC_IA64_GPREL64LSB:       rtype = R_IA64_GPREL64LSB; break;
00532 
00533     case BFD_RELOC_IA64_LTOFF22:   rtype = R_IA64_LTOFF22; break;
00534     case BFD_RELOC_IA64_LTOFF64I:  rtype = R_IA64_LTOFF64I; break;
00535 
00536     case BFD_RELOC_IA64_PLTOFF22:  rtype = R_IA64_PLTOFF22; break;
00537     case BFD_RELOC_IA64_PLTOFF64I: rtype = R_IA64_PLTOFF64I; break;
00538     case BFD_RELOC_IA64_PLTOFF64MSB:      rtype = R_IA64_PLTOFF64MSB; break;
00539     case BFD_RELOC_IA64_PLTOFF64LSB:      rtype = R_IA64_PLTOFF64LSB; break;
00540     case BFD_RELOC_IA64_FPTR64I:   rtype = R_IA64_FPTR64I; break;
00541     case BFD_RELOC_IA64_FPTR32MSB: rtype = R_IA64_FPTR32MSB; break;
00542     case BFD_RELOC_IA64_FPTR32LSB: rtype = R_IA64_FPTR32LSB; break;
00543     case BFD_RELOC_IA64_FPTR64MSB: rtype = R_IA64_FPTR64MSB; break;
00544     case BFD_RELOC_IA64_FPTR64LSB: rtype = R_IA64_FPTR64LSB; break;
00545 
00546     case BFD_RELOC_IA64_PCREL21B:  rtype = R_IA64_PCREL21B; break;
00547     case BFD_RELOC_IA64_PCREL21BI: rtype = R_IA64_PCREL21BI; break;
00548     case BFD_RELOC_IA64_PCREL21M:  rtype = R_IA64_PCREL21M; break;
00549     case BFD_RELOC_IA64_PCREL21F:  rtype = R_IA64_PCREL21F; break;
00550     case BFD_RELOC_IA64_PCREL22:   rtype = R_IA64_PCREL22; break;
00551     case BFD_RELOC_IA64_PCREL60B:  rtype = R_IA64_PCREL60B; break;
00552     case BFD_RELOC_IA64_PCREL64I:  rtype = R_IA64_PCREL64I; break;
00553     case BFD_RELOC_IA64_PCREL32MSB:       rtype = R_IA64_PCREL32MSB; break;
00554     case BFD_RELOC_IA64_PCREL32LSB:       rtype = R_IA64_PCREL32LSB; break;
00555     case BFD_RELOC_IA64_PCREL64MSB:       rtype = R_IA64_PCREL64MSB; break;
00556     case BFD_RELOC_IA64_PCREL64LSB:       rtype = R_IA64_PCREL64LSB; break;
00557 
00558     case BFD_RELOC_IA64_LTOFF_FPTR22:     rtype = R_IA64_LTOFF_FPTR22; break;
00559     case BFD_RELOC_IA64_LTOFF_FPTR64I:    rtype = R_IA64_LTOFF_FPTR64I; break;
00560     case BFD_RELOC_IA64_LTOFF_FPTR32MSB: rtype = R_IA64_LTOFF_FPTR32MSB; break;
00561     case BFD_RELOC_IA64_LTOFF_FPTR32LSB: rtype = R_IA64_LTOFF_FPTR32LSB; break;
00562     case BFD_RELOC_IA64_LTOFF_FPTR64MSB: rtype = R_IA64_LTOFF_FPTR64MSB; break;
00563     case BFD_RELOC_IA64_LTOFF_FPTR64LSB: rtype = R_IA64_LTOFF_FPTR64LSB; break;
00564 
00565     case BFD_RELOC_IA64_SEGREL32MSB:      rtype = R_IA64_SEGREL32MSB; break;
00566     case BFD_RELOC_IA64_SEGREL32LSB:      rtype = R_IA64_SEGREL32LSB; break;
00567     case BFD_RELOC_IA64_SEGREL64MSB:      rtype = R_IA64_SEGREL64MSB; break;
00568     case BFD_RELOC_IA64_SEGREL64LSB:      rtype = R_IA64_SEGREL64LSB; break;
00569 
00570     case BFD_RELOC_IA64_SECREL32MSB:      rtype = R_IA64_SECREL32MSB; break;
00571     case BFD_RELOC_IA64_SECREL32LSB:      rtype = R_IA64_SECREL32LSB; break;
00572     case BFD_RELOC_IA64_SECREL64MSB:      rtype = R_IA64_SECREL64MSB; break;
00573     case BFD_RELOC_IA64_SECREL64LSB:      rtype = R_IA64_SECREL64LSB; break;
00574 
00575     case BFD_RELOC_IA64_REL32MSB:  rtype = R_IA64_REL32MSB; break;
00576     case BFD_RELOC_IA64_REL32LSB:  rtype = R_IA64_REL32LSB; break;
00577     case BFD_RELOC_IA64_REL64MSB:  rtype = R_IA64_REL64MSB; break;
00578     case BFD_RELOC_IA64_REL64LSB:  rtype = R_IA64_REL64LSB; break;
00579 
00580     case BFD_RELOC_IA64_LTV32MSB:  rtype = R_IA64_LTV32MSB; break;
00581     case BFD_RELOC_IA64_LTV32LSB:  rtype = R_IA64_LTV32LSB; break;
00582     case BFD_RELOC_IA64_LTV64MSB:  rtype = R_IA64_LTV64MSB; break;
00583     case BFD_RELOC_IA64_LTV64LSB:  rtype = R_IA64_LTV64LSB; break;
00584 
00585     case BFD_RELOC_IA64_IPLTMSB:   rtype = R_IA64_IPLTMSB; break;
00586     case BFD_RELOC_IA64_IPLTLSB:   rtype = R_IA64_IPLTLSB; break;
00587     case BFD_RELOC_IA64_COPY:             rtype = R_IA64_COPY; break;
00588     case BFD_RELOC_IA64_LTOFF22X:  rtype = R_IA64_LTOFF22X; break;
00589     case BFD_RELOC_IA64_LDXMOV:           rtype = R_IA64_LDXMOV; break;
00590 
00591     case BFD_RELOC_IA64_TPREL14:   rtype = R_IA64_TPREL14; break;
00592     case BFD_RELOC_IA64_TPREL22:   rtype = R_IA64_TPREL22; break;
00593     case BFD_RELOC_IA64_TPREL64I:  rtype = R_IA64_TPREL64I; break;
00594     case BFD_RELOC_IA64_TPREL64MSB:       rtype = R_IA64_TPREL64MSB; break;
00595     case BFD_RELOC_IA64_TPREL64LSB:       rtype = R_IA64_TPREL64LSB; break;
00596     case BFD_RELOC_IA64_LTOFF_TPREL22:    rtype = R_IA64_LTOFF_TPREL22; break;
00597 
00598     case BFD_RELOC_IA64_DTPMOD64MSB:      rtype = R_IA64_DTPMOD64MSB; break;
00599     case BFD_RELOC_IA64_DTPMOD64LSB:      rtype = R_IA64_DTPMOD64LSB; break;
00600     case BFD_RELOC_IA64_LTOFF_DTPMOD22:   rtype = R_IA64_LTOFF_DTPMOD22; break;
00601 
00602     case BFD_RELOC_IA64_DTPREL14:  rtype = R_IA64_DTPREL14; break;
00603     case BFD_RELOC_IA64_DTPREL22:  rtype = R_IA64_DTPREL22; break;
00604     case BFD_RELOC_IA64_DTPREL64I: rtype = R_IA64_DTPREL64I; break;
00605     case BFD_RELOC_IA64_DTPREL32MSB:      rtype = R_IA64_DTPREL32MSB; break;
00606     case BFD_RELOC_IA64_DTPREL32LSB:      rtype = R_IA64_DTPREL32LSB; break;
00607     case BFD_RELOC_IA64_DTPREL64MSB:      rtype = R_IA64_DTPREL64MSB; break;
00608     case BFD_RELOC_IA64_DTPREL64LSB:      rtype = R_IA64_DTPREL64LSB; break;
00609     case BFD_RELOC_IA64_LTOFF_DTPREL22:   rtype = R_IA64_LTOFF_DTPREL22; break;
00610 
00611     default: return 0;
00612     }
00613   return lookup_howto (rtype);
00614 }
00615 
00616 static reloc_howto_type *
00617 elfNN_ia64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
00618                            const char *r_name)
00619 {
00620   unsigned int i;
00621 
00622   for (i = 0;
00623        i < sizeof (ia64_howto_table) / sizeof (ia64_howto_table[0]);
00624        i++)
00625     if (ia64_howto_table[i].name != NULL
00626        && strcasecmp (ia64_howto_table[i].name, r_name) == 0)
00627       return &ia64_howto_table[i];
00628 
00629   return NULL;
00630 }
00631 
00632 /* Given a ELF reloc, return the matching HOWTO structure.  */
00633 
00634 static void
00635 elfNN_ia64_info_to_howto (abfd, bfd_reloc, elf_reloc)
00636      bfd *abfd ATTRIBUTE_UNUSED;
00637      arelent *bfd_reloc;
00638      Elf_Internal_Rela *elf_reloc;
00639 {
00640   bfd_reloc->howto
00641     = lookup_howto ((unsigned int) ELFNN_R_TYPE (elf_reloc->r_info));
00642 }
00643 
00644 #define PLT_HEADER_SIZE            (3 * 16)
00645 #define PLT_MIN_ENTRY_SIZE  (1 * 16)
00646 #define PLT_FULL_ENTRY_SIZE (2 * 16)
00647 #define PLT_RESERVED_WORDS  3
00648 
00649 static const bfd_byte plt_header[PLT_HEADER_SIZE] =
00650 {
00651   0x0b, 0x10, 0x00, 0x1c, 0x00, 0x21,  /*   [MMI]       mov r2=r14;;       */
00652   0xe0, 0x00, 0x08, 0x00, 0x48, 0x00,  /*               addl r14=0,r2      */
00653   0x00, 0x00, 0x04, 0x00,              /*               nop.i 0x0;;        */
00654   0x0b, 0x80, 0x20, 0x1c, 0x18, 0x14,  /*   [MMI]       ld8 r16=[r14],8;;  */
00655   0x10, 0x41, 0x38, 0x30, 0x28, 0x00,  /*               ld8 r17=[r14],8    */
00656   0x00, 0x00, 0x04, 0x00,              /*               nop.i 0x0;;        */
00657   0x11, 0x08, 0x00, 0x1c, 0x18, 0x10,  /*   [MIB]       ld8 r1=[r14]       */
00658   0x60, 0x88, 0x04, 0x80, 0x03, 0x00,  /*               mov b6=r17         */
00659   0x60, 0x00, 0x80, 0x00               /*               br.few b6;;        */
00660 };
00661 
00662 static const bfd_byte plt_min_entry[PLT_MIN_ENTRY_SIZE] =
00663 {
00664   0x11, 0x78, 0x00, 0x00, 0x00, 0x24,  /*   [MIB]       mov r15=0          */
00665   0x00, 0x00, 0x00, 0x02, 0x00, 0x00,  /*               nop.i 0x0          */
00666   0x00, 0x00, 0x00, 0x40               /*               br.few 0 <PLT0>;;  */
00667 };
00668 
00669 static const bfd_byte plt_full_entry[PLT_FULL_ENTRY_SIZE] =
00670 {
00671   0x0b, 0x78, 0x00, 0x02, 0x00, 0x24,  /*   [MMI]       addl r15=0,r1;;    */
00672   0x00, 0x41, 0x3c, 0x70, 0x29, 0xc0,  /*               ld8.acq r16=[r15],8*/
00673   0x01, 0x08, 0x00, 0x84,              /*               mov r14=r1;;       */
00674   0x11, 0x08, 0x00, 0x1e, 0x18, 0x10,  /*   [MIB]       ld8 r1=[r15]       */
00675   0x60, 0x80, 0x04, 0x80, 0x03, 0x00,  /*               mov b6=r16         */
00676   0x60, 0x00, 0x80, 0x00               /*               br.few b6;;        */
00677 };
00678 
00679 #define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"
00680 
00681 static const bfd_byte oor_brl[16] =
00682 {
00683   0x05, 0x00, 0x00, 0x00, 0x01, 0x00,  /*  [MLX]        nop.m 0            */
00684   0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  /*               brl.sptk.few tgt;; */
00685   0x00, 0x00, 0x00, 0xc0
00686 };
00687 
00688 static const bfd_byte oor_ip[48] =
00689 {
00690   0x04, 0x00, 0x00, 0x00, 0x01, 0x00,  /*  [MLX]        nop.m 0            */
00691   0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,  /*               movl r15=0         */
00692   0x01, 0x00, 0x00, 0x60,
00693   0x03, 0x00, 0x00, 0x00, 0x01, 0x00,  /*  [MII]        nop.m 0            */
00694   0x00, 0x01, 0x00, 0x60, 0x00, 0x00,  /*               mov r16=ip;;       */
00695   0xf2, 0x80, 0x00, 0x80,              /*               add r16=r15,r16;;  */
00696   0x11, 0x00, 0x00, 0x00, 0x01, 0x00,  /*  [MIB]        nop.m 0            */
00697   0x60, 0x80, 0x04, 0x80, 0x03, 0x00,  /*               mov b6=r16         */
00698   0x60, 0x00, 0x80, 0x00               /*               br b6;;            */
00699 };
00700 
00701 static size_t oor_branch_size = sizeof (oor_brl);
00702 
00703 void
00704 bfd_elfNN_ia64_after_parse (int itanium)
00705 {
00706   oor_branch_size = itanium ? sizeof (oor_ip) : sizeof (oor_brl);
00707 }
00708 
00709 #define BTYPE_SHIFT  6
00710 #define Y_SHIFT             26
00711 #define X6_SHIFT     27
00712 #define X4_SHIFT     27
00713 #define X3_SHIFT     33
00714 #define X2_SHIFT     31
00715 #define X_SHIFT             33
00716 #define OPCODE_SHIFT 37
00717 
00718 #define OPCODE_BITS  (0xfLL << OPCODE_SHIFT)
00719 #define X6_BITS             (0x3fLL << X6_SHIFT)
00720 #define X4_BITS             (0xfLL << X4_SHIFT)
00721 #define X3_BITS             (0x7LL << X3_SHIFT)
00722 #define X2_BITS             (0x3LL << X2_SHIFT)
00723 #define X_BITS              (0x1LL << X_SHIFT)
00724 #define Y_BITS              (0x1LL << Y_SHIFT)
00725 #define BTYPE_BITS   (0x7LL << BTYPE_SHIFT)
00726 #define PREDICATE_BITS      (0x3fLL)
00727 
00728 #define IS_NOP_B(i) \
00729   (((i) & (OPCODE_BITS | X6_BITS)) == (2LL << OPCODE_SHIFT))
00730 #define IS_NOP_F(i) \
00731   (((i) & (OPCODE_BITS | X_BITS | X6_BITS | Y_BITS)) \
00732    == (0x1LL << X6_SHIFT))
00733 #define IS_NOP_I(i) \
00734   (((i) & (OPCODE_BITS | X3_BITS | X6_BITS | Y_BITS)) \
00735    == (0x1LL << X6_SHIFT))
00736 #define IS_NOP_M(i) \
00737   (((i) & (OPCODE_BITS | X3_BITS | X2_BITS | X4_BITS | Y_BITS)) \
00738    == (0x1LL << X4_SHIFT))
00739 #define IS_BR_COND(i) \
00740   (((i) & (OPCODE_BITS | BTYPE_BITS)) == (0x4LL << OPCODE_SHIFT))
00741 #define IS_BR_CALL(i) \
00742   (((i) & OPCODE_BITS) == (0x5LL << OPCODE_SHIFT))
00743 
00744 static bfd_boolean
00745 elfNN_ia64_relax_br (bfd_byte *contents, bfd_vma off)
00746 {
00747   unsigned int template, mlx;
00748   bfd_vma t0, t1, s0, s1, s2, br_code;
00749   long br_slot;
00750   bfd_byte *hit_addr;
00751 
00752   hit_addr = (bfd_byte *) (contents + off);
00753   br_slot = (long) hit_addr & 0x3;
00754   hit_addr -= br_slot;
00755   t0 = bfd_getl64 (hit_addr + 0);
00756   t1 = bfd_getl64 (hit_addr + 8);
00757 
00758   /* Check if we can turn br into brl.  A label is always at the start
00759      of the bundle.  Even if there are predicates on NOPs, we still
00760      perform this optimization.  */
00761   template = t0 & 0x1e;
00762   s0 = (t0 >> 5) & 0x1ffffffffffLL;
00763   s1 = ((t0 >> 46) | (t1 << 18)) & 0x1ffffffffffLL;
00764   s2 = (t1 >> 23) & 0x1ffffffffffLL;
00765   switch (br_slot)
00766     {
00767     case 0:
00768       /* Check if slot 1 and slot 2 are NOPs. Possible template is
00769          BBB.  We only need to check nop.b.  */
00770       if (!(IS_NOP_B (s1) && IS_NOP_B (s2)))
00771        return FALSE;
00772       br_code = s0;
00773       break;
00774     case 1:
00775       /* Check if slot 2 is NOP. Possible templates are MBB and BBB.
00776         For BBB, slot 0 also has to be nop.b.  */
00777       if (!((template == 0x12                           /* MBB */
00778             && IS_NOP_B (s2))
00779            || (template == 0x16                  /* BBB */
00780               && IS_NOP_B (s0)
00781               && IS_NOP_B (s2))))
00782        return FALSE;
00783       br_code = s1;
00784       break;
00785     case 2:
00786       /* Check if slot 1 is NOP. Possible templates are MIB, MBB, BBB,
00787         MMB and MFB. For BBB, slot 0 also has to be nop.b.  */
00788       if (!((template == 0x10                           /* MIB */
00789             && IS_NOP_I (s1))
00790            || (template == 0x12                  /* MBB */
00791               && IS_NOP_B (s1))
00792            || (template == 0x16                  /* BBB */
00793               && IS_NOP_B (s0)
00794               && IS_NOP_B (s1))
00795            || (template == 0x18                  /* MMB */
00796               && IS_NOP_M (s1))
00797            || (template == 0x1c                  /* MFB */
00798               && IS_NOP_F (s1))))
00799        return FALSE;
00800       br_code = s2;
00801       break;
00802     default:
00803       /* It should never happen.  */
00804       abort ();
00805     }
00806   
00807   /* We can turn br.cond/br.call into brl.cond/brl.call.  */
00808   if (!(IS_BR_COND (br_code) || IS_BR_CALL (br_code)))
00809     return FALSE;
00810 
00811   /* Turn br into brl by setting bit 40.  */
00812   br_code |= 0x1LL << 40;
00813 
00814   /* Turn the old bundle into a MLX bundle with the same stop-bit
00815      variety.  */
00816   if (t0 & 0x1)
00817     mlx = 0x5;
00818   else
00819     mlx = 0x4;
00820 
00821   if (template == 0x16)
00822     {
00823       /* For BBB, we need to put nop.m in slot 0.  We keep the original
00824         predicate only if slot 0 isn't br.  */
00825       if (br_slot == 0)
00826        t0 = 0LL;
00827       else
00828        t0 &= PREDICATE_BITS << 5;
00829       t0 |= 0x1LL << (X4_SHIFT + 5);
00830     }
00831   else
00832     {
00833       /* Keep the original instruction in slot 0.  */
00834       t0 &= 0x1ffffffffffLL << 5;
00835     }
00836 
00837   t0 |= mlx;
00838 
00839   /* Put brl in slot 1.  */
00840   t1 = br_code << 23;
00841 
00842   bfd_putl64 (t0, hit_addr);
00843   bfd_putl64 (t1, hit_addr + 8);
00844   return TRUE;
00845 }
00846 
00847 static void
00848 elfNN_ia64_relax_brl (bfd_byte *contents, bfd_vma off)
00849 {
00850   int template;
00851   bfd_byte *hit_addr;
00852   bfd_vma t0, t1, i0, i1, i2;
00853 
00854   hit_addr = (bfd_byte *) (contents + off);
00855   hit_addr -= (long) hit_addr & 0x3;
00856   t0 = bfd_getl64 (hit_addr);
00857   t1 = bfd_getl64 (hit_addr + 8);
00858 
00859   /* Keep the instruction in slot 0. */
00860   i0 = (t0 >> 5) & 0x1ffffffffffLL;
00861   /* Use nop.b for slot 1. */
00862   i1 = 0x4000000000LL;
00863   /* For slot 2, turn brl into br by masking out bit 40.  */
00864   i2 = (t1 >> 23) & 0x0ffffffffffLL;
00865 
00866   /* Turn a MLX bundle into a MBB bundle with the same stop-bit
00867      variety.  */
00868   if (t0 & 0x1)
00869     template = 0x13;
00870   else
00871     template = 0x12;
00872   t0 = (i1 << 46) | (i0 << 5) | template;
00873   t1 = (i2 << 23) | (i1 >> 18);
00874 
00875   bfd_putl64 (t0, hit_addr);
00876   bfd_putl64 (t1, hit_addr + 8);
00877 }
00878 
00879 /* Rename some of the generic section flags to better document how they
00880    are used here.  */
00881 #define skip_relax_pass_0 need_finalize_relax
00882 #define skip_relax_pass_1 has_gp_reloc
00883 
00884 
00885 /* These functions do relaxation for IA-64 ELF.  */
00886 
00887 static bfd_boolean
00888 elfNN_ia64_relax_section (abfd, sec, link_info, again)
00889      bfd *abfd;
00890      asection *sec;
00891      struct bfd_link_info *link_info;
00892      bfd_boolean *again;
00893 {
00894   struct one_fixup
00895     {
00896       struct one_fixup *next;
00897       asection *tsec;
00898       bfd_vma toff;
00899       bfd_vma trampoff;
00900     };
00901 
00902   Elf_Internal_Shdr *symtab_hdr;
00903   Elf_Internal_Rela *internal_relocs;
00904   Elf_Internal_Rela *irel, *irelend;
00905   bfd_byte *contents;
00906   Elf_Internal_Sym *isymbuf = NULL;
00907   struct elfNN_ia64_link_hash_table *ia64_info;
00908   struct one_fixup *fixups = NULL;
00909   bfd_boolean changed_contents = FALSE;
00910   bfd_boolean changed_relocs = FALSE;
00911   bfd_boolean changed_got = FALSE;
00912   bfd_boolean skip_relax_pass_0 = TRUE;
00913   bfd_boolean skip_relax_pass_1 = TRUE;
00914   bfd_vma gp = 0;
00915 
00916   /* Assume we're not going to change any sizes, and we'll only need
00917      one pass.  */
00918   *again = FALSE;
00919 
00920   /* Don't even try to relax for non-ELF outputs.  */
00921   if (!is_elf_hash_table (link_info->hash))
00922     return FALSE;
00923 
00924   /* Nothing to do if there are no relocations or there is no need for
00925      the current pass.  */
00926   if ((sec->flags & SEC_RELOC) == 0
00927       || sec->reloc_count == 0
00928       || (link_info->relax_pass == 0 && sec->skip_relax_pass_0)
00929       || (link_info->relax_pass == 1 && sec->skip_relax_pass_1))
00930     return TRUE;
00931 
00932   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
00933 
00934   /* Load the relocations for this section.  */
00935   internal_relocs = (_bfd_elf_link_read_relocs
00936                    (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
00937                     link_info->keep_memory));
00938   if (internal_relocs == NULL)
00939     return FALSE;
00940 
00941   ia64_info = elfNN_ia64_hash_table (link_info);
00942   irelend = internal_relocs + sec->reloc_count;
00943 
00944   /* Get the section contents.  */
00945   if (elf_section_data (sec)->this_hdr.contents != NULL)
00946     contents = elf_section_data (sec)->this_hdr.contents;
00947   else
00948     {
00949       if (!bfd_malloc_and_get_section (abfd, sec, &contents))
00950        goto error_return;
00951     }
00952 
00953   for (irel = internal_relocs; irel < irelend; irel++)
00954     {
00955       unsigned long r_type = ELFNN_R_TYPE (irel->r_info);
00956       bfd_vma symaddr, reladdr, trampoff, toff, roff;
00957       asection *tsec;
00958       struct one_fixup *f;
00959       bfd_size_type amt;
00960       bfd_boolean is_branch;
00961       struct elfNN_ia64_dyn_sym_info *dyn_i;
00962       char symtype;
00963 
00964       switch (r_type)
00965        {
00966        case R_IA64_PCREL21B:
00967        case R_IA64_PCREL21BI:
00968        case R_IA64_PCREL21M:
00969        case R_IA64_PCREL21F:
00970          /* In pass 1, all br relaxations are done. We can skip it. */
00971          if (link_info->relax_pass == 1)
00972            continue;
00973          skip_relax_pass_0 = FALSE;
00974          is_branch = TRUE;
00975          break;
00976 
00977        case R_IA64_PCREL60B:
00978          /* We can't optimize brl to br in pass 0 since br relaxations
00979             will increase the code size. Defer it to pass 1.  */
00980          if (link_info->relax_pass == 0)
00981            {
00982              skip_relax_pass_1 = FALSE;
00983              continue;
00984            }
00985          is_branch = TRUE;
00986          break;
00987 
00988        case R_IA64_LTOFF22X:
00989        case R_IA64_LDXMOV:
00990          /* We can't relax ldx/mov in pass 0 since br relaxations will
00991             increase the code size. Defer it to pass 1.  */
00992          if (link_info->relax_pass == 0)
00993            {
00994              skip_relax_pass_1 = FALSE;
00995              continue;
00996            }
00997          is_branch = FALSE;
00998          break;
00999 
01000        default:
01001          continue;
01002        }
01003 
01004       /* Get the value of the symbol referred to by the reloc.  */
01005       if (ELFNN_R_SYM (irel->r_info) < symtab_hdr->sh_info)
01006        {
01007          /* A local symbol.  */
01008          Elf_Internal_Sym *isym;
01009 
01010          /* Read this BFD's local symbols.  */
01011          if (isymbuf == NULL)
01012            {
01013              isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
01014              if (isymbuf == NULL)
01015               isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
01016                                           symtab_hdr->sh_info, 0,
01017                                           NULL, NULL, NULL);
01018              if (isymbuf == 0)
01019               goto error_return;
01020            }
01021 
01022          isym = isymbuf + ELFNN_R_SYM (irel->r_info);
01023          if (isym->st_shndx == SHN_UNDEF)
01024            continue; /* We can't do anything with undefined symbols.  */
01025          else if (isym->st_shndx == SHN_ABS)
01026            tsec = bfd_abs_section_ptr;
01027          else if (isym->st_shndx == SHN_COMMON)
01028            tsec = bfd_com_section_ptr;
01029          else if (isym->st_shndx == SHN_IA_64_ANSI_COMMON)
01030            tsec = bfd_com_section_ptr;
01031          else
01032            tsec = bfd_section_from_elf_index (abfd, isym->st_shndx);
01033 
01034          toff = isym->st_value;
01035          dyn_i = get_dyn_sym_info (ia64_info, NULL, abfd, irel, FALSE);
01036          symtype = ELF_ST_TYPE (isym->st_info);
01037        }
01038       else
01039        {
01040          unsigned long indx;
01041          struct elf_link_hash_entry *h;
01042 
01043          indx = ELFNN_R_SYM (irel->r_info) - symtab_hdr->sh_info;
01044          h = elf_sym_hashes (abfd)[indx];
01045          BFD_ASSERT (h != NULL);
01046 
01047          while (h->root.type == bfd_link_hash_indirect
01048                || h->root.type == bfd_link_hash_warning)
01049            h = (struct elf_link_hash_entry *) h->root.u.i.link;
01050 
01051          dyn_i = get_dyn_sym_info (ia64_info, h, abfd, irel, FALSE);
01052 
01053          /* For branches to dynamic symbols, we're interested instead
01054             in a branch to the PLT entry.  */
01055          if (is_branch && dyn_i && dyn_i->want_plt2)
01056            {
01057              /* Internal branches shouldn't be sent to the PLT.
01058                Leave this for now and we'll give an error later.  */
01059              if (r_type != R_IA64_PCREL21B)
01060               continue;
01061 
01062              tsec = ia64_info->plt_sec;
01063              toff = dyn_i->plt2_offset;
01064              BFD_ASSERT (irel->r_addend == 0);
01065            }
01066 
01067          /* Can't do anything else with dynamic symbols.  */
01068          else if (elfNN_ia64_dynamic_symbol_p (h, link_info, r_type))
01069            continue;
01070 
01071          else
01072            {
01073              /* We can't do anything with undefined symbols.  */
01074              if (h->root.type == bfd_link_hash_undefined
01075                 || h->root.type == bfd_link_hash_undefweak)
01076               continue;
01077 
01078              tsec = h->root.u.def.section;
01079              toff = h->root.u.def.value;
01080            }
01081 
01082          symtype = h->type;
01083        }
01084 
01085       if (tsec->sec_info_type == ELF_INFO_TYPE_MERGE)
01086        {
01087          /* At this stage in linking, no SEC_MERGE symbol has been
01088             adjusted, so all references to such symbols need to be
01089             passed through _bfd_merged_section_offset.  (Later, in
01090             relocate_section, all SEC_MERGE symbols *except* for
01091             section symbols have been adjusted.)
01092 
01093             gas may reduce relocations against symbols in SEC_MERGE
01094             sections to a relocation against the section symbol when
01095             the original addend was zero.  When the reloc is against
01096             a section symbol we should include the addend in the
01097             offset passed to _bfd_merged_section_offset, since the
01098             location of interest is the original symbol.  On the
01099             other hand, an access to "sym+addend" where "sym" is not
01100             a section symbol should not include the addend;  Such an
01101             access is presumed to be an offset from "sym";  The
01102             location of interest is just "sym".  */
01103           if (symtype == STT_SECTION)
01104             toff += irel->r_addend;
01105 
01106           toff = _bfd_merged_section_offset (abfd, &tsec,
01107                                          elf_section_data (tsec)->sec_info,
01108                                          toff);
01109 
01110           if (symtype != STT_SECTION)
01111             toff += irel->r_addend;
01112        }
01113       else
01114        toff += irel->r_addend;
01115 
01116       symaddr = tsec->output_section->vma + tsec->output_offset + toff;
01117 
01118       roff = irel->r_offset;
01119 
01120       if (is_branch)
01121        {
01122          bfd_signed_vma offset;
01123 
01124          reladdr = (sec->output_section->vma
01125                    + sec->output_offset
01126                    + roff) & (bfd_vma) -4;
01127 
01128          /* If the branch is in range, no need to do anything.  */
01129          if ((bfd_signed_vma) (symaddr - reladdr) >= -0x1000000
01130              && (bfd_signed_vma) (symaddr - reladdr) <= 0x0FFFFF0)
01131            {
01132              /* If the 60-bit branch is in 21-bit range, optimize it. */
01133              if (r_type == R_IA64_PCREL60B)
01134               {
01135                 elfNN_ia64_relax_brl (contents, roff);
01136 
01137                 irel->r_info
01138                   = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info),
01139                                 R_IA64_PCREL21B);
01140 
01141                 /* If the original relocation offset points to slot
01142                    1, change it to slot 2.  */
01143                 if ((irel->r_offset & 3) == 1)
01144                   irel->r_offset += 1;
01145               }
01146 
01147              continue;
01148            }
01149          else if (r_type == R_IA64_PCREL60B)
01150            continue;
01151          else if (elfNN_ia64_relax_br (contents, roff))
01152            {
01153              irel->r_info
01154               = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info),
01155                             R_IA64_PCREL60B);
01156 
01157              /* Make the relocation offset point to slot 1.  */
01158              irel->r_offset = (irel->r_offset & ~((bfd_vma) 0x3)) + 1;
01159              continue;
01160            }
01161 
01162          /* We can't put a trampoline in a .init/.fini section. Issue
01163             an error.  */
01164          if (strcmp (sec->output_section->name, ".init") == 0
01165              || strcmp (sec->output_section->name, ".fini") == 0)
01166            {
01167              (*_bfd_error_handler)
01168               (_("%B: Can't relax br at 0x%lx in section `%A'. Please use brl or indirect branch."),
01169                sec->owner, sec, (unsigned long) roff);
01170              bfd_set_error (bfd_error_bad_value);
01171              goto error_return;
01172            }
01173 
01174          /* If the branch and target are in the same section, you've
01175             got one honking big section and we can't help you unless
01176             you are branching backwards.  You'll get an error message
01177             later.  */
01178          if (tsec == sec && toff > roff)
01179            continue;
01180 
01181          /* Look for an existing fixup to this address.  */
01182          for (f = fixups; f ; f = f->next)
01183            if (f->tsec == tsec && f->toff == toff)
01184              break;
01185 
01186          if (f == NULL)
01187            {
01188              /* Two alternatives: If it's a branch to a PLT entry, we can
01189                make a copy of the FULL_PLT entry.  Otherwise, we'll have
01190                to use a `brl' insn to get where we're going.  */
01191 
01192              size_t size;
01193 
01194              if (tsec == ia64_info->plt_sec)
01195               size = sizeof (plt_full_entry);
01196              else
01197               size = oor_branch_size;
01198 
01199              /* Resize the current section to make room for the new branch. */
01200              trampoff = (sec->size + 15) & (bfd_vma) -16;
01201 
01202              /* If trampoline is out of range, there is nothing we
01203                can do.  */
01204              offset = trampoff - (roff & (bfd_vma) -4);
01205              if (offset < -0x1000000 || offset > 0x0FFFFF0)
01206               continue;
01207 
01208              amt = trampoff + size;
01209              contents = (bfd_byte *) bfd_realloc (contents, amt);
01210              if (contents == NULL)
01211               goto error_return;
01212              sec->size = amt;
01213 
01214              if (tsec == ia64_info->plt_sec)
01215               {
01216                 memcpy (contents + trampoff, plt_full_entry, size);
01217 
01218                 /* Hijack the old relocation for use as the PLTOFF reloc.  */
01219                 irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info),
01220                                           R_IA64_PLTOFF22);
01221                 irel->r_offset = trampoff;
01222               }
01223              else
01224               {
01225                 if (size == sizeof (oor_ip))
01226                   {
01227                     memcpy (contents + trampoff, oor_ip, size);
01228                     irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info),
01229                                              R_IA64_PCREL64I);
01230                     irel->r_addend -= 16;
01231                     irel->r_offset = trampoff + 2;
01232                   }
01233                 else
01234                   {
01235                     memcpy (contents + trampoff, oor_brl, size);
01236                     irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info),
01237                                              R_IA64_PCREL60B);
01238                     irel->r_offset = trampoff + 2;
01239                   }
01240 
01241               }
01242 
01243              /* Record the fixup so we don't do it again this section.  */
01244              f = (struct one_fixup *)
01245               bfd_malloc ((bfd_size_type) sizeof (*f));
01246              f->next = fixups;
01247              f->tsec = tsec;
01248              f->toff = toff;
01249              f->trampoff = trampoff;
01250              fixups = f;
01251            }
01252          else
01253            {
01254              /* If trampoline is out of range, there is nothing we
01255                can do.  */
01256              offset = f->trampoff - (roff & (bfd_vma) -4);
01257              if (offset < -0x1000000 || offset > 0x0FFFFF0)
01258               continue;
01259 
01260              /* Nop out the reloc, since we're finalizing things here.  */
01261              irel->r_info = ELFNN_R_INFO (0, R_IA64_NONE);
01262            }
01263 
01264          /* Fix up the existing branch to hit the trampoline.  */
01265          if (elfNN_ia64_install_value (contents + roff, offset, r_type)
01266              != bfd_reloc_ok)
01267            goto error_return;
01268 
01269          changed_contents = TRUE;
01270          changed_relocs = TRUE;
01271        }
01272       else
01273        {
01274          /* Fetch the gp.  */
01275          if (gp == 0)
01276            {
01277              bfd *obfd = sec->output_section->owner;
01278              gp = _bfd_get_gp_value (obfd);
01279              if (gp == 0)
01280               {
01281                 if (!elfNN_ia64_choose_gp (obfd, link_info))
01282                   goto error_return;
01283                 gp = _bfd_get_gp_value (obfd);
01284               }
01285            }
01286 
01287          /* If the data is out of range, do nothing.  */
01288          if ((bfd_signed_vma) (symaddr - gp) >= 0x200000
01289              ||(bfd_signed_vma) (symaddr - gp) < -0x200000)
01290            continue;
01291 
01292          if (r_type == R_IA64_LTOFF22X)
01293            {
01294              irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info),
01295                                       R_IA64_GPREL22);
01296              changed_relocs = TRUE;
01297              if (dyn_i->want_gotx)
01298               {
01299                 dyn_i->want_gotx = 0;
01300                 changed_got |= !dyn_i->want_got;
01301               }
01302            }
01303          else
01304            {
01305              elfNN_ia64_relax_ldxmov (contents, roff);
01306              irel->r_info = ELFNN_R_INFO (0, R_IA64_NONE);
01307              changed_contents = TRUE;
01308              changed_relocs = TRUE;
01309            }
01310        }
01311     }
01312 
01313   /* ??? If we created fixups, this may push the code segment large
01314      enough that the data segment moves, which will change the GP.
01315      Reset the GP so that we re-calculate next round.  We need to
01316      do this at the _beginning_ of the next round; now will not do.  */
01317 
01318   /* Clean up and go home.  */
01319   while (fixups)
01320     {
01321       struct one_fixup *f = fixups;
01322       fixups = fixups->next;
01323       free (f);
01324     }
01325 
01326   if (isymbuf != NULL
01327       && symtab_hdr->contents != (unsigned char *) isymbuf)
01328     {
01329       if (! link_info->keep_memory)
01330        free (isymbuf);
01331       else
01332        {
01333          /* Cache the symbols for elf_link_input_bfd.  */
01334          symtab_hdr->contents = (unsigned char *) isymbuf;
01335        }
01336     }
01337 
01338   if (contents != NULL
01339       && elf_section_data (sec)->this_hdr.contents != contents)
01340     {
01341       if (!changed_contents && !link_info->keep_memory)
01342        free (contents);
01343       else
01344        {
01345          /* Cache the section contents for elf_link_input_bfd.  */
01346          elf_section_data (sec)->this_hdr.contents = contents;
01347        }
01348     }
01349 
01350   if (elf_section_data (sec)->relocs != internal_relocs)
01351     {
01352       if (!changed_relocs)
01353        free (internal_relocs);
01354       else
01355        elf_section_data (sec)->relocs = internal_relocs;
01356     }
01357 
01358   if (changed_got)
01359     {
01360       struct elfNN_ia64_allocate_data data;
01361       data.info = link_info;
01362       data.ofs = 0;
01363       ia64_info->self_dtpmod_offset = (bfd_vma) -1;
01364 
01365       elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_data_got, &data);
01366       elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_fptr_got, &data);
01367       elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_local_got, &data);
01368       ia64_info->got_sec->size = data.ofs;
01369 
01370       if (ia64_info->root.dynamic_sections_created
01371          && ia64_info->rel_got_sec != NULL)
01372        {
01373          /* Resize .rela.got.  */
01374          ia64_info->rel_got_sec->size = 0;
01375          if (link_info->shared
01376              && ia64_info->self_dtpmod_offset != (bfd_vma) -1)
01377            ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela);
01378          data.only_got = TRUE;
01379          elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_dynrel_entries,
01380                                    &data);
01381        }
01382     }
01383 
01384   if (link_info->relax_pass == 0)
01385     {
01386       /* Pass 0 is only needed to relax br.  */
01387       sec->skip_relax_pass_0 = skip_relax_pass_0;
01388       sec->skip_relax_pass_1 = skip_relax_pass_1;
01389     }
01390 
01391   *again = changed_contents || changed_relocs;
01392   return TRUE;
01393 
01394  error_return:
01395   if (isymbuf != NULL && (unsigned char *) isymbuf != symtab_hdr->contents)
01396     free (isymbuf);
01397   if (contents != NULL
01398       && elf_section_data (sec)->this_hdr.contents != contents)
01399     free (contents);
01400   if (internal_relocs != NULL
01401       && elf_section_data (sec)->relocs != internal_relocs)
01402     free (internal_relocs);
01403   return FALSE;
01404 }
01405 #undef skip_relax_pass_0
01406 #undef skip_relax_pass_1
01407 
01408 static void
01409 elfNN_ia64_relax_ldxmov (contents, off)
01410      bfd_byte *contents;
01411      bfd_vma off;
01412 {
01413   int shift, r1, r3;
01414   bfd_vma dword, insn;
01415 
01416   switch ((int)off & 0x3)
01417     {
01418     case 0: shift =  5; break;
01419     case 1: shift = 14; off += 3; break;
01420     case 2: shift = 23; off += 6; break;
01421     default:
01422       abort ();
01423     }
01424 
01425   dword = bfd_getl64 (contents + off);
01426   insn = (dword >> shift) & 0x1ffffffffffLL;
01427 
01428   r1 = (insn >> 6) & 127;
01429   r3 = (insn >> 20) & 127;
01430   if (r1 == r3)
01431     insn = 0x8000000;                               /* nop */
01432   else
01433     insn = (insn & 0x7f01fff) | 0x10800000000LL;   /* (qp) mov r1 = r3 */
01434 
01435   dword &= ~(0x1ffffffffffLL << shift);
01436   dword |= (insn << shift);
01437   bfd_putl64 (dword, contents + off);
01438 }
01439 
01440 /* Return TRUE if NAME is an unwind table section name.  */
01441 
01442 static inline bfd_boolean
01443 is_unwind_section_name (bfd *abfd, const char *name)
01444 {
01445   if (elfNN_ia64_hpux_vec (abfd->xvec)
01446       && !strcmp (name, ELF_STRING_ia64_unwind_hdr))
01447     return FALSE;
01448 
01449   return ((CONST_STRNEQ (name, ELF_STRING_ia64_unwind)
01450           && ! CONST_STRNEQ (name, ELF_STRING_ia64_unwind_info))
01451          || CONST_STRNEQ (name, ELF_STRING_ia64_unwind_once));
01452 }
01453 
01454 /* Handle an IA-64 specific section when reading an object file.  This
01455    is called when bfd_section_from_shdr finds a section with an unknown
01456    type.  */
01457 
01458 static bfd_boolean
01459 elfNN_ia64_section_from_shdr (bfd *abfd,
01460                            Elf_Internal_Shdr *hdr,
01461                            const char *name,
01462                            int shindex)
01463 {
01464   asection *newsect;
01465 
01466   /* There ought to be a place to keep ELF backend specific flags, but
01467      at the moment there isn't one.  We just keep track of the
01468      sections by their name, instead.  Fortunately, the ABI gives
01469      suggested names for all the MIPS specific sections, so we will
01470      probably get away with this.  */
01471   switch (hdr->sh_type)
01472     {
01473     case SHT_IA_64_UNWIND:
01474     case SHT_IA_64_HP_OPT_ANOT:
01475       break;
01476 
01477     case SHT_IA_64_EXT:
01478       if (strcmp (name, ELF_STRING_ia64_archext) != 0)
01479        return FALSE;
01480       break;
01481 
01482     default:
01483       return FALSE;
01484     }
01485 
01486   if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
01487     return FALSE;
01488   newsect = hdr->bfd_section;
01489 
01490   return TRUE;
01491 }
01492 
01493 /* Convert IA-64 specific section flags to bfd internal section flags.  */
01494 
01495 /* ??? There is no bfd internal flag equivalent to the SHF_IA_64_NORECOV
01496    flag.  */
01497 
01498 static bfd_boolean
01499 elfNN_ia64_section_flags (flags, hdr)
01500      flagword *flags;
01501      const Elf_Internal_Shdr *hdr;
01502 {
01503   if (hdr->sh_flags & SHF_IA_64_SHORT)
01504     *flags |= SEC_SMALL_DATA;
01505 
01506   return TRUE;
01507 }
01508 
01509 /* Set the correct type for an IA-64 ELF section.  We do this by the
01510    section name, which is a hack, but ought to work.  */
01511 
01512 static bfd_boolean
01513 elfNN_ia64_fake_sections (abfd, hdr, sec)
01514      bfd *abfd ATTRIBUTE_UNUSED;
01515      Elf_Internal_Shdr *hdr;
01516      asection *sec;
01517 {
01518   register const char *name;
01519 
01520   name = bfd_get_section_name (abfd, sec);
01521 
01522   if (is_unwind_section_name (abfd, name))
01523     {
01524       /* We don't have the sections numbered at this point, so sh_info
01525         is set later, in elfNN_ia64_final_write_processing.  */
01526       hdr->sh_type = SHT_IA_64_UNWIND;
01527       hdr->sh_flags |= SHF_LINK_ORDER;
01528     }
01529   else if (strcmp (name, ELF_STRING_ia64_archext) == 0)
01530     hdr->sh_type = SHT_IA_64_EXT;
01531   else if (strcmp (name, ".HP.opt_annot") == 0)
01532     hdr->sh_type = SHT_IA_64_HP_OPT_ANOT;
01533   else if (strcmp (name, ".reloc") == 0)
01534     /* This is an ugly, but unfortunately necessary hack that is
01535        needed when producing EFI binaries on IA-64. It tells
01536        elf.c:elf_fake_sections() not to consider ".reloc" as a section
01537        containing ELF relocation info.  We need this hack in order to
01538        be able to generate ELF binaries that can be translated into
01539        EFI applications (which are essentially COFF objects).  Those
01540        files contain a COFF ".reloc" section inside an ELFNN object,
01541        which would normally cause BFD to segfault because it would
01542        attempt to interpret this section as containing relocation
01543        entries for section "oc".  With this hack enabled, ".reloc"
01544        will be treated as a normal data section, which will avoid the
01545        segfault.  However, you won't be able to create an ELFNN binary
01546        with a section named "oc" that needs relocations, but that's
01547        the kind of ugly side-effects you get when detecting section
01548        types based on their names...  In practice, this limitation is
01549        unlikely to bite.  */
01550     hdr->sh_type = SHT_PROGBITS;
01551 
01552   if (sec->flags & SEC_SMALL_DATA)
01553     hdr->sh_flags |= SHF_IA_64_SHORT;
01554 
01555   /* Some HP linkers look for the SHF_IA_64_HP_TLS flag instead of SHF_TLS. */
01556 
01557   if (elfNN_ia64_hpux_vec (abfd->xvec) && (sec->flags & SHF_TLS))
01558     hdr->sh_flags |= SHF_IA_64_HP_TLS;
01559 
01560   return TRUE;
01561 }
01562 
01563 /* The final processing done just before writing out an IA-64 ELF
01564    object file.  */
01565 
01566 static void
01567 elfNN_ia64_final_write_processing (abfd, linker)
01568      bfd *abfd;
01569      bfd_boolean linker ATTRIBUTE_UNUSED;
01570 {
01571   Elf_Internal_Shdr *hdr;
01572   asection *s;
01573 
01574   for (s = abfd->sections; s; s = s->next)
01575     {
01576       hdr = &elf_section_data (s)->this_hdr;
01577       switch (hdr->sh_type)
01578        {
01579        case SHT_IA_64_UNWIND:
01580          /* The IA-64 processor-specific ABI requires setting sh_link
01581             to the unwind section, whereas HP-UX requires sh_info to
01582             do so.  For maximum compatibility, we'll set both for
01583             now... */
01584          hdr->sh_info = hdr->sh_link;
01585          break;
01586        }
01587     }
01588 
01589   if (! elf_flags_init (abfd))
01590     {
01591       unsigned long flags = 0;
01592 
01593       if (abfd->xvec->byteorder == BFD_ENDIAN_BIG)
01594        flags |= EF_IA_64_BE;
01595       if (bfd_get_mach (abfd) == bfd_mach_ia64_elf64)
01596        flags |= EF_IA_64_ABI64;
01597 
01598       elf_elfheader(abfd)->e_flags = flags;
01599       elf_flags_init (abfd) = TRUE;
01600     }
01601 }
01602 
01603 /* Hook called by the linker routine which adds symbols from an object
01604    file.  We use it to put .comm items in .sbss, and not .bss.  */
01605 
01606 static bfd_boolean
01607 elfNN_ia64_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
01608      bfd *abfd;
01609      struct bfd_link_info *info;
01610      Elf_Internal_Sym *sym;
01611      const char **namep ATTRIBUTE_UNUSED;
01612      flagword *flagsp ATTRIBUTE_UNUSED;
01613      asection **secp;
01614      bfd_vma *valp;
01615 {
01616   if (sym->st_shndx == SHN_COMMON
01617       && !info->relocatable
01618       && sym->st_size <= elf_gp_size (abfd))
01619     {
01620       /* Common symbols less than or equal to -G nn bytes are
01621         automatically put into .sbss.  */
01622 
01623       asection *scomm = bfd_get_section_by_name (abfd, ".scommon");
01624 
01625       if (scomm == NULL)
01626        {
01627          scomm = bfd_make_section_with_flags (abfd, ".scommon",
01628                                           (SEC_ALLOC
01629                                           | SEC_IS_COMMON
01630                                           | SEC_LINKER_CREATED));
01631          if (scomm == NULL)
01632            return FALSE;
01633        }
01634 
01635       *secp = scomm;
01636       *valp = sym->st_size;
01637     }
01638 
01639   return TRUE;
01640 }
01641 
01642 /* Return the number of additional phdrs we will need.  */
01643 
01644 static int
01645 elfNN_ia64_additional_program_headers (bfd *abfd,
01646                                    struct bfd_link_info *info ATTRIBUTE_UNUSED)
01647 {
01648   asection *s;
01649   int ret = 0;
01650 
01651   /* See if we need a PT_IA_64_ARCHEXT segment.  */
01652   s = bfd_get_section_by_name (abfd, ELF_STRING_ia64_archext);
01653   if (s && (s->flags & SEC_LOAD))
01654     ++ret;
01655 
01656   /* Count how many PT_IA_64_UNWIND segments we need.  */
01657   for (s = abfd->sections; s; s = s->next)
01658     if (is_unwind_section_name (abfd, s->name) && (s->flags & SEC_LOAD))
01659       ++ret;
01660 
01661   return ret;
01662 }
01663 
01664 static bfd_boolean
01665 elfNN_ia64_modify_segment_map (bfd *abfd,
01666                             struct bfd_link_info *info ATTRIBUTE_UNUSED)
01667 {
01668   struct elf_segment_map *m, **pm;
01669   Elf_Internal_Shdr *hdr;
01670   asection *s;
01671 
01672   /* If we need a PT_IA_64_ARCHEXT segment, it must come before
01673      all PT_LOAD segments.  */
01674   s = bfd_get_section_by_name (abfd, ELF_STRING_ia64_archext);
01675   if (s && (s->flags & SEC_LOAD))
01676     {
01677       for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
01678        if (m->p_type == PT_IA_64_ARCHEXT)
01679          break;
01680       if (m == NULL)
01681        {
01682          m = ((struct elf_segment_map *)
01683               bfd_zalloc (abfd, (bfd_size_type) sizeof *m));
01684          if (m == NULL)
01685            return FALSE;
01686 
01687          m->p_type = PT_IA_64_ARCHEXT;
01688          m->count = 1;
01689          m->sections[0] = s;
01690 
01691          /* We want to put it after the PHDR and INTERP segments.  */
01692          pm = &elf_tdata (abfd)->segment_map;
01693          while (*pm != NULL
01694                && ((*pm)->p_type == PT_PHDR
01695                    || (*pm)->p_type == PT_INTERP))
01696            pm = &(*pm)->next;
01697 
01698          m->next = *pm;
01699          *pm = m;
01700        }
01701     }
01702 
01703   /* Install PT_IA_64_UNWIND segments, if needed.  */
01704   for (s = abfd->sections; s; s = s->next)
01705     {
01706       hdr = &elf_section_data (s)->this_hdr;
01707       if (hdr->sh_type != SHT_IA_64_UNWIND)
01708        continue;
01709 
01710       if (s && (s->flags & SEC_LOAD))
01711        {
01712          for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
01713            if (m->p_type == PT_IA_64_UNWIND)
01714              {
01715               int i;
01716 
01717               /* Look through all sections in the unwind segment
01718                  for a match since there may be multiple sections
01719                  to a segment.  */
01720               for (i = m->count - 1; i >= 0; --i)
01721                 if (m->sections[i] == s)
01722                   break;
01723 
01724               if (i >= 0)
01725                 break;
01726              }
01727 
01728          if (m == NULL)
01729            {
01730              m = ((struct elf_segment_map *)
01731                  bfd_zalloc (abfd, (bfd_size_type) sizeof *m));
01732              if (m == NULL)
01733               return FALSE;
01734 
01735              m->p_type = PT_IA_64_UNWIND;
01736              m->count = 1;
01737              m->sections[0] = s;
01738              m->next = NULL;
01739 
01740              /* We want to put it last.  */
01741              pm = &elf_tdata (abfd)->segment_map;
01742              while (*pm != NULL)
01743               pm = &(*pm)->next;
01744              *pm = m;
01745            }
01746        }
01747     }
01748 
01749   return TRUE;
01750 }
01751 
01752 /* Turn on PF_IA_64_NORECOV if needed.  This involves traversing all of
01753    the input sections for each output section in the segment and testing
01754    for SHF_IA_64_NORECOV on each.  */
01755 
01756 static bfd_boolean
01757 elfNN_ia64_modify_program_headers (bfd *abfd,
01758                                struct bfd_link_info *info ATTRIBUTE_UNUSED)
01759 {
01760   struct elf_obj_tdata *tdata = elf_tdata (abfd);
01761   struct elf_segment_map *m;
01762   Elf_Internal_Phdr *p;
01763 
01764   for (p = tdata->phdr, m = tdata->segment_map; m != NULL; m = m->next, p++)
01765     if (m->p_type == PT_LOAD)
01766       {
01767        int i;
01768        for (i = m->count - 1; i >= 0; --i)
01769          {
01770            struct bfd_link_order *order = m->sections[i]->map_head.link_order;
01771 
01772            while (order != NULL)
01773              {
01774               if (order->type == bfd_indirect_link_order)
01775                 {
01776                   asection *is = order->u.indirect.section;
01777                   bfd_vma flags = elf_section_data(is)->this_hdr.sh_flags;
01778                   if (flags & SHF_IA_64_NORECOV)
01779                     {
01780                      p->p_flags |= PF_IA_64_NORECOV;
01781                      goto found;
01782                     }
01783                 }
01784               order = order->next;
01785              }
01786          }
01787       found:;
01788       }
01789 
01790   return TRUE;
01791 }
01792 
01793 /* According to the Tahoe assembler spec, all labels starting with a
01794    '.' are local.  */
01795 
01796 static bfd_boolean
01797 elfNN_ia64_is_local_label_name (abfd, name)
01798      bfd *abfd ATTRIBUTE_UNUSED;
01799      const char *name;
01800 {
01801   return name[0] == '.';
01802 }
01803 
01804 /* Should we do dynamic things to this symbol?  */
01805 
01806 static bfd_boolean
01807 elfNN_ia64_dynamic_symbol_p (h, info, r_type)
01808      struct elf_link_hash_entry *h;
01809      struct bfd_link_info *info;
01810      int r_type;
01811 {
01812   bfd_boolean ignore_protected
01813     = ((r_type & 0xf8) == 0x40            /* FPTR relocs */
01814        || (r_type & 0xf8) == 0x50);       /* LTOFF_FPTR relocs */
01815 
01816   return _bfd_elf_dynamic_symbol_p (h, info, ignore_protected);
01817 }
01818 
01819 static struct bfd_hash_entry*
01820 elfNN_ia64_new_elf_hash_entry (entry, table, string)
01821      struct bfd_hash_entry *entry;
01822      struct bfd_hash_table *table;
01823      const char *string;
01824 {
01825   struct elfNN_ia64_link_hash_entry *ret;
01826   ret = (struct elfNN_ia64_link_hash_entry *) entry;
01827 
01828   /* Allocate the structure if it has not already been allocated by a
01829      subclass.  */
01830   if (!ret)
01831     ret = bfd_hash_allocate (table, sizeof (*ret));
01832 
01833   if (!ret)
01834     return 0;
01835 
01836   /* Call the allocation method of the superclass.  */
01837   ret = ((struct elfNN_ia64_link_hash_entry *)
01838         _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret,
01839                                  table, string));
01840 
01841   ret->info = NULL;
01842   ret->count = 0;
01843   ret->sorted_count = 0;
01844   ret->size = 0;
01845   return (struct bfd_hash_entry *) ret;
01846 }
01847 
01848 static void
01849 elfNN_ia64_hash_copy_indirect (info, xdir, xind)
01850      struct bfd_link_info *info;
01851      struct elf_link_hash_entry *xdir, *xind;
01852 {
01853   struct elfNN_ia64_link_hash_entry *dir, *ind;
01854 
01855   dir = (struct elfNN_ia64_link_hash_entry *) xdir;
01856   ind = (struct elfNN_ia64_link_hash_entry *) xind;
01857 
01858   /* Copy down any references that we may have already seen to the
01859      symbol which just became indirect.  */
01860 
01861   dir->root.ref_dynamic |= ind->root.ref_dynamic;
01862   dir->root.ref_regular |= ind->root.ref_regular;
01863   dir->root.ref_regular_nonweak |= ind->root.ref_regular_nonweak;
01864   dir->root.needs_plt |= ind->root.needs_plt;
01865 
01866   if (ind->root.root.type != bfd_link_hash_indirect)
01867     return;
01868 
01869   /* Copy over the got and plt data.  This would have been done
01870      by check_relocs.  */
01871 
01872   if (ind->info != NULL)
01873     {
01874       struct elfNN_ia64_dyn_sym_info *dyn_i;
01875       unsigned int count;
01876 
01877       if (dir->info)
01878        free (dir->info);
01879 
01880       dir->info = ind->info;
01881       dir->count = ind->count;
01882       dir->sorted_count = ind->sorted_count;
01883       dir->size = ind->size;
01884 
01885       ind->info = NULL;
01886       ind->count = 0;
01887       ind->sorted_count = 0;
01888       ind->size = 0;
01889 
01890       /* Fix up the dyn_sym_info pointers to the global symbol.  */
01891       for (count = dir->count, dyn_i = dir->info;
01892           count != 0;
01893           count--, dyn_i++)
01894        dyn_i->h = &dir->root;
01895     }
01896 
01897   /* Copy over the dynindx.  */
01898 
01899   if (ind->root.dynindx != -1)
01900     {
01901       if (dir->root.dynindx != -1)
01902        _bfd_elf_strtab_delref (elf_hash_table (info)->dynstr,
01903                             dir->root.dynstr_index);
01904       dir->root.dynindx = ind->root.dynindx;
01905       dir->root.dynstr_index = ind->root.dynstr_index;
01906       ind->root.dynindx = -1;
01907       ind->root.dynstr_index = 0;
01908     }
01909 }
01910 
01911 static void
01912 elfNN_ia64_hash_hide_symbol (info, xh, force_local)
01913      struct bfd_link_info *info;
01914      struct elf_link_hash_entry *xh;
01915      bfd_boolean force_local;
01916 {
01917   struct elfNN_ia64_link_hash_entry *h;
01918   struct elfNN_ia64_dyn_sym_info *dyn_i;
01919   unsigned int count;
01920 
01921   h = (struct elfNN_ia64_link_hash_entry *)xh;
01922 
01923   _bfd_elf_link_hash_hide_symbol (info, &h->root, force_local);
01924 
01925   for (count = h->count, dyn_i = h->info;
01926        count != 0;
01927        count--, dyn_i++)
01928     {
01929       dyn_i->want_plt2 = 0;
01930       dyn_i->want_plt = 0;
01931     }
01932 }
01933 
01934 /* Compute a hash of a local hash entry.  */
01935 
01936 static hashval_t
01937 elfNN_ia64_local_htab_hash (ptr)
01938      const void *ptr;
01939 {
01940   struct elfNN_ia64_local_hash_entry *entry
01941     = (struct elfNN_ia64_local_hash_entry *) ptr;
01942 
01943   return (((entry->id & 0xff) << 24) | ((entry->id & 0xff00) << 8))
01944          ^ entry->r_sym ^ (entry->id >> 16);
01945 }
01946 
01947 /* Compare local hash entries.  */
01948 
01949 static int
01950 elfNN_ia64_local_htab_eq (ptr1, ptr2)
01951      const void *ptr1, *ptr2;
01952 {
01953   struct elfNN_ia64_local_hash_entry *entry1
01954     = (struct elfNN_ia64_local_hash_entry *) ptr1;
01955   struct elfNN_ia64_local_hash_entry *entry2
01956     = (struct elfNN_ia64_local_hash_entry *) ptr2;
01957 
01958   return entry1->id == entry2->id && entry1->r_sym == entry2->r_sym;
01959 }
01960 
01961 /* Create the derived linker hash table.  The IA-64 ELF port uses this
01962    derived hash table to keep information specific to the IA-64 ElF
01963    linker (without using static variables).  */
01964 
01965 static struct bfd_link_hash_table*
01966 elfNN_ia64_hash_table_create (abfd)
01967      bfd *abfd;
01968 {
01969   struct elfNN_ia64_link_hash_table *ret;
01970 
01971   ret = bfd_zmalloc ((bfd_size_type) sizeof (*ret));
01972   if (!ret)
01973     return 0;
01974 
01975   if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
01976                                   elfNN_ia64_new_elf_hash_entry,
01977                                   sizeof (struct elfNN_ia64_link_hash_entry)))
01978     {
01979       free (ret);
01980       return 0;
01981     }
01982 
01983   ret->loc_hash_table = htab_try_create (1024, elfNN_ia64_local_htab_hash,
01984                                     elfNN_ia64_local_htab_eq, NULL);
01985   ret->loc_hash_memory = objalloc_create ();
01986   if (!ret->loc_hash_table || !ret->loc_hash_memory)
01987     {
01988       free (ret);
01989       return 0;
01990     }
01991 
01992   return &ret->root.root;
01993 }
01994 
01995 /* Free the global elfNN_ia64_dyn_sym_info array.  */
01996 
01997 static bfd_boolean
01998 elfNN_ia64_global_dyn_info_free (void **xentry,
01999                             PTR unused ATTRIBUTE_UNUSED)
02000 {
02001   struct elfNN_ia64_link_hash_entry *entry
02002     = (struct elfNN_ia64_link_hash_entry *) xentry;
02003 
02004   if (entry->root.root.type == bfd_link_hash_warning)
02005     entry = (struct elfNN_ia64_link_hash_entry *) entry->root.root.u.i.link;
02006 
02007   if (entry->info)
02008     {
02009       free (entry->info);
02010       entry->info = NULL;
02011       entry->count = 0;
02012       entry->sorted_count = 0;
02013       entry->size = 0;
02014     }
02015 
02016   return TRUE;
02017 }
02018 
02019 /* Free the local elfNN_ia64_dyn_sym_info array.  */
02020 
02021 static bfd_boolean
02022 elfNN_ia64_local_dyn_info_free (void **slot,
02023                             PTR unused ATTRIBUTE_UNUSED)
02024 {
02025   struct elfNN_ia64_local_hash_entry *entry
02026     = (struct elfNN_ia64_local_hash_entry *) *slot;
02027 
02028   if (entry->info)
02029     {
02030       free (entry->info);
02031       entry->info = NULL;
02032       entry->count = 0;
02033       entry->sorted_count = 0;
02034       entry->size = 0;
02035     }
02036 
02037   return TRUE;
02038 }
02039 
02040 /* Destroy IA-64 linker hash table.  */
02041 
02042 static void
02043 elfNN_ia64_hash_table_free (hash)
02044      struct bfd_link_hash_table *hash;
02045 {
02046   struct elfNN_ia64_link_hash_table *ia64_info
02047     = (struct elfNN_ia64_link_hash_table *) hash;
02048   if (ia64_info->loc_hash_table)
02049     {
02050       htab_traverse (ia64_info->loc_hash_table,
02051                    elfNN_ia64_local_dyn_info_free, NULL);
02052       htab_delete (ia64_info->loc_hash_table);
02053     }
02054   if (ia64_info->loc_hash_memory)
02055     objalloc_free ((struct objalloc *) ia64_info->loc_hash_memory);
02056   elf_link_hash_traverse (&ia64_info->root,
02057                        elfNN_ia64_global_dyn_info_free, NULL);
02058   _bfd_generic_link_hash_table_free (hash);
02059 }
02060 
02061 /* Traverse both local and global hash tables.  */
02062 
02063 struct elfNN_ia64_dyn_sym_traverse_data
02064 {
02065   bfd_boolean (*func) PARAMS ((struct elfNN_ia64_dyn_sym_info *, PTR));
02066   PTR data;
02067 };
02068 
02069 static bfd_boolean
02070 elfNN_ia64_global_dyn_sym_thunk (xentry, xdata)
02071      struct bfd_hash_entry *xentry;
02072      PTR xdata;
02073 {
02074   struct elfNN_ia64_link_hash_entry *entry
02075     = (struct elfNN_ia64_link_hash_entry *) xentry;
02076   struct elfNN_ia64_dyn_sym_traverse_data *data
02077     = (struct elfNN_ia64_dyn_sym_traverse_data *) xdata;
02078   struct elfNN_ia64_dyn_sym_info *dyn_i;
02079   unsigned int count;
02080 
02081   if (entry->root.root.type == bfd_link_hash_warning)
02082     entry = (struct elfNN_ia64_link_hash_entry *) entry->root.root.u.i.link;
02083 
02084   for (count = entry->count, dyn_i = entry->info;
02085        count != 0;
02086        count--, dyn_i++)
02087     if (! (*data->func) (dyn_i, data->data))
02088       return FALSE;
02089   return TRUE;
02090 }
02091 
02092 static bfd_boolean
02093 elfNN_ia64_local_dyn_sym_thunk (slot, xdata)
02094      void **slot;
02095      PTR xdata;
02096 {
02097   struct elfNN_ia64_local_hash_entry *entry
02098     = (struct elfNN_ia64_local_hash_entry *) *slot;
02099   struct elfNN_ia64_dyn_sym_traverse_data *data
02100     = (struct elfNN_ia64_dyn_sym_traverse_data *) xdata;
02101   struct elfNN_ia64_dyn_sym_info *dyn_i;
02102   unsigned int count;
02103 
02104   for (count = entry->count, dyn_i = entry->info;
02105        count != 0;
02106        count--, dyn_i++)
02107     if (! (*data->func) (dyn_i, data->data))
02108       return FALSE;
02109   return TRUE;
02110 }
02111 
02112 static void
02113 elfNN_ia64_dyn_sym_traverse (ia64_info, func, data)
02114      struct elfNN_ia64_link_hash_table *ia64_info;
02115      bfd_boolean (*func) PARAMS ((struct elfNN_ia64_dyn_sym_info *, PTR));
02116      PTR data;
02117 {
02118   struct elfNN_ia64_dyn_sym_traverse_data xdata;
02119 
02120   xdata.func = func;
02121   xdata.data = data;
02122 
02123   elf_link_hash_traverse (&ia64_info->root,
02124                        elfNN_ia64_global_dyn_sym_thunk, &xdata);
02125   htab_traverse (ia64_info->loc_hash_table,
02126                elfNN_ia64_local_dyn_sym_thunk, &xdata);
02127 }
02128 
02129 static bfd_boolean
02130 elfNN_ia64_create_dynamic_sections (abfd, info)
02131      bfd *abfd;
02132      struct bfd_link_info *info;
02133 {
02134   struct elfNN_ia64_link_hash_table *ia64_info;
02135   asection *s;
02136 
02137   if (! _bfd_elf_create_dynamic_sections (abfd, info))
02138     return FALSE;
02139 
02140   ia64_info = elfNN_ia64_hash_table (info);
02141 
02142   ia64_info->plt_sec = bfd_get_section_by_name (abfd, ".plt");
02143   ia64_info->got_sec = bfd_get_section_by_name (abfd, ".got");
02144 
02145   {
02146     flagword flags = bfd_get_section_flags (abfd, ia64_info->got_sec);
02147     bfd_set_section_flags (abfd, ia64_info->got_sec, SEC_SMALL_DATA | flags);
02148     /* The .got section is always aligned at 8 bytes.  */
02149     bfd_set_section_alignment (abfd, ia64_info->got_sec, 3);
02150   }
02151 
02152   if (!get_pltoff (abfd, info, ia64_info))
02153     return FALSE;
02154 
02155   s = bfd_make_section_with_flags (abfd, ".rela.IA_64.pltoff",
02156                                (SEC_ALLOC | SEC_LOAD
02157                                 | SEC_HAS_CONTENTS
02158                                 | SEC_IN_MEMORY
02159                                 | SEC_LINKER_CREATED
02160                                 | SEC_READONLY));
02161   if (s == NULL
02162       || !bfd_set_section_alignment (abfd, s, LOG_SECTION_ALIGN))
02163     return FALSE;
02164   ia64_info->rel_pltoff_sec = s;
02165 
02166   s = bfd_make_section_with_flags (abfd, ".rela.got",
02167                                (SEC_ALLOC | SEC_LOAD
02168                                 | SEC_HAS_CONTENTS
02169                                 | SEC_IN_MEMORY
02170                                 | SEC_LINKER_CREATED
02171                                 | SEC_READONLY));
02172   if (s == NULL
02173       || !bfd_set_section_alignment (abfd, s, LOG_SECTION_ALIGN))
02174     return FALSE;
02175   ia64_info->rel_got_sec = s;
02176 
02177   return TRUE;
02178 }
02179 
02180 /* Find and/or create a hash entry for local symbol.  */
02181 static struct elfNN_ia64_local_hash_entry *
02182 get_local_sym_hash (ia64_info, abfd, rel, create)
02183      struct elfNN_ia64_link_hash_table *ia64_info;
02184      bfd *abfd;
02185      const Elf_Internal_Rela *rel;
02186      bfd_boolean create;
02187 {
02188   struct elfNN_ia64_local_hash_entry e, *ret;
02189   asection *sec = abfd->sections;
02190   hashval_t h = (((sec->id & 0xff) << 24) | ((sec->id & 0xff00) << 8))
02191               ^ ELFNN_R_SYM (rel->r_info) ^ (sec->id >> 16);
02192   void **slot;
02193 
02194   e.id = sec->id;
02195   e.r_sym = ELFNN_R_SYM (rel->r_info);
02196   slot = htab_find_slot_with_hash (ia64_info->loc_hash_table, &e, h,
02197                                create ? INSERT : NO_INSERT);
02198 
02199   if (!slot)
02200     return NULL;
02201 
02202   if (*slot)
02203     return (struct elfNN_ia64_local_hash_entry *) *slot;
02204 
02205   ret = (struct elfNN_ia64_local_hash_entry *)
02206        objalloc_alloc ((struct objalloc *) ia64_info->loc_hash_memory,
02207                      sizeof (struct elfNN_ia64_local_hash_entry));
02208   if (ret)
02209     {
02210       memset (ret, 0, sizeof (*ret));
02211       ret->id = sec->id;
02212       ret->r_sym = ELFNN_R_SYM (rel->r_info);
02213       *slot = ret;
02214     }
02215   return ret;
02216 }
02217 
02218 /* Used to sort elfNN_ia64_dyn_sym_info array.  */
02219 
02220 static int
02221 addend_compare (const void *xp, const void *yp)
02222 {
02223   const struct elfNN_ia64_dyn_sym_info *x
02224     = (const struct elfNN_ia64_dyn_sym_info *) xp;
02225   const struct elfNN_ia64_dyn_sym_info *y
02226     = (const struct elfNN_ia64_dyn_sym_info *) yp;
02227 
02228   return x->addend < y->addend ? -1 : x->addend > y->addend ? 1 : 0;
02229 }
02230 
02231 /* Sort elfNN_ia64_dyn_sym_info array and remove duplicates.  */
02232 
02233 static unsigned int
02234 sort_dyn_sym_info (struct elfNN_ia64_dyn_sym_info *info,
02235                  unsigned int count)
02236 {
02237   bfd_vma curr, prev;
02238   unsigned int i, dup, diff, dest, src, len;
02239 
02240   qsort (info, count, sizeof (*info), addend_compare);
02241 
02242   /* Find the first duplicate.  */
02243   prev = info [0].addend;
02244   for (i = 1; i < count; i++)
02245     {
02246       curr = info [i].addend;
02247       if (curr == prev)
02248        break;
02249       prev = curr;
02250     }
02251 
02252   /* Remove duplicates.  */
02253   if (i < count)
02254     {
02255       /* We need to move a block of elements to here.  */
02256       dest = i++;
02257       while (i < count)
02258        {
02259          curr = info [i].addend;
02260 
02261          /* Move a block of elements whose first one is different from
02262             the previous.  */
02263          if (curr == prev)
02264            {
02265              for (src = i + 1; src < count; src++)
02266               if (info [src].addend != curr)
02267                 break;
02268            }
02269          else
02270            src = i;
02271 
02272          if (src >= count)
02273            break;
02274 
02275          /* Find the next duplicate.  */
02276          prev = info [src].addend;
02277          for (dup = src + 1; dup < count; dup++)
02278            {
02279              curr = info [dup].addend;
02280              if (curr == prev)
02281               break;
02282              prev = curr;
02283            }
02284 
02285          /* How much to move.  */
02286          len = dup - src;
02287          i = dup + 1;
02288 
02289          if (len == 1 && dup < count)
02290            {
02291              /* If we only move 1 element, we combine it with the next
02292                one.  Find the next different one.  */
02293              for (diff = dup + 1, src++; diff < count; diff++, src++)
02294               if (info [diff].addend != curr)
02295                 break;
02296 
02297              if (diff < count)
02298               {
02299                 /* Find the next duplicate.  */
02300                 prev = info [diff].addend;
02301                 for (dup = diff + 1; dup < count; dup++)
02302                   {
02303                     curr = info [dup].addend;
02304                     if (curr == prev)
02305                      break;
02306                     prev = curr;
02307                     diff++;
02308                   }
02309 
02310                 len = diff - src + 1;
02311                 i = diff + 1;
02312               }
02313            }
02314 
02315          memmove (&info [dest], &info [src], len * sizeof (*info));
02316 
02317          dest += len;
02318        }
02319 
02320       count = dest;
02321     }
02322 
02323   return count;
02324 }
02325 
02326 /* Find and/or create a descriptor for dynamic symbol info.  This will
02327    vary based on global or local symbol, and the addend to the reloc.
02328 
02329    We don't sort when inserting.  Also, we sort and eliminate
02330    duplicates if there is an unsorted section.  Typically, this will
02331    only happen once, because we do all insertions before lookups.  We
02332    then use bsearch to do a lookup.  This also allows lookups to be
02333    fast.  So we have fast insertion (O(log N) due to duplicate check),
02334    fast lookup (O(log N)) and one sort (O(N log N) expected time).
02335    Previously, all lookups were O(N) because of the use of the linked
02336    list and also all insertions were O(N) because of the check for
02337    duplicates.  There are some complications here because the array
02338    size grows occasionally, which may add an O(N) factor, but this
02339    should be rare.  Also,  we free the excess array allocation, which
02340    requires a copy which is O(N), but this only happens once.  */
02341 
02342 static struct elfNN_ia64_dyn_sym_info *
02343 get_dyn_sym_info (ia64_info, h, abfd, rel, create)
02344      struct elfNN_ia64_link_hash_table *ia64_info;
02345      struct elf_link_hash_entry *h;
02346      bfd *abfd;
02347      const Elf_Internal_Rela *rel;
02348      bfd_boolean create;
02349 {
02350   struct elfNN_ia64_dyn_sym_info **info_p, *info, *dyn_i, key;
02351   unsigned int *count_p, *sorted_count_p, *size_p;
02352   unsigned int count, sorted_count, size;
02353   bfd_vma addend = rel ? rel->r_addend : 0;
02354   bfd_size_type amt;
02355 
02356   if (h)
02357     {
02358       struct elfNN_ia64_link_hash_entry *global_h;
02359 
02360       global_h = (struct elfNN_ia64_link_hash_entry *) h;
02361       info_p = &global_h->info;
02362       count_p = &global_h->count;
02363       sorted_count_p = &global_h->sorted_count;
02364       size_p = &global_h->size;
02365     }
02366   else
02367     {
02368       struct elfNN_ia64_local_hash_entry *loc_h;
02369 
02370       loc_h = get_local_sym_hash (ia64_info, abfd, rel, create);
02371       if (!loc_h)
02372        {
02373          BFD_ASSERT (!create);
02374          return NULL;
02375        }
02376 
02377       info_p = &loc_h->info;
02378       count_p = &loc_h->count;
02379       sorted_count_p = &loc_h->sorted_count;
02380       size_p = &loc_h->size;
02381     }
02382 
02383   count = *count_p;
02384   sorted_count = *sorted_count_p;
02385   size = *size_p;
02386   info = *info_p;
02387   if (create)
02388     {
02389       /* When we create the array, we don't check for duplicates,
02390          except in the previously sorted section if one exists, and
02391         against the last inserted entry.  This allows insertions to
02392         be fast.  */
02393       if (info)
02394        {
02395          if (sorted_count)
02396            {
02397              /* Try bsearch first on the sorted section.  */
02398              key.addend = addend;
02399              dyn_i = bsearch (&key, info, sorted_count,
02400                             sizeof (*info), addend_compare);
02401 
02402              if (dyn_i)
02403               {
02404                 return dyn_i;
02405               }
02406            }
02407 
02408          /* Do a quick check for the last inserted entry.  */
02409          dyn_i = info + count - 1;
02410          if (dyn_i->addend == addend)
02411            {
02412              return dyn_i;
02413            }
02414        }
02415 
02416       if (size == 0)
02417        {
02418          /* It is the very first element. We create the array of size
02419             1.  */
02420          size = 1;
02421          amt = size * sizeof (*info);
02422          info = bfd_malloc (amt);
02423        }
02424       else if (size <= count)
02425        {
02426          /* We double the array size every time when we reach the
02427             size limit.  */
02428          size += size;
02429          amt = size * sizeof (*info);
02430          info = bfd_realloc (info, amt);
02431        }
02432       else
02433        goto has_space;
02434 
02435       if (info == NULL)
02436        return NULL;
02437       *size_p = size;
02438       *info_p = info;
02439 
02440 has_space:
02441       /* Append the new one to the array.  */
02442       dyn_i = info + count;
02443       memset (dyn_i, 0, sizeof (*dyn_i));
02444       dyn_i->addend = addend;
02445       
02446       /* We increment count only since the new ones are unsorted and
02447         may have duplicate.  */
02448       (*count_p)++;
02449     }
02450   else
02451     {
02452       /* It is a lookup without insertion.  Sort array if part of the
02453         array isn't sorted.  */
02454       if (count != sorted_count)
02455        {
02456          count = sort_dyn_sym_info (info, count);
02457          *count_p = count;
02458          *sorted_count_p = count;
02459        }
02460 
02461       /* Free unused memory.  */
02462       if (size != count)
02463        {
02464          amt = count * sizeof (*info);
02465          info = bfd_malloc (amt);
02466          if (info != NULL)
02467            {
02468              memcpy (info, *info_p, amt);
02469              free (*info_p);
02470              *size_p = count;
02471              *info_p = info;
02472            }
02473        }
02474 
02475       key.addend = addend;
02476       dyn_i = bsearch (&key, info, count,
02477                      sizeof (*info), addend_compare);
02478     }
02479 
02480   return dyn_i;
02481 }
02482 
02483 static asection *
02484 get_got (abfd, info, ia64_info)
02485      bfd *abfd;
02486      struct bfd_link_info *info;
02487      struct elfNN_ia64_link_hash_table *ia64_info;
02488 {
02489   asection *got;
02490   bfd *dynobj;
02491 
02492   got = ia64_info->got_sec;
02493   if (!got)
02494     {
02495       flagword flags;
02496 
02497       dynobj = ia64_info->root.dynobj;
02498       if (!dynobj)
02499        ia64_info->root.dynobj = dynobj = abfd;
02500       if (!_bfd_elf_create_got_section (dynobj, info))
02501        return 0;
02502 
02503       got = bfd_get_section_by_name (dynobj, ".got");
02504       BFD_ASSERT (got);
02505       ia64_info->got_sec = got;
02506 
02507       /* The .got section is always aligned at 8 bytes.  */
02508       if (!bfd_set_section_alignment (abfd, got, 3))
02509        return 0;
02510 
02511       flags = bfd_get_section_flags (abfd, got);
02512       bfd_set_section_flags (abfd, got, SEC_SMALL_DATA | flags);
02513     }
02514 
02515   return got;
02516 }
02517 
02518 /* Create function descriptor section (.opd).  This section is called .opd
02519    because it contains "official procedure descriptors".  The "official"
02520    refers to the fact that these descriptors are used when taking the address
02521    of a procedure, thus ensuring a unique address for each procedure.  */
02522 
02523 static asection *
02524 get_fptr (abfd, info, ia64_info)
02525      bfd *abfd;
02526      struct bfd_link_info *info;
02527      struct elfNN_ia64_link_hash_table *ia64_info;
02528 {
02529   asection *fptr;
02530   bfd *dynobj;
02531 
02532   fptr = ia64_info->fptr_sec;
02533   if (!fptr)
02534     {
02535       dynobj = ia64_info->root.dynobj;
02536       if (!dynobj)
02537        ia64_info->root.dynobj = dynobj = abfd;
02538 
02539       fptr = bfd_make_section_with_flags (dynobj, ".opd",
02540                                      (SEC_ALLOC
02541                                       | SEC_LOAD
02542                                       | SEC_HAS_CONTENTS
02543                                       | SEC_IN_MEMORY
02544                                       | (info->pie ? 0 : SEC_READONLY)
02545                                       | SEC_LINKER_CREATED));
02546       if (!fptr
02547          || !bfd_set_section_alignment (abfd, fptr, 4))
02548        {
02549          BFD_ASSERT (0);
02550          return NULL;
02551        }
02552 
02553       ia64_info->fptr_sec = fptr;
02554 
02555       if (info->pie)
02556        {
02557          asection *fptr_rel;
02558          fptr_rel = bfd_make_section_with_flags (dynobj, ".rela.opd",
02559                                             (SEC_ALLOC | SEC_LOAD
02560                                              | SEC_HAS_CONTENTS
02561                                              | SEC_IN_MEMORY
02562                                              | SEC_LINKER_CREATED
02563                                              | SEC_READONLY));
02564          if (fptr_rel == NULL
02565              || !bfd_set_section_alignment (abfd, fptr_rel,
02566                                         LOG_SECTION_ALIGN))
02567            {
02568              BFD_ASSERT (0);
02569              return NULL;
02570            }
02571 
02572          ia64_info->rel_fptr_sec = fptr_rel;
02573        }
02574     }
02575 
02576   return fptr;
02577 }
02578 
02579 static asection *
02580 get_pltoff (abfd, info, ia64_info)
02581      bfd *abfd;
02582      struct bfd_link_info *info ATTRIBUTE_UNUSED;
02583      struct elfNN_ia64_link_hash_table *ia64_info;
02584 {
02585   asection *pltoff;
02586   bfd *dynobj;
02587 
02588   pltoff = ia64_info->pltoff_sec;
02589   if (!pltoff)
02590     {
02591       dynobj = ia64_info->root.dynobj;
02592       if (!dynobj)
02593        ia64_info->root.dynobj = dynobj = abfd;
02594 
02595       pltoff = bfd_make_section_with_flags (dynobj,
02596                                        ELF_STRING_ia64_pltoff,
02597                                        (SEC_ALLOC
02598                                         | SEC_LOAD
02599                                         | SEC_HAS_CONTENTS
02600                                         | SEC_IN_MEMORY
02601                                         | SEC_SMALL_DATA
02602                                         | SEC_LINKER_CREATED));
02603       if (!pltoff
02604          || !bfd_set_section_alignment (abfd, pltoff, 4))
02605        {
02606          BFD_ASSERT (0);
02607          return NULL;
02608        }
02609 
02610       ia64_info->pltoff_sec = pltoff;
02611     }
02612 
02613   return pltoff;
02614 }
02615 
02616 static asection *
02617 get_reloc_section (abfd, ia64_info, sec, create)
02618      bfd *abfd;
02619      struct elfNN_ia64_link_hash_table *ia64_info;
02620      asection *sec;
02621      bfd_boolean create;
02622 {
02623   const char *srel_name;
02624   asection *srel;
02625   bfd *dynobj;
02626 
02627   srel_name = (bfd_elf_string_from_elf_section
02628               (abfd, elf_elfheader(abfd)->e_shstrndx,
02629               elf_section_data(sec)->rel_hdr.sh_name));
02630   if (srel_name == NULL)
02631     return NULL;
02632 
02633   BFD_ASSERT ((CONST_STRNEQ (srel_name, ".rela")
02634               && strcmp (bfd_get_section_name (abfd, sec),
02635                        srel_name+5) == 0)
02636              || (CONST_STRNEQ (srel_name, ".rel")
02637                 && strcmp (bfd_get_section_name (abfd, sec),
02638                           srel_name+4) == 0));
02639 
02640   dynobj = ia64_info->root.dynobj;
02641   if (!dynobj)
02642     ia64_info->root.dynobj = dynobj = abfd;
02643 
02644   srel = bfd_get_section_by_name (dynobj, srel_name);
02645   if (srel == NULL && create)
02646     {
02647       srel = bfd_make_section_with_flags (dynobj, srel_name,
02648                                      (SEC_ALLOC | SEC_LOAD
02649                                       | SEC_HAS_CONTENTS
02650                                       | SEC_IN_MEMORY
02651                                       | SEC_LINKER_CREATED
02652                                       | SEC_READONLY));
02653       if (srel == NULL
02654          || !bfd_set_section_alignment (dynobj, srel,
02655                                     LOG_SECTION_ALIGN))
02656        return NULL;
02657     }
02658 
02659   return srel;
02660 }
02661 
02662 static bfd_boolean
02663 count_dyn_reloc (bfd *abfd, struct elfNN_ia64_dyn_sym_info *dyn_i,
02664                asection *srel, int type, bfd_boolean reltext)
02665 {
02666   struct elfNN_ia64_dyn_reloc_entry *rent;
02667 
02668   for (rent = dyn_i->reloc_entries; rent; rent = rent->next)
02669     if (rent->srel == srel && rent->type == type)
02670       break;
02671 
02672   if (!rent)
02673     {
02674       rent = ((struct elfNN_ia64_dyn_reloc_entry *)
02675              bfd_alloc (abfd, (bfd_size_type) sizeof (*rent)));
02676       if (!rent)
02677        return FALSE;
02678 
02679       rent->next = dyn_i->reloc_entries;
02680       rent->srel = srel;
02681       rent->type = type;
02682       rent->count = 0;
02683       dyn_i->reloc_entries = rent;
02684     }
02685   rent->reltext = reltext;
02686   rent->count++;
02687 
02688   return TRUE;
02689 }
02690 
02691 static bfd_boolean
02692 elfNN_ia64_check_relocs (abfd, info, sec, relocs)
02693      bfd *abfd;
02694      struct bfd_link_info *info;
02695      asection *sec;
02696      const Elf_Internal_Rela *relocs;
02697 {
02698   struct elfNN_ia64_link_hash_table *ia64_info;
02699   const Elf_Internal_Rela *relend;
02700   Elf_Internal_Shdr *symtab_hdr;
02701   const Elf_Internal_Rela *rel;
02702   asection *got, *fptr, *srel, *pltoff;
02703   enum {
02704     NEED_GOT = 1,
02705     NEED_GOTX = 2,
02706     NEED_FPTR = 4,
02707     NEED_PLTOFF = 8,
02708     NEED_MIN_PLT = 16,
02709     NEED_FULL_PLT = 32,
02710     NEED_DYNREL = 64,
02711     NEED_LTOFF_FPTR = 128,
02712     NEED_TPREL = 256,
02713     NEED_DTPMOD = 512,
02714     NEED_DTPREL = 1024
02715   };
02716   int need_entry;
02717   struct elf_link_hash_entry *h;
02718   unsigned long r_symndx;
02719   bfd_boolean maybe_dynamic;
02720 
02721   if (info->relocatable)
02722     return TRUE;
02723 
02724   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
02725   ia64_info = elfNN_ia64_hash_table (info);
02726 
02727   got = fptr = srel = pltoff = NULL;
02728 
02729   relend = relocs + sec->reloc_count;
02730 
02731   /* We scan relocations first to create dynamic relocation arrays.  We
02732      modified get_dyn_sym_info to allow fast insertion and support fast
02733      lookup in the next loop.  */
02734   for (rel = relocs; rel < relend; ++rel)
02735     {
02736       r_symndx = ELFNN_R_SYM (rel->r_info);
02737       if (r_symndx >= symtab_hdr->sh_info)
02738        {
02739          long indx = r_symndx - symtab_hdr->sh_info;
02740          h = elf_sym_hashes (abfd)[indx];
02741          while (h->root.type == bfd_link_hash_indirect
02742                || h->root.type == bfd_link_hash_warning)
02743            h = (struct elf_link_hash_entry *) h->root.u.i.link;
02744        }
02745       else
02746        h = NULL;
02747 
02748       /* We can only get preliminary data on whether a symbol is
02749         locally or externally defined, as not all of the input files
02750         have yet been processed.  Do something with what we know, as
02751         this may help reduce memory usage and processing time later.  */
02752       maybe_dynamic = (h && ((!info->executable
02753                            && (!SYMBOLIC_BIND (info, h)
02754                               || info->unresolved_syms_in_shared_libs == RM_IGNORE))
02755                           || !h->def_regular
02756                           || h->root.type == bfd_link_hash_defweak));
02757 
02758       need_entry = 0;
02759       switch (ELFNN_R_TYPE (rel->r_info))
02760        {
02761        case R_IA64_TPREL64MSB:
02762        case R_IA64_TPREL64LSB:
02763          if (info->shared || maybe_dynamic)
02764            need_entry = NEED_DYNREL;
02765          break;
02766 
02767        case R_IA64_LTOFF_TPREL22:
02768          need_entry = NEED_TPREL;
02769          if (info->shared)
02770            info->flags |= DF_STATIC_TLS;
02771          break;
02772 
02773        case R_IA64_DTPREL32MSB:
02774        case R_IA64_DTPREL32LSB:
02775        case R_IA64_DTPREL64MSB:
02776        case R_IA64_DTPREL64LSB:
02777          if (info->shared || maybe_dynamic)
02778            need_entry = NEED_DYNREL;
02779          break;
02780 
02781        case R_IA64_LTOFF_DTPREL22:
02782          need_entry = NEED_DTPREL;
02783          break;
02784 
02785        case R_IA64_DTPMOD64MSB:
02786        case R_IA64_DTPMOD64LSB:
02787          if (info->shared || maybe_dynamic)
02788            need_entry = NEED_DYNREL;
02789          break;
02790 
02791        case R_IA64_LTOFF_DTPMOD22:
02792          need_entry = NEED_DTPMOD;
02793          break;
02794 
02795        case R_IA64_LTOFF_FPTR22:
02796        case R_IA64_LTOFF_FPTR64I:
02797        case R_IA64_LTOFF_FPTR32MSB:
02798        case R_IA64_LTOFF_FPTR32LSB:
02799        case R_IA64_LTOFF_FPTR64MSB:
02800        case R_IA64_LTOFF_FPTR64LSB:
02801          need_entry = NEED_FPTR | NEED_GOT | NEED_LTOFF_FPTR;
02802          break;
02803 
02804        case R_IA64_FPTR64I:
02805        case R_IA64_FPTR32MSB:
02806        case R_IA64_FPTR32LSB:
02807        case R_IA64_FPTR64MSB:
02808        case R_IA64_FPTR64LSB:
02809          if (info->shared || h)
02810            need_entry = NEED_FPTR | NEED_DYNREL;
02811          else
02812            need_entry = NEED_FPTR;
02813          break;
02814 
02815        case R_IA64_LTOFF22:
02816        case R_IA64_LTOFF64I:
02817          need_entry = NEED_GOT;
02818          break;
02819 
02820        case R_IA64_LTOFF22X:
02821          need_entry = NEED_GOTX;
02822          break;
02823 
02824        case R_IA64_PLTOFF22:
02825        case R_IA64_PLTOFF64I:
02826        case R_IA64_PLTOFF64MSB:
02827        case R_IA64_PLTOFF64LSB:
02828          need_entry = NEED_PLTOFF;
02829          if (h)
02830            {
02831              if (maybe_dynamic)
02832               need_entry |= NEED_MIN_PLT;
02833            }
02834          else
02835            {
02836              (*info->callbacks->warning)
02837               (info, _("@pltoff reloc against local symbol"), 0,
02838                abfd, 0, (bfd_vma) 0);
02839            }
02840          break;
02841 
02842        case R_IA64_PCREL21B:
02843         case R_IA64_PCREL60B:
02844          /* Depending on where this symbol is defined, we may or may not
02845             need a full plt entry.  Only skip if we know we'll not need
02846             the entry -- static or symbolic, and the symbol definition
02847             has already been seen.  */
02848          if (maybe_dynamic && rel->r_addend == 0)
02849            need_entry = NEED_FULL_PLT;
02850          break;
02851 
02852        case R_IA64_IMM14:
02853        case R_IA64_IMM22:
02854        case R_IA64_IMM64:
02855        case R_IA64_DIR32MSB:
02856        case R_IA64_DIR32LSB:
02857        case R_IA64_DIR64MSB:
02858        case R_IA64_DIR64LSB:
02859          /* Shared objects will always need at least a REL relocation.  */
02860          if (info->shared || maybe_dynamic)
02861            need_entry = NEED_DYNREL;
02862          break;
02863 
02864        case R_IA64_IPLTMSB:
02865        case R_IA64_IPLTLSB:
02866          /* Shared objects will always need at least a REL relocation.  */
02867          if (info->shared || maybe_dynamic)
02868            need_entry = NEED_DYNREL;
02869          break;
02870 
02871        case R_IA64_PCREL22:
02872        case R_IA64_PCREL64I:
02873        case R_IA64_PCREL32MSB:
02874        case R_IA64_PCREL32LSB:
02875        case R_IA64_PCREL64MSB:
02876        case R_IA64_PCREL64LSB:
02877          if (maybe_dynamic)
02878            need_entry = NEED_DYNREL;
02879          break;
02880        }
02881 
02882       if (!need_entry)
02883        continue;
02884 
02885       if ((need_entry & NEED_FPTR) != 0
02886          && rel->r_addend)
02887        {
02888          (*info->callbacks->warning)
02889            (info, _("non-zero addend in @fptr reloc"), 0,
02890             abfd, 0, (bfd_vma) 0);
02891        }
02892 
02893       if (get_dyn_sym_info (ia64_info, h, abfd, rel, TRUE) == NULL)
02894        return FALSE;
02895     }
02896 
02897   /* Now, we only do lookup without insertion, which is very fast
02898      with the modified get_dyn_sym_info.  */ 
02899   for (rel = relocs; rel < relend; ++rel)
02900     {
02901       struct elfNN_ia64_dyn_sym_info *dyn_i;
02902       int dynrel_type = R_IA64_NONE;
02903 
02904       r_symndx = ELFNN_R_SYM (rel->r_info);
02905       if (r_symndx >= symtab_hdr->sh_info)
02906        {
02907          /* We're dealing with a global symbol -- find its hash entry
02908             and mark it as being referenced.  */
02909          long indx = r_symndx - symtab_hdr->sh_info;
02910          h = elf_sym_hashes (abfd)[indx];
02911          while (h->root.type == bfd_link_hash_indirect
02912                || h->root.type == bfd_link_hash_warning)
02913            h = (struct elf_link_hash_entry *) h->root.u.i.link;
02914 
02915          h->ref_regular = 1;
02916        }
02917       else
02918        h = NULL;
02919 
02920       /* We can only get preliminary data on whether a symbol is
02921         locally or externally defined, as not all of the input files
02922         have yet been processed.  Do something with what we know, as
02923         this may help reduce memory usage and processing time later.  */
02924       maybe_dynamic = (h && ((!info->executable
02925                            && (!SYMBOLIC_BIND (info, h)
02926                               || info->unresolved_syms_in_shared_libs == RM_IGNORE))
02927                           || !h->def_regular
02928                           || h->root.type == bfd_link_hash_defweak));
02929 
02930       need_entry = 0;
02931       switch (ELFNN_R_TYPE (rel->r_info))
02932        {
02933        case R_IA64_TPREL64MSB:
02934        case R_IA64_TPREL64LSB:
02935          if (info->shared || maybe_dynamic)
02936            need_entry = NEED_DYNREL;
02937          dynrel_type = R_IA64_TPREL64LSB;
02938          if (info->shared)
02939            info->flags |= DF_STATIC_TLS;
02940          break;
02941 
02942        case R_IA64_LTOFF_TPREL22:
02943          need_entry = NEED_TPREL;
02944          if (info->shared)
02945            info->flags |= DF_STATIC_TLS;
02946          break;
02947 
02948        case R_IA64_DTPREL32MSB:
02949        case R_IA64_DTPREL32LSB:
02950        case R_IA64_DTPREL64MSB:
02951        case R_IA64_DTPREL64LSB:
02952          if (info->shared || maybe_dynamic)
02953            need_entry = NEED_DYNREL;
02954          dynrel_type = R_IA64_DTPRELNNLSB;
02955          break;
02956 
02957        case R_IA64_LTOFF_DTPREL22:
02958          need_entry = NEED_DTPREL;
02959          break;
02960 
02961        case R_IA64_DTPMOD64MSB:
02962        case R_IA64_DTPMOD64LSB:
02963          if (info->shared || maybe_dynamic)
02964            need_entry = NEED_DYNREL;
02965          dynrel_type = R_IA64_DTPMOD64LSB;
02966          break;
02967 
02968        case R_IA64_LTOFF_DTPMOD22:
02969          need_entry = NEED_DTPMOD;
02970          break;
02971 
02972        case R_IA64_LTOFF_FPTR22:
02973        case R_IA64_LTOFF_FPTR64I:
02974        case R_IA64_LTOFF_FPTR32MSB:
02975        case R_IA64_LTOFF_FPTR32LSB:
02976        case R_IA64_LTOFF_FPTR64MSB:
02977        case R_IA64_LTOFF_FPTR64LSB:
02978          need_entry = NEED_FPTR | NEED_GOT | NEED_LTOFF_FPTR;
02979          break;
02980 
02981        case R_IA64_FPTR64I:
02982        case R_IA64_FPTR32MSB:
02983        case R_IA64_FPTR32LSB:
02984        case R_IA64_FPTR64MSB:
02985        case R_IA64_FPTR64LSB:
02986          if (info->shared || h)
02987            need_entry = NEED_FPTR | NEED_DYNREL;
02988          else
02989            need_entry = NEED_FPTR;
02990          dynrel_type = R_IA64_FPTRNNLSB;
02991          break;
02992 
02993        case R_IA64_LTOFF22:
02994        case R_IA64_LTOFF64I:
02995          need_entry = NEED_GOT;
02996          break;
02997 
02998        case R_IA64_LTOFF22X:
02999          need_entry = NEED_GOTX;
03000          break;
03001 
03002        case R_IA64_PLTOFF22:
03003        case R_IA64_PLTOFF64I:
03004        case R_IA64_PLTOFF64MSB:
03005        case R_IA64_PLTOFF64LSB:
03006          need_entry = NEED_PLTOFF;
03007          if (h)
03008            {
03009              if (maybe_dynamic)
03010               need_entry |= NEED_MIN_PLT;
03011            }
03012          break;
03013 
03014        case R_IA64_PCREL21B:
03015         case R_IA64_PCREL60B:
03016          /* Depending on where this symbol is defined, we may or may not
03017             need a full plt entry.  Only skip if we know we'll not need
03018             the entry -- static or symbolic, and the symbol definition
03019             has already been seen.  */
03020          if (maybe_dynamic && rel->r_addend == 0)
03021            need_entry = NEED_FULL_PLT;
03022          break;
03023 
03024        case R_IA64_IMM14:
03025        case R_IA64_IMM22:
03026        case R_IA64_IMM64:
03027        case R_IA64_DIR32MSB:
03028        case R_IA64_DIR32LSB:
03029        case R_IA64_DIR64MSB:
03030        case R_IA64_DIR64LSB:
03031          /* Shared objects will always need at least a REL relocation.  */
03032          if (info->shared || maybe_dynamic)
03033            need_entry = NEED_DYNREL;
03034          dynrel_type = R_IA64_DIRNNLSB;
03035          break;
03036 
03037        case R_IA64_IPLTMSB:
03038        case R_IA64_IPLTLSB:
03039          /* Shared objects will always need at least a REL relocation.  */
03040          if (info->shared || maybe_dynamic)
03041            need_entry = NEED_DYNREL;
03042          dynrel_type = R_IA64_IPLTLSB;
03043          break;
03044 
03045        case R_IA64_PCREL22:
03046        case R_IA64_PCREL64I:
03047        case R_IA64_PCREL32MSB:
03048        case R_IA64_PCREL32LSB:
03049        case R_IA64_PCREL64MSB:
03050        case R_IA64_PCREL64LSB:
03051          if (maybe_dynamic)
03052            need_entry = NEED_DYNREL;
03053          dynrel_type = R_IA64_PCRELNNLSB;
03054          break;
03055        }
03056 
03057       if (!need_entry)
03058        continue;
03059 
03060       dyn_i = get_dyn_sym_info (ia64_info, h, abfd, rel, FALSE);
03061 
03062       /* Record whether or not this is a local symbol.  */
03063       dyn_i->h = h;
03064 
03065       /* Create what's needed.  */
03066       if (need_entry & (NEED_GOT | NEED_GOTX | NEED_TPREL
03067                      | NEED_DTPMOD | NEED_DTPREL))
03068        {
03069          if (!got)
03070            {
03071              got = get_got (abfd, info, ia64_info);
03072              if (!got)
03073               return FALSE;
03074            }
03075          if (need_entry & NEED_GOT)
03076            dyn_i->want_got = 1;
03077          if (need_entry & NEED_GOTX)
03078            dyn_i->want_gotx = 1;
03079          if (need_entry & NEED_TPREL)
03080            dyn_i->want_tprel = 1;
03081          if (need_entry & NEED_DTPMOD)
03082            dyn_i->want_dtpmod = 1;
03083          if (need_entry & NEED_DTPREL)
03084            dyn_i->want_dtprel = 1;
03085        }
03086       if (need_entry & NEED_FPTR)
03087        {
03088          if (!fptr)
03089            {
03090              fptr = get_fptr (abfd, info, ia64_info);
03091              if (!fptr)
03092               return FALSE;
03093            }
03094 
03095          /* FPTRs for shared libraries are allocated by the dynamic
03096             linker.  Make sure this local symbol will appear in the
03097             dynamic symbol table.  */
03098          if (!h && info->shared)
03099            {
03100              if (! (bfd_elf_link_record_local_dynamic_symbol
03101                    (info, abfd, (long) r_symndx)))
03102               return FALSE;
03103            }
03104 
03105          dyn_i->want_fptr = 1;
03106        }
03107       if (need_entry & NEED_LTOFF_FPTR)
03108        dyn_i->want_ltoff_fptr = 1;
03109       if (need_entry & (NEED_MIN_PLT | NEED_FULL_PLT))
03110        {
03111           if (!ia64_info->root.dynobj)
03112            ia64_info->root.dynobj = abfd;
03113          h->needs_plt = 1;
03114          dyn_i->want_plt = 1;
03115        }
03116       if (need_entry & NEED_FULL_PLT)
03117        dyn_i->want_plt2 = 1;
03118       if (need_entry & NEED_PLTOFF)
03119        {
03120          /* This is needed here, in case @pltoff is used in a non-shared
03121             link.  */
03122          if (!pltoff)
03123            {
03124              pltoff = get_pltoff (abfd, info, ia64_info);
03125              if (!pltoff)
03126               return FALSE;
03127            }
03128 
03129          dyn_i->want_pltoff = 1;
03130        }
03131       if ((need_entry & NEED_DYNREL) && (sec->flags & SEC_ALLOC))
03132        {
03133          if (!srel)
03134            {
03135              srel = get_reloc_section (abfd, ia64_info, sec, TRUE);
03136              if (!srel)
03137               return FALSE;
03138            }
03139          if (!count_dyn_reloc (abfd, dyn_i, srel, dynrel_type,
03140                             (sec->flags & SEC_READONLY) != 0))
03141            return FALSE;
03142        }
03143     }
03144 
03145   return TRUE;
03146 }
03147 
03148 /* For cleanliness, and potentially faster dynamic loading, allocate
03149    external GOT entries first.  */
03150 
03151 static bfd_boolean
03152 allocate_global_data_got (dyn_i, data)
03153      struct elfNN_ia64_dyn_sym_info *dyn_i;
03154      PTR data;
03155 {
03156   struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
03157 
03158   if ((dyn_i->want_got || dyn_i->want_gotx)
03159       && ! dyn_i->want_fptr
03160       && elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info, 0))
03161      {
03162        dyn_i->got_offset = x->ofs;
03163        x->ofs += 8;
03164      }
03165   if (dyn_i->want_tprel)
03166     {
03167       dyn_i->tprel_offset = x->ofs;
03168       x->ofs += 8;
03169     }
03170   if (dyn_i->want_dtpmod)
03171     {
03172       if (elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info, 0))
03173        {
03174          dyn_i->dtpmod_offset = x->ofs;
03175          x->ofs += 8;
03176        }
03177       else
03178        {
03179          struct elfNN_ia64_link_hash_table *ia64_info;
03180 
03181          ia64_info = elfNN_ia64_hash_table (x->info);
03182          if (ia64_info->self_dtpmod_offset == (bfd_vma) -1)
03183            {
03184              ia64_info->self_dtpmod_offset = x->ofs;
03185              x->ofs += 8;
03186            }
03187          dyn_i->dtpmod_offset = ia64_info->self_dtpmod_offset;
03188        }
03189     }
03190   if (dyn_i->want_dtprel)
03191     {
03192       dyn_i->dtprel_offset = x->ofs;
03193       x->ofs += 8;
03194     }
03195   return TRUE;
03196 }
03197 
03198 /* Next, allocate all the GOT entries used by LTOFF_FPTR relocs.  */
03199 
03200 static bfd_boolean
03201 allocate_global_fptr_got (dyn_i, data)
03202      struct elfNN_ia64_dyn_sym_info *dyn_i;
03203      PTR data;
03204 {
03205   struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
03206 
03207   if (dyn_i->want_got
03208       && dyn_i->want_fptr
03209       && elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info, R_IA64_FPTRNNLSB))
03210     {
03211       dyn_i->got_offset = x->ofs;
03212       x->ofs += 8;
03213     }
03214   return TRUE;
03215 }
03216 
03217 /* Lastly, allocate all the GOT entries for local data.  */
03218 
03219 static bfd_boolean
03220 allocate_local_got (dyn_i, data)
03221      struct elfNN_ia64_dyn_sym_info *dyn_i;
03222      PTR data;
03223 {
03224   struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
03225 
03226   if ((dyn_i->want_got || dyn_i->want_gotx)
03227       && !elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info, 0))
03228     {
03229       dyn_i->got_offset = x->ofs;
03230       x->ofs += 8;
03231     }
03232   return TRUE;
03233 }
03234 
03235 /* Search for the index of a global symbol in it's defining object file.  */
03236 
03237 static long
03238 global_sym_index (h)
03239      struct elf_link_hash_entry *h;
03240 {
03241   struct elf_link_hash_entry **p;
03242   bfd *obj;
03243 
03244   BFD_ASSERT (h->root.type == bfd_link_hash_defined
03245              || h->root.type == bfd_link_hash_defweak);
03246 
03247   obj = h->root.u.def.section->owner;
03248   for (p = elf_sym_hashes (obj); *p != h; ++p)
03249     continue;
03250 
03251   return p - elf_sym_hashes (obj) + elf_tdata (obj)->symtab_hdr.sh_info;
03252 }
03253 
03254 /* Allocate function descriptors.  We can do these for every function
03255    in a main executable that is not exported.  */
03256 
03257 static bfd_boolean
03258 allocate_fptr (dyn_i, data)
03259      struct elfNN_ia64_dyn_sym_info *dyn_i;
03260      PTR data;
03261 {
03262   struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
03263 
03264   if (dyn_i->want_fptr)
03265     {
03266       struct elf_link_hash_entry *h = dyn_i->h;
03267 
03268       if (h)
03269        while (h->root.type == bfd_link_hash_indirect
03270               || h->root.type == bfd_link_hash_warning)
03271          h = (struct elf_link_hash_entry *) h->root.u.i.link;
03272 
03273       if (!x->info->executable
03274          && (!h
03275              || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
03276              || (h->root.type != bfd_link_hash_undefweak
03277                 && h->root.type != bfd_link_hash_undefined)))
03278        {
03279          if (h && h->dynindx == -1)
03280            {
03281              BFD_ASSERT ((h->root.type == bfd_link_hash_defined)
03282                        || (h->root.type == bfd_link_hash_defweak));
03283 
03284              if (!bfd_elf_link_record_local_dynamic_symbol
03285                   (x->info, h->root.u.def.section->owner,
03286                    global_sym_index (h)))
03287               return FALSE;
03288            }
03289 
03290          dyn_i->want_fptr = 0;
03291        }
03292       else if (h == NULL || h->dynindx == -1)
03293        {
03294          dyn_i->fptr_offset = x->ofs;
03295          x->ofs += 16;
03296        }
03297       else
03298        dyn_i->want_fptr = 0;
03299     }
03300   return TRUE;
03301 }
03302 
03303 /* Allocate all the minimal PLT entries.  */
03304 
03305 static bfd_boolean
03306 allocate_plt_entries (dyn_i, data)
03307      struct elfNN_ia64_dyn_sym_info *dyn_i;
03308      PTR data;
03309 {
03310   struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
03311 
03312   if (dyn_i->want_plt)
03313     {
03314       struct elf_link_hash_entry *h = dyn_i->h;
03315 
03316       if (h)
03317        while (h->root.type == bfd_link_hash_indirect
03318               || h->root.type == bfd_link_hash_warning)
03319          h = (struct elf_link_hash_entry *) h->root.u.i.link;
03320 
03321       /* ??? Versioned symbols seem to lose NEEDS_PLT.  */
03322       if (elfNN_ia64_dynamic_symbol_p (h, x->info, 0))
03323        {
03324          bfd_size_type offset = x->ofs;
03325          if (offset == 0)
03326            offset = PLT_HEADER_SIZE;
03327          dyn_i->plt_offset = offset;
03328          x->ofs = offset + PLT_MIN_ENTRY_SIZE;
03329 
03330          dyn_i->want_pltoff = 1;
03331        }
03332       else
03333        {
03334          dyn_i->want_plt = 0;
03335          dyn_i->want_plt2 = 0;
03336        }
03337     }
03338   return TRUE;
03339 }
03340 
03341 /* Allocate all the full PLT entries.  */
03342 
03343 static bfd_boolean
03344 allocate_plt2_entries (dyn_i, data)
03345      struct elfNN_ia64_dyn_sym_info *dyn_i;
03346      PTR data;
03347 {
03348   struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
03349 
03350   if (dyn_i->want_plt2)
03351     {
03352       struct elf_link_hash_entry *h = dyn_i->h;
03353       bfd_size_type ofs = x->ofs;
03354 
03355       dyn_i->plt2_offset = ofs;
03356       x->ofs = ofs + PLT_FULL_ENTRY_SIZE;
03357 
03358       while (h->root.type == bfd_link_hash_indirect
03359             || h->root.type == bfd_link_hash_warning)
03360        h = (struct elf_link_hash_entry *) h->root.u.i.link;
03361       dyn_i->h->plt.offset = ofs;
03362     }
03363   return TRUE;
03364 }
03365 
03366 /* Allocate all the PLTOFF entries requested by relocations and
03367    plt entries.  We can't share space with allocated FPTR entries,
03368    because the latter are not necessarily addressable by the GP.
03369    ??? Relaxation might be able to determine that they are.  */
03370 
03371 static bfd_boolean
03372 allocate_pltoff_entries (dyn_i, data)
03373      struct elfNN_ia64_dyn_sym_info *dyn_i;
03374      PTR data;
03375 {
03376   struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
03377 
03378   if (dyn_i->want_pltoff)
03379     {
03380       dyn_i->pltoff_offset = x->ofs;
03381       x->ofs += 16;
03382     }
03383   return TRUE;
03384 }
03385 
03386 /* Allocate dynamic relocations for those symbols that turned out
03387    to be dynamic.  */
03388 
03389 static bfd_boolean
03390 allocate_dynrel_entries (dyn_i, data)
03391      struct elfNN_ia64_dyn_sym_info *dyn_i;
03392      PTR data;
03393 {
03394   struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
03395   struct elfNN_ia64_link_hash_table *ia64_info;
03396   struct elfNN_ia64_dyn_reloc_entry *rent;
03397   bfd_boolean dynamic_symbol, shared, resolved_zero;
03398 
03399   ia64_info = elfNN_ia64_hash_table (x->info);
03400 
03401   /* Note that this can't be used in relation to FPTR relocs below.  */
03402   dynamic_symbol = elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info, 0);
03403 
03404   shared = x->info->shared;
03405   resolved_zero = (dyn_i->h
03406                  && ELF_ST_VISIBILITY (dyn_i->h->other)
03407                  && dyn_i->h->root.type == bfd_link_hash_undefweak);
03408 
03409   /* Take care of the GOT and PLT relocations.  */
03410 
03411   if ((!resolved_zero
03412        && (dynamic_symbol || shared)
03413        && (dyn_i->want_got || dyn_i->want_gotx))
03414       || (dyn_i->want_ltoff_fptr
03415          && dyn_i->h
03416          && dyn_i->h->dynindx != -1))
03417     {
03418       if (!dyn_i->want_ltoff_fptr
03419          || !x->info->pie
03420          || dyn_i->h == NULL
03421          || dyn_i->h->root.type != bfd_link_hash_undefweak)
03422        ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela);
03423     }
03424   if ((dynamic_symbol || shared) && dyn_i->want_tprel)
03425     ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela);
03426   if (dynamic_symbol && dyn_i->want_dtpmod)
03427     ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela);
03428   if (dynamic_symbol && dyn_i->want_dtprel)
03429     ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela);
03430 
03431   if (x->only_got)
03432     return TRUE;
03433 
03434   if (ia64_info->rel_fptr_sec && dyn_i->want_fptr)
03435     {
03436       if (dyn_i->h == NULL || dyn_i->h->root.type != bfd_link_hash_undefweak)
03437        ia64_info->rel_fptr_sec->size += sizeof (ElfNN_External_Rela);
03438     }
03439 
03440   if (!resolved_zero && dyn_i->want_pltoff)
03441     {
03442       bfd_size_type t = 0;
03443 
03444       /* Dynamic symbols get one IPLT relocation.  Local symbols in
03445         shared libraries get two REL relocations.  Local symbols in
03446         main applications get nothing.  */
03447       if (dynamic_symbol)
03448        t = sizeof (ElfNN_External_Rela);
03449       else if (shared)
03450        t = 2 * sizeof (ElfNN_External_Rela);
03451 
03452       ia64_info->rel_pltoff_sec->size += t;
03453     }
03454 
03455   /* Take care of the normal data relocations.  */
03456 
03457   for (rent = dyn_i->reloc_entries; rent; rent = rent->next)
03458     {
03459       int count = rent->count;
03460 
03461       switch (rent->type)
03462        {
03463        case R_IA64_FPTR32LSB:
03464        case R_IA64_FPTR64LSB:
03465          /* Allocate one iff !want_fptr and not PIE, which by this point
03466             will be true only if we're actually allocating one statically
03467             in the main executable.  Position independent executables
03468             need a relative reloc.  */
03469          if (dyn_i->want_fptr && !x->info->pie)
03470            continue;
03471          break;
03472        case R_IA64_PCREL32LSB:
03473        case R_IA64_PCREL64LSB:
03474          if (!dynamic_symbol)
03475            continue;
03476          break;
03477        case R_IA64_DIR32LSB:
03478        case R_IA64_DIR64LSB:
03479          if (!dynamic_symbol && !shared)
03480            continue;
03481          break;
03482        case R_IA64_IPLTLSB:
03483          if (!dynamic_symbol && !shared)
03484            continue;
03485          /* Use two REL relocations for IPLT relocations
03486             against local symbols.  */
03487          if (!dynamic_symbol)
03488            count *= 2;
03489          break;
03490        case R_IA64_DTPREL32LSB:
03491        case R_IA64_TPREL64LSB:
03492        case R_IA64_DTPREL64LSB:
03493        case R_IA64_DTPMOD64LSB:
03494          break;
03495        default:
03496          abort ();
03497        }
03498       if (rent->reltext)
03499        ia64_info->reltext = 1;
03500       rent->srel->size += sizeof (ElfNN_External_Rela) * count;
03501     }
03502 
03503   return TRUE;
03504 }
03505 
03506 static bfd_boolean
03507 elfNN_ia64_adjust_dynamic_symbol (info, h)
03508      struct bfd_link_info *info ATTRIBUTE_UNUSED;
03509      struct elf_link_hash_entry *h;
03510 {
03511   /* ??? Undefined symbols with PLT entries should be re-defined
03512      to be the PLT entry.  */
03513 
03514   /* If this is a weak symbol, and there is a real definition, the
03515      processor independent code will have arranged for us to see the
03516      real definition first, and we can just use the same value.  */
03517   if (h->u.weakdef != NULL)
03518     {
03519       BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
03520                   || h->u.weakdef->root.type == bfd_link_hash_defweak);
03521       h->root.u.def.section = h->u.weakdef->root.u.def.section;
03522       h->root.u.def.value = h->u.weakdef->root.u.def.value;
03523       return TRUE;
03524     }
03525 
03526   /* If this is a reference to a symbol defined by a dynamic object which
03527      is not a function, we might allocate the symbol in our .dynbss section
03528      and allocate a COPY dynamic relocation.
03529 
03530      But IA-64 code is canonically PIC, so as a rule we can avoid this sort
03531      of hackery.  */
03532 
03533   return TRUE;
03534 }
03535 
03536 static bfd_boolean
03537 elfNN_ia64_size_dynamic_sections (output_bfd, info)
03538      bfd *output_bfd ATTRIBUTE_UNUSED;
03539      struct bfd_link_info *info;
03540 {
03541   struct elfNN_ia64_allocate_data data;
03542   struct elfNN_ia64_link_hash_table *ia64_info;
03543   asection *sec;
03544   bfd *dynobj;
03545   bfd_boolean relplt = FALSE;
03546 
03547   dynobj = elf_hash_table(info)->dynobj;
03548   ia64_info = elfNN_ia64_hash_table (info);
03549   ia64_info->self_dtpmod_offset = (bfd_vma) -1;
03550   BFD_ASSERT(dynobj != NULL);
03551   data.info = info;
03552 
03553   /* Set the contents of the .interp section to the interpreter.  */
03554   if (ia64_info->root.dynamic_sections_created
03555       && info->executable)
03556     {
03557       sec = bfd_get_section_by_name (dynobj, ".interp");
03558       BFD_ASSERT (sec != NULL);
03559       sec->contents = (bfd_byte *) ELF_DYNAMIC_INTERPRETER;
03560       sec->size = strlen (ELF_DYNAMIC_INTERPRETER) + 1;
03561     }
03562 
03563   /* Allocate the GOT entries.  */
03564 
03565   if (ia64_info->got_sec)
03566     {
03567       data.ofs = 0;
03568       elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_data_got, &data);
03569       elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_fptr_got, &data);
03570       elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_local_got, &data);
03571       ia64_info->got_sec->size = data.ofs;
03572     }
03573 
03574   /* Allocate the FPTR entries.  */
03575 
03576   if (ia64_info->fptr_sec)
03577     {
03578       data.ofs = 0;
03579       elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_fptr, &data);
03580       ia64_info->fptr_sec->size = data.ofs;
03581     }
03582 
03583   /* Now that we've seen all of the input files, we can decide which
03584      symbols need plt entries.  Allocate the minimal PLT entries first.
03585      We do this even though dynamic_sections_created may be FALSE, because
03586      this has the side-effect of clearing want_plt and want_plt2.  */
03587 
03588   data.ofs = 0;
03589   elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_plt_entries, &data);
03590 
03591   ia64_info->minplt_entries = 0;
03592   if (data.ofs)
03593     {
03594       ia64_info->minplt_entries
03595        = (data.ofs - PLT_HEADER_SIZE) / PLT_MIN_ENTRY_SIZE;
03596     }
03597 
03598   /* Align the pointer for the plt2 entries.  */
03599   data.ofs = (data.ofs + 31) & (bfd_vma) -32;
03600 
03601   elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_plt2_entries, &data);
03602   if (data.ofs != 0 || ia64_info->root.dynamic_sections_created)
03603     {
03604       /* FIXME: we always reserve the memory for dynamic linker even if
03605         there are no PLT entries since dynamic linker may assume the
03606         reserved memory always exists.  */
03607 
03608       BFD_ASSERT (ia64_info->root.dynamic_sections_created);
03609 
03610       ia64_info->plt_sec->size = data.ofs;
03611 
03612       /* If we've got a .plt, we need some extra memory for the dynamic
03613         linker.  We stuff these in .got.plt.  */
03614       sec = bfd_get_section_by_name (dynobj, ".got.plt");
03615       sec->size = 8 * PLT_RESERVED_WORDS;
03616     }
03617 
03618   /* Allocate the PLTOFF entries.  */
03619 
03620   if (ia64_info->pltoff_sec)
03621     {
03622       data.ofs = 0;
03623       elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_pltoff_entries, &data);
03624       ia64_info->pltoff_sec->size = data.ofs;
03625     }
03626 
03627   if (ia64_info->root.dynamic_sections_created)
03628     {
03629       /* Allocate space for the dynamic relocations that turned out to be
03630         required.  */
03631 
03632       if (info->shared && ia64_info->self_dtpmod_offset != (bfd_vma) -1)
03633        ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela);
03634       data.only_got = FALSE;
03635       elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_dynrel_entries, &data);
03636     }
03637 
03638   /* We have now determined the sizes of the various dynamic sections.
03639      Allocate memory for them.  */
03640   for (sec = dynobj->sections; sec != NULL; sec = sec->next)
03641     {
03642       bfd_boolean strip;
03643 
03644       if (!(sec->flags & SEC_LINKER_CREATED))
03645        continue;
03646 
03647       /* If we don't need this section, strip it from the output file.
03648         There were several sections primarily related to dynamic
03649         linking that must be create before the linker maps input
03650         sections to output sections.  The linker does that before
03651         bfd_elf_size_dynamic_sections is called, and it is that
03652         function which decides whether anything needs to go into
03653         these sections.  */
03654 
03655       strip = (sec->size == 0);
03656 
03657       if (sec == ia64_info->got_sec)
03658        strip = FALSE;
03659       else if (sec == ia64_info->rel_got_sec)
03660        {
03661          if (strip)
03662            ia64_info->rel_got_sec = NULL;
03663          else
03664            /* We use the reloc_count field as a counter if we need to
03665               copy relocs into the output file.  */
03666            sec->reloc_count = 0;
03667        }
03668       else if (sec == ia64_info->fptr_sec)
03669        {
03670          if (strip)
03671            ia64_info->fptr_sec = NULL;
03672        }
03673       else if (sec == ia64_info->rel_fptr_sec)
03674        {
03675          if (strip)
03676            ia64_info->rel_fptr_sec = NULL;
03677          else
03678            /* We use the reloc_count field as a counter if we need to
03679               copy relocs into the output file.  */
03680            sec->reloc_count = 0;
03681        }
03682       else if (sec == ia64_info->plt_sec)
03683        {
03684          if (strip)
03685            ia64_info->plt_sec = NULL;
03686        }
03687       else if (sec == ia64_info->pltoff_sec)
03688        {
03689          if (strip)
03690            ia64_info->pltoff_sec = NULL;
03691        }
03692       else if (sec == ia64_info->rel_pltoff_sec)
03693        {
03694          if (strip)
03695            ia64_info->rel_pltoff_sec = NULL;
03696          else
03697            {
03698              relplt = TRUE;
03699              /* We use the reloc_count field as a counter if we need to
03700                copy relocs into the output file.  */
03701              sec->reloc_count = 0;
03702            }
03703        }
03704       else
03705        {
03706          const char *name;
03707 
03708          /* It's OK to base decisions on the section name, because none
03709             of the dynobj section names depend upon the input files.  */
03710          name = bfd_get_section_name (dynobj, sec);
03711 
03712          if (strcmp (name, ".got.plt") == 0)
03713            strip = FALSE;
03714          else if (CONST_STRNEQ (name, ".rel"))
03715            {
03716              if (!strip)
03717               {
03718                 /* We use the reloc_count field as a counter if we need to
03719                    copy relocs into the output file.  */
03720                 sec->reloc_count = 0;
03721               }
03722            }
03723          else
03724            continue;
03725        }
03726 
03727       if (strip)
03728        sec->flags |= SEC_EXCLUDE;
03729       else
03730        {
03731          /* Allocate memory for the section contents.  */
03732          sec->contents = (bfd_byte *) bfd_zalloc (dynobj, sec->size);
03733          if (sec->contents == NULL && sec->size != 0)
03734            return FALSE;
03735        }
03736     }
03737 
03738   if (elf_hash_table (info)->dynamic_sections_created)
03739     {
03740       /* Add some entries to the .dynamic section.  We fill in the values
03741         later (in finish_dynamic_sections) but we must add the entries now
03742         so that we get the correct size for the .dynamic section.  */
03743 
03744       if (info->executable)
03745        {
03746          /* The DT_DEBUG entry is filled in by the dynamic linker and used
03747             by the debugger.  */
03748 #define add_dynamic_entry(TAG, VAL) \
03749   _bfd_elf_add_dynamic_entry (info, TAG, VAL)
03750 
03751          if (!add_dynamic_entry (DT_DEBUG, 0))
03752            return FALSE;
03753        }
03754 
03755       if (!add_dynamic_entry (DT_IA_64_PLT_RESERVE, 0))
03756        return FALSE;
03757       if (!add_dynamic_entry (DT_PLTGOT, 0))
03758        return FALSE;
03759 
03760       if (relplt)
03761        {
03762          if (!add_dynamic_entry (DT_PLTRELSZ, 0)
03763              || !add_dynamic_entry (DT_PLTREL, DT_RELA)
03764              || !add_dynamic_entry (DT_JMPREL, 0))
03765            return FALSE;
03766        }
03767 
03768       if (!add_dynamic_entry (DT_RELA, 0)
03769          || !add_dynamic_entry (DT_RELASZ, 0)
03770          || !add_dynamic_entry (DT_RELAENT, sizeof (ElfNN_External_Rela)))
03771        return FALSE;
03772 
03773       if (ia64_info->reltext)
03774        {
03775          if (!add_dynamic_entry (DT_TEXTREL, 0))
03776            return FALSE;
03777          info->flags |= DF_TEXTREL;
03778        }
03779     }
03780 
03781   /* ??? Perhaps force __gp local.  */
03782 
03783   return TRUE;
03784 }
03785 
03786 static bfd_reloc_status_type
03787 elfNN_ia64_install_value (hit_addr, v, r_type)
03788      bfd_byte *hit_addr;
03789      bfd_vma v;
03790      unsigned int r_type;
03791 {
03792   const struct ia64_operand *op;
03793   int bigendian = 0, shift = 0;
03794   bfd_vma t0, t1, dword;
03795   ia64_insn insn;
03796   enum ia64_opnd opnd;
03797   const char *err;
03798   size_t size = 8;
03799 #ifdef BFD_HOST_U_64_BIT
03800   BFD_HOST_U_64_BIT val = (BFD_HOST_U_64_BIT) v;
03801 #else
03802   bfd_vma val = v;
03803 #endif
03804 
03805   opnd = IA64_OPND_NIL;
03806   switch (r_type)
03807     {
03808     case R_IA64_NONE:
03809     case R_IA64_LDXMOV:
03810       return bfd_reloc_ok;
03811 
03812       /* Instruction relocations.  */
03813 
03814     case R_IA64_IMM14:
03815     case R_IA64_TPREL14:
03816     case R_IA64_DTPREL14:
03817       opnd = IA64_OPND_IMM14;
03818       break;
03819 
03820     case R_IA64_PCREL21F:   opnd = IA64_OPND_TGT25; break;
03821     case R_IA64_PCREL21M:   opnd = IA64_OPND_TGT25b; break;
03822     case R_IA64_PCREL60B:   opnd = IA64_OPND_TGT64; break;
03823     case R_IA64_PCREL21B:
03824     case R_IA64_PCREL21BI:
03825       opnd = IA64_OPND_TGT25c;
03826       break;
03827 
03828     case R_IA64_IMM22:
03829     case R_IA64_GPREL22:
03830     case R_IA64_LTOFF22:
03831     case R_IA64_LTOFF22X:
03832     case R_IA64_PLTOFF22:
03833     case R_IA64_PCREL22:
03834     case R_IA64_LTOFF_FPTR22:
03835     case R_IA64_TPREL22:
03836     case R_IA64_DTPREL22:
03837     case R_IA64_LTOFF_TPREL22:
03838     case R_IA64_LTOFF_DTPMOD22:
03839     case R_IA64_LTOFF_DTPREL22:
03840       opnd = IA64_OPND_IMM22;
03841       break;
03842 
03843     case R_IA64_IMM64:
03844     case R_IA64_GPREL64I:
03845     case R_IA64_LTOFF64I:
03846     case R_IA64_PLTOFF64I:
03847     case R_IA64_PCREL64I:
03848     case R_IA64_FPTR64I:
03849     case R_IA64_LTOFF_FPTR64I:
03850     case R_IA64_TPREL64I:
03851     case R_IA64_DTPREL64I:
03852       opnd = IA64_OPND_IMMU64;
03853       break;
03854 
03855       /* Data relocations.  */
03856 
03857     case R_IA64_DIR32MSB:
03858     case R_IA64_GPREL32MSB:
03859     case R_IA64_FPTR32MSB:
03860     case R_IA64_PCREL32MSB:
03861     case R_IA64_LTOFF_FPTR32MSB:
03862     case R_IA64_SEGREL32MSB:
03863     case R_IA64_SECREL32MSB:
03864     case R_IA64_LTV32MSB:
03865     case R_IA64_DTPREL32MSB:
03866       size = 4; bigendian = 1;
03867       break;
03868 
03869     case R_IA64_DIR32LSB:
03870     case R_IA64_GPREL32LSB:
03871     case R_IA64_FPTR32LSB:
03872     case R_IA64_PCREL32LSB:
03873     case R_IA64_LTOFF_FPTR32LSB:
03874     case R_IA64_SEGREL32LSB:
03875     case R_IA64_SECREL32LSB:
03876     case R_IA64_LTV32LSB:
03877     case R_IA64_DTPREL32LSB:
03878       size = 4; bigendian = 0;
03879       break;
03880 
03881     case R_IA64_DIR64MSB:
03882     case R_IA64_GPREL64MSB:
03883     case R_IA64_PLTOFF64MSB:
03884     case R_IA64_FPTR64MSB:
03885     case R_IA64_PCREL64MSB:
03886     case R_IA64_LTOFF_FPTR64MSB:
03887     case R_IA64_SEGREL64MSB:
03888     case R_IA64_SECREL64MSB:
03889     case R_IA64_LTV64MSB:
03890     case R_IA64_TPREL64MSB:
03891     case R_IA64_DTPMOD64MSB:
03892     case R_IA64_DTPREL64MSB:
03893       size = 8; bigendian = 1;
03894       break;
03895 
03896     case R_IA64_DIR64LSB:
03897     case R_IA64_GPREL64LSB:
03898     case R_IA64_PLTOFF64LSB:
03899     case R_IA64_FPTR64LSB:
03900     case R_IA64_PCREL64LSB:
03901     case R_IA64_LTOFF_FPTR64LSB:
03902     case R_IA64_SEGREL64LSB:
03903     case R_IA64_SECREL64LSB:
03904     case R_IA64_LTV64LSB:
03905     case R_IA64_TPREL64LSB:
03906     case R_IA64_DTPMOD64LSB:
03907     case R_IA64_DTPREL64LSB:
03908       size = 8; bigendian = 0;
03909       break;
03910 
03911       /* Unsupported / Dynamic relocations.  */
03912     default:
03913       return bfd_reloc_notsupported;
03914     }
03915 
03916   switch (opnd)
03917     {
03918     case IA64_OPND_IMMU64:
03919       hit_addr -= (long) hit_addr & 0x3;
03920       t0 = bfd_getl64 (hit_addr);
03921       t1 = bfd_getl64 (hit_addr + 8);
03922 
03923       /* tmpl/s: bits  0.. 5 in t0
03924         slot 0: bits  5..45 in t0
03925         slot 1: bits 46..63 in t0, bits 0..22 in t1
03926         slot 2: bits 23..63 in t1 */
03927 
03928       /* First, clear the bits that form the 64 bit constant.  */
03929       t0 &= ~(0x3ffffLL << 46);
03930       t1 &= ~(0x7fffffLL
03931              | ((  (0x07fLL << 13) | (0x1ffLL << 27)
03932                   | (0x01fLL << 22) | (0x001LL << 21)
03933                   | (0x001LL << 36)) << 23));
03934 
03935       t0 |= ((val >> 22) & 0x03ffffLL) << 46;           /* 18 lsbs of imm41 */
03936       t1 |= ((val >> 40) & 0x7fffffLL) <<  0;           /* 23 msbs of imm41 */
03937       t1 |= (  (((val >>  0) & 0x07f) << 13)            /* imm7b */
03938               | (((val >>  7) & 0x1ff) << 27)           /* imm9d */
03939               | (((val >> 16) & 0x01f) << 22)           /* imm5c */
03940               | (((val >> 21) & 0x001) << 21)           /* ic */
03941               | (((val >> 63) & 0x001) << 36)) << 23;   /* i */
03942 
03943       bfd_putl64 (t0, hit_addr);
03944       bfd_putl64 (t1, hit_addr + 8);
03945       break;
03946 
03947     case IA64_OPND_TGT64:
03948       hit_addr -= (long) hit_addr & 0x3;
03949       t0 = bfd_getl64 (hit_addr);
03950       t1 = bfd_getl64 (hit_addr + 8);
03951 
03952       /* tmpl/s: bits  0.. 5 in t0
03953         slot 0: bits  5..45 in t0
03954         slot 1: bits 46..63 in t0, bits 0..22 in t1
03955         slot 2: bits 23..63 in t1 */
03956 
03957       /* First, clear the bits that form the 64 bit constant.  */
03958       t0 &= ~(0x3ffffLL << 46);
03959       t1 &= ~(0x7fffffLL
03960              | ((1LL << 36 | 0xfffffLL << 13) << 23));
03961 
03962       val >>= 4;
03963       t0 |= ((val >> 20) & 0xffffLL) << 2 << 46; /* 16 lsbs of imm39 */
03964       t1 |= ((val >> 36) & 0x7fffffLL) << 0;            /* 23 msbs of imm39 */
03965       t1 |= ((((val >> 0) & 0xfffffLL) << 13)           /* imm20b */
03966              | (((val >> 59) & 0x1LL) << 36)) << 23;    /* i */
03967 
03968       bfd_putl64 (t0, hit_addr);
03969       bfd_putl64 (t1, hit_addr + 8);
03970       break;
03971 
03972     default:
03973       switch ((long) hit_addr & 0x3)
03974        {
03975        case 0: shift =  5; break;
03976        case 1: shift = 14; hit_addr += 3; break;
03977        case 2: shift = 23; hit_addr += 6; break;
03978        case 3: return bfd_reloc_notsupported; /* shouldn't happen...  */
03979        }
03980       dword = bfd_getl64 (hit_addr);
03981       insn = (dword >> shift) & 0x1ffffffffffLL;
03982 
03983       op = elf64_ia64_operands + opnd;
03984       err = (*op->insert) (op, val, &insn);
03985       if (err)
03986        return bfd_reloc_overflow;
03987 
03988       dword &= ~(0x1ffffffffffLL << shift);
03989       dword |= (insn << shift);
03990       bfd_putl64 (dword, hit_addr);
03991       break;
03992 
03993     case IA64_OPND_NIL:
03994       /* A data relocation.  */
03995       if (bigendian)
03996        if (size == 4)
03997          bfd_putb32 (val, hit_addr);
03998        else
03999          bfd_putb64 (val, hit_addr);
04000       else
04001        if (size == 4)
04002          bfd_putl32 (val, hit_addr);
04003        else
04004          bfd_putl64 (val, hit_addr);
04005       break;
04006     }
04007 
04008   return bfd_reloc_ok;
04009 }
04010 
04011 static void
04012 elfNN_ia64_install_dyn_reloc (abfd, info, sec, srel, offset, type,
04013                            dynindx, addend)
04014      bfd *abfd;
04015      struct bfd_link_info *info;
04016      asection *sec;
04017      asection *srel;
04018      bfd_vma offset;
04019      unsigned int type;
04020      long dynindx;
04021      bfd_vma addend;
04022 {
04023   Elf_Internal_Rela outrel;
04024   bfd_byte *loc;
04025 
04026   BFD_ASSERT (dynindx != -1);
04027   outrel.r_info = ELFNN_R_INFO (dynindx, type);
04028   outrel.r_addend = addend;
04029   outrel.r_offset = _bfd_elf_section_offset (abfd, info, sec, offset);
04030   if (outrel.r_offset >= (bfd_vma) -2)
04031     {
04032       /* Run for the hills.  We shouldn't be outputting a relocation
04033         for this.  So do what everyone else does and output a no-op.  */
04034       outrel.r_info = ELFNN_R_INFO (0, R_IA64_NONE);
04035       outrel.r_addend = 0;
04036       outrel.r_offset = 0;
04037     }
04038   else
04039     outrel.r_offset += sec->output_section->vma + sec->output_offset;
04040 
04041   loc = srel->contents;
04042   loc += srel->reloc_count++ * sizeof (ElfNN_External_Rela);
04043   bfd_elfNN_swap_reloca_out (abfd, &outrel, loc);
04044   BFD_ASSERT (sizeof (ElfNN_External_Rela) * srel->reloc_count <= srel->size);
04045 }
04046 
04047 /* Store an entry for target address TARGET_ADDR in the linkage table
04048    and return the gp-relative address of the linkage table entry.  */
04049 
04050 static bfd_vma
04051 set_got_entry (abfd, info, dyn_i, dynindx, addend, value, dyn_r_type)
04052      bfd *abfd;
04053      struct bfd_link_info *info;
04054      struct elfNN_ia64_dyn_sym_info *dyn_i;
04055      long dynindx;
04056      bfd_vma addend;
04057      bfd_vma value;
04058      unsigned int dyn_r_type;
04059 {
04060   struct elfNN_ia64_link_hash_table *ia64_info;
04061   asection *got_sec;
04062   bfd_boolean done;
04063   bfd_vma got_offset;
04064 
04065   ia64_info = elfNN_ia64_hash_table (info);
04066   got_sec = ia64_info->got_sec;
04067 
04068   switch (dyn_r_type)
04069     {
04070     case R_IA64_TPREL64LSB:
04071       done = dyn_i->tprel_done;
04072       dyn_i->tprel_done = TRUE;
04073       got_offset = dyn_i->tprel_offset;
04074       break;
04075     case R_IA64_DTPMOD64LSB:
04076       if (dyn_i->dtpmod_offset != ia64_info->self_dtpmod_offset)
04077        {
04078          done = dyn_i->dtpmod_done;
04079          dyn_i->dtpmod_done = TRUE;
04080        }
04081       else
04082        {
04083          done = ia64_info->self_dtpmod_done;
04084          ia64_info->self_dtpmod_done = TRUE;
04085          dynindx = 0;
04086        }
04087       got_offset = dyn_i->dtpmod_offset;
04088       break;
04089     case R_IA64_DTPREL32LSB:
04090     case R_IA64_DTPREL64LSB:
04091       done = dyn_i->dtprel_done;
04092       dyn_i->dtprel_done = TRUE;
04093       got_offset = dyn_i->dtprel_offset;
04094       break;
04095     default:
04096       done = dyn_i->got_done;
04097       dyn_i->got_done = TRUE;
04098       got_offset = dyn_i->got_offset;
04099       break;
04100     }
04101 
04102   BFD_ASSERT ((got_offset & 7) == 0);
04103 
04104   if (! done)
04105     {
04106       /* Store the target address in the linkage table entry.  */
04107       bfd_put_64 (abfd, value, got_sec->contents + got_offset);
04108 
04109       /* Install a dynamic relocation if needed.  */
04110       if (((info->shared
04111            && (!dyn_i->h
04112               || ELF_ST_VISIBILITY (dyn_i->h->other) == STV_DEFAULT
04113               || dyn_i->h->root.type != bfd_link_hash_undefweak)
04114            && dyn_r_type != R_IA64_DTPREL32LSB
04115            && dyn_r_type != R_IA64_DTPREL64LSB)
04116            || elfNN_ia64_dynamic_symbol_p (dyn_i->h, info, dyn_r_type)
04117           || (dynindx != -1
04118               && (dyn_r_type == R_IA64_FPTR32LSB
04119                  || dyn_r_type == R_IA64_FPTR64LSB)))
04120          && (!dyn_i->want_ltoff_fptr
04121              || !info->pie
04122              || !dyn_i->h
04123              || dyn_i->h->root.type != bfd_link_hash_undefweak))
04124        {
04125          if (dynindx == -1
04126              && dyn_r_type != R_IA64_TPREL64LSB
04127              && dyn_r_type != R_IA64_DTPMOD64LSB
04128              && dyn_r_type != R_IA64_DTPREL32LSB
04129              && dyn_r_type != R_IA64_DTPREL64LSB)
04130            {
04131              dyn_r_type = R_IA64_RELNNLSB;
04132              dynindx = 0;
04133              addend = value;
04134            }
04135 
04136          if (bfd_big_endian (abfd))
04137            {
04138              switch (dyn_r_type)
04139               {
04140               case R_IA64_REL32LSB:
04141                 dyn_r_type = R_IA64_REL32MSB;
04142                 break;
04143               case R_IA64_DIR32LSB:
04144                 dyn_r_type = R_IA64_DIR32MSB;
04145                 break;
04146               case R_IA64_FPTR32LSB:
04147                 dyn_r_type = R_IA64_FPTR32MSB;
04148                 break;
04149               case R_IA64_DTPREL32LSB:
04150                 dyn_r_type = R_IA64_DTPREL32MSB;
04151                 break;
04152               case R_IA64_REL64LSB:
04153                 dyn_r_type = R_IA64_REL64MSB;
04154                 break;
04155               case R_IA64_DIR64LSB:
04156                 dyn_r_type = R_IA64_DIR64MSB;
04157                 break;
04158               case R_IA64_FPTR64LSB:
04159                 dyn_r_type = R_IA64_FPTR64MSB;
04160                 break;
04161               case R_IA64_TPREL64LSB:
04162                 dyn_r_type = R_IA64_TPREL64MSB;
04163                 break;
04164               case R_IA64_DTPMOD64LSB:
04165                 dyn_r_type = R_IA64_DTPMOD64MSB;
04166                 break;
04167               case R_IA64_DTPREL64LSB:
04168                 dyn_r_type = R_IA64_DTPREL64MSB;
04169                 break;
04170               default:
04171                 BFD_ASSERT (FALSE);
04172                 break;
04173               }
04174            }
04175 
04176          elfNN_ia64_install_dyn_reloc (abfd, NULL, got_sec,
04177                                    ia64_info->rel_got_sec,
04178                                    got_offset, dyn_r_type,
04179                                    dynindx, addend);
04180        }
04181     }
04182 
04183   /* Return the address of the linkage table entry.  */
04184   value = (got_sec->output_section->vma
04185           + got_sec->output_offset
04186           + got_offset);
04187 
04188   return value;
04189 }
04190 
04191 /* Fill in a function descriptor consisting of the function's code
04192    address and its global pointer.  Return the descriptor's address.  */
04193 
04194 static bfd_vma
04195 set_fptr_entry (abfd, info, dyn_i, value)
04196      bfd *abfd;
04197      struct bfd_link_info *info;
04198      struct elfNN_ia64_dyn_sym_info *dyn_i;
04199      bfd_vma value;
04200 {
04201   struct elfNN_ia64_link_hash_table *ia64_info;
04202   asection *fptr_sec;
04203 
04204   ia64_info = elfNN_ia64_hash_table (info);
04205   fptr_sec = ia64_info->fptr_sec;
04206 
04207   if (!dyn_i->fptr_done)
04208     {
04209       dyn_i->fptr_done = 1;
04210 
04211       /* Fill in the function descriptor.  */
04212       bfd_put_64 (abfd, value, fptr_sec->contents + dyn_i->fptr_offset);
04213       bfd_put_64 (abfd, _bfd_get_gp_value (abfd),
04214                 fptr_sec->contents + dyn_i->fptr_offset + 8);
04215       if (ia64_info->rel_fptr_sec)
04216        {
04217          Elf_Internal_Rela outrel;
04218          bfd_byte *loc;
04219 
04220          if (bfd_little_endian (abfd))
04221            outrel.r_info = ELFNN_R_INFO (0, R_IA64_IPLTLSB);
04222          else
04223            outrel.r_info = ELFNN_R_INFO (0, R_IA64_IPLTMSB);
04224          outrel.r_addend = value;
04225          outrel.r_offset = (fptr_sec->output_section->vma
04226                           + fptr_sec->output_offset
04227                           + dyn_i->fptr_offset);
04228          loc = ia64_info->rel_fptr_sec->contents;
04229          loc += ia64_info->rel_fptr_sec->reloc_count++
04230                * sizeof (ElfNN_External_Rela);
04231          bfd_elfNN_swap_reloca_out (abfd, &outrel, loc);
04232        }
04233     }
04234 
04235   /* Return the descriptor's address.  */
04236   value = (fptr_sec->output_section->vma
04237           + fptr_sec->output_offset
04238           + dyn_i->fptr_offset);
04239 
04240   return value;
04241 }
04242 
04243 /* Fill in a PLTOFF entry consisting of the function's code address
04244    and its global pointer.  Return the descriptor's address.  */
04245 
04246 static bfd_vma
04247 set_pltoff_entry (abfd, info, dyn_i, value, is_plt)
04248      bfd *abfd;
04249      struct bfd_link_info *info;
04250      struct elfNN_ia64_dyn_sym_info *dyn_i;
04251      bfd_vma value;
04252      bfd_boolean is_plt;
04253 {
04254   struct elfNN_ia64_link_hash_table *ia64_info;
04255   asection *pltoff_sec;
04256 
04257   ia64_info = elfNN_ia64_hash_table (info);
04258   pltoff_sec = ia64_info->pltoff_sec;
04259 
04260   /* Don't do anything if this symbol uses a real PLT entry.  In
04261      that case, we'll fill this in during finish_dynamic_symbol.  */
04262   if ((! dyn_i->want_plt || is_plt)
04263       && !dyn_i->pltoff_done)
04264     {
04265       bfd_vma gp = _bfd_get_gp_value (abfd);
04266 
04267       /* Fill in the function descriptor.  */
04268       bfd_put_64 (abfd, value, pltoff_sec->contents + dyn_i->pltoff_offset);
04269       bfd_put_64 (abfd, gp, pltoff_sec->contents + dyn_i->pltoff_offset + 8);
04270 
04271       /* Install dynamic relocations if needed.  */
04272       if (!is_plt
04273          && info->shared
04274          && (!dyn_i->h
04275              || ELF_ST_VISIBILITY (dyn_i->h->other) == STV_DEFAULT
04276              || dyn_i->h->root.type != bfd_link_hash_undefweak))
04277        {
04278          unsigned int dyn_r_type;
04279 
04280          if (bfd_big_endian (abfd))
04281            dyn_r_type = R_IA64_RELNNMSB;
04282          else
04283            dyn_r_type = R_IA64_RELNNLSB;
04284 
04285          elfNN_ia64_install_dyn_reloc (abfd, NULL, pltoff_sec,
04286                                    ia64_info->rel_pltoff_sec,
04287                                    dyn_i->pltoff_offset,
04288                                    dyn_r_type, 0, value);
04289          elfNN_ia64_install_dyn_reloc (abfd, NULL, pltoff_sec,
04290                                    ia64_info->rel_pltoff_sec,
04291                                    dyn_i->pltoff_offset + ARCH_SIZE / 8,
04292                                    dyn_r_type, 0, gp);
04293        }
04294 
04295       dyn_i->pltoff_done = 1;
04296     }
04297 
04298   /* Return the descriptor's address.  */
04299   value = (pltoff_sec->output_section->vma
04300           + pltoff_sec->output_offset
04301           + dyn_i->pltoff_offset);
04302 
04303   return value;
04304 }
04305 
04306 /* Return the base VMA address which should be subtracted from real addresses
04307    when resolving @tprel() relocation.
04308    Main program TLS (whose template starts at PT_TLS p_vaddr)
04309    is assigned offset round(2 * size of pointer, PT_TLS p_align).  */
04310 
04311 static bfd_vma
04312 elfNN_ia64_tprel_base (info)
04313      struct bfd_link_info *info;
04314 {
04315   asection *tls_sec = elf_hash_table (info)->tls_sec;
04316 
04317   BFD_ASSERT (tls_sec != NULL);
04318   return tls_sec->vma - align_power ((bfd_vma) ARCH_SIZE / 4,
04319                                  tls_sec->alignment_power);
04320 }
04321 
04322 /* Return the base VMA address which should be subtracted from real addresses
04323    when resolving @dtprel() relocation.
04324    This is PT_TLS segment p_vaddr.  */
04325 
04326 static bfd_vma
04327 elfNN_ia64_dtprel_base (info)
04328      struct bfd_link_info *info;
04329 {
04330   BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
04331   return elf_hash_table (info)->tls_sec->vma;
04332 }
04333 
04334 /* Called through qsort to sort the .IA_64.unwind section during a
04335    non-relocatable link.  Set elfNN_ia64_unwind_entry_compare_bfd
04336    to the output bfd so we can do proper endianness frobbing.  */
04337 
04338 static bfd *elfNN_ia64_unwind_entry_compare_bfd;
04339 
04340 static int
04341 elfNN_ia64_unwind_entry_compare (a, b)
04342      const PTR a;
04343      const PTR b;
04344 {
04345   bfd_vma av, bv;
04346 
04347   av = bfd_get_64 (elfNN_ia64_unwind_entry_compare_bfd, a);
04348   bv = bfd_get_64 (elfNN_ia64_unwind_entry_compare_bfd, b);
04349 
04350   return (av < bv ? -1 : av > bv ? 1 : 0);
04351 }
04352 
04353 /* Make sure we've got ourselves a nice fat __gp value.  */
04354 static bfd_boolean
04355 elfNN_ia64_choose_gp (abfd, info)
04356      bfd *abfd;
04357      struct bfd_link_info *info;
04358 {
04359   bfd_vma min_vma = (bfd_vma) -1, max_vma = 0;
04360   bfd_vma min_short_vma = min_vma, max_short_vma = 0;
04361   struct elf_link_hash_entry *gp;
04362   bfd_vma gp_val;
04363   asection *os;
04364   struct elfNN_ia64_link_hash_table *ia64_info;
04365 
04366   ia64_info = elfNN_ia64_hash_table (info);
04367 
04368   /* Find the min and max vma of all sections marked short.  Also collect
04369      min and max vma of any type, for use in selecting a nice gp.  */
04370   for (os = abfd->sections; os ; os = os->next)
04371     {
04372       bfd_vma lo, hi;
04373 
04374       if ((os->flags & SEC_ALLOC) == 0)
04375        continue;
04376 
04377       lo = os->vma;
04378       hi = os->vma + (os->rawsize ? os->rawsize : os->size);
04379       if (hi < lo)
04380        hi = (bfd_vma) -1;
04381 
04382       if (min_vma > lo)
04383        min_vma = lo;
04384       if (max_vma < hi)
04385        max_vma = hi;
04386       if (os->flags & SEC_SMALL_DATA)
04387        {
04388          if (min_short_vma > lo)
04389            min_short_vma = lo;
04390          if (max_short_vma < hi)
04391            max_short_vma = hi;
04392        }
04393     }
04394 
04395   /* See if the user wants to force a value.  */
04396   gp = elf_link_hash_lookup (elf_hash_table (info), "__gp", FALSE,
04397                           FALSE, FALSE);
04398 
04399   if (gp
04400       && (gp->root.type == bfd_link_hash_defined
04401          || gp->root.type == bfd_link_hash_defweak))
04402     {
04403       asection *gp_sec = gp->root.u.def.section;
04404       gp_val = (gp->root.u.def.value
04405               + gp_sec->output_section->vma
04406               + gp_sec->output_offset);
04407     }
04408   else
04409     {
04410       /* Pick a sensible value.  */
04411 
04412       asection *got_sec = ia64_info->got_sec;
04413 
04414       /* Start with just the address of the .got.  */
04415       if (got_sec)
04416        gp_val = got_sec->output_section->vma;
04417       else if (max_short_vma != 0)
04418        gp_val = min_short_vma;
04419       else if (max_vma - min_vma < 0x200000)
04420        gp_val = min_vma;
04421       else
04422        gp_val = max_vma - 0x200000 + 8;
04423 
04424       /* If it is possible to address the entire image, but we
04425         don't with the choice above, adjust.  */
04426       if (max_vma - min_vma < 0x400000
04427          && (max_vma - gp_val >= 0x200000
04428              || gp_val - min_vma > 0x200000))
04429        gp_val = min_vma + 0x200000;
04430       else if (max_short_vma != 0)
04431        {
04432          /* If we don't cover all the short data, adjust.  */
04433          if (max_short_vma - gp_val >= 0x200000)
04434            gp_val = min_short_vma + 0x200000;
04435 
04436          /* If we're addressing stuff past the end, adjust back.  */
04437          if (gp_val > max_vma)
04438            gp_val = max_vma - 0x200000 + 8;
04439        }
04440     }
04441 
04442   /* Validate whether all SHF_IA_64_SHORT sections are within
04443      range of the chosen GP.  */
04444 
04445   if (max_short_vma != 0)
04446     {
04447       if (max_short_vma - min_short_vma >= 0x400000)
04448        {
04449          (*_bfd_error_handler)
04450            (_("%s: short data segment overflowed (0x%lx >= 0x400000)"),
04451             bfd_get_filename (abfd),
04452             (unsigned long) (max_short_vma - min_short_vma));
04453          return FALSE;
04454        }
04455       else if ((gp_val > min_short_vma
04456               && gp_val - min_short_vma > 0x200000)
04457               || (gp_val < max_short_vma
04458                  && max_short_vma - gp_val >= 0x200000))
04459        {
04460          (*_bfd_error_handler)
04461            (_("%s: __gp does not cover short data segment"),
04462             bfd_get_filename (abfd));
04463          return FALSE;
04464        }
04465     }
04466 
04467   _bfd_set_gp_value (abfd, gp_val);
04468 
04469   return TRUE;
04470 }
04471 
04472 static bfd_boolean
04473 elfNN_ia64_final_link (abfd, info)
04474      bfd *abfd;
04475      struct bfd_link_info *info;
04476 {
04477   struct elfNN_ia64_link_hash_table *ia64_info;
04478   asection *unwind_output_sec;
04479 
04480   ia64_info = elfNN_ia64_hash_table (info);
04481 
04482   /* Make sure we've got ourselves a nice fat __gp value.  */
04483   if (!info->relocatable)
04484     {
04485       bfd_vma gp_val;
04486       struct elf_link_hash_entry *gp;
04487 
04488       /* We assume after gp is set, section size will only decrease. We
04489         need to adjust gp for it.  */
04490       _bfd_set_gp_value (abfd, 0);
04491       if (! elfNN_ia64_choose_gp (abfd, info))
04492        return FALSE;
04493       gp_val = _bfd_get_gp_value (abfd);
04494 
04495       gp = elf_link_hash_lookup (elf_hash_table (info), "__gp", FALSE,
04496                               FALSE, FALSE);
04497       if (gp)
04498        {
04499          gp->root.type = bfd_link_hash_defined;
04500          gp->root.u.def.value = gp_val;
04501          gp->root.u.def.section = bfd_abs_section_ptr;
04502        }
04503     }
04504 
04505   /* If we're producing a final executable, we need to sort the contents
04506      of the .IA_64.unwind section.  Force this section to be relocated
04507      into memory rather than written immediately to the output file.  */
04508   unwind_output_sec = NULL;
04509   if (!info->relocatable)
04510     {
04511       asection *s = bfd_get_section_by_name (abfd, ELF_STRING_ia64_unwind);
04512       if (s)
04513        {
04514          unwind_output_sec = s->output_section;
04515          unwind_output_sec->contents
04516            = bfd_malloc (unwind_output_sec->size);
04517          if (unwind_output_sec->contents == NULL)
04518            return FALSE;
04519        }
04520     }
04521 
04522   /* Invoke the regular ELF backend linker to do all the work.  */
04523   if (!bfd_elf_final_link (abfd, info))
04524     return FALSE;
04525 
04526   if (unwind_output_sec)
04527     {
04528       elfNN_ia64_unwind_entry_compare_bfd = abfd;
04529       qsort (unwind_output_sec->contents,
04530             (size_t) (unwind_output_sec->size / 24),
04531             24,
04532             elfNN_ia64_unwind_entry_compare);
04533 
04534       if (! bfd_set_section_contents (abfd, unwind_output_sec,
04535                                   unwind_output_sec->contents, (bfd_vma) 0,
04536                                   unwind_output_sec->size))
04537        return FALSE;
04538     }
04539 
04540   return TRUE;
04541 }
04542 
04543 static bfd_boolean
04544 elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
04545                           contents, relocs, local_syms, local_sections)
04546      bfd *output_bfd;
04547      struct bfd_link_info *info;
04548      bfd *input_bfd;
04549      asection *input_section;
04550      bfd_byte *contents;
04551      Elf_Internal_Rela *relocs;
04552      Elf_Internal_Sym *local_syms;
04553      asection **local_sections;
04554 {
04555   struct elfNN_ia64_link_hash_table *ia64_info;
04556   Elf_Internal_Shdr *symtab_hdr;
04557   Elf_Internal_Rela *rel;
04558   Elf_Internal_Rela *relend;
04559   asection *srel;
04560   bfd_boolean ret_val = TRUE;      /* for non-fatal errors */
04561   bfd_vma gp_val;
04562 
04563   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
04564   ia64_info = elfNN_ia64_hash_table (info);
04565 
04566   /* Infect various flags from the input section to the output section.  */
04567   if (info->relocatable)
04568     {
04569       bfd_vma flags;
04570 
04571       flags = elf_section_data(input_section)->this_hdr.sh_flags;
04572       flags &= SHF_IA_64_NORECOV;
04573 
04574       elf_section_data(input_section->output_section)
04575        ->this_hdr.sh_flags |= flags;
04576     }
04577 
04578   gp_val = _bfd_get_gp_value (output_bfd);
04579   srel = get_reloc_section (input_bfd, ia64_info, input_section, FALSE);
04580 
04581   rel = relocs;
04582   relend = relocs + input_section->reloc_count;
04583   for (; rel < relend; ++rel)
04584     {
04585       struct elf_link_hash_entry *h;
04586       struct elfNN_ia64_dyn_sym_info *dyn_i;
04587       bfd_reloc_status_type r;
04588       reloc_howto_type *howto;
04589       unsigned long r_symndx;
04590       Elf_Internal_Sym *sym;
04591       unsigned int r_type;
04592       bfd_vma value;
04593       asection *sym_sec;
04594       bfd_byte *hit_addr;
04595       bfd_boolean dynamic_symbol_p;
04596       bfd_boolean undef_weak_ref;
04597 
04598       r_type = ELFNN_R_TYPE (rel->r_info);
04599       if (r_type > R_IA64_MAX_RELOC_CODE)
04600        {
04601          (*_bfd_error_handler)
04602            (_("%B: unknown relocation type %d"),
04603             input_bfd, (int) r_type);
04604          bfd_set_error (bfd_error_bad_value);
04605          ret_val = FALSE;
04606          continue;
04607        }
04608 
04609       howto = lookup_howto (r_type);
04610       r_symndx = ELFNN_R_SYM (rel->r_info);
04611       h = NULL;
04612       sym = NULL;
04613       sym_sec = NULL;
04614       undef_weak_ref = FALSE;
04615 
04616       if (r_symndx < symtab_hdr->sh_info)
04617        {
04618          /* Reloc against local symbol.  */
04619          asection *msec;
04620          sym = local_syms + r_symndx;
04621          sym_sec = local_sections[r_symndx];
04622          msec = sym_sec;
04623          value = _bfd_elf_rela_local_sym (output_bfd, sym, &msec, rel);
04624          if (!info->relocatable
04625              && (sym_sec->flags & SEC_MERGE) != 0
04626              && ELF_ST_TYPE (sym->st_info) == STT_SECTION
04627              && sym_sec->sec_info_type == ELF_INFO_TYPE_MERGE)
04628            {
04629              struct elfNN_ia64_local_hash_entry *loc_h;
04630 
04631              loc_h = get_local_sym_hash (ia64_info, input_bfd, rel, FALSE);
04632              if (loc_h && ! loc_h->sec_merge_done)
04633               {
04634                 struct elfNN_ia64_dyn_sym_info *dynent;
04635                 unsigned int count;
04636 
04637                 for (count = loc_h->count, dynent = loc_h->info;
04638                      count != 0;
04639                      count--, dynent++)
04640                   {
04641                     msec = sym_sec;
04642                     dynent->addend =
04643                      _bfd_merged_section_offset (output_bfd, &msec,
04644                                               elf_section_data (msec)->
04645                                               sec_info,
04646                                               sym->st_value
04647                                               + dynent->addend);
04648                     dynent->addend -= sym->st_value;
04649                     dynent->addend += msec->output_section->vma
04650                                    + msec->output_offset
04651                                    - sym_sec->output_section->vma
04652                                    - sym_sec->output_offset;
04653                   }
04654                 
04655                 qsort (loc_h->info, loc_h->count,
04656                       sizeof (*loc_h->info), addend_compare);
04657 
04658                 loc_h->sec_merge_done = 1;
04659               }
04660            }
04661        }
04662       else
04663        {
04664          bfd_boolean unresolved_reloc;
04665          bfd_boolean warned;
04666          struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
04667 
04668          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
04669                                r_symndx, symtab_hdr, sym_hashes,
04670                                h, sym_sec, value,
04671                                unresolved_reloc, warned);
04672 
04673          if (h->root.type == bfd_link_hash_undefweak)
04674            undef_weak_ref = TRUE;
04675          else if (warned)
04676            continue;
04677        }
04678 
04679       /* For relocs against symbols from removed linkonce sections,
04680         or sections discarded by a linker script, we just want the
04681         section contents zeroed.  Avoid any special processing.  */
04682       if (sym_sec != NULL && elf_discarded_section (sym_sec))
04683        {
04684          _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
04685          rel->r_info = 0;
04686          rel->r_addend = 0;
04687          continue;
04688        }
04689 
04690       if (info->relocatable)
04691        continue;
04692 
04693       hit_addr = contents + rel->r_offset;
04694       value += rel->r_addend;
04695       dynamic_symbol_p = elfNN_ia64_dynamic_symbol_p (h, info, r_type);
04696 
04697       switch (r_type)
04698        {
04699        case R_IA64_NONE:
04700        case R_IA64_LDXMOV:
04701          continue;
04702 
04703        case R_IA64_IMM14:
04704        case R_IA64_IMM22:
04705        case R_IA64_IMM64:
04706        case R_IA64_DIR32MSB:
04707        case R_IA64_DIR32LSB:
04708        case R_IA64_DIR64MSB:
04709        case R_IA64_DIR64LSB:
04710          /* Install a dynamic relocation for this reloc.  */
04711          if ((dynamic_symbol_p || info->shared)
04712              && r_symndx != 0
04713              && (input_section->flags & SEC_ALLOC) != 0)
04714            {
04715              unsigned int dyn_r_type;
04716              long dynindx;
04717              bfd_vma addend;
04718 
04719              BFD_ASSERT (srel != NULL);
04720 
04721              switch (r_type)
04722               {
04723               case R_IA64_IMM14:
04724               case R_IA64_IMM22:
04725               case R_IA64_IMM64:
04726                 /* ??? People shouldn't be doing non-pic code in
04727                    shared libraries nor dynamic executables.  */
04728                 (*_bfd_error_handler)
04729                   (_("%B: non-pic code with imm relocation against dynamic symbol `%s'"),
04730                    input_bfd,
04731                    h ? h->root.root.string
04732                      : bfd_elf_sym_name (input_bfd, symtab_hdr, sym,
04733                                       sym_sec));
04734                 ret_val = FALSE;
04735                 continue;
04736 
04737               default:
04738                 break;
04739               }
04740 
04741              /* If we don't need dynamic symbol lookup, find a
04742                matching RELATIVE relocation.  */
04743              dyn_r_type = r_type;
04744              if (dynamic_symbol_p)
04745               {
04746                 dynindx = h->dynindx;
04747                 addend = rel->r_addend;
04748                 value = 0;
04749               }
04750              else
04751               {
04752                 switch (r_type)
04753                   {
04754                   case R_IA64_DIR32MSB:
04755                     dyn_r_type = R_IA64_REL32MSB;
04756                     break;
04757                   case R_IA64_DIR32LSB:
04758                     dyn_r_type = R_IA64_REL32LSB;
04759                     break;
04760                   case R_IA64_DIR64MSB:
04761                     dyn_r_type = R_IA64_REL64MSB;
04762                     break;
04763                   case R_IA64_DIR64LSB:
04764                     dyn_r_type = R_IA64_REL64LSB;
04765                     break;
04766 
04767                   default:
04768                     break;
04769                   }
04770                 dynindx = 0;
04771                 addend = value;
04772               }
04773 
04774              elfNN_ia64_install_dyn_reloc (output_bfd, info, input_section,
04775                                        srel, rel->r_offset, dyn_r_type,
04776                                        dynindx, addend);
04777            }
04778          /* Fall through.  */
04779 
04780        case R_IA64_LTV32MSB:
04781        case R_IA64_LTV32LSB:
04782        case R_IA64_LTV64MSB:
04783        case R_IA64_LTV64LSB:
04784          r = elfNN_ia64_install_value (hit_addr, value, r_type);
04785          break;
04786 
04787        case R_IA64_GPREL22:
04788        case R_IA64_GPREL64I:
04789        case R_IA64_GPREL32MSB:
04790        case R_IA64_GPREL32LSB:
04791        case R_IA64_GPREL64MSB:
04792        case R_IA64_GPREL64LSB:
04793          if (dynamic_symbol_p)
04794            {
04795              (*_bfd_error_handler)
04796               (_("%B: @gprel relocation against dynamic symbol %s"),
04797                input_bfd,
04798                h ? h->root.root.string
04799                  : bfd_elf_sym_name (input_bfd, symtab_hdr, sym,
04800                                    sym_sec));
04801              ret_val = FALSE;
04802              continue;
04803            }
04804          value -= gp_val;
04805          r = elfNN_ia64_install_value (hit_addr, value, r_type);
04806          break;
04807 
04808        case R_IA64_LTOFF22:
04809        case R_IA64_LTOFF22X:
04810        case R_IA64_LTOFF64I:
04811           dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
04812          value = set_got_entry (input_bfd, info, dyn_i, (h ? h->dynindx : -1),
04813                              rel->r_addend, value, R_IA64_DIRNNLSB);
04814          value -= gp_val;
04815          r = elfNN_ia64_install_value (hit_addr, value, r_type);
04816          break;
04817 
04818        case R_IA64_PLTOFF22:
04819        case R_IA64_PLTOFF64I:
04820        case R_IA64_PLTOFF64MSB:
04821        case R_IA64_PLTOFF64LSB:
04822           dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
04823          value = set_pltoff_entry (output_bfd, info, dyn_i, value, FALSE);
04824          value -= gp_val;
04825          r = elfNN_ia64_install_value (hit_addr, value, r_type);
04826          break;
04827 
04828        case R_IA64_FPTR64I:
04829        case R_IA64_FPTR32MSB:
04830        case R_IA64_FPTR32LSB:
04831        case R_IA64_FPTR64MSB:
04832        case R_IA64_FPTR64LSB:
04833           dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
04834          if (dyn_i->want_fptr)
04835            {
04836              if (!undef_weak_ref)
04837               value = set_fptr_entry (output_bfd, info, dyn_i, value);
04838            }
04839          if (!dyn_i->want_fptr || info->pie)
04840            {
04841              long dynindx;
04842              unsigned int dyn_r_type = r_type;
04843              bfd_vma addend = rel->r_addend;
04844 
04845              /* Otherwise, we expect the dynamic linker to create
04846                the entry.  */
04847 
04848              if (dyn_i->want_fptr)
04849               {
04850                 if (r_type == R_IA64_FPTR64I)
04851                   {
04852                     /* We can't represent this without a dynamic symbol.
04853                       Adjust the relocation to be against an output
04854                       section symbol, which are always present in the
04855                       dynamic symbol table.  */
04856                     /* ??? People shouldn't be doing non-pic code in
04857                       shared libraries.  Hork.  */
04858                     (*_bfd_error_handler)
04859                      (_("%B: linking non-pic code in a position independent executable"),
04860                       input_bfd);
04861                     ret_val = FALSE;
04862                     continue;
04863                   }
04864                 dynindx = 0;
04865                 addend = value;
04866                 dyn_r_type = r_type + R_IA64_RELNNLSB - R_IA64_FPTRNNLSB;
04867               }
04868              else if (h)
04869               {
04870                 if (h->dynindx != -1)
04871                   dynindx = h->dynindx;
04872                 else
04873                   dynindx = (_bfd_elf_link_lookup_local_dynindx
04874                             (info, h->root.u.def.section->owner,
04875                             global_sym_index (h)));
04876                 value = 0;
04877               }
04878              else
04879               {
04880                 dynindx = (_bfd_elf_link_lookup_local_dynindx
04881                           (info, input_bfd, (long) r_symndx));
04882                 value = 0;
04883               }
04884 
04885              elfNN_ia64_install_dyn_reloc (output_bfd, info, input_section,
04886                                        srel, rel->r_offset, dyn_r_type,
04887                                        dynindx, addend);
04888            }
04889 
04890          r = elfNN_ia64_install_value (hit_addr, value, r_type);
04891          break;
04892 
04893        case R_IA64_LTOFF_FPTR22:
04894        case R_IA64_LTOFF_FPTR64I:
04895        case R_IA64_LTOFF_FPTR32MSB:
04896        case R_IA64_LTOFF_FPTR32LSB:
04897        case R_IA64_LTOFF_FPTR64MSB:
04898        case R_IA64_LTOFF_FPTR64LSB:
04899          {
04900            long dynindx;
04901 
04902            dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
04903            if (dyn_i->want_fptr)
04904              {
04905               BFD_ASSERT (h == NULL || h->dynindx == -1);
04906                if (!undef_weak_ref)
04907                  value = set_fptr_entry (output_bfd, info, dyn_i, value);
04908               dynindx = -1;
04909              }
04910            else
04911              {
04912                /* Otherwise, we expect the dynamic linker to create
04913                  the entry.  */
04914                if (h)
04915                 {
04916                   if (h->dynindx != -1)
04917                     dynindx = h->dynindx;
04918                   else
04919                     dynindx = (_bfd_elf_link_lookup_local_dynindx
04920                              (info, h->root.u.def.section->owner,
04921                               global_sym_index (h)));
04922                 }
04923               else
04924                 dynindx = (_bfd_elf_link_lookup_local_dynindx
04925                           (info, input_bfd, (long) r_symndx));
04926               value = 0;
04927              }
04928 
04929            value = set_got_entry (output_bfd, info, dyn_i, dynindx,
04930                                rel->r_addend, value, R_IA64_FPTRNNLSB);
04931            value -= gp_val;
04932            r = elfNN_ia64_install_value (hit_addr, value, r_type);
04933          }
04934          break;
04935 
04936        case R_IA64_PCREL32MSB:
04937        case R_IA64_PCREL32LSB:
04938        case R_IA64_PCREL64MSB:
04939        case R_IA64_PCREL64LSB:
04940          /* Install a dynamic relocation for this reloc.  */
04941          if (dynamic_symbol_p && r_symndx != 0)
04942            {
04943              BFD_ASSERT (srel != NULL);
04944 
04945              elfNN_ia64_install_dyn_reloc (output_bfd, info, input_section,
04946                                        srel, rel->r_offset, r_type,
04947                                        h->dynindx, rel->r_addend);
04948            }
04949          goto finish_pcrel;
04950 
04951        case R_IA64_PCREL21B:
04952        case R_IA64_PCREL60B:
04953          /* We should have created a PLT entry for any dynamic symbol.  */
04954          dyn_i = NULL;
04955          if (h)
04956            dyn_i = get_dyn_sym_info (ia64_info, h, NULL, NULL, FALSE);
04957 
04958          if (dyn_i && dyn_i->want_plt2)
04959            {
04960              /* Should have caught this earlier.  */
04961              BFD_ASSERT (rel->r_addend == 0);
04962 
04963              value = (ia64_info->plt_sec->output_section->vma
04964                      + ia64_info->plt_sec->output_offset
04965                      + dyn_i->plt2_offset);
04966            }
04967          else
04968            {
04969              /* Since there's no PLT entry, Validate that this is
04970                locally defined.  */
04971              BFD_ASSERT (undef_weak_ref || sym_sec->output_section != NULL);
04972 
04973              /* If the symbol is undef_weak, we shouldn't be trying
04974                to call it.  There's every chance that we'd wind up
04975                with an out-of-range fixup here.  Don't bother setting
04976                any value at all.  */
04977              if (undef_weak_ref)
04978               continue;
04979            }
04980          goto finish_pcrel;
04981 
04982        case R_IA64_PCREL21BI:
04983        case R_IA64_PCREL21F:
04984        case R_IA64_PCREL21M:
04985        case R_IA64_PCREL22:
04986        case R_IA64_PCREL64I:
04987          /* The PCREL21BI reloc is specifically not intended for use with
04988             dynamic relocs.  PCREL21F and PCREL21M are used for speculation
04989             fixup code, and thus probably ought not be dynamic.  The
04990             PCREL22 and PCREL64I relocs aren't emitted as dynamic relocs.  */
04991          if (dynamic_symbol_p)
04992            {
04993              const char *msg;
04994 
04995              if (r_type == R_IA64_PCREL21BI)
04996               msg = _("%B: @internal branch to dynamic symbol %s");
04997              else if (r_type == R_IA64_PCREL21F || r_type == R_IA64_PCREL21M)
04998               msg = _("%B: speculation fixup to dynamic symbol %s");
04999              else
05000               msg = _("%B: @pcrel relocation against dynamic symbol %s");
05001              (*_bfd_error_handler) (msg, input_bfd,
05002                                  h ? h->root.root.string
05003                                    : bfd_elf_sym_name (input_bfd,
05004                                                     symtab_hdr,
05005                                                     sym,
05006                                                     sym_sec));
05007              ret_val = FALSE;
05008              continue;
05009            }
05010          goto finish_pcrel;
05011 
05012        finish_pcrel:
05013          /* Make pc-relative.  */
05014          value -= (input_section->output_section->vma
05015                   + input_section->output_offset
05016                   + rel->r_offset) & ~ (bfd_vma) 0x3;
05017          r = elfNN_ia64_install_value (hit_addr, value, r_type);
05018          break;
05019 
05020        case R_IA64_SEGREL32MSB:
05021        case R_IA64_SEGREL32LSB:
05022        case R_IA64_SEGREL64MSB:
05023        case R_IA64_SEGREL64LSB:
05024            {
05025              struct elf_segment_map *m;
05026              Elf_Internal_Phdr *p;
05027 
05028              /* Find the segment that contains the output_section.  */
05029              for (m = elf_tdata (output_bfd)->segment_map,
05030                    p = elf_tdata (output_bfd)->phdr;
05031                  m != NULL;
05032                  m = m->next, p++)
05033               {
05034                 int i;
05035                 for (i = m->count - 1; i >= 0; i--)
05036                   if (m->sections[i] == input_section->output_section)
05037                     break;
05038                 if (i >= 0)
05039                   break;
05040               }
05041 
05042              if (m == NULL)
05043               {
05044                 r = bfd_reloc_notsupported;
05045               }
05046              else
05047               {
05048                 /* The VMA of the segment is the vaddr of the associated
05049                    program header.  */
05050                 if (value > p->p_vaddr)
05051                   value -= p->p_vaddr;
05052                 else
05053                   value = 0;
05054                 r = elfNN_ia64_install_value (hit_addr, value, r_type);
05055               }
05056              break;
05057            }
05058 
05059        case R_IA64_SECREL32MSB:
05060        case R_IA64_SECREL32LSB:
05061        case R_IA64_SECREL64MSB:
05062        case R_IA64_SECREL64LSB:
05063          /* Make output-section relative to section where the symbol
05064             is defined. PR 475  */
05065          if (sym_sec)
05066            value -= sym_sec->output_section->vma;
05067          r = elfNN_ia64_install_value (hit_addr, value, r_type);
05068          break;
05069 
05070        case R_IA64_IPLTMSB:
05071        case R_IA64_IPLTLSB:
05072          /* Install a dynamic relocation for this reloc.  */
05073          if ((dynamic_symbol_p || info->shared)
05074              && (input_section->flags & SEC_ALLOC) != 0)
05075            {
05076              BFD_ASSERT (srel != NULL);
05077 
05078              /* If we don't need dynamic symbol lookup, install two
05079                RELATIVE relocations.  */
05080              if (!dynamic_symbol_p)
05081               {
05082                 unsigned int dyn_r_type;
05083 
05084                 if (r_type == R_IA64_IPLTMSB)
05085                   dyn_r_type = R_IA64_REL64MSB;
05086                 else
05087                   dyn_r_type = R_IA64_REL64LSB;
05088 
05089                 elfNN_ia64_install_dyn_reloc (output_bfd, info,
05090                                           input_section,
05091                                           srel, rel->r_offset,
05092                                           dyn_r_type, 0, value);
05093                 elfNN_ia64_install_dyn_reloc (output_bfd, info,
05094                                           input_section,
05095                                           srel, rel->r_offset + 8,
05096                                           dyn_r_type, 0, gp_val);
05097               }
05098              else
05099               elfNN_ia64_install_dyn_reloc (output_bfd, info, input_section,
05100                                          srel, rel->r_offset, r_type,
05101                                          h->dynindx, rel->r_addend);
05102            }
05103 
05104          if (r_type == R_IA64_IPLTMSB)
05105            r_type = R_IA64_DIR64MSB;
05106          else
05107            r_type = R_IA64_DIR64LSB;
05108          elfNN_ia64_install_value (hit_addr, value, r_type);
05109          r = elfNN_ia64_install_value (hit_addr + 8, gp_val, r_type);
05110          break;
05111 
05112        case R_IA64_TPREL14:
05113        case R_IA64_TPREL22:
05114        case R_IA64_TPREL64I:
05115          value -= elfNN_ia64_tprel_base (info);
05116          r = elfNN_ia64_install_value (hit_addr, value, r_type);
05117          break;
05118 
05119        case R_IA64_DTPREL14:
05120        case R_IA64_DTPREL22:
05121        case R_IA64_DTPREL64I:
05122        case R_IA64_DTPREL32LSB:
05123        case R_IA64_DTPREL32MSB:
05124        case R_IA64_DTPREL64LSB:
05125        case R_IA64_DTPREL64MSB:
05126          value -= elfNN_ia64_dtprel_base (info);
05127          r = elfNN_ia64_install_value (hit_addr, value, r_type);
05128          break;
05129 
05130        case R_IA64_LTOFF_TPREL22:
05131        case R_IA64_LTOFF_DTPMOD22:
05132        case R_IA64_LTOFF_DTPREL22:
05133          {
05134            int got_r_type;
05135            long dynindx = h ? h->dynindx : -1;
05136            bfd_vma r_addend = rel->r_addend;
05137 
05138            switch (r_type)
05139              {
05140              default:
05141              case R_IA64_LTOFF_TPREL22:
05142               if (!dynamic_symbol_p)
05143                 {
05144                   if (!info->shared)
05145                     value -= elfNN_ia64_tprel_base (info);
05146                   else
05147                     {
05148                      r_addend += value - elfNN_ia64_dtprel_base (info);
05149                      dynindx = 0;
05150                     }
05151                 }
05152               got_r_type = R_IA64_TPREL64LSB;
05153               break;
05154              case R_IA64_LTOFF_DTPMOD22:
05155               if (!dynamic_symbol_p && !info->shared)
05156                 value = 1;
05157               got_r_type = R_IA64_DTPMOD64LSB;
05158               break;
05159              case R_IA64_LTOFF_DTPREL22:
05160               if (!dynamic_symbol_p)
05161                 value -= elfNN_ia64_dtprel_base (info);
05162               got_r_type = R_IA64_DTPRELNNLSB;
05163               break;
05164              }
05165            dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
05166            value = set_got_entry (input_bfd, info, dyn_i, dynindx, r_addend,
05167                                value, got_r_type);
05168            value -= gp_val;
05169            r = elfNN_ia64_install_value (hit_addr, value, r_type);
05170          }
05171          break;
05172 
05173        default:
05174          r = bfd_reloc_notsupported;
05175          break;
05176        }
05177 
05178       switch (r)
05179        {
05180        case bfd_reloc_ok:
05181          break;
05182 
05183        case bfd_reloc_undefined:
05184          /* This can happen for global table relative relocs if
05185             __gp is undefined.  This is a panic situation so we
05186             don't try to continue.  */
05187          (*info->callbacks->undefined_symbol)
05188            (info, "__gp", input_bfd, input_section, rel->r_offset, 1);
05189          return FALSE;
05190 
05191        case bfd_reloc_notsupported:
05192          {
05193            const char *name;
05194 
05195            if (h)
05196              name = h->root.root.string;
05197            else
05198              name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym,
05199                                    sym_sec);
05200            if (!(*info->callbacks->warning) (info, _("unsupported reloc"),
05201                                          name, input_bfd,
05202                                          input_section, rel->r_offset))
05203              return FALSE;
05204            ret_val = FALSE;
05205          }
05206          break;
05207 
05208        case bfd_reloc_dangerous:
05209        case bfd_reloc_outofrange:
05210        case bfd_reloc_overflow:
05211        default:
05212          {
05213            const char *name;
05214 
05215            if (h)
05216              name = h->root.root.string;
05217            else
05218              name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym,
05219                                    sym_sec);
05220 
05221            switch (r_type)
05222              {
05223              case R_IA64_PCREL21B:
05224              case R_IA64_PCREL21BI:
05225              case R_IA64_PCREL21M:
05226              case R_IA64_PCREL21F:
05227               if (is_elf_hash_table (info->hash))
05228                 {
05229                   /* Relaxtion is always performed for ELF output.
05230                      Overflow failures for those relocations mean
05231                      that the section is too big to relax.  */
05232                   (*_bfd_error_handler)
05233                     (_("%B: Can't relax br (%s) to `%s' at 0x%lx in section `%A' with size 0x%lx (> 0x1000000)."),
05234                      input_bfd, input_section, howto->name, name,
05235                      rel->r_offset, input_section->size);
05236                   break;
05237                 }
05238              default:
05239               if (!(*info->callbacks->reloc_overflow) (info,
05240                                                   &h->root,
05241                                                   name,
05242                                                   howto->name,
05243                                                   (bfd_vma) 0,
05244                                                   input_bfd,
05245                                                   input_section,
05246                                                   rel->r_offset))
05247                 return FALSE;
05248               break;
05249              }
05250 
05251            ret_val = FALSE;
05252          }
05253          break;
05254        }
05255     }
05256 
05257   return ret_val;
05258 }
05259 
05260 static bfd_boolean
05261 elfNN_ia64_finish_dynamic_symbol (output_bfd, info, h, sym)
05262      bfd *output_bfd;
05263      struct bfd_link_info *info;
05264      struct elf_link_hash_entry *h;
05265      Elf_Internal_Sym *sym;
05266 {
05267   struct elfNN_ia64_link_hash_table *ia64_info;
05268   struct elfNN_ia64_dyn_sym_info *dyn_i;
05269 
05270   ia64_info = elfNN_ia64_hash_table (info);
05271   dyn_i = get_dyn_sym_info (ia64_info, h, NULL, NULL, FALSE);
05272 
05273   /* Fill in the PLT data, if required.  */
05274   if (dyn_i && dyn_i->want_plt)
05275     {
05276       Elf_Internal_Rela outrel;
05277       bfd_byte *loc;
05278       asection *plt_sec;
05279       bfd_vma plt_addr, pltoff_addr, gp_val, index;
05280 
05281       gp_val = _bfd_get_gp_value (output_bfd);
05282 
05283       /* Initialize the minimal PLT entry.  */
05284 
05285       index = (dyn_i->plt_offset - PLT_HEADER_SIZE) / PLT_MIN_ENTRY_SIZE;
05286       plt_sec = ia64_info->plt_sec;
05287       loc = plt_sec->contents + dyn_i->plt_offset;
05288 
05289       memcpy (loc, plt_min_entry, PLT_MIN_ENTRY_SIZE);
05290       elfNN_ia64_install_value (loc, index, R_IA64_IMM22);
05291       elfNN_ia64_install_value (loc+2, -dyn_i->plt_offset, R_IA64_PCREL21B);
05292 
05293       plt_addr = (plt_sec->output_section->vma
05294                 + plt_sec->output_offset
05295                 + dyn_i->plt_offset);
05296       pltoff_addr = set_pltoff_entry (output_bfd, info, dyn_i, plt_addr, TRUE);
05297 
05298       /* Initialize the FULL PLT entry, if needed.  */
05299       if (dyn_i->want_plt2)
05300        {
05301          loc = plt_sec->contents + dyn_i->plt2_offset;
05302 
05303          memcpy (loc, plt_full_entry, PLT_FULL_ENTRY_SIZE);
05304          elfNN_ia64_install_value (loc, pltoff_addr - gp_val, R_IA64_IMM22);
05305 
05306          /* Mark the symbol as undefined, rather than as defined in the
05307             plt section.  Leave the value alone.  */
05308          /* ??? We didn't redefine it in adjust_dynamic_symbol in the
05309             first place.  But perhaps elflink.c did some for us.  */
05310          if (!h->def_regular)
05311            sym->st_shndx = SHN_UNDEF;
05312        }
05313 
05314       /* Create the dynamic relocation.  */
05315       outrel.r_offset = pltoff_addr;
05316       if (bfd_little_endian (output_bfd))
05317        outrel.r_info = ELFNN_R_INFO (h->dynindx, R_IA64_IPLTLSB);
05318       else
05319        outrel.r_info = ELFNN_R_INFO (h->dynindx, R_IA64_IPLTMSB);
05320       outrel.r_addend = 0;
05321 
05322       /* This is fun.  In the .IA_64.pltoff section, we've got entries
05323         that correspond both to real PLT entries, and those that
05324         happened to resolve to local symbols but need to be created
05325         to satisfy @pltoff relocations.  The .rela.IA_64.pltoff
05326         relocations for the real PLT should come at the end of the
05327         section, so that they can be indexed by plt entry at runtime.
05328 
05329         We emitted all of the relocations for the non-PLT @pltoff
05330         entries during relocate_section.  So we can consider the
05331         existing sec->reloc_count to be the base of the array of
05332         PLT relocations.  */
05333 
05334       loc = ia64_info->rel_pltoff_sec->contents;
05335       loc += ((ia64_info->rel_pltoff_sec->reloc_count + index)
05336              * sizeof (ElfNN_External_Rela));
05337       bfd_elfNN_swap_reloca_out (output_bfd, &outrel, loc);
05338     }
05339 
05340   /* Mark some specially defined symbols as absolute.  */
05341   if (strcmp (h->root.root.string, "_DYNAMIC") == 0
05342       || h == ia64_info->root.hgot
05343       || h == ia64_info->root.hplt)
05344     sym->st_shndx = SHN_ABS;
05345 
05346   return TRUE;
05347 }
05348 
05349 static bfd_boolean
05350 elfNN_ia64_finish_dynamic_sections (abfd, info)
05351      bfd *abfd;
05352      struct bfd_link_info *info;
05353 {
05354   struct elfNN_ia64_link_hash_table *ia64_info;
05355   bfd *dynobj;
05356 
05357   ia64_info = elfNN_ia64_hash_table (info);
05358   dynobj = ia64_info->root.dynobj;
05359 
05360   if (elf_hash_table (info)->dynamic_sections_created)
05361     {
05362       ElfNN_External_Dyn *dyncon, *dynconend;
05363       asection *sdyn, *sgotplt;
05364       bfd_vma gp_val;
05365 
05366       sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
05367       sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
05368       BFD_ASSERT (sdyn != NULL);
05369       dyncon = (ElfNN_External_Dyn *) sdyn->contents;
05370       dynconend = (ElfNN_External_Dyn *) (sdyn->contents + sdyn->size);
05371 
05372       gp_val = _bfd_get_gp_value (abfd);
05373 
05374       for (; dyncon < dynconend; dyncon++)
05375        {
05376          Elf_Internal_Dyn dyn;
05377 
05378          bfd_elfNN_swap_dyn_in (dynobj, dyncon, &dyn);
05379 
05380          switch (dyn.d_tag)
05381            {
05382            case DT_PLTGOT:
05383              dyn.d_un.d_ptr = gp_val;
05384              break;
05385 
05386            case DT_PLTRELSZ:
05387              dyn.d_un.d_val = (ia64_info->minplt_entries
05388                             * sizeof (ElfNN_External_Rela));
05389              break;
05390 
05391            case DT_JMPREL:
05392              /* See the comment above in finish_dynamic_symbol.  */
05393              dyn.d_un.d_ptr = (ia64_info->rel_pltoff_sec->output_section->vma
05394                             + ia64_info->rel_pltoff_sec->output_offset
05395                             + (ia64_info->rel_pltoff_sec->reloc_count
05396                                * sizeof (ElfNN_External_Rela)));
05397              break;
05398 
05399            case DT_IA_64_PLT_RESERVE:
05400              dyn.d_un.d_ptr = (sgotplt->output_section->vma
05401                             + sgotplt->output_offset);
05402              break;
05403 
05404            case DT_RELASZ:
05405              /* Do not have RELASZ include JMPREL.  This makes things
05406                easier on ld.so.  This is not what the rest of BFD set up.  */
05407              dyn.d_un.d_val -= (ia64_info->minplt_entries
05408                              * sizeof (ElfNN_External_Rela));
05409              break;
05410            }
05411 
05412          bfd_elfNN_swap_dyn_out (abfd, &dyn, dyncon);
05413        }
05414 
05415       /* Initialize the PLT0 entry.  */
05416       if (ia64_info->plt_sec)
05417        {
05418          bfd_byte *loc = ia64_info->plt_sec->contents;
05419          bfd_vma pltres;
05420 
05421          memcpy (loc, plt_header, PLT_HEADER_SIZE);
05422 
05423          pltres = (sgotplt->output_section->vma
05424                   + sgotplt->output_offset
05425                   - gp_val);
05426 
05427          elfNN_ia64_install_value (loc+1, pltres, R_IA64_GPREL22);
05428        }
05429     }
05430 
05431   return TRUE;
05432 }
05433 
05434 /* ELF file flag handling:  */
05435 
05436 /* Function to keep IA-64 specific file flags.  */
05437 static bfd_boolean
05438 elfNN_ia64_set_private_flags (abfd, flags)
05439      bfd *abfd;
05440      flagword flags;
05441 {
05442   BFD_ASSERT (!elf_flags_init (abfd)
05443              || elf_elfheader (abfd)->e_flags == flags);
05444 
05445   elf_elfheader (abfd)->e_flags = flags;
05446   elf_flags_init (abfd) = TRUE;
05447   return TRUE;
05448 }
05449 
05450 /* Merge backend specific data from an object file to the output
05451    object file when linking.  */
05452 static bfd_boolean
05453 elfNN_ia64_merge_private_bfd_data (ibfd, obfd)
05454      bfd *ibfd, *obfd;
05455 {
05456   flagword out_flags;
05457   flagword in_flags;
05458   bfd_boolean ok = TRUE;
05459 
05460   /* Don't even pretend to support mixed-format linking.  */
05461   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
05462       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
05463     return FALSE;
05464 
05465   in_flags  = elf_elfheader (ibfd)->e_flags;
05466   out_flags = elf_elfheader (obfd)->e_flags;
05467 
05468   if (! elf_flags_init (obfd))
05469     {
05470       elf_flags_init (obfd) = TRUE;
05471       elf_elfheader (obfd)->e_flags = in_flags;
05472 
05473       if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
05474          && bfd_get_arch_info (obfd)->the_default)
05475        {
05476          return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
05477                                 bfd_get_mach (ibfd));
05478        }
05479 
05480       return TRUE;
05481     }
05482 
05483   /* Check flag compatibility.  */
05484   if (in_flags == out_flags)
05485     return TRUE;
05486 
05487   /* Output has EF_IA_64_REDUCEDFP set only if all inputs have it set.  */
05488   if (!(in_flags & EF_IA_64_REDUCEDFP) && (out_flags & EF_IA_64_REDUCEDFP))
05489     elf_elfheader (obfd)->e_flags &= ~EF_IA_64_REDUCEDFP;
05490 
05491   if ((in_flags & EF_IA_64_TRAPNIL) != (out_flags & EF_IA_64_TRAPNIL))
05492     {
05493       (*_bfd_error_handler)
05494        (_("%B: linking trap-on-NULL-dereference with non-trapping files"),
05495         ibfd);
05496 
05497       bfd_set_error (bfd_error_bad_value);
05498       ok = FALSE;
05499     }
05500   if ((in_flags & EF_IA_64_BE) != (out_flags & EF_IA_64_BE))
05501     {
05502       (*_bfd_error_handler)
05503        (_("%B: linking big-endian files with little-endian files"),
05504         ibfd);
05505 
05506       bfd_set_error (bfd_error_bad_value);
05507       ok = FALSE;
05508     }
05509   if ((in_flags & EF_IA_64_ABI64) != (out_flags & EF_IA_64_ABI64))
05510     {
05511       (*_bfd_error_handler)
05512        (_("%B: linking 64-bit files with 32-bit files"),
05513         ibfd);
05514 
05515       bfd_set_error (bfd_error_bad_value);
05516       ok = FALSE;
05517     }
05518   if ((in_flags & EF_IA_64_CONS_GP) != (out_flags & EF_IA_64_CONS_GP))
05519     {
05520       (*_bfd_error_handler)
05521        (_("%B: linking constant-gp files with non-constant-gp files"),
05522         ibfd);
05523 
05524       bfd_set_error (bfd_error_bad_value);
05525       ok = FALSE;
05526     }
05527   if ((in_flags & EF_IA_64_NOFUNCDESC_CONS_GP)
05528       != (out_flags & EF_IA_64_NOFUNCDESC_CONS_GP))
05529     {
05530       (*_bfd_error_handler)
05531        (_("%B: linking auto-pic files with non-auto-pic files"),
05532         ibfd);
05533 
05534       bfd_set_error (bfd_error_bad_value);
05535       ok = FALSE;
05536     }
05537 
05538   return ok;
05539 }
05540 
05541 static bfd_boolean
05542 elfNN_ia64_print_private_bfd_data (abfd, ptr)
05543      bfd *abfd;
05544      PTR ptr;
05545 {
05546   FILE *file = (FILE *) ptr;
05547   flagword flags = elf_elfheader (abfd)->e_flags;
05548 
05549   BFD_ASSERT (abfd != NULL && ptr != NULL);
05550 
05551   fprintf (file, "private flags = %s%s%s%s%s%s%s%s\n",
05552           (flags & EF_IA_64_TRAPNIL) ? "TRAPNIL, " : "",
05553           (flags & EF_IA_64_EXT) ? "EXT, " : "",
05554           (flags & EF_IA_64_BE) ? "BE, " : "LE, ",
05555           (flags & EF_IA_64_REDUCEDFP) ? "REDUCEDFP, " : "",
05556           (flags & EF_IA_64_CONS_GP) ? "CONS_GP, " : "",
05557           (flags & EF_IA_64_NOFUNCDESC_CONS_GP) ? "NOFUNCDESC_CONS_GP, " : "",
05558           (flags & EF_IA_64_ABSOLUTE) ? "ABSOLUTE, " : "",
05559           (flags & EF_IA_64_ABI64) ? "ABI64" : "ABI32");
05560 
05561   _bfd_elf_print_private_bfd_data (abfd, ptr);
05562   return TRUE;
05563 }
05564 
05565 static enum elf_reloc_type_class
05566 elfNN_ia64_reloc_type_class (rela)
05567      const Elf_Internal_Rela *rela;
05568 {
05569   switch ((int) ELFNN_R_TYPE (rela->r_info))
05570     {
05571     case R_IA64_REL32MSB:
05572     case R_IA64_REL32LSB:
05573     case R_IA64_REL64MSB:
05574     case R_IA64_REL64LSB:
05575       return reloc_class_relative;
05576     case R_IA64_IPLTMSB:
05577     case R_IA64_IPLTLSB:
05578       return reloc_class_plt;
05579     case R_IA64_COPY:
05580       return reloc_class_copy;
05581     default:
05582       return reloc_class_normal;
05583     }
05584 }
05585 
05586 static const struct bfd_elf_special_section elfNN_ia64_special_sections[] =
05587 {
05588   { STRING_COMMA_LEN (".sbss"),  -1, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE + SHF_IA_64_SHORT },
05589   { STRING_COMMA_LEN (".sdata"), -1, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_IA_64_SHORT },
05590   { NULL,                    0,   0, 0,            0 }
05591 };
05592 
05593 static bfd_boolean
05594 elfNN_ia64_object_p (bfd *abfd)
05595 {
05596   asection *sec;
05597   asection *group, *unwi, *unw;
05598   flagword flags;
05599   const char *name;
05600   char *unwi_name, *unw_name;
05601   bfd_size_type amt;
05602 
05603   if (abfd->flags & DYNAMIC)
05604     return TRUE;
05605 
05606   /* Flags for fake group section.  */
05607   flags = (SEC_LINKER_CREATED | SEC_GROUP | SEC_LINK_ONCE
05608           | SEC_EXCLUDE);
05609 
05610   /* We add a fake section group for each .gnu.linkonce.t.* section,
05611      which isn't in a section group, and its unwind sections.  */
05612   for (sec = abfd->sections; sec != NULL; sec = sec->next)
05613     {
05614       if (elf_sec_group (sec) == NULL
05615          && ((sec->flags & (SEC_LINK_ONCE | SEC_CODE | SEC_GROUP))
05616              == (SEC_LINK_ONCE | SEC_CODE))
05617          && CONST_STRNEQ (sec->name, ".gnu.linkonce.t."))
05618        {
05619          name = sec->name + 16;
05620 
05621          amt = strlen (name) + sizeof (".gnu.linkonce.ia64unwi.");
05622          unwi_name = bfd_alloc (abfd, amt);
05623          if (!unwi_name)
05624            return FALSE;
05625 
05626          strcpy (stpcpy (unwi_name, ".gnu.linkonce.ia64unwi."), name);
05627          unwi = bfd_get_section_by_name (abfd, unwi_name);
05628 
05629          amt = strlen (name) + sizeof (".gnu.linkonce.ia64unw.");
05630          unw_name = bfd_alloc (abfd, amt);
05631          if (!unw_name)
05632            return FALSE;
05633 
05634          strcpy (stpcpy (unw_name, ".gnu.linkonce.ia64unw."), name);
05635          unw = bfd_get_section_by_name (abfd, unw_name);
05636 
05637          /* We need to create a fake group section for it and its
05638             unwind sections.  */
05639          group = bfd_make_section_anyway_with_flags (abfd, name,
05640                                                 flags);
05641          if (group == NULL)
05642            return FALSE;
05643 
05644          /* Move the fake group section to the beginning.  */
05645          bfd_section_list_remove (abfd, group);
05646          bfd_section_list_prepend (abfd, group);
05647 
05648          elf_next_in_group (group) = sec;
05649 
05650          elf_group_name (sec) = name;
05651          elf_next_in_group (sec) = sec;
05652          elf_sec_group (sec) = group;
05653 
05654          if (unwi)
05655            {
05656              elf_group_name (unwi) = name;
05657              elf_next_in_group (unwi) = sec;
05658              elf_next_in_group (sec) = unwi;
05659              elf_sec_group (unwi) = group;
05660            }
05661 
05662           if (unw)
05663             {
05664               elf_group_name (unw) = name;
05665               if (unwi)
05666                {
05667                  elf_next_in_group (unw) = elf_next_in_group (unwi);
05668                  elf_next_in_group (unwi) = unw;
05669                }
05670               else
05671                {
05672                  elf_next_in_group (unw) = sec;
05673                  elf_next_in_group (sec) = unw;
05674                }
05675               elf_sec_group (unw) = group;
05676             }
05677 
05678           /* Fake SHT_GROUP section header.  */
05679          elf_section_data (group)->this_hdr.bfd_section = group;
05680          elf_section_data (group)->this_hdr.sh_type = SHT_GROUP;
05681        }
05682     }
05683   return TRUE;
05684 }
05685 
05686 static bfd_boolean
05687 elfNN_ia64_hpux_vec (const bfd_target *vec)
05688 {
05689   extern const bfd_target bfd_elfNN_ia64_hpux_big_vec;
05690   return (vec == & bfd_elfNN_ia64_hpux_big_vec);
05691 }
05692 
05693 static void
05694 elfNN_hpux_post_process_headers (abfd, info)
05695        bfd *abfd;
05696        struct bfd_link_info *info ATTRIBUTE_UNUSED;
05697 {
05698   Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd);
05699 
05700   i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi;
05701   i_ehdrp->e_ident[EI_ABIVERSION] = 1;
05702 }
05703 
05704 bfd_boolean
05705 elfNN_hpux_backend_section_from_bfd_section (abfd, sec, retval)
05706        bfd *abfd ATTRIBUTE_UNUSED;
05707        asection *sec;
05708        int *retval;
05709 {
05710   if (bfd_is_com_section (sec))
05711     {
05712       *retval = SHN_IA_64_ANSI_COMMON;
05713       return TRUE;
05714     }
05715   return FALSE;
05716 }
05717 
05718 static void
05719 elfNN_hpux_backend_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
05720                                   asymbol *asym)
05721 {
05722   elf_symbol_type *elfsym = (elf_symbol_type *) asym;
05723 
05724   switch (elfsym->internal_elf_sym.st_shndx)
05725     {
05726     case SHN_IA_64_ANSI_COMMON:
05727       asym->section = bfd_com_section_ptr;
05728       asym->value = elfsym->internal_elf_sym.st_size;
05729       asym->flags &= ~BSF_GLOBAL;
05730       break;
05731     }
05732 }
05733 
05734 
05735 #define TARGET_LITTLE_SYM          bfd_elfNN_ia64_little_vec
05736 #define TARGET_LITTLE_NAME         "elfNN-ia64-little"
05737 #define TARGET_BIG_SYM                    bfd_elfNN_ia64_big_vec
05738 #define TARGET_BIG_NAME                   "elfNN-ia64-big"
05739 #define ELF_ARCH                   bfd_arch_ia64
05740 #define ELF_MACHINE_CODE           EM_IA_64
05741 #define ELF_MACHINE_ALT1           1999   /* EAS2.3 */
05742 #define ELF_MACHINE_ALT2           1998   /* EAS2.2 */
05743 #define ELF_MAXPAGESIZE                   0x10000       /* 64KB */
05744 #define ELF_COMMONPAGESIZE         0x4000 /* 16KB */
05745 
05746 #define elf_backend_section_from_shdr \
05747        elfNN_ia64_section_from_shdr
05748 #define elf_backend_section_flags \
05749        elfNN_ia64_section_flags
05750 #define elf_backend_fake_sections \
05751        elfNN_ia64_fake_sections
05752 #define elf_backend_final_write_processing \
05753        elfNN_ia64_final_write_processing
05754 #define elf_backend_add_symbol_hook \
05755        elfNN_ia64_add_symbol_hook
05756 #define elf_backend_additional_program_headers \
05757        elfNN_ia64_additional_program_headers
05758 #define elf_backend_modify_segment_map \
05759        elfNN_ia64_modify_segment_map
05760 #define elf_backend_modify_program_headers \
05761        elfNN_ia64_modify_program_headers
05762 #define elf_info_to_howto \
05763        elfNN_ia64_info_to_howto
05764 
05765 #define bfd_elfNN_bfd_reloc_type_lookup \
05766        elfNN_ia64_reloc_type_lookup
05767 #define bfd_elfNN_bfd_reloc_name_lookup \
05768        elfNN_ia64_reloc_name_lookup
05769 #define bfd_elfNN_bfd_is_local_label_name \
05770        elfNN_ia64_is_local_label_name
05771 #define bfd_elfNN_bfd_relax_section \
05772        elfNN_ia64_relax_section
05773 
05774 #define elf_backend_object_p \
05775        elfNN_ia64_object_p
05776 
05777 /* Stuff for the BFD linker: */
05778 #define bfd_elfNN_bfd_link_hash_table_create \
05779        elfNN_ia64_hash_table_create
05780 #define bfd_elfNN_bfd_link_hash_table_free \
05781        elfNN_ia64_hash_table_free
05782 #define elf_backend_create_dynamic_sections \
05783        elfNN_ia64_create_dynamic_sections
05784 #define elf_backend_check_relocs \
05785        elfNN_ia64_check_relocs
05786 #define elf_backend_adjust_dynamic_symbol \
05787        elfNN_ia64_adjust_dynamic_symbol
05788 #define elf_backend_size_dynamic_sections \
05789        elfNN_ia64_size_dynamic_sections
05790 #define elf_backend_omit_section_dynsym \
05791   ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
05792 #define elf_backend_relocate_section \
05793        elfNN_ia64_relocate_section
05794 #define elf_backend_finish_dynamic_symbol \
05795        elfNN_ia64_finish_dynamic_symbol
05796 #define elf_backend_finish_dynamic_sections \
05797        elfNN_ia64_finish_dynamic_sections
05798 #define bfd_elfNN_bfd_final_link \
05799        elfNN_ia64_final_link
05800 
05801 #define bfd_elfNN_bfd_merge_private_bfd_data \
05802        elfNN_ia64_merge_private_bfd_data
05803 #define bfd_elfNN_bfd_set_private_flags \
05804        elfNN_ia64_set_private_flags
05805 #define bfd_elfNN_bfd_print_private_bfd_data \
05806        elfNN_ia64_print_private_bfd_data
05807 
05808 #define elf_backend_plt_readonly   1
05809 #define elf_backend_want_plt_sym   0
05810 #define elf_backend_plt_alignment  5
05811 #define elf_backend_got_header_size       0
05812 #define elf_backend_want_got_plt   1
05813 #define elf_backend_may_use_rel_p  1
05814 #define elf_backend_may_use_rela_p 1
05815 #define elf_backend_default_use_rela_p    1
05816 #define elf_backend_want_dynbss           0
05817 #define elf_backend_copy_indirect_symbol elfNN_ia64_hash_copy_indirect
05818 #define elf_backend_hide_symbol           elfNN_ia64_hash_hide_symbol
05819 #define elf_backend_fixup_symbol   _bfd_elf_link_hash_fixup_symbol
05820 #define elf_backend_reloc_type_class      elfNN_ia64_reloc_type_class
05821 #define elf_backend_rela_normal           1
05822 #define elf_backend_special_sections      elfNN_ia64_special_sections
05823 #define elf_backend_default_execstack     0
05824 
05825 /* FIXME: PR 290: The Intel C compiler generates SHT_IA_64_UNWIND with
05826    SHF_LINK_ORDER. But it doesn't set the sh_link or sh_info fields.
05827    We don't want to flood users with so many error messages. We turn
05828    off the warning for now. It will be turned on later when the Intel
05829    compiler is fixed.   */
05830 #define elf_backend_link_order_error_handler NULL
05831 
05832 #include "elfNN-target.h"
05833 
05834 /* HPUX-specific vectors.  */
05835 
05836 #undef  TARGET_LITTLE_SYM
05837 #undef  TARGET_LITTLE_NAME
05838 #undef  TARGET_BIG_SYM
05839 #define TARGET_BIG_SYM                  bfd_elfNN_ia64_hpux_big_vec
05840 #undef  TARGET_BIG_NAME
05841 #define TARGET_BIG_NAME                 "elfNN-ia64-hpux-big"
05842 
05843 /* These are HP-UX specific functions.  */
05844 
05845 #undef  elf_backend_post_process_headers
05846 #define elf_backend_post_process_headers elfNN_hpux_post_process_headers
05847 
05848 #undef  elf_backend_section_from_bfd_section
05849 #define elf_backend_section_from_bfd_section elfNN_hpux_backend_section_from_bfd_section
05850 
05851 #undef elf_backend_symbol_processing
05852 #define elf_backend_symbol_processing elfNN_hpux_backend_symbol_processing
05853 
05854 #undef  elf_backend_want_p_paddr_set_to_zero
05855 #define elf_backend_want_p_paddr_set_to_zero 1
05856 
05857 #undef  ELF_MAXPAGESIZE
05858 #define ELF_MAXPAGESIZE                 0x1000  /* 4K */
05859 #undef ELF_COMMONPAGESIZE
05860 #undef ELF_OSABI
05861 #define ELF_OSABI                  ELFOSABI_HPUX
05862 
05863 #undef  elfNN_bed
05864 #define elfNN_bed elfNN_ia64_hpux_bed
05865 
05866 #include "elfNN-target.h"
05867 
05868 #undef  elf_backend_want_p_paddr_set_to_zero