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