Add support for dwarf2 debug information.
[binutils.git] / bfd / elfxx-ia64.c
blobbff78c84345c164c18fd07aed44199daf7f92e0d
1 /* IA-64 support for 64-bit ELF
2 Copyright 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
3 Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
5 This file is part of BFD, the Binary File Descriptor library.
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.
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.
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. */
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"
28 /* THE RULES for all the stuff the linker creates --
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.
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.
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.
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.
53 MIN_PLT Created by PLTOFF entries against dynamic symbols. This
54 does not reqire dynamic relocations. */
56 #define NELEMS(a) ((int) (sizeof (a) / sizeof ((a)[0])))
58 typedef struct bfd_hash_entry *(*new_hash_entry_func)
59 PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
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. */
65 struct elfNN_ia64_dyn_sym_info
67 /* The addend for which this entry is relevant. */
68 bfd_vma addend;
70 /* Next addend in the list. */
71 struct elfNN_ia64_dyn_sym_info *next;
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;
78 bfd_vma tprel_offset;
79 bfd_vma dtpmod_offset;
80 bfd_vma dtprel_offset;
82 /* The symbol table entry, if any, that this was derrived from. */
83 struct elf_link_hash_entry *h;
85 /* Used to count non-got, non-plt relocations for delayed sizing
86 of relocation sections. */
87 struct elfNN_ia64_dyn_reloc_entry
89 struct elfNN_ia64_dyn_reloc_entry *next;
90 asection *srel;
91 int type;
92 int count;
93 } *reloc_entries;
95 /* TRUE when the section contents have been updated. */
96 unsigned got_done : 1;
97 unsigned fptr_done : 1;
98 unsigned pltoff_done : 1;
99 unsigned tprel_done : 1;
100 unsigned dtpmod_done : 1;
101 unsigned dtprel_done : 1;
103 /* TRUE for the different kinds of linker data we want created. */
104 unsigned want_got : 1;
105 unsigned want_gotx : 1;
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;
111 unsigned want_tprel : 1;
112 unsigned want_dtpmod : 1;
113 unsigned want_dtprel : 1;
116 struct elfNN_ia64_local_hash_entry
118 struct bfd_hash_entry root;
119 struct elfNN_ia64_dyn_sym_info *info;
121 /* TRUE if this hash entry's addends was translated for
122 SHF_MERGE optimization. */
123 unsigned sec_merge_done : 1;
126 struct elfNN_ia64_local_hash_table
128 struct bfd_hash_table root;
129 /* No additional fields for now. */
132 struct elfNN_ia64_link_hash_entry
134 struct elf_link_hash_entry root;
135 struct elfNN_ia64_dyn_sym_info *info;
138 struct elfNN_ia64_link_hash_table
140 /* The main hash table. */
141 struct elf_link_hash_table root;
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 */
150 bfd_size_type minplt_entries; /* number of minplt entries */
151 unsigned reltext : 1; /* are there relocs against readonly sections? */
152 unsigned self_dtpmod_done : 1;/* has self DTPMOD entry been finished? */
153 bfd_vma self_dtpmod_offset; /* .got offset to self DTPMOD entry */
155 struct elfNN_ia64_local_hash_table loc_hash_table;
158 struct elfNN_ia64_allocate_data
160 struct bfd_link_info *info;
161 bfd_size_type ofs;
164 #define elfNN_ia64_hash_table(p) \
165 ((struct elfNN_ia64_link_hash_table *) ((p)->hash))
167 static bfd_reloc_status_type elfNN_ia64_reloc
168 PARAMS ((bfd *abfd, arelent *reloc, asymbol *sym, PTR data,
169 asection *input_section, bfd *output_bfd, char **error_message));
170 static reloc_howto_type * lookup_howto
171 PARAMS ((unsigned int rtype));
172 static reloc_howto_type *elfNN_ia64_reloc_type_lookup
173 PARAMS ((bfd *abfd, bfd_reloc_code_real_type bfd_code));
174 static void elfNN_ia64_info_to_howto
175 PARAMS ((bfd *abfd, arelent *bfd_reloc, Elf_Internal_Rela *elf_reloc));
176 static bfd_boolean elfNN_ia64_relax_section
177 PARAMS((bfd *abfd, asection *sec, struct bfd_link_info *link_info,
178 bfd_boolean *again));
179 static void elfNN_ia64_relax_ldxmov
180 PARAMS((bfd *abfd, bfd_byte *contents, bfd_vma off));
181 static bfd_boolean is_unwind_section_name
182 PARAMS ((bfd *abfd, const char *));
183 static bfd_boolean elfNN_ia64_section_from_shdr
184 PARAMS ((bfd *, Elf_Internal_Shdr *, const char *));
185 static bfd_boolean elfNN_ia64_section_flags
186 PARAMS ((flagword *, Elf_Internal_Shdr *));
187 static bfd_boolean elfNN_ia64_fake_sections
188 PARAMS ((bfd *abfd, Elf_Internal_Shdr *hdr, asection *sec));
189 static void elfNN_ia64_final_write_processing
190 PARAMS ((bfd *abfd, bfd_boolean linker));
191 static bfd_boolean elfNN_ia64_add_symbol_hook
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));
195 static bfd_boolean elfNN_ia64_aix_vec
196 PARAMS ((const bfd_target *vec));
197 static bfd_boolean elfNN_ia64_aix_add_symbol_hook
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));
201 static bfd_boolean elfNN_ia64_aix_link_add_symbols
202 PARAMS ((bfd *abfd, struct bfd_link_info *info));
203 static int elfNN_ia64_additional_program_headers
204 PARAMS ((bfd *abfd));
205 static bfd_boolean elfNN_ia64_modify_segment_map
206 PARAMS ((bfd *));
207 static bfd_boolean elfNN_ia64_is_local_label_name
208 PARAMS ((bfd *abfd, const char *name));
209 static bfd_boolean elfNN_ia64_dynamic_symbol_p
210 PARAMS ((struct elf_link_hash_entry *h, struct bfd_link_info *info));
211 static bfd_boolean elfNN_ia64_local_hash_table_init
212 PARAMS ((struct elfNN_ia64_local_hash_table *ht, bfd *abfd,
213 new_hash_entry_func new));
214 static struct bfd_hash_entry *elfNN_ia64_new_loc_hash_entry
215 PARAMS ((struct bfd_hash_entry *entry, struct bfd_hash_table *table,
216 const char *string));
217 static struct bfd_hash_entry *elfNN_ia64_new_elf_hash_entry
218 PARAMS ((struct bfd_hash_entry *entry, struct bfd_hash_table *table,
219 const char *string));
220 static void elfNN_ia64_hash_copy_indirect
221 PARAMS ((struct elf_backend_data *, struct elf_link_hash_entry *,
222 struct elf_link_hash_entry *));
223 static void elfNN_ia64_hash_hide_symbol
224 PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *, bfd_boolean));
225 static struct bfd_link_hash_table *elfNN_ia64_hash_table_create
226 PARAMS ((bfd *abfd));
227 static struct elfNN_ia64_local_hash_entry *elfNN_ia64_local_hash_lookup
228 PARAMS ((struct elfNN_ia64_local_hash_table *table, const char *string,
229 bfd_boolean create, bfd_boolean copy));
230 static bfd_boolean elfNN_ia64_global_dyn_sym_thunk
231 PARAMS ((struct bfd_hash_entry *, PTR));
232 static bfd_boolean elfNN_ia64_local_dyn_sym_thunk
233 PARAMS ((struct bfd_hash_entry *, PTR));
234 static void elfNN_ia64_dyn_sym_traverse
235 PARAMS ((struct elfNN_ia64_link_hash_table *ia64_info,
236 bfd_boolean (*func) (struct elfNN_ia64_dyn_sym_info *, PTR),
237 PTR info));
238 static bfd_boolean elfNN_ia64_create_dynamic_sections
239 PARAMS ((bfd *abfd, struct bfd_link_info *info));
240 static struct elfNN_ia64_local_hash_entry * get_local_sym_hash
241 PARAMS ((struct elfNN_ia64_link_hash_table *ia64_info,
242 bfd *abfd, const Elf_Internal_Rela *rel, bfd_boolean create));
243 static struct elfNN_ia64_dyn_sym_info * get_dyn_sym_info
244 PARAMS ((struct elfNN_ia64_link_hash_table *ia64_info,
245 struct elf_link_hash_entry *h,
246 bfd *abfd, const Elf_Internal_Rela *rel, bfd_boolean create));
247 static asection *get_got
248 PARAMS ((bfd *abfd, struct bfd_link_info *info,
249 struct elfNN_ia64_link_hash_table *ia64_info));
250 static asection *get_fptr
251 PARAMS ((bfd *abfd, struct bfd_link_info *info,
252 struct elfNN_ia64_link_hash_table *ia64_info));
253 static asection *get_pltoff
254 PARAMS ((bfd *abfd, struct bfd_link_info *info,
255 struct elfNN_ia64_link_hash_table *ia64_info));
256 static asection *get_reloc_section
257 PARAMS ((bfd *abfd, struct elfNN_ia64_link_hash_table *ia64_info,
258 asection *sec, bfd_boolean create));
259 static bfd_boolean count_dyn_reloc
260 PARAMS ((bfd *abfd, struct elfNN_ia64_dyn_sym_info *dyn_i,
261 asection *srel, int type));
262 static bfd_boolean elfNN_ia64_check_relocs
263 PARAMS ((bfd *abfd, struct bfd_link_info *info, asection *sec,
264 const Elf_Internal_Rela *relocs));
265 static bfd_boolean elfNN_ia64_adjust_dynamic_symbol
266 PARAMS ((struct bfd_link_info *info, struct elf_link_hash_entry *h));
267 static long global_sym_index
268 PARAMS ((struct elf_link_hash_entry *h));
269 static bfd_boolean allocate_fptr
270 PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
271 static bfd_boolean allocate_global_data_got
272 PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
273 static bfd_boolean allocate_global_fptr_got
274 PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
275 static bfd_boolean allocate_local_got
276 PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
277 static bfd_boolean allocate_pltoff_entries
278 PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
279 static bfd_boolean allocate_plt_entries
280 PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
281 static bfd_boolean allocate_plt2_entries
282 PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
283 static bfd_boolean allocate_dynrel_entries
284 PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
285 static bfd_boolean elfNN_ia64_size_dynamic_sections
286 PARAMS ((bfd *output_bfd, struct bfd_link_info *info));
287 static bfd_reloc_status_type elfNN_ia64_install_value
288 PARAMS ((bfd *abfd, bfd_byte *hit_addr, bfd_vma val, unsigned int r_type));
289 static void elfNN_ia64_install_dyn_reloc
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));
293 static bfd_vma set_got_entry
294 PARAMS ((bfd *abfd, struct bfd_link_info *info,
295 struct elfNN_ia64_dyn_sym_info *dyn_i, long dynindx,
296 bfd_vma addend, bfd_vma value, unsigned int dyn_r_type));
297 static bfd_vma set_fptr_entry
298 PARAMS ((bfd *abfd, struct bfd_link_info *info,
299 struct elfNN_ia64_dyn_sym_info *dyn_i,
300 bfd_vma value));
301 static bfd_vma set_pltoff_entry
302 PARAMS ((bfd *abfd, struct bfd_link_info *info,
303 struct elfNN_ia64_dyn_sym_info *dyn_i,
304 bfd_vma value, bfd_boolean));
305 static bfd_vma elfNN_ia64_tprel_base
306 PARAMS ((struct bfd_link_info *info));
307 static bfd_vma elfNN_ia64_dtprel_base
308 PARAMS ((struct bfd_link_info *info));
309 static int elfNN_ia64_unwind_entry_compare
310 PARAMS ((const PTR, const PTR));
311 static bfd_boolean elfNN_ia64_choose_gp
312 PARAMS ((bfd *abfd, struct bfd_link_info *info));
313 static bfd_boolean elfNN_ia64_final_link
314 PARAMS ((bfd *abfd, struct bfd_link_info *info));
315 static bfd_boolean elfNN_ia64_relocate_section
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));
320 static bfd_boolean elfNN_ia64_finish_dynamic_symbol
321 PARAMS ((bfd *output_bfd, struct bfd_link_info *info,
322 struct elf_link_hash_entry *h, Elf_Internal_Sym *sym));
323 static bfd_boolean elfNN_ia64_finish_dynamic_sections
324 PARAMS ((bfd *abfd, struct bfd_link_info *info));
325 static bfd_boolean elfNN_ia64_set_private_flags
326 PARAMS ((bfd *abfd, flagword flags));
327 static bfd_boolean elfNN_ia64_merge_private_bfd_data
328 PARAMS ((bfd *ibfd, bfd *obfd));
329 static bfd_boolean elfNN_ia64_print_private_bfd_data
330 PARAMS ((bfd *abfd, PTR ptr));
331 static enum elf_reloc_type_class elfNN_ia64_reloc_type_class
332 PARAMS ((const Elf_Internal_Rela *));
333 static bfd_boolean elfNN_ia64_hpux_vec
334 PARAMS ((const bfd_target *vec));
335 static void elfNN_hpux_post_process_headers
336 PARAMS ((bfd *abfd, struct bfd_link_info *info));
337 bfd_boolean elfNN_hpux_backend_section_from_bfd_section
338 PARAMS ((bfd *abfd, asection *sec, int *retval));
340 /* ia64-specific relocation. */
342 /* Perform a relocation. Not much to do here as all the hard work is
343 done in elfNN_ia64_final_link_relocate. */
344 static bfd_reloc_status_type
345 elfNN_ia64_reloc (abfd, reloc, sym, data, input_section,
346 output_bfd, error_message)
347 bfd *abfd ATTRIBUTE_UNUSED;
348 arelent *reloc;
349 asymbol *sym ATTRIBUTE_UNUSED;
350 PTR data ATTRIBUTE_UNUSED;
351 asection *input_section;
352 bfd *output_bfd;
353 char **error_message;
355 if (output_bfd)
357 reloc->address += input_section->output_offset;
358 return bfd_reloc_ok;
361 if (input_section->flags & SEC_DEBUGGING)
362 return bfd_reloc_continue;
364 *error_message = "Unsupported call to elfNN_ia64_reloc";
365 return bfd_reloc_notsupported;
368 #define IA64_HOWTO(TYPE, NAME, SIZE, PCREL, IN) \
369 HOWTO (TYPE, 0, SIZE, 0, PCREL, 0, complain_overflow_signed, \
370 elfNN_ia64_reloc, NAME, FALSE, 0, 0, IN)
372 /* This table has to be sorted according to increasing number of the
373 TYPE field. */
374 static reloc_howto_type ia64_howto_table[] =
376 IA64_HOWTO (R_IA64_NONE, "NONE", 0, FALSE, TRUE),
378 IA64_HOWTO (R_IA64_IMM14, "IMM14", 0, FALSE, TRUE),
379 IA64_HOWTO (R_IA64_IMM22, "IMM22", 0, FALSE, TRUE),
380 IA64_HOWTO (R_IA64_IMM64, "IMM64", 0, FALSE, TRUE),
381 IA64_HOWTO (R_IA64_DIR32MSB, "DIR32MSB", 2, FALSE, TRUE),
382 IA64_HOWTO (R_IA64_DIR32LSB, "DIR32LSB", 2, FALSE, TRUE),
383 IA64_HOWTO (R_IA64_DIR64MSB, "DIR64MSB", 4, FALSE, TRUE),
384 IA64_HOWTO (R_IA64_DIR64LSB, "DIR64LSB", 4, FALSE, TRUE),
386 IA64_HOWTO (R_IA64_GPREL22, "GPREL22", 0, FALSE, TRUE),
387 IA64_HOWTO (R_IA64_GPREL64I, "GPREL64I", 0, FALSE, TRUE),
388 IA64_HOWTO (R_IA64_GPREL32MSB, "GPREL32MSB", 2, FALSE, TRUE),
389 IA64_HOWTO (R_IA64_GPREL32LSB, "GPREL32LSB", 2, FALSE, TRUE),
390 IA64_HOWTO (R_IA64_GPREL64MSB, "GPREL64MSB", 4, FALSE, TRUE),
391 IA64_HOWTO (R_IA64_GPREL64LSB, "GPREL64LSB", 4, FALSE, TRUE),
393 IA64_HOWTO (R_IA64_LTOFF22, "LTOFF22", 0, FALSE, TRUE),
394 IA64_HOWTO (R_IA64_LTOFF64I, "LTOFF64I", 0, FALSE, TRUE),
396 IA64_HOWTO (R_IA64_PLTOFF22, "PLTOFF22", 0, FALSE, TRUE),
397 IA64_HOWTO (R_IA64_PLTOFF64I, "PLTOFF64I", 0, FALSE, TRUE),
398 IA64_HOWTO (R_IA64_PLTOFF64MSB, "PLTOFF64MSB", 4, FALSE, TRUE),
399 IA64_HOWTO (R_IA64_PLTOFF64LSB, "PLTOFF64LSB", 4, FALSE, TRUE),
401 IA64_HOWTO (R_IA64_FPTR64I, "FPTR64I", 0, FALSE, TRUE),
402 IA64_HOWTO (R_IA64_FPTR32MSB, "FPTR32MSB", 2, FALSE, TRUE),
403 IA64_HOWTO (R_IA64_FPTR32LSB, "FPTR32LSB", 2, FALSE, TRUE),
404 IA64_HOWTO (R_IA64_FPTR64MSB, "FPTR64MSB", 4, FALSE, TRUE),
405 IA64_HOWTO (R_IA64_FPTR64LSB, "FPTR64LSB", 4, FALSE, TRUE),
407 IA64_HOWTO (R_IA64_PCREL60B, "PCREL60B", 0, TRUE, TRUE),
408 IA64_HOWTO (R_IA64_PCREL21B, "PCREL21B", 0, TRUE, TRUE),
409 IA64_HOWTO (R_IA64_PCREL21M, "PCREL21M", 0, TRUE, TRUE),
410 IA64_HOWTO (R_IA64_PCREL21F, "PCREL21F", 0, TRUE, TRUE),
411 IA64_HOWTO (R_IA64_PCREL32MSB, "PCREL32MSB", 2, TRUE, TRUE),
412 IA64_HOWTO (R_IA64_PCREL32LSB, "PCREL32LSB", 2, TRUE, TRUE),
413 IA64_HOWTO (R_IA64_PCREL64MSB, "PCREL64MSB", 4, TRUE, TRUE),
414 IA64_HOWTO (R_IA64_PCREL64LSB, "PCREL64LSB", 4, TRUE, TRUE),
416 IA64_HOWTO (R_IA64_LTOFF_FPTR22, "LTOFF_FPTR22", 0, FALSE, TRUE),
417 IA64_HOWTO (R_IA64_LTOFF_FPTR64I, "LTOFF_FPTR64I", 0, FALSE, TRUE),
418 IA64_HOWTO (R_IA64_LTOFF_FPTR32MSB, "LTOFF_FPTR32MSB", 2, FALSE, TRUE),
419 IA64_HOWTO (R_IA64_LTOFF_FPTR32LSB, "LTOFF_FPTR32LSB", 2, FALSE, TRUE),
420 IA64_HOWTO (R_IA64_LTOFF_FPTR64MSB, "LTOFF_FPTR64MSB", 4, FALSE, TRUE),
421 IA64_HOWTO (R_IA64_LTOFF_FPTR64LSB, "LTOFF_FPTR64LSB", 4, FALSE, TRUE),
423 IA64_HOWTO (R_IA64_SEGREL32MSB, "SEGREL32MSB", 2, FALSE, TRUE),
424 IA64_HOWTO (R_IA64_SEGREL32LSB, "SEGREL32LSB", 2, FALSE, TRUE),
425 IA64_HOWTO (R_IA64_SEGREL64MSB, "SEGREL64MSB", 4, FALSE, TRUE),
426 IA64_HOWTO (R_IA64_SEGREL64LSB, "SEGREL64LSB", 4, FALSE, TRUE),
428 IA64_HOWTO (R_IA64_SECREL32MSB, "SECREL32MSB", 2, FALSE, TRUE),
429 IA64_HOWTO (R_IA64_SECREL32LSB, "SECREL32LSB", 2, FALSE, TRUE),
430 IA64_HOWTO (R_IA64_SECREL64MSB, "SECREL64MSB", 4, FALSE, TRUE),
431 IA64_HOWTO (R_IA64_SECREL64LSB, "SECREL64LSB", 4, FALSE, TRUE),
433 IA64_HOWTO (R_IA64_REL32MSB, "REL32MSB", 2, FALSE, TRUE),
434 IA64_HOWTO (R_IA64_REL32LSB, "REL32LSB", 2, FALSE, TRUE),
435 IA64_HOWTO (R_IA64_REL64MSB, "REL64MSB", 4, FALSE, TRUE),
436 IA64_HOWTO (R_IA64_REL64LSB, "REL64LSB", 4, FALSE, TRUE),
438 IA64_HOWTO (R_IA64_LTV32MSB, "LTV32MSB", 2, FALSE, TRUE),
439 IA64_HOWTO (R_IA64_LTV32LSB, "LTV32LSB", 2, FALSE, TRUE),
440 IA64_HOWTO (R_IA64_LTV64MSB, "LTV64MSB", 4, FALSE, TRUE),
441 IA64_HOWTO (R_IA64_LTV64LSB, "LTV64LSB", 4, FALSE, TRUE),
443 IA64_HOWTO (R_IA64_PCREL21BI, "PCREL21BI", 0, TRUE, TRUE),
444 IA64_HOWTO (R_IA64_PCREL22, "PCREL22", 0, TRUE, TRUE),
445 IA64_HOWTO (R_IA64_PCREL64I, "PCREL64I", 0, TRUE, TRUE),
447 IA64_HOWTO (R_IA64_IPLTMSB, "IPLTMSB", 4, FALSE, TRUE),
448 IA64_HOWTO (R_IA64_IPLTLSB, "IPLTLSB", 4, FALSE, TRUE),
449 IA64_HOWTO (R_IA64_COPY, "COPY", 4, FALSE, TRUE),
450 IA64_HOWTO (R_IA64_LTOFF22X, "LTOFF22X", 0, FALSE, TRUE),
451 IA64_HOWTO (R_IA64_LDXMOV, "LDXMOV", 0, FALSE, TRUE),
453 IA64_HOWTO (R_IA64_TPREL14, "TPREL14", 0, FALSE, FALSE),
454 IA64_HOWTO (R_IA64_TPREL22, "TPREL22", 0, FALSE, FALSE),
455 IA64_HOWTO (R_IA64_TPREL64I, "TPREL64I", 0, FALSE, FALSE),
456 IA64_HOWTO (R_IA64_TPREL64MSB, "TPREL64MSB", 8, FALSE, FALSE),
457 IA64_HOWTO (R_IA64_TPREL64LSB, "TPREL64LSB", 8, FALSE, FALSE),
458 IA64_HOWTO (R_IA64_LTOFF_TPREL22, "LTOFF_TPREL22", 0, FALSE, FALSE),
460 IA64_HOWTO (R_IA64_DTPMOD64MSB, "TPREL64MSB", 8, FALSE, FALSE),
461 IA64_HOWTO (R_IA64_DTPMOD64LSB, "TPREL64LSB", 8, FALSE, FALSE),
462 IA64_HOWTO (R_IA64_LTOFF_DTPMOD22, "LTOFF_DTPMOD22", 0, FALSE, FALSE),
464 IA64_HOWTO (R_IA64_DTPREL14, "DTPREL14", 0, FALSE, FALSE),
465 IA64_HOWTO (R_IA64_DTPREL22, "DTPREL22", 0, FALSE, FALSE),
466 IA64_HOWTO (R_IA64_DTPREL64I, "DTPREL64I", 0, FALSE, FALSE),
467 IA64_HOWTO (R_IA64_DTPREL32MSB, "DTPREL32MSB", 4, FALSE, FALSE),
468 IA64_HOWTO (R_IA64_DTPREL32LSB, "DTPREL32LSB", 4, FALSE, FALSE),
469 IA64_HOWTO (R_IA64_DTPREL64MSB, "DTPREL64MSB", 8, FALSE, FALSE),
470 IA64_HOWTO (R_IA64_DTPREL64LSB, "DTPREL64LSB", 8, FALSE, FALSE),
471 IA64_HOWTO (R_IA64_LTOFF_DTPREL22, "LTOFF_DTPREL22", 0, FALSE, FALSE),
474 static unsigned char elf_code_to_howto_index[R_IA64_MAX_RELOC_CODE + 1];
476 /* Given a BFD reloc type, return the matching HOWTO structure. */
478 static reloc_howto_type *
479 lookup_howto (rtype)
480 unsigned int rtype;
482 static int inited = 0;
483 int i;
485 if (!inited)
487 inited = 1;
489 memset (elf_code_to_howto_index, 0xff, sizeof (elf_code_to_howto_index));
490 for (i = 0; i < NELEMS (ia64_howto_table); ++i)
491 elf_code_to_howto_index[ia64_howto_table[i].type] = i;
494 BFD_ASSERT (rtype <= R_IA64_MAX_RELOC_CODE);
495 i = elf_code_to_howto_index[rtype];
496 if (i >= NELEMS (ia64_howto_table))
497 return 0;
498 return ia64_howto_table + i;
501 static reloc_howto_type*
502 elfNN_ia64_reloc_type_lookup (abfd, bfd_code)
503 bfd *abfd ATTRIBUTE_UNUSED;
504 bfd_reloc_code_real_type bfd_code;
506 unsigned int rtype;
508 switch (bfd_code)
510 case BFD_RELOC_NONE: rtype = R_IA64_NONE; break;
512 case BFD_RELOC_IA64_IMM14: rtype = R_IA64_IMM14; break;
513 case BFD_RELOC_IA64_IMM22: rtype = R_IA64_IMM22; break;
514 case BFD_RELOC_IA64_IMM64: rtype = R_IA64_IMM64; break;
516 case BFD_RELOC_IA64_DIR32MSB: rtype = R_IA64_DIR32MSB; break;
517 case BFD_RELOC_IA64_DIR32LSB: rtype = R_IA64_DIR32LSB; break;
518 case BFD_RELOC_IA64_DIR64MSB: rtype = R_IA64_DIR64MSB; break;
519 case BFD_RELOC_IA64_DIR64LSB: rtype = R_IA64_DIR64LSB; break;
521 case BFD_RELOC_IA64_GPREL22: rtype = R_IA64_GPREL22; break;
522 case BFD_RELOC_IA64_GPREL64I: rtype = R_IA64_GPREL64I; break;
523 case BFD_RELOC_IA64_GPREL32MSB: rtype = R_IA64_GPREL32MSB; break;
524 case BFD_RELOC_IA64_GPREL32LSB: rtype = R_IA64_GPREL32LSB; break;
525 case BFD_RELOC_IA64_GPREL64MSB: rtype = R_IA64_GPREL64MSB; break;
526 case BFD_RELOC_IA64_GPREL64LSB: rtype = R_IA64_GPREL64LSB; break;
528 case BFD_RELOC_IA64_LTOFF22: rtype = R_IA64_LTOFF22; break;
529 case BFD_RELOC_IA64_LTOFF64I: rtype = R_IA64_LTOFF64I; break;
531 case BFD_RELOC_IA64_PLTOFF22: rtype = R_IA64_PLTOFF22; break;
532 case BFD_RELOC_IA64_PLTOFF64I: rtype = R_IA64_PLTOFF64I; break;
533 case BFD_RELOC_IA64_PLTOFF64MSB: rtype = R_IA64_PLTOFF64MSB; break;
534 case BFD_RELOC_IA64_PLTOFF64LSB: rtype = R_IA64_PLTOFF64LSB; break;
535 case BFD_RELOC_IA64_FPTR64I: rtype = R_IA64_FPTR64I; break;
536 case BFD_RELOC_IA64_FPTR32MSB: rtype = R_IA64_FPTR32MSB; break;
537 case BFD_RELOC_IA64_FPTR32LSB: rtype = R_IA64_FPTR32LSB; break;
538 case BFD_RELOC_IA64_FPTR64MSB: rtype = R_IA64_FPTR64MSB; break;
539 case BFD_RELOC_IA64_FPTR64LSB: rtype = R_IA64_FPTR64LSB; break;
541 case BFD_RELOC_IA64_PCREL21B: rtype = R_IA64_PCREL21B; break;
542 case BFD_RELOC_IA64_PCREL21BI: rtype = R_IA64_PCREL21BI; break;
543 case BFD_RELOC_IA64_PCREL21M: rtype = R_IA64_PCREL21M; break;
544 case BFD_RELOC_IA64_PCREL21F: rtype = R_IA64_PCREL21F; break;
545 case BFD_RELOC_IA64_PCREL22: rtype = R_IA64_PCREL22; break;
546 case BFD_RELOC_IA64_PCREL60B: rtype = R_IA64_PCREL60B; break;
547 case BFD_RELOC_IA64_PCREL64I: rtype = R_IA64_PCREL64I; break;
548 case BFD_RELOC_IA64_PCREL32MSB: rtype = R_IA64_PCREL32MSB; break;
549 case BFD_RELOC_IA64_PCREL32LSB: rtype = R_IA64_PCREL32LSB; break;
550 case BFD_RELOC_IA64_PCREL64MSB: rtype = R_IA64_PCREL64MSB; break;
551 case BFD_RELOC_IA64_PCREL64LSB: rtype = R_IA64_PCREL64LSB; break;
553 case BFD_RELOC_IA64_LTOFF_FPTR22: rtype = R_IA64_LTOFF_FPTR22; break;
554 case BFD_RELOC_IA64_LTOFF_FPTR64I: rtype = R_IA64_LTOFF_FPTR64I; break;
555 case BFD_RELOC_IA64_LTOFF_FPTR32MSB: rtype = R_IA64_LTOFF_FPTR32MSB; break;
556 case BFD_RELOC_IA64_LTOFF_FPTR32LSB: rtype = R_IA64_LTOFF_FPTR32LSB; break;
557 case BFD_RELOC_IA64_LTOFF_FPTR64MSB: rtype = R_IA64_LTOFF_FPTR64MSB; break;
558 case BFD_RELOC_IA64_LTOFF_FPTR64LSB: rtype = R_IA64_LTOFF_FPTR64LSB; break;
560 case BFD_RELOC_IA64_SEGREL32MSB: rtype = R_IA64_SEGREL32MSB; break;
561 case BFD_RELOC_IA64_SEGREL32LSB: rtype = R_IA64_SEGREL32LSB; break;
562 case BFD_RELOC_IA64_SEGREL64MSB: rtype = R_IA64_SEGREL64MSB; break;
563 case BFD_RELOC_IA64_SEGREL64LSB: rtype = R_IA64_SEGREL64LSB; break;
565 case BFD_RELOC_IA64_SECREL32MSB: rtype = R_IA64_SECREL32MSB; break;
566 case BFD_RELOC_IA64_SECREL32LSB: rtype = R_IA64_SECREL32LSB; break;
567 case BFD_RELOC_IA64_SECREL64MSB: rtype = R_IA64_SECREL64MSB; break;
568 case BFD_RELOC_IA64_SECREL64LSB: rtype = R_IA64_SECREL64LSB; break;
570 case BFD_RELOC_IA64_REL32MSB: rtype = R_IA64_REL32MSB; break;
571 case BFD_RELOC_IA64_REL32LSB: rtype = R_IA64_REL32LSB; break;
572 case BFD_RELOC_IA64_REL64MSB: rtype = R_IA64_REL64MSB; break;
573 case BFD_RELOC_IA64_REL64LSB: rtype = R_IA64_REL64LSB; break;
575 case BFD_RELOC_IA64_LTV32MSB: rtype = R_IA64_LTV32MSB; break;
576 case BFD_RELOC_IA64_LTV32LSB: rtype = R_IA64_LTV32LSB; break;
577 case BFD_RELOC_IA64_LTV64MSB: rtype = R_IA64_LTV64MSB; break;
578 case BFD_RELOC_IA64_LTV64LSB: rtype = R_IA64_LTV64LSB; break;
580 case BFD_RELOC_IA64_IPLTMSB: rtype = R_IA64_IPLTMSB; break;
581 case BFD_RELOC_IA64_IPLTLSB: rtype = R_IA64_IPLTLSB; break;
582 case BFD_RELOC_IA64_COPY: rtype = R_IA64_COPY; break;
583 case BFD_RELOC_IA64_LTOFF22X: rtype = R_IA64_LTOFF22X; break;
584 case BFD_RELOC_IA64_LDXMOV: rtype = R_IA64_LDXMOV; break;
586 case BFD_RELOC_IA64_TPREL14: rtype = R_IA64_TPREL14; break;
587 case BFD_RELOC_IA64_TPREL22: rtype = R_IA64_TPREL22; break;
588 case BFD_RELOC_IA64_TPREL64I: rtype = R_IA64_TPREL64I; break;
589 case BFD_RELOC_IA64_TPREL64MSB: rtype = R_IA64_TPREL64MSB; break;
590 case BFD_RELOC_IA64_TPREL64LSB: rtype = R_IA64_TPREL64LSB; break;
591 case BFD_RELOC_IA64_LTOFF_TPREL22: rtype = R_IA64_LTOFF_TPREL22; break;
593 case BFD_RELOC_IA64_DTPMOD64MSB: rtype = R_IA64_DTPMOD64MSB; break;
594 case BFD_RELOC_IA64_DTPMOD64LSB: rtype = R_IA64_DTPMOD64LSB; break;
595 case BFD_RELOC_IA64_LTOFF_DTPMOD22: rtype = R_IA64_LTOFF_DTPMOD22; break;
597 case BFD_RELOC_IA64_DTPREL14: rtype = R_IA64_DTPREL14; break;
598 case BFD_RELOC_IA64_DTPREL22: rtype = R_IA64_DTPREL22; break;
599 case BFD_RELOC_IA64_DTPREL64I: rtype = R_IA64_DTPREL64I; break;
600 case BFD_RELOC_IA64_DTPREL32MSB: rtype = R_IA64_DTPREL32MSB; break;
601 case BFD_RELOC_IA64_DTPREL32LSB: rtype = R_IA64_DTPREL32LSB; break;
602 case BFD_RELOC_IA64_DTPREL64MSB: rtype = R_IA64_DTPREL64MSB; break;
603 case BFD_RELOC_IA64_DTPREL64LSB: rtype = R_IA64_DTPREL64LSB; break;
604 case BFD_RELOC_IA64_LTOFF_DTPREL22: rtype = R_IA64_LTOFF_DTPREL22; break;
606 default: return 0;
608 return lookup_howto (rtype);
611 /* Given a ELF reloc, return the matching HOWTO structure. */
613 static void
614 elfNN_ia64_info_to_howto (abfd, bfd_reloc, elf_reloc)
615 bfd *abfd ATTRIBUTE_UNUSED;
616 arelent *bfd_reloc;
617 Elf_Internal_Rela *elf_reloc;
619 bfd_reloc->howto
620 = lookup_howto ((unsigned int) ELFNN_R_TYPE (elf_reloc->r_info));
623 #define PLT_HEADER_SIZE (3 * 16)
624 #define PLT_MIN_ENTRY_SIZE (1 * 16)
625 #define PLT_FULL_ENTRY_SIZE (2 * 16)
626 #define PLT_RESERVED_WORDS 3
628 static const bfd_byte plt_header[PLT_HEADER_SIZE] =
630 0x0b, 0x10, 0x00, 0x1c, 0x00, 0x21, /* [MMI] mov r2=r14;; */
631 0xe0, 0x00, 0x08, 0x00, 0x48, 0x00, /* addl r14=0,r2 */
632 0x00, 0x00, 0x04, 0x00, /* nop.i 0x0;; */
633 0x0b, 0x80, 0x20, 0x1c, 0x18, 0x14, /* [MMI] ld8 r16=[r14],8;; */
634 0x10, 0x41, 0x38, 0x30, 0x28, 0x00, /* ld8 r17=[r14],8 */
635 0x00, 0x00, 0x04, 0x00, /* nop.i 0x0;; */
636 0x11, 0x08, 0x00, 0x1c, 0x18, 0x10, /* [MIB] ld8 r1=[r14] */
637 0x60, 0x88, 0x04, 0x80, 0x03, 0x00, /* mov b6=r17 */
638 0x60, 0x00, 0x80, 0x00 /* br.few b6;; */
641 static const bfd_byte plt_min_entry[PLT_MIN_ENTRY_SIZE] =
643 0x11, 0x78, 0x00, 0x00, 0x00, 0x24, /* [MIB] mov r15=0 */
644 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, /* nop.i 0x0 */
645 0x00, 0x00, 0x00, 0x40 /* br.few 0 <PLT0>;; */
648 static const bfd_byte plt_full_entry[PLT_FULL_ENTRY_SIZE] =
650 0x0b, 0x78, 0x00, 0x02, 0x00, 0x24, /* [MMI] addl r15=0,r1;; */
651 0x00, 0x41, 0x3c, 0x30, 0x28, 0xc0, /* ld8 r16=[r15],8 */
652 0x01, 0x08, 0x00, 0x84, /* mov r14=r1;; */
653 0x11, 0x08, 0x00, 0x1e, 0x18, 0x10, /* [MIB] ld8 r1=[r15] */
654 0x60, 0x80, 0x04, 0x80, 0x03, 0x00, /* mov b6=r16 */
655 0x60, 0x00, 0x80, 0x00 /* br.few b6;; */
658 #define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"
659 #define AIX_DYNAMIC_INTERPRETER "/usr/lib/ia64l64/libc.so.1"
660 #define DYNAMIC_INTERPRETER(abfd) \
661 (elfNN_ia64_aix_vec (abfd->xvec) ? AIX_DYNAMIC_INTERPRETER : ELF_DYNAMIC_INTERPRETER)
663 static const bfd_byte oor_brl[16] =
665 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MLX] nop.m 0 */
666 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* brl.sptk.few tgt;; */
667 0x00, 0x00, 0x00, 0xc0
670 /* These functions do relaxation for IA-64 ELF. */
672 static bfd_boolean
673 elfNN_ia64_relax_section (abfd, sec, link_info, again)
674 bfd *abfd;
675 asection *sec;
676 struct bfd_link_info *link_info;
677 bfd_boolean *again;
679 struct one_fixup
681 struct one_fixup *next;
682 asection *tsec;
683 bfd_vma toff;
684 bfd_vma trampoff;
687 Elf_Internal_Shdr *symtab_hdr;
688 Elf_Internal_Rela *internal_relocs;
689 Elf_Internal_Rela *irel, *irelend;
690 bfd_byte *contents;
691 Elf_Internal_Sym *isymbuf = NULL;
692 struct elfNN_ia64_link_hash_table *ia64_info;
693 struct one_fixup *fixups = NULL;
694 bfd_boolean changed_contents = FALSE;
695 bfd_boolean changed_relocs = FALSE;
696 bfd_boolean changed_got = FALSE;
697 bfd_vma gp = 0;
699 /* Assume we're not going to change any sizes, and we'll only need
700 one pass. */
701 *again = FALSE;
703 /* Don't even try to relax for non-ELF outputs. */
704 if (link_info->hash->creator->flavour != bfd_target_elf_flavour)
705 return FALSE;
707 /* Nothing to do if there are no relocations. */
708 if ((sec->flags & SEC_RELOC) == 0
709 || sec->reloc_count == 0)
710 return TRUE;
712 /* If this is the first time we have been called for this section,
713 initialize the cooked size. */
714 if (sec->_cooked_size == 0)
715 sec->_cooked_size = sec->_raw_size;
717 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
719 /* Load the relocations for this section. */
720 internal_relocs = (_bfd_elfNN_link_read_relocs
721 (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
722 link_info->keep_memory));
723 if (internal_relocs == NULL)
724 return FALSE;
726 ia64_info = elfNN_ia64_hash_table (link_info);
727 irelend = internal_relocs + sec->reloc_count;
729 /* Get the section contents. */
730 if (elf_section_data (sec)->this_hdr.contents != NULL)
731 contents = elf_section_data (sec)->this_hdr.contents;
732 else
734 contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
735 if (contents == NULL)
736 goto error_return;
738 if (! bfd_get_section_contents (abfd, sec, contents,
739 (file_ptr) 0, sec->_raw_size))
740 goto error_return;
743 for (irel = internal_relocs; irel < irelend; irel++)
745 unsigned long r_type = ELFNN_R_TYPE (irel->r_info);
746 bfd_vma symaddr, reladdr, trampoff, toff, roff;
747 asection *tsec;
748 struct one_fixup *f;
749 bfd_size_type amt;
750 bfd_boolean is_branch;
751 struct elfNN_ia64_dyn_sym_info *dyn_i;
753 switch (r_type)
755 case R_IA64_PCREL21B:
756 case R_IA64_PCREL21BI:
757 case R_IA64_PCREL21M:
758 case R_IA64_PCREL21F:
759 is_branch = TRUE;
760 break;
762 case R_IA64_LTOFF22X:
763 case R_IA64_LDXMOV:
764 is_branch = FALSE;
765 break;
767 default:
768 continue;
771 /* Get the value of the symbol referred to by the reloc. */
772 if (ELFNN_R_SYM (irel->r_info) < symtab_hdr->sh_info)
774 /* A local symbol. */
775 Elf_Internal_Sym *isym;
777 /* Read this BFD's local symbols. */
778 if (isymbuf == NULL)
780 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
781 if (isymbuf == NULL)
782 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
783 symtab_hdr->sh_info, 0,
784 NULL, NULL, NULL);
785 if (isymbuf == 0)
786 goto error_return;
789 isym = isymbuf + ELF64_R_SYM (irel->r_info);
790 if (isym->st_shndx == SHN_UNDEF)
791 continue; /* We can't do anthing with undefined symbols. */
792 else if (isym->st_shndx == SHN_ABS)
793 tsec = bfd_abs_section_ptr;
794 else if (isym->st_shndx == SHN_COMMON)
795 tsec = bfd_com_section_ptr;
796 else if (isym->st_shndx == SHN_IA_64_ANSI_COMMON)
797 tsec = bfd_com_section_ptr;
798 else
799 tsec = bfd_section_from_elf_index (abfd, isym->st_shndx);
801 toff = isym->st_value;
802 dyn_i = get_dyn_sym_info (ia64_info, NULL, abfd, irel, FALSE);
804 else
806 unsigned long indx;
807 struct elf_link_hash_entry *h;
809 indx = ELFNN_R_SYM (irel->r_info) - symtab_hdr->sh_info;
810 h = elf_sym_hashes (abfd)[indx];
811 BFD_ASSERT (h != NULL);
813 while (h->root.type == bfd_link_hash_indirect
814 || h->root.type == bfd_link_hash_warning)
815 h = (struct elf_link_hash_entry *) h->root.u.i.link;
817 dyn_i = get_dyn_sym_info (ia64_info, h, abfd, irel, FALSE);
819 /* For branches to dynamic symbols, we're interested instead
820 in a branch to the PLT entry. */
821 if (is_branch && dyn_i && dyn_i->want_plt2)
823 /* Internal branches shouldn't be sent to the PLT.
824 Leave this for now and we'll give an error later. */
825 if (r_type != R_IA64_PCREL21B)
826 continue;
828 tsec = ia64_info->plt_sec;
829 toff = dyn_i->plt2_offset;
830 BFD_ASSERT (irel->r_addend == 0);
833 /* Can't do anything else with dynamic symbols. */
834 else if (elfNN_ia64_dynamic_symbol_p (h, link_info))
835 continue;
837 else
839 /* We can't do anthing with undefined symbols. */
840 if (h->root.type == bfd_link_hash_undefined
841 || h->root.type == bfd_link_hash_undefweak)
842 continue;
844 tsec = h->root.u.def.section;
845 toff = h->root.u.def.value;
849 if (tsec->sec_info_type == ELF_INFO_TYPE_MERGE)
850 toff = _bfd_merged_section_offset (abfd, &tsec,
851 elf_section_data (tsec)->sec_info,
852 toff + irel->r_addend,
853 (bfd_vma) 0);
854 else
855 toff += irel->r_addend;
857 symaddr = tsec->output_section->vma + tsec->output_offset + toff;
859 roff = irel->r_offset;
861 if (is_branch)
863 reladdr = (sec->output_section->vma
864 + sec->output_offset
865 + roff) & (bfd_vma) -4;
867 /* If the branch is in range, no need to do anything. */
868 if ((bfd_signed_vma) (symaddr - reladdr) >= -0x1000000
869 && (bfd_signed_vma) (symaddr - reladdr) <= 0x0FFFFF0)
870 continue;
872 /* If the branch and target are in the same section, you've
873 got one honking big section and we can't help you. You'll
874 get an error message later. */
875 if (tsec == sec)
876 continue;
878 /* Look for an existing fixup to this address. */
879 for (f = fixups; f ; f = f->next)
880 if (f->tsec == tsec && f->toff == toff)
881 break;
883 if (f == NULL)
885 /* Two alternatives: If it's a branch to a PLT entry, we can
886 make a copy of the FULL_PLT entry. Otherwise, we'll have
887 to use a `brl' insn to get where we're going. */
889 size_t size;
891 if (tsec == ia64_info->plt_sec)
892 size = sizeof (plt_full_entry);
893 else
895 size = sizeof (oor_brl);
898 /* Resize the current section to make room for the new branch. */
899 trampoff = (sec->_cooked_size + 15) & (bfd_vma) -16;
900 amt = trampoff + size;
901 contents = (bfd_byte *) bfd_realloc (contents, amt);
902 if (contents == NULL)
903 goto error_return;
904 sec->_cooked_size = amt;
906 if (tsec == ia64_info->plt_sec)
908 memcpy (contents + trampoff, plt_full_entry, size);
910 /* Hijack the old relocation for use as the PLTOFF reloc. */
911 irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info),
912 R_IA64_PLTOFF22);
913 irel->r_offset = trampoff;
915 else
917 memcpy (contents + trampoff, oor_brl, size);
918 irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info),
919 R_IA64_PCREL60B);
920 irel->r_offset = trampoff + 2;
923 /* Record the fixup so we don't do it again this section. */
924 f = (struct one_fixup *)
925 bfd_malloc ((bfd_size_type) sizeof (*f));
926 f->next = fixups;
927 f->tsec = tsec;
928 f->toff = toff;
929 f->trampoff = trampoff;
930 fixups = f;
932 else
934 /* Nop out the reloc, since we're finalizing things here. */
935 irel->r_info = ELFNN_R_INFO (0, R_IA64_NONE);
938 /* Fix up the existing branch to hit the trampoline. Hope like
939 hell this doesn't overflow too. */
940 if (elfNN_ia64_install_value (abfd, contents + roff,
941 f->trampoff - (roff & (bfd_vma) -4),
942 r_type) != bfd_reloc_ok)
943 goto error_return;
945 changed_contents = TRUE;
946 changed_relocs = TRUE;
948 else
950 /* Fetch the gp. */
951 if (gp == 0)
953 bfd *obfd = sec->output_section->owner;
954 gp = _bfd_get_gp_value (obfd);
955 if (gp == 0)
957 if (!elfNN_ia64_choose_gp (obfd, link_info))
958 goto error_return;
959 gp = _bfd_get_gp_value (obfd);
963 /* If the data is out of range, do nothing. */
964 if ((bfd_signed_vma) (symaddr - gp) >= 0x200000
965 ||(bfd_signed_vma) (symaddr - gp) < -0x200000)
966 continue;
968 if (r_type == R_IA64_LTOFF22X)
970 irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info),
971 R_IA64_GPREL22);
972 changed_relocs = TRUE;
973 if (dyn_i->want_gotx)
975 dyn_i->want_gotx = 0;
976 changed_got |= !dyn_i->want_got;
979 else
981 elfNN_ia64_relax_ldxmov (abfd, contents, roff);
982 irel->r_info = ELFNN_R_INFO (0, R_IA64_NONE);
983 changed_contents = TRUE;
984 changed_relocs = TRUE;
989 /* ??? If we created fixups, this may push the code segment large
990 enough that the data segment moves, which will change the GP.
991 Reset the GP so that we re-calculate next round. We need to
992 do this at the _beginning_ of the next round; now will not do. */
994 /* Clean up and go home. */
995 while (fixups)
997 struct one_fixup *f = fixups;
998 fixups = fixups->next;
999 free (f);
1002 if (isymbuf != NULL
1003 && symtab_hdr->contents != (unsigned char *) isymbuf)
1005 if (! link_info->keep_memory)
1006 free (isymbuf);
1007 else
1009 /* Cache the symbols for elf_link_input_bfd. */
1010 symtab_hdr->contents = (unsigned char *) isymbuf;
1014 if (contents != NULL
1015 && elf_section_data (sec)->this_hdr.contents != contents)
1017 if (!changed_contents && !link_info->keep_memory)
1018 free (contents);
1019 else
1021 /* Cache the section contents for elf_link_input_bfd. */
1022 elf_section_data (sec)->this_hdr.contents = contents;
1026 if (elf_section_data (sec)->relocs != internal_relocs)
1028 if (!changed_relocs)
1029 free (internal_relocs);
1030 else
1031 elf_section_data (sec)->relocs = internal_relocs;
1034 if (changed_got)
1036 struct elfNN_ia64_allocate_data data;
1037 data.info = link_info;
1038 data.ofs = 0;
1039 ia64_info->self_dtpmod_offset = (bfd_vma) -1;
1041 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_data_got, &data);
1042 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_fptr_got, &data);
1043 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_local_got, &data);
1044 ia64_info->got_sec->_raw_size = data.ofs;
1045 ia64_info->got_sec->_cooked_size = data.ofs;
1047 /* ??? Resize .rela.got too. */
1050 *again = changed_contents || changed_relocs;
1051 return TRUE;
1053 error_return:
1054 if (isymbuf != NULL && (unsigned char *) isymbuf != symtab_hdr->contents)
1055 free (isymbuf);
1056 if (contents != NULL
1057 && elf_section_data (sec)->this_hdr.contents != contents)
1058 free (contents);
1059 if (internal_relocs != NULL
1060 && elf_section_data (sec)->relocs != internal_relocs)
1061 free (internal_relocs);
1062 return FALSE;
1065 static void
1066 elfNN_ia64_relax_ldxmov (abfd, contents, off)
1067 bfd *abfd;
1068 bfd_byte *contents;
1069 bfd_vma off;
1071 int shift, r1, r3;
1072 bfd_vma dword, insn;
1074 switch ((int)off & 0x3)
1076 case 0: shift = 5; break;
1077 case 1: shift = 14; off += 3; break;
1078 case 2: shift = 23; off += 6; break;
1079 case 3:
1080 abort ();
1083 dword = bfd_get_64 (abfd, contents + off);
1084 insn = (dword >> shift) & 0x1ffffffffffLL;
1086 r1 = (insn >> 6) & 127;
1087 r3 = (insn >> 20) & 127;
1088 if (r1 == r3)
1089 insn = 0x8000000; /* nop */
1090 else
1091 insn = (insn & 0x7f01fff) | 0x10800000000LL; /* (qp) mov r1 = r3 */
1093 dword &= ~(0x1ffffffffffLL << shift);
1094 dword |= (insn << shift);
1095 bfd_put_64 (abfd, dword, contents + off);
1098 /* Return TRUE if NAME is an unwind table section name. */
1100 static inline bfd_boolean
1101 is_unwind_section_name (abfd, name)
1102 bfd *abfd;
1103 const char *name;
1105 size_t len1, len2, len3;
1107 if (elfNN_ia64_hpux_vec (abfd->xvec)
1108 && !strcmp (name, ELF_STRING_ia64_unwind_hdr))
1109 return FALSE;
1111 len1 = sizeof (ELF_STRING_ia64_unwind) - 1;
1112 len2 = sizeof (ELF_STRING_ia64_unwind_info) - 1;
1113 len3 = sizeof (ELF_STRING_ia64_unwind_once) - 1;
1114 return ((strncmp (name, ELF_STRING_ia64_unwind, len1) == 0
1115 && strncmp (name, ELF_STRING_ia64_unwind_info, len2) != 0)
1116 || strncmp (name, ELF_STRING_ia64_unwind_once, len3) == 0);
1119 /* Handle an IA-64 specific section when reading an object file. This
1120 is called when elfcode.h finds a section with an unknown type. */
1122 static bfd_boolean
1123 elfNN_ia64_section_from_shdr (abfd, hdr, name)
1124 bfd *abfd;
1125 Elf_Internal_Shdr *hdr;
1126 const char *name;
1128 asection *newsect;
1130 /* There ought to be a place to keep ELF backend specific flags, but
1131 at the moment there isn't one. We just keep track of the
1132 sections by their name, instead. Fortunately, the ABI gives
1133 suggested names for all the MIPS specific sections, so we will
1134 probably get away with this. */
1135 switch (hdr->sh_type)
1137 case SHT_IA_64_UNWIND:
1138 case SHT_IA_64_HP_OPT_ANOT:
1139 break;
1141 case SHT_IA_64_EXT:
1142 if (strcmp (name, ELF_STRING_ia64_archext) != 0)
1143 return FALSE;
1144 break;
1146 default:
1147 return FALSE;
1150 if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
1151 return FALSE;
1152 newsect = hdr->bfd_section;
1154 return TRUE;
1157 /* Convert IA-64 specific section flags to bfd internal section flags. */
1159 /* ??? There is no bfd internal flag equivalent to the SHF_IA_64_NORECOV
1160 flag. */
1162 static bfd_boolean
1163 elfNN_ia64_section_flags (flags, hdr)
1164 flagword *flags;
1165 Elf_Internal_Shdr *hdr;
1167 if (hdr->sh_flags & SHF_IA_64_SHORT)
1168 *flags |= SEC_SMALL_DATA;
1170 return TRUE;
1173 /* Set the correct type for an IA-64 ELF section. We do this by the
1174 section name, which is a hack, but ought to work. */
1176 static bfd_boolean
1177 elfNN_ia64_fake_sections (abfd, hdr, sec)
1178 bfd *abfd ATTRIBUTE_UNUSED;
1179 Elf_Internal_Shdr *hdr;
1180 asection *sec;
1182 register const char *name;
1184 name = bfd_get_section_name (abfd, sec);
1186 if (is_unwind_section_name (abfd, name))
1188 /* We don't have the sections numbered at this point, so sh_info
1189 is set later, in elfNN_ia64_final_write_processing. */
1190 hdr->sh_type = SHT_IA_64_UNWIND;
1191 hdr->sh_flags |= SHF_LINK_ORDER;
1193 else if (strcmp (name, ELF_STRING_ia64_archext) == 0)
1194 hdr->sh_type = SHT_IA_64_EXT;
1195 else if (strcmp (name, ".HP.opt_annot") == 0)
1196 hdr->sh_type = SHT_IA_64_HP_OPT_ANOT;
1197 else if (strcmp (name, ".reloc") == 0)
1198 /* This is an ugly, but unfortunately necessary hack that is
1199 needed when producing EFI binaries on IA-64. It tells
1200 elf.c:elf_fake_sections() not to consider ".reloc" as a section
1201 containing ELF relocation info. We need this hack in order to
1202 be able to generate ELF binaries that can be translated into
1203 EFI applications (which are essentially COFF objects). Those
1204 files contain a COFF ".reloc" section inside an ELFNN object,
1205 which would normally cause BFD to segfault because it would
1206 attempt to interpret this section as containing relocation
1207 entries for section "oc". With this hack enabled, ".reloc"
1208 will be treated as a normal data section, which will avoid the
1209 segfault. However, you won't be able to create an ELFNN binary
1210 with a section named "oc" that needs relocations, but that's
1211 the kind of ugly side-effects you get when detecting section
1212 types based on their names... In practice, this limitation is
1213 unlikely to bite. */
1214 hdr->sh_type = SHT_PROGBITS;
1216 if (sec->flags & SEC_SMALL_DATA)
1217 hdr->sh_flags |= SHF_IA_64_SHORT;
1219 return TRUE;
1222 /* The final processing done just before writing out an IA-64 ELF
1223 object file. */
1225 static void
1226 elfNN_ia64_final_write_processing (abfd, linker)
1227 bfd *abfd;
1228 bfd_boolean linker ATTRIBUTE_UNUSED;
1230 Elf_Internal_Shdr *hdr;
1231 const char *sname;
1232 asection *text_sect, *s;
1233 size_t len;
1235 for (s = abfd->sections; s; s = s->next)
1237 hdr = &elf_section_data (s)->this_hdr;
1238 switch (hdr->sh_type)
1240 case SHT_IA_64_UNWIND:
1241 /* See comments in gas/config/tc-ia64.c:dot_endp on why we
1242 have to do this. */
1243 sname = bfd_get_section_name (abfd, s);
1244 len = sizeof (ELF_STRING_ia64_unwind) - 1;
1245 if (sname && strncmp (sname, ELF_STRING_ia64_unwind, len) == 0)
1247 sname += len;
1249 if (sname[0] == '\0')
1250 /* .IA_64.unwind -> .text */
1251 text_sect = bfd_get_section_by_name (abfd, ".text");
1252 else
1253 /* .IA_64.unwindFOO -> FOO */
1254 text_sect = bfd_get_section_by_name (abfd, sname);
1256 else if (sname
1257 && (len = sizeof (ELF_STRING_ia64_unwind_once) - 1,
1258 strncmp (sname, ELF_STRING_ia64_unwind_once, len)) == 0)
1260 /* .gnu.linkonce.ia64unw.FOO -> .gnu.linkonce.t.FOO */
1261 size_t len2 = sizeof (".gnu.linkonce.t.") - 1;
1262 char *once_name = bfd_malloc (len2 + strlen (sname + len) + 1);
1264 if (once_name != NULL)
1266 memcpy (once_name, ".gnu.linkonce.t.", len2);
1267 strcpy (once_name + len2, sname + len);
1268 text_sect = bfd_get_section_by_name (abfd, once_name);
1269 free (once_name);
1271 else
1272 /* Should only happen if we run out of memory, in
1273 which case we're probably toast anyway. Try to
1274 cope by finding the section the slow way. */
1275 for (text_sect = abfd->sections;
1276 text_sect != NULL;
1277 text_sect = text_sect->next)
1279 if (strncmp (bfd_section_name (abfd, text_sect),
1280 ".gnu.linkonce.t.", len2) == 0
1281 && strcmp (bfd_section_name (abfd, text_sect) + len2,
1282 sname + len) == 0)
1283 break;
1286 else
1287 /* last resort: fall back on .text */
1288 text_sect = bfd_get_section_by_name (abfd, ".text");
1290 if (text_sect)
1292 /* The IA-64 processor-specific ABI requires setting
1293 sh_link to the unwind section, whereas HP-UX requires
1294 sh_info to do so. For maximum compatibility, we'll
1295 set both for now... */
1296 hdr->sh_link = elf_section_data (text_sect)->this_idx;
1297 hdr->sh_info = elf_section_data (text_sect)->this_idx;
1299 break;
1303 if (! elf_flags_init (abfd))
1305 unsigned long flags = 0;
1307 if (abfd->xvec->byteorder == BFD_ENDIAN_BIG)
1308 flags |= EF_IA_64_BE;
1309 if (bfd_get_mach (abfd) == bfd_mach_ia64_elf64)
1310 flags |= EF_IA_64_ABI64;
1312 elf_elfheader(abfd)->e_flags = flags;
1313 elf_flags_init (abfd) = TRUE;
1317 /* Hook called by the linker routine which adds symbols from an object
1318 file. We use it to put .comm items in .sbss, and not .bss. */
1320 static bfd_boolean
1321 elfNN_ia64_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
1322 bfd *abfd;
1323 struct bfd_link_info *info;
1324 const Elf_Internal_Sym *sym;
1325 const char **namep ATTRIBUTE_UNUSED;
1326 flagword *flagsp ATTRIBUTE_UNUSED;
1327 asection **secp;
1328 bfd_vma *valp;
1330 if (sym->st_shndx == SHN_COMMON
1331 && !info->relocateable
1332 && sym->st_size <= elf_gp_size (abfd))
1334 /* Common symbols less than or equal to -G nn bytes are
1335 automatically put into .sbss. */
1337 asection *scomm = bfd_get_section_by_name (abfd, ".scommon");
1339 if (scomm == NULL)
1341 scomm = bfd_make_section (abfd, ".scommon");
1342 if (scomm == NULL
1343 || !bfd_set_section_flags (abfd, scomm, (SEC_ALLOC
1344 | SEC_IS_COMMON
1345 | SEC_LINKER_CREATED)))
1346 return FALSE;
1349 *secp = scomm;
1350 *valp = sym->st_size;
1353 return TRUE;
1356 static bfd_boolean
1357 elfNN_ia64_aix_vec (const bfd_target *vec)
1359 extern const bfd_target bfd_elfNN_ia64_aix_little_vec;
1360 extern const bfd_target bfd_elfNN_ia64_aix_big_vec;
1362 return (/**/vec == & bfd_elfNN_ia64_aix_little_vec
1363 || vec == & bfd_elfNN_ia64_aix_big_vec);
1366 /* Hook called by the linker routine which adds symbols from an object
1367 file. We use it to handle OS-specific symbols. */
1369 static bfd_boolean
1370 elfNN_ia64_aix_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
1371 bfd *abfd;
1372 struct bfd_link_info *info;
1373 const Elf_Internal_Sym *sym;
1374 const char **namep;
1375 flagword *flagsp;
1376 asection **secp;
1377 bfd_vma *valp;
1379 if (strcmp (*namep, "__GLOB_DATA_PTR") == 0)
1381 /* Define __GLOB_DATA_PTR when it is encountered. This is expected to
1382 be a linker-defined symbol by the Aix C runtime startup code. IBM sez
1383 no one else should use it b/c it is undocumented. */
1384 struct elf_link_hash_entry *h;
1386 h = elf_link_hash_lookup (elf_hash_table (info), *namep,
1387 FALSE, FALSE, FALSE);
1388 if (h == NULL)
1390 struct elf_backend_data *bed;
1391 struct elfNN_ia64_link_hash_table *ia64_info;
1392 struct bfd_link_hash_entry *bh = NULL;
1394 bed = get_elf_backend_data (abfd);
1395 ia64_info = elfNN_ia64_hash_table (info);
1397 if (!(_bfd_generic_link_add_one_symbol
1398 (info, abfd, *namep, BSF_GLOBAL,
1399 bfd_get_section_by_name (abfd, ".bss"),
1400 bed->got_symbol_offset, (const char *) NULL, FALSE,
1401 bed->collect, &bh)))
1402 return FALSE;
1404 h = (struct elf_link_hash_entry *) bh;
1405 h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
1406 h->type = STT_OBJECT;
1408 if (! _bfd_elf_link_record_dynamic_symbol (info, h))
1409 return FALSE;
1412 return TRUE;
1414 else if (sym->st_shndx == SHN_LOOS)
1416 unsigned int i;
1418 /* SHN_AIX_SYSCALL: Treat this as any other symbol. The special symbol
1419 is only relevant when compiling code for extended system calls.
1420 Replace the "special" section with .text, if possible.
1421 Note that these symbols are always assumed to be in .text. */
1422 for (i = 1; i < elf_numsections (abfd); i++)
1424 asection * sec = bfd_section_from_elf_index (abfd, i);
1426 if (sec && strcmp (sec->name, ".text") == 0)
1428 *secp = sec;
1429 break;
1433 if (*secp == NULL)
1434 *secp = bfd_abs_section_ptr;
1436 *valp = sym->st_size;
1438 return TRUE;
1440 else
1442 return elfNN_ia64_add_symbol_hook (abfd, info, sym,
1443 namep, flagsp, secp, valp);
1447 bfd_boolean
1448 elfNN_ia64_aix_link_add_symbols (abfd, info)
1449 bfd *abfd;
1450 struct bfd_link_info *info;
1452 /* Make sure dynamic sections are always created. */
1453 if (! elf_hash_table (info)->dynamic_sections_created
1454 && abfd->xvec == info->hash->creator)
1456 if (! bfd_elfNN_link_create_dynamic_sections (abfd, info))
1457 return FALSE;
1460 /* Now do the standard call. */
1461 return bfd_elfNN_bfd_link_add_symbols (abfd, info);
1464 /* Return the number of additional phdrs we will need. */
1466 static int
1467 elfNN_ia64_additional_program_headers (abfd)
1468 bfd *abfd;
1470 asection *s;
1471 int ret = 0;
1473 /* See if we need a PT_IA_64_ARCHEXT segment. */
1474 s = bfd_get_section_by_name (abfd, ELF_STRING_ia64_archext);
1475 if (s && (s->flags & SEC_LOAD))
1476 ++ret;
1478 /* Count how many PT_IA_64_UNWIND segments we need. */
1479 for (s = abfd->sections; s; s = s->next)
1480 if (is_unwind_section_name (abfd, s->name) && (s->flags & SEC_LOAD))
1481 ++ret;
1483 return ret;
1486 static bfd_boolean
1487 elfNN_ia64_modify_segment_map (abfd)
1488 bfd *abfd;
1490 struct elf_segment_map *m, **pm;
1491 Elf_Internal_Shdr *hdr;
1492 asection *s;
1494 /* If we need a PT_IA_64_ARCHEXT segment, it must come before
1495 all PT_LOAD segments. */
1496 s = bfd_get_section_by_name (abfd, ELF_STRING_ia64_archext);
1497 if (s && (s->flags & SEC_LOAD))
1499 for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
1500 if (m->p_type == PT_IA_64_ARCHEXT)
1501 break;
1502 if (m == NULL)
1504 m = ((struct elf_segment_map *)
1505 bfd_zalloc (abfd, (bfd_size_type) sizeof *m));
1506 if (m == NULL)
1507 return FALSE;
1509 m->p_type = PT_IA_64_ARCHEXT;
1510 m->count = 1;
1511 m->sections[0] = s;
1513 /* We want to put it after the PHDR and INTERP segments. */
1514 pm = &elf_tdata (abfd)->segment_map;
1515 while (*pm != NULL
1516 && ((*pm)->p_type == PT_PHDR
1517 || (*pm)->p_type == PT_INTERP))
1518 pm = &(*pm)->next;
1520 m->next = *pm;
1521 *pm = m;
1525 /* Install PT_IA_64_UNWIND segments, if needed. */
1526 for (s = abfd->sections; s; s = s->next)
1528 hdr = &elf_section_data (s)->this_hdr;
1529 if (hdr->sh_type != SHT_IA_64_UNWIND)
1530 continue;
1532 if (s && (s->flags & SEC_LOAD))
1534 for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
1535 if (m->p_type == PT_IA_64_UNWIND)
1537 int i;
1539 /* Look through all sections in the unwind segment
1540 for a match since there may be multiple sections
1541 to a segment. */
1542 for (i = m->count - 1; i >= 0; --i)
1543 if (m->sections[i] == s)
1544 break;
1546 if (i >= 0)
1547 break;
1550 if (m == NULL)
1552 m = ((struct elf_segment_map *)
1553 bfd_zalloc (abfd, (bfd_size_type) sizeof *m));
1554 if (m == NULL)
1555 return FALSE;
1557 m->p_type = PT_IA_64_UNWIND;
1558 m->count = 1;
1559 m->sections[0] = s;
1560 m->next = NULL;
1562 /* We want to put it last. */
1563 pm = &elf_tdata (abfd)->segment_map;
1564 while (*pm != NULL)
1565 pm = &(*pm)->next;
1566 *pm = m;
1571 /* Turn on PF_IA_64_NORECOV if needed. This involves traversing all of
1572 the input sections for each output section in the segment and testing
1573 for SHF_IA_64_NORECOV on each. */
1574 for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
1575 if (m->p_type == PT_LOAD)
1577 int i;
1578 for (i = m->count - 1; i >= 0; --i)
1580 struct bfd_link_order *order = m->sections[i]->link_order_head;
1581 while (order)
1583 if (order->type == bfd_indirect_link_order)
1585 asection *is = order->u.indirect.section;
1586 bfd_vma flags = elf_section_data(is)->this_hdr.sh_flags;
1587 if (flags & SHF_IA_64_NORECOV)
1589 m->p_flags |= PF_IA_64_NORECOV;
1590 goto found;
1593 order = order->next;
1596 found:;
1599 return TRUE;
1602 /* According to the Tahoe assembler spec, all labels starting with a
1603 '.' are local. */
1605 static bfd_boolean
1606 elfNN_ia64_is_local_label_name (abfd, name)
1607 bfd *abfd ATTRIBUTE_UNUSED;
1608 const char *name;
1610 return name[0] == '.';
1613 /* Should we do dynamic things to this symbol? */
1615 static bfd_boolean
1616 elfNN_ia64_dynamic_symbol_p (h, info)
1617 struct elf_link_hash_entry *h;
1618 struct bfd_link_info *info;
1620 if (h == NULL)
1621 return FALSE;
1623 while (h->root.type == bfd_link_hash_indirect
1624 || h->root.type == bfd_link_hash_warning)
1625 h = (struct elf_link_hash_entry *) h->root.u.i.link;
1627 if (h->dynindx == -1)
1628 return FALSE;
1629 switch (ELF_ST_VISIBILITY (h->other))
1631 case STV_INTERNAL:
1632 case STV_HIDDEN:
1633 return FALSE;
1634 default:
1635 break;
1638 if (h->root.type == bfd_link_hash_undefweak
1639 || h->root.type == bfd_link_hash_defweak)
1640 return TRUE;
1642 if ((info->shared && (!info->symbolic || info->allow_shlib_undefined))
1643 || ((h->elf_link_hash_flags
1644 & (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR))
1645 == (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR)))
1646 return TRUE;
1648 return FALSE;
1651 static bfd_boolean
1652 elfNN_ia64_local_hash_table_init (ht, abfd, new)
1653 struct elfNN_ia64_local_hash_table *ht;
1654 bfd *abfd ATTRIBUTE_UNUSED;
1655 new_hash_entry_func new;
1657 memset (ht, 0, sizeof (*ht));
1658 return bfd_hash_table_init (&ht->root, new);
1661 static struct bfd_hash_entry*
1662 elfNN_ia64_new_loc_hash_entry (entry, table, string)
1663 struct bfd_hash_entry *entry;
1664 struct bfd_hash_table *table;
1665 const char *string;
1667 struct elfNN_ia64_local_hash_entry *ret;
1668 ret = (struct elfNN_ia64_local_hash_entry *) entry;
1670 /* Allocate the structure if it has not already been allocated by a
1671 subclass. */
1672 if (!ret)
1673 ret = bfd_hash_allocate (table, sizeof (*ret));
1675 if (!ret)
1676 return 0;
1678 /* Initialize our local data. All zeros, and definitely easier
1679 than setting a handful of bit fields. */
1680 memset (ret, 0, sizeof (*ret));
1682 /* Call the allocation method of the superclass. */
1683 ret = ((struct elfNN_ia64_local_hash_entry *)
1684 bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
1686 return (struct bfd_hash_entry *) ret;
1689 static struct bfd_hash_entry*
1690 elfNN_ia64_new_elf_hash_entry (entry, table, string)
1691 struct bfd_hash_entry *entry;
1692 struct bfd_hash_table *table;
1693 const char *string;
1695 struct elfNN_ia64_link_hash_entry *ret;
1696 ret = (struct elfNN_ia64_link_hash_entry *) entry;
1698 /* Allocate the structure if it has not already been allocated by a
1699 subclass. */
1700 if (!ret)
1701 ret = bfd_hash_allocate (table, sizeof (*ret));
1703 if (!ret)
1704 return 0;
1706 /* Initialize our local data. All zeros, and definitely easier
1707 than setting a handful of bit fields. */
1708 memset (ret, 0, sizeof (*ret));
1710 /* Call the allocation method of the superclass. */
1711 ret = ((struct elfNN_ia64_link_hash_entry *)
1712 _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret,
1713 table, string));
1715 return (struct bfd_hash_entry *) ret;
1718 static void
1719 elfNN_ia64_hash_copy_indirect (bed, xdir, xind)
1720 struct elf_backend_data *bed ATTRIBUTE_UNUSED;
1721 struct elf_link_hash_entry *xdir, *xind;
1723 struct elfNN_ia64_link_hash_entry *dir, *ind;
1725 dir = (struct elfNN_ia64_link_hash_entry *) xdir;
1726 ind = (struct elfNN_ia64_link_hash_entry *) xind;
1728 /* Copy down any references that we may have already seen to the
1729 symbol which just became indirect. */
1731 dir->root.elf_link_hash_flags |=
1732 (ind->root.elf_link_hash_flags
1733 & (ELF_LINK_HASH_REF_DYNAMIC
1734 | ELF_LINK_HASH_REF_REGULAR
1735 | ELF_LINK_HASH_REF_REGULAR_NONWEAK));
1737 if (ind->root.root.type != bfd_link_hash_indirect)
1738 return;
1740 /* Copy over the got and plt data. This would have been done
1741 by check_relocs. */
1743 if (dir->info == NULL)
1745 struct elfNN_ia64_dyn_sym_info *dyn_i;
1747 dir->info = dyn_i = ind->info;
1748 ind->info = NULL;
1750 /* Fix up the dyn_sym_info pointers to the global symbol. */
1751 for (; dyn_i; dyn_i = dyn_i->next)
1752 dyn_i->h = &dir->root;
1754 BFD_ASSERT (ind->info == NULL);
1756 /* Copy over the dynindx. */
1758 if (dir->root.dynindx == -1)
1760 dir->root.dynindx = ind->root.dynindx;
1761 dir->root.dynstr_index = ind->root.dynstr_index;
1762 ind->root.dynindx = -1;
1763 ind->root.dynstr_index = 0;
1765 BFD_ASSERT (ind->root.dynindx == -1);
1768 static void
1769 elfNN_ia64_hash_hide_symbol (info, xh, force_local)
1770 struct bfd_link_info *info;
1771 struct elf_link_hash_entry *xh;
1772 bfd_boolean force_local;
1774 struct elfNN_ia64_link_hash_entry *h;
1775 struct elfNN_ia64_dyn_sym_info *dyn_i;
1777 h = (struct elfNN_ia64_link_hash_entry *)xh;
1779 _bfd_elf_link_hash_hide_symbol (info, &h->root, force_local);
1781 for (dyn_i = h->info; dyn_i; dyn_i = dyn_i->next)
1782 dyn_i->want_plt2 = 0;
1785 /* Create the derived linker hash table. The IA-64 ELF port uses this
1786 derived hash table to keep information specific to the IA-64 ElF
1787 linker (without using static variables). */
1789 static struct bfd_link_hash_table*
1790 elfNN_ia64_hash_table_create (abfd)
1791 bfd *abfd;
1793 struct elfNN_ia64_link_hash_table *ret;
1795 ret = bfd_zmalloc ((bfd_size_type) sizeof (*ret));
1796 if (!ret)
1797 return 0;
1799 if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
1800 elfNN_ia64_new_elf_hash_entry))
1802 free (ret);
1803 return 0;
1806 if (!elfNN_ia64_local_hash_table_init (&ret->loc_hash_table, abfd,
1807 elfNN_ia64_new_loc_hash_entry))
1809 free (ret);
1810 return 0;
1813 return &ret->root.root;
1816 /* Look up an entry in a Alpha ELF linker hash table. */
1818 static INLINE struct elfNN_ia64_local_hash_entry *
1819 elfNN_ia64_local_hash_lookup(table, string, create, copy)
1820 struct elfNN_ia64_local_hash_table *table;
1821 const char *string;
1822 bfd_boolean create, copy;
1824 return ((struct elfNN_ia64_local_hash_entry *)
1825 bfd_hash_lookup (&table->root, string, create, copy));
1828 /* Traverse both local and global hash tables. */
1830 struct elfNN_ia64_dyn_sym_traverse_data
1832 bfd_boolean (*func) PARAMS ((struct elfNN_ia64_dyn_sym_info *, PTR));
1833 PTR data;
1836 static bfd_boolean
1837 elfNN_ia64_global_dyn_sym_thunk (xentry, xdata)
1838 struct bfd_hash_entry *xentry;
1839 PTR xdata;
1841 struct elfNN_ia64_link_hash_entry *entry
1842 = (struct elfNN_ia64_link_hash_entry *) xentry;
1843 struct elfNN_ia64_dyn_sym_traverse_data *data
1844 = (struct elfNN_ia64_dyn_sym_traverse_data *) xdata;
1845 struct elfNN_ia64_dyn_sym_info *dyn_i;
1847 if (entry->root.root.type == bfd_link_hash_warning)
1848 entry = (struct elfNN_ia64_link_hash_entry *) entry->root.root.u.i.link;
1850 for (dyn_i = entry->info; dyn_i; dyn_i = dyn_i->next)
1851 if (! (*data->func) (dyn_i, data->data))
1852 return FALSE;
1853 return TRUE;
1856 static bfd_boolean
1857 elfNN_ia64_local_dyn_sym_thunk (xentry, xdata)
1858 struct bfd_hash_entry *xentry;
1859 PTR xdata;
1861 struct elfNN_ia64_local_hash_entry *entry
1862 = (struct elfNN_ia64_local_hash_entry *) xentry;
1863 struct elfNN_ia64_dyn_sym_traverse_data *data
1864 = (struct elfNN_ia64_dyn_sym_traverse_data *) xdata;
1865 struct elfNN_ia64_dyn_sym_info *dyn_i;
1867 for (dyn_i = entry->info; dyn_i; dyn_i = dyn_i->next)
1868 if (! (*data->func) (dyn_i, data->data))
1869 return FALSE;
1870 return TRUE;
1873 static void
1874 elfNN_ia64_dyn_sym_traverse (ia64_info, func, data)
1875 struct elfNN_ia64_link_hash_table *ia64_info;
1876 bfd_boolean (*func) PARAMS ((struct elfNN_ia64_dyn_sym_info *, PTR));
1877 PTR data;
1879 struct elfNN_ia64_dyn_sym_traverse_data xdata;
1881 xdata.func = func;
1882 xdata.data = data;
1884 elf_link_hash_traverse (&ia64_info->root,
1885 elfNN_ia64_global_dyn_sym_thunk, &xdata);
1886 bfd_hash_traverse (&ia64_info->loc_hash_table.root,
1887 elfNN_ia64_local_dyn_sym_thunk, &xdata);
1890 static bfd_boolean
1891 elfNN_ia64_create_dynamic_sections (abfd, info)
1892 bfd *abfd;
1893 struct bfd_link_info *info;
1895 struct elfNN_ia64_link_hash_table *ia64_info;
1896 asection *s;
1898 if (! _bfd_elf_create_dynamic_sections (abfd, info))
1899 return FALSE;
1901 ia64_info = elfNN_ia64_hash_table (info);
1903 ia64_info->plt_sec = bfd_get_section_by_name (abfd, ".plt");
1904 ia64_info->got_sec = bfd_get_section_by_name (abfd, ".got");
1907 flagword flags = bfd_get_section_flags (abfd, ia64_info->got_sec);
1908 bfd_set_section_flags (abfd, ia64_info->got_sec, SEC_SMALL_DATA | flags);
1911 if (!get_pltoff (abfd, info, ia64_info))
1912 return FALSE;
1914 s = bfd_make_section(abfd, ".rela.IA_64.pltoff");
1915 if (s == NULL
1916 || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
1917 | SEC_HAS_CONTENTS
1918 | SEC_IN_MEMORY
1919 | SEC_LINKER_CREATED
1920 | SEC_READONLY))
1921 || !bfd_set_section_alignment (abfd, s, 3))
1922 return FALSE;
1923 ia64_info->rel_pltoff_sec = s;
1925 s = bfd_make_section(abfd, ".rela.got");
1926 if (s == NULL
1927 || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
1928 | SEC_HAS_CONTENTS
1929 | SEC_IN_MEMORY
1930 | SEC_LINKER_CREATED
1931 | SEC_READONLY))
1932 || !bfd_set_section_alignment (abfd, s, 3))
1933 return FALSE;
1934 ia64_info->rel_got_sec = s;
1936 return TRUE;
1939 /* Find and/or create a hash entry for local symbol. */
1940 static struct elfNN_ia64_local_hash_entry *
1941 get_local_sym_hash (ia64_info, abfd, rel, create)
1942 struct elfNN_ia64_link_hash_table *ia64_info;
1943 bfd *abfd;
1944 const Elf_Internal_Rela *rel;
1945 bfd_boolean create;
1947 struct elfNN_ia64_local_hash_entry *ret;
1948 asection *sec = abfd->sections;
1949 char addr_name [34];
1951 BFD_ASSERT ((sizeof (sec->id)*2 + 1 + sizeof (unsigned long)*2 + 1) <= 34);
1952 BFD_ASSERT (sec);
1954 /* Construct a string for use in the elfNN_ia64_local_hash_table.
1955 name describes what was once anonymous memory. */
1957 sprintf (addr_name, "%x:%lx",
1958 sec->id, (unsigned long) ELFNN_R_SYM (rel->r_info));
1960 /* Collect the canonical entry data for this address. */
1961 ret = elfNN_ia64_local_hash_lookup (&ia64_info->loc_hash_table,
1962 addr_name, create, create);
1963 return ret;
1966 /* Find and/or create a descriptor for dynamic symbol info. This will
1967 vary based on global or local symbol, and the addend to the reloc. */
1969 static struct elfNN_ia64_dyn_sym_info *
1970 get_dyn_sym_info (ia64_info, h, abfd, rel, create)
1971 struct elfNN_ia64_link_hash_table *ia64_info;
1972 struct elf_link_hash_entry *h;
1973 bfd *abfd;
1974 const Elf_Internal_Rela *rel;
1975 bfd_boolean create;
1977 struct elfNN_ia64_dyn_sym_info **pp;
1978 struct elfNN_ia64_dyn_sym_info *dyn_i;
1979 bfd_vma addend = rel ? rel->r_addend : 0;
1981 if (h)
1982 pp = &((struct elfNN_ia64_link_hash_entry *)h)->info;
1983 else
1985 struct elfNN_ia64_local_hash_entry *loc_h;
1987 loc_h = get_local_sym_hash (ia64_info, abfd, rel, create);
1988 if (!loc_h)
1990 BFD_ASSERT (!create);
1991 return NULL;
1994 pp = &loc_h->info;
1997 for (dyn_i = *pp; dyn_i && dyn_i->addend != addend; dyn_i = *pp)
1998 pp = &dyn_i->next;
2000 if (dyn_i == NULL && create)
2002 dyn_i = ((struct elfNN_ia64_dyn_sym_info *)
2003 bfd_zalloc (abfd, (bfd_size_type) sizeof *dyn_i));
2004 *pp = dyn_i;
2005 dyn_i->addend = addend;
2008 return dyn_i;
2011 static asection *
2012 get_got (abfd, info, ia64_info)
2013 bfd *abfd;
2014 struct bfd_link_info *info;
2015 struct elfNN_ia64_link_hash_table *ia64_info;
2017 asection *got;
2018 bfd *dynobj;
2020 got = ia64_info->got_sec;
2021 if (!got)
2023 flagword flags;
2025 dynobj = ia64_info->root.dynobj;
2026 if (!dynobj)
2027 ia64_info->root.dynobj = dynobj = abfd;
2028 if (!_bfd_elf_create_got_section (dynobj, info))
2029 return 0;
2031 got = bfd_get_section_by_name (dynobj, ".got");
2032 BFD_ASSERT (got);
2033 ia64_info->got_sec = got;
2035 flags = bfd_get_section_flags (abfd, got);
2036 bfd_set_section_flags (abfd, got, SEC_SMALL_DATA | flags);
2039 return got;
2042 /* Create function descriptor section (.opd). This section is called .opd
2043 because it contains "official prodecure descriptors". The "official"
2044 refers to the fact that these descriptors are used when taking the address
2045 of a procedure, thus ensuring a unique address for each procedure. */
2047 static asection *
2048 get_fptr (abfd, info, ia64_info)
2049 bfd *abfd;
2050 struct bfd_link_info *info ATTRIBUTE_UNUSED;
2051 struct elfNN_ia64_link_hash_table *ia64_info;
2053 asection *fptr;
2054 bfd *dynobj;
2056 fptr = ia64_info->fptr_sec;
2057 if (!fptr)
2059 dynobj = ia64_info->root.dynobj;
2060 if (!dynobj)
2061 ia64_info->root.dynobj = dynobj = abfd;
2063 fptr = bfd_make_section (dynobj, ".opd");
2064 if (!fptr
2065 || !bfd_set_section_flags (dynobj, fptr,
2066 (SEC_ALLOC
2067 | SEC_LOAD
2068 | SEC_HAS_CONTENTS
2069 | SEC_IN_MEMORY
2070 | SEC_READONLY
2071 | SEC_LINKER_CREATED))
2072 || !bfd_set_section_alignment (abfd, fptr, 4))
2074 BFD_ASSERT (0);
2075 return NULL;
2078 ia64_info->fptr_sec = fptr;
2081 return fptr;
2084 static asection *
2085 get_pltoff (abfd, info, ia64_info)
2086 bfd *abfd;
2087 struct bfd_link_info *info ATTRIBUTE_UNUSED;
2088 struct elfNN_ia64_link_hash_table *ia64_info;
2090 asection *pltoff;
2091 bfd *dynobj;
2093 pltoff = ia64_info->pltoff_sec;
2094 if (!pltoff)
2096 dynobj = ia64_info->root.dynobj;
2097 if (!dynobj)
2098 ia64_info->root.dynobj = dynobj = abfd;
2100 pltoff = bfd_make_section (dynobj, ELF_STRING_ia64_pltoff);
2101 if (!pltoff
2102 || !bfd_set_section_flags (dynobj, pltoff,
2103 (SEC_ALLOC
2104 | SEC_LOAD
2105 | SEC_HAS_CONTENTS
2106 | SEC_IN_MEMORY
2107 | SEC_SMALL_DATA
2108 | SEC_LINKER_CREATED))
2109 || !bfd_set_section_alignment (abfd, pltoff, 4))
2111 BFD_ASSERT (0);
2112 return NULL;
2115 ia64_info->pltoff_sec = pltoff;
2118 return pltoff;
2121 static asection *
2122 get_reloc_section (abfd, ia64_info, sec, create)
2123 bfd *abfd;
2124 struct elfNN_ia64_link_hash_table *ia64_info;
2125 asection *sec;
2126 bfd_boolean create;
2128 const char *srel_name;
2129 asection *srel;
2130 bfd *dynobj;
2132 srel_name = (bfd_elf_string_from_elf_section
2133 (abfd, elf_elfheader(abfd)->e_shstrndx,
2134 elf_section_data(sec)->rel_hdr.sh_name));
2135 if (srel_name == NULL)
2136 return NULL;
2138 BFD_ASSERT ((strncmp (srel_name, ".rela", 5) == 0
2139 && strcmp (bfd_get_section_name (abfd, sec),
2140 srel_name+5) == 0)
2141 || (strncmp (srel_name, ".rel", 4) == 0
2142 && strcmp (bfd_get_section_name (abfd, sec),
2143 srel_name+4) == 0));
2145 dynobj = ia64_info->root.dynobj;
2146 if (!dynobj)
2147 ia64_info->root.dynobj = dynobj = abfd;
2149 srel = bfd_get_section_by_name (dynobj, srel_name);
2150 if (srel == NULL && create)
2152 srel = bfd_make_section (dynobj, srel_name);
2153 if (srel == NULL
2154 || !bfd_set_section_flags (dynobj, srel,
2155 (SEC_ALLOC
2156 | SEC_LOAD
2157 | SEC_HAS_CONTENTS
2158 | SEC_IN_MEMORY
2159 | SEC_LINKER_CREATED
2160 | SEC_READONLY))
2161 || !bfd_set_section_alignment (dynobj, srel, 3))
2162 return NULL;
2165 if (sec->flags & SEC_READONLY)
2166 ia64_info->reltext = 1;
2168 return srel;
2171 static bfd_boolean
2172 count_dyn_reloc (abfd, dyn_i, srel, type)
2173 bfd *abfd;
2174 struct elfNN_ia64_dyn_sym_info *dyn_i;
2175 asection *srel;
2176 int type;
2178 struct elfNN_ia64_dyn_reloc_entry *rent;
2180 for (rent = dyn_i->reloc_entries; rent; rent = rent->next)
2181 if (rent->srel == srel && rent->type == type)
2182 break;
2184 if (!rent)
2186 rent = ((struct elfNN_ia64_dyn_reloc_entry *)
2187 bfd_alloc (abfd, (bfd_size_type) sizeof (*rent)));
2188 if (!rent)
2189 return FALSE;
2191 rent->next = dyn_i->reloc_entries;
2192 rent->srel = srel;
2193 rent->type = type;
2194 rent->count = 0;
2195 dyn_i->reloc_entries = rent;
2197 rent->count++;
2199 return TRUE;
2202 static bfd_boolean
2203 elfNN_ia64_check_relocs (abfd, info, sec, relocs)
2204 bfd *abfd;
2205 struct bfd_link_info *info;
2206 asection *sec;
2207 const Elf_Internal_Rela *relocs;
2209 struct elfNN_ia64_link_hash_table *ia64_info;
2210 const Elf_Internal_Rela *relend;
2211 Elf_Internal_Shdr *symtab_hdr;
2212 const Elf_Internal_Rela *rel;
2213 asection *got, *fptr, *srel;
2215 if (info->relocateable)
2216 return TRUE;
2218 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
2219 ia64_info = elfNN_ia64_hash_table (info);
2221 got = fptr = srel = NULL;
2223 relend = relocs + sec->reloc_count;
2224 for (rel = relocs; rel < relend; ++rel)
2226 enum {
2227 NEED_GOT = 1,
2228 NEED_GOTX = 2,
2229 NEED_FPTR = 4,
2230 NEED_PLTOFF = 8,
2231 NEED_MIN_PLT = 16,
2232 NEED_FULL_PLT = 32,
2233 NEED_DYNREL = 64,
2234 NEED_LTOFF_FPTR = 128,
2235 NEED_TPREL = 256,
2236 NEED_DTPMOD = 512,
2237 NEED_DTPREL = 1024
2240 struct elf_link_hash_entry *h = NULL;
2241 unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
2242 struct elfNN_ia64_dyn_sym_info *dyn_i;
2243 int need_entry;
2244 bfd_boolean maybe_dynamic;
2245 int dynrel_type = R_IA64_NONE;
2247 if (r_symndx >= symtab_hdr->sh_info)
2249 /* We're dealing with a global symbol -- find its hash entry
2250 and mark it as being referenced. */
2251 long indx = r_symndx - symtab_hdr->sh_info;
2252 h = elf_sym_hashes (abfd)[indx];
2253 while (h->root.type == bfd_link_hash_indirect
2254 || h->root.type == bfd_link_hash_warning)
2255 h = (struct elf_link_hash_entry *) h->root.u.i.link;
2257 h->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR;
2260 /* We can only get preliminary data on whether a symbol is
2261 locally or externally defined, as not all of the input files
2262 have yet been processed. Do something with what we know, as
2263 this may help reduce memory usage and processing time later. */
2264 maybe_dynamic = FALSE;
2265 if (h && ((info->shared
2266 && (!info->symbolic || info->allow_shlib_undefined))
2267 || ! (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)
2268 || h->root.type == bfd_link_hash_defweak
2269 || elfNN_ia64_aix_vec (abfd->xvec)))
2270 maybe_dynamic = TRUE;
2272 need_entry = 0;
2273 switch (ELFNN_R_TYPE (rel->r_info))
2275 case R_IA64_TPREL64MSB:
2276 case R_IA64_TPREL64LSB:
2277 if (info->shared || maybe_dynamic)
2278 need_entry = NEED_DYNREL;
2279 dynrel_type = R_IA64_TPREL64LSB;
2280 if (info->shared)
2281 info->flags |= DF_STATIC_TLS;
2282 break;
2284 case R_IA64_LTOFF_TPREL22:
2285 need_entry = NEED_TPREL;
2286 if (info->shared)
2287 info->flags |= DF_STATIC_TLS;
2288 break;
2290 case R_IA64_DTPREL64MSB:
2291 case R_IA64_DTPREL64LSB:
2292 if (info->shared || maybe_dynamic)
2293 need_entry = NEED_DYNREL;
2294 dynrel_type = R_IA64_DTPREL64LSB;
2295 break;
2297 case R_IA64_LTOFF_DTPREL22:
2298 need_entry = NEED_DTPREL;
2299 break;
2301 case R_IA64_DTPMOD64MSB:
2302 case R_IA64_DTPMOD64LSB:
2303 if (info->shared || maybe_dynamic)
2304 need_entry = NEED_DYNREL;
2305 dynrel_type = R_IA64_DTPMOD64LSB;
2306 break;
2308 case R_IA64_LTOFF_DTPMOD22:
2309 need_entry = NEED_DTPMOD;
2310 break;
2312 case R_IA64_LTOFF_FPTR22:
2313 case R_IA64_LTOFF_FPTR64I:
2314 case R_IA64_LTOFF_FPTR32MSB:
2315 case R_IA64_LTOFF_FPTR32LSB:
2316 case R_IA64_LTOFF_FPTR64MSB:
2317 case R_IA64_LTOFF_FPTR64LSB:
2318 need_entry = NEED_FPTR | NEED_GOT | NEED_LTOFF_FPTR;
2319 break;
2321 case R_IA64_FPTR64I:
2322 case R_IA64_FPTR32MSB:
2323 case R_IA64_FPTR32LSB:
2324 case R_IA64_FPTR64MSB:
2325 case R_IA64_FPTR64LSB:
2326 if (info->shared || h || elfNN_ia64_aix_vec (abfd->xvec))
2327 need_entry = NEED_FPTR | NEED_DYNREL;
2328 else
2329 need_entry = NEED_FPTR;
2330 dynrel_type = R_IA64_FPTR64LSB;
2331 break;
2333 case R_IA64_LTOFF22:
2334 case R_IA64_LTOFF64I:
2335 need_entry = NEED_GOT;
2336 break;
2338 case R_IA64_LTOFF22X:
2339 need_entry = NEED_GOTX;
2340 break;
2342 case R_IA64_PLTOFF22:
2343 case R_IA64_PLTOFF64I:
2344 case R_IA64_PLTOFF64MSB:
2345 case R_IA64_PLTOFF64LSB:
2346 need_entry = NEED_PLTOFF;
2347 if (h)
2349 if (maybe_dynamic)
2350 need_entry |= NEED_MIN_PLT;
2352 else
2354 (*info->callbacks->warning)
2355 (info, _("@pltoff reloc against local symbol"), 0,
2356 abfd, 0, (bfd_vma) 0);
2358 break;
2360 case R_IA64_PCREL21B:
2361 case R_IA64_PCREL60B:
2362 /* Depending on where this symbol is defined, we may or may not
2363 need a full plt entry. Only skip if we know we'll not need
2364 the entry -- static or symbolic, and the symbol definition
2365 has already been seen. */
2366 if (maybe_dynamic && rel->r_addend == 0)
2367 need_entry = NEED_FULL_PLT;
2368 break;
2370 case R_IA64_IMM14:
2371 case R_IA64_IMM22:
2372 case R_IA64_IMM64:
2373 case R_IA64_DIR32MSB:
2374 case R_IA64_DIR32LSB:
2375 case R_IA64_DIR64MSB:
2376 case R_IA64_DIR64LSB:
2377 /* Shared objects will always need at least a REL relocation. */
2378 if (info->shared || maybe_dynamic
2379 || (elfNN_ia64_aix_vec (abfd->xvec)
2380 && (!h || strcmp (h->root.root.string,
2381 "__GLOB_DATA_PTR") != 0)))
2382 need_entry = NEED_DYNREL;
2383 dynrel_type = R_IA64_DIR64LSB;
2384 break;
2386 case R_IA64_IPLTMSB:
2387 case R_IA64_IPLTLSB:
2388 /* Shared objects will always need at least a REL relocation. */
2389 if (info->shared || maybe_dynamic)
2390 need_entry = NEED_DYNREL;
2391 dynrel_type = R_IA64_IPLTLSB;
2392 break;
2394 case R_IA64_PCREL22:
2395 case R_IA64_PCREL64I:
2396 case R_IA64_PCREL32MSB:
2397 case R_IA64_PCREL32LSB:
2398 case R_IA64_PCREL64MSB:
2399 case R_IA64_PCREL64LSB:
2400 if (maybe_dynamic)
2401 need_entry = NEED_DYNREL;
2402 dynrel_type = R_IA64_PCREL64LSB;
2403 break;
2406 if (!need_entry)
2407 continue;
2409 if ((need_entry & NEED_FPTR) != 0
2410 && rel->r_addend)
2412 (*info->callbacks->warning)
2413 (info, _("non-zero addend in @fptr reloc"), 0,
2414 abfd, 0, (bfd_vma) 0);
2417 dyn_i = get_dyn_sym_info (ia64_info, h, abfd, rel, TRUE);
2419 /* Record whether or not this is a local symbol. */
2420 dyn_i->h = h;
2422 /* Create what's needed. */
2423 if (need_entry & (NEED_GOT | NEED_GOTX | NEED_TPREL
2424 | NEED_DTPMOD | NEED_DTPREL))
2426 if (!got)
2428 got = get_got (abfd, info, ia64_info);
2429 if (!got)
2430 return FALSE;
2432 if (need_entry & NEED_GOT)
2433 dyn_i->want_got = 1;
2434 if (need_entry & NEED_GOTX)
2435 dyn_i->want_gotx = 1;
2436 if (need_entry & NEED_TPREL)
2437 dyn_i->want_tprel = 1;
2438 if (need_entry & NEED_DTPMOD)
2439 dyn_i->want_dtpmod = 1;
2440 if (need_entry & NEED_DTPREL)
2441 dyn_i->want_dtprel = 1;
2443 if (need_entry & NEED_FPTR)
2445 if (!fptr)
2447 fptr = get_fptr (abfd, info, ia64_info);
2448 if (!fptr)
2449 return FALSE;
2452 /* FPTRs for shared libraries are allocated by the dynamic
2453 linker. Make sure this local symbol will appear in the
2454 dynamic symbol table. */
2455 if (!h && (info->shared
2456 /* AIX also needs one */
2457 || elfNN_ia64_aix_vec (abfd->xvec)))
2459 if (! (_bfd_elfNN_link_record_local_dynamic_symbol
2460 (info, abfd, (long) r_symndx)))
2461 return FALSE;
2464 dyn_i->want_fptr = 1;
2466 if (need_entry & NEED_LTOFF_FPTR)
2467 dyn_i->want_ltoff_fptr = 1;
2468 if (need_entry & (NEED_MIN_PLT | NEED_FULL_PLT))
2470 if (!ia64_info->root.dynobj)
2471 ia64_info->root.dynobj = abfd;
2472 h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
2473 dyn_i->want_plt = 1;
2475 if (need_entry & NEED_FULL_PLT)
2476 dyn_i->want_plt2 = 1;
2477 if (need_entry & NEED_PLTOFF)
2478 dyn_i->want_pltoff = 1;
2479 if ((need_entry & NEED_DYNREL) && (sec->flags & SEC_ALLOC))
2481 if (!srel)
2483 srel = get_reloc_section (abfd, ia64_info, sec, TRUE);
2484 if (!srel)
2485 return FALSE;
2487 if (!count_dyn_reloc (abfd, dyn_i, srel, dynrel_type))
2488 return FALSE;
2492 return TRUE;
2495 /* For cleanliness, and potentially faster dynamic loading, allocate
2496 external GOT entries first. */
2498 static bfd_boolean
2499 allocate_global_data_got (dyn_i, data)
2500 struct elfNN_ia64_dyn_sym_info *dyn_i;
2501 PTR data;
2503 struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
2505 if ((dyn_i->want_got || dyn_i->want_gotx)
2506 && ! dyn_i->want_fptr
2507 && (elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info)
2508 || (elfNN_ia64_aix_vec (x->info->hash->creator)
2509 && (!dyn_i->h || strcmp (dyn_i->h->root.root.string,
2510 "__GLOB_DATA_PTR") != 0))))
2512 dyn_i->got_offset = x->ofs;
2513 x->ofs += 8;
2515 if (dyn_i->want_tprel)
2517 dyn_i->tprel_offset = x->ofs;
2518 x->ofs += 8;
2520 if (dyn_i->want_dtpmod)
2522 if (elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info))
2524 dyn_i->dtpmod_offset = x->ofs;
2525 x->ofs += 8;
2527 else
2529 struct elfNN_ia64_link_hash_table *ia64_info;
2531 ia64_info = elfNN_ia64_hash_table (x->info);
2532 if (ia64_info->self_dtpmod_offset == (bfd_vma) -1)
2534 ia64_info->self_dtpmod_offset = x->ofs;
2535 x->ofs += 8;
2537 dyn_i->dtpmod_offset = ia64_info->self_dtpmod_offset;
2540 if (dyn_i->want_dtprel)
2542 dyn_i->dtprel_offset = x->ofs;
2543 x->ofs += 8;
2545 return TRUE;
2548 /* Next, allocate all the GOT entries used by LTOFF_FPTR relocs. */
2550 static bfd_boolean
2551 allocate_global_fptr_got (dyn_i, data)
2552 struct elfNN_ia64_dyn_sym_info *dyn_i;
2553 PTR data;
2555 struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
2557 if (dyn_i->want_got
2558 && dyn_i->want_fptr
2559 && (elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info)
2560 || elfNN_ia64_aix_vec (x->info->hash->creator)))
2562 dyn_i->got_offset = x->ofs;
2563 x->ofs += 8;
2565 return TRUE;
2568 /* Lastly, allocate all the GOT entries for local data. */
2570 static bfd_boolean
2571 allocate_local_got (dyn_i, data)
2572 struct elfNN_ia64_dyn_sym_info *dyn_i;
2573 PTR data;
2575 struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
2577 if ((dyn_i->want_got || dyn_i->want_gotx)
2578 && ! (elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info)
2579 || elfNN_ia64_aix_vec (x->info->hash->creator)))
2581 dyn_i->got_offset = x->ofs;
2582 x->ofs += 8;
2584 return TRUE;
2587 /* Search for the index of a global symbol in it's defining object file. */
2589 static long
2590 global_sym_index (h)
2591 struct elf_link_hash_entry *h;
2593 struct elf_link_hash_entry **p;
2594 bfd *obj;
2596 BFD_ASSERT (h->root.type == bfd_link_hash_defined
2597 || h->root.type == bfd_link_hash_defweak);
2599 obj = h->root.u.def.section->owner;
2600 for (p = elf_sym_hashes (obj); *p != h; ++p)
2601 continue;
2603 return p - elf_sym_hashes (obj) + elf_tdata (obj)->symtab_hdr.sh_info;
2606 /* Allocate function descriptors. We can do these for every function
2607 in a main executable that is not exported. */
2609 static bfd_boolean
2610 allocate_fptr (dyn_i, data)
2611 struct elfNN_ia64_dyn_sym_info *dyn_i;
2612 PTR data;
2614 struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
2616 if (dyn_i->want_fptr)
2618 struct elf_link_hash_entry *h = dyn_i->h;
2620 if (h)
2621 while (h->root.type == bfd_link_hash_indirect
2622 || h->root.type == bfd_link_hash_warning)
2623 h = (struct elf_link_hash_entry *) h->root.u.i.link;
2625 if (x->info->shared
2626 /* AIX needs an FPTR in this case. */
2627 || (elfNN_ia64_aix_vec (x->info->hash->creator)
2628 && (!h
2629 || h->root.type == bfd_link_hash_defined
2630 || h->root.type == bfd_link_hash_defweak)))
2632 if (h && h->dynindx == -1)
2634 BFD_ASSERT ((h->root.type == bfd_link_hash_defined)
2635 || (h->root.type == bfd_link_hash_defweak));
2637 if (!_bfd_elfNN_link_record_local_dynamic_symbol
2638 (x->info, h->root.u.def.section->owner,
2639 global_sym_index (h)))
2640 return FALSE;
2643 dyn_i->want_fptr = 0;
2645 else if (h == NULL || h->dynindx == -1)
2647 dyn_i->fptr_offset = x->ofs;
2648 x->ofs += 16;
2650 else
2651 dyn_i->want_fptr = 0;
2653 return TRUE;
2656 /* Allocate all the minimal PLT entries. */
2658 static bfd_boolean
2659 allocate_plt_entries (dyn_i, data)
2660 struct elfNN_ia64_dyn_sym_info *dyn_i;
2661 PTR data;
2663 struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
2665 if (dyn_i->want_plt)
2667 struct elf_link_hash_entry *h = dyn_i->h;
2669 if (h)
2670 while (h->root.type == bfd_link_hash_indirect
2671 || h->root.type == bfd_link_hash_warning)
2672 h = (struct elf_link_hash_entry *) h->root.u.i.link;
2674 /* ??? Versioned symbols seem to lose ELF_LINK_HASH_NEEDS_PLT. */
2675 if (elfNN_ia64_dynamic_symbol_p (h, x->info))
2677 bfd_size_type offset = x->ofs;
2678 if (offset == 0)
2679 offset = PLT_HEADER_SIZE;
2680 dyn_i->plt_offset = offset;
2681 x->ofs = offset + PLT_MIN_ENTRY_SIZE;
2683 dyn_i->want_pltoff = 1;
2685 else
2687 dyn_i->want_plt = 0;
2688 dyn_i->want_plt2 = 0;
2691 return TRUE;
2694 /* Allocate all the full PLT entries. */
2696 static bfd_boolean
2697 allocate_plt2_entries (dyn_i, data)
2698 struct elfNN_ia64_dyn_sym_info *dyn_i;
2699 PTR data;
2701 struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
2703 if (dyn_i->want_plt2)
2705 struct elf_link_hash_entry *h = dyn_i->h;
2706 bfd_size_type ofs = x->ofs;
2708 dyn_i->plt2_offset = ofs;
2709 x->ofs = ofs + PLT_FULL_ENTRY_SIZE;
2711 while (h->root.type == bfd_link_hash_indirect
2712 || h->root.type == bfd_link_hash_warning)
2713 h = (struct elf_link_hash_entry *) h->root.u.i.link;
2714 dyn_i->h->plt.offset = ofs;
2716 return TRUE;
2719 /* Allocate all the PLTOFF entries requested by relocations and
2720 plt entries. We can't share space with allocated FPTR entries,
2721 because the latter are not necessarily addressable by the GP.
2722 ??? Relaxation might be able to determine that they are. */
2724 static bfd_boolean
2725 allocate_pltoff_entries (dyn_i, data)
2726 struct elfNN_ia64_dyn_sym_info *dyn_i;
2727 PTR data;
2729 struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
2731 if (dyn_i->want_pltoff)
2733 dyn_i->pltoff_offset = x->ofs;
2734 x->ofs += 16;
2736 return TRUE;
2739 /* Allocate dynamic relocations for those symbols that turned out
2740 to be dynamic. */
2742 static bfd_boolean
2743 allocate_dynrel_entries (dyn_i, data)
2744 struct elfNN_ia64_dyn_sym_info *dyn_i;
2745 PTR data;
2747 struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
2748 struct elfNN_ia64_link_hash_table *ia64_info;
2749 struct elfNN_ia64_dyn_reloc_entry *rent;
2750 bfd_boolean dynamic_symbol, shared;
2752 ia64_info = elfNN_ia64_hash_table (x->info);
2753 dynamic_symbol = elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info)
2754 || (elfNN_ia64_aix_vec (x->info->hash->creator)
2755 /* Don't allocate an entry for __GLOB_DATA_PTR */
2756 && (!dyn_i->h || strcmp (dyn_i->h->root.root.string,
2757 "__GLOB_DATA_PTR") != 0));
2758 shared = x->info->shared;
2760 /* Take care of the normal data relocations. */
2762 for (rent = dyn_i->reloc_entries; rent; rent = rent->next)
2764 int count = rent->count;
2766 switch (rent->type)
2768 case R_IA64_FPTR64LSB:
2769 /* Allocate one iff !want_fptr, which by this point will
2770 be true only if we're actually allocating one statically
2771 in the main executable. */
2772 if (dyn_i->want_fptr)
2773 continue;
2774 break;
2775 case R_IA64_PCREL64LSB:
2776 if (!dynamic_symbol)
2777 continue;
2778 break;
2779 case R_IA64_DIR64LSB:
2780 if (!dynamic_symbol && !shared)
2781 continue;
2782 break;
2783 case R_IA64_IPLTLSB:
2784 if (!dynamic_symbol && !shared)
2785 continue;
2786 /* Use two REL relocations for IPLT relocations
2787 against local symbols. */
2788 if (!dynamic_symbol)
2789 count *= 2;
2790 break;
2791 case R_IA64_TPREL64LSB:
2792 case R_IA64_DTPREL64LSB:
2793 case R_IA64_DTPMOD64LSB:
2794 break;
2795 default:
2796 abort ();
2798 rent->srel->_raw_size += sizeof (ElfNN_External_Rela) * count;
2801 /* Take care of the GOT and PLT relocations. */
2803 if (((dynamic_symbol || shared) && (dyn_i->want_got || dyn_i->want_gotx))
2804 || (dyn_i->want_ltoff_fptr && dyn_i->h && dyn_i->h->dynindx != -1))
2805 ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
2806 if ((dynamic_symbol || shared) && dyn_i->want_tprel)
2807 ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
2808 if (dynamic_symbol && dyn_i->want_dtpmod)
2809 ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
2810 if (dynamic_symbol && dyn_i->want_dtprel)
2811 ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
2813 if (dyn_i->want_pltoff)
2815 bfd_size_type t = 0;
2817 /* Dynamic symbols get one IPLT relocation. Local symbols in
2818 shared libraries get two REL relocations. Local symbols in
2819 main applications get nothing. */
2820 if (dynamic_symbol)
2821 t = sizeof (ElfNN_External_Rela);
2822 else if (shared)
2823 t = 2 * sizeof (ElfNN_External_Rela);
2825 ia64_info->rel_pltoff_sec->_raw_size += t;
2828 return TRUE;
2831 static bfd_boolean
2832 elfNN_ia64_adjust_dynamic_symbol (info, h)
2833 struct bfd_link_info *info ATTRIBUTE_UNUSED;
2834 struct elf_link_hash_entry *h;
2836 /* ??? Undefined symbols with PLT entries should be re-defined
2837 to be the PLT entry. */
2839 /* If this is a weak symbol, and there is a real definition, the
2840 processor independent code will have arranged for us to see the
2841 real definition first, and we can just use the same value. */
2842 if (h->weakdef != NULL)
2844 BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
2845 || h->weakdef->root.type == bfd_link_hash_defweak);
2846 h->root.u.def.section = h->weakdef->root.u.def.section;
2847 h->root.u.def.value = h->weakdef->root.u.def.value;
2848 return TRUE;
2851 /* If this is a reference to a symbol defined by a dynamic object which
2852 is not a function, we might allocate the symbol in our .dynbss section
2853 and allocate a COPY dynamic relocation.
2855 But IA-64 code is canonically PIC, so as a rule we can avoid this sort
2856 of hackery. */
2858 return TRUE;
2861 static bfd_boolean
2862 elfNN_ia64_size_dynamic_sections (output_bfd, info)
2863 bfd *output_bfd;
2864 struct bfd_link_info *info;
2866 struct elfNN_ia64_allocate_data data;
2867 struct elfNN_ia64_link_hash_table *ia64_info;
2868 asection *sec;
2869 bfd *dynobj;
2870 bfd_boolean relplt = FALSE;
2872 dynobj = elf_hash_table(info)->dynobj;
2873 ia64_info = elfNN_ia64_hash_table (info);
2874 ia64_info->self_dtpmod_offset = (bfd_vma) -1;
2875 BFD_ASSERT(dynobj != NULL);
2876 data.info = info;
2878 /* Set the contents of the .interp section to the interpreter. */
2879 if (ia64_info->root.dynamic_sections_created
2880 && !info->shared)
2882 sec = bfd_get_section_by_name (dynobj, ".interp");
2883 BFD_ASSERT (sec != NULL);
2884 sec->contents = (bfd_byte *) DYNAMIC_INTERPRETER (output_bfd);
2885 sec->_raw_size = strlen (DYNAMIC_INTERPRETER (output_bfd)) + 1;
2888 /* Allocate the GOT entries. */
2890 if (ia64_info->got_sec)
2892 data.ofs = 0;
2893 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_data_got, &data);
2894 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_fptr_got, &data);
2895 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_local_got, &data);
2896 ia64_info->got_sec->_raw_size = data.ofs;
2899 /* Allocate the FPTR entries. */
2901 if (ia64_info->fptr_sec)
2903 data.ofs = 0;
2904 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_fptr, &data);
2905 ia64_info->fptr_sec->_raw_size = data.ofs;
2908 /* Now that we've seen all of the input files, we can decide which
2909 symbols need plt entries. Allocate the minimal PLT entries first.
2910 We do this even though dynamic_sections_created may be FALSE, because
2911 this has the side-effect of clearing want_plt and want_plt2. */
2913 data.ofs = 0;
2914 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_plt_entries, &data);
2916 ia64_info->minplt_entries = 0;
2917 if (data.ofs)
2919 ia64_info->minplt_entries
2920 = (data.ofs - PLT_HEADER_SIZE) / PLT_MIN_ENTRY_SIZE;
2923 /* Align the pointer for the plt2 entries. */
2924 data.ofs = (data.ofs + 31) & (bfd_vma) -32;
2926 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_plt2_entries, &data);
2927 if (data.ofs != 0)
2929 BFD_ASSERT (ia64_info->root.dynamic_sections_created);
2931 ia64_info->plt_sec->_raw_size = data.ofs;
2933 /* If we've got a .plt, we need some extra memory for the dynamic
2934 linker. We stuff these in .got.plt. */
2935 sec = bfd_get_section_by_name (dynobj, ".got.plt");
2936 sec->_raw_size = 8 * PLT_RESERVED_WORDS;
2939 /* Allocate the PLTOFF entries. */
2941 if (ia64_info->pltoff_sec)
2943 data.ofs = 0;
2944 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_pltoff_entries, &data);
2945 ia64_info->pltoff_sec->_raw_size = data.ofs;
2948 if (ia64_info->root.dynamic_sections_created)
2950 /* Allocate space for the dynamic relocations that turned out to be
2951 required. */
2953 if (info->shared && ia64_info->self_dtpmod_offset != (bfd_vma) -1)
2954 ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
2955 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_dynrel_entries, &data);
2958 /* We have now determined the sizes of the various dynamic sections.
2959 Allocate memory for them. */
2960 for (sec = dynobj->sections; sec != NULL; sec = sec->next)
2962 bfd_boolean strip;
2964 if (!(sec->flags & SEC_LINKER_CREATED))
2965 continue;
2967 /* If we don't need this section, strip it from the output file.
2968 There were several sections primarily related to dynamic
2969 linking that must be create before the linker maps input
2970 sections to output sections. The linker does that before
2971 bfd_elf_size_dynamic_sections is called, and it is that
2972 function which decides whether anything needs to go into
2973 these sections. */
2975 strip = (sec->_raw_size == 0);
2977 if (sec == ia64_info->got_sec)
2978 strip = FALSE;
2979 else if (sec == ia64_info->rel_got_sec)
2981 if (strip)
2982 ia64_info->rel_got_sec = NULL;
2983 else
2984 /* We use the reloc_count field as a counter if we need to
2985 copy relocs into the output file. */
2986 sec->reloc_count = 0;
2988 else if (sec == ia64_info->fptr_sec)
2990 if (strip)
2991 ia64_info->fptr_sec = NULL;
2993 else if (sec == ia64_info->plt_sec)
2995 if (strip)
2996 ia64_info->plt_sec = NULL;
2998 else if (sec == ia64_info->pltoff_sec)
3000 if (strip)
3001 ia64_info->pltoff_sec = NULL;
3003 else if (sec == ia64_info->rel_pltoff_sec)
3005 if (strip)
3006 ia64_info->rel_pltoff_sec = NULL;
3007 else
3009 relplt = TRUE;
3010 /* We use the reloc_count field as a counter if we need to
3011 copy relocs into the output file. */
3012 sec->reloc_count = 0;
3015 else
3017 const char *name;
3019 /* It's OK to base decisions on the section name, because none
3020 of the dynobj section names depend upon the input files. */
3021 name = bfd_get_section_name (dynobj, sec);
3023 if (strcmp (name, ".got.plt") == 0)
3024 strip = FALSE;
3025 else if (strncmp (name, ".rel", 4) == 0)
3027 if (!strip)
3029 /* We use the reloc_count field as a counter if we need to
3030 copy relocs into the output file. */
3031 sec->reloc_count = 0;
3034 else
3035 continue;
3038 if (strip)
3039 _bfd_strip_section_from_output (info, sec);
3040 else
3042 /* Allocate memory for the section contents. */
3043 sec->contents = (bfd_byte *) bfd_zalloc (dynobj, sec->_raw_size);
3044 if (sec->contents == NULL && sec->_raw_size != 0)
3045 return FALSE;
3049 if (elf_hash_table (info)->dynamic_sections_created)
3051 /* Add some entries to the .dynamic section. We fill in the values
3052 later (in finish_dynamic_sections) but we must add the entries now
3053 so that we get the correct size for the .dynamic section. */
3055 if (!info->shared)
3057 /* The DT_DEBUG entry is filled in by the dynamic linker and used
3058 by the debugger. */
3059 #define add_dynamic_entry(TAG, VAL) \
3060 bfd_elfNN_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
3062 if (!add_dynamic_entry (DT_DEBUG, 0))
3063 return FALSE;
3066 if (!add_dynamic_entry (DT_IA_64_PLT_RESERVE, 0))
3067 return FALSE;
3068 if (!add_dynamic_entry (DT_PLTGOT, 0))
3069 return FALSE;
3071 if (relplt)
3073 if (!add_dynamic_entry (DT_PLTRELSZ, 0)
3074 || !add_dynamic_entry (DT_PLTREL, DT_RELA)
3075 || !add_dynamic_entry (DT_JMPREL, 0))
3076 return FALSE;
3079 if (!add_dynamic_entry (DT_RELA, 0)
3080 || !add_dynamic_entry (DT_RELASZ, 0)
3081 || !add_dynamic_entry (DT_RELAENT, sizeof (ElfNN_External_Rela)))
3082 return FALSE;
3084 if (ia64_info->reltext)
3086 if (!add_dynamic_entry (DT_TEXTREL, 0))
3087 return FALSE;
3088 info->flags |= DF_TEXTREL;
3092 /* ??? Perhaps force __gp local. */
3094 return TRUE;
3097 static bfd_reloc_status_type
3098 elfNN_ia64_install_value (abfd, hit_addr, v, r_type)
3099 bfd *abfd;
3100 bfd_byte *hit_addr;
3101 bfd_vma v;
3102 unsigned int r_type;
3104 const struct ia64_operand *op;
3105 int bigendian = 0, shift = 0;
3106 bfd_vma t0, t1, insn, dword;
3107 enum ia64_opnd opnd;
3108 const char *err;
3109 size_t size = 8;
3110 #ifdef BFD_HOST_U_64_BIT
3111 BFD_HOST_U_64_BIT val = (BFD_HOST_U_64_BIT) v;
3112 #else
3113 bfd_vma val = v;
3114 #endif
3116 opnd = IA64_OPND_NIL;
3117 switch (r_type)
3119 case R_IA64_NONE:
3120 case R_IA64_LDXMOV:
3121 return bfd_reloc_ok;
3123 /* Instruction relocations. */
3125 case R_IA64_IMM14:
3126 case R_IA64_TPREL14:
3127 case R_IA64_DTPREL14:
3128 opnd = IA64_OPND_IMM14;
3129 break;
3131 case R_IA64_PCREL21F: opnd = IA64_OPND_TGT25; break;
3132 case R_IA64_PCREL21M: opnd = IA64_OPND_TGT25b; break;
3133 case R_IA64_PCREL60B: opnd = IA64_OPND_TGT64; break;
3134 case R_IA64_PCREL21B:
3135 case R_IA64_PCREL21BI:
3136 opnd = IA64_OPND_TGT25c;
3137 break;
3139 case R_IA64_IMM22:
3140 case R_IA64_GPREL22:
3141 case R_IA64_LTOFF22:
3142 case R_IA64_LTOFF22X:
3143 case R_IA64_PLTOFF22:
3144 case R_IA64_PCREL22:
3145 case R_IA64_LTOFF_FPTR22:
3146 case R_IA64_TPREL22:
3147 case R_IA64_DTPREL22:
3148 case R_IA64_LTOFF_TPREL22:
3149 case R_IA64_LTOFF_DTPMOD22:
3150 case R_IA64_LTOFF_DTPREL22:
3151 opnd = IA64_OPND_IMM22;
3152 break;
3154 case R_IA64_IMM64:
3155 case R_IA64_GPREL64I:
3156 case R_IA64_LTOFF64I:
3157 case R_IA64_PLTOFF64I:
3158 case R_IA64_PCREL64I:
3159 case R_IA64_FPTR64I:
3160 case R_IA64_LTOFF_FPTR64I:
3161 case R_IA64_TPREL64I:
3162 case R_IA64_DTPREL64I:
3163 opnd = IA64_OPND_IMMU64;
3164 break;
3166 /* Data relocations. */
3168 case R_IA64_DIR32MSB:
3169 case R_IA64_GPREL32MSB:
3170 case R_IA64_FPTR32MSB:
3171 case R_IA64_PCREL32MSB:
3172 case R_IA64_LTOFF_FPTR32MSB:
3173 case R_IA64_SEGREL32MSB:
3174 case R_IA64_SECREL32MSB:
3175 case R_IA64_LTV32MSB:
3176 case R_IA64_DTPREL32MSB:
3177 size = 4; bigendian = 1;
3178 break;
3180 case R_IA64_DIR32LSB:
3181 case R_IA64_GPREL32LSB:
3182 case R_IA64_FPTR32LSB:
3183 case R_IA64_PCREL32LSB:
3184 case R_IA64_LTOFF_FPTR32LSB:
3185 case R_IA64_SEGREL32LSB:
3186 case R_IA64_SECREL32LSB:
3187 case R_IA64_LTV32LSB:
3188 case R_IA64_DTPREL32LSB:
3189 size = 4; bigendian = 0;
3190 break;
3192 case R_IA64_DIR64MSB:
3193 case R_IA64_GPREL64MSB:
3194 case R_IA64_PLTOFF64MSB:
3195 case R_IA64_FPTR64MSB:
3196 case R_IA64_PCREL64MSB:
3197 case R_IA64_LTOFF_FPTR64MSB:
3198 case R_IA64_SEGREL64MSB:
3199 case R_IA64_SECREL64MSB:
3200 case R_IA64_LTV64MSB:
3201 case R_IA64_TPREL64MSB:
3202 case R_IA64_DTPMOD64MSB:
3203 case R_IA64_DTPREL64MSB:
3204 size = 8; bigendian = 1;
3205 break;
3207 case R_IA64_DIR64LSB:
3208 case R_IA64_GPREL64LSB:
3209 case R_IA64_PLTOFF64LSB:
3210 case R_IA64_FPTR64LSB:
3211 case R_IA64_PCREL64LSB:
3212 case R_IA64_LTOFF_FPTR64LSB:
3213 case R_IA64_SEGREL64LSB:
3214 case R_IA64_SECREL64LSB:
3215 case R_IA64_LTV64LSB:
3216 case R_IA64_TPREL64LSB:
3217 case R_IA64_DTPMOD64LSB:
3218 case R_IA64_DTPREL64LSB:
3219 size = 8; bigendian = 0;
3220 break;
3222 /* Unsupported / Dynamic relocations. */
3223 default:
3224 return bfd_reloc_notsupported;
3227 switch (opnd)
3229 case IA64_OPND_IMMU64:
3230 hit_addr -= (long) hit_addr & 0x3;
3231 t0 = bfd_get_64 (abfd, hit_addr);
3232 t1 = bfd_get_64 (abfd, hit_addr + 8);
3234 /* tmpl/s: bits 0.. 5 in t0
3235 slot 0: bits 5..45 in t0
3236 slot 1: bits 46..63 in t0, bits 0..22 in t1
3237 slot 2: bits 23..63 in t1 */
3239 /* First, clear the bits that form the 64 bit constant. */
3240 t0 &= ~(0x3ffffLL << 46);
3241 t1 &= ~(0x7fffffLL
3242 | (( (0x07fLL << 13) | (0x1ffLL << 27)
3243 | (0x01fLL << 22) | (0x001LL << 21)
3244 | (0x001LL << 36)) << 23));
3246 t0 |= ((val >> 22) & 0x03ffffLL) << 46; /* 18 lsbs of imm41 */
3247 t1 |= ((val >> 40) & 0x7fffffLL) << 0; /* 23 msbs of imm41 */
3248 t1 |= ( (((val >> 0) & 0x07f) << 13) /* imm7b */
3249 | (((val >> 7) & 0x1ff) << 27) /* imm9d */
3250 | (((val >> 16) & 0x01f) << 22) /* imm5c */
3251 | (((val >> 21) & 0x001) << 21) /* ic */
3252 | (((val >> 63) & 0x001) << 36)) << 23; /* i */
3254 bfd_put_64 (abfd, t0, hit_addr);
3255 bfd_put_64 (abfd, t1, hit_addr + 8);
3256 break;
3258 case IA64_OPND_TGT64:
3259 hit_addr -= (long) hit_addr & 0x3;
3260 t0 = bfd_get_64 (abfd, hit_addr);
3261 t1 = bfd_get_64 (abfd, hit_addr + 8);
3263 /* tmpl/s: bits 0.. 5 in t0
3264 slot 0: bits 5..45 in t0
3265 slot 1: bits 46..63 in t0, bits 0..22 in t1
3266 slot 2: bits 23..63 in t1 */
3268 /* First, clear the bits that form the 64 bit constant. */
3269 t0 &= ~(0x3ffffLL << 46);
3270 t1 &= ~(0x7fffffLL
3271 | ((1LL << 36 | 0xfffffLL << 13) << 23));
3273 val >>= 4;
3274 t0 |= ((val >> 20) & 0xffffLL) << 2 << 46; /* 16 lsbs of imm39 */
3275 t1 |= ((val >> 36) & 0x7fffffLL) << 0; /* 23 msbs of imm39 */
3276 t1 |= ((((val >> 0) & 0xfffffLL) << 13) /* imm20b */
3277 | (((val >> 59) & 0x1LL) << 36)) << 23; /* i */
3279 bfd_put_64 (abfd, t0, hit_addr);
3280 bfd_put_64 (abfd, t1, hit_addr + 8);
3281 break;
3283 default:
3284 switch ((long) hit_addr & 0x3)
3286 case 0: shift = 5; break;
3287 case 1: shift = 14; hit_addr += 3; break;
3288 case 2: shift = 23; hit_addr += 6; break;
3289 case 3: return bfd_reloc_notsupported; /* shouldn't happen... */
3291 dword = bfd_get_64 (abfd, hit_addr);
3292 insn = (dword >> shift) & 0x1ffffffffffLL;
3294 op = elf64_ia64_operands + opnd;
3295 err = (*op->insert) (op, val, (ia64_insn *)& insn);
3296 if (err)
3297 return bfd_reloc_overflow;
3299 dword &= ~(0x1ffffffffffLL << shift);
3300 dword |= (insn << shift);
3301 bfd_put_64 (abfd, dword, hit_addr);
3302 break;
3304 case IA64_OPND_NIL:
3305 /* A data relocation. */
3306 if (bigendian)
3307 if (size == 4)
3308 bfd_putb32 (val, hit_addr);
3309 else
3310 bfd_putb64 (val, hit_addr);
3311 else
3312 if (size == 4)
3313 bfd_putl32 (val, hit_addr);
3314 else
3315 bfd_putl64 (val, hit_addr);
3316 break;
3319 return bfd_reloc_ok;
3322 static void
3323 elfNN_ia64_install_dyn_reloc (abfd, info, sec, srel, offset, type,
3324 dynindx, addend)
3325 bfd *abfd;
3326 struct bfd_link_info *info;
3327 asection *sec;
3328 asection *srel;
3329 bfd_vma offset;
3330 unsigned int type;
3331 long dynindx;
3332 bfd_vma addend;
3334 Elf_Internal_Rela outrel;
3335 bfd_byte *loc;
3337 BFD_ASSERT (dynindx != -1);
3338 outrel.r_info = ELFNN_R_INFO (dynindx, type);
3339 outrel.r_addend = addend;
3340 outrel.r_offset = _bfd_elf_section_offset (abfd, info, sec, offset);
3341 if (outrel.r_offset >= (bfd_vma) -2)
3343 /* Run for the hills. We shouldn't be outputting a relocation
3344 for this. So do what everyone else does and output a no-op. */
3345 outrel.r_info = ELFNN_R_INFO (0, R_IA64_NONE);
3346 outrel.r_addend = 0;
3347 outrel.r_offset = 0;
3349 else
3350 outrel.r_offset += sec->output_section->vma + sec->output_offset;
3352 loc = srel->contents;
3353 loc += srel->reloc_count++ * sizeof (ElfNN_External_Rela);
3354 bfd_elfNN_swap_reloca_out (abfd, &outrel, loc);
3355 BFD_ASSERT (sizeof (ElfNN_External_Rela) * srel->reloc_count
3356 <= srel->_cooked_size);
3359 /* Store an entry for target address TARGET_ADDR in the linkage table
3360 and return the gp-relative address of the linkage table entry. */
3362 static bfd_vma
3363 set_got_entry (abfd, info, dyn_i, dynindx, addend, value, dyn_r_type)
3364 bfd *abfd;
3365 struct bfd_link_info *info;
3366 struct elfNN_ia64_dyn_sym_info *dyn_i;
3367 long dynindx;
3368 bfd_vma addend;
3369 bfd_vma value;
3370 unsigned int dyn_r_type;
3372 struct elfNN_ia64_link_hash_table *ia64_info;
3373 asection *got_sec;
3374 bfd_boolean done;
3375 bfd_vma got_offset;
3377 ia64_info = elfNN_ia64_hash_table (info);
3378 got_sec = ia64_info->got_sec;
3380 switch (dyn_r_type)
3382 case R_IA64_TPREL64LSB:
3383 done = dyn_i->tprel_done;
3384 dyn_i->tprel_done = TRUE;
3385 got_offset = dyn_i->tprel_offset;
3386 break;
3387 case R_IA64_DTPMOD64LSB:
3388 if (dyn_i->dtpmod_offset != ia64_info->self_dtpmod_offset)
3390 done = dyn_i->dtpmod_done;
3391 dyn_i->dtpmod_done = TRUE;
3393 else
3395 done = ia64_info->self_dtpmod_done;
3396 ia64_info->self_dtpmod_done = TRUE;
3397 dynindx = 0;
3399 got_offset = dyn_i->dtpmod_offset;
3400 break;
3401 case R_IA64_DTPREL64LSB:
3402 done = dyn_i->dtprel_done;
3403 dyn_i->dtprel_done = TRUE;
3404 got_offset = dyn_i->dtprel_offset;
3405 break;
3406 default:
3407 done = dyn_i->got_done;
3408 dyn_i->got_done = TRUE;
3409 got_offset = dyn_i->got_offset;
3410 break;
3413 BFD_ASSERT ((got_offset & 7) == 0);
3415 if (! done)
3417 /* Store the target address in the linkage table entry. */
3418 bfd_put_64 (abfd, value, got_sec->contents + got_offset);
3420 /* Install a dynamic relocation if needed. */
3421 if ((info->shared && dyn_r_type != R_IA64_DTPREL64LSB)
3422 || elfNN_ia64_dynamic_symbol_p (dyn_i->h, info)
3423 || elfNN_ia64_aix_vec (abfd->xvec)
3424 || (dynindx != -1 && dyn_r_type == R_IA64_FPTR64LSB))
3426 if (dynindx == -1
3427 && dyn_r_type != R_IA64_TPREL64LSB
3428 && dyn_r_type != R_IA64_DTPMOD64LSB
3429 && dyn_r_type != R_IA64_DTPREL64LSB)
3431 dyn_r_type = R_IA64_REL64LSB;
3432 dynindx = 0;
3433 addend = value;
3436 if (bfd_big_endian (abfd))
3438 switch (dyn_r_type)
3440 case R_IA64_REL64LSB:
3441 dyn_r_type = R_IA64_REL64MSB;
3442 break;
3443 case R_IA64_DIR64LSB:
3444 dyn_r_type = R_IA64_DIR64MSB;
3445 break;
3446 case R_IA64_FPTR64LSB:
3447 dyn_r_type = R_IA64_FPTR64MSB;
3448 break;
3449 case R_IA64_TPREL64LSB:
3450 dyn_r_type = R_IA64_TPREL64MSB;
3451 break;
3452 case R_IA64_DTPMOD64LSB:
3453 dyn_r_type = R_IA64_DTPMOD64MSB;
3454 break;
3455 case R_IA64_DTPREL64LSB:
3456 dyn_r_type = R_IA64_DTPREL64MSB;
3457 break;
3458 default:
3459 BFD_ASSERT (FALSE);
3460 break;
3464 elfNN_ia64_install_dyn_reloc (abfd, NULL, got_sec,
3465 ia64_info->rel_got_sec,
3466 got_offset, dyn_r_type,
3467 dynindx, addend);
3471 /* Return the address of the linkage table entry. */
3472 value = (got_sec->output_section->vma
3473 + got_sec->output_offset
3474 + got_offset);
3476 return value;
3479 /* Fill in a function descriptor consisting of the function's code
3480 address and its global pointer. Return the descriptor's address. */
3482 static bfd_vma
3483 set_fptr_entry (abfd, info, dyn_i, value)
3484 bfd *abfd;
3485 struct bfd_link_info *info;
3486 struct elfNN_ia64_dyn_sym_info *dyn_i;
3487 bfd_vma value;
3489 struct elfNN_ia64_link_hash_table *ia64_info;
3490 asection *fptr_sec;
3492 ia64_info = elfNN_ia64_hash_table (info);
3493 fptr_sec = ia64_info->fptr_sec;
3495 if (!dyn_i->fptr_done)
3497 dyn_i->fptr_done = 1;
3499 /* Fill in the function descriptor. */
3500 bfd_put_64 (abfd, value, fptr_sec->contents + dyn_i->fptr_offset);
3501 bfd_put_64 (abfd, _bfd_get_gp_value (abfd),
3502 fptr_sec->contents + dyn_i->fptr_offset + 8);
3505 /* Return the descriptor's address. */
3506 value = (fptr_sec->output_section->vma
3507 + fptr_sec->output_offset
3508 + dyn_i->fptr_offset);
3510 return value;
3513 /* Fill in a PLTOFF entry consisting of the function's code address
3514 and its global pointer. Return the descriptor's address. */
3516 static bfd_vma
3517 set_pltoff_entry (abfd, info, dyn_i, value, is_plt)
3518 bfd *abfd;
3519 struct bfd_link_info *info;
3520 struct elfNN_ia64_dyn_sym_info *dyn_i;
3521 bfd_vma value;
3522 bfd_boolean is_plt;
3524 struct elfNN_ia64_link_hash_table *ia64_info;
3525 asection *pltoff_sec;
3527 ia64_info = elfNN_ia64_hash_table (info);
3528 pltoff_sec = ia64_info->pltoff_sec;
3530 /* Don't do anything if this symbol uses a real PLT entry. In
3531 that case, we'll fill this in during finish_dynamic_symbol. */
3532 if ((! dyn_i->want_plt || is_plt)
3533 && !dyn_i->pltoff_done)
3535 bfd_vma gp = _bfd_get_gp_value (abfd);
3537 /* Fill in the function descriptor. */
3538 bfd_put_64 (abfd, value, pltoff_sec->contents + dyn_i->pltoff_offset);
3539 bfd_put_64 (abfd, gp, pltoff_sec->contents + dyn_i->pltoff_offset + 8);
3541 /* Install dynamic relocations if needed. */
3542 if (!is_plt && info->shared)
3544 unsigned int dyn_r_type;
3546 if (bfd_big_endian (abfd))
3547 dyn_r_type = R_IA64_REL64MSB;
3548 else
3549 dyn_r_type = R_IA64_REL64LSB;
3551 elfNN_ia64_install_dyn_reloc (abfd, NULL, pltoff_sec,
3552 ia64_info->rel_pltoff_sec,
3553 dyn_i->pltoff_offset,
3554 dyn_r_type, 0, value);
3555 elfNN_ia64_install_dyn_reloc (abfd, NULL, pltoff_sec,
3556 ia64_info->rel_pltoff_sec,
3557 dyn_i->pltoff_offset + 8,
3558 dyn_r_type, 0, gp);
3561 dyn_i->pltoff_done = 1;
3564 /* Return the descriptor's address. */
3565 value = (pltoff_sec->output_section->vma
3566 + pltoff_sec->output_offset
3567 + dyn_i->pltoff_offset);
3569 return value;
3572 /* Return the base VMA address which should be subtracted from real addresses
3573 when resolving @tprel() relocation.
3574 Main program TLS (whose template starts at PT_TLS p_vaddr)
3575 is assigned offset round(16, PT_TLS p_align). */
3577 static bfd_vma
3578 elfNN_ia64_tprel_base (info)
3579 struct bfd_link_info *info;
3581 struct elf_link_tls_segment *tls_segment
3582 = elf_hash_table (info)->tls_segment;
3584 BFD_ASSERT (tls_segment != NULL);
3585 return (tls_segment->start
3586 - align_power ((bfd_vma) 16, tls_segment->align));
3589 /* Return the base VMA address which should be subtracted from real addresses
3590 when resolving @dtprel() relocation.
3591 This is PT_TLS segment p_vaddr. */
3593 static bfd_vma
3594 elfNN_ia64_dtprel_base (info)
3595 struct bfd_link_info *info;
3597 BFD_ASSERT (elf_hash_table (info)->tls_segment != NULL);
3598 return elf_hash_table (info)->tls_segment->start;
3601 /* Called through qsort to sort the .IA_64.unwind section during a
3602 non-relocatable link. Set elfNN_ia64_unwind_entry_compare_bfd
3603 to the output bfd so we can do proper endianness frobbing. */
3605 static bfd *elfNN_ia64_unwind_entry_compare_bfd;
3607 static int
3608 elfNN_ia64_unwind_entry_compare (a, b)
3609 const PTR a;
3610 const PTR b;
3612 bfd_vma av, bv;
3614 av = bfd_get_64 (elfNN_ia64_unwind_entry_compare_bfd, a);
3615 bv = bfd_get_64 (elfNN_ia64_unwind_entry_compare_bfd, b);
3617 return (av < bv ? -1 : av > bv ? 1 : 0);
3620 /* Make sure we've got ourselves a nice fat __gp value. */
3621 static bfd_boolean
3622 elfNN_ia64_choose_gp (abfd, info)
3623 bfd *abfd;
3624 struct bfd_link_info *info;
3626 bfd_vma min_vma = (bfd_vma) -1, max_vma = 0;
3627 bfd_vma min_short_vma = min_vma, max_short_vma = 0;
3628 struct elf_link_hash_entry *gp;
3629 bfd_vma gp_val;
3630 asection *os;
3631 struct elfNN_ia64_link_hash_table *ia64_info;
3633 ia64_info = elfNN_ia64_hash_table (info);
3635 /* Find the min and max vma of all sections marked short. Also collect
3636 min and max vma of any type, for use in selecting a nice gp. */
3637 for (os = abfd->sections; os ; os = os->next)
3639 bfd_vma lo, hi;
3641 if ((os->flags & SEC_ALLOC) == 0)
3642 continue;
3644 lo = os->vma;
3645 hi = os->vma + os->_raw_size;
3646 if (hi < lo)
3647 hi = (bfd_vma) -1;
3649 if (min_vma > lo)
3650 min_vma = lo;
3651 if (max_vma < hi)
3652 max_vma = hi;
3653 if (os->flags & SEC_SMALL_DATA)
3655 if (min_short_vma > lo)
3656 min_short_vma = lo;
3657 if (max_short_vma < hi)
3658 max_short_vma = hi;
3662 /* See if the user wants to force a value. */
3663 gp = elf_link_hash_lookup (elf_hash_table (info), "__gp", FALSE,
3664 FALSE, FALSE);
3666 if (gp
3667 && (gp->root.type == bfd_link_hash_defined
3668 || gp->root.type == bfd_link_hash_defweak))
3670 asection *gp_sec = gp->root.u.def.section;
3671 gp_val = (gp->root.u.def.value
3672 + gp_sec->output_section->vma
3673 + gp_sec->output_offset);
3675 else
3677 /* Pick a sensible value. */
3679 asection *got_sec = ia64_info->got_sec;
3681 /* Start with just the address of the .got. */
3682 if (got_sec)
3683 gp_val = got_sec->output_section->vma;
3684 else if (max_short_vma != 0)
3685 gp_val = min_short_vma;
3686 else
3687 gp_val = min_vma;
3689 /* If it is possible to address the entire image, but we
3690 don't with the choice above, adjust. */
3691 if (max_vma - min_vma < 0x400000
3692 && max_vma - gp_val <= 0x200000
3693 && gp_val - min_vma > 0x200000)
3694 gp_val = min_vma + 0x200000;
3695 else if (max_short_vma != 0)
3697 /* If we don't cover all the short data, adjust. */
3698 if (max_short_vma - gp_val >= 0x200000)
3699 gp_val = min_short_vma + 0x200000;
3701 /* If we're addressing stuff past the end, adjust back. */
3702 if (gp_val > max_vma)
3703 gp_val = max_vma - 0x200000 + 8;
3707 /* Validate whether all SHF_IA_64_SHORT sections are within
3708 range of the chosen GP. */
3710 if (max_short_vma != 0)
3712 if (max_short_vma - min_short_vma >= 0x400000)
3714 (*_bfd_error_handler)
3715 (_("%s: short data segment overflowed (0x%lx >= 0x400000)"),
3716 bfd_get_filename (abfd),
3717 (unsigned long) (max_short_vma - min_short_vma));
3718 return FALSE;
3720 else if ((gp_val > min_short_vma
3721 && gp_val - min_short_vma > 0x200000)
3722 || (gp_val < max_short_vma
3723 && max_short_vma - gp_val >= 0x200000))
3725 (*_bfd_error_handler)
3726 (_("%s: __gp does not cover short data segment"),
3727 bfd_get_filename (abfd));
3728 return FALSE;
3732 _bfd_set_gp_value (abfd, gp_val);
3734 return TRUE;
3737 static bfd_boolean
3738 elfNN_ia64_final_link (abfd, info)
3739 bfd *abfd;
3740 struct bfd_link_info *info;
3742 struct elfNN_ia64_link_hash_table *ia64_info;
3743 asection *unwind_output_sec;
3745 ia64_info = elfNN_ia64_hash_table (info);
3747 /* Make sure we've got ourselves a nice fat __gp value. */
3748 if (!info->relocateable)
3750 bfd_vma gp_val = _bfd_get_gp_value (abfd);
3751 struct elf_link_hash_entry *gp;
3753 if (gp_val == 0)
3755 if (! elfNN_ia64_choose_gp (abfd, info))
3756 return FALSE;
3757 gp_val = _bfd_get_gp_value (abfd);
3760 gp = elf_link_hash_lookup (elf_hash_table (info), "__gp", FALSE,
3761 FALSE, FALSE);
3762 if (gp)
3764 gp->root.type = bfd_link_hash_defined;
3765 gp->root.u.def.value = gp_val;
3766 gp->root.u.def.section = bfd_abs_section_ptr;
3770 /* If we're producing a final executable, we need to sort the contents
3771 of the .IA_64.unwind section. Force this section to be relocated
3772 into memory rather than written immediately to the output file. */
3773 unwind_output_sec = NULL;
3774 if (!info->relocateable)
3776 asection *s = bfd_get_section_by_name (abfd, ELF_STRING_ia64_unwind);
3777 if (s)
3779 unwind_output_sec = s->output_section;
3780 unwind_output_sec->contents
3781 = bfd_malloc (unwind_output_sec->_raw_size);
3782 if (unwind_output_sec->contents == NULL)
3783 return FALSE;
3787 /* Invoke the regular ELF backend linker to do all the work. */
3788 if (!bfd_elfNN_bfd_final_link (abfd, info))
3789 return FALSE;
3791 if (unwind_output_sec)
3793 elfNN_ia64_unwind_entry_compare_bfd = abfd;
3794 qsort (unwind_output_sec->contents,
3795 (size_t) (unwind_output_sec->_raw_size / 24),
3797 elfNN_ia64_unwind_entry_compare);
3799 if (! bfd_set_section_contents (abfd, unwind_output_sec,
3800 unwind_output_sec->contents, (bfd_vma) 0,
3801 unwind_output_sec->_raw_size))
3802 return FALSE;
3805 return TRUE;
3808 static bfd_boolean
3809 elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
3810 contents, relocs, local_syms, local_sections)
3811 bfd *output_bfd;
3812 struct bfd_link_info *info;
3813 bfd *input_bfd;
3814 asection *input_section;
3815 bfd_byte *contents;
3816 Elf_Internal_Rela *relocs;
3817 Elf_Internal_Sym *local_syms;
3818 asection **local_sections;
3820 struct elfNN_ia64_link_hash_table *ia64_info;
3821 Elf_Internal_Shdr *symtab_hdr;
3822 Elf_Internal_Rela *rel;
3823 Elf_Internal_Rela *relend;
3824 asection *srel;
3825 bfd_boolean ret_val = TRUE; /* for non-fatal errors */
3826 bfd_vma gp_val;
3828 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
3829 ia64_info = elfNN_ia64_hash_table (info);
3831 /* Infect various flags from the input section to the output section. */
3832 if (info->relocateable)
3834 bfd_vma flags;
3836 flags = elf_section_data(input_section)->this_hdr.sh_flags;
3837 flags &= SHF_IA_64_NORECOV;
3839 elf_section_data(input_section->output_section)
3840 ->this_hdr.sh_flags |= flags;
3841 return TRUE;
3844 gp_val = _bfd_get_gp_value (output_bfd);
3845 srel = get_reloc_section (input_bfd, ia64_info, input_section, FALSE);
3847 rel = relocs;
3848 relend = relocs + input_section->reloc_count;
3849 for (; rel < relend; ++rel)
3851 struct elf_link_hash_entry *h;
3852 struct elfNN_ia64_dyn_sym_info *dyn_i;
3853 bfd_reloc_status_type r;
3854 reloc_howto_type *howto;
3855 unsigned long r_symndx;
3856 Elf_Internal_Sym *sym;
3857 unsigned int r_type;
3858 bfd_vma value;
3859 asection *sym_sec;
3860 bfd_byte *hit_addr;
3861 bfd_boolean dynamic_symbol_p;
3862 bfd_boolean undef_weak_ref;
3864 r_type = ELFNN_R_TYPE (rel->r_info);
3865 if (r_type > R_IA64_MAX_RELOC_CODE)
3867 (*_bfd_error_handler)
3868 (_("%s: unknown relocation type %d"),
3869 bfd_archive_filename (input_bfd), (int)r_type);
3870 bfd_set_error (bfd_error_bad_value);
3871 ret_val = FALSE;
3872 continue;
3875 howto = lookup_howto (r_type);
3876 r_symndx = ELFNN_R_SYM (rel->r_info);
3877 h = NULL;
3878 sym = NULL;
3879 sym_sec = NULL;
3880 undef_weak_ref = FALSE;
3882 if (r_symndx < symtab_hdr->sh_info)
3884 /* Reloc against local symbol. */
3885 sym = local_syms + r_symndx;
3886 sym_sec = local_sections[r_symndx];
3887 value = _bfd_elf_rela_local_sym (output_bfd, sym, sym_sec, rel);
3888 if ((sym_sec->flags & SEC_MERGE)
3889 && ELF_ST_TYPE (sym->st_info) == STT_SECTION
3890 && sym_sec->sec_info_type == ELF_INFO_TYPE_MERGE)
3892 struct elfNN_ia64_local_hash_entry *loc_h;
3894 loc_h = get_local_sym_hash (ia64_info, input_bfd, rel, FALSE);
3895 if (loc_h && ! loc_h->sec_merge_done)
3897 struct elfNN_ia64_dyn_sym_info *dynent;
3898 asection *msec;
3900 for (dynent = loc_h->info; dynent; dynent = dynent->next)
3902 msec = sym_sec;
3903 dynent->addend =
3904 _bfd_merged_section_offset (output_bfd, &msec,
3905 elf_section_data (msec)->
3906 sec_info,
3907 sym->st_value
3908 + dynent->addend,
3909 (bfd_vma) 0);
3910 dynent->addend -= sym->st_value;
3911 dynent->addend += msec->output_section->vma
3912 + msec->output_offset
3913 - sym_sec->output_section->vma
3914 - sym_sec->output_offset;
3916 loc_h->sec_merge_done = 1;
3920 else
3922 long indx;
3924 /* Reloc against global symbol. */
3925 indx = r_symndx - symtab_hdr->sh_info;
3926 h = elf_sym_hashes (input_bfd)[indx];
3927 while (h->root.type == bfd_link_hash_indirect
3928 || h->root.type == bfd_link_hash_warning)
3929 h = (struct elf_link_hash_entry *) h->root.u.i.link;
3931 value = 0;
3932 if (h->root.type == bfd_link_hash_defined
3933 || h->root.type == bfd_link_hash_defweak)
3935 sym_sec = h->root.u.def.section;
3937 /* Detect the cases that sym_sec->output_section is
3938 expected to be NULL -- all cases in which the symbol
3939 is defined in another shared module. This includes
3940 PLT relocs for which we've created a PLT entry and
3941 other relocs for which we're prepared to create
3942 dynamic relocations. */
3943 /* ??? Just accept it NULL and continue. */
3945 if (sym_sec->output_section != NULL)
3947 value = (h->root.u.def.value
3948 + sym_sec->output_section->vma
3949 + sym_sec->output_offset);
3952 else if (h->root.type == bfd_link_hash_undefweak)
3953 undef_weak_ref = TRUE;
3954 else if (info->shared
3955 && !info->no_undefined
3956 && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
3958 else
3960 if (! ((*info->callbacks->undefined_symbol)
3961 (info, h->root.root.string, input_bfd,
3962 input_section, rel->r_offset,
3963 (!info->shared || info->no_undefined
3964 || ELF_ST_VISIBILITY (h->other)))))
3965 return FALSE;
3966 continue;
3970 hit_addr = contents + rel->r_offset;
3971 value += rel->r_addend;
3972 dynamic_symbol_p = elfNN_ia64_dynamic_symbol_p (h, info);
3974 switch (r_type)
3976 case R_IA64_NONE:
3977 case R_IA64_LDXMOV:
3978 continue;
3980 case R_IA64_IMM14:
3981 case R_IA64_IMM22:
3982 case R_IA64_IMM64:
3983 case R_IA64_DIR32MSB:
3984 case R_IA64_DIR32LSB:
3985 case R_IA64_DIR64MSB:
3986 case R_IA64_DIR64LSB:
3987 /* Install a dynamic relocation for this reloc. */
3988 if ((dynamic_symbol_p || info->shared
3989 || (elfNN_ia64_aix_vec (info->hash->creator)
3990 /* Don't emit relocs for __GLOB_DATA_PTR on AIX. */
3991 && (!h || strcmp (h->root.root.string,
3992 "__GLOB_DATA_PTR") != 0)))
3993 && r_symndx != 0
3994 && (input_section->flags & SEC_ALLOC) != 0)
3996 unsigned int dyn_r_type;
3997 long dynindx;
3998 bfd_vma addend;
4000 BFD_ASSERT (srel != NULL);
4002 /* If we don't need dynamic symbol lookup, find a
4003 matching RELATIVE relocation. */
4004 dyn_r_type = r_type;
4005 if (dynamic_symbol_p)
4007 dynindx = h->dynindx;
4008 addend = rel->r_addend;
4009 value = 0;
4011 else
4013 switch (r_type)
4015 case R_IA64_DIR32MSB:
4016 dyn_r_type = R_IA64_REL32MSB;
4017 break;
4018 case R_IA64_DIR32LSB:
4019 dyn_r_type = R_IA64_REL32LSB;
4020 break;
4021 case R_IA64_DIR64MSB:
4022 dyn_r_type = R_IA64_REL64MSB;
4023 break;
4024 case R_IA64_DIR64LSB:
4025 dyn_r_type = R_IA64_REL64LSB;
4026 break;
4028 default:
4029 /* We can't represent this without a dynamic symbol.
4030 Adjust the relocation to be against an output
4031 section symbol, which are always present in the
4032 dynamic symbol table. */
4033 /* ??? People shouldn't be doing non-pic code in
4034 shared libraries. Hork. */
4035 (*_bfd_error_handler)
4036 (_("%s: linking non-pic code in a shared library"),
4037 bfd_archive_filename (input_bfd));
4038 ret_val = FALSE;
4039 continue;
4041 dynindx = 0;
4042 addend = value;
4045 if (elfNN_ia64_aix_vec (info->hash->creator))
4046 rel->r_addend = value;
4047 elfNN_ia64_install_dyn_reloc (output_bfd, info, input_section,
4048 srel, rel->r_offset, dyn_r_type,
4049 dynindx, addend);
4051 /* Fall through. */
4053 case R_IA64_LTV32MSB:
4054 case R_IA64_LTV32LSB:
4055 case R_IA64_LTV64MSB:
4056 case R_IA64_LTV64LSB:
4057 r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
4058 break;
4060 case R_IA64_GPREL22:
4061 case R_IA64_GPREL64I:
4062 case R_IA64_GPREL32MSB:
4063 case R_IA64_GPREL32LSB:
4064 case R_IA64_GPREL64MSB:
4065 case R_IA64_GPREL64LSB:
4066 if (dynamic_symbol_p)
4068 (*_bfd_error_handler)
4069 (_("%s: @gprel relocation against dynamic symbol %s"),
4070 bfd_archive_filename (input_bfd), h->root.root.string);
4071 ret_val = FALSE;
4072 continue;
4074 value -= gp_val;
4075 r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
4076 break;
4078 case R_IA64_LTOFF22:
4079 case R_IA64_LTOFF22X:
4080 case R_IA64_LTOFF64I:
4081 dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
4082 value = set_got_entry (input_bfd, info, dyn_i, (h ? h->dynindx : -1),
4083 rel->r_addend, value, R_IA64_DIR64LSB);
4084 value -= gp_val;
4085 r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
4086 break;
4088 case R_IA64_PLTOFF22:
4089 case R_IA64_PLTOFF64I:
4090 case R_IA64_PLTOFF64MSB:
4091 case R_IA64_PLTOFF64LSB:
4092 dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
4093 value = set_pltoff_entry (output_bfd, info, dyn_i, value, FALSE);
4094 value -= gp_val;
4095 r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
4096 break;
4098 case R_IA64_FPTR64I:
4099 case R_IA64_FPTR32MSB:
4100 case R_IA64_FPTR32LSB:
4101 case R_IA64_FPTR64MSB:
4102 case R_IA64_FPTR64LSB:
4103 dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
4104 if (dyn_i->want_fptr)
4106 if (!undef_weak_ref)
4107 value = set_fptr_entry (output_bfd, info, dyn_i, value);
4109 else
4111 long dynindx;
4113 /* Otherwise, we expect the dynamic linker to create
4114 the entry. */
4116 if (h)
4118 if (h->dynindx != -1)
4119 dynindx = h->dynindx;
4120 else
4121 dynindx = (_bfd_elf_link_lookup_local_dynindx
4122 (info, h->root.u.def.section->owner,
4123 global_sym_index (h)));
4125 else
4127 dynindx = (_bfd_elf_link_lookup_local_dynindx
4128 (info, input_bfd, (long) r_symndx));
4131 elfNN_ia64_install_dyn_reloc (output_bfd, info, input_section,
4132 srel, rel->r_offset, r_type,
4133 dynindx, rel->r_addend);
4134 value = 0;
4137 r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
4138 break;
4140 case R_IA64_LTOFF_FPTR22:
4141 case R_IA64_LTOFF_FPTR64I:
4142 case R_IA64_LTOFF_FPTR32MSB:
4143 case R_IA64_LTOFF_FPTR32LSB:
4144 case R_IA64_LTOFF_FPTR64MSB:
4145 case R_IA64_LTOFF_FPTR64LSB:
4147 long dynindx;
4149 dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
4150 if (dyn_i->want_fptr)
4152 BFD_ASSERT (h == NULL || h->dynindx == -1)
4153 if (!undef_weak_ref)
4154 value = set_fptr_entry (output_bfd, info, dyn_i, value);
4155 dynindx = -1;
4157 else
4159 /* Otherwise, we expect the dynamic linker to create
4160 the entry. */
4161 if (h)
4163 if (h->dynindx != -1)
4164 dynindx = h->dynindx;
4165 else
4166 dynindx = (_bfd_elf_link_lookup_local_dynindx
4167 (info, h->root.u.def.section->owner,
4168 global_sym_index (h)));
4170 else
4171 dynindx = (_bfd_elf_link_lookup_local_dynindx
4172 (info, input_bfd, (long) r_symndx));
4173 value = 0;
4176 value = set_got_entry (output_bfd, info, dyn_i, dynindx,
4177 rel->r_addend, value, R_IA64_FPTR64LSB);
4178 value -= gp_val;
4179 r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
4181 break;
4183 case R_IA64_PCREL32MSB:
4184 case R_IA64_PCREL32LSB:
4185 case R_IA64_PCREL64MSB:
4186 case R_IA64_PCREL64LSB:
4187 /* Install a dynamic relocation for this reloc. */
4188 if ((dynamic_symbol_p
4189 || elfNN_ia64_aix_vec (info->hash->creator))
4190 && r_symndx != 0)
4192 BFD_ASSERT (srel != NULL);
4194 elfNN_ia64_install_dyn_reloc (output_bfd, info, input_section,
4195 srel, rel->r_offset, r_type,
4196 h->dynindx, rel->r_addend);
4198 goto finish_pcrel;
4200 case R_IA64_PCREL21B:
4201 case R_IA64_PCREL60B:
4202 /* We should have created a PLT entry for any dynamic symbol. */
4203 dyn_i = NULL;
4204 if (h)
4205 dyn_i = get_dyn_sym_info (ia64_info, h, NULL, NULL, FALSE);
4207 if (dyn_i && dyn_i->want_plt2)
4209 /* Should have caught this earlier. */
4210 BFD_ASSERT (rel->r_addend == 0);
4212 value = (ia64_info->plt_sec->output_section->vma
4213 + ia64_info->plt_sec->output_offset
4214 + dyn_i->plt2_offset);
4216 else
4218 /* Since there's no PLT entry, Validate that this is
4219 locally defined. */
4220 BFD_ASSERT (undef_weak_ref || sym_sec->output_section != NULL);
4222 /* If the symbol is undef_weak, we shouldn't be trying
4223 to call it. There's every chance that we'd wind up
4224 with an out-of-range fixup here. Don't bother setting
4225 any value at all. */
4226 if (undef_weak_ref)
4227 continue;
4229 goto finish_pcrel;
4231 case R_IA64_PCREL21BI:
4232 case R_IA64_PCREL21F:
4233 case R_IA64_PCREL21M:
4234 case R_IA64_PCREL22:
4235 case R_IA64_PCREL64I:
4236 /* The PCREL21BI reloc is specifically not intended for use with
4237 dynamic relocs. PCREL21F and PCREL21M are used for speculation
4238 fixup code, and thus probably ought not be dynamic. The
4239 PCREL22 and PCREL64I relocs aren't emitted as dynamic relocs. */
4240 if (dynamic_symbol_p)
4242 const char *msg;
4244 if (r_type == R_IA64_PCREL21BI)
4245 msg = _("%s: @internal branch to dynamic symbol %s");
4246 else if (r_type == R_IA64_PCREL21F || r_type == R_IA64_PCREL21M)
4247 msg = _("%s: speculation fixup to dynamic symbol %s");
4248 else
4249 msg = _("%s: @pcrel relocation against dynamic symbol %s");
4250 (*_bfd_error_handler) (msg, bfd_archive_filename (input_bfd),
4251 h->root.root.string);
4252 ret_val = FALSE;
4253 continue;
4255 goto finish_pcrel;
4257 finish_pcrel:
4258 /* Make pc-relative. */
4259 value -= (input_section->output_section->vma
4260 + input_section->output_offset
4261 + rel->r_offset) & ~ (bfd_vma) 0x3;
4262 r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
4263 break;
4265 case R_IA64_SEGREL32MSB:
4266 case R_IA64_SEGREL32LSB:
4267 case R_IA64_SEGREL64MSB:
4268 case R_IA64_SEGREL64LSB:
4269 if (r_symndx == 0)
4271 /* If the input section was discarded from the output, then
4272 do nothing. */
4273 r = bfd_reloc_ok;
4275 else
4277 struct elf_segment_map *m;
4278 Elf_Internal_Phdr *p;
4280 /* Find the segment that contains the output_section. */
4281 for (m = elf_tdata (output_bfd)->segment_map,
4282 p = elf_tdata (output_bfd)->phdr;
4283 m != NULL;
4284 m = m->next, p++)
4286 int i;
4287 for (i = m->count - 1; i >= 0; i--)
4288 if (m->sections[i] == sym_sec->output_section)
4289 break;
4290 if (i >= 0)
4291 break;
4294 if (m == NULL)
4296 r = bfd_reloc_notsupported;
4298 else
4300 /* The VMA of the segment is the vaddr of the associated
4301 program header. */
4302 if (value > p->p_vaddr)
4303 value -= p->p_vaddr;
4304 else
4305 value = 0;
4306 r = elfNN_ia64_install_value (output_bfd, hit_addr, value,
4307 r_type);
4309 break;
4312 case R_IA64_SECREL32MSB:
4313 case R_IA64_SECREL32LSB:
4314 case R_IA64_SECREL64MSB:
4315 case R_IA64_SECREL64LSB:
4316 /* Make output-section relative. */
4317 if (value > input_section->output_section->vma)
4318 value -= input_section->output_section->vma;
4319 else
4320 value = 0;
4321 r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
4322 break;
4324 case R_IA64_IPLTMSB:
4325 case R_IA64_IPLTLSB:
4326 /* Install a dynamic relocation for this reloc. */
4327 if ((dynamic_symbol_p || info->shared)
4328 && (input_section->flags & SEC_ALLOC) != 0)
4330 BFD_ASSERT (srel != NULL);
4332 /* If we don't need dynamic symbol lookup, install two
4333 RELATIVE relocations. */
4334 if (! dynamic_symbol_p)
4336 unsigned int dyn_r_type;
4338 if (r_type == R_IA64_IPLTMSB)
4339 dyn_r_type = R_IA64_REL64MSB;
4340 else
4341 dyn_r_type = R_IA64_REL64LSB;
4343 elfNN_ia64_install_dyn_reloc (output_bfd, info,
4344 input_section,
4345 srel, rel->r_offset,
4346 dyn_r_type, 0, value);
4347 elfNN_ia64_install_dyn_reloc (output_bfd, info,
4348 input_section,
4349 srel, rel->r_offset + 8,
4350 dyn_r_type, 0, gp_val);
4352 else
4353 elfNN_ia64_install_dyn_reloc (output_bfd, info, input_section,
4354 srel, rel->r_offset, r_type,
4355 h->dynindx, rel->r_addend);
4358 if (r_type == R_IA64_IPLTMSB)
4359 r_type = R_IA64_DIR64MSB;
4360 else
4361 r_type = R_IA64_DIR64LSB;
4362 elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
4363 r = elfNN_ia64_install_value (output_bfd, hit_addr + 8, gp_val,
4364 r_type);
4365 break;
4367 case R_IA64_TPREL14:
4368 case R_IA64_TPREL22:
4369 case R_IA64_TPREL64I:
4370 value -= elfNN_ia64_tprel_base (info);
4371 r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
4372 break;
4374 case R_IA64_DTPREL14:
4375 case R_IA64_DTPREL22:
4376 case R_IA64_DTPREL64I:
4377 case R_IA64_DTPREL64LSB:
4378 case R_IA64_DTPREL64MSB:
4379 value -= elfNN_ia64_dtprel_base (info);
4380 r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
4381 break;
4383 case R_IA64_LTOFF_TPREL22:
4384 case R_IA64_LTOFF_DTPMOD22:
4385 case R_IA64_LTOFF_DTPREL22:
4387 int got_r_type;
4388 long dynindx = h ? h->dynindx : -1;
4389 bfd_vma r_addend = rel->r_addend;
4391 switch (r_type)
4393 default:
4394 case R_IA64_LTOFF_TPREL22:
4395 if (!dynamic_symbol_p)
4397 if (!info->shared)
4398 value -= elfNN_ia64_tprel_base (info);
4399 else
4401 r_addend += value - elfNN_ia64_dtprel_base (info);
4402 dynindx = 0;
4405 got_r_type = R_IA64_TPREL64LSB;
4406 break;
4407 case R_IA64_LTOFF_DTPMOD22:
4408 if (!dynamic_symbol_p && !info->shared)
4409 value = 1;
4410 got_r_type = R_IA64_DTPMOD64LSB;
4411 break;
4412 case R_IA64_LTOFF_DTPREL22:
4413 if (!dynamic_symbol_p)
4414 value -= elfNN_ia64_dtprel_base (info);
4415 got_r_type = R_IA64_DTPREL64LSB;
4416 break;
4418 dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
4419 value = set_got_entry (input_bfd, info, dyn_i, dynindx, r_addend,
4420 value, got_r_type);
4421 value -= gp_val;
4422 r = elfNN_ia64_install_value (output_bfd, hit_addr, value,
4423 r_type);
4425 break;
4427 default:
4428 r = bfd_reloc_notsupported;
4429 break;
4432 switch (r)
4434 case bfd_reloc_ok:
4435 break;
4437 case bfd_reloc_undefined:
4438 /* This can happen for global table relative relocs if
4439 __gp is undefined. This is a panic situation so we
4440 don't try to continue. */
4441 (*info->callbacks->undefined_symbol)
4442 (info, "__gp", input_bfd, input_section, rel->r_offset, 1);
4443 return FALSE;
4445 case bfd_reloc_notsupported:
4447 const char *name;
4449 if (h)
4450 name = h->root.root.string;
4451 else
4453 name = bfd_elf_string_from_elf_section (input_bfd,
4454 symtab_hdr->sh_link,
4455 sym->st_name);
4456 if (name == NULL)
4457 return FALSE;
4458 if (*name == '\0')
4459 name = bfd_section_name (input_bfd, input_section);
4461 if (!(*info->callbacks->warning) (info, _("unsupported reloc"),
4462 name, input_bfd,
4463 input_section, rel->r_offset))
4464 return FALSE;
4465 ret_val = FALSE;
4467 break;
4469 case bfd_reloc_dangerous:
4470 case bfd_reloc_outofrange:
4471 case bfd_reloc_overflow:
4472 default:
4474 const char *name;
4476 if (h)
4477 name = h->root.root.string;
4478 else
4480 name = bfd_elf_string_from_elf_section (input_bfd,
4481 symtab_hdr->sh_link,
4482 sym->st_name);
4483 if (name == NULL)
4484 return FALSE;
4485 if (*name == '\0')
4486 name = bfd_section_name (input_bfd, input_section);
4488 if (!(*info->callbacks->reloc_overflow) (info, name,
4489 howto->name,
4490 (bfd_vma) 0,
4491 input_bfd,
4492 input_section,
4493 rel->r_offset))
4494 return FALSE;
4495 ret_val = FALSE;
4497 break;
4501 return ret_val;
4504 static bfd_boolean
4505 elfNN_ia64_finish_dynamic_symbol (output_bfd, info, h, sym)
4506 bfd *output_bfd;
4507 struct bfd_link_info *info;
4508 struct elf_link_hash_entry *h;
4509 Elf_Internal_Sym *sym;
4511 struct elfNN_ia64_link_hash_table *ia64_info;
4512 struct elfNN_ia64_dyn_sym_info *dyn_i;
4514 ia64_info = elfNN_ia64_hash_table (info);
4515 dyn_i = get_dyn_sym_info (ia64_info, h, NULL, NULL, FALSE);
4517 /* Fill in the PLT data, if required. */
4518 if (dyn_i && dyn_i->want_plt)
4520 Elf_Internal_Rela outrel;
4521 bfd_byte *loc;
4522 asection *plt_sec;
4523 bfd_vma plt_addr, pltoff_addr, gp_val, index;
4525 gp_val = _bfd_get_gp_value (output_bfd);
4527 /* Initialize the minimal PLT entry. */
4529 index = (dyn_i->plt_offset - PLT_HEADER_SIZE) / PLT_MIN_ENTRY_SIZE;
4530 plt_sec = ia64_info->plt_sec;
4531 loc = plt_sec->contents + dyn_i->plt_offset;
4533 memcpy (loc, plt_min_entry, PLT_MIN_ENTRY_SIZE);
4534 elfNN_ia64_install_value (output_bfd, loc, index, R_IA64_IMM22);
4535 elfNN_ia64_install_value (output_bfd, loc+2, -dyn_i->plt_offset,
4536 R_IA64_PCREL21B);
4538 plt_addr = (plt_sec->output_section->vma
4539 + plt_sec->output_offset
4540 + dyn_i->plt_offset);
4541 pltoff_addr = set_pltoff_entry (output_bfd, info, dyn_i, plt_addr, TRUE);
4543 /* Initialize the FULL PLT entry, if needed. */
4544 if (dyn_i->want_plt2)
4546 loc = plt_sec->contents + dyn_i->plt2_offset;
4548 memcpy (loc, plt_full_entry, PLT_FULL_ENTRY_SIZE);
4549 elfNN_ia64_install_value (output_bfd, loc, pltoff_addr - gp_val,
4550 R_IA64_IMM22);
4552 /* Mark the symbol as undefined, rather than as defined in the
4553 plt section. Leave the value alone. */
4554 /* ??? We didn't redefine it in adjust_dynamic_symbol in the
4555 first place. But perhaps elflink.h did some for us. */
4556 if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
4557 sym->st_shndx = SHN_UNDEF;
4560 /* Create the dynamic relocation. */
4561 outrel.r_offset = pltoff_addr;
4562 if (bfd_little_endian (output_bfd))
4563 outrel.r_info = ELFNN_R_INFO (h->dynindx, R_IA64_IPLTLSB);
4564 else
4565 outrel.r_info = ELFNN_R_INFO (h->dynindx, R_IA64_IPLTMSB);
4566 outrel.r_addend = 0;
4568 /* This is fun. In the .IA_64.pltoff section, we've got entries
4569 that correspond both to real PLT entries, and those that
4570 happened to resolve to local symbols but need to be created
4571 to satisfy @pltoff relocations. The .rela.IA_64.pltoff
4572 relocations for the real PLT should come at the end of the
4573 section, so that they can be indexed by plt entry at runtime.
4575 We emitted all of the relocations for the non-PLT @pltoff
4576 entries during relocate_section. So we can consider the
4577 existing sec->reloc_count to be the base of the array of
4578 PLT relocations. */
4580 loc = ia64_info->rel_pltoff_sec->contents;
4581 loc += ((ia64_info->rel_pltoff_sec->reloc_count + index)
4582 * sizeof (Elf64_External_Rela));
4583 bfd_elfNN_swap_reloca_out (output_bfd, &outrel, loc);
4586 /* Mark some specially defined symbols as absolute. */
4587 if (strcmp (h->root.root.string, "_DYNAMIC") == 0
4588 || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0
4589 || strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0)
4590 sym->st_shndx = SHN_ABS;
4592 return TRUE;
4595 static bfd_boolean
4596 elfNN_ia64_finish_dynamic_sections (abfd, info)
4597 bfd *abfd;
4598 struct bfd_link_info *info;
4600 struct elfNN_ia64_link_hash_table *ia64_info;
4601 bfd *dynobj;
4603 ia64_info = elfNN_ia64_hash_table (info);
4604 dynobj = ia64_info->root.dynobj;
4606 if (elf_hash_table (info)->dynamic_sections_created)
4608 ElfNN_External_Dyn *dyncon, *dynconend;
4609 asection *sdyn, *sgotplt;
4610 bfd_vma gp_val;
4612 sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
4613 sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
4614 BFD_ASSERT (sdyn != NULL);
4615 dyncon = (ElfNN_External_Dyn *) sdyn->contents;
4616 dynconend = (ElfNN_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
4618 gp_val = _bfd_get_gp_value (abfd);
4620 for (; dyncon < dynconend; dyncon++)
4622 Elf_Internal_Dyn dyn;
4624 bfd_elfNN_swap_dyn_in (dynobj, dyncon, &dyn);
4626 switch (dyn.d_tag)
4628 case DT_PLTGOT:
4629 dyn.d_un.d_ptr = gp_val;
4630 break;
4632 case DT_PLTRELSZ:
4633 dyn.d_un.d_val = (ia64_info->minplt_entries
4634 * sizeof (ElfNN_External_Rela));
4635 break;
4637 case DT_JMPREL:
4638 /* See the comment above in finish_dynamic_symbol. */
4639 dyn.d_un.d_ptr = (ia64_info->rel_pltoff_sec->output_section->vma
4640 + ia64_info->rel_pltoff_sec->output_offset
4641 + (ia64_info->rel_pltoff_sec->reloc_count
4642 * sizeof (ElfNN_External_Rela)));
4643 break;
4645 case DT_IA_64_PLT_RESERVE:
4646 dyn.d_un.d_ptr = (sgotplt->output_section->vma
4647 + sgotplt->output_offset);
4648 break;
4650 case DT_RELASZ:
4651 /* Do not have RELASZ include JMPREL. This makes things
4652 easier on ld.so. This is not what the rest of BFD set up. */
4653 dyn.d_un.d_val -= (ia64_info->minplt_entries
4654 * sizeof (ElfNN_External_Rela));
4655 break;
4658 bfd_elfNN_swap_dyn_out (abfd, &dyn, dyncon);
4661 /* Initialize the PLT0 entry. */
4662 if (ia64_info->plt_sec)
4664 bfd_byte *loc = ia64_info->plt_sec->contents;
4665 bfd_vma pltres;
4667 memcpy (loc, plt_header, PLT_HEADER_SIZE);
4669 pltres = (sgotplt->output_section->vma
4670 + sgotplt->output_offset
4671 - gp_val);
4673 elfNN_ia64_install_value (abfd, loc+1, pltres, R_IA64_GPREL22);
4677 return TRUE;
4680 /* ELF file flag handling: */
4682 /* Function to keep IA-64 specific file flags. */
4683 static bfd_boolean
4684 elfNN_ia64_set_private_flags (abfd, flags)
4685 bfd *abfd;
4686 flagword flags;
4688 BFD_ASSERT (!elf_flags_init (abfd)
4689 || elf_elfheader (abfd)->e_flags == flags);
4691 elf_elfheader (abfd)->e_flags = flags;
4692 elf_flags_init (abfd) = TRUE;
4693 return TRUE;
4696 /* Merge backend specific data from an object file to the output
4697 object file when linking. */
4698 static bfd_boolean
4699 elfNN_ia64_merge_private_bfd_data (ibfd, obfd)
4700 bfd *ibfd, *obfd;
4702 flagword out_flags;
4703 flagword in_flags;
4704 bfd_boolean ok = TRUE;
4706 /* Don't even pretend to support mixed-format linking. */
4707 if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
4708 || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
4709 return FALSE;
4711 in_flags = elf_elfheader (ibfd)->e_flags;
4712 out_flags = elf_elfheader (obfd)->e_flags;
4714 if (! elf_flags_init (obfd))
4716 elf_flags_init (obfd) = TRUE;
4717 elf_elfheader (obfd)->e_flags = in_flags;
4719 if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
4720 && bfd_get_arch_info (obfd)->the_default)
4722 return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
4723 bfd_get_mach (ibfd));
4726 return TRUE;
4729 /* Check flag compatibility. */
4730 if (in_flags == out_flags)
4731 return TRUE;
4733 /* Output has EF_IA_64_REDUCEDFP set only if all inputs have it set. */
4734 if (!(in_flags & EF_IA_64_REDUCEDFP) && (out_flags & EF_IA_64_REDUCEDFP))
4735 elf_elfheader (obfd)->e_flags &= ~EF_IA_64_REDUCEDFP;
4737 if ((in_flags & EF_IA_64_TRAPNIL) != (out_flags & EF_IA_64_TRAPNIL))
4739 (*_bfd_error_handler)
4740 (_("%s: linking trap-on-NULL-dereference with non-trapping files"),
4741 bfd_archive_filename (ibfd));
4743 bfd_set_error (bfd_error_bad_value);
4744 ok = FALSE;
4746 if ((in_flags & EF_IA_64_BE) != (out_flags & EF_IA_64_BE))
4748 (*_bfd_error_handler)
4749 (_("%s: linking big-endian files with little-endian files"),
4750 bfd_archive_filename (ibfd));
4752 bfd_set_error (bfd_error_bad_value);
4753 ok = FALSE;
4755 if ((in_flags & EF_IA_64_ABI64) != (out_flags & EF_IA_64_ABI64))
4757 (*_bfd_error_handler)
4758 (_("%s: linking 64-bit files with 32-bit files"),
4759 bfd_archive_filename (ibfd));
4761 bfd_set_error (bfd_error_bad_value);
4762 ok = FALSE;
4764 if ((in_flags & EF_IA_64_CONS_GP) != (out_flags & EF_IA_64_CONS_GP))
4766 (*_bfd_error_handler)
4767 (_("%s: linking constant-gp files with non-constant-gp files"),
4768 bfd_archive_filename (ibfd));
4770 bfd_set_error (bfd_error_bad_value);
4771 ok = FALSE;
4773 if ((in_flags & EF_IA_64_NOFUNCDESC_CONS_GP)
4774 != (out_flags & EF_IA_64_NOFUNCDESC_CONS_GP))
4776 (*_bfd_error_handler)
4777 (_("%s: linking auto-pic files with non-auto-pic files"),
4778 bfd_archive_filename (ibfd));
4780 bfd_set_error (bfd_error_bad_value);
4781 ok = FALSE;
4784 return ok;
4787 static bfd_boolean
4788 elfNN_ia64_print_private_bfd_data (abfd, ptr)
4789 bfd *abfd;
4790 PTR ptr;
4792 FILE *file = (FILE *) ptr;
4793 flagword flags = elf_elfheader (abfd)->e_flags;
4795 BFD_ASSERT (abfd != NULL && ptr != NULL);
4797 fprintf (file, "private flags = %s%s%s%s%s%s%s%s\n",
4798 (flags & EF_IA_64_TRAPNIL) ? "TRAPNIL, " : "",
4799 (flags & EF_IA_64_EXT) ? "EXT, " : "",
4800 (flags & EF_IA_64_BE) ? "BE, " : "LE, ",
4801 (flags & EF_IA_64_REDUCEDFP) ? "REDUCEDFP, " : "",
4802 (flags & EF_IA_64_CONS_GP) ? "CONS_GP, " : "",
4803 (flags & EF_IA_64_NOFUNCDESC_CONS_GP) ? "NOFUNCDESC_CONS_GP, " : "",
4804 (flags & EF_IA_64_ABSOLUTE) ? "ABSOLUTE, " : "",
4805 (flags & EF_IA_64_ABI64) ? "ABI64" : "ABI32");
4807 _bfd_elf_print_private_bfd_data (abfd, ptr);
4808 return TRUE;
4811 static enum elf_reloc_type_class
4812 elfNN_ia64_reloc_type_class (rela)
4813 const Elf_Internal_Rela *rela;
4815 switch ((int) ELFNN_R_TYPE (rela->r_info))
4817 case R_IA64_REL32MSB:
4818 case R_IA64_REL32LSB:
4819 case R_IA64_REL64MSB:
4820 case R_IA64_REL64LSB:
4821 return reloc_class_relative;
4822 case R_IA64_IPLTMSB:
4823 case R_IA64_IPLTLSB:
4824 return reloc_class_plt;
4825 case R_IA64_COPY:
4826 return reloc_class_copy;
4827 default:
4828 return reloc_class_normal;
4832 static bfd_boolean
4833 elfNN_ia64_hpux_vec (const bfd_target *vec)
4835 extern const bfd_target bfd_elfNN_ia64_hpux_big_vec;
4836 return (vec == & bfd_elfNN_ia64_hpux_big_vec);
4839 static void
4840 elfNN_hpux_post_process_headers (abfd, info)
4841 bfd *abfd;
4842 struct bfd_link_info *info ATTRIBUTE_UNUSED;
4844 Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd);
4846 i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_HPUX;
4847 i_ehdrp->e_ident[EI_ABIVERSION] = 1;
4850 bfd_boolean
4851 elfNN_hpux_backend_section_from_bfd_section (abfd, sec, retval)
4852 bfd *abfd ATTRIBUTE_UNUSED;
4853 asection *sec;
4854 int *retval;
4856 if (bfd_is_com_section (sec))
4858 *retval = SHN_IA_64_ANSI_COMMON;
4859 return TRUE;
4861 return FALSE;
4864 #define TARGET_LITTLE_SYM bfd_elfNN_ia64_little_vec
4865 #define TARGET_LITTLE_NAME "elfNN-ia64-little"
4866 #define TARGET_BIG_SYM bfd_elfNN_ia64_big_vec
4867 #define TARGET_BIG_NAME "elfNN-ia64-big"
4868 #define ELF_ARCH bfd_arch_ia64
4869 #define ELF_MACHINE_CODE EM_IA_64
4870 #define ELF_MACHINE_ALT1 1999 /* EAS2.3 */
4871 #define ELF_MACHINE_ALT2 1998 /* EAS2.2 */
4872 #define ELF_MAXPAGESIZE 0x10000 /* 64KB */
4874 #define elf_backend_section_from_shdr \
4875 elfNN_ia64_section_from_shdr
4876 #define elf_backend_section_flags \
4877 elfNN_ia64_section_flags
4878 #define elf_backend_fake_sections \
4879 elfNN_ia64_fake_sections
4880 #define elf_backend_final_write_processing \
4881 elfNN_ia64_final_write_processing
4882 #define elf_backend_add_symbol_hook \
4883 elfNN_ia64_add_symbol_hook
4884 #define elf_backend_additional_program_headers \
4885 elfNN_ia64_additional_program_headers
4886 #define elf_backend_modify_segment_map \
4887 elfNN_ia64_modify_segment_map
4888 #define elf_info_to_howto \
4889 elfNN_ia64_info_to_howto
4891 #define bfd_elfNN_bfd_reloc_type_lookup \
4892 elfNN_ia64_reloc_type_lookup
4893 #define bfd_elfNN_bfd_is_local_label_name \
4894 elfNN_ia64_is_local_label_name
4895 #define bfd_elfNN_bfd_relax_section \
4896 elfNN_ia64_relax_section
4898 /* Stuff for the BFD linker: */
4899 #define bfd_elfNN_bfd_link_hash_table_create \
4900 elfNN_ia64_hash_table_create
4901 #define elf_backend_create_dynamic_sections \
4902 elfNN_ia64_create_dynamic_sections
4903 #define elf_backend_check_relocs \
4904 elfNN_ia64_check_relocs
4905 #define elf_backend_adjust_dynamic_symbol \
4906 elfNN_ia64_adjust_dynamic_symbol
4907 #define elf_backend_size_dynamic_sections \
4908 elfNN_ia64_size_dynamic_sections
4909 #define elf_backend_relocate_section \
4910 elfNN_ia64_relocate_section
4911 #define elf_backend_finish_dynamic_symbol \
4912 elfNN_ia64_finish_dynamic_symbol
4913 #define elf_backend_finish_dynamic_sections \
4914 elfNN_ia64_finish_dynamic_sections
4915 #define bfd_elfNN_bfd_final_link \
4916 elfNN_ia64_final_link
4918 #define bfd_elfNN_bfd_merge_private_bfd_data \
4919 elfNN_ia64_merge_private_bfd_data
4920 #define bfd_elfNN_bfd_set_private_flags \
4921 elfNN_ia64_set_private_flags
4922 #define bfd_elfNN_bfd_print_private_bfd_data \
4923 elfNN_ia64_print_private_bfd_data
4925 #define elf_backend_plt_readonly 1
4926 #define elf_backend_want_plt_sym 0
4927 #define elf_backend_plt_alignment 5
4928 #define elf_backend_got_header_size 0
4929 #define elf_backend_plt_header_size PLT_HEADER_SIZE
4930 #define elf_backend_want_got_plt 1
4931 #define elf_backend_may_use_rel_p 1
4932 #define elf_backend_may_use_rela_p 1
4933 #define elf_backend_default_use_rela_p 1
4934 #define elf_backend_want_dynbss 0
4935 #define elf_backend_copy_indirect_symbol elfNN_ia64_hash_copy_indirect
4936 #define elf_backend_hide_symbol elfNN_ia64_hash_hide_symbol
4937 #define elf_backend_reloc_type_class elfNN_ia64_reloc_type_class
4938 #define elf_backend_rela_normal 1
4940 #include "elfNN-target.h"
4942 /* AIX-specific vectors. */
4944 #undef TARGET_LITTLE_SYM
4945 #define TARGET_LITTLE_SYM bfd_elfNN_ia64_aix_little_vec
4946 #undef TARGET_LITTLE_NAME
4947 #define TARGET_LITTLE_NAME "elfNN-ia64-aix-little"
4948 #undef TARGET_BIG_SYM
4949 #define TARGET_BIG_SYM bfd_elfNN_ia64_aix_big_vec
4950 #undef TARGET_BIG_NAME
4951 #define TARGET_BIG_NAME "elfNN-ia64-aix-big"
4953 #undef elf_backend_add_symbol_hook
4954 #define elf_backend_add_symbol_hook elfNN_ia64_aix_add_symbol_hook
4956 #undef bfd_elfNN_bfd_link_add_symbols
4957 #define bfd_elfNN_bfd_link_add_symbols elfNN_ia64_aix_link_add_symbols
4959 #define elfNN_bed elfNN_ia64_aix_bed
4961 #include "elfNN-target.h"
4963 /* HPUX-specific vectors. */
4965 #undef TARGET_LITTLE_SYM
4966 #undef TARGET_LITTLE_NAME
4967 #undef TARGET_BIG_SYM
4968 #define TARGET_BIG_SYM bfd_elfNN_ia64_hpux_big_vec
4969 #undef TARGET_BIG_NAME
4970 #define TARGET_BIG_NAME "elfNN-ia64-hpux-big"
4972 /* We need to undo the AIX specific functions. */
4974 #undef elf_backend_add_symbol_hook
4975 #define elf_backend_add_symbol_hook elfNN_ia64_add_symbol_hook
4977 #undef bfd_elfNN_bfd_link_add_symbols
4978 #define bfd_elfNN_bfd_link_add_symbols _bfd_generic_link_add_symbols
4980 /* These are HP-UX specific functions. */
4982 #undef elf_backend_post_process_headers
4983 #define elf_backend_post_process_headers elfNN_hpux_post_process_headers
4985 #undef elf_backend_section_from_bfd_section
4986 #define elf_backend_section_from_bfd_section elfNN_hpux_backend_section_from_bfd_section
4988 #undef elf_backend_want_p_paddr_set_to_zero
4989 #define elf_backend_want_p_paddr_set_to_zero 1
4991 #undef ELF_MAXPAGESIZE
4992 #define ELF_MAXPAGESIZE 0x1000 /* 1K */
4994 #undef elfNN_bed
4995 #define elfNN_bed elfNN_ia64_hpux_bed
4997 #include "elfNN-target.h"
4999 #undef elf_backend_want_p_paddr_set_to_zero