daily update
[deliverable/binutils-gdb.git] / bfd / elfxx-ia64.c
CommitLineData
800eeca4 1/* IA-64 support for 64-bit ELF
b3dfd7fe 2 Copyright 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
800eeca4
JW
3 Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
4
5e8d7549 5 This file is part of BFD, the Binary File Descriptor library.
800eeca4 6
5e8d7549
NC
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
800eeca4 11
5e8d7549
NC
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
800eeca4 16
5e8d7549
NC
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
800eeca4
JW
20
21#include "bfd.h"
22#include "sysdep.h"
23#include "libbfd.h"
24#include "elf-bfd.h"
25#include "opcode/ia64.h"
26#include "elf/ia64.h"
27
5e8d7549 28/* THE RULES for all the stuff the linker creates --
b34976b6 29
5e8d7549
NC
30 GOT Entries created in response to LTOFF or LTOFF_FPTR
31 relocations. Dynamic relocs created for dynamic
32 symbols in an application; REL relocs for locals
33 in a shared library.
b34976b6 34
5e8d7549
NC
35 FPTR The canonical function descriptor. Created for local
36 symbols in applications. Descriptors for dynamic symbols
37 and local symbols in shared libraries are created by
38 ld.so. Thus there are no dynamic relocs against these
39 objects. The FPTR relocs for such _are_ passed through
40 to the dynamic relocation tables.
b34976b6 41
5e8d7549
NC
42 FULL_PLT Created for a PCREL21B relocation against a dynamic symbol.
43 Requires the creation of a PLTOFF entry. This does not
44 require any dynamic relocations.
b34976b6 45
5e8d7549
NC
46 PLTOFF Created by PLTOFF relocations. For local symbols, this
47 is an alternate function descriptor, and in shared libraries
48 requires two REL relocations. Note that this cannot be
49 transformed into an FPTR relocation, since it must be in
50 range of the GP. For dynamic symbols, this is a function
51 descriptor for a MIN_PLT entry, and requires one IPLT reloc.
b34976b6 52
5e8d7549
NC
53 MIN_PLT Created by PLTOFF entries against dynamic symbols. This
54 does not reqire dynamic relocations. */
800eeca4 55
800eeca4
JW
56#define NELEMS(a) ((int) (sizeof (a) / sizeof ((a)[0])))
57
58typedef struct bfd_hash_entry *(*new_hash_entry_func)
59 PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
60
61/* In dynamically (linker-) created sections, we generally need to keep track
62 of the place a symbol or expression got allocated to. This is done via hash
63 tables that store entries of the following type. */
64
bbe66d08 65struct elfNN_ia64_dyn_sym_info
800eeca4
JW
66{
67 /* The addend for which this entry is relevant. */
68 bfd_vma addend;
69
70 /* Next addend in the list. */
bbe66d08 71 struct elfNN_ia64_dyn_sym_info *next;
800eeca4
JW
72
73 bfd_vma got_offset;
74 bfd_vma fptr_offset;
75 bfd_vma pltoff_offset;
76 bfd_vma plt_offset;
77 bfd_vma plt2_offset;
13ae64f3
JJ
78 bfd_vma tprel_offset;
79 bfd_vma dtpmod_offset;
80 bfd_vma dtprel_offset;
800eeca4
JW
81
82 /* The symbol table entry, if any, that this was derrived from. */
83 struct elf_link_hash_entry *h;
3e932841 84
800eeca4
JW
85 /* Used to count non-got, non-plt relocations for delayed sizing
86 of relocation sections. */
bbe66d08 87 struct elfNN_ia64_dyn_reloc_entry
800eeca4 88 {
bbe66d08 89 struct elfNN_ia64_dyn_reloc_entry *next;
800eeca4
JW
90 asection *srel;
91 int type;
92 int count;
93 } *reloc_entries;
94
b34976b6 95 /* TRUE when the section contents have been updated. */
800eeca4
JW
96 unsigned got_done : 1;
97 unsigned fptr_done : 1;
98 unsigned pltoff_done : 1;
13ae64f3
JJ
99 unsigned tprel_done : 1;
100 unsigned dtpmod_done : 1;
101 unsigned dtprel_done : 1;
800eeca4 102
b34976b6 103 /* TRUE for the different kinds of linker data we want created. */
800eeca4 104 unsigned want_got : 1;
2c4c2bc0 105 unsigned want_gotx : 1;
800eeca4
JW
106 unsigned want_fptr : 1;
107 unsigned want_ltoff_fptr : 1;
108 unsigned want_plt : 1;
109 unsigned want_plt2 : 1;
110 unsigned want_pltoff : 1;
13ae64f3
JJ
111 unsigned want_tprel : 1;
112 unsigned want_dtpmod : 1;
113 unsigned want_dtprel : 1;
800eeca4
JW
114};
115
bbe66d08 116struct elfNN_ia64_local_hash_entry
800eeca4
JW
117{
118 struct bfd_hash_entry root;
bbe66d08 119 struct elfNN_ia64_dyn_sym_info *info;
f7460f5f 120
b34976b6 121 /* TRUE if this hash entry's addends was translated for
f7460f5f
JJ
122 SHF_MERGE optimization. */
123 unsigned sec_merge_done : 1;
800eeca4
JW
124};
125
bbe66d08 126struct elfNN_ia64_local_hash_table
800eeca4
JW
127{
128 struct bfd_hash_table root;
129 /* No additional fields for now. */
130};
131
bbe66d08 132struct elfNN_ia64_link_hash_entry
800eeca4
JW
133{
134 struct elf_link_hash_entry root;
bbe66d08 135 struct elfNN_ia64_dyn_sym_info *info;
800eeca4
JW
136};
137
bbe66d08 138struct elfNN_ia64_link_hash_table
800eeca4 139{
5e8d7549 140 /* The main hash table. */
800eeca4
JW
141 struct elf_link_hash_table root;
142
143 asection *got_sec; /* the linkage table section (or NULL) */
144 asection *rel_got_sec; /* dynamic relocation section for same */
145 asection *fptr_sec; /* function descriptor table (or NULL) */
146 asection *plt_sec; /* the primary plt section (or NULL) */
147 asection *pltoff_sec; /* private descriptors for plt (or NULL) */
148 asection *rel_pltoff_sec; /* dynamic relocation section for same */
149
150 bfd_size_type minplt_entries; /* number of minplt entries */
db6751f2 151 unsigned reltext : 1; /* are there relocs against readonly sections? */
b3dfd7fe
JJ
152 unsigned self_dtpmod_done : 1;/* has self DTPMOD entry been finished? */
153 bfd_vma self_dtpmod_offset; /* .got offset to self DTPMOD entry */
800eeca4 154
bbe66d08 155 struct elfNN_ia64_local_hash_table loc_hash_table;
800eeca4
JW
156};
157
2c4c2bc0
RH
158struct elfNN_ia64_allocate_data
159{
160 struct bfd_link_info *info;
161 bfd_size_type ofs;
162};
163
bbe66d08
JW
164#define elfNN_ia64_hash_table(p) \
165 ((struct elfNN_ia64_link_hash_table *) ((p)->hash))
800eeca4 166
bbe66d08 167static bfd_reloc_status_type elfNN_ia64_reloc
800eeca4
JW
168 PARAMS ((bfd *abfd, arelent *reloc, asymbol *sym, PTR data,
169 asection *input_section, bfd *output_bfd, char **error_message));
170static reloc_howto_type * lookup_howto
171 PARAMS ((unsigned int rtype));
bbe66d08 172static reloc_howto_type *elfNN_ia64_reloc_type_lookup
800eeca4 173 PARAMS ((bfd *abfd, bfd_reloc_code_real_type bfd_code));
bbe66d08 174static void elfNN_ia64_info_to_howto
947216bf 175 PARAMS ((bfd *abfd, arelent *bfd_reloc, Elf_Internal_Rela *elf_reloc));
b34976b6 176static bfd_boolean elfNN_ia64_relax_section
748abff6 177 PARAMS((bfd *abfd, asection *sec, struct bfd_link_info *link_info,
b34976b6 178 bfd_boolean *again));
2c4c2bc0
RH
179static void elfNN_ia64_relax_ldxmov
180 PARAMS((bfd *abfd, bfd_byte *contents, bfd_vma off));
b34976b6 181static bfd_boolean is_unwind_section_name
d9cf1b54 182 PARAMS ((bfd *abfd, const char *));
b34976b6 183static bfd_boolean elfNN_ia64_section_from_shdr
947216bf 184 PARAMS ((bfd *, Elf_Internal_Shdr *, const char *));
b34976b6 185static bfd_boolean elfNN_ia64_section_flags
947216bf 186 PARAMS ((flagword *, Elf_Internal_Shdr *));
b34976b6 187static bfd_boolean elfNN_ia64_fake_sections
947216bf 188 PARAMS ((bfd *abfd, Elf_Internal_Shdr *hdr, asection *sec));
81545d45 189static void elfNN_ia64_final_write_processing
b34976b6
AM
190 PARAMS ((bfd *abfd, bfd_boolean linker));
191static bfd_boolean elfNN_ia64_add_symbol_hook
800eeca4
JW
192 PARAMS ((bfd *abfd, struct bfd_link_info *info, const Elf_Internal_Sym *sym,
193 const char **namep, flagword *flagsp, asection **secp,
194 bfd_vma *valp));
b34976b6 195static bfd_boolean elfNN_ia64_aix_vec
7b6dab7f 196 PARAMS ((const bfd_target *vec));
b34976b6 197static bfd_boolean elfNN_ia64_aix_add_symbol_hook
7b6dab7f
TW
198 PARAMS ((bfd *abfd, struct bfd_link_info *info, const Elf_Internal_Sym *sym,
199 const char **namep, flagword *flagsp, asection **secp,
200 bfd_vma *valp));
b34976b6 201static bfd_boolean elfNN_ia64_aix_link_add_symbols
7b6dab7f 202 PARAMS ((bfd *abfd, struct bfd_link_info *info));
bbe66d08 203static int elfNN_ia64_additional_program_headers
800eeca4 204 PARAMS ((bfd *abfd));
b34976b6 205static bfd_boolean elfNN_ia64_modify_segment_map
cea4409c 206 PARAMS ((bfd *));
b34976b6 207static bfd_boolean elfNN_ia64_is_local_label_name
800eeca4 208 PARAMS ((bfd *abfd, const char *name));
b34976b6 209static bfd_boolean elfNN_ia64_dynamic_symbol_p
800eeca4 210 PARAMS ((struct elf_link_hash_entry *h, struct bfd_link_info *info));
b34976b6 211static bfd_boolean elfNN_ia64_local_hash_table_init
bbe66d08 212 PARAMS ((struct elfNN_ia64_local_hash_table *ht, bfd *abfd,
800eeca4 213 new_hash_entry_func new));
bbe66d08 214static struct bfd_hash_entry *elfNN_ia64_new_loc_hash_entry
800eeca4
JW
215 PARAMS ((struct bfd_hash_entry *entry, struct bfd_hash_table *table,
216 const char *string));
bbe66d08 217static struct bfd_hash_entry *elfNN_ia64_new_elf_hash_entry
800eeca4
JW
218 PARAMS ((struct bfd_hash_entry *entry, struct bfd_hash_table *table,
219 const char *string));
cea4409c 220static void elfNN_ia64_hash_copy_indirect
b48fa14c
AM
221 PARAMS ((struct elf_backend_data *, struct elf_link_hash_entry *,
222 struct elf_link_hash_entry *));
cea4409c 223static void elfNN_ia64_hash_hide_symbol
b34976b6 224 PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *, bfd_boolean));
bbe66d08 225static struct bfd_link_hash_table *elfNN_ia64_hash_table_create
800eeca4 226 PARAMS ((bfd *abfd));
bbe66d08
JW
227static struct elfNN_ia64_local_hash_entry *elfNN_ia64_local_hash_lookup
228 PARAMS ((struct elfNN_ia64_local_hash_table *table, const char *string,
b34976b6
AM
229 bfd_boolean create, bfd_boolean copy));
230static bfd_boolean elfNN_ia64_global_dyn_sym_thunk
cea4409c 231 PARAMS ((struct bfd_hash_entry *, PTR));
b34976b6 232static bfd_boolean elfNN_ia64_local_dyn_sym_thunk
cea4409c 233 PARAMS ((struct bfd_hash_entry *, PTR));
bbe66d08
JW
234static void elfNN_ia64_dyn_sym_traverse
235 PARAMS ((struct elfNN_ia64_link_hash_table *ia64_info,
b34976b6 236 bfd_boolean (*func) (struct elfNN_ia64_dyn_sym_info *, PTR),
800eeca4 237 PTR info));
b34976b6 238static bfd_boolean elfNN_ia64_create_dynamic_sections
800eeca4 239 PARAMS ((bfd *abfd, struct bfd_link_info *info));
f7460f5f
JJ
240static struct elfNN_ia64_local_hash_entry * get_local_sym_hash
241 PARAMS ((struct elfNN_ia64_link_hash_table *ia64_info,
b34976b6 242 bfd *abfd, const Elf_Internal_Rela *rel, bfd_boolean create));
bbe66d08
JW
243static struct elfNN_ia64_dyn_sym_info * get_dyn_sym_info
244 PARAMS ((struct elfNN_ia64_link_hash_table *ia64_info,
800eeca4 245 struct elf_link_hash_entry *h,
b34976b6 246 bfd *abfd, const Elf_Internal_Rela *rel, bfd_boolean create));
800eeca4
JW
247static asection *get_got
248 PARAMS ((bfd *abfd, struct bfd_link_info *info,
bbe66d08 249 struct elfNN_ia64_link_hash_table *ia64_info));
800eeca4
JW
250static asection *get_fptr
251 PARAMS ((bfd *abfd, struct bfd_link_info *info,
bbe66d08 252 struct elfNN_ia64_link_hash_table *ia64_info));
800eeca4
JW
253static asection *get_pltoff
254 PARAMS ((bfd *abfd, struct bfd_link_info *info,
bbe66d08 255 struct elfNN_ia64_link_hash_table *ia64_info));
800eeca4 256static asection *get_reloc_section
bbe66d08 257 PARAMS ((bfd *abfd, struct elfNN_ia64_link_hash_table *ia64_info,
b34976b6
AM
258 asection *sec, bfd_boolean create));
259static bfd_boolean count_dyn_reloc
bbe66d08 260 PARAMS ((bfd *abfd, struct elfNN_ia64_dyn_sym_info *dyn_i,
800eeca4 261 asection *srel, int type));
b34976b6 262static bfd_boolean elfNN_ia64_check_relocs
800eeca4
JW
263 PARAMS ((bfd *abfd, struct bfd_link_info *info, asection *sec,
264 const Elf_Internal_Rela *relocs));
b34976b6 265static bfd_boolean elfNN_ia64_adjust_dynamic_symbol
800eeca4 266 PARAMS ((struct bfd_link_info *info, struct elf_link_hash_entry *h));
dc810e39 267static long global_sym_index
800eeca4 268 PARAMS ((struct elf_link_hash_entry *h));
b34976b6 269static bfd_boolean allocate_fptr
bbe66d08 270 PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
b34976b6 271static bfd_boolean allocate_global_data_got
bbe66d08 272 PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
b34976b6 273static bfd_boolean allocate_global_fptr_got
bbe66d08 274 PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
b34976b6 275static bfd_boolean allocate_local_got
bbe66d08 276 PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
b34976b6 277static bfd_boolean allocate_pltoff_entries
bbe66d08 278 PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
b34976b6 279static bfd_boolean allocate_plt_entries
bbe66d08 280 PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
b34976b6 281static bfd_boolean allocate_plt2_entries
bbe66d08 282 PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
b34976b6 283static bfd_boolean allocate_dynrel_entries
bbe66d08 284 PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
b34976b6 285static bfd_boolean elfNN_ia64_size_dynamic_sections
800eeca4 286 PARAMS ((bfd *output_bfd, struct bfd_link_info *info));
bbe66d08 287static bfd_reloc_status_type elfNN_ia64_install_value
800eeca4 288 PARAMS ((bfd *abfd, bfd_byte *hit_addr, bfd_vma val, unsigned int r_type));
bbe66d08 289static void elfNN_ia64_install_dyn_reloc
800eeca4
JW
290 PARAMS ((bfd *abfd, struct bfd_link_info *info, asection *sec,
291 asection *srel, bfd_vma offset, unsigned int type,
292 long dynindx, bfd_vma addend));
293static bfd_vma set_got_entry
294 PARAMS ((bfd *abfd, struct bfd_link_info *info,
bbe66d08 295 struct elfNN_ia64_dyn_sym_info *dyn_i, long dynindx,
800eeca4
JW
296 bfd_vma addend, bfd_vma value, unsigned int dyn_r_type));
297static bfd_vma set_fptr_entry
298 PARAMS ((bfd *abfd, struct bfd_link_info *info,
bbe66d08 299 struct elfNN_ia64_dyn_sym_info *dyn_i,
800eeca4
JW
300 bfd_vma value));
301static bfd_vma set_pltoff_entry
302 PARAMS ((bfd *abfd, struct bfd_link_info *info,
bbe66d08 303 struct elfNN_ia64_dyn_sym_info *dyn_i,
b34976b6 304 bfd_vma value, bfd_boolean));
13ae64f3
JJ
305static bfd_vma elfNN_ia64_tprel_base
306 PARAMS ((struct bfd_link_info *info));
307static bfd_vma elfNN_ia64_dtprel_base
308 PARAMS ((struct bfd_link_info *info));
cea4409c
AM
309static int elfNN_ia64_unwind_entry_compare
310 PARAMS ((const PTR, const PTR));
2c4c2bc0
RH
311static bfd_boolean elfNN_ia64_choose_gp
312 PARAMS ((bfd *abfd, struct bfd_link_info *info));
b34976b6 313static bfd_boolean elfNN_ia64_final_link
800eeca4 314 PARAMS ((bfd *abfd, struct bfd_link_info *info));
b34976b6 315static bfd_boolean elfNN_ia64_relocate_section
800eeca4
JW
316 PARAMS ((bfd *output_bfd, struct bfd_link_info *info, bfd *input_bfd,
317 asection *input_section, bfd_byte *contents,
318 Elf_Internal_Rela *relocs, Elf_Internal_Sym *local_syms,
319 asection **local_sections));
b34976b6 320static bfd_boolean elfNN_ia64_finish_dynamic_symbol
800eeca4
JW
321 PARAMS ((bfd *output_bfd, struct bfd_link_info *info,
322 struct elf_link_hash_entry *h, Elf_Internal_Sym *sym));
b34976b6 323static bfd_boolean elfNN_ia64_finish_dynamic_sections
800eeca4 324 PARAMS ((bfd *abfd, struct bfd_link_info *info));
b34976b6 325static bfd_boolean elfNN_ia64_set_private_flags
800eeca4 326 PARAMS ((bfd *abfd, flagword flags));
b34976b6 327static bfd_boolean elfNN_ia64_merge_private_bfd_data
800eeca4 328 PARAMS ((bfd *ibfd, bfd *obfd));
b34976b6 329static bfd_boolean elfNN_ia64_print_private_bfd_data
800eeca4 330 PARAMS ((bfd *abfd, PTR ptr));
db6751f2 331static enum elf_reloc_type_class elfNN_ia64_reloc_type_class
f51e552e 332 PARAMS ((const Elf_Internal_Rela *));
b34976b6 333static bfd_boolean elfNN_ia64_hpux_vec
d9cf1b54 334 PARAMS ((const bfd_target *vec));
fcf12726
AM
335static void elfNN_hpux_post_process_headers
336 PARAMS ((bfd *abfd, struct bfd_link_info *info));
b34976b6 337bfd_boolean elfNN_hpux_backend_section_from_bfd_section
af746e92 338 PARAMS ((bfd *abfd, asection *sec, int *retval));
800eeca4 339\f
5e8d7549 340/* ia64-specific relocation. */
800eeca4
JW
341
342/* Perform a relocation. Not much to do here as all the hard work is
bbe66d08 343 done in elfNN_ia64_final_link_relocate. */
800eeca4 344static bfd_reloc_status_type
bbe66d08 345elfNN_ia64_reloc (abfd, reloc, sym, data, input_section,
800eeca4 346 output_bfd, error_message)
64bf6ae6 347 bfd *abfd ATTRIBUTE_UNUSED;
800eeca4 348 arelent *reloc;
64bf6ae6
JW
349 asymbol *sym ATTRIBUTE_UNUSED;
350 PTR data ATTRIBUTE_UNUSED;
800eeca4
JW
351 asection *input_section;
352 bfd *output_bfd;
353 char **error_message;
354{
355 if (output_bfd)
356 {
357 reloc->address += input_section->output_offset;
358 return bfd_reloc_ok;
359 }
bbe66d08 360 *error_message = "Unsupported call to elfNN_ia64_reloc";
800eeca4
JW
361 return bfd_reloc_notsupported;
362}
363
364#define IA64_HOWTO(TYPE, NAME, SIZE, PCREL, IN) \
365 HOWTO (TYPE, 0, SIZE, 0, PCREL, 0, complain_overflow_signed, \
b34976b6 366 elfNN_ia64_reloc, NAME, FALSE, 0, 0, IN)
800eeca4
JW
367
368/* This table has to be sorted according to increasing number of the
369 TYPE field. */
370static reloc_howto_type ia64_howto_table[] =
371 {
b34976b6
AM
372 IA64_HOWTO (R_IA64_NONE, "NONE", 0, FALSE, TRUE),
373
374 IA64_HOWTO (R_IA64_IMM14, "IMM14", 0, FALSE, TRUE),
375 IA64_HOWTO (R_IA64_IMM22, "IMM22", 0, FALSE, TRUE),
376 IA64_HOWTO (R_IA64_IMM64, "IMM64", 0, FALSE, TRUE),
377 IA64_HOWTO (R_IA64_DIR32MSB, "DIR32MSB", 2, FALSE, TRUE),
378 IA64_HOWTO (R_IA64_DIR32LSB, "DIR32LSB", 2, FALSE, TRUE),
379 IA64_HOWTO (R_IA64_DIR64MSB, "DIR64MSB", 4, FALSE, TRUE),
380 IA64_HOWTO (R_IA64_DIR64LSB, "DIR64LSB", 4, FALSE, TRUE),
381
382 IA64_HOWTO (R_IA64_GPREL22, "GPREL22", 0, FALSE, TRUE),
383 IA64_HOWTO (R_IA64_GPREL64I, "GPREL64I", 0, FALSE, TRUE),
384 IA64_HOWTO (R_IA64_GPREL32MSB, "GPREL32MSB", 2, FALSE, TRUE),
385 IA64_HOWTO (R_IA64_GPREL32LSB, "GPREL32LSB", 2, FALSE, TRUE),
386 IA64_HOWTO (R_IA64_GPREL64MSB, "GPREL64MSB", 4, FALSE, TRUE),
387 IA64_HOWTO (R_IA64_GPREL64LSB, "GPREL64LSB", 4, FALSE, TRUE),
388
389 IA64_HOWTO (R_IA64_LTOFF22, "LTOFF22", 0, FALSE, TRUE),
390 IA64_HOWTO (R_IA64_LTOFF64I, "LTOFF64I", 0, FALSE, TRUE),
391
392 IA64_HOWTO (R_IA64_PLTOFF22, "PLTOFF22", 0, FALSE, TRUE),
393 IA64_HOWTO (R_IA64_PLTOFF64I, "PLTOFF64I", 0, FALSE, TRUE),
394 IA64_HOWTO (R_IA64_PLTOFF64MSB, "PLTOFF64MSB", 4, FALSE, TRUE),
395 IA64_HOWTO (R_IA64_PLTOFF64LSB, "PLTOFF64LSB", 4, FALSE, TRUE),
396
397 IA64_HOWTO (R_IA64_FPTR64I, "FPTR64I", 0, FALSE, TRUE),
398 IA64_HOWTO (R_IA64_FPTR32MSB, "FPTR32MSB", 2, FALSE, TRUE),
399 IA64_HOWTO (R_IA64_FPTR32LSB, "FPTR32LSB", 2, FALSE, TRUE),
400 IA64_HOWTO (R_IA64_FPTR64MSB, "FPTR64MSB", 4, FALSE, TRUE),
401 IA64_HOWTO (R_IA64_FPTR64LSB, "FPTR64LSB", 4, FALSE, TRUE),
402
403 IA64_HOWTO (R_IA64_PCREL60B, "PCREL60B", 0, TRUE, TRUE),
404 IA64_HOWTO (R_IA64_PCREL21B, "PCREL21B", 0, TRUE, TRUE),
405 IA64_HOWTO (R_IA64_PCREL21M, "PCREL21M", 0, TRUE, TRUE),
406 IA64_HOWTO (R_IA64_PCREL21F, "PCREL21F", 0, TRUE, TRUE),
407 IA64_HOWTO (R_IA64_PCREL32MSB, "PCREL32MSB", 2, TRUE, TRUE),
408 IA64_HOWTO (R_IA64_PCREL32LSB, "PCREL32LSB", 2, TRUE, TRUE),
409 IA64_HOWTO (R_IA64_PCREL64MSB, "PCREL64MSB", 4, TRUE, TRUE),
410 IA64_HOWTO (R_IA64_PCREL64LSB, "PCREL64LSB", 4, TRUE, TRUE),
411
412 IA64_HOWTO (R_IA64_LTOFF_FPTR22, "LTOFF_FPTR22", 0, FALSE, TRUE),
413 IA64_HOWTO (R_IA64_LTOFF_FPTR64I, "LTOFF_FPTR64I", 0, FALSE, TRUE),
414 IA64_HOWTO (R_IA64_LTOFF_FPTR32MSB, "LTOFF_FPTR32MSB", 2, FALSE, TRUE),
415 IA64_HOWTO (R_IA64_LTOFF_FPTR32LSB, "LTOFF_FPTR32LSB", 2, FALSE, TRUE),
416 IA64_HOWTO (R_IA64_LTOFF_FPTR64MSB, "LTOFF_FPTR64MSB", 4, FALSE, TRUE),
417 IA64_HOWTO (R_IA64_LTOFF_FPTR64LSB, "LTOFF_FPTR64LSB", 4, FALSE, TRUE),
418
419 IA64_HOWTO (R_IA64_SEGREL32MSB, "SEGREL32MSB", 2, FALSE, TRUE),
420 IA64_HOWTO (R_IA64_SEGREL32LSB, "SEGREL32LSB", 2, FALSE, TRUE),
421 IA64_HOWTO (R_IA64_SEGREL64MSB, "SEGREL64MSB", 4, FALSE, TRUE),
422 IA64_HOWTO (R_IA64_SEGREL64LSB, "SEGREL64LSB", 4, FALSE, TRUE),
423
424 IA64_HOWTO (R_IA64_SECREL32MSB, "SECREL32MSB", 2, FALSE, TRUE),
425 IA64_HOWTO (R_IA64_SECREL32LSB, "SECREL32LSB", 2, FALSE, TRUE),
426 IA64_HOWTO (R_IA64_SECREL64MSB, "SECREL64MSB", 4, FALSE, TRUE),
427 IA64_HOWTO (R_IA64_SECREL64LSB, "SECREL64LSB", 4, FALSE, TRUE),
428
429 IA64_HOWTO (R_IA64_REL32MSB, "REL32MSB", 2, FALSE, TRUE),
430 IA64_HOWTO (R_IA64_REL32LSB, "REL32LSB", 2, FALSE, TRUE),
431 IA64_HOWTO (R_IA64_REL64MSB, "REL64MSB", 4, FALSE, TRUE),
432 IA64_HOWTO (R_IA64_REL64LSB, "REL64LSB", 4, FALSE, TRUE),
433
434 IA64_HOWTO (R_IA64_LTV32MSB, "LTV32MSB", 2, FALSE, TRUE),
435 IA64_HOWTO (R_IA64_LTV32LSB, "LTV32LSB", 2, FALSE, TRUE),
436 IA64_HOWTO (R_IA64_LTV64MSB, "LTV64MSB", 4, FALSE, TRUE),
437 IA64_HOWTO (R_IA64_LTV64LSB, "LTV64LSB", 4, FALSE, TRUE),
438
439 IA64_HOWTO (R_IA64_PCREL21BI, "PCREL21BI", 0, TRUE, TRUE),
440 IA64_HOWTO (R_IA64_PCREL22, "PCREL22", 0, TRUE, TRUE),
441 IA64_HOWTO (R_IA64_PCREL64I, "PCREL64I", 0, TRUE, TRUE),
442
443 IA64_HOWTO (R_IA64_IPLTMSB, "IPLTMSB", 4, FALSE, TRUE),
444 IA64_HOWTO (R_IA64_IPLTLSB, "IPLTLSB", 4, FALSE, TRUE),
445 IA64_HOWTO (R_IA64_COPY, "COPY", 4, FALSE, TRUE),
446 IA64_HOWTO (R_IA64_LTOFF22X, "LTOFF22X", 0, FALSE, TRUE),
447 IA64_HOWTO (R_IA64_LDXMOV, "LDXMOV", 0, FALSE, TRUE),
448
449 IA64_HOWTO (R_IA64_TPREL14, "TPREL14", 0, FALSE, FALSE),
450 IA64_HOWTO (R_IA64_TPREL22, "TPREL22", 0, FALSE, FALSE),
451 IA64_HOWTO (R_IA64_TPREL64I, "TPREL64I", 0, FALSE, FALSE),
452 IA64_HOWTO (R_IA64_TPREL64MSB, "TPREL64MSB", 8, FALSE, FALSE),
453 IA64_HOWTO (R_IA64_TPREL64LSB, "TPREL64LSB", 8, FALSE, FALSE),
454 IA64_HOWTO (R_IA64_LTOFF_TPREL22, "LTOFF_TPREL22", 0, FALSE, FALSE),
455
456 IA64_HOWTO (R_IA64_DTPMOD64MSB, "TPREL64MSB", 8, FALSE, FALSE),
457 IA64_HOWTO (R_IA64_DTPMOD64LSB, "TPREL64LSB", 8, FALSE, FALSE),
458 IA64_HOWTO (R_IA64_LTOFF_DTPMOD22, "LTOFF_DTPMOD22", 0, FALSE, FALSE),
459
460 IA64_HOWTO (R_IA64_DTPREL14, "DTPREL14", 0, FALSE, FALSE),
461 IA64_HOWTO (R_IA64_DTPREL22, "DTPREL22", 0, FALSE, FALSE),
462 IA64_HOWTO (R_IA64_DTPREL64I, "DTPREL64I", 0, FALSE, FALSE),
463 IA64_HOWTO (R_IA64_DTPREL32MSB, "DTPREL32MSB", 4, FALSE, FALSE),
464 IA64_HOWTO (R_IA64_DTPREL32LSB, "DTPREL32LSB", 4, FALSE, FALSE),
465 IA64_HOWTO (R_IA64_DTPREL64MSB, "DTPREL64MSB", 8, FALSE, FALSE),
466 IA64_HOWTO (R_IA64_DTPREL64LSB, "DTPREL64LSB", 8, FALSE, FALSE),
467 IA64_HOWTO (R_IA64_LTOFF_DTPREL22, "LTOFF_DTPREL22", 0, FALSE, FALSE),
800eeca4
JW
468 };
469
470static unsigned char elf_code_to_howto_index[R_IA64_MAX_RELOC_CODE + 1];
471
472/* Given a BFD reloc type, return the matching HOWTO structure. */
473
5e8d7549 474static reloc_howto_type *
800eeca4
JW
475lookup_howto (rtype)
476 unsigned int rtype;
477{
478 static int inited = 0;
479 int i;
480
481 if (!inited)
482 {
483 inited = 1;
484
485 memset (elf_code_to_howto_index, 0xff, sizeof (elf_code_to_howto_index));
486 for (i = 0; i < NELEMS (ia64_howto_table); ++i)
487 elf_code_to_howto_index[ia64_howto_table[i].type] = i;
488 }
489
490 BFD_ASSERT (rtype <= R_IA64_MAX_RELOC_CODE);
491 i = elf_code_to_howto_index[rtype];
492 if (i >= NELEMS (ia64_howto_table))
493 return 0;
494 return ia64_howto_table + i;
495}
496
497static reloc_howto_type*
bbe66d08 498elfNN_ia64_reloc_type_lookup (abfd, bfd_code)
64bf6ae6 499 bfd *abfd ATTRIBUTE_UNUSED;
800eeca4
JW
500 bfd_reloc_code_real_type bfd_code;
501{
502 unsigned int rtype;
503
504 switch (bfd_code)
505 {
506 case BFD_RELOC_NONE: rtype = R_IA64_NONE; break;
507
508 case BFD_RELOC_IA64_IMM14: rtype = R_IA64_IMM14; break;
509 case BFD_RELOC_IA64_IMM22: rtype = R_IA64_IMM22; break;
510 case BFD_RELOC_IA64_IMM64: rtype = R_IA64_IMM64; break;
511
512 case BFD_RELOC_IA64_DIR32MSB: rtype = R_IA64_DIR32MSB; break;
513 case BFD_RELOC_IA64_DIR32LSB: rtype = R_IA64_DIR32LSB; break;
514 case BFD_RELOC_IA64_DIR64MSB: rtype = R_IA64_DIR64MSB; break;
515 case BFD_RELOC_IA64_DIR64LSB: rtype = R_IA64_DIR64LSB; break;
516
517 case BFD_RELOC_IA64_GPREL22: rtype = R_IA64_GPREL22; break;
518 case BFD_RELOC_IA64_GPREL64I: rtype = R_IA64_GPREL64I; break;
519 case BFD_RELOC_IA64_GPREL32MSB: rtype = R_IA64_GPREL32MSB; break;
520 case BFD_RELOC_IA64_GPREL32LSB: rtype = R_IA64_GPREL32LSB; break;
521 case BFD_RELOC_IA64_GPREL64MSB: rtype = R_IA64_GPREL64MSB; break;
522 case BFD_RELOC_IA64_GPREL64LSB: rtype = R_IA64_GPREL64LSB; break;
523
524 case BFD_RELOC_IA64_LTOFF22: rtype = R_IA64_LTOFF22; break;
525 case BFD_RELOC_IA64_LTOFF64I: rtype = R_IA64_LTOFF64I; break;
526
527 case BFD_RELOC_IA64_PLTOFF22: rtype = R_IA64_PLTOFF22; break;
528 case BFD_RELOC_IA64_PLTOFF64I: rtype = R_IA64_PLTOFF64I; break;
529 case BFD_RELOC_IA64_PLTOFF64MSB: rtype = R_IA64_PLTOFF64MSB; break;
530 case BFD_RELOC_IA64_PLTOFF64LSB: rtype = R_IA64_PLTOFF64LSB; break;
531 case BFD_RELOC_IA64_FPTR64I: rtype = R_IA64_FPTR64I; break;
532 case BFD_RELOC_IA64_FPTR32MSB: rtype = R_IA64_FPTR32MSB; break;
533 case BFD_RELOC_IA64_FPTR32LSB: rtype = R_IA64_FPTR32LSB; break;
534 case BFD_RELOC_IA64_FPTR64MSB: rtype = R_IA64_FPTR64MSB; break;
535 case BFD_RELOC_IA64_FPTR64LSB: rtype = R_IA64_FPTR64LSB; break;
536
537 case BFD_RELOC_IA64_PCREL21B: rtype = R_IA64_PCREL21B; break;
748abff6 538 case BFD_RELOC_IA64_PCREL21BI: rtype = R_IA64_PCREL21BI; break;
800eeca4
JW
539 case BFD_RELOC_IA64_PCREL21M: rtype = R_IA64_PCREL21M; break;
540 case BFD_RELOC_IA64_PCREL21F: rtype = R_IA64_PCREL21F; break;
748abff6
RH
541 case BFD_RELOC_IA64_PCREL22: rtype = R_IA64_PCREL22; break;
542 case BFD_RELOC_IA64_PCREL60B: rtype = R_IA64_PCREL60B; break;
543 case BFD_RELOC_IA64_PCREL64I: rtype = R_IA64_PCREL64I; break;
800eeca4
JW
544 case BFD_RELOC_IA64_PCREL32MSB: rtype = R_IA64_PCREL32MSB; break;
545 case BFD_RELOC_IA64_PCREL32LSB: rtype = R_IA64_PCREL32LSB; break;
546 case BFD_RELOC_IA64_PCREL64MSB: rtype = R_IA64_PCREL64MSB; break;
547 case BFD_RELOC_IA64_PCREL64LSB: rtype = R_IA64_PCREL64LSB; break;
548
549 case BFD_RELOC_IA64_LTOFF_FPTR22: rtype = R_IA64_LTOFF_FPTR22; break;
550 case BFD_RELOC_IA64_LTOFF_FPTR64I: rtype = R_IA64_LTOFF_FPTR64I; break;
a4bd8390
JW
551 case BFD_RELOC_IA64_LTOFF_FPTR32MSB: rtype = R_IA64_LTOFF_FPTR32MSB; break;
552 case BFD_RELOC_IA64_LTOFF_FPTR32LSB: rtype = R_IA64_LTOFF_FPTR32LSB; break;
800eeca4
JW
553 case BFD_RELOC_IA64_LTOFF_FPTR64MSB: rtype = R_IA64_LTOFF_FPTR64MSB; break;
554 case BFD_RELOC_IA64_LTOFF_FPTR64LSB: rtype = R_IA64_LTOFF_FPTR64LSB; break;
555
800eeca4
JW
556 case BFD_RELOC_IA64_SEGREL32MSB: rtype = R_IA64_SEGREL32MSB; break;
557 case BFD_RELOC_IA64_SEGREL32LSB: rtype = R_IA64_SEGREL32LSB; break;
558 case BFD_RELOC_IA64_SEGREL64MSB: rtype = R_IA64_SEGREL64MSB; break;
559 case BFD_RELOC_IA64_SEGREL64LSB: rtype = R_IA64_SEGREL64LSB; break;
560
561 case BFD_RELOC_IA64_SECREL32MSB: rtype = R_IA64_SECREL32MSB; break;
562 case BFD_RELOC_IA64_SECREL32LSB: rtype = R_IA64_SECREL32LSB; break;
563 case BFD_RELOC_IA64_SECREL64MSB: rtype = R_IA64_SECREL64MSB; break;
564 case BFD_RELOC_IA64_SECREL64LSB: rtype = R_IA64_SECREL64LSB; break;
565
566 case BFD_RELOC_IA64_REL32MSB: rtype = R_IA64_REL32MSB; break;
567 case BFD_RELOC_IA64_REL32LSB: rtype = R_IA64_REL32LSB; break;
568 case BFD_RELOC_IA64_REL64MSB: rtype = R_IA64_REL64MSB; break;
569 case BFD_RELOC_IA64_REL64LSB: rtype = R_IA64_REL64LSB; break;
570
571 case BFD_RELOC_IA64_LTV32MSB: rtype = R_IA64_LTV32MSB; break;
572 case BFD_RELOC_IA64_LTV32LSB: rtype = R_IA64_LTV32LSB; break;
573 case BFD_RELOC_IA64_LTV64MSB: rtype = R_IA64_LTV64MSB; break;
574 case BFD_RELOC_IA64_LTV64LSB: rtype = R_IA64_LTV64LSB; break;
575
576 case BFD_RELOC_IA64_IPLTMSB: rtype = R_IA64_IPLTMSB; break;
577 case BFD_RELOC_IA64_IPLTLSB: rtype = R_IA64_IPLTLSB; break;
800eeca4
JW
578 case BFD_RELOC_IA64_COPY: rtype = R_IA64_COPY; break;
579 case BFD_RELOC_IA64_LTOFF22X: rtype = R_IA64_LTOFF22X; break;
580 case BFD_RELOC_IA64_LDXMOV: rtype = R_IA64_LDXMOV; break;
581
13ae64f3 582 case BFD_RELOC_IA64_TPREL14: rtype = R_IA64_TPREL14; break;
800eeca4 583 case BFD_RELOC_IA64_TPREL22: rtype = R_IA64_TPREL22; break;
13ae64f3 584 case BFD_RELOC_IA64_TPREL64I: rtype = R_IA64_TPREL64I; break;
800eeca4
JW
585 case BFD_RELOC_IA64_TPREL64MSB: rtype = R_IA64_TPREL64MSB; break;
586 case BFD_RELOC_IA64_TPREL64LSB: rtype = R_IA64_TPREL64LSB; break;
13ae64f3
JJ
587 case BFD_RELOC_IA64_LTOFF_TPREL22: rtype = R_IA64_LTOFF_TPREL22; break;
588
589 case BFD_RELOC_IA64_DTPMOD64MSB: rtype = R_IA64_DTPMOD64MSB; break;
590 case BFD_RELOC_IA64_DTPMOD64LSB: rtype = R_IA64_DTPMOD64LSB; break;
591 case BFD_RELOC_IA64_LTOFF_DTPMOD22: rtype = R_IA64_LTOFF_DTPMOD22; break;
592
593 case BFD_RELOC_IA64_DTPREL14: rtype = R_IA64_DTPREL14; break;
594 case BFD_RELOC_IA64_DTPREL22: rtype = R_IA64_DTPREL22; break;
595 case BFD_RELOC_IA64_DTPREL64I: rtype = R_IA64_DTPREL64I; break;
596 case BFD_RELOC_IA64_DTPREL32MSB: rtype = R_IA64_DTPREL32MSB; break;
597 case BFD_RELOC_IA64_DTPREL32LSB: rtype = R_IA64_DTPREL32LSB; break;
598 case BFD_RELOC_IA64_DTPREL64MSB: rtype = R_IA64_DTPREL64MSB; break;
599 case BFD_RELOC_IA64_DTPREL64LSB: rtype = R_IA64_DTPREL64LSB; break;
600 case BFD_RELOC_IA64_LTOFF_DTPREL22: rtype = R_IA64_LTOFF_DTPREL22; break;
800eeca4
JW
601
602 default: return 0;
603 }
604 return lookup_howto (rtype);
605}
606
607/* Given a ELF reloc, return the matching HOWTO structure. */
608
609static void
bbe66d08 610elfNN_ia64_info_to_howto (abfd, bfd_reloc, elf_reloc)
64bf6ae6 611 bfd *abfd ATTRIBUTE_UNUSED;
800eeca4 612 arelent *bfd_reloc;
947216bf 613 Elf_Internal_Rela *elf_reloc;
800eeca4 614{
dc810e39
AM
615 bfd_reloc->howto
616 = lookup_howto ((unsigned int) ELFNN_R_TYPE (elf_reloc->r_info));
800eeca4
JW
617}
618\f
619#define PLT_HEADER_SIZE (3 * 16)
620#define PLT_MIN_ENTRY_SIZE (1 * 16)
621#define PLT_FULL_ENTRY_SIZE (2 * 16)
622#define PLT_RESERVED_WORDS 3
623
624static const bfd_byte plt_header[PLT_HEADER_SIZE] =
625{
626 0x0b, 0x10, 0x00, 0x1c, 0x00, 0x21, /* [MMI] mov r2=r14;; */
627 0xe0, 0x00, 0x08, 0x00, 0x48, 0x00, /* addl r14=0,r2 */
628 0x00, 0x00, 0x04, 0x00, /* nop.i 0x0;; */
629 0x0b, 0x80, 0x20, 0x1c, 0x18, 0x14, /* [MMI] ld8 r16=[r14],8;; */
630 0x10, 0x41, 0x38, 0x30, 0x28, 0x00, /* ld8 r17=[r14],8 */
631 0x00, 0x00, 0x04, 0x00, /* nop.i 0x0;; */
632 0x11, 0x08, 0x00, 0x1c, 0x18, 0x10, /* [MIB] ld8 r1=[r14] */
633 0x60, 0x88, 0x04, 0x80, 0x03, 0x00, /* mov b6=r17 */
634 0x60, 0x00, 0x80, 0x00 /* br.few b6;; */
635};
636
637static const bfd_byte plt_min_entry[PLT_MIN_ENTRY_SIZE] =
638{
639 0x11, 0x78, 0x00, 0x00, 0x00, 0x24, /* [MIB] mov r15=0 */
640 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, /* nop.i 0x0 */
641 0x00, 0x00, 0x00, 0x40 /* br.few 0 <PLT0>;; */
642};
643
644static const bfd_byte plt_full_entry[PLT_FULL_ENTRY_SIZE] =
645{
646 0x0b, 0x78, 0x00, 0x02, 0x00, 0x24, /* [MMI] addl r15=0,r1;; */
647 0x00, 0x41, 0x3c, 0x30, 0x28, 0xc0, /* ld8 r16=[r15],8 */
648 0x01, 0x08, 0x00, 0x84, /* mov r14=r1;; */
649 0x11, 0x08, 0x00, 0x1e, 0x18, 0x10, /* [MIB] ld8 r1=[r15] */
650 0x60, 0x80, 0x04, 0x80, 0x03, 0x00, /* mov b6=r16 */
651 0x60, 0x00, 0x80, 0x00 /* br.few b6;; */
652};
653
654#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"
7b6dab7f
TW
655#define AIX_DYNAMIC_INTERPRETER "/usr/lib/ia64l64/libc.so.1"
656#define DYNAMIC_INTERPRETER(abfd) \
657 (elfNN_ia64_aix_vec (abfd->xvec) ? AIX_DYNAMIC_INTERPRETER : ELF_DYNAMIC_INTERPRETER)
748abff6 658
748abff6
RH
659static const bfd_byte oor_brl[16] =
660{
661 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MLX] nop.m 0 */
662 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* brl.sptk.few tgt;; */
663 0x00, 0x00, 0x00, 0xc0
664};
748abff6 665\f
2c4c2bc0 666/* These functions do relaxation for IA-64 ELF. */
748abff6 667
b34976b6 668static bfd_boolean
bbe66d08 669elfNN_ia64_relax_section (abfd, sec, link_info, again)
748abff6
RH
670 bfd *abfd;
671 asection *sec;
672 struct bfd_link_info *link_info;
b34976b6 673 bfd_boolean *again;
748abff6
RH
674{
675 struct one_fixup
676 {
677 struct one_fixup *next;
678 asection *tsec;
679 bfd_vma toff;
680 bfd_vma trampoff;
681 };
682
683 Elf_Internal_Shdr *symtab_hdr;
684 Elf_Internal_Rela *internal_relocs;
748abff6
RH
685 Elf_Internal_Rela *irel, *irelend;
686 bfd_byte *contents;
6cdc0ccc 687 Elf_Internal_Sym *isymbuf = NULL;
bbe66d08 688 struct elfNN_ia64_link_hash_table *ia64_info;
748abff6 689 struct one_fixup *fixups = NULL;
b34976b6
AM
690 bfd_boolean changed_contents = FALSE;
691 bfd_boolean changed_relocs = FALSE;
2c4c2bc0
RH
692 bfd_boolean changed_got = FALSE;
693 bfd_vma gp = 0;
748abff6 694
46f5aac8
KH
695 /* Assume we're not going to change any sizes, and we'll only need
696 one pass. */
b34976b6 697 *again = FALSE;
748abff6 698
04b3329b
L
699 /* Don't even try to relax for non-ELF outputs. */
700 if (link_info->hash->creator->flavour != bfd_target_elf_flavour)
701 return FALSE;
702
748abff6
RH
703 /* Nothing to do if there are no relocations. */
704 if ((sec->flags & SEC_RELOC) == 0
705 || sec->reloc_count == 0)
b34976b6 706 return TRUE;
748abff6
RH
707
708 /* If this is the first time we have been called for this section,
709 initialize the cooked size. */
710 if (sec->_cooked_size == 0)
711 sec->_cooked_size = sec->_raw_size;
712
713 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
714
715 /* Load the relocations for this section. */
bbe66d08 716 internal_relocs = (_bfd_elfNN_link_read_relocs
748abff6
RH
717 (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
718 link_info->keep_memory));
719 if (internal_relocs == NULL)
b34976b6 720 return FALSE;
748abff6 721
bbe66d08 722 ia64_info = elfNN_ia64_hash_table (link_info);
748abff6
RH
723 irelend = internal_relocs + sec->reloc_count;
724
748abff6 725 /* Get the section contents. */
748abff6
RH
726 if (elf_section_data (sec)->this_hdr.contents != NULL)
727 contents = elf_section_data (sec)->this_hdr.contents;
728 else
729 {
730 contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
731 if (contents == NULL)
732 goto error_return;
748abff6
RH
733
734 if (! bfd_get_section_contents (abfd, sec, contents,
735 (file_ptr) 0, sec->_raw_size))
736 goto error_return;
737 }
738
2c4c2bc0 739 for (irel = internal_relocs; irel < irelend; irel++)
748abff6 740 {
2f9bd3f6 741 unsigned long r_type = ELFNN_R_TYPE (irel->r_info);
748abff6 742 bfd_vma symaddr, reladdr, trampoff, toff, roff;
748abff6
RH
743 asection *tsec;
744 struct one_fixup *f;
dc810e39 745 bfd_size_type amt;
2c4c2bc0
RH
746 bfd_boolean is_branch;
747 struct elfNN_ia64_dyn_sym_info *dyn_i;
748abff6 748
2c4c2bc0
RH
749 switch (r_type)
750 {
751 case R_IA64_PCREL21B:
752 case R_IA64_PCREL21BI:
753 case R_IA64_PCREL21M:
754 case R_IA64_PCREL21F:
755 is_branch = TRUE;
756 break;
757
758 case R_IA64_LTOFF22X:
759 case R_IA64_LDXMOV:
760 is_branch = FALSE;
761 break;
762
763 default:
764 continue;
765 }
748abff6
RH
766
767 /* Get the value of the symbol referred to by the reloc. */
bbe66d08 768 if (ELFNN_R_SYM (irel->r_info) < symtab_hdr->sh_info)
748abff6
RH
769 {
770 /* A local symbol. */
6cdc0ccc
AM
771 Elf_Internal_Sym *isym;
772
773 /* Read this BFD's local symbols. */
774 if (isymbuf == NULL)
775 {
776 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
777 if (isymbuf == NULL)
778 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
779 symtab_hdr->sh_info, 0,
780 NULL, NULL, NULL);
781 if (isymbuf == 0)
782 goto error_return;
783 }
784
785 isym = isymbuf + ELF64_R_SYM (irel->r_info);
786 if (isym->st_shndx == SHN_UNDEF)
748abff6 787 continue; /* We can't do anthing with undefined symbols. */
6cdc0ccc 788 else if (isym->st_shndx == SHN_ABS)
748abff6 789 tsec = bfd_abs_section_ptr;
6cdc0ccc 790 else if (isym->st_shndx == SHN_COMMON)
748abff6 791 tsec = bfd_com_section_ptr;
6cdc0ccc 792 else if (isym->st_shndx == SHN_IA_64_ANSI_COMMON)
d9cf1b54 793 tsec = bfd_com_section_ptr;
3e932841 794 else
6cdc0ccc 795 tsec = bfd_section_from_elf_index (abfd, isym->st_shndx);
748abff6 796
6cdc0ccc 797 toff = isym->st_value;
2c4c2bc0 798 dyn_i = get_dyn_sym_info (ia64_info, NULL, abfd, irel, FALSE);
748abff6
RH
799 }
800 else
801 {
802 unsigned long indx;
803 struct elf_link_hash_entry *h;
748abff6 804
bbe66d08 805 indx = ELFNN_R_SYM (irel->r_info) - symtab_hdr->sh_info;
748abff6
RH
806 h = elf_sym_hashes (abfd)[indx];
807 BFD_ASSERT (h != NULL);
808
809 while (h->root.type == bfd_link_hash_indirect
810 || h->root.type == bfd_link_hash_warning)
811 h = (struct elf_link_hash_entry *) h->root.u.i.link;
812
b34976b6 813 dyn_i = get_dyn_sym_info (ia64_info, h, abfd, irel, FALSE);
748abff6
RH
814
815 /* For branches to dynamic symbols, we're interested instead
816 in a branch to the PLT entry. */
2c4c2bc0 817 if (is_branch && dyn_i && dyn_i->want_plt2)
748abff6 818 {
2f9bd3f6
RH
819 /* Internal branches shouldn't be sent to the PLT.
820 Leave this for now and we'll give an error later. */
821 if (r_type != R_IA64_PCREL21B)
822 continue;
823
748abff6
RH
824 tsec = ia64_info->plt_sec;
825 toff = dyn_i->plt2_offset;
3fa1d917 826 BFD_ASSERT (irel->r_addend == 0);
748abff6 827 }
2c4c2bc0
RH
828
829 /* Can't do anything else with dynamic symbols. */
830 else if (elfNN_ia64_dynamic_symbol_p (h, link_info))
831 continue;
832
748abff6
RH
833 else
834 {
835 /* We can't do anthing with undefined symbols. */
836 if (h->root.type == bfd_link_hash_undefined
837 || h->root.type == bfd_link_hash_undefweak)
838 continue;
839
840 tsec = h->root.u.def.section;
841 toff = h->root.u.def.value;
842 }
843 }
844
3fa1d917
JJ
845 if (tsec->sec_info_type == ELF_INFO_TYPE_MERGE)
846 toff = _bfd_merged_section_offset (abfd, &tsec,
847 elf_section_data (tsec)->sec_info,
848 toff + irel->r_addend,
849 (bfd_vma) 0);
850 else
851 toff += irel->r_addend;
852
853 symaddr = tsec->output_section->vma + tsec->output_offset + toff;
748abff6
RH
854
855 roff = irel->r_offset;
748abff6 856
2c4c2bc0
RH
857 if (is_branch)
858 {
859 reladdr = (sec->output_section->vma
860 + sec->output_offset
861 + roff) & (bfd_vma) -4;
748abff6 862
2c4c2bc0
RH
863 /* If the branch is in range, no need to do anything. */
864 if ((bfd_signed_vma) (symaddr - reladdr) >= -0x1000000
865 && (bfd_signed_vma) (symaddr - reladdr) <= 0x0FFFFF0)
866 continue;
748abff6 867
2c4c2bc0
RH
868 /* If the branch and target are in the same section, you've
869 got one honking big section and we can't help you. You'll
870 get an error message later. */
871 if (tsec == sec)
872 continue;
748abff6 873
2c4c2bc0
RH
874 /* Look for an existing fixup to this address. */
875 for (f = fixups; f ; f = f->next)
876 if (f->tsec == tsec && f->toff == toff)
877 break;
748abff6 878
2c4c2bc0 879 if (f == NULL)
748abff6 880 {
2c4c2bc0
RH
881 /* Two alternatives: If it's a branch to a PLT entry, we can
882 make a copy of the FULL_PLT entry. Otherwise, we'll have
883 to use a `brl' insn to get where we're going. */
884
885 size_t size;
886
887 if (tsec == ia64_info->plt_sec)
888 size = sizeof (plt_full_entry);
889 else
890 {
2c4c2bc0 891 size = sizeof (oor_brl);
2c4c2bc0 892 }
748abff6 893
2c4c2bc0
RH
894 /* Resize the current section to make room for the new branch. */
895 trampoff = (sec->_cooked_size + 15) & (bfd_vma) -16;
896 amt = trampoff + size;
897 contents = (bfd_byte *) bfd_realloc (contents, amt);
898 if (contents == NULL)
899 goto error_return;
900 sec->_cooked_size = amt;
748abff6 901
2c4c2bc0
RH
902 if (tsec == ia64_info->plt_sec)
903 {
904 memcpy (contents + trampoff, plt_full_entry, size);
748abff6 905
2c4c2bc0
RH
906 /* Hijack the old relocation for use as the PLTOFF reloc. */
907 irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info),
908 R_IA64_PLTOFF22);
909 irel->r_offset = trampoff;
910 }
911 else
912 {
2c4c2bc0
RH
913 memcpy (contents + trampoff, oor_brl, size);
914 irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info),
915 R_IA64_PCREL60B);
916 irel->r_offset = trampoff + 2;
2c4c2bc0
RH
917 }
918
919 /* Record the fixup so we don't do it again this section. */
920 f = (struct one_fixup *)
921 bfd_malloc ((bfd_size_type) sizeof (*f));
922 f->next = fixups;
923 f->tsec = tsec;
924 f->toff = toff;
925 f->trampoff = trampoff;
926 fixups = f;
748abff6 927 }
2c4c2bc0
RH
928 else
929 {
930 /* Nop out the reloc, since we're finalizing things here. */
931 irel->r_info = ELFNN_R_INFO (0, R_IA64_NONE);
932 }
933
934 /* Fix up the existing branch to hit the trampoline. Hope like
935 hell this doesn't overflow too. */
936 if (elfNN_ia64_install_value (abfd, contents + roff,
937 f->trampoff - (roff & (bfd_vma) -4),
938 r_type) != bfd_reloc_ok)
939 goto error_return;
748abff6 940
2c4c2bc0
RH
941 changed_contents = TRUE;
942 changed_relocs = TRUE;
748abff6
RH
943 }
944 else
945 {
2c4c2bc0
RH
946 /* Fetch the gp. */
947 if (gp == 0)
948 {
949 bfd *obfd = sec->output_section->owner;
950 gp = _bfd_get_gp_value (obfd);
951 if (gp == 0)
952 {
953 if (!elfNN_ia64_choose_gp (obfd, link_info))
954 goto error_return;
955 gp = _bfd_get_gp_value (obfd);
956 }
957 }
748abff6 958
2c4c2bc0 959 /* If the data is out of range, do nothing. */
484a4f9c
RH
960 if ((bfd_signed_vma) (symaddr - gp) >= 0x200000
961 ||(bfd_signed_vma) (symaddr - gp) < -0x200000)
2c4c2bc0 962 continue;
748abff6 963
2c4c2bc0
RH
964 if (r_type == R_IA64_LTOFF22X)
965 {
966 irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info),
967 R_IA64_GPREL22);
968 changed_relocs = TRUE;
969 if (dyn_i->want_gotx)
970 {
971 dyn_i->want_gotx = 0;
972 changed_got |= !dyn_i->want_got;
973 }
974 }
975 else
976 {
977 elfNN_ia64_relax_ldxmov (abfd, contents, roff);
978 irel->r_info = ELFNN_R_INFO (0, R_IA64_NONE);
979 changed_contents = TRUE;
980 changed_relocs = TRUE;
981 }
982 }
748abff6
RH
983 }
984
2c4c2bc0
RH
985 /* ??? If we created fixups, this may push the code segment large
986 enough that the data segment moves, which will change the GP.
987 Reset the GP so that we re-calculate next round. We need to
988 do this at the _beginning_ of the next round; now will not do. */
989
748abff6
RH
990 /* Clean up and go home. */
991 while (fixups)
992 {
993 struct one_fixup *f = fixups;
994 fixups = fixups->next;
995 free (f);
996 }
997
6cdc0ccc
AM
998 if (isymbuf != NULL
999 && symtab_hdr->contents != (unsigned char *) isymbuf)
748abff6
RH
1000 {
1001 if (! link_info->keep_memory)
6cdc0ccc 1002 free (isymbuf);
748abff6
RH
1003 else
1004 {
6cdc0ccc
AM
1005 /* Cache the symbols for elf_link_input_bfd. */
1006 symtab_hdr->contents = (unsigned char *) isymbuf;
748abff6
RH
1007 }
1008 }
1009
6cdc0ccc
AM
1010 if (contents != NULL
1011 && elf_section_data (sec)->this_hdr.contents != contents)
748abff6 1012 {
6cdc0ccc
AM
1013 if (!changed_contents && !link_info->keep_memory)
1014 free (contents);
748abff6
RH
1015 else
1016 {
6cdc0ccc
AM
1017 /* Cache the section contents for elf_link_input_bfd. */
1018 elf_section_data (sec)->this_hdr.contents = contents;
748abff6
RH
1019 }
1020 }
1021
6cdc0ccc
AM
1022 if (elf_section_data (sec)->relocs != internal_relocs)
1023 {
1024 if (!changed_relocs)
1025 free (internal_relocs);
1026 else
1027 elf_section_data (sec)->relocs = internal_relocs;
1028 }
1029
2c4c2bc0
RH
1030 if (changed_got)
1031 {
1032 struct elfNN_ia64_allocate_data data;
1033 data.info = link_info;
1034 data.ofs = 0;
9d73f260 1035 ia64_info->self_dtpmod_offset = (bfd_vma) -1;
2c4c2bc0
RH
1036
1037 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_data_got, &data);
1038 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_fptr_got, &data);
1039 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_local_got, &data);
1040 ia64_info->got_sec->_raw_size = data.ofs;
1041 ia64_info->got_sec->_cooked_size = data.ofs;
1042
1043 /* ??? Resize .rela.got too. */
1044 }
1045
748abff6 1046 *again = changed_contents || changed_relocs;
b34976b6 1047 return TRUE;
748abff6
RH
1048
1049 error_return:
6cdc0ccc
AM
1050 if (isymbuf != NULL && (unsigned char *) isymbuf != symtab_hdr->contents)
1051 free (isymbuf);
1052 if (contents != NULL
1053 && elf_section_data (sec)->this_hdr.contents != contents)
1054 free (contents);
1055 if (internal_relocs != NULL
1056 && elf_section_data (sec)->relocs != internal_relocs)
1057 free (internal_relocs);
b34976b6 1058 return FALSE;
748abff6 1059}
2c4c2bc0
RH
1060
1061static void
1062elfNN_ia64_relax_ldxmov (abfd, contents, off)
1063 bfd *abfd;
1064 bfd_byte *contents;
1065 bfd_vma off;
1066{
1067 int shift, r1, r3;
1068 bfd_vma dword, insn;
1069
1070 switch ((int)off & 0x3)
1071 {
1072 case 0: shift = 5; break;
1073 case 1: shift = 14; off += 3; break;
1074 case 2: shift = 23; off += 6; break;
1075 case 3:
1076 abort ();
1077 }
1078
1079 dword = bfd_get_64 (abfd, contents + off);
1080 insn = (dword >> shift) & 0x1ffffffffffLL;
1081
1082 r1 = (insn >> 6) & 127;
1083 r3 = (insn >> 20) & 127;
1084 if (r1 == r3)
1085 insn = 0x8000000; /* nop */
1086 else
1087 insn = (insn & 0x7f01fff) | 0x10800000000LL; /* (qp) mov r1 = r3 */
1088
1089 dword &= ~(0x1ffffffffffLL << shift);
1090 dword |= (insn << shift);
1091 bfd_put_64 (abfd, dword, contents + off);
1092}
800eeca4 1093\f
b34976b6 1094/* Return TRUE if NAME is an unwind table section name. */
81545d45 1095
b34976b6 1096static inline bfd_boolean
d9cf1b54
AM
1097is_unwind_section_name (abfd, name)
1098 bfd *abfd;
81545d45
RH
1099 const char *name;
1100{
579f31ac 1101 size_t len1, len2, len3;
81545d45 1102
d9cf1b54
AM
1103 if (elfNN_ia64_hpux_vec (abfd->xvec)
1104 && !strcmp (name, ELF_STRING_ia64_unwind_hdr))
b34976b6 1105 return FALSE;
d9cf1b54 1106
81545d45
RH
1107 len1 = sizeof (ELF_STRING_ia64_unwind) - 1;
1108 len2 = sizeof (ELF_STRING_ia64_unwind_info) - 1;
579f31ac
JJ
1109 len3 = sizeof (ELF_STRING_ia64_unwind_once) - 1;
1110 return ((strncmp (name, ELF_STRING_ia64_unwind, len1) == 0
1111 && strncmp (name, ELF_STRING_ia64_unwind_info, len2) != 0)
1112 || strncmp (name, ELF_STRING_ia64_unwind_once, len3) == 0);
81545d45
RH
1113}
1114
800eeca4
JW
1115/* Handle an IA-64 specific section when reading an object file. This
1116 is called when elfcode.h finds a section with an unknown type. */
1117
b34976b6 1118static bfd_boolean
bbe66d08 1119elfNN_ia64_section_from_shdr (abfd, hdr, name)
800eeca4 1120 bfd *abfd;
947216bf 1121 Elf_Internal_Shdr *hdr;
90937f86 1122 const char *name;
800eeca4
JW
1123{
1124 asection *newsect;
1125
1126 /* There ought to be a place to keep ELF backend specific flags, but
1127 at the moment there isn't one. We just keep track of the
1128 sections by their name, instead. Fortunately, the ABI gives
1129 suggested names for all the MIPS specific sections, so we will
1130 probably get away with this. */
1131 switch (hdr->sh_type)
1132 {
1133 case SHT_IA_64_UNWIND:
d9cf1b54 1134 case SHT_IA_64_HP_OPT_ANOT:
800eeca4
JW
1135 break;
1136
1137 case SHT_IA_64_EXT:
1138 if (strcmp (name, ELF_STRING_ia64_archext) != 0)
b34976b6 1139 return FALSE;
800eeca4
JW
1140 break;
1141
1142 default:
b34976b6 1143 return FALSE;
800eeca4
JW
1144 }
1145
1146 if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
b34976b6 1147 return FALSE;
800eeca4
JW
1148 newsect = hdr->bfd_section;
1149
b34976b6 1150 return TRUE;
fa152c49
JW
1151}
1152
1153/* Convert IA-64 specific section flags to bfd internal section flags. */
1154
1155/* ??? There is no bfd internal flag equivalent to the SHF_IA_64_NORECOV
1156 flag. */
1157
b34976b6 1158static bfd_boolean
bbe66d08 1159elfNN_ia64_section_flags (flags, hdr)
fa152c49 1160 flagword *flags;
947216bf 1161 Elf_Internal_Shdr *hdr;
fa152c49 1162{
800eeca4 1163 if (hdr->sh_flags & SHF_IA_64_SHORT)
fa152c49 1164 *flags |= SEC_SMALL_DATA;
800eeca4 1165
b34976b6 1166 return TRUE;
800eeca4
JW
1167}
1168
1169/* Set the correct type for an IA-64 ELF section. We do this by the
1170 section name, which is a hack, but ought to work. */
1171
b34976b6 1172static bfd_boolean
bbe66d08 1173elfNN_ia64_fake_sections (abfd, hdr, sec)
64bf6ae6 1174 bfd *abfd ATTRIBUTE_UNUSED;
947216bf 1175 Elf_Internal_Shdr *hdr;
800eeca4
JW
1176 asection *sec;
1177{
1178 register const char *name;
1179
1180 name = bfd_get_section_name (abfd, sec);
1181
d9cf1b54 1182 if (is_unwind_section_name (abfd, name))
81545d45
RH
1183 {
1184 /* We don't have the sections numbered at this point, so sh_info
1185 is set later, in elfNN_ia64_final_write_processing. */
1186 hdr->sh_type = SHT_IA_64_UNWIND;
1187 hdr->sh_flags |= SHF_LINK_ORDER;
1188 }
800eeca4
JW
1189 else if (strcmp (name, ELF_STRING_ia64_archext) == 0)
1190 hdr->sh_type = SHT_IA_64_EXT;
d9cf1b54
AM
1191 else if (strcmp (name, ".HP.opt_annot") == 0)
1192 hdr->sh_type = SHT_IA_64_HP_OPT_ANOT;
800eeca4 1193 else if (strcmp (name, ".reloc") == 0)
5e8d7549
NC
1194 /* This is an ugly, but unfortunately necessary hack that is
1195 needed when producing EFI binaries on IA-64. It tells
1196 elf.c:elf_fake_sections() not to consider ".reloc" as a section
1197 containing ELF relocation info. We need this hack in order to
1198 be able to generate ELF binaries that can be translated into
1199 EFI applications (which are essentially COFF objects). Those
1200 files contain a COFF ".reloc" section inside an ELFNN object,
1201 which would normally cause BFD to segfault because it would
1202 attempt to interpret this section as containing relocation
1203 entries for section "oc". With this hack enabled, ".reloc"
1204 will be treated as a normal data section, which will avoid the
1205 segfault. However, you won't be able to create an ELFNN binary
1206 with a section named "oc" that needs relocations, but that's
1207 the kind of ugly side-effects you get when detecting section
1208 types based on their names... In practice, this limitation is
1209 unlikely to bite. */
800eeca4
JW
1210 hdr->sh_type = SHT_PROGBITS;
1211
1212 if (sec->flags & SEC_SMALL_DATA)
1213 hdr->sh_flags |= SHF_IA_64_SHORT;
1214
b34976b6 1215 return TRUE;
800eeca4
JW
1216}
1217
81545d45
RH
1218/* The final processing done just before writing out an IA-64 ELF
1219 object file. */
1220
1221static void
1222elfNN_ia64_final_write_processing (abfd, linker)
1223 bfd *abfd;
b34976b6 1224 bfd_boolean linker ATTRIBUTE_UNUSED;
81545d45
RH
1225{
1226 Elf_Internal_Shdr *hdr;
1227 const char *sname;
1228 asection *text_sect, *s;
1229 size_t len;
1230
1231 for (s = abfd->sections; s; s = s->next)
1232 {
1233 hdr = &elf_section_data (s)->this_hdr;
1234 switch (hdr->sh_type)
1235 {
1236 case SHT_IA_64_UNWIND:
1237 /* See comments in gas/config/tc-ia64.c:dot_endp on why we
1238 have to do this. */
1239 sname = bfd_get_section_name (abfd, s);
1240 len = sizeof (ELF_STRING_ia64_unwind) - 1;
1241 if (sname && strncmp (sname, ELF_STRING_ia64_unwind, len) == 0)
1242 {
1243 sname += len;
1244
1245 if (sname[0] == '\0')
1246 /* .IA_64.unwind -> .text */
1247 text_sect = bfd_get_section_by_name (abfd, ".text");
1248 else
1249 /* .IA_64.unwindFOO -> FOO */
1250 text_sect = bfd_get_section_by_name (abfd, sname);
1251 }
579f31ac
JJ
1252 else if (sname
1253 && (len = sizeof (ELF_STRING_ia64_unwind_once) - 1,
1254 strncmp (sname, ELF_STRING_ia64_unwind_once, len)) == 0)
1255 {
1256 /* .gnu.linkonce.ia64unw.FOO -> .gnu.linkonce.t.FOO */
1257 size_t len2 = sizeof (".gnu.linkonce.t.") - 1;
fcf12726 1258 char *once_name = bfd_malloc (len2 + strlen (sname + len) + 1);
579f31ac 1259
fcf12726
AM
1260 if (once_name != NULL)
1261 {
1262 memcpy (once_name, ".gnu.linkonce.t.", len2);
1263 strcpy (once_name + len2, sname + len);
1264 text_sect = bfd_get_section_by_name (abfd, once_name);
1265 free (once_name);
1266 }
1267 else
1268 /* Should only happen if we run out of memory, in
1269 which case we're probably toast anyway. Try to
1270 cope by finding the section the slow way. */
1271 for (text_sect = abfd->sections;
1272 text_sect != NULL;
1273 text_sect = text_sect->next)
1274 {
1275 if (strncmp (bfd_section_name (abfd, text_sect),
1276 ".gnu.linkonce.t.", len2) == 0
1277 && strcmp (bfd_section_name (abfd, text_sect) + len2,
1278 sname + len) == 0)
1279 break;
1280 }
579f31ac 1281 }
81545d45
RH
1282 else
1283 /* last resort: fall back on .text */
1284 text_sect = bfd_get_section_by_name (abfd, ".text");
1285
1286 if (text_sect)
1287 {
1288 /* The IA-64 processor-specific ABI requires setting
1289 sh_link to the unwind section, whereas HP-UX requires
1290 sh_info to do so. For maximum compatibility, we'll
1291 set both for now... */
1292 hdr->sh_link = elf_section_data (text_sect)->this_idx;
1293 hdr->sh_info = elf_section_data (text_sect)->this_idx;
1294 }
1295 break;
1296 }
1297 }
9d46020e
AM
1298
1299 if (! elf_flags_init (abfd))
1300 {
1301 unsigned long flags = 0;
1302
1303 if (abfd->xvec->byteorder == BFD_ENDIAN_BIG)
1304 flags |= EF_IA_64_BE;
1305 if (bfd_get_mach (abfd) == bfd_mach_ia64_elf64)
1306 flags |= EF_IA_64_ABI64;
1307
1308 elf_elfheader(abfd)->e_flags = flags;
b34976b6 1309 elf_flags_init (abfd) = TRUE;
9d46020e 1310 }
81545d45
RH
1311}
1312
800eeca4
JW
1313/* Hook called by the linker routine which adds symbols from an object
1314 file. We use it to put .comm items in .sbss, and not .bss. */
1315
b34976b6 1316static bfd_boolean
bbe66d08 1317elfNN_ia64_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
800eeca4
JW
1318 bfd *abfd;
1319 struct bfd_link_info *info;
1320 const Elf_Internal_Sym *sym;
64bf6ae6
JW
1321 const char **namep ATTRIBUTE_UNUSED;
1322 flagword *flagsp ATTRIBUTE_UNUSED;
800eeca4
JW
1323 asection **secp;
1324 bfd_vma *valp;
1325{
1326 if (sym->st_shndx == SHN_COMMON
1327 && !info->relocateable
c0846b23 1328 && sym->st_size <= elf_gp_size (abfd))
800eeca4
JW
1329 {
1330 /* Common symbols less than or equal to -G nn bytes are
1331 automatically put into .sbss. */
1332
1333 asection *scomm = bfd_get_section_by_name (abfd, ".scommon");
1334
1335 if (scomm == NULL)
1336 {
1337 scomm = bfd_make_section (abfd, ".scommon");
1338 if (scomm == NULL
1339 || !bfd_set_section_flags (abfd, scomm, (SEC_ALLOC
1340 | SEC_IS_COMMON
1341 | SEC_LINKER_CREATED)))
b34976b6 1342 return FALSE;
800eeca4
JW
1343 }
1344
1345 *secp = scomm;
1346 *valp = sym->st_size;
1347 }
1348
b34976b6 1349 return TRUE;
800eeca4
JW
1350}
1351
b34976b6 1352static bfd_boolean
7b6dab7f
TW
1353elfNN_ia64_aix_vec (const bfd_target *vec)
1354{
1355 extern const bfd_target bfd_elfNN_ia64_aix_little_vec;
1356 extern const bfd_target bfd_elfNN_ia64_aix_big_vec;
1357
dc810e39 1358 return (/**/vec == & bfd_elfNN_ia64_aix_little_vec
7b6dab7f
TW
1359 || vec == & bfd_elfNN_ia64_aix_big_vec);
1360}
1361
1362/* Hook called by the linker routine which adds symbols from an object
1363 file. We use it to handle OS-specific symbols. */
1364
b34976b6 1365static bfd_boolean
7b6dab7f
TW
1366elfNN_ia64_aix_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
1367 bfd *abfd;
1368 struct bfd_link_info *info;
1369 const Elf_Internal_Sym *sym;
1370 const char **namep;
1371 flagword *flagsp;
1372 asection **secp;
1373 bfd_vma *valp;
1374{
1375 if (strcmp (*namep, "__GLOB_DATA_PTR") == 0)
1376 {
64e9ece0
TW
1377 /* Define __GLOB_DATA_PTR when it is encountered. This is expected to
1378 be a linker-defined symbol by the Aix C runtime startup code. IBM sez
1379 no one else should use it b/c it is undocumented. */
7b6dab7f
TW
1380 struct elf_link_hash_entry *h;
1381
0a991dfe 1382 h = elf_link_hash_lookup (elf_hash_table (info), *namep,
b34976b6 1383 FALSE, FALSE, FALSE);
dc810e39 1384 if (h == NULL)
7b6dab7f
TW
1385 {
1386 struct elf_backend_data *bed;
1387 struct elfNN_ia64_link_hash_table *ia64_info;
14a793b2 1388 struct bfd_link_hash_entry *bh = NULL;
7b6dab7f
TW
1389
1390 bed = get_elf_backend_data (abfd);
1391 ia64_info = elfNN_ia64_hash_table (info);
dc810e39 1392
7b6dab7f 1393 if (!(_bfd_generic_link_add_one_symbol
dc810e39 1394 (info, abfd, *namep, BSF_GLOBAL,
64e9ece0 1395 bfd_get_section_by_name (abfd, ".bss"),
b34976b6 1396 bed->got_symbol_offset, (const char *) NULL, FALSE,
14a793b2 1397 bed->collect, &bh)))
b34976b6 1398 return FALSE;
dc810e39 1399
14a793b2 1400 h = (struct elf_link_hash_entry *) bh;
7b6dab7f
TW
1401 h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
1402 h->type = STT_OBJECT;
dc810e39 1403
64e9ece0 1404 if (! _bfd_elf_link_record_dynamic_symbol (info, h))
b34976b6 1405 return FALSE;
7b6dab7f
TW
1406 }
1407
b34976b6 1408 return TRUE;
7b6dab7f
TW
1409 }
1410 else if (sym->st_shndx == SHN_LOOS)
1411 {
9ad5cbcf 1412 unsigned int i;
dc810e39 1413
10d1e03a
TW
1414 /* SHN_AIX_SYSCALL: Treat this as any other symbol. The special symbol
1415 is only relevant when compiling code for extended system calls.
dc810e39 1416 Replace the "special" section with .text, if possible.
64e9ece0 1417 Note that these symbols are always assumed to be in .text. */
9ad5cbcf 1418 for (i = 1; i < elf_numsections (abfd); i++)
7b6dab7f 1419 {
9ad5cbcf 1420 asection * sec = bfd_section_from_elf_index (abfd, i);
dc810e39 1421
7b6dab7f
TW
1422 if (sec && strcmp (sec->name, ".text") == 0)
1423 {
1424 *secp = sec;
1425 break;
1426 }
1427 }
1428
7b6dab7f
TW
1429 if (*secp == NULL)
1430 *secp = bfd_abs_section_ptr;
dc810e39 1431
7b6dab7f 1432 *valp = sym->st_size;
dc810e39 1433
b34976b6 1434 return TRUE;
7b6dab7f 1435 }
dc810e39 1436 else
7b6dab7f 1437 {
dc810e39 1438 return elfNN_ia64_add_symbol_hook (abfd, info, sym,
7b6dab7f
TW
1439 namep, flagsp, secp, valp);
1440 }
1441}
1442
b34976b6 1443bfd_boolean
7b6dab7f
TW
1444elfNN_ia64_aix_link_add_symbols (abfd, info)
1445 bfd *abfd;
1446 struct bfd_link_info *info;
1447{
1448 /* Make sure dynamic sections are always created. */
1449 if (! elf_hash_table (info)->dynamic_sections_created
1450 && abfd->xvec == info->hash->creator)
1451 {
1452 if (! bfd_elfNN_link_create_dynamic_sections (abfd, info))
b34976b6 1453 return FALSE;
7b6dab7f
TW
1454 }
1455
1456 /* Now do the standard call. */
1457 return bfd_elfNN_bfd_link_add_symbols (abfd, info);
1458}
1459
800eeca4
JW
1460/* Return the number of additional phdrs we will need. */
1461
1462static int
bbe66d08 1463elfNN_ia64_additional_program_headers (abfd)
800eeca4
JW
1464 bfd *abfd;
1465{
1466 asection *s;
1467 int ret = 0;
1468
1469 /* See if we need a PT_IA_64_ARCHEXT segment. */
1470 s = bfd_get_section_by_name (abfd, ELF_STRING_ia64_archext);
1471 if (s && (s->flags & SEC_LOAD))
1472 ++ret;
1473
81545d45
RH
1474 /* Count how many PT_IA_64_UNWIND segments we need. */
1475 for (s = abfd->sections; s; s = s->next)
d9cf1b54 1476 if (is_unwind_section_name (abfd, s->name) && (s->flags & SEC_LOAD))
81545d45 1477 ++ret;
800eeca4
JW
1478
1479 return ret;
1480}
1481
b34976b6 1482static bfd_boolean
bbe66d08 1483elfNN_ia64_modify_segment_map (abfd)
800eeca4
JW
1484 bfd *abfd;
1485{
1486 struct elf_segment_map *m, **pm;
81545d45 1487 Elf_Internal_Shdr *hdr;
800eeca4
JW
1488 asection *s;
1489
1490 /* If we need a PT_IA_64_ARCHEXT segment, it must come before
1491 all PT_LOAD segments. */
1492 s = bfd_get_section_by_name (abfd, ELF_STRING_ia64_archext);
1493 if (s && (s->flags & SEC_LOAD))
1494 {
1495 for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
1496 if (m->p_type == PT_IA_64_ARCHEXT)
1497 break;
1498 if (m == NULL)
1499 {
dc810e39
AM
1500 m = ((struct elf_segment_map *)
1501 bfd_zalloc (abfd, (bfd_size_type) sizeof *m));
800eeca4 1502 if (m == NULL)
b34976b6 1503 return FALSE;
800eeca4
JW
1504
1505 m->p_type = PT_IA_64_ARCHEXT;
1506 m->count = 1;
1507 m->sections[0] = s;
1508
1509 /* We want to put it after the PHDR and INTERP segments. */
1510 pm = &elf_tdata (abfd)->segment_map;
1511 while (*pm != NULL
1512 && ((*pm)->p_type == PT_PHDR
1513 || (*pm)->p_type == PT_INTERP))
1514 pm = &(*pm)->next;
1515
1516 m->next = *pm;
1517 *pm = m;
1518 }
1519 }
1520
81545d45
RH
1521 /* Install PT_IA_64_UNWIND segments, if needed. */
1522 for (s = abfd->sections; s; s = s->next)
800eeca4 1523 {
81545d45
RH
1524 hdr = &elf_section_data (s)->this_hdr;
1525 if (hdr->sh_type != SHT_IA_64_UNWIND)
1526 continue;
1527
1528 if (s && (s->flags & SEC_LOAD))
800eeca4 1529 {
81545d45 1530 for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
d9cf1b54
AM
1531 if (m->p_type == PT_IA_64_UNWIND)
1532 {
40c97fc6
AM
1533 int i;
1534
d9cf1b54
AM
1535 /* Look through all sections in the unwind segment
1536 for a match since there may be multiple sections
1537 to a segment. */
40c97fc6
AM
1538 for (i = m->count - 1; i >= 0; --i)
1539 if (m->sections[i] == s)
1540 break;
d9cf1b54 1541
40c97fc6 1542 if (i >= 0)
d9cf1b54
AM
1543 break;
1544 }
81545d45 1545
800eeca4 1546 if (m == NULL)
81545d45 1547 {
dc810e39
AM
1548 m = ((struct elf_segment_map *)
1549 bfd_zalloc (abfd, (bfd_size_type) sizeof *m));
81545d45 1550 if (m == NULL)
b34976b6 1551 return FALSE;
800eeca4 1552
81545d45
RH
1553 m->p_type = PT_IA_64_UNWIND;
1554 m->count = 1;
1555 m->sections[0] = s;
1556 m->next = NULL;
800eeca4 1557
81545d45
RH
1558 /* We want to put it last. */
1559 pm = &elf_tdata (abfd)->segment_map;
1560 while (*pm != NULL)
1561 pm = &(*pm)->next;
1562 *pm = m;
1563 }
800eeca4
JW
1564 }
1565 }
1566
1567 /* Turn on PF_IA_64_NORECOV if needed. This involves traversing all of
1568 the input sections for each output section in the segment and testing
1569 for SHF_IA_64_NORECOV on each. */
1570 for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
1571 if (m->p_type == PT_LOAD)
1572 {
1573 int i;
1574 for (i = m->count - 1; i >= 0; --i)
1575 {
1576 struct bfd_link_order *order = m->sections[i]->link_order_head;
1577 while (order)
1578 {
1579 if (order->type == bfd_indirect_link_order)
1580 {
1581 asection *is = order->u.indirect.section;
1582 bfd_vma flags = elf_section_data(is)->this_hdr.sh_flags;
1583 if (flags & SHF_IA_64_NORECOV)
1584 {
1585 m->p_flags |= PF_IA_64_NORECOV;
1586 goto found;
1587 }
1588 }
1589 order = order->next;
1590 }
1591 }
1592 found:;
1593 }
1594
b34976b6 1595 return TRUE;
800eeca4
JW
1596}
1597
800eeca4
JW
1598/* According to the Tahoe assembler spec, all labels starting with a
1599 '.' are local. */
1600
b34976b6 1601static bfd_boolean
bbe66d08 1602elfNN_ia64_is_local_label_name (abfd, name)
64bf6ae6 1603 bfd *abfd ATTRIBUTE_UNUSED;
800eeca4
JW
1604 const char *name;
1605{
1606 return name[0] == '.';
1607}
1608
1609/* Should we do dynamic things to this symbol? */
1610
b34976b6 1611static bfd_boolean
bbe66d08 1612elfNN_ia64_dynamic_symbol_p (h, info)
800eeca4
JW
1613 struct elf_link_hash_entry *h;
1614 struct bfd_link_info *info;
1615{
1616 if (h == NULL)
b34976b6 1617 return FALSE;
800eeca4
JW
1618
1619 while (h->root.type == bfd_link_hash_indirect
1620 || h->root.type == bfd_link_hash_warning)
1621 h = (struct elf_link_hash_entry *) h->root.u.i.link;
1622
1623 if (h->dynindx == -1)
b34976b6 1624 return FALSE;
2719f880
L
1625 switch (ELF_ST_VISIBILITY (h->other))
1626 {
1627 case STV_INTERNAL:
1628 case STV_HIDDEN:
b34976b6 1629 return FALSE;
5e8d7549
NC
1630 default:
1631 break;
2719f880 1632 }
800eeca4
JW
1633
1634 if (h->root.type == bfd_link_hash_undefweak
1635 || h->root.type == bfd_link_hash_defweak)
b34976b6 1636 return TRUE;
800eeca4 1637
671bae9c 1638 if ((info->shared && (!info->symbolic || info->allow_shlib_undefined))
800eeca4
JW
1639 || ((h->elf_link_hash_flags
1640 & (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR))
1641 == (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR)))
b34976b6 1642 return TRUE;
800eeca4 1643
b34976b6 1644 return FALSE;
800eeca4
JW
1645}
1646\f
b34976b6 1647static bfd_boolean
bbe66d08
JW
1648elfNN_ia64_local_hash_table_init (ht, abfd, new)
1649 struct elfNN_ia64_local_hash_table *ht;
64bf6ae6 1650 bfd *abfd ATTRIBUTE_UNUSED;
800eeca4
JW
1651 new_hash_entry_func new;
1652{
3e932841 1653 memset (ht, 0, sizeof (*ht));
800eeca4
JW
1654 return bfd_hash_table_init (&ht->root, new);
1655}
1656
1657static struct bfd_hash_entry*
bbe66d08 1658elfNN_ia64_new_loc_hash_entry (entry, table, string)
800eeca4
JW
1659 struct bfd_hash_entry *entry;
1660 struct bfd_hash_table *table;
1661 const char *string;
1662{
bbe66d08
JW
1663 struct elfNN_ia64_local_hash_entry *ret;
1664 ret = (struct elfNN_ia64_local_hash_entry *) entry;
800eeca4
JW
1665
1666 /* Allocate the structure if it has not already been allocated by a
1667 subclass. */
1668 if (!ret)
1669 ret = bfd_hash_allocate (table, sizeof (*ret));
1670
1671 if (!ret)
1672 return 0;
1673
1674 /* Initialize our local data. All zeros, and definitely easier
1675 than setting a handful of bit fields. */
3e932841 1676 memset (ret, 0, sizeof (*ret));
800eeca4
JW
1677
1678 /* Call the allocation method of the superclass. */
bbe66d08 1679 ret = ((struct elfNN_ia64_local_hash_entry *)
800eeca4
JW
1680 bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
1681
1682 return (struct bfd_hash_entry *) ret;
1683}
1684
1685static struct bfd_hash_entry*
bbe66d08 1686elfNN_ia64_new_elf_hash_entry (entry, table, string)
800eeca4
JW
1687 struct bfd_hash_entry *entry;
1688 struct bfd_hash_table *table;
1689 const char *string;
1690{
bbe66d08
JW
1691 struct elfNN_ia64_link_hash_entry *ret;
1692 ret = (struct elfNN_ia64_link_hash_entry *) entry;
800eeca4
JW
1693
1694 /* Allocate the structure if it has not already been allocated by a
1695 subclass. */
1696 if (!ret)
1697 ret = bfd_hash_allocate (table, sizeof (*ret));
1698
1699 if (!ret)
1700 return 0;
1701
1702 /* Initialize our local data. All zeros, and definitely easier
1703 than setting a handful of bit fields. */
3e932841 1704 memset (ret, 0, sizeof (*ret));
800eeca4
JW
1705
1706 /* Call the allocation method of the superclass. */
bbe66d08 1707 ret = ((struct elfNN_ia64_link_hash_entry *)
800eeca4
JW
1708 _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret,
1709 table, string));
1710
1711 return (struct bfd_hash_entry *) ret;
1712}
1713
1714static void
b48fa14c
AM
1715elfNN_ia64_hash_copy_indirect (bed, xdir, xind)
1716 struct elf_backend_data *bed ATTRIBUTE_UNUSED;
800eeca4
JW
1717 struct elf_link_hash_entry *xdir, *xind;
1718{
bbe66d08 1719 struct elfNN_ia64_link_hash_entry *dir, *ind;
800eeca4 1720
57c7194e
AM
1721 dir = (struct elfNN_ia64_link_hash_entry *) xdir;
1722 ind = (struct elfNN_ia64_link_hash_entry *) xind;
800eeca4 1723
3e932841 1724 /* Copy down any references that we may have already seen to the
800eeca4
JW
1725 symbol which just became indirect. */
1726
1727 dir->root.elf_link_hash_flags |=
1728 (ind->root.elf_link_hash_flags
1729 & (ELF_LINK_HASH_REF_DYNAMIC
1730 | ELF_LINK_HASH_REF_REGULAR
1731 | ELF_LINK_HASH_REF_REGULAR_NONWEAK));
1732
1e370bd2 1733 if (ind->root.root.type != bfd_link_hash_indirect)
0a991dfe
AM
1734 return;
1735
800eeca4
JW
1736 /* Copy over the got and plt data. This would have been done
1737 by check_relocs. */
1738
1739 if (dir->info == NULL)
1740 {
bbe66d08 1741 struct elfNN_ia64_dyn_sym_info *dyn_i;
800eeca4
JW
1742
1743 dir->info = dyn_i = ind->info;
1744 ind->info = NULL;
1745
1746 /* Fix up the dyn_sym_info pointers to the global symbol. */
1747 for (; dyn_i; dyn_i = dyn_i->next)
1748 dyn_i->h = &dir->root;
1749 }
1750 BFD_ASSERT (ind->info == NULL);
1751
1752 /* Copy over the dynindx. */
1753
1754 if (dir->root.dynindx == -1)
1755 {
1756 dir->root.dynindx = ind->root.dynindx;
1757 dir->root.dynstr_index = ind->root.dynstr_index;
1758 ind->root.dynindx = -1;
1759 ind->root.dynstr_index = 0;
1760 }
1761 BFD_ASSERT (ind->root.dynindx == -1);
1762}
1763
1764static void
e5094212
AM
1765elfNN_ia64_hash_hide_symbol (info, xh, force_local)
1766 struct bfd_link_info *info;
800eeca4 1767 struct elf_link_hash_entry *xh;
b34976b6 1768 bfd_boolean force_local;
800eeca4 1769{
bbe66d08
JW
1770 struct elfNN_ia64_link_hash_entry *h;
1771 struct elfNN_ia64_dyn_sym_info *dyn_i;
800eeca4 1772
bbe66d08 1773 h = (struct elfNN_ia64_link_hash_entry *)xh;
800eeca4 1774
e5094212 1775 _bfd_elf_link_hash_hide_symbol (info, &h->root, force_local);
800eeca4
JW
1776
1777 for (dyn_i = h->info; dyn_i; dyn_i = dyn_i->next)
1778 dyn_i->want_plt2 = 0;
1779}
1780
1781/* Create the derived linker hash table. The IA-64 ELF port uses this
1782 derived hash table to keep information specific to the IA-64 ElF
1783 linker (without using static variables). */
1784
1785static struct bfd_link_hash_table*
bbe66d08 1786elfNN_ia64_hash_table_create (abfd)
800eeca4
JW
1787 bfd *abfd;
1788{
bbe66d08 1789 struct elfNN_ia64_link_hash_table *ret;
800eeca4 1790
dc810e39 1791 ret = bfd_zalloc (abfd, (bfd_size_type) sizeof (*ret));
800eeca4
JW
1792 if (!ret)
1793 return 0;
1794 if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
bbe66d08 1795 elfNN_ia64_new_elf_hash_entry))
800eeca4
JW
1796 {
1797 bfd_release (abfd, ret);
1798 return 0;
1799 }
1800
bbe66d08
JW
1801 if (!elfNN_ia64_local_hash_table_init (&ret->loc_hash_table, abfd,
1802 elfNN_ia64_new_loc_hash_entry))
800eeca4
JW
1803 return 0;
1804 return &ret->root.root;
1805}
1806
1807/* Look up an entry in a Alpha ELF linker hash table. */
1808
bbe66d08
JW
1809static INLINE struct elfNN_ia64_local_hash_entry *
1810elfNN_ia64_local_hash_lookup(table, string, create, copy)
1811 struct elfNN_ia64_local_hash_table *table;
800eeca4 1812 const char *string;
b34976b6 1813 bfd_boolean create, copy;
800eeca4 1814{
bbe66d08 1815 return ((struct elfNN_ia64_local_hash_entry *)
800eeca4
JW
1816 bfd_hash_lookup (&table->root, string, create, copy));
1817}
1818
1819/* Traverse both local and global hash tables. */
1820
bbe66d08 1821struct elfNN_ia64_dyn_sym_traverse_data
800eeca4 1822{
b34976b6 1823 bfd_boolean (*func) PARAMS ((struct elfNN_ia64_dyn_sym_info *, PTR));
800eeca4
JW
1824 PTR data;
1825};
1826
b34976b6 1827static bfd_boolean
bbe66d08 1828elfNN_ia64_global_dyn_sym_thunk (xentry, xdata)
800eeca4
JW
1829 struct bfd_hash_entry *xentry;
1830 PTR xdata;
1831{
bbe66d08
JW
1832 struct elfNN_ia64_link_hash_entry *entry
1833 = (struct elfNN_ia64_link_hash_entry *) xentry;
1834 struct elfNN_ia64_dyn_sym_traverse_data *data
1835 = (struct elfNN_ia64_dyn_sym_traverse_data *) xdata;
1836 struct elfNN_ia64_dyn_sym_info *dyn_i;
800eeca4 1837
e92d460e
AM
1838 if (entry->root.root.type == bfd_link_hash_warning)
1839 entry = (struct elfNN_ia64_link_hash_entry *) entry->root.root.u.i.link;
1840
800eeca4
JW
1841 for (dyn_i = entry->info; dyn_i; dyn_i = dyn_i->next)
1842 if (! (*data->func) (dyn_i, data->data))
b34976b6
AM
1843 return FALSE;
1844 return TRUE;
800eeca4
JW
1845}
1846
b34976b6 1847static bfd_boolean
bbe66d08 1848elfNN_ia64_local_dyn_sym_thunk (xentry, xdata)
800eeca4
JW
1849 struct bfd_hash_entry *xentry;
1850 PTR xdata;
1851{
bbe66d08
JW
1852 struct elfNN_ia64_local_hash_entry *entry
1853 = (struct elfNN_ia64_local_hash_entry *) xentry;
1854 struct elfNN_ia64_dyn_sym_traverse_data *data
1855 = (struct elfNN_ia64_dyn_sym_traverse_data *) xdata;
1856 struct elfNN_ia64_dyn_sym_info *dyn_i;
800eeca4
JW
1857
1858 for (dyn_i = entry->info; dyn_i; dyn_i = dyn_i->next)
1859 if (! (*data->func) (dyn_i, data->data))
b34976b6
AM
1860 return FALSE;
1861 return TRUE;
800eeca4
JW
1862}
1863
1864static void
bbe66d08
JW
1865elfNN_ia64_dyn_sym_traverse (ia64_info, func, data)
1866 struct elfNN_ia64_link_hash_table *ia64_info;
b34976b6 1867 bfd_boolean (*func) PARAMS ((struct elfNN_ia64_dyn_sym_info *, PTR));
800eeca4
JW
1868 PTR data;
1869{
bbe66d08 1870 struct elfNN_ia64_dyn_sym_traverse_data xdata;
800eeca4
JW
1871
1872 xdata.func = func;
1873 xdata.data = data;
1874
1875 elf_link_hash_traverse (&ia64_info->root,
bbe66d08 1876 elfNN_ia64_global_dyn_sym_thunk, &xdata);
800eeca4 1877 bfd_hash_traverse (&ia64_info->loc_hash_table.root,
bbe66d08 1878 elfNN_ia64_local_dyn_sym_thunk, &xdata);
800eeca4
JW
1879}
1880\f
b34976b6 1881static bfd_boolean
bbe66d08 1882elfNN_ia64_create_dynamic_sections (abfd, info)
800eeca4
JW
1883 bfd *abfd;
1884 struct bfd_link_info *info;
1885{
bbe66d08 1886 struct elfNN_ia64_link_hash_table *ia64_info;
800eeca4
JW
1887 asection *s;
1888
1889 if (! _bfd_elf_create_dynamic_sections (abfd, info))
b34976b6 1890 return FALSE;
800eeca4 1891
bbe66d08 1892 ia64_info = elfNN_ia64_hash_table (info);
800eeca4
JW
1893
1894 ia64_info->plt_sec = bfd_get_section_by_name (abfd, ".plt");
1895 ia64_info->got_sec = bfd_get_section_by_name (abfd, ".got");
1896
1897 {
1898 flagword flags = bfd_get_section_flags (abfd, ia64_info->got_sec);
1899 bfd_set_section_flags (abfd, ia64_info->got_sec, SEC_SMALL_DATA | flags);
1900 }
1901
1902 if (!get_pltoff (abfd, info, ia64_info))
b34976b6 1903 return FALSE;
800eeca4
JW
1904
1905 s = bfd_make_section(abfd, ".rela.IA_64.pltoff");
1906 if (s == NULL
1907 || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
1908 | SEC_HAS_CONTENTS
1909 | SEC_IN_MEMORY
1910 | SEC_LINKER_CREATED
1911 | SEC_READONLY))
1912 || !bfd_set_section_alignment (abfd, s, 3))
b34976b6 1913 return FALSE;
800eeca4
JW
1914 ia64_info->rel_pltoff_sec = s;
1915
1916 s = bfd_make_section(abfd, ".rela.got");
1917 if (s == NULL
1918 || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
1919 | SEC_HAS_CONTENTS
1920 | SEC_IN_MEMORY
1921 | SEC_LINKER_CREATED
1922 | SEC_READONLY))
1923 || !bfd_set_section_alignment (abfd, s, 3))
b34976b6 1924 return FALSE;
800eeca4
JW
1925 ia64_info->rel_got_sec = s;
1926
b34976b6 1927 return TRUE;
800eeca4
JW
1928}
1929
f7460f5f
JJ
1930/* Find and/or create a hash entry for local symbol. */
1931static struct elfNN_ia64_local_hash_entry *
1932get_local_sym_hash (ia64_info, abfd, rel, create)
1933 struct elfNN_ia64_link_hash_table *ia64_info;
1934 bfd *abfd;
1935 const Elf_Internal_Rela *rel;
b34976b6 1936 bfd_boolean create;
f7460f5f 1937{
fcf12726 1938 struct elfNN_ia64_local_hash_entry *ret;
d48770d4
L
1939 asection *sec = abfd->sections;
1940 char addr_name [34];
1941
1942 BFD_ASSERT ((sizeof (sec->id)*2 + 1 + sizeof (unsigned long)*2 + 1) <= 34);
1943 BFD_ASSERT (sec);
f7460f5f
JJ
1944
1945 /* Construct a string for use in the elfNN_ia64_local_hash_table.
1946 name describes what was once anonymous memory. */
1947
d48770d4
L
1948 sprintf (addr_name, "%x:%lx",
1949 sec->id, (unsigned long) ELFNN_R_SYM (rel->r_info));
f7460f5f
JJ
1950
1951 /* Collect the canonical entry data for this address. */
fcf12726
AM
1952 ret = elfNN_ia64_local_hash_lookup (&ia64_info->loc_hash_table,
1953 addr_name, create, create);
fcf12726 1954 return ret;
f7460f5f
JJ
1955}
1956
800eeca4
JW
1957/* Find and/or create a descriptor for dynamic symbol info. This will
1958 vary based on global or local symbol, and the addend to the reloc. */
1959
bbe66d08 1960static struct elfNN_ia64_dyn_sym_info *
800eeca4 1961get_dyn_sym_info (ia64_info, h, abfd, rel, create)
bbe66d08 1962 struct elfNN_ia64_link_hash_table *ia64_info;
800eeca4
JW
1963 struct elf_link_hash_entry *h;
1964 bfd *abfd;
1965 const Elf_Internal_Rela *rel;
b34976b6 1966 bfd_boolean create;
800eeca4 1967{
bbe66d08
JW
1968 struct elfNN_ia64_dyn_sym_info **pp;
1969 struct elfNN_ia64_dyn_sym_info *dyn_i;
800eeca4 1970 bfd_vma addend = rel ? rel->r_addend : 0;
3e932841 1971
800eeca4 1972 if (h)
bbe66d08 1973 pp = &((struct elfNN_ia64_link_hash_entry *)h)->info;
800eeca4
JW
1974 else
1975 {
bbe66d08 1976 struct elfNN_ia64_local_hash_entry *loc_h;
800eeca4 1977
f7460f5f 1978 loc_h = get_local_sym_hash (ia64_info, abfd, rel, create);
f86b235a
RH
1979 if (!loc_h)
1980 {
1981 BFD_ASSERT (!create);
1982 return NULL;
1983 }
800eeca4
JW
1984
1985 pp = &loc_h->info;
3e932841 1986 }
800eeca4
JW
1987
1988 for (dyn_i = *pp; dyn_i && dyn_i->addend != addend; dyn_i = *pp)
1989 pp = &dyn_i->next;
1990
1991 if (dyn_i == NULL && create)
1992 {
dc810e39
AM
1993 dyn_i = ((struct elfNN_ia64_dyn_sym_info *)
1994 bfd_zalloc (abfd, (bfd_size_type) sizeof *dyn_i));
800eeca4
JW
1995 *pp = dyn_i;
1996 dyn_i->addend = addend;
1997 }
1998
1999 return dyn_i;
2000}
2001
2002static asection *
2003get_got (abfd, info, ia64_info)
2004 bfd *abfd;
2005 struct bfd_link_info *info;
bbe66d08 2006 struct elfNN_ia64_link_hash_table *ia64_info;
800eeca4 2007{
64bf6ae6 2008 asection *got;
800eeca4
JW
2009 bfd *dynobj;
2010
2011 got = ia64_info->got_sec;
2012 if (!got)
2013 {
2014 flagword flags;
2015
2016 dynobj = ia64_info->root.dynobj;
2017 if (!dynobj)
2018 ia64_info->root.dynobj = dynobj = abfd;
2019 if (!_bfd_elf_create_got_section (dynobj, info))
2020 return 0;
2021
2022 got = bfd_get_section_by_name (dynobj, ".got");
2023 BFD_ASSERT (got);
2024 ia64_info->got_sec = got;
2025
2026 flags = bfd_get_section_flags (abfd, got);
2027 bfd_set_section_flags (abfd, got, SEC_SMALL_DATA | flags);
2028 }
2029
2030 return got;
2031}
2032
2033/* Create function descriptor section (.opd). This section is called .opd
2034 because it contains "official prodecure descriptors". The "official"
2035 refers to the fact that these descriptors are used when taking the address
2036 of a procedure, thus ensuring a unique address for each procedure. */
2037
2038static asection *
2039get_fptr (abfd, info, ia64_info)
2040 bfd *abfd;
64bf6ae6 2041 struct bfd_link_info *info ATTRIBUTE_UNUSED;
bbe66d08 2042 struct elfNN_ia64_link_hash_table *ia64_info;
800eeca4
JW
2043{
2044 asection *fptr;
2045 bfd *dynobj;
2046
2047 fptr = ia64_info->fptr_sec;
2048 if (!fptr)
2049 {
2050 dynobj = ia64_info->root.dynobj;
2051 if (!dynobj)
2052 ia64_info->root.dynobj = dynobj = abfd;
2053
2054 fptr = bfd_make_section (dynobj, ".opd");
2055 if (!fptr
2056 || !bfd_set_section_flags (dynobj, fptr,
2057 (SEC_ALLOC
2058 | SEC_LOAD
2059 | SEC_HAS_CONTENTS
2060 | SEC_IN_MEMORY
2061 | SEC_READONLY
2062 | SEC_LINKER_CREATED))
2063 || !bfd_set_section_alignment (abfd, fptr, 4))
2064 {
2065 BFD_ASSERT (0);
2066 return NULL;
2067 }
2068
2069 ia64_info->fptr_sec = fptr;
2070 }
2071
2072 return fptr;
2073}
2074
2075static asection *
2076get_pltoff (abfd, info, ia64_info)
2077 bfd *abfd;
64bf6ae6 2078 struct bfd_link_info *info ATTRIBUTE_UNUSED;
bbe66d08 2079 struct elfNN_ia64_link_hash_table *ia64_info;
800eeca4
JW
2080{
2081 asection *pltoff;
2082 bfd *dynobj;
2083
2084 pltoff = ia64_info->pltoff_sec;
2085 if (!pltoff)
2086 {
2087 dynobj = ia64_info->root.dynobj;
2088 if (!dynobj)
2089 ia64_info->root.dynobj = dynobj = abfd;
2090
2091 pltoff = bfd_make_section (dynobj, ELF_STRING_ia64_pltoff);
2092 if (!pltoff
2093 || !bfd_set_section_flags (dynobj, pltoff,
2094 (SEC_ALLOC
2095 | SEC_LOAD
2096 | SEC_HAS_CONTENTS
2097 | SEC_IN_MEMORY
2098 | SEC_SMALL_DATA
2099 | SEC_LINKER_CREATED))
2100 || !bfd_set_section_alignment (abfd, pltoff, 4))
2101 {
2102 BFD_ASSERT (0);
2103 return NULL;
2104 }
2105
2106 ia64_info->pltoff_sec = pltoff;
2107 }
2108
2109 return pltoff;
2110}
2111
2112static asection *
2113get_reloc_section (abfd, ia64_info, sec, create)
2114 bfd *abfd;
bbe66d08 2115 struct elfNN_ia64_link_hash_table *ia64_info;
800eeca4 2116 asection *sec;
b34976b6 2117 bfd_boolean create;
800eeca4
JW
2118{
2119 const char *srel_name;
2120 asection *srel;
2121 bfd *dynobj;
2122
2123 srel_name = (bfd_elf_string_from_elf_section
2124 (abfd, elf_elfheader(abfd)->e_shstrndx,
2125 elf_section_data(sec)->rel_hdr.sh_name));
2126 if (srel_name == NULL)
2127 return NULL;
2128
2129 BFD_ASSERT ((strncmp (srel_name, ".rela", 5) == 0
2130 && strcmp (bfd_get_section_name (abfd, sec),
2131 srel_name+5) == 0)
2132 || (strncmp (srel_name, ".rel", 4) == 0
2133 && strcmp (bfd_get_section_name (abfd, sec),
2134 srel_name+4) == 0));
2135
2136 dynobj = ia64_info->root.dynobj;
2137 if (!dynobj)
2138 ia64_info->root.dynobj = dynobj = abfd;
2139
2140 srel = bfd_get_section_by_name (dynobj, srel_name);
2141 if (srel == NULL && create)
2142 {
2143 srel = bfd_make_section (dynobj, srel_name);
2144 if (srel == NULL
2145 || !bfd_set_section_flags (dynobj, srel,
2146 (SEC_ALLOC
2147 | SEC_LOAD
2148 | SEC_HAS_CONTENTS
2149 | SEC_IN_MEMORY
2150 | SEC_LINKER_CREATED
2151 | SEC_READONLY))
2152 || !bfd_set_section_alignment (dynobj, srel, 3))
2153 return NULL;
2154 }
2155
db6751f2
JJ
2156 if (sec->flags & SEC_READONLY)
2157 ia64_info->reltext = 1;
2158
800eeca4
JW
2159 return srel;
2160}
2161
b34976b6 2162static bfd_boolean
800eeca4
JW
2163count_dyn_reloc (abfd, dyn_i, srel, type)
2164 bfd *abfd;
bbe66d08 2165 struct elfNN_ia64_dyn_sym_info *dyn_i;
800eeca4
JW
2166 asection *srel;
2167 int type;
2168{
bbe66d08 2169 struct elfNN_ia64_dyn_reloc_entry *rent;
800eeca4
JW
2170
2171 for (rent = dyn_i->reloc_entries; rent; rent = rent->next)
2172 if (rent->srel == srel && rent->type == type)
2173 break;
2174
2175 if (!rent)
2176 {
dc810e39
AM
2177 rent = ((struct elfNN_ia64_dyn_reloc_entry *)
2178 bfd_alloc (abfd, (bfd_size_type) sizeof (*rent)));
800eeca4 2179 if (!rent)
b34976b6 2180 return FALSE;
800eeca4
JW
2181
2182 rent->next = dyn_i->reloc_entries;
2183 rent->srel = srel;
2184 rent->type = type;
2185 rent->count = 0;
2186 dyn_i->reloc_entries = rent;
2187 }
2188 rent->count++;
2189
b34976b6 2190 return TRUE;
800eeca4
JW
2191}
2192
b34976b6 2193static bfd_boolean
bbe66d08 2194elfNN_ia64_check_relocs (abfd, info, sec, relocs)
800eeca4
JW
2195 bfd *abfd;
2196 struct bfd_link_info *info;
2197 asection *sec;
2198 const Elf_Internal_Rela *relocs;
2199{
bbe66d08 2200 struct elfNN_ia64_link_hash_table *ia64_info;
800eeca4
JW
2201 const Elf_Internal_Rela *relend;
2202 Elf_Internal_Shdr *symtab_hdr;
2203 const Elf_Internal_Rela *rel;
2204 asection *got, *fptr, *srel;
2205
2206 if (info->relocateable)
b34976b6 2207 return TRUE;
800eeca4
JW
2208
2209 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
bbe66d08 2210 ia64_info = elfNN_ia64_hash_table (info);
800eeca4
JW
2211
2212 got = fptr = srel = NULL;
2213
2214 relend = relocs + sec->reloc_count;
2215 for (rel = relocs; rel < relend; ++rel)
2216 {
2217 enum {
2218 NEED_GOT = 1,
2c4c2bc0
RH
2219 NEED_GOTX = 2,
2220 NEED_FPTR = 4,
2221 NEED_PLTOFF = 8,
2222 NEED_MIN_PLT = 16,
2223 NEED_FULL_PLT = 32,
2224 NEED_DYNREL = 64,
2225 NEED_LTOFF_FPTR = 128,
2226 NEED_TPREL = 256,
2227 NEED_DTPMOD = 512,
2228 NEED_DTPREL = 1024
800eeca4
JW
2229 };
2230
2231 struct elf_link_hash_entry *h = NULL;
bbe66d08
JW
2232 unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
2233 struct elfNN_ia64_dyn_sym_info *dyn_i;
800eeca4 2234 int need_entry;
b34976b6 2235 bfd_boolean maybe_dynamic;
64bf6ae6 2236 int dynrel_type = R_IA64_NONE;
800eeca4
JW
2237
2238 if (r_symndx >= symtab_hdr->sh_info)
2239 {
2240 /* We're dealing with a global symbol -- find its hash entry
2241 and mark it as being referenced. */
2242 long indx = r_symndx - symtab_hdr->sh_info;
2243 h = elf_sym_hashes (abfd)[indx];
2244 while (h->root.type == bfd_link_hash_indirect
2245 || h->root.type == bfd_link_hash_warning)
2246 h = (struct elf_link_hash_entry *) h->root.u.i.link;
2247
2248 h->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR;
2249 }
2250
2251 /* We can only get preliminary data on whether a symbol is
2252 locally or externally defined, as not all of the input files
2253 have yet been processed. Do something with what we know, as
2254 this may help reduce memory usage and processing time later. */
b34976b6 2255 maybe_dynamic = FALSE;
671bae9c
NC
2256 if (h && ((info->shared
2257 && (!info->symbolic || info->allow_shlib_undefined))
800eeca4 2258 || ! (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)
7b6dab7f
TW
2259 || h->root.type == bfd_link_hash_defweak
2260 || elfNN_ia64_aix_vec (abfd->xvec)))
b34976b6 2261 maybe_dynamic = TRUE;
800eeca4
JW
2262
2263 need_entry = 0;
bbe66d08 2264 switch (ELFNN_R_TYPE (rel->r_info))
800eeca4 2265 {
800eeca4
JW
2266 case R_IA64_TPREL64MSB:
2267 case R_IA64_TPREL64LSB:
13ae64f3
JJ
2268 if (info->shared || maybe_dynamic)
2269 need_entry = NEED_DYNREL;
2270 dynrel_type = R_IA64_TPREL64LSB;
2271 if (info->shared)
2272 info->flags |= DF_STATIC_TLS;
2273 break;
2274
2275 case R_IA64_LTOFF_TPREL22:
2276 need_entry = NEED_TPREL;
2277 if (info->shared)
2278 info->flags |= DF_STATIC_TLS;
2279 break;
2280
2281 case R_IA64_DTPREL64MSB:
2282 case R_IA64_DTPREL64LSB:
2283 if (info->shared || maybe_dynamic)
2284 need_entry = NEED_DYNREL;
2285 dynrel_type = R_IA64_DTPREL64LSB;
2286 break;
2287
2288 case R_IA64_LTOFF_DTPREL22:
2289 need_entry = NEED_DTPREL;
2290 break;
2291
2292 case R_IA64_DTPMOD64MSB:
2293 case R_IA64_DTPMOD64LSB:
2294 if (info->shared || maybe_dynamic)
2295 need_entry = NEED_DYNREL;
2296 dynrel_type = R_IA64_DTPMOD64LSB;
2297 break;
2298
2299 case R_IA64_LTOFF_DTPMOD22:
2300 need_entry = NEED_DTPMOD;
2301 break;
800eeca4
JW
2302
2303 case R_IA64_LTOFF_FPTR22:
2304 case R_IA64_LTOFF_FPTR64I:
a4bd8390
JW
2305 case R_IA64_LTOFF_FPTR32MSB:
2306 case R_IA64_LTOFF_FPTR32LSB:
800eeca4
JW
2307 case R_IA64_LTOFF_FPTR64MSB:
2308 case R_IA64_LTOFF_FPTR64LSB:
2309 need_entry = NEED_FPTR | NEED_GOT | NEED_LTOFF_FPTR;
2310 break;
2311
2312 case R_IA64_FPTR64I:
2313 case R_IA64_FPTR32MSB:
2314 case R_IA64_FPTR32LSB:
2315 case R_IA64_FPTR64MSB:
2316 case R_IA64_FPTR64LSB:
64e9ece0 2317 if (info->shared || h || elfNN_ia64_aix_vec (abfd->xvec))
800eeca4
JW
2318 need_entry = NEED_FPTR | NEED_DYNREL;
2319 else
2320 need_entry = NEED_FPTR;
2321 dynrel_type = R_IA64_FPTR64LSB;
2322 break;
2323
2324 case R_IA64_LTOFF22:
800eeca4
JW
2325 case R_IA64_LTOFF64I:
2326 need_entry = NEED_GOT;
2327 break;
2328
2c4c2bc0
RH
2329 case R_IA64_LTOFF22X:
2330 need_entry = NEED_GOTX;
2331 break;
2332
800eeca4
JW
2333 case R_IA64_PLTOFF22:
2334 case R_IA64_PLTOFF64I:
2335 case R_IA64_PLTOFF64MSB:
2336 case R_IA64_PLTOFF64LSB:
2337 need_entry = NEED_PLTOFF;
2338 if (h)
2339 {
2340 if (maybe_dynamic)
2341 need_entry |= NEED_MIN_PLT;
2342 }
2343 else
2344 {
2345 (*info->callbacks->warning)
2346 (info, _("@pltoff reloc against local symbol"), 0,
dc810e39 2347 abfd, 0, (bfd_vma) 0);
800eeca4
JW
2348 }
2349 break;
2350
2351 case R_IA64_PCREL21B:
748abff6 2352 case R_IA64_PCREL60B:
800eeca4
JW
2353 /* Depending on where this symbol is defined, we may or may not
2354 need a full plt entry. Only skip if we know we'll not need
2355 the entry -- static or symbolic, and the symbol definition
2356 has already been seen. */
2357 if (maybe_dynamic && rel->r_addend == 0)
2358 need_entry = NEED_FULL_PLT;
2359 break;
2360
2361 case R_IA64_IMM14:
2362 case R_IA64_IMM22:
2363 case R_IA64_IMM64:
2364 case R_IA64_DIR32MSB:
2365 case R_IA64_DIR32LSB:
2366 case R_IA64_DIR64MSB:
2367 case R_IA64_DIR64LSB:
2368 /* Shared objects will always need at least a REL relocation. */
7b6dab7f 2369 if (info->shared || maybe_dynamic
7b6dab7f 2370 || (elfNN_ia64_aix_vec (abfd->xvec)
64e9ece0 2371 && (!h || strcmp (h->root.root.string,
7b6dab7f 2372 "__GLOB_DATA_PTR") != 0)))
800eeca4
JW
2373 need_entry = NEED_DYNREL;
2374 dynrel_type = R_IA64_DIR64LSB;
2375 break;
2376
18b27f17
RH
2377 case R_IA64_IPLTMSB:
2378 case R_IA64_IPLTLSB:
2379 /* Shared objects will always need at least a REL relocation. */
2380 if (info->shared || maybe_dynamic)
2381 need_entry = NEED_DYNREL;
2382 dynrel_type = R_IA64_IPLTLSB;
2383 break;
2384
748abff6
RH
2385 case R_IA64_PCREL22:
2386 case R_IA64_PCREL64I:
800eeca4
JW
2387 case R_IA64_PCREL32MSB:
2388 case R_IA64_PCREL32LSB:
2389 case R_IA64_PCREL64MSB:
2390 case R_IA64_PCREL64LSB:
2391 if (maybe_dynamic)
2392 need_entry = NEED_DYNREL;
2393 dynrel_type = R_IA64_PCREL64LSB;
2394 break;
2395 }
2396
2397 if (!need_entry)
2398 continue;
2399
2400 if ((need_entry & NEED_FPTR) != 0
2401 && rel->r_addend)
2402 {
2403 (*info->callbacks->warning)
2404 (info, _("non-zero addend in @fptr reloc"), 0,
dc810e39 2405 abfd, 0, (bfd_vma) 0);
800eeca4
JW
2406 }
2407
b34976b6 2408 dyn_i = get_dyn_sym_info (ia64_info, h, abfd, rel, TRUE);
800eeca4
JW
2409
2410 /* Record whether or not this is a local symbol. */
2411 dyn_i->h = h;
2412
2413 /* Create what's needed. */
2c4c2bc0
RH
2414 if (need_entry & (NEED_GOT | NEED_GOTX | NEED_TPREL
2415 | NEED_DTPMOD | NEED_DTPREL))
800eeca4
JW
2416 {
2417 if (!got)
2418 {
2419 got = get_got (abfd, info, ia64_info);
2420 if (!got)
b34976b6 2421 return FALSE;
800eeca4 2422 }
13ae64f3
JJ
2423 if (need_entry & NEED_GOT)
2424 dyn_i->want_got = 1;
2c4c2bc0
RH
2425 if (need_entry & NEED_GOTX)
2426 dyn_i->want_gotx = 1;
13ae64f3
JJ
2427 if (need_entry & NEED_TPREL)
2428 dyn_i->want_tprel = 1;
2429 if (need_entry & NEED_DTPMOD)
2430 dyn_i->want_dtpmod = 1;
2431 if (need_entry & NEED_DTPREL)
2432 dyn_i->want_dtprel = 1;
800eeca4
JW
2433 }
2434 if (need_entry & NEED_FPTR)
2435 {
2436 if (!fptr)
2437 {
2438 fptr = get_fptr (abfd, info, ia64_info);
2439 if (!fptr)
b34976b6 2440 return FALSE;
800eeca4
JW
2441 }
2442
2443 /* FPTRs for shared libraries are allocated by the dynamic
2444 linker. Make sure this local symbol will appear in the
2445 dynamic symbol table. */
7b6dab7f
TW
2446 if (!h && (info->shared
2447 /* AIX also needs one */
2448 || elfNN_ia64_aix_vec (abfd->xvec)))
800eeca4 2449 {
bbe66d08 2450 if (! (_bfd_elfNN_link_record_local_dynamic_symbol
dc810e39 2451 (info, abfd, (long) r_symndx)))
b34976b6 2452 return FALSE;
800eeca4
JW
2453 }
2454
2455 dyn_i->want_fptr = 1;
2456 }
2457 if (need_entry & NEED_LTOFF_FPTR)
2458 dyn_i->want_ltoff_fptr = 1;
2459 if (need_entry & (NEED_MIN_PLT | NEED_FULL_PLT))
2460 {
2461 if (!ia64_info->root.dynobj)
2462 ia64_info->root.dynobj = abfd;
2463 h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
2464 dyn_i->want_plt = 1;
2465 }
2466 if (need_entry & NEED_FULL_PLT)
2467 dyn_i->want_plt2 = 1;
2468 if (need_entry & NEED_PLTOFF)
2469 dyn_i->want_pltoff = 1;
2470 if ((need_entry & NEED_DYNREL) && (sec->flags & SEC_ALLOC))
2471 {
2472 if (!srel)
2473 {
b34976b6 2474 srel = get_reloc_section (abfd, ia64_info, sec, TRUE);
800eeca4 2475 if (!srel)
b34976b6 2476 return FALSE;
800eeca4
JW
2477 }
2478 if (!count_dyn_reloc (abfd, dyn_i, srel, dynrel_type))
b34976b6 2479 return FALSE;
800eeca4
JW
2480 }
2481 }
2482
b34976b6 2483 return TRUE;
800eeca4
JW
2484}
2485
800eeca4
JW
2486/* For cleanliness, and potentially faster dynamic loading, allocate
2487 external GOT entries first. */
2488
b34976b6 2489static bfd_boolean
800eeca4 2490allocate_global_data_got (dyn_i, data)
bbe66d08 2491 struct elfNN_ia64_dyn_sym_info *dyn_i;
800eeca4
JW
2492 PTR data;
2493{
bbe66d08 2494 struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
800eeca4 2495
2c4c2bc0 2496 if ((dyn_i->want_got || dyn_i->want_gotx)
800eeca4 2497 && ! dyn_i->want_fptr
7b6dab7f 2498 && (elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info)
64e9ece0
TW
2499 || (elfNN_ia64_aix_vec (x->info->hash->creator)
2500 && (!dyn_i->h || strcmp (dyn_i->h->root.root.string,
2501 "__GLOB_DATA_PTR") != 0))))
800eeca4
JW
2502 {
2503 dyn_i->got_offset = x->ofs;
2504 x->ofs += 8;
2505 }
13ae64f3
JJ
2506 if (dyn_i->want_tprel)
2507 {
2508 dyn_i->tprel_offset = x->ofs;
2509 x->ofs += 8;
2510 }
2511 if (dyn_i->want_dtpmod)
2512 {
b3dfd7fe
JJ
2513 if (elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info))
2514 {
2515 dyn_i->dtpmod_offset = x->ofs;
2516 x->ofs += 8;
2517 }
2518 else
2519 {
2520 struct elfNN_ia64_link_hash_table *ia64_info;
2521
2522 ia64_info = elfNN_ia64_hash_table (x->info);
2523 if (ia64_info->self_dtpmod_offset == (bfd_vma) -1)
2524 {
2525 ia64_info->self_dtpmod_offset = x->ofs;
2526 x->ofs += 8;
2527 }
2528 dyn_i->dtpmod_offset = ia64_info->self_dtpmod_offset;
2529 }
13ae64f3
JJ
2530 }
2531 if (dyn_i->want_dtprel)
2532 {
2533 dyn_i->dtprel_offset = x->ofs;
2534 x->ofs += 8;
2535 }
b34976b6 2536 return TRUE;
800eeca4
JW
2537}
2538
2539/* Next, allocate all the GOT entries used by LTOFF_FPTR relocs. */
2540
b34976b6 2541static bfd_boolean
800eeca4 2542allocate_global_fptr_got (dyn_i, data)
bbe66d08 2543 struct elfNN_ia64_dyn_sym_info *dyn_i;
800eeca4
JW
2544 PTR data;
2545{
bbe66d08 2546 struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
800eeca4
JW
2547
2548 if (dyn_i->want_got
2549 && dyn_i->want_fptr
7b6dab7f
TW
2550 && (elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info)
2551 || elfNN_ia64_aix_vec (x->info->hash->creator)))
800eeca4
JW
2552 {
2553 dyn_i->got_offset = x->ofs;
2554 x->ofs += 8;
2555 }
b34976b6 2556 return TRUE;
800eeca4
JW
2557}
2558
2559/* Lastly, allocate all the GOT entries for local data. */
2560
b34976b6 2561static bfd_boolean
800eeca4 2562allocate_local_got (dyn_i, data)
bbe66d08 2563 struct elfNN_ia64_dyn_sym_info *dyn_i;
800eeca4
JW
2564 PTR data;
2565{
bbe66d08 2566 struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
800eeca4 2567
2c4c2bc0 2568 if ((dyn_i->want_got || dyn_i->want_gotx)
7b6dab7f
TW
2569 && ! (elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info)
2570 || elfNN_ia64_aix_vec (x->info->hash->creator)))
800eeca4
JW
2571 {
2572 dyn_i->got_offset = x->ofs;
2573 x->ofs += 8;
2574 }
b34976b6 2575 return TRUE;
800eeca4
JW
2576}
2577
2578/* Search for the index of a global symbol in it's defining object file. */
2579
dc810e39 2580static long
800eeca4
JW
2581global_sym_index (h)
2582 struct elf_link_hash_entry *h;
2583{
2584 struct elf_link_hash_entry **p;
2585 bfd *obj;
2586
2587 BFD_ASSERT (h->root.type == bfd_link_hash_defined
2588 || h->root.type == bfd_link_hash_defweak);
2589
2590 obj = h->root.u.def.section->owner;
2591 for (p = elf_sym_hashes (obj); *p != h; ++p)
2592 continue;
2593
2594 return p - elf_sym_hashes (obj) + elf_tdata (obj)->symtab_hdr.sh_info;
2595}
2596
2597/* Allocate function descriptors. We can do these for every function
2598 in a main executable that is not exported. */
2599
b34976b6 2600static bfd_boolean
800eeca4 2601allocate_fptr (dyn_i, data)
bbe66d08 2602 struct elfNN_ia64_dyn_sym_info *dyn_i;
800eeca4
JW
2603 PTR data;
2604{
bbe66d08 2605 struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
800eeca4
JW
2606
2607 if (dyn_i->want_fptr)
2608 {
2609 struct elf_link_hash_entry *h = dyn_i->h;
3e932841 2610
800eeca4
JW
2611 if (h)
2612 while (h->root.type == bfd_link_hash_indirect
2613 || h->root.type == bfd_link_hash_warning)
2614 h = (struct elf_link_hash_entry *) h->root.u.i.link;
2615
7b6dab7f
TW
2616 if (x->info->shared
2617 /* AIX needs an FPTR in this case. */
2618 || (elfNN_ia64_aix_vec (x->info->hash->creator)
2619 && (!h
2620 || h->root.type == bfd_link_hash_defined
2621 || h->root.type == bfd_link_hash_defweak)))
800eeca4
JW
2622 {
2623 if (h && h->dynindx == -1)
2624 {
2625 BFD_ASSERT ((h->root.type == bfd_link_hash_defined)
2626 || (h->root.type == bfd_link_hash_defweak));
2627
bbe66d08 2628 if (!_bfd_elfNN_link_record_local_dynamic_symbol
800eeca4
JW
2629 (x->info, h->root.u.def.section->owner,
2630 global_sym_index (h)))
b34976b6 2631 return FALSE;
800eeca4
JW
2632 }
2633
2634 dyn_i->want_fptr = 0;
2635 }
2636 else if (h == NULL || h->dynindx == -1)
2637 {
2638 dyn_i->fptr_offset = x->ofs;
2639 x->ofs += 16;
2640 }
2641 else
2642 dyn_i->want_fptr = 0;
2643 }
b34976b6 2644 return TRUE;
800eeca4
JW
2645}
2646
2647/* Allocate all the minimal PLT entries. */
2648
b34976b6 2649static bfd_boolean
800eeca4 2650allocate_plt_entries (dyn_i, data)
bbe66d08 2651 struct elfNN_ia64_dyn_sym_info *dyn_i;
800eeca4
JW
2652 PTR data;
2653{
bbe66d08 2654 struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
800eeca4
JW
2655
2656 if (dyn_i->want_plt)
2657 {
2658 struct elf_link_hash_entry *h = dyn_i->h;
2659
2660 if (h)
2661 while (h->root.type == bfd_link_hash_indirect
2662 || h->root.type == bfd_link_hash_warning)
2663 h = (struct elf_link_hash_entry *) h->root.u.i.link;
2664
2665 /* ??? Versioned symbols seem to lose ELF_LINK_HASH_NEEDS_PLT. */
bbe66d08 2666 if (elfNN_ia64_dynamic_symbol_p (h, x->info))
800eeca4
JW
2667 {
2668 bfd_size_type offset = x->ofs;
2669 if (offset == 0)
2670 offset = PLT_HEADER_SIZE;
2671 dyn_i->plt_offset = offset;
2672 x->ofs = offset + PLT_MIN_ENTRY_SIZE;
2673
2674 dyn_i->want_pltoff = 1;
2675 }
2676 else
2677 {
2678 dyn_i->want_plt = 0;
2679 dyn_i->want_plt2 = 0;
2680 }
2681 }
b34976b6 2682 return TRUE;
800eeca4
JW
2683}
2684
2685/* Allocate all the full PLT entries. */
2686
b34976b6 2687static bfd_boolean
800eeca4 2688allocate_plt2_entries (dyn_i, data)
bbe66d08 2689 struct elfNN_ia64_dyn_sym_info *dyn_i;
800eeca4
JW
2690 PTR data;
2691{
bbe66d08 2692 struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
800eeca4
JW
2693
2694 if (dyn_i->want_plt2)
2695 {
2696 struct elf_link_hash_entry *h = dyn_i->h;
2697 bfd_size_type ofs = x->ofs;
2698
2699 dyn_i->plt2_offset = ofs;
2700 x->ofs = ofs + PLT_FULL_ENTRY_SIZE;
2701
2702 while (h->root.type == bfd_link_hash_indirect
2703 || h->root.type == bfd_link_hash_warning)
2704 h = (struct elf_link_hash_entry *) h->root.u.i.link;
2705 dyn_i->h->plt.offset = ofs;
2706 }
b34976b6 2707 return TRUE;
800eeca4
JW
2708}
2709
2710/* Allocate all the PLTOFF entries requested by relocations and
2711 plt entries. We can't share space with allocated FPTR entries,
2712 because the latter are not necessarily addressable by the GP.
2713 ??? Relaxation might be able to determine that they are. */
2714
b34976b6 2715static bfd_boolean
800eeca4 2716allocate_pltoff_entries (dyn_i, data)
bbe66d08 2717 struct elfNN_ia64_dyn_sym_info *dyn_i;
800eeca4
JW
2718 PTR data;
2719{
bbe66d08 2720 struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
800eeca4
JW
2721
2722 if (dyn_i->want_pltoff)
2723 {
2724 dyn_i->pltoff_offset = x->ofs;
2725 x->ofs += 16;
2726 }
b34976b6 2727 return TRUE;
800eeca4
JW
2728}
2729
2730/* Allocate dynamic relocations for those symbols that turned out
2731 to be dynamic. */
2732
b34976b6 2733static bfd_boolean
800eeca4 2734allocate_dynrel_entries (dyn_i, data)
bbe66d08 2735 struct elfNN_ia64_dyn_sym_info *dyn_i;
800eeca4
JW
2736 PTR data;
2737{
bbe66d08
JW
2738 struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
2739 struct elfNN_ia64_link_hash_table *ia64_info;
2740 struct elfNN_ia64_dyn_reloc_entry *rent;
b34976b6 2741 bfd_boolean dynamic_symbol, shared;
800eeca4 2742
bbe66d08 2743 ia64_info = elfNN_ia64_hash_table (x->info);
7b6dab7f 2744 dynamic_symbol = elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info)
64e9ece0
TW
2745 || (elfNN_ia64_aix_vec (x->info->hash->creator)
2746 /* Don't allocate an entry for __GLOB_DATA_PTR */
2747 && (!dyn_i->h || strcmp (dyn_i->h->root.root.string,
2748 "__GLOB_DATA_PTR") != 0));
800eeca4
JW
2749 shared = x->info->shared;
2750
2751 /* Take care of the normal data relocations. */
2752
2753 for (rent = dyn_i->reloc_entries; rent; rent = rent->next)
2754 {
18b27f17
RH
2755 int count = rent->count;
2756
800eeca4
JW
2757 switch (rent->type)
2758 {
2759 case R_IA64_FPTR64LSB:
2760 /* Allocate one iff !want_fptr, which by this point will
2761 be true only if we're actually allocating one statically
2762 in the main executable. */
2763 if (dyn_i->want_fptr)
2764 continue;
2765 break;
2766 case R_IA64_PCREL64LSB:
2767 if (!dynamic_symbol)
2768 continue;
2769 break;
2770 case R_IA64_DIR64LSB:
2771 if (!dynamic_symbol && !shared)
2772 continue;
2773 break;
18b27f17
RH
2774 case R_IA64_IPLTLSB:
2775 if (!dynamic_symbol && !shared)
2776 continue;
2777 /* Use two REL relocations for IPLT relocations
2778 against local symbols. */
2779 if (!dynamic_symbol)
2780 count *= 2;
2781 break;
13ae64f3
JJ
2782 case R_IA64_TPREL64LSB:
2783 case R_IA64_DTPREL64LSB:
2784 case R_IA64_DTPMOD64LSB:
2785 break;
18b27f17
RH
2786 default:
2787 abort ();
800eeca4 2788 }
18b27f17 2789 rent->srel->_raw_size += sizeof (ElfNN_External_Rela) * count;
800eeca4
JW
2790 }
2791
2792 /* Take care of the GOT and PLT relocations. */
2793
2c4c2bc0 2794 if (((dynamic_symbol || shared) && (dyn_i->want_got || dyn_i->want_gotx))
800eeca4 2795 || (dyn_i->want_ltoff_fptr && dyn_i->h && dyn_i->h->dynindx != -1))
bbe66d08 2796 ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
13ae64f3
JJ
2797 if ((dynamic_symbol || shared) && dyn_i->want_tprel)
2798 ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
b3dfd7fe 2799 if (dynamic_symbol && dyn_i->want_dtpmod)
13ae64f3
JJ
2800 ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
2801 if (dynamic_symbol && dyn_i->want_dtprel)
2802 ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
800eeca4
JW
2803
2804 if (dyn_i->want_pltoff)
2805 {
2806 bfd_size_type t = 0;
2807
2808 /* Dynamic symbols get one IPLT relocation. Local symbols in
2809 shared libraries get two REL relocations. Local symbols in
2810 main applications get nothing. */
2811 if (dynamic_symbol)
bbe66d08 2812 t = sizeof (ElfNN_External_Rela);
800eeca4 2813 else if (shared)
bbe66d08 2814 t = 2 * sizeof (ElfNN_External_Rela);
800eeca4
JW
2815
2816 ia64_info->rel_pltoff_sec->_raw_size += t;
2817 }
2818
b34976b6 2819 return TRUE;
800eeca4
JW
2820}
2821
b34976b6 2822static bfd_boolean
bbe66d08 2823elfNN_ia64_adjust_dynamic_symbol (info, h)
64bf6ae6 2824 struct bfd_link_info *info ATTRIBUTE_UNUSED;
800eeca4
JW
2825 struct elf_link_hash_entry *h;
2826{
2827 /* ??? Undefined symbols with PLT entries should be re-defined
2828 to be the PLT entry. */
2829
2830 /* If this is a weak symbol, and there is a real definition, the
2831 processor independent code will have arranged for us to see the
2832 real definition first, and we can just use the same value. */
2833 if (h->weakdef != NULL)
2834 {
2835 BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
2836 || h->weakdef->root.type == bfd_link_hash_defweak);
2837 h->root.u.def.section = h->weakdef->root.u.def.section;
2838 h->root.u.def.value = h->weakdef->root.u.def.value;
b34976b6 2839 return TRUE;
800eeca4
JW
2840 }
2841
2842 /* If this is a reference to a symbol defined by a dynamic object which
2843 is not a function, we might allocate the symbol in our .dynbss section
2844 and allocate a COPY dynamic relocation.
2845
2846 But IA-64 code is canonically PIC, so as a rule we can avoid this sort
2847 of hackery. */
2848
b34976b6 2849 return TRUE;
800eeca4
JW
2850}
2851
b34976b6 2852static bfd_boolean
bbe66d08 2853elfNN_ia64_size_dynamic_sections (output_bfd, info)
800eeca4
JW
2854 bfd *output_bfd;
2855 struct bfd_link_info *info;
2856{
bbe66d08
JW
2857 struct elfNN_ia64_allocate_data data;
2858 struct elfNN_ia64_link_hash_table *ia64_info;
800eeca4
JW
2859 asection *sec;
2860 bfd *dynobj;
b34976b6 2861 bfd_boolean relplt = FALSE;
800eeca4
JW
2862
2863 dynobj = elf_hash_table(info)->dynobj;
bbe66d08 2864 ia64_info = elfNN_ia64_hash_table (info);
b3dfd7fe 2865 ia64_info->self_dtpmod_offset = (bfd_vma) -1;
800eeca4
JW
2866 BFD_ASSERT(dynobj != NULL);
2867 data.info = info;
2868
2869 /* Set the contents of the .interp section to the interpreter. */
2870 if (ia64_info->root.dynamic_sections_created
2871 && !info->shared)
2872 {
2873 sec = bfd_get_section_by_name (dynobj, ".interp");
2874 BFD_ASSERT (sec != NULL);
7b6dab7f
TW
2875 sec->contents = (bfd_byte *) DYNAMIC_INTERPRETER (output_bfd);
2876 sec->_raw_size = strlen (DYNAMIC_INTERPRETER (output_bfd)) + 1;
800eeca4
JW
2877 }
2878
800eeca4
JW
2879 /* Allocate the GOT entries. */
2880
2881 if (ia64_info->got_sec)
2882 {
2883 data.ofs = 0;
bbe66d08
JW
2884 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_data_got, &data);
2885 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_fptr_got, &data);
2886 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_local_got, &data);
800eeca4
JW
2887 ia64_info->got_sec->_raw_size = data.ofs;
2888 }
2889
2890 /* Allocate the FPTR entries. */
2891
2892 if (ia64_info->fptr_sec)
2893 {
2894 data.ofs = 0;
bbe66d08 2895 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_fptr, &data);
800eeca4
JW
2896 ia64_info->fptr_sec->_raw_size = data.ofs;
2897 }
2898
2899 /* Now that we've seen all of the input files, we can decide which
2900 symbols need plt entries. Allocate the minimal PLT entries first.
b34976b6 2901 We do this even though dynamic_sections_created may be FALSE, because
800eeca4
JW
2902 this has the side-effect of clearing want_plt and want_plt2. */
2903
2904 data.ofs = 0;
bbe66d08 2905 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_plt_entries, &data);
800eeca4
JW
2906
2907 ia64_info->minplt_entries = 0;
2908 if (data.ofs)
2909 {
2910 ia64_info->minplt_entries
2911 = (data.ofs - PLT_HEADER_SIZE) / PLT_MIN_ENTRY_SIZE;
2912 }
2913
2914 /* Align the pointer for the plt2 entries. */
dc810e39 2915 data.ofs = (data.ofs + 31) & (bfd_vma) -32;
800eeca4 2916
bbe66d08 2917 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_plt2_entries, &data);
800eeca4
JW
2918 if (data.ofs != 0)
2919 {
2920 BFD_ASSERT (ia64_info->root.dynamic_sections_created);
2921
2922 ia64_info->plt_sec->_raw_size = data.ofs;
2923
2924 /* If we've got a .plt, we need some extra memory for the dynamic
2925 linker. We stuff these in .got.plt. */
2926 sec = bfd_get_section_by_name (dynobj, ".got.plt");
2927 sec->_raw_size = 8 * PLT_RESERVED_WORDS;
2928 }
2929
2930 /* Allocate the PLTOFF entries. */
2931
2932 if (ia64_info->pltoff_sec)
2933 {
2934 data.ofs = 0;
bbe66d08 2935 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_pltoff_entries, &data);
800eeca4
JW
2936 ia64_info->pltoff_sec->_raw_size = data.ofs;
2937 }
2938
2939 if (ia64_info->root.dynamic_sections_created)
2940 {
2941 /* Allocate space for the dynamic relocations that turned out to be
2942 required. */
2943
b3dfd7fe
JJ
2944 if (info->shared && ia64_info->self_dtpmod_offset != (bfd_vma) -1)
2945 ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
bbe66d08 2946 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_dynrel_entries, &data);
800eeca4
JW
2947 }
2948
2949 /* We have now determined the sizes of the various dynamic sections.
2950 Allocate memory for them. */
2951 for (sec = dynobj->sections; sec != NULL; sec = sec->next)
2952 {
b34976b6 2953 bfd_boolean strip;
800eeca4
JW
2954
2955 if (!(sec->flags & SEC_LINKER_CREATED))
2956 continue;
2957
2958 /* If we don't need this section, strip it from the output file.
2959 There were several sections primarily related to dynamic
2960 linking that must be create before the linker maps input
2961 sections to output sections. The linker does that before
2962 bfd_elf_size_dynamic_sections is called, and it is that
2963 function which decides whether anything needs to go into
2964 these sections. */
2965
2966 strip = (sec->_raw_size == 0);
2967
2968 if (sec == ia64_info->got_sec)
b34976b6 2969 strip = FALSE;
800eeca4
JW
2970 else if (sec == ia64_info->rel_got_sec)
2971 {
2972 if (strip)
2973 ia64_info->rel_got_sec = NULL;
2974 else
2975 /* We use the reloc_count field as a counter if we need to
2976 copy relocs into the output file. */
2977 sec->reloc_count = 0;
2978 }
2979 else if (sec == ia64_info->fptr_sec)
2980 {
2981 if (strip)
2982 ia64_info->fptr_sec = NULL;
2983 }
2984 else if (sec == ia64_info->plt_sec)
2985 {
2986 if (strip)
2987 ia64_info->plt_sec = NULL;
2988 }
2989 else if (sec == ia64_info->pltoff_sec)
2990 {
2991 if (strip)
2992 ia64_info->pltoff_sec = NULL;
2993 }
2994 else if (sec == ia64_info->rel_pltoff_sec)
2995 {
2996 if (strip)
2997 ia64_info->rel_pltoff_sec = NULL;
2998 else
2999 {
b34976b6 3000 relplt = TRUE;
800eeca4
JW
3001 /* We use the reloc_count field as a counter if we need to
3002 copy relocs into the output file. */
3003 sec->reloc_count = 0;
3004 }
3005 }
3006 else
3007 {
3008 const char *name;
3009
3010 /* It's OK to base decisions on the section name, because none
3011 of the dynobj section names depend upon the input files. */
3012 name = bfd_get_section_name (dynobj, sec);
3013
3014 if (strcmp (name, ".got.plt") == 0)
b34976b6 3015 strip = FALSE;
800eeca4
JW
3016 else if (strncmp (name, ".rel", 4) == 0)
3017 {
3018 if (!strip)
3019 {
800eeca4
JW
3020 /* We use the reloc_count field as a counter if we need to
3021 copy relocs into the output file. */
3022 sec->reloc_count = 0;
3023 }
3024 }
3025 else
3026 continue;
3027 }
3028
3029 if (strip)
3030 _bfd_strip_section_from_output (info, sec);
3031 else
3032 {
3033 /* Allocate memory for the section contents. */
dc810e39 3034 sec->contents = (bfd_byte *) bfd_zalloc (dynobj, sec->_raw_size);
800eeca4 3035 if (sec->contents == NULL && sec->_raw_size != 0)
b34976b6 3036 return FALSE;
800eeca4
JW
3037 }
3038 }
3039
3040 if (elf_hash_table (info)->dynamic_sections_created)
3041 {
3042 /* Add some entries to the .dynamic section. We fill in the values
3043 later (in finish_dynamic_sections) but we must add the entries now
3044 so that we get the correct size for the .dynamic section. */
3045
3046 if (!info->shared)
3047 {
3048 /* The DT_DEBUG entry is filled in by the dynamic linker and used
3049 by the debugger. */
dc810e39
AM
3050#define add_dynamic_entry(TAG, VAL) \
3051 bfd_elfNN_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
3052
3053 if (!add_dynamic_entry (DT_DEBUG, 0))
b34976b6 3054 return FALSE;
800eeca4
JW
3055 }
3056
dc810e39 3057 if (!add_dynamic_entry (DT_IA_64_PLT_RESERVE, 0))
b34976b6 3058 return FALSE;
dc810e39 3059 if (!add_dynamic_entry (DT_PLTGOT, 0))
b34976b6 3060 return FALSE;
800eeca4
JW
3061
3062 if (relplt)
3063 {
dc810e39
AM
3064 if (!add_dynamic_entry (DT_PLTRELSZ, 0)
3065 || !add_dynamic_entry (DT_PLTREL, DT_RELA)
3066 || !add_dynamic_entry (DT_JMPREL, 0))
b34976b6 3067 return FALSE;
800eeca4
JW
3068 }
3069
dc810e39
AM
3070 if (!add_dynamic_entry (DT_RELA, 0)
3071 || !add_dynamic_entry (DT_RELASZ, 0)
3072 || !add_dynamic_entry (DT_RELAENT, sizeof (ElfNN_External_Rela)))
b34976b6 3073 return FALSE;
800eeca4 3074
db6751f2 3075 if (ia64_info->reltext)
800eeca4 3076 {
dc810e39 3077 if (!add_dynamic_entry (DT_TEXTREL, 0))
b34976b6 3078 return FALSE;
d6cf2879 3079 info->flags |= DF_TEXTREL;
800eeca4
JW
3080 }
3081 }
3082
3083 /* ??? Perhaps force __gp local. */
3084
b34976b6 3085 return TRUE;
800eeca4
JW
3086}
3087
3088static bfd_reloc_status_type
1e738b87 3089elfNN_ia64_install_value (abfd, hit_addr, v, r_type)
800eeca4
JW
3090 bfd *abfd;
3091 bfd_byte *hit_addr;
1e738b87 3092 bfd_vma v;
800eeca4
JW
3093 unsigned int r_type;
3094{
3095 const struct ia64_operand *op;
3096 int bigendian = 0, shift = 0;
3097 bfd_vma t0, t1, insn, dword;
3098 enum ia64_opnd opnd;
3099 const char *err;
3100 size_t size = 8;
1e738b87
NC
3101#ifdef BFD_HOST_U_64_BIT
3102 BFD_HOST_U_64_BIT val = (BFD_HOST_U_64_BIT) v;
3103#else
3104 bfd_vma val = v;
3105#endif
800eeca4
JW
3106
3107 opnd = IA64_OPND_NIL;
3108 switch (r_type)
3109 {
3110 case R_IA64_NONE:
3111 case R_IA64_LDXMOV:
3112 return bfd_reloc_ok;
3113
3e932841 3114 /* Instruction relocations. */
800eeca4 3115
13ae64f3
JJ
3116 case R_IA64_IMM14:
3117 case R_IA64_TPREL14:
3118 case R_IA64_DTPREL14:
3119 opnd = IA64_OPND_IMM14;
3120 break;
748abff6 3121
800eeca4
JW
3122 case R_IA64_PCREL21F: opnd = IA64_OPND_TGT25; break;
3123 case R_IA64_PCREL21M: opnd = IA64_OPND_TGT25b; break;
748abff6
RH
3124 case R_IA64_PCREL60B: opnd = IA64_OPND_TGT64; break;
3125 case R_IA64_PCREL21B:
3126 case R_IA64_PCREL21BI:
3127 opnd = IA64_OPND_TGT25c;
3128 break;
800eeca4
JW
3129
3130 case R_IA64_IMM22:
3131 case R_IA64_GPREL22:
3132 case R_IA64_LTOFF22:
3133 case R_IA64_LTOFF22X:
3134 case R_IA64_PLTOFF22:
748abff6 3135 case R_IA64_PCREL22:
800eeca4 3136 case R_IA64_LTOFF_FPTR22:
13ae64f3
JJ
3137 case R_IA64_TPREL22:
3138 case R_IA64_DTPREL22:
3139 case R_IA64_LTOFF_TPREL22:
3140 case R_IA64_LTOFF_DTPMOD22:
3141 case R_IA64_LTOFF_DTPREL22:
800eeca4
JW
3142 opnd = IA64_OPND_IMM22;
3143 break;
3144
3145 case R_IA64_IMM64:
3146 case R_IA64_GPREL64I:
3147 case R_IA64_LTOFF64I:
3148 case R_IA64_PLTOFF64I:
748abff6 3149 case R_IA64_PCREL64I:
800eeca4
JW
3150 case R_IA64_FPTR64I:
3151 case R_IA64_LTOFF_FPTR64I:
13ae64f3
JJ
3152 case R_IA64_TPREL64I:
3153 case R_IA64_DTPREL64I:
800eeca4
JW
3154 opnd = IA64_OPND_IMMU64;
3155 break;
3156
3157 /* Data relocations. */
3158
3159 case R_IA64_DIR32MSB:
3160 case R_IA64_GPREL32MSB:
3161 case R_IA64_FPTR32MSB:
3162 case R_IA64_PCREL32MSB:
a4bd8390 3163 case R_IA64_LTOFF_FPTR32MSB:
800eeca4
JW
3164 case R_IA64_SEGREL32MSB:
3165 case R_IA64_SECREL32MSB:
3166 case R_IA64_LTV32MSB:
13ae64f3 3167 case R_IA64_DTPREL32MSB:
800eeca4
JW
3168 size = 4; bigendian = 1;
3169 break;
3170
3171 case R_IA64_DIR32LSB:
3172 case R_IA64_GPREL32LSB:
3173 case R_IA64_FPTR32LSB:
3174 case R_IA64_PCREL32LSB:
a4bd8390 3175 case R_IA64_LTOFF_FPTR32LSB:
800eeca4
JW
3176 case R_IA64_SEGREL32LSB:
3177 case R_IA64_SECREL32LSB:
3178 case R_IA64_LTV32LSB:
13ae64f3 3179 case R_IA64_DTPREL32LSB:
800eeca4
JW
3180 size = 4; bigendian = 0;
3181 break;
3182
3183 case R_IA64_DIR64MSB:
3184 case R_IA64_GPREL64MSB:
3185 case R_IA64_PLTOFF64MSB:
3186 case R_IA64_FPTR64MSB:
3187 case R_IA64_PCREL64MSB:
3188 case R_IA64_LTOFF_FPTR64MSB:
3189 case R_IA64_SEGREL64MSB:
3190 case R_IA64_SECREL64MSB:
3191 case R_IA64_LTV64MSB:
13ae64f3
JJ
3192 case R_IA64_TPREL64MSB:
3193 case R_IA64_DTPMOD64MSB:
3194 case R_IA64_DTPREL64MSB:
800eeca4
JW
3195 size = 8; bigendian = 1;
3196 break;
3197
3198 case R_IA64_DIR64LSB:
3199 case R_IA64_GPREL64LSB:
3200 case R_IA64_PLTOFF64LSB:
3201 case R_IA64_FPTR64LSB:
3202 case R_IA64_PCREL64LSB:
3203 case R_IA64_LTOFF_FPTR64LSB:
3204 case R_IA64_SEGREL64LSB:
3205 case R_IA64_SECREL64LSB:
3206 case R_IA64_LTV64LSB:
13ae64f3
JJ
3207 case R_IA64_TPREL64LSB:
3208 case R_IA64_DTPMOD64LSB:
3209 case R_IA64_DTPREL64LSB:
800eeca4
JW
3210 size = 8; bigendian = 0;
3211 break;
3212
3213 /* Unsupported / Dynamic relocations. */
800eeca4
JW
3214 default:
3215 return bfd_reloc_notsupported;
3216 }
3217
3218 switch (opnd)
3219 {
3220 case IA64_OPND_IMMU64:
3221 hit_addr -= (long) hit_addr & 0x3;
3222 t0 = bfd_get_64 (abfd, hit_addr);
3223 t1 = bfd_get_64 (abfd, hit_addr + 8);
3224
3225 /* tmpl/s: bits 0.. 5 in t0
3226 slot 0: bits 5..45 in t0
3227 slot 1: bits 46..63 in t0, bits 0..22 in t1
3228 slot 2: bits 23..63 in t1 */
3229
3230 /* First, clear the bits that form the 64 bit constant. */
3231 t0 &= ~(0x3ffffLL << 46);
3232 t1 &= ~(0x7fffffLL
3233 | (( (0x07fLL << 13) | (0x1ffLL << 27)
3234 | (0x01fLL << 22) | (0x001LL << 21)
3235 | (0x001LL << 36)) << 23));
3236
3237 t0 |= ((val >> 22) & 0x03ffffLL) << 46; /* 18 lsbs of imm41 */
3238 t1 |= ((val >> 40) & 0x7fffffLL) << 0; /* 23 msbs of imm41 */
3239 t1 |= ( (((val >> 0) & 0x07f) << 13) /* imm7b */
3240 | (((val >> 7) & 0x1ff) << 27) /* imm9d */
3241 | (((val >> 16) & 0x01f) << 22) /* imm5c */
3242 | (((val >> 21) & 0x001) << 21) /* ic */
3243 | (((val >> 63) & 0x001) << 36)) << 23; /* i */
3244
3245 bfd_put_64 (abfd, t0, hit_addr);
3246 bfd_put_64 (abfd, t1, hit_addr + 8);
3247 break;
3248
748abff6
RH
3249 case IA64_OPND_TGT64:
3250 hit_addr -= (long) hit_addr & 0x3;
3251 t0 = bfd_get_64 (abfd, hit_addr);
3252 t1 = bfd_get_64 (abfd, hit_addr + 8);
3253
3254 /* tmpl/s: bits 0.. 5 in t0
3255 slot 0: bits 5..45 in t0
3256 slot 1: bits 46..63 in t0, bits 0..22 in t1
3257 slot 2: bits 23..63 in t1 */
3258
3259 /* First, clear the bits that form the 64 bit constant. */
3260 t0 &= ~(0x3ffffLL << 46);
3261 t1 &= ~(0x7fffffLL
3262 | ((1LL << 36 | 0xfffffLL << 13) << 23));
3263
3264 val >>= 4;
3265 t0 |= ((val >> 20) & 0xffffLL) << 2 << 46; /* 16 lsbs of imm39 */
3266 t1 |= ((val >> 36) & 0x7fffffLL) << 0; /* 23 msbs of imm39 */
3267 t1 |= ((((val >> 0) & 0xfffffLL) << 13) /* imm20b */
3268 | (((val >> 59) & 0x1LL) << 36)) << 23; /* i */
3269
3270 bfd_put_64 (abfd, t0, hit_addr);
3271 bfd_put_64 (abfd, t1, hit_addr + 8);
3272 break;
3273
800eeca4
JW
3274 default:
3275 switch ((long) hit_addr & 0x3)
3276 {
3277 case 0: shift = 5; break;
3278 case 1: shift = 14; hit_addr += 3; break;
3279 case 2: shift = 23; hit_addr += 6; break;
3e932841 3280 case 3: return bfd_reloc_notsupported; /* shouldn't happen... */
800eeca4
JW
3281 }
3282 dword = bfd_get_64 (abfd, hit_addr);
3283 insn = (dword >> shift) & 0x1ffffffffffLL;
3284
3285 op = elf64_ia64_operands + opnd;
1e738b87 3286 err = (*op->insert) (op, val, (ia64_insn *)& insn);
800eeca4
JW
3287 if (err)
3288 return bfd_reloc_overflow;
3289
3290 dword &= ~(0x1ffffffffffLL << shift);
3291 dword |= (insn << shift);
3292 bfd_put_64 (abfd, dword, hit_addr);
3293 break;
3294
3295 case IA64_OPND_NIL:
3296 /* A data relocation. */
3297 if (bigendian)
3298 if (size == 4)
3299 bfd_putb32 (val, hit_addr);
3300 else
3301 bfd_putb64 (val, hit_addr);
3302 else
3303 if (size == 4)
3304 bfd_putl32 (val, hit_addr);
3305 else
3306 bfd_putl64 (val, hit_addr);
3307 break;
3308 }
3309
3310 return bfd_reloc_ok;
3311}
3312
3313static void
bbe66d08 3314elfNN_ia64_install_dyn_reloc (abfd, info, sec, srel, offset, type,
800eeca4
JW
3315 dynindx, addend)
3316 bfd *abfd;
3317 struct bfd_link_info *info;
3318 asection *sec;
3319 asection *srel;
3320 bfd_vma offset;
3321 unsigned int type;
3322 long dynindx;
3323 bfd_vma addend;
3324{
3325 Elf_Internal_Rela outrel;
947216bf 3326 bfd_byte *loc;
800eeca4 3327
800eeca4 3328 BFD_ASSERT (dynindx != -1);
bbe66d08 3329 outrel.r_info = ELFNN_R_INFO (dynindx, type);
800eeca4 3330 outrel.r_addend = addend;
c629eae0 3331 outrel.r_offset = _bfd_elf_section_offset (abfd, info, sec, offset);
99eb2ac8 3332 if (outrel.r_offset >= (bfd_vma) -2)
800eeca4 3333 {
c629eae0
JJ
3334 /* Run for the hills. We shouldn't be outputting a relocation
3335 for this. So do what everyone else does and output a no-op. */
3336 outrel.r_info = ELFNN_R_INFO (0, R_IA64_NONE);
3337 outrel.r_addend = 0;
3338 outrel.r_offset = 0;
800eeca4 3339 }
99eb2ac8
AM
3340 else
3341 outrel.r_offset += sec->output_section->vma + sec->output_offset;
800eeca4 3342
947216bf
AM
3343 loc = srel->contents;
3344 loc += srel->reloc_count++ * sizeof (ElfNN_External_Rela);
3345 bfd_elfNN_swap_reloca_out (abfd, &outrel, loc);
3e932841 3346 BFD_ASSERT (sizeof (ElfNN_External_Rela) * srel->reloc_count
800eeca4
JW
3347 <= srel->_cooked_size);
3348}
3349
3350/* Store an entry for target address TARGET_ADDR in the linkage table
3351 and return the gp-relative address of the linkage table entry. */
3352
3353static bfd_vma
3354set_got_entry (abfd, info, dyn_i, dynindx, addend, value, dyn_r_type)
3355 bfd *abfd;
3356 struct bfd_link_info *info;
bbe66d08 3357 struct elfNN_ia64_dyn_sym_info *dyn_i;
800eeca4
JW
3358 long dynindx;
3359 bfd_vma addend;
3360 bfd_vma value;
3361 unsigned int dyn_r_type;
3362{
bbe66d08 3363 struct elfNN_ia64_link_hash_table *ia64_info;
800eeca4 3364 asection *got_sec;
b34976b6 3365 bfd_boolean done;
13ae64f3 3366 bfd_vma got_offset;
800eeca4 3367
bbe66d08 3368 ia64_info = elfNN_ia64_hash_table (info);
800eeca4
JW
3369 got_sec = ia64_info->got_sec;
3370
13ae64f3 3371 switch (dyn_r_type)
800eeca4 3372 {
13ae64f3
JJ
3373 case R_IA64_TPREL64LSB:
3374 done = dyn_i->tprel_done;
b34976b6 3375 dyn_i->tprel_done = TRUE;
13ae64f3
JJ
3376 got_offset = dyn_i->tprel_offset;
3377 break;
3378 case R_IA64_DTPMOD64LSB:
b3dfd7fe
JJ
3379 if (dyn_i->dtpmod_offset != ia64_info->self_dtpmod_offset)
3380 {
3381 done = dyn_i->dtpmod_done;
3382 dyn_i->dtpmod_done = TRUE;
3383 }
3384 else
3385 {
3386 done = ia64_info->self_dtpmod_done;
3387 ia64_info->self_dtpmod_done = TRUE;
3388 dynindx = 0;
3389 }
13ae64f3
JJ
3390 got_offset = dyn_i->dtpmod_offset;
3391 break;
3392 case R_IA64_DTPREL64LSB:
3393 done = dyn_i->dtprel_done;
b34976b6 3394 dyn_i->dtprel_done = TRUE;
13ae64f3
JJ
3395 got_offset = dyn_i->dtprel_offset;
3396 break;
3397 default:
3398 done = dyn_i->got_done;
b34976b6 3399 dyn_i->got_done = TRUE;
13ae64f3
JJ
3400 got_offset = dyn_i->got_offset;
3401 break;
3402 }
800eeca4 3403
13ae64f3
JJ
3404 BFD_ASSERT ((got_offset & 7) == 0);
3405
3406 if (! done)
3407 {
800eeca4 3408 /* Store the target address in the linkage table entry. */
13ae64f3 3409 bfd_put_64 (abfd, value, got_sec->contents + got_offset);
800eeca4
JW
3410
3411 /* Install a dynamic relocation if needed. */
13ae64f3 3412 if ((info->shared && dyn_r_type != R_IA64_DTPREL64LSB)
bbe66d08 3413 || elfNN_ia64_dynamic_symbol_p (dyn_i->h, info)
7b6dab7f 3414 || elfNN_ia64_aix_vec (abfd->xvec)
800eeca4
JW
3415 || (dynindx != -1 && dyn_r_type == R_IA64_FPTR64LSB))
3416 {
13ae64f3
JJ
3417 if (dynindx == -1
3418 && dyn_r_type != R_IA64_TPREL64LSB
3419 && dyn_r_type != R_IA64_DTPMOD64LSB
3420 && dyn_r_type != R_IA64_DTPREL64LSB)
800eeca4
JW
3421 {
3422 dyn_r_type = R_IA64_REL64LSB;
3423 dynindx = 0;
3424 addend = value;
3425 }
3426
3427 if (bfd_big_endian (abfd))
3428 {
3429 switch (dyn_r_type)
3430 {
3431 case R_IA64_REL64LSB:
3432 dyn_r_type = R_IA64_REL64MSB;
3433 break;
3434 case R_IA64_DIR64LSB:
3435 dyn_r_type = R_IA64_DIR64MSB;
3436 break;
3437 case R_IA64_FPTR64LSB:
3438 dyn_r_type = R_IA64_FPTR64MSB;
3439 break;
13ae64f3
JJ
3440 case R_IA64_TPREL64LSB:
3441 dyn_r_type = R_IA64_TPREL64MSB;
3442 break;
3443 case R_IA64_DTPMOD64LSB:
3444 dyn_r_type = R_IA64_DTPMOD64MSB;
3445 break;
3446 case R_IA64_DTPREL64LSB:
3447 dyn_r_type = R_IA64_DTPREL64MSB;
3448 break;
800eeca4 3449 default:
b34976b6 3450 BFD_ASSERT (FALSE);
800eeca4
JW
3451 break;
3452 }
3453 }
3454
bbe66d08 3455 elfNN_ia64_install_dyn_reloc (abfd, NULL, got_sec,
800eeca4 3456 ia64_info->rel_got_sec,
13ae64f3 3457 got_offset, dyn_r_type,
800eeca4
JW
3458 dynindx, addend);
3459 }
3460 }
3461
3462 /* Return the address of the linkage table entry. */
3463 value = (got_sec->output_section->vma
3464 + got_sec->output_offset
13ae64f3 3465 + got_offset);
800eeca4
JW
3466
3467 return value;
3468}
3469
3470/* Fill in a function descriptor consisting of the function's code
3471 address and its global pointer. Return the descriptor's address. */
3472
3473static bfd_vma
3474set_fptr_entry (abfd, info, dyn_i, value)
3475 bfd *abfd;
3476 struct bfd_link_info *info;
bbe66d08 3477 struct elfNN_ia64_dyn_sym_info *dyn_i;
800eeca4
JW
3478 bfd_vma value;
3479{
bbe66d08 3480 struct elfNN_ia64_link_hash_table *ia64_info;
800eeca4
JW
3481 asection *fptr_sec;
3482
bbe66d08 3483 ia64_info = elfNN_ia64_hash_table (info);
800eeca4
JW
3484 fptr_sec = ia64_info->fptr_sec;
3485
3486 if (!dyn_i->fptr_done)
3487 {
3488 dyn_i->fptr_done = 1;
3489
3490 /* Fill in the function descriptor. */
3491 bfd_put_64 (abfd, value, fptr_sec->contents + dyn_i->fptr_offset);
3492 bfd_put_64 (abfd, _bfd_get_gp_value (abfd),
3493 fptr_sec->contents + dyn_i->fptr_offset + 8);
3494 }
3495
3496 /* Return the descriptor's address. */
3497 value = (fptr_sec->output_section->vma
3498 + fptr_sec->output_offset
3499 + dyn_i->fptr_offset);
3500
3501 return value;
3502}
3503
3504/* Fill in a PLTOFF entry consisting of the function's code address
3505 and its global pointer. Return the descriptor's address. */
3506
3507static bfd_vma
3508set_pltoff_entry (abfd, info, dyn_i, value, is_plt)
3509 bfd *abfd;
3510 struct bfd_link_info *info;
bbe66d08 3511 struct elfNN_ia64_dyn_sym_info *dyn_i;
800eeca4 3512 bfd_vma value;
b34976b6 3513 bfd_boolean is_plt;
800eeca4 3514{
bbe66d08 3515 struct elfNN_ia64_link_hash_table *ia64_info;
800eeca4
JW
3516 asection *pltoff_sec;
3517
bbe66d08 3518 ia64_info = elfNN_ia64_hash_table (info);
800eeca4
JW
3519 pltoff_sec = ia64_info->pltoff_sec;
3520
3521 /* Don't do anything if this symbol uses a real PLT entry. In
3522 that case, we'll fill this in during finish_dynamic_symbol. */
3523 if ((! dyn_i->want_plt || is_plt)
3524 && !dyn_i->pltoff_done)
3525 {
18b27f17
RH
3526 bfd_vma gp = _bfd_get_gp_value (abfd);
3527
800eeca4
JW
3528 /* Fill in the function descriptor. */
3529 bfd_put_64 (abfd, value, pltoff_sec->contents + dyn_i->pltoff_offset);
18b27f17 3530 bfd_put_64 (abfd, gp, pltoff_sec->contents + dyn_i->pltoff_offset + 8);
800eeca4
JW
3531
3532 /* Install dynamic relocations if needed. */
3533 if (!is_plt && info->shared)
3534 {
3535 unsigned int dyn_r_type;
3536
3537 if (bfd_big_endian (abfd))
3538 dyn_r_type = R_IA64_REL64MSB;
3539 else
3540 dyn_r_type = R_IA64_REL64LSB;
3541
bbe66d08 3542 elfNN_ia64_install_dyn_reloc (abfd, NULL, pltoff_sec,
800eeca4
JW
3543 ia64_info->rel_pltoff_sec,
3544 dyn_i->pltoff_offset,
18b27f17 3545 dyn_r_type, 0, value);
bbe66d08 3546 elfNN_ia64_install_dyn_reloc (abfd, NULL, pltoff_sec,
800eeca4
JW
3547 ia64_info->rel_pltoff_sec,
3548 dyn_i->pltoff_offset + 8,
18b27f17 3549 dyn_r_type, 0, gp);
800eeca4
JW
3550 }
3551
3552 dyn_i->pltoff_done = 1;
3553 }
3554
3555 /* Return the descriptor's address. */
3556 value = (pltoff_sec->output_section->vma
3557 + pltoff_sec->output_offset
3558 + dyn_i->pltoff_offset);
3559
3560 return value;
3561}
3562
13ae64f3
JJ
3563/* Return the base VMA address which should be subtracted from real addresses
3564 when resolving @tprel() relocation.
3565 Main program TLS (whose template starts at PT_TLS p_vaddr)
3566 is assigned offset round(16, PT_TLS p_align). */
3567
3568static bfd_vma
3569elfNN_ia64_tprel_base (info)
3570 struct bfd_link_info *info;
3571{
3572 struct elf_link_tls_segment *tls_segment
3573 = elf_hash_table (info)->tls_segment;
3574
3575 BFD_ASSERT (tls_segment != NULL);
3576 return (tls_segment->start
3577 - align_power ((bfd_vma) 16, tls_segment->align));
3578}
3579
3580/* Return the base VMA address which should be subtracted from real addresses
3581 when resolving @dtprel() relocation.
3582 This is PT_TLS segment p_vaddr. */
3583
3584static bfd_vma
3585elfNN_ia64_dtprel_base (info)
3586 struct bfd_link_info *info;
3587{
3588 BFD_ASSERT (elf_hash_table (info)->tls_segment != NULL);
3589 return elf_hash_table (info)->tls_segment->start;
3590}
3591
f3b6f7c3 3592/* Called through qsort to sort the .IA_64.unwind section during a
bbe66d08 3593 non-relocatable link. Set elfNN_ia64_unwind_entry_compare_bfd
f3b6f7c3
RH
3594 to the output bfd so we can do proper endianness frobbing. */
3595
bbe66d08 3596static bfd *elfNN_ia64_unwind_entry_compare_bfd;
f3b6f7c3
RH
3597
3598static int
bbe66d08 3599elfNN_ia64_unwind_entry_compare (a, b)
cea4409c
AM
3600 const PTR a;
3601 const PTR b;
f3b6f7c3
RH
3602{
3603 bfd_vma av, bv;
3604
bbe66d08
JW
3605 av = bfd_get_64 (elfNN_ia64_unwind_entry_compare_bfd, a);
3606 bv = bfd_get_64 (elfNN_ia64_unwind_entry_compare_bfd, b);
f3b6f7c3
RH
3607
3608 return (av < bv ? -1 : av > bv ? 1 : 0);
3609}
3610
2c4c2bc0 3611/* Make sure we've got ourselves a nice fat __gp value. */
b34976b6 3612static bfd_boolean
2c4c2bc0 3613elfNN_ia64_choose_gp (abfd, info)
800eeca4
JW
3614 bfd *abfd;
3615 struct bfd_link_info *info;
3616{
2c4c2bc0
RH
3617 bfd_vma min_vma = (bfd_vma) -1, max_vma = 0;
3618 bfd_vma min_short_vma = min_vma, max_short_vma = 0;
3619 struct elf_link_hash_entry *gp;
3620 bfd_vma gp_val;
3621 asection *os;
bbe66d08 3622 struct elfNN_ia64_link_hash_table *ia64_info;
9a951beb 3623
bbe66d08 3624 ia64_info = elfNN_ia64_hash_table (info);
800eeca4 3625
2c4c2bc0
RH
3626 /* Find the min and max vma of all sections marked short. Also collect
3627 min and max vma of any type, for use in selecting a nice gp. */
3628 for (os = abfd->sections; os ; os = os->next)
800eeca4 3629 {
2c4c2bc0 3630 bfd_vma lo, hi;
800eeca4 3631
2c4c2bc0
RH
3632 if ((os->flags & SEC_ALLOC) == 0)
3633 continue;
3634
3635 lo = os->vma;
3636 hi = os->vma + os->_raw_size;
3637 if (hi < lo)
3638 hi = (bfd_vma) -1;
3639
3640 if (min_vma > lo)
3641 min_vma = lo;
3642 if (max_vma < hi)
3643 max_vma = hi;
3644 if (os->flags & SEC_SMALL_DATA)
800eeca4 3645 {
2c4c2bc0
RH
3646 if (min_short_vma > lo)
3647 min_short_vma = lo;
3648 if (max_short_vma < hi)
3649 max_short_vma = hi;
3650 }
3651 }
800eeca4 3652
2c4c2bc0
RH
3653 /* See if the user wants to force a value. */
3654 gp = elf_link_hash_lookup (elf_hash_table (info), "__gp", FALSE,
3655 FALSE, FALSE);
800eeca4 3656
2c4c2bc0
RH
3657 if (gp
3658 && (gp->root.type == bfd_link_hash_defined
3659 || gp->root.type == bfd_link_hash_defweak))
3660 {
3661 asection *gp_sec = gp->root.u.def.section;
3662 gp_val = (gp->root.u.def.value
3663 + gp_sec->output_section->vma
3664 + gp_sec->output_offset);
3665 }
3666 else
3667 {
3668 /* Pick a sensible value. */
800eeca4 3669
2c4c2bc0
RH
3670 asection *got_sec = ia64_info->got_sec;
3671
3672 /* Start with just the address of the .got. */
3673 if (got_sec)
3674 gp_val = got_sec->output_section->vma;
3675 else if (max_short_vma != 0)
3676 gp_val = min_short_vma;
3677 else
3678 gp_val = min_vma;
3679
3680 /* If it is possible to address the entire image, but we
3681 don't with the choice above, adjust. */
3682 if (max_vma - min_vma < 0x400000
3683 && max_vma - gp_val <= 0x200000
3684 && gp_val - min_vma > 0x200000)
3685 gp_val = min_vma + 0x200000;
3686 else if (max_short_vma != 0)
3687 {
3688 /* If we don't cover all the short data, adjust. */
3689 if (max_short_vma - gp_val >= 0x200000)
3690 gp_val = min_short_vma + 0x200000;
3691
3692 /* If we're addressing stuff past the end, adjust back. */
3693 if (gp_val > max_vma)
3694 gp_val = max_vma - 0x200000 + 8;
800eeca4 3695 }
2c4c2bc0 3696 }
800eeca4 3697
2c4c2bc0
RH
3698 /* Validate whether all SHF_IA_64_SHORT sections are within
3699 range of the chosen GP. */
800eeca4 3700
2c4c2bc0
RH
3701 if (max_short_vma != 0)
3702 {
3703 if (max_short_vma - min_short_vma >= 0x400000)
800eeca4 3704 {
2c4c2bc0
RH
3705 (*_bfd_error_handler)
3706 (_("%s: short data segment overflowed (0x%lx >= 0x400000)"),
3707 bfd_get_filename (abfd),
3708 (unsigned long) (max_short_vma - min_short_vma));
3709 return FALSE;
800eeca4 3710 }
2c4c2bc0
RH
3711 else if ((gp_val > min_short_vma
3712 && gp_val - min_short_vma > 0x200000)
3713 || (gp_val < max_short_vma
3714 && max_short_vma - gp_val >= 0x200000))
800eeca4 3715 {
2c4c2bc0
RH
3716 (*_bfd_error_handler)
3717 (_("%s: __gp does not cover short data segment"),
3718 bfd_get_filename (abfd));
3719 return FALSE;
3720 }
3721 }
800eeca4 3722
2c4c2bc0 3723 _bfd_set_gp_value (abfd, gp_val);
800eeca4 3724
2c4c2bc0
RH
3725 return TRUE;
3726}
800eeca4 3727
2c4c2bc0
RH
3728static bfd_boolean
3729elfNN_ia64_final_link (abfd, info)
3730 bfd *abfd;
3731 struct bfd_link_info *info;
3732{
3733 struct elfNN_ia64_link_hash_table *ia64_info;
3734 asection *unwind_output_sec;
800eeca4 3735
2c4c2bc0 3736 ia64_info = elfNN_ia64_hash_table (info);
800eeca4 3737
2c4c2bc0
RH
3738 /* Make sure we've got ourselves a nice fat __gp value. */
3739 if (!info->relocateable)
3740 {
3741 bfd_vma gp_val = _bfd_get_gp_value (abfd);
3742 struct elf_link_hash_entry *gp;
3743
3744 if (gp_val == 0)
800eeca4 3745 {
2c4c2bc0
RH
3746 if (! elfNN_ia64_choose_gp (abfd, info))
3747 return FALSE;
3748 gp_val = _bfd_get_gp_value (abfd);
800eeca4
JW
3749 }
3750
2c4c2bc0
RH
3751 gp = elf_link_hash_lookup (elf_hash_table (info), "__gp", FALSE,
3752 FALSE, FALSE);
b4adccfd
RH
3753 if (gp)
3754 {
3755 gp->root.type = bfd_link_hash_defined;
3756 gp->root.u.def.value = gp_val;
3757 gp->root.u.def.section = bfd_abs_section_ptr;
3758 }
800eeca4
JW
3759 }
3760
f3b6f7c3 3761 /* If we're producing a final executable, we need to sort the contents
9a951beb
RH
3762 of the .IA_64.unwind section. Force this section to be relocated
3763 into memory rather than written immediately to the output file. */
3764 unwind_output_sec = NULL;
f3b6f7c3
RH
3765 if (!info->relocateable)
3766 {
3767 asection *s = bfd_get_section_by_name (abfd, ELF_STRING_ia64_unwind);
3768 if (s)
3769 {
9a951beb
RH
3770 unwind_output_sec = s->output_section;
3771 unwind_output_sec->contents
3772 = bfd_malloc (unwind_output_sec->_raw_size);
3773 if (unwind_output_sec->contents == NULL)
b34976b6 3774 return FALSE;
9a951beb
RH
3775 }
3776 }
f3b6f7c3 3777
9a951beb
RH
3778 /* Invoke the regular ELF backend linker to do all the work. */
3779 if (!bfd_elfNN_bfd_final_link (abfd, info))
b34976b6 3780 return FALSE;
f3b6f7c3 3781
9a951beb
RH
3782 if (unwind_output_sec)
3783 {
3784 elfNN_ia64_unwind_entry_compare_bfd = abfd;
dc810e39
AM
3785 qsort (unwind_output_sec->contents,
3786 (size_t) (unwind_output_sec->_raw_size / 24),
3787 24,
3788 elfNN_ia64_unwind_entry_compare);
9a951beb
RH
3789
3790 if (! bfd_set_section_contents (abfd, unwind_output_sec,
dc810e39 3791 unwind_output_sec->contents, (bfd_vma) 0,
9a951beb 3792 unwind_output_sec->_raw_size))
b34976b6 3793 return FALSE;
f3b6f7c3
RH
3794 }
3795
b34976b6 3796 return TRUE;
800eeca4
JW
3797}
3798
b34976b6 3799static bfd_boolean
bbe66d08 3800elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
800eeca4
JW
3801 contents, relocs, local_syms, local_sections)
3802 bfd *output_bfd;
3803 struct bfd_link_info *info;
3804 bfd *input_bfd;
3805 asection *input_section;
3806 bfd_byte *contents;
3807 Elf_Internal_Rela *relocs;
3808 Elf_Internal_Sym *local_syms;
3809 asection **local_sections;
3810{
bbe66d08 3811 struct elfNN_ia64_link_hash_table *ia64_info;
800eeca4
JW
3812 Elf_Internal_Shdr *symtab_hdr;
3813 Elf_Internal_Rela *rel;
3814 Elf_Internal_Rela *relend;
3815 asection *srel;
b34976b6 3816 bfd_boolean ret_val = TRUE; /* for non-fatal errors */
800eeca4
JW
3817 bfd_vma gp_val;
3818
3819 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
bbe66d08 3820 ia64_info = elfNN_ia64_hash_table (info);
800eeca4
JW
3821
3822 /* Infect various flags from the input section to the output section. */
3823 if (info->relocateable)
3824 {
3825 bfd_vma flags;
3826
3827 flags = elf_section_data(input_section)->this_hdr.sh_flags;
3828 flags &= SHF_IA_64_NORECOV;
3829
3830 elf_section_data(input_section->output_section)
3831 ->this_hdr.sh_flags |= flags;
b34976b6 3832 return TRUE;
800eeca4
JW
3833 }
3834
3835 gp_val = _bfd_get_gp_value (output_bfd);
b34976b6 3836 srel = get_reloc_section (input_bfd, ia64_info, input_section, FALSE);
800eeca4
JW
3837
3838 rel = relocs;
3839 relend = relocs + input_section->reloc_count;
3840 for (; rel < relend; ++rel)
3841 {
3842 struct elf_link_hash_entry *h;
bbe66d08 3843 struct elfNN_ia64_dyn_sym_info *dyn_i;
800eeca4
JW
3844 bfd_reloc_status_type r;
3845 reloc_howto_type *howto;
3846 unsigned long r_symndx;
3847 Elf_Internal_Sym *sym;
3848 unsigned int r_type;
3849 bfd_vma value;
3850 asection *sym_sec;
3851 bfd_byte *hit_addr;
b34976b6
AM
3852 bfd_boolean dynamic_symbol_p;
3853 bfd_boolean undef_weak_ref;
800eeca4 3854
bbe66d08 3855 r_type = ELFNN_R_TYPE (rel->r_info);
800eeca4
JW
3856 if (r_type > R_IA64_MAX_RELOC_CODE)
3857 {
3858 (*_bfd_error_handler)
3859 (_("%s: unknown relocation type %d"),
8f615d07 3860 bfd_archive_filename (input_bfd), (int)r_type);
800eeca4 3861 bfd_set_error (bfd_error_bad_value);
b34976b6 3862 ret_val = FALSE;
800eeca4
JW
3863 continue;
3864 }
b491616a 3865
800eeca4 3866 howto = lookup_howto (r_type);
bbe66d08 3867 r_symndx = ELFNN_R_SYM (rel->r_info);
800eeca4
JW
3868 h = NULL;
3869 sym = NULL;
3870 sym_sec = NULL;
b34976b6 3871 undef_weak_ref = FALSE;
800eeca4
JW
3872
3873 if (r_symndx < symtab_hdr->sh_info)
3874 {
3875 /* Reloc against local symbol. */
3876 sym = local_syms + r_symndx;
3877 sym_sec = local_sections[r_symndx];
f8df10f4 3878 value = _bfd_elf_rela_local_sym (output_bfd, sym, sym_sec, rel);
f7460f5f
JJ
3879 if ((sym_sec->flags & SEC_MERGE)
3880 && ELF_ST_TYPE (sym->st_info) == STT_SECTION
68bfbfcc 3881 && sym_sec->sec_info_type == ELF_INFO_TYPE_MERGE)
f7460f5f
JJ
3882 {
3883 struct elfNN_ia64_local_hash_entry *loc_h;
b34976b6
AM
3884
3885 loc_h = get_local_sym_hash (ia64_info, input_bfd, rel, FALSE);
f7460f5f
JJ
3886 if (loc_h && ! loc_h->sec_merge_done)
3887 {
3888 struct elfNN_ia64_dyn_sym_info *dynent;
3889 asection *msec;
3890
3891 for (dynent = loc_h->info; dynent; dynent = dynent->next)
3892 {
3893 msec = sym_sec;
3894 dynent->addend =
3895 _bfd_merged_section_offset (output_bfd, &msec,
3896 elf_section_data (msec)->
65765700 3897 sec_info,
f7460f5f
JJ
3898 sym->st_value
3899 + dynent->addend,
3900 (bfd_vma) 0);
3901 dynent->addend -= sym->st_value;
3902 dynent->addend += msec->output_section->vma
3903 + msec->output_offset
3904 - sym_sec->output_section->vma
3905 - sym_sec->output_offset;
3906 }
3907 loc_h->sec_merge_done = 1;
3908 }
3909 }
800eeca4
JW
3910 }
3911 else
3912 {
3913 long indx;
3914
3915 /* Reloc against global symbol. */
3916 indx = r_symndx - symtab_hdr->sh_info;
3917 h = elf_sym_hashes (input_bfd)[indx];
3918 while (h->root.type == bfd_link_hash_indirect
3919 || h->root.type == bfd_link_hash_warning)
3920 h = (struct elf_link_hash_entry *) h->root.u.i.link;
3921
3922 value = 0;
3923 if (h->root.type == bfd_link_hash_defined
3924 || h->root.type == bfd_link_hash_defweak)
3925 {
3926 sym_sec = h->root.u.def.section;
3927
3928 /* Detect the cases that sym_sec->output_section is
3929 expected to be NULL -- all cases in which the symbol
3930 is defined in another shared module. This includes
3931 PLT relocs for which we've created a PLT entry and
3932 other relocs for which we're prepared to create
3933 dynamic relocations. */
3934 /* ??? Just accept it NULL and continue. */
3935
3936 if (sym_sec->output_section != NULL)
3937 {
3938 value = (h->root.u.def.value
3939 + sym_sec->output_section->vma
3940 + sym_sec->output_offset);
3941 }
3942 }
3943 else if (h->root.type == bfd_link_hash_undefweak)
b34976b6 3944 undef_weak_ref = TRUE;
671bae9c 3945 else if (info->shared
3a27a730
L
3946 && !info->no_undefined
3947 && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
800eeca4
JW
3948 ;
3949 else
3950 {
3951 if (! ((*info->callbacks->undefined_symbol)
3952 (info, h->root.root.string, input_bfd,
3953 input_section, rel->r_offset,
3a27a730
L
3954 (!info->shared || info->no_undefined
3955 || ELF_ST_VISIBILITY (h->other)))))
b34976b6
AM
3956 return FALSE;
3957 ret_val = FALSE;
800eeca4
JW
3958 continue;
3959 }
3960 }
3961
3962 hit_addr = contents + rel->r_offset;
3963 value += rel->r_addend;
bbe66d08 3964 dynamic_symbol_p = elfNN_ia64_dynamic_symbol_p (h, info);
800eeca4
JW
3965
3966 switch (r_type)
3967 {
3968 case R_IA64_NONE:
3969 case R_IA64_LDXMOV:
3970 continue;
3971
3972 case R_IA64_IMM14:
3973 case R_IA64_IMM22:
3974 case R_IA64_IMM64:
3975 case R_IA64_DIR32MSB:
3976 case R_IA64_DIR32LSB:
3977 case R_IA64_DIR64MSB:
3978 case R_IA64_DIR64LSB:
3979 /* Install a dynamic relocation for this reloc. */
7b6dab7f
TW
3980 if ((dynamic_symbol_p || info->shared
3981 || (elfNN_ia64_aix_vec (info->hash->creator)
64e9ece0 3982 /* Don't emit relocs for __GLOB_DATA_PTR on AIX. */
dc810e39 3983 && (!h || strcmp (h->root.root.string,
64e9ece0 3984 "__GLOB_DATA_PTR") != 0)))
ec338859 3985 && r_symndx != 0
800eeca4
JW
3986 && (input_section->flags & SEC_ALLOC) != 0)
3987 {
3988 unsigned int dyn_r_type;
3989 long dynindx;
18b27f17 3990 bfd_vma addend;
800eeca4
JW
3991
3992 BFD_ASSERT (srel != NULL);
3993
3994 /* If we don't need dynamic symbol lookup, find a
3995 matching RELATIVE relocation. */
3996 dyn_r_type = r_type;
3997 if (dynamic_symbol_p)
18b27f17
RH
3998 {
3999 dynindx = h->dynindx;
4000 addend = rel->r_addend;
4001 value = 0;
4002 }
800eeca4
JW
4003 else
4004 {
4005 switch (r_type)
4006 {
4007 case R_IA64_DIR32MSB:
4008 dyn_r_type = R_IA64_REL32MSB;
4009 break;
4010 case R_IA64_DIR32LSB:
4011 dyn_r_type = R_IA64_REL32LSB;
4012 break;
4013 case R_IA64_DIR64MSB:
4014 dyn_r_type = R_IA64_REL64MSB;
4015 break;
4016 case R_IA64_DIR64LSB:
4017 dyn_r_type = R_IA64_REL64LSB;
4018 break;
4019
4020 default:
4021 /* We can't represent this without a dynamic symbol.
4022 Adjust the relocation to be against an output
4023 section symbol, which are always present in the
4024 dynamic symbol table. */
4025 /* ??? People shouldn't be doing non-pic code in
4026 shared libraries. Hork. */
4027 (*_bfd_error_handler)
4028 (_("%s: linking non-pic code in a shared library"),
8f615d07 4029 bfd_archive_filename (input_bfd));
b34976b6 4030 ret_val = FALSE;
800eeca4
JW
4031 continue;
4032 }
4033 dynindx = 0;
18b27f17 4034 addend = value;
800eeca4
JW
4035 }
4036
7b6dab7f
TW
4037 if (elfNN_ia64_aix_vec (info->hash->creator))
4038 rel->r_addend = value;
bbe66d08 4039 elfNN_ia64_install_dyn_reloc (output_bfd, info, input_section,
800eeca4 4040 srel, rel->r_offset, dyn_r_type,
18b27f17 4041 dynindx, addend);
800eeca4 4042 }
ae9a127f 4043 /* Fall through. */
800eeca4
JW
4044
4045 case R_IA64_LTV32MSB:
4046 case R_IA64_LTV32LSB:
4047 case R_IA64_LTV64MSB:
4048 case R_IA64_LTV64LSB:
bbe66d08 4049 r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
800eeca4
JW
4050 break;
4051
4052 case R_IA64_GPREL22:
4053 case R_IA64_GPREL64I:
4054 case R_IA64_GPREL32MSB:
4055 case R_IA64_GPREL32LSB:
4056 case R_IA64_GPREL64MSB:
4057 case R_IA64_GPREL64LSB:
4058 if (dynamic_symbol_p)
4059 {
4060 (*_bfd_error_handler)
4061 (_("%s: @gprel relocation against dynamic symbol %s"),
8f615d07 4062 bfd_archive_filename (input_bfd), h->root.root.string);
b34976b6 4063 ret_val = FALSE;
800eeca4
JW
4064 continue;
4065 }
4066 value -= gp_val;
bbe66d08 4067 r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
800eeca4
JW
4068 break;
4069
4070 case R_IA64_LTOFF22:
4071 case R_IA64_LTOFF22X:
4072 case R_IA64_LTOFF64I:
b34976b6 4073 dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
800eeca4
JW
4074 value = set_got_entry (input_bfd, info, dyn_i, (h ? h->dynindx : -1),
4075 rel->r_addend, value, R_IA64_DIR64LSB);
4076 value -= gp_val;
bbe66d08 4077 r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
800eeca4
JW
4078 break;
4079
4080 case R_IA64_PLTOFF22:
4081 case R_IA64_PLTOFF64I:
4082 case R_IA64_PLTOFF64MSB:
4083 case R_IA64_PLTOFF64LSB:
b34976b6
AM
4084 dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
4085 value = set_pltoff_entry (output_bfd, info, dyn_i, value, FALSE);
800eeca4 4086 value -= gp_val;
bbe66d08 4087 r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
800eeca4
JW
4088 break;
4089
4090 case R_IA64_FPTR64I:
4091 case R_IA64_FPTR32MSB:
4092 case R_IA64_FPTR32LSB:
4093 case R_IA64_FPTR64MSB:
4094 case R_IA64_FPTR64LSB:
b34976b6 4095 dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
800eeca4
JW
4096 if (dyn_i->want_fptr)
4097 {
4098 if (!undef_weak_ref)
4099 value = set_fptr_entry (output_bfd, info, dyn_i, value);
4100 }
4101 else
4102 {
4103 long dynindx;
4104
4105 /* Otherwise, we expect the dynamic linker to create
4106 the entry. */
4107
4108 if (h)
4109 {
4110 if (h->dynindx != -1)
4111 dynindx = h->dynindx;
4112 else
4113 dynindx = (_bfd_elf_link_lookup_local_dynindx
4114 (info, h->root.u.def.section->owner,
4115 global_sym_index (h)));
4116 }
4117 else
4118 {
4119 dynindx = (_bfd_elf_link_lookup_local_dynindx
dc810e39 4120 (info, input_bfd, (long) r_symndx));
800eeca4
JW
4121 }
4122
bbe66d08 4123 elfNN_ia64_install_dyn_reloc (output_bfd, info, input_section,
800eeca4
JW
4124 srel, rel->r_offset, r_type,
4125 dynindx, rel->r_addend);
4126 value = 0;
4127 }
4128
bbe66d08 4129 r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
800eeca4
JW
4130 break;
4131
4132 case R_IA64_LTOFF_FPTR22:
4133 case R_IA64_LTOFF_FPTR64I:
a4bd8390
JW
4134 case R_IA64_LTOFF_FPTR32MSB:
4135 case R_IA64_LTOFF_FPTR32LSB:
800eeca4
JW
4136 case R_IA64_LTOFF_FPTR64MSB:
4137 case R_IA64_LTOFF_FPTR64LSB:
4138 {
4139 long dynindx;
4140
b34976b6 4141 dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
800eeca4
JW
4142 if (dyn_i->want_fptr)
4143 {
4144 BFD_ASSERT (h == NULL || h->dynindx == -1)
4145 if (!undef_weak_ref)
4146 value = set_fptr_entry (output_bfd, info, dyn_i, value);
4147 dynindx = -1;
4148 }
4149 else
4150 {
4151 /* Otherwise, we expect the dynamic linker to create
4152 the entry. */
4153 if (h)
4154 {
4155 if (h->dynindx != -1)
4156 dynindx = h->dynindx;
4157 else
4158 dynindx = (_bfd_elf_link_lookup_local_dynindx
4159 (info, h->root.u.def.section->owner,
4160 global_sym_index (h)));
4161 }
4162 else
4163 dynindx = (_bfd_elf_link_lookup_local_dynindx
dc810e39 4164 (info, input_bfd, (long) r_symndx));
800eeca4
JW
4165 value = 0;
4166 }
4167
4168 value = set_got_entry (output_bfd, info, dyn_i, dynindx,
4169 rel->r_addend, value, R_IA64_FPTR64LSB);
4170 value -= gp_val;
bbe66d08 4171 r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
800eeca4
JW
4172 }
4173 break;
4174
4175 case R_IA64_PCREL32MSB:
4176 case R_IA64_PCREL32LSB:
4177 case R_IA64_PCREL64MSB:
4178 case R_IA64_PCREL64LSB:
4179 /* Install a dynamic relocation for this reloc. */
ec338859
AM
4180 if ((dynamic_symbol_p
4181 || elfNN_ia64_aix_vec (info->hash->creator))
4182 && r_symndx != 0)
800eeca4
JW
4183 {
4184 BFD_ASSERT (srel != NULL);
4185
bbe66d08 4186 elfNN_ia64_install_dyn_reloc (output_bfd, info, input_section,
800eeca4
JW
4187 srel, rel->r_offset, r_type,
4188 h->dynindx, rel->r_addend);
4189 }
4190 goto finish_pcrel;
4191
800eeca4 4192 case R_IA64_PCREL21B:
748abff6 4193 case R_IA64_PCREL60B:
800eeca4 4194 /* We should have created a PLT entry for any dynamic symbol. */
800eeca4
JW
4195 dyn_i = NULL;
4196 if (h)
b34976b6 4197 dyn_i = get_dyn_sym_info (ia64_info, h, NULL, NULL, FALSE);
800eeca4
JW
4198
4199 if (dyn_i && dyn_i->want_plt2)
4200 {
4201 /* Should have caught this earlier. */
4202 BFD_ASSERT (rel->r_addend == 0);
4203
4204 value = (ia64_info->plt_sec->output_section->vma
4205 + ia64_info->plt_sec->output_offset
4206 + dyn_i->plt2_offset);
4207 }
4208 else
4209 {
4210 /* Since there's no PLT entry, Validate that this is
4211 locally defined. */
4212 BFD_ASSERT (undef_weak_ref || sym_sec->output_section != NULL);
4213
4214 /* If the symbol is undef_weak, we shouldn't be trying
4215 to call it. There's every chance that we'd wind up
4216 with an out-of-range fixup here. Don't bother setting
4217 any value at all. */
4218 if (undef_weak_ref)
4219 continue;
4220 }
4221 goto finish_pcrel;
4222
2f9bd3f6
RH
4223 case R_IA64_PCREL21BI:
4224 case R_IA64_PCREL21F:
4225 case R_IA64_PCREL21M:
748abff6
RH
4226 case R_IA64_PCREL22:
4227 case R_IA64_PCREL64I:
2f9bd3f6
RH
4228 /* The PCREL21BI reloc is specifically not intended for use with
4229 dynamic relocs. PCREL21F and PCREL21M are used for speculation
4230 fixup code, and thus probably ought not be dynamic. The
4231 PCREL22 and PCREL64I relocs aren't emitted as dynamic relocs. */
4232 if (dynamic_symbol_p)
4233 {
4234 const char *msg;
4235
4236 if (r_type == R_IA64_PCREL21BI)
4237 msg = _("%s: @internal branch to dynamic symbol %s");
4238 else if (r_type == R_IA64_PCREL21F || r_type == R_IA64_PCREL21M)
4239 msg = _("%s: speculation fixup to dynamic symbol %s");
4240 else
4241 msg = _("%s: @pcrel relocation against dynamic symbol %s");
4242 (*_bfd_error_handler) (msg, bfd_archive_filename (input_bfd),
4243 h->root.root.string);
4244 ret_val = FALSE;
4245 continue;
4246 }
4247 goto finish_pcrel;
4248
800eeca4
JW
4249 finish_pcrel:
4250 /* Make pc-relative. */
4251 value -= (input_section->output_section->vma
4252 + input_section->output_offset
4253 + rel->r_offset) & ~ (bfd_vma) 0x3;
bbe66d08 4254 r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
800eeca4
JW
4255 break;
4256
4257 case R_IA64_SEGREL32MSB:
4258 case R_IA64_SEGREL32LSB:
4259 case R_IA64_SEGREL64MSB:
4260 case R_IA64_SEGREL64LSB:
d7458677
AM
4261 if (r_symndx == 0)
4262 {
4263 /* If the input section was discarded from the output, then
4264 do nothing. */
4265 r = bfd_reloc_ok;
4266 }
4267 else
4268 {
4269 struct elf_segment_map *m;
4270 Elf_Internal_Phdr *p;
4271
4272 /* Find the segment that contains the output_section. */
4273 for (m = elf_tdata (output_bfd)->segment_map,
4274 p = elf_tdata (output_bfd)->phdr;
4275 m != NULL;
4276 m = m->next, p++)
4277 {
4278 int i;
4279 for (i = m->count - 1; i >= 0; i--)
4280 if (m->sections[i] == sym_sec->output_section)
4281 break;
4282 if (i >= 0)
800eeca4 4283 break;
d7458677 4284 }
800eeca4 4285
d7458677
AM
4286 if (m == NULL)
4287 {
800eeca4 4288 r = bfd_reloc_notsupported;
d7458677
AM
4289 }
4290 else
4291 {
4292 /* The VMA of the segment is the vaddr of the associated
4293 program header. */
4294 if (value > p->p_vaddr)
4295 value -= p->p_vaddr;
4296 else
4297 value = 0;
4298 r = elfNN_ia64_install_value (output_bfd, hit_addr, value,
4299 r_type);
4300 }
4301 break;
4302 }
800eeca4
JW
4303
4304 case R_IA64_SECREL32MSB:
4305 case R_IA64_SECREL32LSB:
4306 case R_IA64_SECREL64MSB:
4307 case R_IA64_SECREL64LSB:
4308 /* Make output-section relative. */
4309 if (value > input_section->output_section->vma)
4310 value -= input_section->output_section->vma;
4311 else
4312 value = 0;
bbe66d08 4313 r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
800eeca4
JW
4314 break;
4315
800eeca4
JW
4316 case R_IA64_IPLTMSB:
4317 case R_IA64_IPLTLSB:
18b27f17
RH
4318 /* Install a dynamic relocation for this reloc. */
4319 if ((dynamic_symbol_p || info->shared)
4320 && (input_section->flags & SEC_ALLOC) != 0)
4321 {
18b27f17
RH
4322 BFD_ASSERT (srel != NULL);
4323
4324 /* If we don't need dynamic symbol lookup, install two
4325 RELATIVE relocations. */
4326 if (! dynamic_symbol_p)
4327 {
4328 unsigned int dyn_r_type;
3e932841 4329
18b27f17
RH
4330 if (r_type == R_IA64_IPLTMSB)
4331 dyn_r_type = R_IA64_REL64MSB;
4332 else
4333 dyn_r_type = R_IA64_REL64LSB;
4334
4335 elfNN_ia64_install_dyn_reloc (output_bfd, info,
4336 input_section,
4337 srel, rel->r_offset,
4338 dyn_r_type, 0, value);
4339 elfNN_ia64_install_dyn_reloc (output_bfd, info,
4340 input_section,
4341 srel, rel->r_offset + 8,
4342 dyn_r_type, 0, gp_val);
4343 }
4344 else
4345 elfNN_ia64_install_dyn_reloc (output_bfd, info, input_section,
4346 srel, rel->r_offset, r_type,
4347 h->dynindx, rel->r_addend);
4348 }
4349
4350 if (r_type == R_IA64_IPLTMSB)
4351 r_type = R_IA64_DIR64MSB;
4352 else
4353 r_type = R_IA64_DIR64LSB;
4354 elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
4355 r = elfNN_ia64_install_value (output_bfd, hit_addr + 8, gp_val,
4356 r_type);
4357 break;
800eeca4 4358
13ae64f3
JJ
4359 case R_IA64_TPREL14:
4360 case R_IA64_TPREL22:
4361 case R_IA64_TPREL64I:
4362 value -= elfNN_ia64_tprel_base (info);
4363 r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
4364 break;
4365
4366 case R_IA64_DTPREL14:
4367 case R_IA64_DTPREL22:
4368 case R_IA64_DTPREL64I:
b3dfd7fe
JJ
4369 case R_IA64_DTPREL64LSB:
4370 case R_IA64_DTPREL64MSB:
13ae64f3
JJ
4371 value -= elfNN_ia64_dtprel_base (info);
4372 r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
4373 break;
4374
4375 case R_IA64_LTOFF_TPREL22:
4376 case R_IA64_LTOFF_DTPMOD22:
4377 case R_IA64_LTOFF_DTPREL22:
4378 {
4379 int got_r_type;
a823975a
JJ
4380 long dynindx = h ? h->dynindx : -1;
4381 bfd_vma r_addend = rel->r_addend;
13ae64f3
JJ
4382
4383 switch (r_type)
4384 {
4385 default:
4386 case R_IA64_LTOFF_TPREL22:
a823975a
JJ
4387 if (!dynamic_symbol_p)
4388 {
4389 if (!info->shared)
4390 value -= elfNN_ia64_tprel_base (info);
4391 else
4392 {
4393 r_addend += value - elfNN_ia64_dtprel_base (info);
4394 dynindx = 0;
4395 }
4396 }
13ae64f3
JJ
4397 got_r_type = R_IA64_TPREL64LSB;
4398 break;
4399 case R_IA64_LTOFF_DTPMOD22:
4400 if (!dynamic_symbol_p && !info->shared)
4401 value = 1;
4402 got_r_type = R_IA64_DTPMOD64LSB;
4403 break;
4404 case R_IA64_LTOFF_DTPREL22:
4405 if (!dynamic_symbol_p)
4406 value -= elfNN_ia64_dtprel_base (info);
4407 got_r_type = R_IA64_DTPREL64LSB;
4408 break;
4409 }
b34976b6 4410 dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
a823975a 4411 value = set_got_entry (input_bfd, info, dyn_i, dynindx, r_addend,
13ae64f3
JJ
4412 value, got_r_type);
4413 value -= gp_val;
4414 r = elfNN_ia64_install_value (output_bfd, hit_addr, value,
4415 r_type);
4416 }
4417 break;
4418
800eeca4
JW
4419 default:
4420 r = bfd_reloc_notsupported;
4421 break;
4422 }
4423
4424 switch (r)
4425 {
4426 case bfd_reloc_ok:
4427 break;
4428
4429 case bfd_reloc_undefined:
4430 /* This can happen for global table relative relocs if
4431 __gp is undefined. This is a panic situation so we
4432 don't try to continue. */
4433 (*info->callbacks->undefined_symbol)
4434 (info, "__gp", input_bfd, input_section, rel->r_offset, 1);
b34976b6 4435 return FALSE;
800eeca4
JW
4436
4437 case bfd_reloc_notsupported:
4438 {
4439 const char *name;
4440
4441 if (h)
4442 name = h->root.root.string;
4443 else
4444 {
4445 name = bfd_elf_string_from_elf_section (input_bfd,
4446 symtab_hdr->sh_link,
4447 sym->st_name);
4448 if (name == NULL)
b34976b6 4449 return FALSE;
800eeca4
JW
4450 if (*name == '\0')
4451 name = bfd_section_name (input_bfd, input_section);
4452 }
4453 if (!(*info->callbacks->warning) (info, _("unsupported reloc"),
4454 name, input_bfd,
4455 input_section, rel->r_offset))
b34976b6
AM
4456 return FALSE;
4457 ret_val = FALSE;
800eeca4
JW
4458 }
4459 break;
4460
4461 case bfd_reloc_dangerous:
4462 case bfd_reloc_outofrange:
4463 case bfd_reloc_overflow:
4464 default:
4465 {
4466 const char *name;
4467
4468 if (h)
4469 name = h->root.root.string;
4470 else
4471 {
4472 name = bfd_elf_string_from_elf_section (input_bfd,
4473 symtab_hdr->sh_link,
4474 sym->st_name);
4475 if (name == NULL)
b34976b6 4476 return FALSE;
800eeca4
JW
4477 if (*name == '\0')
4478 name = bfd_section_name (input_bfd, input_section);
4479 }
4480 if (!(*info->callbacks->reloc_overflow) (info, name,
dc810e39
AM
4481 howto->name,
4482 (bfd_vma) 0,
800eeca4
JW
4483 input_bfd,
4484 input_section,
4485 rel->r_offset))
b34976b6
AM
4486 return FALSE;
4487 ret_val = FALSE;
800eeca4
JW
4488 }
4489 break;
4490 }
4491 }
4492
4493 return ret_val;
4494}
4495
b34976b6 4496static bfd_boolean
bbe66d08 4497elfNN_ia64_finish_dynamic_symbol (output_bfd, info, h, sym)
800eeca4
JW
4498 bfd *output_bfd;
4499 struct bfd_link_info *info;
4500 struct elf_link_hash_entry *h;
4501 Elf_Internal_Sym *sym;
4502{
bbe66d08
JW
4503 struct elfNN_ia64_link_hash_table *ia64_info;
4504 struct elfNN_ia64_dyn_sym_info *dyn_i;
800eeca4 4505
bbe66d08 4506 ia64_info = elfNN_ia64_hash_table (info);
b34976b6 4507 dyn_i = get_dyn_sym_info (ia64_info, h, NULL, NULL, FALSE);
800eeca4
JW
4508
4509 /* Fill in the PLT data, if required. */
4510 if (dyn_i && dyn_i->want_plt)
4511 {
4512 Elf_Internal_Rela outrel;
4513 bfd_byte *loc;
4514 asection *plt_sec;
4515 bfd_vma plt_addr, pltoff_addr, gp_val, index;
800eeca4
JW
4516
4517 gp_val = _bfd_get_gp_value (output_bfd);
4518
4519 /* Initialize the minimal PLT entry. */
4520
4521 index = (dyn_i->plt_offset - PLT_HEADER_SIZE) / PLT_MIN_ENTRY_SIZE;
4522 plt_sec = ia64_info->plt_sec;
4523 loc = plt_sec->contents + dyn_i->plt_offset;
4524
4525 memcpy (loc, plt_min_entry, PLT_MIN_ENTRY_SIZE);
bbe66d08
JW
4526 elfNN_ia64_install_value (output_bfd, loc, index, R_IA64_IMM22);
4527 elfNN_ia64_install_value (output_bfd, loc+2, -dyn_i->plt_offset,
800eeca4
JW
4528 R_IA64_PCREL21B);
4529
4530 plt_addr = (plt_sec->output_section->vma
4531 + plt_sec->output_offset
4532 + dyn_i->plt_offset);
b34976b6 4533 pltoff_addr = set_pltoff_entry (output_bfd, info, dyn_i, plt_addr, TRUE);
800eeca4
JW
4534
4535 /* Initialize the FULL PLT entry, if needed. */
4536 if (dyn_i->want_plt2)
4537 {
4538 loc = plt_sec->contents + dyn_i->plt2_offset;
4539
4540 memcpy (loc, plt_full_entry, PLT_FULL_ENTRY_SIZE);
bbe66d08 4541 elfNN_ia64_install_value (output_bfd, loc, pltoff_addr - gp_val,
800eeca4
JW
4542 R_IA64_IMM22);
4543
4544 /* Mark the symbol as undefined, rather than as defined in the
4545 plt section. Leave the value alone. */
4546 /* ??? We didn't redefine it in adjust_dynamic_symbol in the
4547 first place. But perhaps elflink.h did some for us. */
4548 if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
4549 sym->st_shndx = SHN_UNDEF;
4550 }
4551
4552 /* Create the dynamic relocation. */
4553 outrel.r_offset = pltoff_addr;
4554 if (bfd_little_endian (output_bfd))
bbe66d08 4555 outrel.r_info = ELFNN_R_INFO (h->dynindx, R_IA64_IPLTLSB);
800eeca4 4556 else
bbe66d08 4557 outrel.r_info = ELFNN_R_INFO (h->dynindx, R_IA64_IPLTMSB);
800eeca4
JW
4558 outrel.r_addend = 0;
4559
4560 /* This is fun. In the .IA_64.pltoff section, we've got entries
4561 that correspond both to real PLT entries, and those that
4562 happened to resolve to local symbols but need to be created
4563 to satisfy @pltoff relocations. The .rela.IA_64.pltoff
4564 relocations for the real PLT should come at the end of the
4565 section, so that they can be indexed by plt entry at runtime.
4566
4567 We emitted all of the relocations for the non-PLT @pltoff
4568 entries during relocate_section. So we can consider the
4569 existing sec->reloc_count to be the base of the array of
4570 PLT relocations. */
4571
947216bf
AM
4572 loc = ia64_info->rel_pltoff_sec->contents;
4573 loc += ((ia64_info->rel_pltoff_sec->reloc_count + index)
4574 * sizeof (Elf64_External_Rela));
4575 bfd_elfNN_swap_reloca_out (output_bfd, &outrel, loc);
800eeca4
JW
4576 }
4577
4578 /* Mark some specially defined symbols as absolute. */
4579 if (strcmp (h->root.root.string, "_DYNAMIC") == 0
4580 || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0
4581 || strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0)
4582 sym->st_shndx = SHN_ABS;
4583
b34976b6 4584 return TRUE;
800eeca4
JW
4585}
4586
b34976b6 4587static bfd_boolean
bbe66d08 4588elfNN_ia64_finish_dynamic_sections (abfd, info)
800eeca4
JW
4589 bfd *abfd;
4590 struct bfd_link_info *info;
4591{
bbe66d08 4592 struct elfNN_ia64_link_hash_table *ia64_info;
800eeca4
JW
4593 bfd *dynobj;
4594
bbe66d08 4595 ia64_info = elfNN_ia64_hash_table (info);
800eeca4
JW
4596 dynobj = ia64_info->root.dynobj;
4597
4598 if (elf_hash_table (info)->dynamic_sections_created)
4599 {
bbe66d08 4600 ElfNN_External_Dyn *dyncon, *dynconend;
800eeca4
JW
4601 asection *sdyn, *sgotplt;
4602 bfd_vma gp_val;
4603
4604 sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
4605 sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
4606 BFD_ASSERT (sdyn != NULL);
bbe66d08
JW
4607 dyncon = (ElfNN_External_Dyn *) sdyn->contents;
4608 dynconend = (ElfNN_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
800eeca4
JW
4609
4610 gp_val = _bfd_get_gp_value (abfd);
4611
4612 for (; dyncon < dynconend; dyncon++)
4613 {
4614 Elf_Internal_Dyn dyn;
800eeca4 4615
bbe66d08 4616 bfd_elfNN_swap_dyn_in (dynobj, dyncon, &dyn);
800eeca4
JW
4617
4618 switch (dyn.d_tag)
4619 {
4620 case DT_PLTGOT:
4621 dyn.d_un.d_ptr = gp_val;
4622 break;
4623
4624 case DT_PLTRELSZ:
4625 dyn.d_un.d_val = (ia64_info->minplt_entries
bbe66d08 4626 * sizeof (ElfNN_External_Rela));
800eeca4
JW
4627 break;
4628
4629 case DT_JMPREL:
4630 /* See the comment above in finish_dynamic_symbol. */
4631 dyn.d_un.d_ptr = (ia64_info->rel_pltoff_sec->output_section->vma
4632 + ia64_info->rel_pltoff_sec->output_offset
4633 + (ia64_info->rel_pltoff_sec->reloc_count
bbe66d08 4634 * sizeof (ElfNN_External_Rela)));
800eeca4
JW
4635 break;
4636
4637 case DT_IA_64_PLT_RESERVE:
4638 dyn.d_un.d_ptr = (sgotplt->output_section->vma
4639 + sgotplt->output_offset);
4640 break;
4641
4642 case DT_RELASZ:
4643 /* Do not have RELASZ include JMPREL. This makes things
3e932841 4644 easier on ld.so. This is not what the rest of BFD set up. */
800eeca4 4645 dyn.d_un.d_val -= (ia64_info->minplt_entries
bbe66d08 4646 * sizeof (ElfNN_External_Rela));
800eeca4 4647 break;
800eeca4
JW
4648 }
4649
bbe66d08 4650 bfd_elfNN_swap_dyn_out (abfd, &dyn, dyncon);
800eeca4
JW
4651 }
4652
ae9a127f 4653 /* Initialize the PLT0 entry. */
800eeca4
JW
4654 if (ia64_info->plt_sec)
4655 {
4656 bfd_byte *loc = ia64_info->plt_sec->contents;
4657 bfd_vma pltres;
4658
4659 memcpy (loc, plt_header, PLT_HEADER_SIZE);
4660
4661 pltres = (sgotplt->output_section->vma
4662 + sgotplt->output_offset
4663 - gp_val);
4664
bbe66d08 4665 elfNN_ia64_install_value (abfd, loc+1, pltres, R_IA64_GPREL22);
800eeca4
JW
4666 }
4667 }
4668
b34976b6 4669 return TRUE;
800eeca4
JW
4670}
4671\f
ae9a127f 4672/* ELF file flag handling: */
800eeca4 4673
3e932841 4674/* Function to keep IA-64 specific file flags. */
b34976b6 4675static bfd_boolean
bbe66d08 4676elfNN_ia64_set_private_flags (abfd, flags)
800eeca4
JW
4677 bfd *abfd;
4678 flagword flags;
4679{
4680 BFD_ASSERT (!elf_flags_init (abfd)
4681 || elf_elfheader (abfd)->e_flags == flags);
4682
4683 elf_elfheader (abfd)->e_flags = flags;
b34976b6
AM
4684 elf_flags_init (abfd) = TRUE;
4685 return TRUE;
800eeca4
JW
4686}
4687
800eeca4
JW
4688/* Merge backend specific data from an object file to the output
4689 object file when linking. */
b34976b6 4690static bfd_boolean
bbe66d08 4691elfNN_ia64_merge_private_bfd_data (ibfd, obfd)
800eeca4
JW
4692 bfd *ibfd, *obfd;
4693{
4694 flagword out_flags;
4695 flagword in_flags;
b34976b6 4696 bfd_boolean ok = TRUE;
800eeca4
JW
4697
4698 /* Don't even pretend to support mixed-format linking. */
4699 if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
4700 || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
b34976b6 4701 return FALSE;
800eeca4
JW
4702
4703 in_flags = elf_elfheader (ibfd)->e_flags;
4704 out_flags = elf_elfheader (obfd)->e_flags;
4705
4706 if (! elf_flags_init (obfd))
4707 {
b34976b6 4708 elf_flags_init (obfd) = TRUE;
800eeca4
JW
4709 elf_elfheader (obfd)->e_flags = in_flags;
4710
4711 if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
4712 && bfd_get_arch_info (obfd)->the_default)
4713 {
4714 return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
4715 bfd_get_mach (ibfd));
4716 }
4717
b34976b6 4718 return TRUE;
800eeca4
JW
4719 }
4720
4721 /* Check flag compatibility. */
4722 if (in_flags == out_flags)
b34976b6 4723 return TRUE;
800eeca4 4724
c43c2cc5
JW
4725 /* Output has EF_IA_64_REDUCEDFP set only if all inputs have it set. */
4726 if (!(in_flags & EF_IA_64_REDUCEDFP) && (out_flags & EF_IA_64_REDUCEDFP))
4727 elf_elfheader (obfd)->e_flags &= ~EF_IA_64_REDUCEDFP;
4728
800eeca4
JW
4729 if ((in_flags & EF_IA_64_TRAPNIL) != (out_flags & EF_IA_64_TRAPNIL))
4730 {
4731 (*_bfd_error_handler)
4732 (_("%s: linking trap-on-NULL-dereference with non-trapping files"),
8f615d07 4733 bfd_archive_filename (ibfd));
800eeca4
JW
4734
4735 bfd_set_error (bfd_error_bad_value);
b34976b6 4736 ok = FALSE;
800eeca4
JW
4737 }
4738 if ((in_flags & EF_IA_64_BE) != (out_flags & EF_IA_64_BE))
4739 {
4740 (*_bfd_error_handler)
4741 (_("%s: linking big-endian files with little-endian files"),
8f615d07 4742 bfd_archive_filename (ibfd));
800eeca4
JW
4743
4744 bfd_set_error (bfd_error_bad_value);
b34976b6 4745 ok = FALSE;
800eeca4
JW
4746 }
4747 if ((in_flags & EF_IA_64_ABI64) != (out_flags & EF_IA_64_ABI64))
4748 {
4749 (*_bfd_error_handler)
4750 (_("%s: linking 64-bit files with 32-bit files"),
8f615d07 4751 bfd_archive_filename (ibfd));
800eeca4
JW
4752
4753 bfd_set_error (bfd_error_bad_value);
b34976b6 4754 ok = FALSE;
800eeca4 4755 }
c43c2cc5
JW
4756 if ((in_flags & EF_IA_64_CONS_GP) != (out_flags & EF_IA_64_CONS_GP))
4757 {
4758 (*_bfd_error_handler)
4759 (_("%s: linking constant-gp files with non-constant-gp files"),
8f615d07 4760 bfd_archive_filename (ibfd));
c43c2cc5
JW
4761
4762 bfd_set_error (bfd_error_bad_value);
b34976b6 4763 ok = FALSE;
c43c2cc5
JW
4764 }
4765 if ((in_flags & EF_IA_64_NOFUNCDESC_CONS_GP)
4766 != (out_flags & EF_IA_64_NOFUNCDESC_CONS_GP))
4767 {
4768 (*_bfd_error_handler)
4769 (_("%s: linking auto-pic files with non-auto-pic files"),
8f615d07 4770 bfd_archive_filename (ibfd));
c43c2cc5
JW
4771
4772 bfd_set_error (bfd_error_bad_value);
b34976b6 4773 ok = FALSE;
c43c2cc5 4774 }
800eeca4
JW
4775
4776 return ok;
4777}
4778
b34976b6 4779static bfd_boolean
bbe66d08 4780elfNN_ia64_print_private_bfd_data (abfd, ptr)
800eeca4
JW
4781 bfd *abfd;
4782 PTR ptr;
4783{
4784 FILE *file = (FILE *) ptr;
4785 flagword flags = elf_elfheader (abfd)->e_flags;
4786
4787 BFD_ASSERT (abfd != NULL && ptr != NULL);
4788
c43c2cc5 4789 fprintf (file, "private flags = %s%s%s%s%s%s%s%s\n",
800eeca4
JW
4790 (flags & EF_IA_64_TRAPNIL) ? "TRAPNIL, " : "",
4791 (flags & EF_IA_64_EXT) ? "EXT, " : "",
4792 (flags & EF_IA_64_BE) ? "BE, " : "LE, ",
c43c2cc5
JW
4793 (flags & EF_IA_64_REDUCEDFP) ? "REDUCEDFP, " : "",
4794 (flags & EF_IA_64_CONS_GP) ? "CONS_GP, " : "",
4795 (flags & EF_IA_64_NOFUNCDESC_CONS_GP) ? "NOFUNCDESC_CONS_GP, " : "",
4796 (flags & EF_IA_64_ABSOLUTE) ? "ABSOLUTE, " : "",
800eeca4 4797 (flags & EF_IA_64_ABI64) ? "ABI64" : "ABI32");
3e932841 4798
800eeca4 4799 _bfd_elf_print_private_bfd_data (abfd, ptr);
b34976b6 4800 return TRUE;
800eeca4 4801}
db6751f2
JJ
4802
4803static enum elf_reloc_type_class
f51e552e
AM
4804elfNN_ia64_reloc_type_class (rela)
4805 const Elf_Internal_Rela *rela;
db6751f2 4806{
f51e552e 4807 switch ((int) ELFNN_R_TYPE (rela->r_info))
db6751f2
JJ
4808 {
4809 case R_IA64_REL32MSB:
4810 case R_IA64_REL32LSB:
4811 case R_IA64_REL64MSB:
4812 case R_IA64_REL64LSB:
4813 return reloc_class_relative;
4814 case R_IA64_IPLTMSB:
4815 case R_IA64_IPLTLSB:
4816 return reloc_class_plt;
4817 case R_IA64_COPY:
4818 return reloc_class_copy;
4819 default:
4820 return reloc_class_normal;
4821 }
4822}
fcf12726 4823
b34976b6 4824static bfd_boolean
d9cf1b54
AM
4825elfNN_ia64_hpux_vec (const bfd_target *vec)
4826{
4827 extern const bfd_target bfd_elfNN_ia64_hpux_big_vec;
4828 return (vec == & bfd_elfNN_ia64_hpux_big_vec);
4829}
4830
fcf12726
AM
4831static void
4832elfNN_hpux_post_process_headers (abfd, info)
4833 bfd *abfd;
4834 struct bfd_link_info *info ATTRIBUTE_UNUSED;
4835{
4836 Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd);
4837
4838 i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_HPUX;
4839 i_ehdrp->e_ident[EI_ABIVERSION] = 1;
4840}
d9cf1b54 4841
b34976b6 4842bfd_boolean
af746e92 4843elfNN_hpux_backend_section_from_bfd_section (abfd, sec, retval)
d9cf1b54 4844 bfd *abfd ATTRIBUTE_UNUSED;
d9cf1b54
AM
4845 asection *sec;
4846 int *retval;
4847{
4848 if (bfd_is_com_section (sec))
4849 {
4850 *retval = SHN_IA_64_ANSI_COMMON;
b34976b6 4851 return TRUE;
d9cf1b54 4852 }
b34976b6 4853 return FALSE;
d9cf1b54 4854}
800eeca4 4855\f
bbe66d08
JW
4856#define TARGET_LITTLE_SYM bfd_elfNN_ia64_little_vec
4857#define TARGET_LITTLE_NAME "elfNN-ia64-little"
4858#define TARGET_BIG_SYM bfd_elfNN_ia64_big_vec
4859#define TARGET_BIG_NAME "elfNN-ia64-big"
800eeca4
JW
4860#define ELF_ARCH bfd_arch_ia64
4861#define ELF_MACHINE_CODE EM_IA_64
4862#define ELF_MACHINE_ALT1 1999 /* EAS2.3 */
4863#define ELF_MACHINE_ALT2 1998 /* EAS2.2 */
4864#define ELF_MAXPAGESIZE 0x10000 /* 64KB */
4865
4866#define elf_backend_section_from_shdr \
bbe66d08 4867 elfNN_ia64_section_from_shdr
fa152c49 4868#define elf_backend_section_flags \
bbe66d08 4869 elfNN_ia64_section_flags
800eeca4 4870#define elf_backend_fake_sections \
bbe66d08 4871 elfNN_ia64_fake_sections
81545d45
RH
4872#define elf_backend_final_write_processing \
4873 elfNN_ia64_final_write_processing
800eeca4 4874#define elf_backend_add_symbol_hook \
bbe66d08 4875 elfNN_ia64_add_symbol_hook
800eeca4 4876#define elf_backend_additional_program_headers \
bbe66d08 4877 elfNN_ia64_additional_program_headers
800eeca4 4878#define elf_backend_modify_segment_map \
bbe66d08 4879 elfNN_ia64_modify_segment_map
800eeca4 4880#define elf_info_to_howto \
bbe66d08 4881 elfNN_ia64_info_to_howto
800eeca4 4882
bbe66d08
JW
4883#define bfd_elfNN_bfd_reloc_type_lookup \
4884 elfNN_ia64_reloc_type_lookup
4885#define bfd_elfNN_bfd_is_local_label_name \
4886 elfNN_ia64_is_local_label_name
4887#define bfd_elfNN_bfd_relax_section \
4888 elfNN_ia64_relax_section
800eeca4
JW
4889
4890/* Stuff for the BFD linker: */
bbe66d08
JW
4891#define bfd_elfNN_bfd_link_hash_table_create \
4892 elfNN_ia64_hash_table_create
800eeca4 4893#define elf_backend_create_dynamic_sections \
bbe66d08 4894 elfNN_ia64_create_dynamic_sections
800eeca4 4895#define elf_backend_check_relocs \
bbe66d08 4896 elfNN_ia64_check_relocs
800eeca4 4897#define elf_backend_adjust_dynamic_symbol \
bbe66d08 4898 elfNN_ia64_adjust_dynamic_symbol
800eeca4 4899#define elf_backend_size_dynamic_sections \
bbe66d08 4900 elfNN_ia64_size_dynamic_sections
800eeca4 4901#define elf_backend_relocate_section \
bbe66d08 4902 elfNN_ia64_relocate_section
800eeca4 4903#define elf_backend_finish_dynamic_symbol \
bbe66d08 4904 elfNN_ia64_finish_dynamic_symbol
800eeca4 4905#define elf_backend_finish_dynamic_sections \
bbe66d08
JW
4906 elfNN_ia64_finish_dynamic_sections
4907#define bfd_elfNN_bfd_final_link \
4908 elfNN_ia64_final_link
4909
bbe66d08
JW
4910#define bfd_elfNN_bfd_merge_private_bfd_data \
4911 elfNN_ia64_merge_private_bfd_data
4912#define bfd_elfNN_bfd_set_private_flags \
4913 elfNN_ia64_set_private_flags
4914#define bfd_elfNN_bfd_print_private_bfd_data \
4915 elfNN_ia64_print_private_bfd_data
800eeca4
JW
4916
4917#define elf_backend_plt_readonly 1
4918#define elf_backend_want_plt_sym 0
4919#define elf_backend_plt_alignment 5
4920#define elf_backend_got_header_size 0
4921#define elf_backend_plt_header_size PLT_HEADER_SIZE
4922#define elf_backend_want_got_plt 1
4923#define elf_backend_may_use_rel_p 1
4924#define elf_backend_may_use_rela_p 1
4925#define elf_backend_default_use_rela_p 1
4926#define elf_backend_want_dynbss 0
bbe66d08
JW
4927#define elf_backend_copy_indirect_symbol elfNN_ia64_hash_copy_indirect
4928#define elf_backend_hide_symbol elfNN_ia64_hash_hide_symbol
db6751f2 4929#define elf_backend_reloc_type_class elfNN_ia64_reloc_type_class
b491616a 4930#define elf_backend_rela_normal 1
800eeca4 4931
bbe66d08 4932#include "elfNN-target.h"
7b6dab7f
TW
4933
4934/* AIX-specific vectors. */
4935
4936#undef TARGET_LITTLE_SYM
4937#define TARGET_LITTLE_SYM bfd_elfNN_ia64_aix_little_vec
4938#undef TARGET_LITTLE_NAME
4939#define TARGET_LITTLE_NAME "elfNN-ia64-aix-little"
4940#undef TARGET_BIG_SYM
4941#define TARGET_BIG_SYM bfd_elfNN_ia64_aix_big_vec
4942#undef TARGET_BIG_NAME
4943#define TARGET_BIG_NAME "elfNN-ia64-aix-big"
4944
4945#undef elf_backend_add_symbol_hook
4946#define elf_backend_add_symbol_hook elfNN_ia64_aix_add_symbol_hook
4947
4948#undef bfd_elfNN_bfd_link_add_symbols
4949#define bfd_elfNN_bfd_link_add_symbols elfNN_ia64_aix_link_add_symbols
4950
4951#define elfNN_bed elfNN_ia64_aix_bed
4952
4953#include "elfNN-target.h"
fcf12726
AM
4954
4955/* HPUX-specific vectors. */
4956
4957#undef TARGET_LITTLE_SYM
4958#undef TARGET_LITTLE_NAME
4959#undef TARGET_BIG_SYM
4960#define TARGET_BIG_SYM bfd_elfNN_ia64_hpux_big_vec
4961#undef TARGET_BIG_NAME
4962#define TARGET_BIG_NAME "elfNN-ia64-hpux-big"
4963
254ed743
NC
4964/* We need to undo the AIX specific functions. */
4965
4966#undef elf_backend_add_symbol_hook
4967#define elf_backend_add_symbol_hook elfNN_ia64_add_symbol_hook
4968
4969#undef bfd_elfNN_bfd_link_add_symbols
4970#define bfd_elfNN_bfd_link_add_symbols _bfd_generic_link_add_symbols
4971
4972/* These are HP-UX specific functions. */
4973
fcf12726
AM
4974#undef elf_backend_post_process_headers
4975#define elf_backend_post_process_headers elfNN_hpux_post_process_headers
4976
d9cf1b54
AM
4977#undef elf_backend_section_from_bfd_section
4978#define elf_backend_section_from_bfd_section elfNN_hpux_backend_section_from_bfd_section
4979
5e8d7549
NC
4980#undef elf_backend_want_p_paddr_set_to_zero
4981#define elf_backend_want_p_paddr_set_to_zero 1
4982
fcf12726
AM
4983#undef ELF_MAXPAGESIZE
4984#define ELF_MAXPAGESIZE 0x1000 /* 1K */
4985
4986#undef elfNN_bed
4987#define elfNN_bed elfNN_ia64_hpux_bed
4988
4989#include "elfNN-target.h"
5e8d7549
NC
4990
4991#undef elf_backend_want_p_paddr_set_to_zero
This page took 0.456252 seconds and 4 git commands to generate.