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