00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "bfd.h"
00027 #include "sysdep.h"
00028 #include "libbfd.h"
00029 #include "elf-bfd.h"
00030 #include "opcode/ia64.h"
00031 #include "elf/ia64.h"
00032 #include "objalloc.h"
00033 #include "hashtab.h"
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 #define NELEMS(a) ((int) (sizeof (a) / sizeof ((a)[0])))
00064
00065 typedef struct bfd_hash_entry *(*new_hash_entry_func)
00066 PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
00067
00068
00069
00070
00071
00072 struct elfNN_ia64_dyn_sym_info
00073 {
00074
00075 bfd_vma addend;
00076
00077
00078 struct elfNN_ia64_dyn_sym_info *next;
00079
00080 bfd_vma got_offset;
00081 bfd_vma fptr_offset;
00082 bfd_vma pltoff_offset;
00083 bfd_vma plt_offset;
00084 bfd_vma plt2_offset;
00085 bfd_vma tprel_offset;
00086 bfd_vma dtpmod_offset;
00087 bfd_vma dtprel_offset;
00088
00089
00090 struct elf_link_hash_entry *h;
00091
00092
00093
00094 struct elfNN_ia64_dyn_reloc_entry
00095 {
00096 struct elfNN_ia64_dyn_reloc_entry *next;
00097 asection *srel;
00098 int type;
00099 int count;
00100
00101
00102 bfd_boolean reltext;
00103 } *reloc_entries;
00104
00105
00106 unsigned got_done : 1;
00107 unsigned fptr_done : 1;
00108 unsigned pltoff_done : 1;
00109 unsigned tprel_done : 1;
00110 unsigned dtpmod_done : 1;
00111 unsigned dtprel_done : 1;
00112
00113
00114 unsigned want_got : 1;
00115 unsigned want_gotx : 1;
00116 unsigned want_fptr : 1;
00117 unsigned want_ltoff_fptr : 1;
00118 unsigned want_plt : 1;
00119 unsigned want_plt2 : 1;
00120 unsigned want_pltoff : 1;
00121 unsigned want_tprel : 1;
00122 unsigned want_dtpmod : 1;
00123 unsigned want_dtprel : 1;
00124 };
00125
00126 struct elfNN_ia64_local_hash_entry
00127 {
00128 int id;
00129 unsigned int r_sym;
00130 struct elfNN_ia64_dyn_sym_info *info;
00131
00132
00133
00134 unsigned sec_merge_done : 1;
00135 };
00136
00137 struct elfNN_ia64_link_hash_entry
00138 {
00139 struct elf_link_hash_entry root;
00140 struct elfNN_ia64_dyn_sym_info *info;
00141 };
00142
00143 struct elfNN_ia64_link_hash_table
00144 {
00145
00146 struct elf_link_hash_table root;
00147
00148 asection *got_sec;
00149 asection *rel_got_sec;
00150 asection *fptr_sec;
00151 asection *rel_fptr_sec;
00152 asection *plt_sec;
00153 asection *pltoff_sec;
00154 asection *rel_pltoff_sec;
00155
00156 bfd_size_type minplt_entries;
00157 unsigned reltext : 1;
00158 unsigned self_dtpmod_done : 1;
00159 bfd_vma self_dtpmod_offset;
00160
00161 htab_t loc_hash_table;
00162 void *loc_hash_memory;
00163 };
00164
00165 struct elfNN_ia64_allocate_data
00166 {
00167 struct bfd_link_info *info;
00168 bfd_size_type ofs;
00169 };
00170
00171 #define elfNN_ia64_hash_table(p) \
00172 ((struct elfNN_ia64_link_hash_table *) ((p)->hash))
00173
00174 static bfd_reloc_status_type elfNN_ia64_reloc
00175 PARAMS ((bfd *abfd, arelent *reloc, asymbol *sym, PTR data,
00176 asection *input_section, bfd *output_bfd, char **error_message));
00177 static reloc_howto_type * lookup_howto
00178 PARAMS ((unsigned int rtype));
00179 static reloc_howto_type *elfNN_ia64_reloc_type_lookup
00180 PARAMS ((bfd *abfd, bfd_reloc_code_real_type bfd_code));
00181 static void elfNN_ia64_info_to_howto
00182 PARAMS ((bfd *abfd, arelent *bfd_reloc, Elf_Internal_Rela *elf_reloc));
00183 static bfd_boolean elfNN_ia64_relax_section
00184 PARAMS((bfd *abfd, asection *sec, struct bfd_link_info *link_info,
00185 bfd_boolean *again));
00186 static void elfNN_ia64_relax_ldxmov
00187 PARAMS((bfd_byte *contents, bfd_vma off));
00188 static bfd_boolean is_unwind_section_name
00189 PARAMS ((bfd *abfd, const char *));
00190 static bfd_boolean elfNN_ia64_section_from_shdr
00191 PARAMS ((bfd *, Elf_Internal_Shdr *, const char *));
00192 static bfd_boolean elfNN_ia64_section_flags
00193 PARAMS ((flagword *, const Elf_Internal_Shdr *));
00194 static bfd_boolean elfNN_ia64_fake_sections
00195 PARAMS ((bfd *abfd, Elf_Internal_Shdr *hdr, asection *sec));
00196 static void elfNN_ia64_final_write_processing
00197 PARAMS ((bfd *abfd, bfd_boolean linker));
00198 static bfd_boolean elfNN_ia64_add_symbol_hook
00199 PARAMS ((bfd *abfd, struct bfd_link_info *info, Elf_Internal_Sym *sym,
00200 const char **namep, flagword *flagsp, asection **secp,
00201 bfd_vma *valp));
00202 static int elfNN_ia64_additional_program_headers
00203 PARAMS ((bfd *abfd));
00204 static bfd_boolean elfNN_ia64_modify_segment_map
00205 PARAMS ((bfd *, struct bfd_link_info *));
00206 static bfd_boolean elfNN_ia64_is_local_label_name
00207 PARAMS ((bfd *abfd, const char *name));
00208 static bfd_boolean elfNN_ia64_dynamic_symbol_p
00209 PARAMS ((struct elf_link_hash_entry *h, struct bfd_link_info *info, int));
00210 static struct bfd_hash_entry *elfNN_ia64_new_elf_hash_entry
00211 PARAMS ((struct bfd_hash_entry *entry, struct bfd_hash_table *table,
00212 const char *string));
00213 static void elfNN_ia64_hash_copy_indirect
00214 PARAMS ((const struct elf_backend_data *, struct elf_link_hash_entry *,
00215 struct elf_link_hash_entry *));
00216 static void elfNN_ia64_hash_hide_symbol
00217 PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *, bfd_boolean));
00218 static hashval_t elfNN_ia64_local_htab_hash PARAMS ((const void *));
00219 static int elfNN_ia64_local_htab_eq PARAMS ((const void *ptr1,
00220 const void *ptr2));
00221 static struct bfd_link_hash_table *elfNN_ia64_hash_table_create
00222 PARAMS ((bfd *abfd));
00223 static void elfNN_ia64_hash_table_free
00224 PARAMS ((struct bfd_link_hash_table *hash));
00225 static bfd_boolean elfNN_ia64_global_dyn_sym_thunk
00226 PARAMS ((struct bfd_hash_entry *, PTR));
00227 static int elfNN_ia64_local_dyn_sym_thunk
00228 PARAMS ((void **, PTR));
00229 static void elfNN_ia64_dyn_sym_traverse
00230 PARAMS ((struct elfNN_ia64_link_hash_table *ia64_info,
00231 bfd_boolean (*func) (struct elfNN_ia64_dyn_sym_info *, PTR),
00232 PTR info));
00233 static bfd_boolean elfNN_ia64_create_dynamic_sections
00234 PARAMS ((bfd *abfd, struct bfd_link_info *info));
00235 static struct elfNN_ia64_local_hash_entry * get_local_sym_hash
00236 PARAMS ((struct elfNN_ia64_link_hash_table *ia64_info,
00237 bfd *abfd, const Elf_Internal_Rela *rel, bfd_boolean create));
00238 static struct elfNN_ia64_dyn_sym_info * get_dyn_sym_info
00239 PARAMS ((struct elfNN_ia64_link_hash_table *ia64_info,
00240 struct elf_link_hash_entry *h,
00241 bfd *abfd, const Elf_Internal_Rela *rel, bfd_boolean create));
00242 static asection *get_got
00243 PARAMS ((bfd *abfd, struct bfd_link_info *info,
00244 struct elfNN_ia64_link_hash_table *ia64_info));
00245 static asection *get_fptr
00246 PARAMS ((bfd *abfd, struct bfd_link_info *info,
00247 struct elfNN_ia64_link_hash_table *ia64_info));
00248 static asection *get_pltoff
00249 PARAMS ((bfd *abfd, struct bfd_link_info *info,
00250 struct elfNN_ia64_link_hash_table *ia64_info));
00251 static asection *get_reloc_section
00252 PARAMS ((bfd *abfd, struct elfNN_ia64_link_hash_table *ia64_info,
00253 asection *sec, bfd_boolean create));
00254 static bfd_boolean elfNN_ia64_check_relocs
00255 PARAMS ((bfd *abfd, struct bfd_link_info *info, asection *sec,
00256 const Elf_Internal_Rela *relocs));
00257 static bfd_boolean elfNN_ia64_adjust_dynamic_symbol
00258 PARAMS ((struct bfd_link_info *info, struct elf_link_hash_entry *h));
00259 static long global_sym_index
00260 PARAMS ((struct elf_link_hash_entry *h));
00261 static bfd_boolean allocate_fptr
00262 PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
00263 static bfd_boolean allocate_global_data_got
00264 PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
00265 static bfd_boolean allocate_global_fptr_got
00266 PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
00267 static bfd_boolean allocate_local_got
00268 PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
00269 static bfd_boolean allocate_pltoff_entries
00270 PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
00271 static bfd_boolean allocate_plt_entries
00272 PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
00273 static bfd_boolean allocate_plt2_entries
00274 PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
00275 static bfd_boolean allocate_dynrel_entries
00276 PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
00277 static bfd_boolean elfNN_ia64_size_dynamic_sections
00278 PARAMS ((bfd *output_bfd, struct bfd_link_info *info));
00279 static bfd_reloc_status_type elfNN_ia64_install_value
00280 PARAMS ((bfd_byte *hit_addr, bfd_vma val, unsigned int r_type));
00281 static void elfNN_ia64_install_dyn_reloc
00282 PARAMS ((bfd *abfd, struct bfd_link_info *info, asection *sec,
00283 asection *srel, bfd_vma offset, unsigned int type,
00284 long dynindx, bfd_vma addend));
00285 static bfd_vma set_got_entry
00286 PARAMS ((bfd *abfd, struct bfd_link_info *info,
00287 struct elfNN_ia64_dyn_sym_info *dyn_i, long dynindx,
00288 bfd_vma addend, bfd_vma value, unsigned int dyn_r_type));
00289 static bfd_vma set_fptr_entry
00290 PARAMS ((bfd *abfd, struct bfd_link_info *info,
00291 struct elfNN_ia64_dyn_sym_info *dyn_i,
00292 bfd_vma value));
00293 static bfd_vma set_pltoff_entry
00294 PARAMS ((bfd *abfd, struct bfd_link_info *info,
00295 struct elfNN_ia64_dyn_sym_info *dyn_i,
00296 bfd_vma value, bfd_boolean));
00297 static bfd_vma elfNN_ia64_tprel_base
00298 PARAMS ((struct bfd_link_info *info));
00299 static bfd_vma elfNN_ia64_dtprel_base
00300 PARAMS ((struct bfd_link_info *info));
00301 static int elfNN_ia64_unwind_entry_compare
00302 PARAMS ((const PTR, const PTR));
00303 static bfd_boolean elfNN_ia64_choose_gp
00304 PARAMS ((bfd *abfd, struct bfd_link_info *info));
00305 static bfd_boolean elfNN_ia64_final_link
00306 PARAMS ((bfd *abfd, struct bfd_link_info *info));
00307 static bfd_boolean elfNN_ia64_relocate_section
00308 PARAMS ((bfd *output_bfd, struct bfd_link_info *info, bfd *input_bfd,
00309 asection *input_section, bfd_byte *contents,
00310 Elf_Internal_Rela *relocs, Elf_Internal_Sym *local_syms,
00311 asection **local_sections));
00312 static bfd_boolean elfNN_ia64_finish_dynamic_symbol
00313 PARAMS ((bfd *output_bfd, struct bfd_link_info *info,
00314 struct elf_link_hash_entry *h, Elf_Internal_Sym *sym));
00315 static bfd_boolean elfNN_ia64_finish_dynamic_sections
00316 PARAMS ((bfd *abfd, struct bfd_link_info *info));
00317 static bfd_boolean elfNN_ia64_set_private_flags
00318 PARAMS ((bfd *abfd, flagword flags));
00319 static bfd_boolean elfNN_ia64_merge_private_bfd_data
00320 PARAMS ((bfd *ibfd, bfd *obfd));
00321 static bfd_boolean elfNN_ia64_print_private_bfd_data
00322 PARAMS ((bfd *abfd, PTR ptr));
00323 static enum elf_reloc_type_class elfNN_ia64_reloc_type_class
00324 PARAMS ((const Elf_Internal_Rela *));
00325 static bfd_boolean elfNN_ia64_hpux_vec
00326 PARAMS ((const bfd_target *vec));
00327 static void elfNN_hpux_post_process_headers
00328 PARAMS ((bfd *abfd, struct bfd_link_info *info));
00329 bfd_boolean elfNN_hpux_backend_section_from_bfd_section
00330 PARAMS ((bfd *abfd, asection *sec, int *retval));
00331
00332
00333
00334
00335
00336 static bfd_reloc_status_type
00337 elfNN_ia64_reloc (abfd, reloc, sym, data, input_section,
00338 output_bfd, error_message)
00339 bfd *abfd ATTRIBUTE_UNUSED;
00340 arelent *reloc;
00341 asymbol *sym ATTRIBUTE_UNUSED;
00342 PTR data ATTRIBUTE_UNUSED;
00343 asection *input_section;
00344 bfd *output_bfd;
00345 char **error_message;
00346 {
00347 if (output_bfd)
00348 {
00349 reloc->address += input_section->output_offset;
00350 return bfd_reloc_ok;
00351 }
00352
00353 if (input_section->flags & SEC_DEBUGGING)
00354 return bfd_reloc_continue;
00355
00356 *error_message = "Unsupported call to elfNN_ia64_reloc";
00357 return bfd_reloc_notsupported;
00358 }
00359
00360 #define IA64_HOWTO(TYPE, NAME, SIZE, PCREL, IN) \
00361 HOWTO (TYPE, 0, SIZE, 0, PCREL, 0, complain_overflow_signed, \
00362 elfNN_ia64_reloc, NAME, FALSE, 0, -1, IN)
00363
00364
00365
00366 static reloc_howto_type ia64_howto_table[] =
00367 {
00368 IA64_HOWTO (R_IA64_NONE, "NONE", 0, FALSE, TRUE),
00369
00370 IA64_HOWTO (R_IA64_IMM14, "IMM14", 0, FALSE, TRUE),
00371 IA64_HOWTO (R_IA64_IMM22, "IMM22", 0, FALSE, TRUE),
00372 IA64_HOWTO (R_IA64_IMM64, "IMM64", 0, FALSE, TRUE),
00373 IA64_HOWTO (R_IA64_DIR32MSB, "DIR32MSB", 2, FALSE, TRUE),
00374 IA64_HOWTO (R_IA64_DIR32LSB, "DIR32LSB", 2, FALSE, TRUE),
00375 IA64_HOWTO (R_IA64_DIR64MSB, "DIR64MSB", 4, FALSE, TRUE),
00376 IA64_HOWTO (R_IA64_DIR64LSB, "DIR64LSB", 4, FALSE, TRUE),
00377
00378 IA64_HOWTO (R_IA64_GPREL22, "GPREL22", 0, FALSE, TRUE),
00379 IA64_HOWTO (R_IA64_GPREL64I, "GPREL64I", 0, FALSE, TRUE),
00380 IA64_HOWTO (R_IA64_GPREL32MSB, "GPREL32MSB", 2, FALSE, TRUE),
00381 IA64_HOWTO (R_IA64_GPREL32LSB, "GPREL32LSB", 2, FALSE, TRUE),
00382 IA64_HOWTO (R_IA64_GPREL64MSB, "GPREL64MSB", 4, FALSE, TRUE),
00383 IA64_HOWTO (R_IA64_GPREL64LSB, "GPREL64LSB", 4, FALSE, TRUE),
00384
00385 IA64_HOWTO (R_IA64_LTOFF22, "LTOFF22", 0, FALSE, TRUE),
00386 IA64_HOWTO (R_IA64_LTOFF64I, "LTOFF64I", 0, FALSE, TRUE),
00387
00388 IA64_HOWTO (R_IA64_PLTOFF22, "PLTOFF22", 0, FALSE, TRUE),
00389 IA64_HOWTO (R_IA64_PLTOFF64I, "PLTOFF64I", 0, FALSE, TRUE),
00390 IA64_HOWTO (R_IA64_PLTOFF64MSB, "PLTOFF64MSB", 4, FALSE, TRUE),
00391 IA64_HOWTO (R_IA64_PLTOFF64LSB, "PLTOFF64LSB", 4, FALSE, TRUE),
00392
00393 IA64_HOWTO (R_IA64_FPTR64I, "FPTR64I", 0, FALSE, TRUE),
00394 IA64_HOWTO (R_IA64_FPTR32MSB, "FPTR32MSB", 2, FALSE, TRUE),
00395 IA64_HOWTO (R_IA64_FPTR32LSB, "FPTR32LSB", 2, FALSE, TRUE),
00396 IA64_HOWTO (R_IA64_FPTR64MSB, "FPTR64MSB", 4, FALSE, TRUE),
00397 IA64_HOWTO (R_IA64_FPTR64LSB, "FPTR64LSB", 4, FALSE, TRUE),
00398
00399 IA64_HOWTO (R_IA64_PCREL60B, "PCREL60B", 0, TRUE, TRUE),
00400 IA64_HOWTO (R_IA64_PCREL21B, "PCREL21B", 0, TRUE, TRUE),
00401 IA64_HOWTO (R_IA64_PCREL21M, "PCREL21M", 0, TRUE, TRUE),
00402 IA64_HOWTO (R_IA64_PCREL21F, "PCREL21F", 0, TRUE, TRUE),
00403 IA64_HOWTO (R_IA64_PCREL32MSB, "PCREL32MSB", 2, TRUE, TRUE),
00404 IA64_HOWTO (R_IA64_PCREL32LSB, "PCREL32LSB", 2, TRUE, TRUE),
00405 IA64_HOWTO (R_IA64_PCREL64MSB, "PCREL64MSB", 4, TRUE, TRUE),
00406 IA64_HOWTO (R_IA64_PCREL64LSB, "PCREL64LSB", 4, TRUE, TRUE),
00407
00408 IA64_HOWTO (R_IA64_LTOFF_FPTR22, "LTOFF_FPTR22", 0, FALSE, TRUE),
00409 IA64_HOWTO (R_IA64_LTOFF_FPTR64I, "LTOFF_FPTR64I", 0, FALSE, TRUE),
00410 IA64_HOWTO (R_IA64_LTOFF_FPTR32MSB, "LTOFF_FPTR32MSB", 2, FALSE, TRUE),
00411 IA64_HOWTO (R_IA64_LTOFF_FPTR32LSB, "LTOFF_FPTR32LSB", 2, FALSE, TRUE),
00412 IA64_HOWTO (R_IA64_LTOFF_FPTR64MSB, "LTOFF_FPTR64MSB", 4, FALSE, TRUE),
00413 IA64_HOWTO (R_IA64_LTOFF_FPTR64LSB, "LTOFF_FPTR64LSB", 4, FALSE, TRUE),
00414
00415 IA64_HOWTO (R_IA64_SEGREL32MSB, "SEGREL32MSB", 2, FALSE, TRUE),
00416 IA64_HOWTO (R_IA64_SEGREL32LSB, "SEGREL32LSB", 2, FALSE, TRUE),
00417 IA64_HOWTO (R_IA64_SEGREL64MSB, "SEGREL64MSB", 4, FALSE, TRUE),
00418 IA64_HOWTO (R_IA64_SEGREL64LSB, "SEGREL64LSB", 4, FALSE, TRUE),
00419
00420 IA64_HOWTO (R_IA64_SECREL32MSB, "SECREL32MSB", 2, FALSE, TRUE),
00421 IA64_HOWTO (R_IA64_SECREL32LSB, "SECREL32LSB", 2, FALSE, TRUE),
00422 IA64_HOWTO (R_IA64_SECREL64MSB, "SECREL64MSB", 4, FALSE, TRUE),
00423 IA64_HOWTO (R_IA64_SECREL64LSB, "SECREL64LSB", 4, FALSE, TRUE),
00424
00425 IA64_HOWTO (R_IA64_REL32MSB, "REL32MSB", 2, FALSE, TRUE),
00426 IA64_HOWTO (R_IA64_REL32LSB, "REL32LSB", 2, FALSE, TRUE),
00427 IA64_HOWTO (R_IA64_REL64MSB, "REL64MSB", 4, FALSE, TRUE),
00428 IA64_HOWTO (R_IA64_REL64LSB, "REL64LSB", 4, FALSE, TRUE),
00429
00430 IA64_HOWTO (R_IA64_LTV32MSB, "LTV32MSB", 2, FALSE, TRUE),
00431 IA64_HOWTO (R_IA64_LTV32LSB, "LTV32LSB", 2, FALSE, TRUE),
00432 IA64_HOWTO (R_IA64_LTV64MSB, "LTV64MSB", 4, FALSE, TRUE),
00433 IA64_HOWTO (R_IA64_LTV64LSB, "LTV64LSB", 4, FALSE, TRUE),
00434
00435 IA64_HOWTO (R_IA64_PCREL21BI, "PCREL21BI", 0, TRUE, TRUE),
00436 IA64_HOWTO (R_IA64_PCREL22, "PCREL22", 0, TRUE, TRUE),
00437 IA64_HOWTO (R_IA64_PCREL64I, "PCREL64I", 0, TRUE, TRUE),
00438
00439 IA64_HOWTO (R_IA64_IPLTMSB, "IPLTMSB", 4, FALSE, TRUE),
00440 IA64_HOWTO (R_IA64_IPLTLSB, "IPLTLSB", 4, FALSE, TRUE),
00441 IA64_HOWTO (R_IA64_COPY, "COPY", 4, FALSE, TRUE),
00442 IA64_HOWTO (R_IA64_LTOFF22X, "LTOFF22X", 0, FALSE, TRUE),
00443 IA64_HOWTO (R_IA64_LDXMOV, "LDXMOV", 0, FALSE, TRUE),
00444
00445 IA64_HOWTO (R_IA64_TPREL14, "TPREL14", 0, FALSE, FALSE),
00446 IA64_HOWTO (R_IA64_TPREL22, "TPREL22", 0, FALSE, FALSE),
00447 IA64_HOWTO (R_IA64_TPREL64I, "TPREL64I", 0, FALSE, FALSE),
00448 IA64_HOWTO (R_IA64_TPREL64MSB, "TPREL64MSB", 4, FALSE, FALSE),
00449 IA64_HOWTO (R_IA64_TPREL64LSB, "TPREL64LSB", 4, FALSE, FALSE),
00450 IA64_HOWTO (R_IA64_LTOFF_TPREL22, "LTOFF_TPREL22", 0, FALSE, FALSE),
00451
00452 IA64_HOWTO (R_IA64_DTPMOD64MSB, "DTPMOD64MSB", 4, FALSE, FALSE),
00453 IA64_HOWTO (R_IA64_DTPMOD64LSB, "DTPMOD64LSB", 4, FALSE, FALSE),
00454 IA64_HOWTO (R_IA64_LTOFF_DTPMOD22, "LTOFF_DTPMOD22", 0, FALSE, FALSE),
00455
00456 IA64_HOWTO (R_IA64_DTPREL14, "DTPREL14", 0, FALSE, FALSE),
00457 IA64_HOWTO (R_IA64_DTPREL22, "DTPREL22", 0, FALSE, FALSE),
00458 IA64_HOWTO (R_IA64_DTPREL64I, "DTPREL64I", 0, FALSE, FALSE),
00459 IA64_HOWTO (R_IA64_DTPREL32MSB, "DTPREL32MSB", 2, FALSE, FALSE),
00460 IA64_HOWTO (R_IA64_DTPREL32LSB, "DTPREL32LSB", 2, FALSE, FALSE),
00461 IA64_HOWTO (R_IA64_DTPREL64MSB, "DTPREL64MSB", 4, FALSE, FALSE),
00462 IA64_HOWTO (R_IA64_DTPREL64LSB, "DTPREL64LSB", 4, FALSE, FALSE),
00463 IA64_HOWTO (R_IA64_LTOFF_DTPREL22, "LTOFF_DTPREL22", 0, FALSE, FALSE),
00464 };
00465
00466 static unsigned char elf_code_to_howto_index[R_IA64_MAX_RELOC_CODE + 1];
00467
00468
00469
00470 static reloc_howto_type *
00471 lookup_howto (rtype)
00472 unsigned int rtype;
00473 {
00474 static int inited = 0;
00475 int i;
00476
00477 if (!inited)
00478 {
00479 inited = 1;
00480
00481 memset (elf_code_to_howto_index, 0xff, sizeof (elf_code_to_howto_index));
00482 for (i = 0; i < NELEMS (ia64_howto_table); ++i)
00483 elf_code_to_howto_index[ia64_howto_table[i].type] = i;
00484 }
00485
00486 BFD_ASSERT (rtype <= R_IA64_MAX_RELOC_CODE);
00487 i = elf_code_to_howto_index[rtype];
00488 if (i >= NELEMS (ia64_howto_table))
00489 return 0;
00490 return ia64_howto_table + i;
00491 }
00492
00493 static reloc_howto_type*
00494 elfNN_ia64_reloc_type_lookup (abfd, bfd_code)
00495 bfd *abfd ATTRIBUTE_UNUSED;
00496 bfd_reloc_code_real_type bfd_code;
00497 {
00498 unsigned int rtype;
00499
00500 switch (bfd_code)
00501 {
00502 case BFD_RELOC_NONE: rtype = R_IA64_NONE; break;
00503
00504 case BFD_RELOC_IA64_IMM14: rtype = R_IA64_IMM14; break;
00505 case BFD_RELOC_IA64_IMM22: rtype = R_IA64_IMM22; break;
00506 case BFD_RELOC_IA64_IMM64: rtype = R_IA64_IMM64; break;
00507
00508 case BFD_RELOC_IA64_DIR32MSB: rtype = R_IA64_DIR32MSB; break;
00509 case BFD_RELOC_IA64_DIR32LSB: rtype = R_IA64_DIR32LSB; break;
00510 case BFD_RELOC_IA64_DIR64MSB: rtype = R_IA64_DIR64MSB; break;
00511 case BFD_RELOC_IA64_DIR64LSB: rtype = R_IA64_DIR64LSB; break;
00512
00513 case BFD_RELOC_IA64_GPREL22: rtype = R_IA64_GPREL22; break;
00514 case BFD_RELOC_IA64_GPREL64I: rtype = R_IA64_GPREL64I; break;
00515 case BFD_RELOC_IA64_GPREL32MSB: rtype = R_IA64_GPREL32MSB; break;
00516 case BFD_RELOC_IA64_GPREL32LSB: rtype = R_IA64_GPREL32LSB; break;
00517 case BFD_RELOC_IA64_GPREL64MSB: rtype = R_IA64_GPREL64MSB; break;
00518 case BFD_RELOC_IA64_GPREL64LSB: rtype = R_IA64_GPREL64LSB; break;
00519
00520 case BFD_RELOC_IA64_LTOFF22: rtype = R_IA64_LTOFF22; break;
00521 case BFD_RELOC_IA64_LTOFF64I: rtype = R_IA64_LTOFF64I; break;
00522
00523 case BFD_RELOC_IA64_PLTOFF22: rtype = R_IA64_PLTOFF22; break;
00524 case BFD_RELOC_IA64_PLTOFF64I: rtype = R_IA64_PLTOFF64I; break;
00525 case BFD_RELOC_IA64_PLTOFF64MSB: rtype = R_IA64_PLTOFF64MSB; break;
00526 case BFD_RELOC_IA64_PLTOFF64LSB: rtype = R_IA64_PLTOFF64LSB; break;
00527 case BFD_RELOC_IA64_FPTR64I: rtype = R_IA64_FPTR64I; break;
00528 case BFD_RELOC_IA64_FPTR32MSB: rtype = R_IA64_FPTR32MSB; break;
00529 case BFD_RELOC_IA64_FPTR32LSB: rtype = R_IA64_FPTR32LSB; break;
00530 case BFD_RELOC_IA64_FPTR64MSB: rtype = R_IA64_FPTR64MSB; break;
00531 case BFD_RELOC_IA64_FPTR64LSB: rtype = R_IA64_FPTR64LSB; break;
00532
00533 case BFD_RELOC_IA64_PCREL21B: rtype = R_IA64_PCREL21B; break;
00534 case BFD_RELOC_IA64_PCREL21BI: rtype = R_IA64_PCREL21BI; break;
00535 case BFD_RELOC_IA64_PCREL21M: rtype = R_IA64_PCREL21M; break;
00536 case BFD_RELOC_IA64_PCREL21F: rtype = R_IA64_PCREL21F; break;
00537 case BFD_RELOC_IA64_PCREL22: rtype = R_IA64_PCREL22; break;
00538 case BFD_RELOC_IA64_PCREL60B: rtype = R_IA64_PCREL60B; break;
00539 case BFD_RELOC_IA64_PCREL64I: rtype = R_IA64_PCREL64I; break;
00540 case BFD_RELOC_IA64_PCREL32MSB: rtype = R_IA64_PCREL32MSB; break;
00541 case BFD_RELOC_IA64_PCREL32LSB: rtype = R_IA64_PCREL32LSB; break;
00542 case BFD_RELOC_IA64_PCREL64MSB: rtype = R_IA64_PCREL64MSB; break;
00543 case BFD_RELOC_IA64_PCREL64LSB: rtype = R_IA64_PCREL64LSB; break;
00544
00545 case BFD_RELOC_IA64_LTOFF_FPTR22: rtype = R_IA64_LTOFF_FPTR22; break;
00546 case BFD_RELOC_IA64_LTOFF_FPTR64I: rtype = R_IA64_LTOFF_FPTR64I; break;
00547 case BFD_RELOC_IA64_LTOFF_FPTR32MSB: rtype = R_IA64_LTOFF_FPTR32MSB; break;
00548 case BFD_RELOC_IA64_LTOFF_FPTR32LSB: rtype = R_IA64_LTOFF_FPTR32LSB; break;
00549 case BFD_RELOC_IA64_LTOFF_FPTR64MSB: rtype = R_IA64_LTOFF_FPTR64MSB; break;
00550 case BFD_RELOC_IA64_LTOFF_FPTR64LSB: rtype = R_IA64_LTOFF_FPTR64LSB; break;
00551
00552 case BFD_RELOC_IA64_SEGREL32MSB: rtype = R_IA64_SEGREL32MSB; break;
00553 case BFD_RELOC_IA64_SEGREL32LSB: rtype = R_IA64_SEGREL32LSB; break;
00554 case BFD_RELOC_IA64_SEGREL64MSB: rtype = R_IA64_SEGREL64MSB; break;
00555 case BFD_RELOC_IA64_SEGREL64LSB: rtype = R_IA64_SEGREL64LSB; break;
00556
00557 case BFD_RELOC_IA64_SECREL32MSB: rtype = R_IA64_SECREL32MSB; break;
00558 case BFD_RELOC_IA64_SECREL32LSB: rtype = R_IA64_SECREL32LSB; break;
00559 case BFD_RELOC_IA64_SECREL64MSB: rtype = R_IA64_SECREL64MSB; break;
00560 case BFD_RELOC_IA64_SECREL64LSB: rtype = R_IA64_SECREL64LSB; break;
00561
00562 case BFD_RELOC_IA64_REL32MSB: rtype = R_IA64_REL32MSB; break;
00563 case BFD_RELOC_IA64_REL32LSB: rtype = R_IA64_REL32LSB; break;
00564 case BFD_RELOC_IA64_REL64MSB: rtype = R_IA64_REL64MSB; break;
00565 case BFD_RELOC_IA64_REL64LSB: rtype = R_IA64_REL64LSB; break;
00566
00567 case BFD_RELOC_IA64_LTV32MSB: rtype = R_IA64_LTV32MSB; break;
00568 case BFD_RELOC_IA64_LTV32LSB: rtype = R_IA64_LTV32LSB; break;
00569 case BFD_RELOC_IA64_LTV64MSB: rtype = R_IA64_LTV64MSB; break;
00570 case BFD_RELOC_IA64_LTV64LSB: rtype = R_IA64_LTV64LSB; break;
00571
00572 case BFD_RELOC_IA64_IPLTMSB: rtype = R_IA64_IPLTMSB; break;
00573 case BFD_RELOC_IA64_IPLTLSB: rtype = R_IA64_IPLTLSB; break;
00574 case BFD_RELOC_IA64_COPY: rtype = R_IA64_COPY; break;
00575 case BFD_RELOC_IA64_LTOFF22X: rtype = R_IA64_LTOFF22X; break;
00576 case BFD_RELOC_IA64_LDXMOV: rtype = R_IA64_LDXMOV; break;
00577
00578 case BFD_RELOC_IA64_TPREL14: rtype = R_IA64_TPREL14; break;
00579 case BFD_RELOC_IA64_TPREL22: rtype = R_IA64_TPREL22; break;
00580 case BFD_RELOC_IA64_TPREL64I: rtype = R_IA64_TPREL64I; break;
00581 case BFD_RELOC_IA64_TPREL64MSB: rtype = R_IA64_TPREL64MSB; break;
00582 case BFD_RELOC_IA64_TPREL64LSB: rtype = R_IA64_TPREL64LSB; break;
00583 case BFD_RELOC_IA64_LTOFF_TPREL22: rtype = R_IA64_LTOFF_TPREL22; break;
00584
00585 case BFD_RELOC_IA64_DTPMOD64MSB: rtype = R_IA64_DTPMOD64MSB; break;
00586 case BFD_RELOC_IA64_DTPMOD64LSB: rtype = R_IA64_DTPMOD64LSB; break;
00587 case BFD_RELOC_IA64_LTOFF_DTPMOD22: rtype = R_IA64_LTOFF_DTPMOD22; break;
00588
00589 case BFD_RELOC_IA64_DTPREL14: rtype = R_IA64_DTPREL14; break;
00590 case BFD_RELOC_IA64_DTPREL22: rtype = R_IA64_DTPREL22; break;
00591 case BFD_RELOC_IA64_DTPREL64I: rtype = R_IA64_DTPREL64I; break;
00592 case BFD_RELOC_IA64_DTPREL32MSB: rtype = R_IA64_DTPREL32MSB; break;
00593 case BFD_RELOC_IA64_DTPREL32LSB: rtype = R_IA64_DTPREL32LSB; break;
00594 case BFD_RELOC_IA64_DTPREL64MSB: rtype = R_IA64_DTPREL64MSB; break;
00595 case BFD_RELOC_IA64_DTPREL64LSB: rtype = R_IA64_DTPREL64LSB; break;
00596 case BFD_RELOC_IA64_LTOFF_DTPREL22: rtype = R_IA64_LTOFF_DTPREL22; break;
00597
00598 default: return 0;
00599 }
00600 return lookup_howto (rtype);
00601 }
00602
00603
00604
00605 static void
00606 elfNN_ia64_info_to_howto (abfd, bfd_reloc, elf_reloc)
00607 bfd *abfd ATTRIBUTE_UNUSED;
00608 arelent *bfd_reloc;
00609 Elf_Internal_Rela *elf_reloc;
00610 {
00611 bfd_reloc->howto
00612 = lookup_howto ((unsigned int) ELFNN_R_TYPE (elf_reloc->r_info));
00613 }
00614
00615 #define PLT_HEADER_SIZE (3 * 16)
00616 #define PLT_MIN_ENTRY_SIZE (1 * 16)
00617 #define PLT_FULL_ENTRY_SIZE (2 * 16)
00618 #define PLT_RESERVED_WORDS 3
00619
00620 static const bfd_byte plt_header[PLT_HEADER_SIZE] =
00621 {
00622 0x0b, 0x10, 0x00, 0x1c, 0x00, 0x21,
00623 0xe0, 0x00, 0x08, 0x00, 0x48, 0x00,
00624 0x00, 0x00, 0x04, 0x00,
00625 0x0b, 0x80, 0x20, 0x1c, 0x18, 0x14,
00626 0x10, 0x41, 0x38, 0x30, 0x28, 0x00,
00627 0x00, 0x00, 0x04, 0x00,
00628 0x11, 0x08, 0x00, 0x1c, 0x18, 0x10,
00629 0x60, 0x88, 0x04, 0x80, 0x03, 0x00,
00630 0x60, 0x00, 0x80, 0x00
00631 };
00632
00633 static const bfd_byte plt_min_entry[PLT_MIN_ENTRY_SIZE] =
00634 {
00635 0x11, 0x78, 0x00, 0x00, 0x00, 0x24,
00636 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
00637 0x00, 0x00, 0x00, 0x40
00638 };
00639
00640 static const bfd_byte plt_full_entry[PLT_FULL_ENTRY_SIZE] =
00641 {
00642 0x0b, 0x78, 0x00, 0x02, 0x00, 0x24,
00643 0x00, 0x41, 0x3c, 0x70, 0x29, 0xc0,
00644 0x01, 0x08, 0x00, 0x84,
00645 0x11, 0x08, 0x00, 0x1e, 0x18, 0x10,
00646 0x60, 0x80, 0x04, 0x80, 0x03, 0x00,
00647 0x60, 0x00, 0x80, 0x00
00648 };
00649
00650 #define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"
00651
00652 static const bfd_byte oor_brl[16] =
00653 {
00654 0x05, 0x00, 0x00, 0x00, 0x01, 0x00,
00655 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00656 0x00, 0x00, 0x00, 0xc0
00657 };
00658
00659 static const bfd_byte oor_ip[48] =
00660 {
00661 0x04, 0x00, 0x00, 0x00, 0x01, 0x00,
00662 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
00663 0x01, 0x00, 0x00, 0x60,
00664 0x03, 0x00, 0x00, 0x00, 0x01, 0x00,
00665 0x00, 0x01, 0x00, 0x60, 0x00, 0x00,
00666 0xf2, 0x80, 0x00, 0x80,
00667 0x11, 0x00, 0x00, 0x00, 0x01, 0x00,
00668 0x60, 0x80, 0x04, 0x80, 0x03, 0x00,
00669 0x60, 0x00, 0x80, 0x00
00670 };
00671
00672 static size_t oor_branch_size = sizeof (oor_brl);
00673
00674 void
00675 bfd_elfNN_ia64_after_parse (int itanium)
00676 {
00677 oor_branch_size = itanium ? sizeof (oor_ip) : sizeof (oor_brl);
00678 }
00679
00680 static void
00681 elfNN_ia64_relax_brl (bfd_byte *contents, bfd_vma off)
00682 {
00683 unsigned int template, t0, t1, t2, t3;
00684 bfd_byte *hit_addr;
00685
00686 hit_addr = (bfd_byte *) (contents + off);
00687 hit_addr -= (long) hit_addr & 0x3;
00688 t0 = bfd_getl32 (hit_addr + 0);
00689 t1 = bfd_getl32 (hit_addr + 4);
00690 t2 = bfd_getl32 (hit_addr + 8);
00691 t3 = bfd_getl32 (hit_addr + 12);
00692
00693
00694
00695 template = 0x12;
00696 if ((t0 & 0x1f) == 5)
00697 template += 1;
00698
00699
00700 t0 &= 0xffffffe0;
00701 t1 &= 0x3fff;
00702
00703 t0 |= template;
00704
00705
00706 t2 &= 0xff800000;
00707 t3 &= 0x7fffffff;
00708
00709
00710 t2 |= 0x100000;
00711
00712 bfd_putl32 (t0, hit_addr);
00713 bfd_putl32 (t1, hit_addr + 4);
00714 bfd_putl32 (t2, hit_addr + 8);
00715 bfd_putl32 (t3, hit_addr + 12);
00716 }
00717
00718
00719
00720 static bfd_boolean
00721 elfNN_ia64_relax_section (abfd, sec, link_info, again)
00722 bfd *abfd;
00723 asection *sec;
00724 struct bfd_link_info *link_info;
00725 bfd_boolean *again;
00726 {
00727 struct one_fixup
00728 {
00729 struct one_fixup *next;
00730 asection *tsec;
00731 bfd_vma toff;
00732 bfd_vma trampoff;
00733 };
00734
00735 Elf_Internal_Shdr *symtab_hdr;
00736 Elf_Internal_Rela *internal_relocs;
00737 Elf_Internal_Rela *irel, *irelend;
00738 bfd_byte *contents;
00739 Elf_Internal_Sym *isymbuf = NULL;
00740 struct elfNN_ia64_link_hash_table *ia64_info;
00741 struct one_fixup *fixups = NULL;
00742 bfd_boolean changed_contents = FALSE;
00743 bfd_boolean changed_relocs = FALSE;
00744 bfd_boolean changed_got = FALSE;
00745 bfd_vma gp = 0;
00746
00747
00748
00749 *again = FALSE;
00750
00751
00752 if (!is_elf_hash_table (link_info->hash))
00753 return FALSE;
00754
00755
00756
00757 if ((sec->flags & SEC_RELOC) == 0
00758 || sec->reloc_count == 0
00759 || (!link_info->need_relax_finalize
00760 && sec->need_finalize_relax == 0))
00761 return TRUE;
00762
00763 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
00764
00765
00766 internal_relocs = (_bfd_elf_link_read_relocs
00767 (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
00768 link_info->keep_memory));
00769 if (internal_relocs == NULL)
00770 return FALSE;
00771
00772 ia64_info = elfNN_ia64_hash_table (link_info);
00773 irelend = internal_relocs + sec->reloc_count;
00774
00775
00776 if (elf_section_data (sec)->this_hdr.contents != NULL)
00777 contents = elf_section_data (sec)->this_hdr.contents;
00778 else
00779 {
00780 if (!bfd_malloc_and_get_section (abfd, sec, &contents))
00781 goto error_return;
00782 }
00783
00784 for (irel = internal_relocs; irel < irelend; irel++)
00785 {
00786 unsigned long r_type = ELFNN_R_TYPE (irel->r_info);
00787 bfd_vma symaddr, reladdr, trampoff, toff, roff;
00788 asection *tsec;
00789 struct one_fixup *f;
00790 bfd_size_type amt;
00791 bfd_boolean is_branch;
00792 struct elfNN_ia64_dyn_sym_info *dyn_i;
00793 char symtype;
00794
00795 switch (r_type)
00796 {
00797 case R_IA64_PCREL21B:
00798 case R_IA64_PCREL21BI:
00799 case R_IA64_PCREL21M:
00800 case R_IA64_PCREL21F:
00801
00802
00803 if (!link_info->need_relax_finalize)
00804 continue;
00805 is_branch = TRUE;
00806 break;
00807
00808 case R_IA64_PCREL60B:
00809
00810
00811
00812 if (link_info->need_relax_finalize)
00813 {
00814 sec->need_finalize_relax = 1;
00815 continue;
00816 }
00817 is_branch = TRUE;
00818 break;
00819
00820 case R_IA64_LTOFF22X:
00821 case R_IA64_LDXMOV:
00822
00823
00824
00825 if (link_info->need_relax_finalize)
00826 {
00827 sec->need_finalize_relax = 1;
00828 continue;
00829 }
00830 is_branch = FALSE;
00831 break;
00832
00833 default:
00834 continue;
00835 }
00836
00837
00838 if (ELFNN_R_SYM (irel->r_info) < symtab_hdr->sh_info)
00839 {
00840
00841 Elf_Internal_Sym *isym;
00842
00843
00844 if (isymbuf == NULL)
00845 {
00846 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
00847 if (isymbuf == NULL)
00848 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
00849 symtab_hdr->sh_info, 0,
00850 NULL, NULL, NULL);
00851 if (isymbuf == 0)
00852 goto error_return;
00853 }
00854
00855 isym = isymbuf + ELFNN_R_SYM (irel->r_info);
00856 if (isym->st_shndx == SHN_UNDEF)
00857 continue;
00858 else if (isym->st_shndx == SHN_ABS)
00859 tsec = bfd_abs_section_ptr;
00860 else if (isym->st_shndx == SHN_COMMON)
00861 tsec = bfd_com_section_ptr;
00862 else if (isym->st_shndx == SHN_IA_64_ANSI_COMMON)
00863 tsec = bfd_com_section_ptr;
00864 else
00865 tsec = bfd_section_from_elf_index (abfd, isym->st_shndx);
00866
00867 toff = isym->st_value;
00868 dyn_i = get_dyn_sym_info (ia64_info, NULL, abfd, irel, FALSE);
00869 symtype = ELF_ST_TYPE (isym->st_info);
00870 }
00871 else
00872 {
00873 unsigned long indx;
00874 struct elf_link_hash_entry *h;
00875
00876 indx = ELFNN_R_SYM (irel->r_info) - symtab_hdr->sh_info;
00877 h = elf_sym_hashes (abfd)[indx];
00878 BFD_ASSERT (h != NULL);
00879
00880 while (h->root.type == bfd_link_hash_indirect
00881 || h->root.type == bfd_link_hash_warning)
00882 h = (struct elf_link_hash_entry *) h->root.u.i.link;
00883
00884 dyn_i = get_dyn_sym_info (ia64_info, h, abfd, irel, FALSE);
00885
00886
00887
00888 if (is_branch && dyn_i && dyn_i->want_plt2)
00889 {
00890
00891
00892 if (r_type != R_IA64_PCREL21B)
00893 continue;
00894
00895 tsec = ia64_info->plt_sec;
00896 toff = dyn_i->plt2_offset;
00897 BFD_ASSERT (irel->r_addend == 0);
00898 }
00899
00900
00901 else if (elfNN_ia64_dynamic_symbol_p (h, link_info, r_type))
00902 continue;
00903
00904 else
00905 {
00906
00907 if (h->root.type == bfd_link_hash_undefined
00908 || h->root.type == bfd_link_hash_undefweak)
00909 continue;
00910
00911 tsec = h->root.u.def.section;
00912 toff = h->root.u.def.value;
00913 }
00914
00915 symtype = h->type;
00916 }
00917
00918 if (tsec->sec_info_type == ELF_INFO_TYPE_MERGE)
00919 {
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936 if (symtype == STT_SECTION)
00937 toff += irel->r_addend;
00938
00939 toff = _bfd_merged_section_offset (abfd, &tsec,
00940 elf_section_data (tsec)->sec_info,
00941 toff);
00942
00943 if (symtype != STT_SECTION)
00944 toff += irel->r_addend;
00945 }
00946 else
00947 toff += irel->r_addend;
00948
00949 symaddr = tsec->output_section->vma + tsec->output_offset + toff;
00950
00951 roff = irel->r_offset;
00952
00953 if (is_branch)
00954 {
00955 bfd_signed_vma offset;
00956
00957 reladdr = (sec->output_section->vma
00958 + sec->output_offset
00959 + roff) & (bfd_vma) -4;
00960
00961
00962 if ((bfd_signed_vma) (symaddr - reladdr) >= -0x1000000
00963 && (bfd_signed_vma) (symaddr - reladdr) <= 0x0FFFFF0)
00964 {
00965
00966 if (r_type == R_IA64_PCREL60B)
00967 {
00968 elfNN_ia64_relax_brl (contents, roff);
00969
00970 irel->r_info
00971 = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info),
00972 R_IA64_PCREL21B);
00973
00974
00975
00976 if ((irel->r_offset & 3) == 1)
00977 irel->r_offset += 1;
00978 }
00979
00980 continue;
00981 }
00982 else if (r_type == R_IA64_PCREL60B)
00983 continue;
00984
00985
00986
00987 if (strcmp (sec->output_section->name, ".init") == 0
00988 || strcmp (sec->output_section->name, ".fini") == 0)
00989 {
00990 (*_bfd_error_handler)
00991 (_("%B: Can't relax br at 0x%lx in section `%A'. Please use brl or indirect branch."),
00992 sec->owner, sec, (unsigned long) roff);
00993 bfd_set_error (bfd_error_bad_value);
00994 goto error_return;
00995 }
00996
00997
00998
00999
01000
01001 if (tsec == sec && toff > roff)
01002 continue;
01003
01004
01005 for (f = fixups; f ; f = f->next)
01006 if (f->tsec == tsec && f->toff == toff)
01007 break;
01008
01009 if (f == NULL)
01010 {
01011
01012
01013
01014
01015 size_t size;
01016
01017 if (tsec == ia64_info->plt_sec)
01018 size = sizeof (plt_full_entry);
01019 else
01020 size = oor_branch_size;
01021
01022
01023 trampoff = (sec->size + 15) & (bfd_vma) -16;
01024
01025
01026
01027 offset = trampoff - (roff & (bfd_vma) -4);
01028 if (offset < -0x1000000 || offset > 0x0FFFFF0)
01029 continue;
01030
01031 amt = trampoff + size;
01032 contents = (bfd_byte *) bfd_realloc (contents, amt);
01033 if (contents == NULL)
01034 goto error_return;
01035 sec->size = amt;
01036
01037 if (tsec == ia64_info->plt_sec)
01038 {
01039 memcpy (contents + trampoff, plt_full_entry, size);
01040
01041
01042 irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info),
01043 R_IA64_PLTOFF22);
01044 irel->r_offset = trampoff;
01045 }
01046 else
01047 {
01048 if (size == sizeof (oor_ip))
01049 {
01050 memcpy (contents + trampoff, oor_ip, size);
01051 irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info),
01052 R_IA64_PCREL64I);
01053 irel->r_addend -= 16;
01054 irel->r_offset = trampoff + 2;
01055 }
01056 else
01057 {
01058 memcpy (contents + trampoff, oor_brl, size);
01059 irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info),
01060 R_IA64_PCREL60B);
01061 irel->r_offset = trampoff + 2;
01062 }
01063
01064 }
01065
01066
01067 f = (struct one_fixup *)
01068 bfd_malloc ((bfd_size_type) sizeof (*f));
01069 f->next = fixups;
01070 f->tsec = tsec;
01071 f->toff = toff;
01072 f->trampoff = trampoff;
01073 fixups = f;
01074 }
01075 else
01076 {
01077
01078
01079 offset = f->trampoff - (roff & (bfd_vma) -4);
01080 if (offset < -0x1000000 || offset > 0x0FFFFF0)
01081 continue;
01082
01083
01084 irel->r_info = ELFNN_R_INFO (0, R_IA64_NONE);
01085 }
01086
01087
01088 if (elfNN_ia64_install_value (contents + roff, offset, r_type)
01089 != bfd_reloc_ok)
01090 goto error_return;
01091
01092 changed_contents = TRUE;
01093 changed_relocs = TRUE;
01094 }
01095 else
01096 {
01097
01098 if (gp == 0)
01099 {
01100 bfd *obfd = sec->output_section->owner;
01101 gp = _bfd_get_gp_value (obfd);
01102 if (gp == 0)
01103 {
01104 if (!elfNN_ia64_choose_gp (obfd, link_info))
01105 goto error_return;
01106 gp = _bfd_get_gp_value (obfd);
01107 }
01108 }
01109
01110
01111 if ((bfd_signed_vma) (symaddr - gp) >= 0x200000
01112 ||(bfd_signed_vma) (symaddr - gp) < -0x200000)
01113 continue;
01114
01115 if (r_type == R_IA64_LTOFF22X)
01116 {
01117 irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info),
01118 R_IA64_GPREL22);
01119 changed_relocs = TRUE;
01120 if (dyn_i->want_gotx)
01121 {
01122 dyn_i->want_gotx = 0;
01123 changed_got |= !dyn_i->want_got;
01124 }
01125 }
01126 else
01127 {
01128 elfNN_ia64_relax_ldxmov (contents, roff);
01129 irel->r_info = ELFNN_R_INFO (0, R_IA64_NONE);
01130 changed_contents = TRUE;
01131 changed_relocs = TRUE;
01132 }
01133 }
01134 }
01135
01136
01137
01138
01139
01140
01141
01142 while (fixups)
01143 {
01144 struct one_fixup *f = fixups;
01145 fixups = fixups->next;
01146 free (f);
01147 }
01148
01149 if (isymbuf != NULL
01150 && symtab_hdr->contents != (unsigned char *) isymbuf)
01151 {
01152 if (! link_info->keep_memory)
01153 free (isymbuf);
01154 else
01155 {
01156
01157 symtab_hdr->contents = (unsigned char *) isymbuf;
01158 }
01159 }
01160
01161 if (contents != NULL
01162 && elf_section_data (sec)->this_hdr.contents != contents)
01163 {
01164 if (!changed_contents && !link_info->keep_memory)
01165 free (contents);
01166 else
01167 {
01168
01169 elf_section_data (sec)->this_hdr.contents = contents;
01170 }
01171 }
01172
01173 if (elf_section_data (sec)->relocs != internal_relocs)
01174 {
01175 if (!changed_relocs)
01176 free (internal_relocs);
01177 else
01178 elf_section_data (sec)->relocs = internal_relocs;
01179 }
01180
01181 if (changed_got)
01182 {
01183 struct elfNN_ia64_allocate_data data;
01184 data.info = link_info;
01185 data.ofs = 0;
01186 ia64_info->self_dtpmod_offset = (bfd_vma) -1;
01187
01188 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_data_got, &data);
01189 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_fptr_got, &data);
01190 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_local_got, &data);
01191 ia64_info->got_sec->size = data.ofs;
01192
01193
01194 }
01195
01196 if (!link_info->need_relax_finalize)
01197 sec->need_finalize_relax = 0;
01198
01199 *again = changed_contents || changed_relocs;
01200 return TRUE;
01201
01202 error_return:
01203 if (isymbuf != NULL && (unsigned char *) isymbuf != symtab_hdr->contents)
01204 free (isymbuf);
01205 if (contents != NULL
01206 && elf_section_data (sec)->this_hdr.contents != contents)
01207 free (contents);
01208 if (internal_relocs != NULL
01209 && elf_section_data (sec)->relocs != internal_relocs)
01210 free (internal_relocs);
01211 return FALSE;
01212 }
01213
01214 static void
01215 elfNN_ia64_relax_ldxmov (contents, off)
01216 bfd_byte *contents;
01217 bfd_vma off;
01218 {
01219 int shift, r1, r3;
01220 bfd_vma dword, insn;
01221
01222 switch ((int)off & 0x3)
01223 {
01224 case 0: shift = 5; break;
01225 case 1: shift = 14; off += 3; break;
01226 case 2: shift = 23; off += 6; break;
01227 default:
01228 abort ();
01229 }
01230
01231 dword = bfd_getl64 (contents + off);
01232 insn = (dword >> shift) & 0x1ffffffffffLL;
01233
01234 r1 = (insn >> 6) & 127;
01235 r3 = (insn >> 20) & 127;
01236 if (r1 == r3)
01237 insn = 0x8000000;
01238 else
01239 insn = (insn & 0x7f01fff) | 0x10800000000LL;
01240
01241 dword &= ~(0x1ffffffffffLL << shift);
01242 dword |= (insn << shift);
01243 bfd_putl64 (dword, contents + off);
01244 }
01245
01246
01247
01248 static inline bfd_boolean
01249 is_unwind_section_name (abfd, name)
01250 bfd *abfd;
01251 const char *name;
01252 {
01253 size_t len1, len2, len3;
01254
01255 if (elfNN_ia64_hpux_vec (abfd->xvec)
01256 && !strcmp (name, ELF_STRING_ia64_unwind_hdr))
01257 return FALSE;
01258
01259 len1 = sizeof (ELF_STRING_ia64_unwind) - 1;
01260 len2 = sizeof (ELF_STRING_ia64_unwind_info) - 1;
01261 len3 = sizeof (ELF_STRING_ia64_unwind_once) - 1;
01262 return ((strncmp (name, ELF_STRING_ia64_unwind, len1) == 0
01263 && strncmp (name, ELF_STRING_ia64_unwind_info, len2) != 0)
01264 || strncmp (name, ELF_STRING_ia64_unwind_once, len3) == 0);
01265 }
01266
01267
01268
01269
01270 static bfd_boolean
01271 elfNN_ia64_section_from_shdr (abfd, hdr, name)
01272 bfd *abfd;
01273 Elf_Internal_Shdr *hdr;
01274 const char *name;
01275 {
01276 asection *newsect;
01277
01278
01279
01280
01281
01282
01283 switch (hdr->sh_type)
01284 {
01285 case SHT_IA_64_UNWIND:
01286 case SHT_IA_64_HP_OPT_ANOT:
01287 break;
01288
01289 case SHT_IA_64_EXT:
01290 if (strcmp (name, ELF_STRING_ia64_archext) != 0)
01291 return FALSE;
01292 break;
01293
01294 default:
01295 return FALSE;
01296 }
01297
01298 if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
01299 return FALSE;
01300 newsect = hdr->bfd_section;
01301
01302 return TRUE;
01303 }
01304
01305
01306
01307
01308
01309
01310 static bfd_boolean
01311 elfNN_ia64_section_flags (flags, hdr)
01312 flagword *flags;
01313 const Elf_Internal_Shdr *hdr;
01314 {
01315 if (hdr->sh_flags & SHF_IA_64_SHORT)
01316 *flags |= SEC_SMALL_DATA;
01317
01318 return TRUE;
01319 }
01320
01321
01322
01323
01324 static bfd_boolean
01325 elfNN_ia64_fake_sections (abfd, hdr, sec)
01326 bfd *abfd ATTRIBUTE_UNUSED;
01327 Elf_Internal_Shdr *hdr;
01328 asection *sec;
01329 {
01330 register const char *name;
01331
01332 name = bfd_get_section_name (abfd, sec);
01333
01334 if (is_unwind_section_name (abfd, name))
01335 {
01336
01337
01338 hdr->sh_type = SHT_IA_64_UNWIND;
01339 hdr->sh_flags |= SHF_LINK_ORDER;
01340 }
01341 else if (strcmp (name, ELF_STRING_ia64_archext) == 0)
01342 hdr->sh_type = SHT_IA_64_EXT;
01343 else if (strcmp (name, ".HP.opt_annot") == 0)
01344 hdr->sh_type = SHT_IA_64_HP_OPT_ANOT;
01345 else if (strcmp (name, ".reloc") == 0)
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362 hdr->sh_type = SHT_PROGBITS;
01363
01364 if (sec->flags & SEC_SMALL_DATA)
01365 hdr->sh_flags |= SHF_IA_64_SHORT;
01366
01367 return TRUE;
01368 }
01369
01370
01371
01372
01373 static void
01374 elfNN_ia64_final_write_processing (abfd, linker)
01375 bfd *abfd;
01376 bfd_boolean linker ATTRIBUTE_UNUSED;
01377 {
01378 Elf_Internal_Shdr *hdr;
01379 asection *s;
01380
01381 for (s = abfd->sections; s; s = s->next)
01382 {
01383 hdr = &elf_section_data (s)->this_hdr;
01384 switch (hdr->sh_type)
01385 {
01386 case SHT_IA_64_UNWIND:
01387
01388
01389
01390
01391 hdr->sh_info = hdr->sh_link;
01392 break;
01393 }
01394 }
01395
01396 if (! elf_flags_init (abfd))
01397 {
01398 unsigned long flags = 0;
01399
01400 if (abfd->xvec->byteorder == BFD_ENDIAN_BIG)
01401 flags |= EF_IA_64_BE;
01402 if (bfd_get_mach (abfd) == bfd_mach_ia64_elf64)
01403 flags |= EF_IA_64_ABI64;
01404
01405 elf_elfheader(abfd)->e_flags = flags;
01406 elf_flags_init (abfd) = TRUE;
01407 }
01408 }
01409
01410
01411
01412
01413 static bfd_boolean
01414 elfNN_ia64_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
01415 bfd *abfd;
01416 struct bfd_link_info *info;
01417 Elf_Internal_Sym *sym;
01418 const char **namep ATTRIBUTE_UNUSED;
01419 flagword *flagsp ATTRIBUTE_UNUSED;
01420 asection **secp;
01421 bfd_vma *valp;
01422 {
01423 if (sym->st_shndx == SHN_COMMON
01424 && !info->relocatable
01425 && sym->st_size <= elf_gp_size (abfd))
01426 {
01427
01428
01429
01430 asection *scomm = bfd_get_section_by_name (abfd, ".scommon");
01431
01432 if (scomm == NULL)
01433 {
01434 scomm = bfd_make_section (abfd, ".scommon");
01435 if (scomm == NULL
01436 || !bfd_set_section_flags (abfd, scomm, (SEC_ALLOC
01437 | SEC_IS_COMMON
01438 | SEC_LINKER_CREATED)))
01439 return FALSE;
01440 }
01441
01442 *secp = scomm;
01443 *valp = sym->st_size;
01444 }
01445
01446 return TRUE;
01447 }
01448
01449
01450
01451 static int
01452 elfNN_ia64_additional_program_headers (abfd)
01453 bfd *abfd;
01454 {
01455 asection *s;
01456 int ret = 0;
01457
01458
01459 s = bfd_get_section_by_name (abfd, ELF_STRING_ia64_archext);
01460 if (s && (s->flags & SEC_LOAD))
01461 ++ret;
01462
01463
01464 for (s = abfd->sections; s; s = s->next)
01465 if (is_unwind_section_name (abfd, s->name) && (s->flags & SEC_LOAD))
01466 ++ret;
01467
01468 return ret;
01469 }
01470
01471 static bfd_boolean
01472 elfNN_ia64_modify_segment_map (abfd, info)
01473 bfd *abfd;
01474 struct bfd_link_info *info ATTRIBUTE_UNUSED;
01475 {
01476 struct elf_segment_map *m, **pm;
01477 Elf_Internal_Shdr *hdr;
01478 asection *s;
01479
01480
01481
01482 s = bfd_get_section_by_name (abfd, ELF_STRING_ia64_archext);
01483 if (s && (s->flags & SEC_LOAD))
01484 {
01485 for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
01486 if (m->p_type == PT_IA_64_ARCHEXT)
01487 break;
01488 if (m == NULL)
01489 {
01490 m = ((struct elf_segment_map *)
01491 bfd_zalloc (abfd, (bfd_size_type) sizeof *m));
01492 if (m == NULL)
01493 return FALSE;
01494
01495 m->p_type = PT_IA_64_ARCHEXT;
01496 m->count = 1;
01497 m->sections[0] = s;
01498
01499
01500 pm = &elf_tdata (abfd)->segment_map;
01501 while (*pm != NULL
01502 && ((*pm)->p_type == PT_PHDR
01503 || (*pm)->p_type == PT_INTERP))
01504 pm = &(*pm)->next;
01505
01506 m->next = *pm;
01507 *pm = m;
01508 }
01509 }
01510
01511
01512 for (s = abfd->sections; s; s = s->next)
01513 {
01514 hdr = &elf_section_data (s)->this_hdr;
01515 if (hdr->sh_type != SHT_IA_64_UNWIND)
01516 continue;
01517
01518 if (s && (s->flags & SEC_LOAD))
01519 {
01520 for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
01521 if (m->p_type == PT_IA_64_UNWIND)
01522 {
01523 int i;
01524
01525
01526
01527
01528 for (i = m->count - 1; i >= 0; --i)
01529 if (m->sections[i] == s)
01530 break;
01531
01532 if (i >= 0)
01533 break;
01534 }
01535
01536 if (m == NULL)
01537 {
01538 m = ((struct elf_segment_map *)
01539 bfd_zalloc (abfd, (bfd_size_type) sizeof *m));
01540 if (m == NULL)
01541 return FALSE;
01542
01543 m->p_type = PT_IA_64_UNWIND;
01544 m->count = 1;
01545 m->sections[0] = s;
01546 m->next = NULL;
01547
01548
01549 pm = &elf_tdata (abfd)->segment_map;
01550 while (*pm != NULL)
01551 pm = &(*pm)->next;
01552 *pm = m;
01553 }
01554 }
01555 }
01556
01557
01558
01559
01560 for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
01561 if (m->p_type == PT_LOAD)
01562 {
01563 int i;
01564 for (i = m->count - 1; i >= 0; --i)
01565 {
01566 struct bfd_link_order *order = m->sections[i]->link_order_head;
01567 while (order)
01568 {
01569 if (order->type == bfd_indirect_link_order)
01570 {
01571 asection *is = order->u.indirect.section;
01572 bfd_vma flags = elf_section_data(is)->this_hdr.sh_flags;
01573 if (flags & SHF_IA_64_NORECOV)
01574 {
01575 m->p_flags |= PF_IA_64_NORECOV;
01576 goto found;
01577 }
01578 }
01579 order = order->next;
01580 }
01581 }
01582 found:;
01583 }
01584
01585 return TRUE;
01586 }
01587
01588
01589
01590
01591 static bfd_boolean
01592 elfNN_ia64_is_local_label_name (abfd, name)
01593 bfd *abfd ATTRIBUTE_UNUSED;
01594 const char *name;
01595 {
01596 return name[0] == '.';
01597 }
01598
01599
01600
01601 static bfd_boolean
01602 elfNN_ia64_dynamic_symbol_p (h, info, r_type)
01603 struct elf_link_hash_entry *h;
01604 struct bfd_link_info *info;
01605 int r_type;
01606 {
01607 bfd_boolean ignore_protected
01608 = ((r_type & 0xf8) == 0x40
01609 || (r_type & 0xf8) == 0x50);
01610
01611 return _bfd_elf_dynamic_symbol_p (h, info, ignore_protected);
01612 }
01613
01614 static struct bfd_hash_entry*
01615 elfNN_ia64_new_elf_hash_entry (entry, table, string)
01616 struct bfd_hash_entry *entry;
01617 struct bfd_hash_table *table;
01618 const char *string;
01619 {
01620 struct elfNN_ia64_link_hash_entry *ret;
01621 ret = (struct elfNN_ia64_link_hash_entry *) entry;
01622
01623
01624
01625 if (!ret)
01626 ret = bfd_hash_allocate (table, sizeof (*ret));
01627
01628 if (!ret)
01629 return 0;
01630
01631
01632 ret = ((struct elfNN_ia64_link_hash_entry *)
01633 _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret,
01634 table, string));
01635
01636 ret->info = NULL;
01637 return (struct bfd_hash_entry *) ret;
01638 }
01639
01640 static void
01641 elfNN_ia64_hash_copy_indirect (bed, xdir, xind)
01642 const struct elf_backend_data *bed ATTRIBUTE_UNUSED;
01643 struct elf_link_hash_entry *xdir, *xind;
01644 {
01645 struct elfNN_ia64_link_hash_entry *dir, *ind;
01646
01647 dir = (struct elfNN_ia64_link_hash_entry *) xdir;
01648 ind = (struct elfNN_ia64_link_hash_entry *) xind;
01649
01650
01651
01652
01653 dir->root.ref_dynamic |= ind->root.ref_dynamic;
01654 dir->root.ref_regular |= ind->root.ref_regular;
01655 dir->root.ref_regular_nonweak |= ind->root.ref_regular_nonweak;
01656 dir->root.needs_plt |= ind->root.needs_plt;
01657
01658 if (ind->root.root.type != bfd_link_hash_indirect)
01659 return;
01660
01661
01662
01663
01664 if (dir->info == NULL)
01665 {
01666 struct elfNN_ia64_dyn_sym_info *dyn_i;
01667
01668 dir->info = dyn_i = ind->info;
01669 ind->info = NULL;
01670
01671
01672 for (; dyn_i; dyn_i = dyn_i->next)
01673 dyn_i->h = &dir->root;
01674 }
01675 BFD_ASSERT (ind->info == NULL);
01676
01677
01678
01679 if (dir->root.dynindx == -1)
01680 {
01681 dir->root.dynindx = ind->root.dynindx;
01682 dir->root.dynstr_index = ind->root.dynstr_index;
01683 ind->root.dynindx = -1;
01684 ind->root.dynstr_index = 0;
01685 }
01686 BFD_ASSERT (ind->root.dynindx == -1);
01687 }
01688
01689 static void
01690 elfNN_ia64_hash_hide_symbol (info, xh, force_local)
01691 struct bfd_link_info *info;
01692 struct elf_link_hash_entry *xh;
01693 bfd_boolean force_local;
01694 {
01695 struct elfNN_ia64_link_hash_entry *h;
01696 struct elfNN_ia64_dyn_sym_info *dyn_i;
01697
01698 h = (struct elfNN_ia64_link_hash_entry *)xh;
01699
01700 _bfd_elf_link_hash_hide_symbol (info, &h->root, force_local);
01701
01702 for (dyn_i = h->info; dyn_i; dyn_i = dyn_i->next)
01703 {
01704 dyn_i->want_plt2 = 0;
01705 dyn_i->want_plt = 0;
01706 }
01707 }
01708
01709
01710
01711 static hashval_t
01712 elfNN_ia64_local_htab_hash (ptr)
01713 const void *ptr;
01714 {
01715 struct elfNN_ia64_local_hash_entry *entry
01716 = (struct elfNN_ia64_local_hash_entry *) ptr;
01717
01718 return (((entry->id & 0xff) << 24) | ((entry->id & 0xff00) << 8))
01719 ^ entry->r_sym ^ (entry->id >> 16);
01720 }
01721
01722
01723
01724 static int
01725 elfNN_ia64_local_htab_eq (ptr1, ptr2)
01726 const void *ptr1, *ptr2;
01727 {
01728 struct elfNN_ia64_local_hash_entry *entry1
01729 = (struct elfNN_ia64_local_hash_entry *) ptr1;
01730 struct elfNN_ia64_local_hash_entry *entry2
01731 = (struct elfNN_ia64_local_hash_entry *) ptr2;
01732
01733 return entry1->id == entry2->id && entry1->r_sym == entry2->r_sym;
01734 }
01735
01736
01737
01738
01739
01740 static struct bfd_link_hash_table*
01741 elfNN_ia64_hash_table_create (abfd)
01742 bfd *abfd;
01743 {
01744 struct elfNN_ia64_link_hash_table *ret;
01745
01746 ret = bfd_zmalloc ((bfd_size_type) sizeof (*ret));
01747 if (!ret)
01748 return 0;
01749
01750 if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
01751 elfNN_ia64_new_elf_hash_entry))
01752 {
01753 free (ret);
01754 return 0;
01755 }
01756
01757 ret->loc_hash_table = htab_try_create (1024, elfNN_ia64_local_htab_hash,
01758 elfNN_ia64_local_htab_eq, NULL);
01759 ret->loc_hash_memory = objalloc_create ();
01760 if (!ret->loc_hash_table || !ret->loc_hash_memory)
01761 {
01762 free (ret);
01763 return 0;
01764 }
01765
01766 return &ret->root.root;
01767 }
01768
01769
01770
01771 static void
01772 elfNN_ia64_hash_table_free (hash)
01773 struct bfd_link_hash_table *hash;
01774 {
01775 struct elfNN_ia64_link_hash_table *ia64_info
01776 = (struct elfNN_ia64_link_hash_table *) hash;
01777 if (ia64_info->loc_hash_table)
01778 htab_delete (ia64_info->loc_hash_table);
01779 if (ia64_info->loc_hash_memory)
01780 objalloc_free ((struct objalloc *) ia64_info->loc_hash_memory);
01781 _bfd_generic_link_hash_table_free (hash);
01782 }
01783
01784
01785
01786 struct elfNN_ia64_dyn_sym_traverse_data
01787 {
01788 bfd_boolean (*func) PARAMS ((struct elfNN_ia64_dyn_sym_info *, PTR));
01789 PTR data;
01790 };
01791
01792 static bfd_boolean
01793 elfNN_ia64_global_dyn_sym_thunk (xentry, xdata)
01794 struct bfd_hash_entry *xentry;
01795 PTR xdata;
01796 {
01797 struct elfNN_ia64_link_hash_entry *entry
01798 = (struct elfNN_ia64_link_hash_entry *) xentry;
01799 struct elfNN_ia64_dyn_sym_traverse_data *data
01800 = (struct elfNN_ia64_dyn_sym_traverse_data *) xdata;
01801 struct elfNN_ia64_dyn_sym_info *dyn_i;
01802
01803 if (entry->root.root.type == bfd_link_hash_warning)
01804 entry = (struct elfNN_ia64_link_hash_entry *) entry->root.root.u.i.link;
01805
01806 for (dyn_i = entry->info; dyn_i; dyn_i = dyn_i->next)
01807 if (! (*data->func) (dyn_i, data->data))
01808 return FALSE;
01809 return TRUE;
01810 }
01811
01812 static bfd_boolean
01813 elfNN_ia64_local_dyn_sym_thunk (slot, xdata)
01814 void **slot;
01815 PTR xdata;
01816 {
01817 struct elfNN_ia64_local_hash_entry *entry
01818 = (struct elfNN_ia64_local_hash_entry *) *slot;
01819 struct elfNN_ia64_dyn_sym_traverse_data *data
01820 = (struct elfNN_ia64_dyn_sym_traverse_data *) xdata;
01821 struct elfNN_ia64_dyn_sym_info *dyn_i;
01822
01823 for (dyn_i = entry->info; dyn_i; dyn_i = dyn_i->next)
01824 if (! (*data->func) (dyn_i, data->data))
01825 return 0;
01826 return 1;
01827 }
01828
01829 static void
01830 elfNN_ia64_dyn_sym_traverse (ia64_info, func, data)
01831 struct elfNN_ia64_link_hash_table *ia64_info;
01832 bfd_boolean (*func) PARAMS ((struct elfNN_ia64_dyn_sym_info *, PTR));
01833 PTR data;
01834 {
01835 struct elfNN_ia64_dyn_sym_traverse_data xdata;
01836
01837 xdata.func = func;
01838 xdata.data = data;
01839
01840 elf_link_hash_traverse (&ia64_info->root,
01841 elfNN_ia64_global_dyn_sym_thunk, &xdata);
01842 htab_traverse (ia64_info->loc_hash_table,
01843 elfNN_ia64_local_dyn_sym_thunk, &xdata);
01844 }
01845
01846 static bfd_boolean
01847 elfNN_ia64_create_dynamic_sections (abfd, info)
01848 bfd *abfd;
01849 struct bfd_link_info *info;
01850 {
01851 struct elfNN_ia64_link_hash_table *ia64_info;
01852 asection *s;
01853
01854 if (! _bfd_elf_create_dynamic_sections (abfd, info))
01855 return FALSE;
01856
01857 ia64_info = elfNN_ia64_hash_table (info);
01858
01859 ia64_info->plt_sec = bfd_get_section_by_name (abfd, ".plt");
01860 ia64_info->got_sec = bfd_get_section_by_name (abfd, ".got");
01861
01862 {
01863 flagword flags = bfd_get_section_flags (abfd, ia64_info->got_sec);
01864 bfd_set_section_flags (abfd, ia64_info->got_sec, SEC_SMALL_DATA | flags);
01865
01866 bfd_set_section_alignment (abfd, ia64_info->got_sec, 3);
01867 }
01868
01869 if (!get_pltoff (abfd, info, ia64_info))
01870 return FALSE;
01871
01872 s = bfd_make_section(abfd, ".rela.IA_64.pltoff");
01873 if (s == NULL
01874 || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
01875 | SEC_HAS_CONTENTS
01876 | SEC_IN_MEMORY
01877 | SEC_LINKER_CREATED
01878 | SEC_READONLY))
01879 || !bfd_set_section_alignment (abfd, s, 3))
01880 return FALSE;
01881 ia64_info->rel_pltoff_sec = s;
01882
01883 s = bfd_make_section(abfd, ".rela.got");
01884 if (s == NULL
01885 || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
01886 | SEC_HAS_CONTENTS
01887 | SEC_IN_MEMORY
01888 | SEC_LINKER_CREATED
01889 | SEC_READONLY))
01890 || !bfd_set_section_alignment (abfd, s, 3))
01891 return FALSE;
01892 ia64_info->rel_got_sec = s;
01893
01894 return TRUE;
01895 }
01896
01897
01898 static struct elfNN_ia64_local_hash_entry *
01899 get_local_sym_hash (ia64_info, abfd, rel, create)
01900 struct elfNN_ia64_link_hash_table *ia64_info;
01901 bfd *abfd;
01902 const Elf_Internal_Rela *rel;
01903 bfd_boolean create;
01904 {
01905 struct elfNN_ia64_local_hash_entry e, *ret;
01906 asection *sec = abfd->sections;
01907 hashval_t h = (((sec->id & 0xff) << 24) | ((sec->id & 0xff00) << 8))
01908 ^ ELFNN_R_SYM (rel->r_info) ^ (sec->id >> 16);
01909 void **slot;
01910
01911 e.id = sec->id;
01912 e.r_sym = ELFNN_R_SYM (rel->r_info);
01913 slot = htab_find_slot_with_hash (ia64_info->loc_hash_table, &e, h,
01914 create ? INSERT : NO_INSERT);
01915
01916 if (!slot)
01917 return NULL;
01918
01919 if (*slot)
01920 return (struct elfNN_ia64_local_hash_entry *) *slot;
01921
01922 ret = (struct elfNN_ia64_local_hash_entry *)
01923 objalloc_alloc ((struct objalloc *) ia64_info->loc_hash_memory,
01924 sizeof (struct elfNN_ia64_local_hash_entry));
01925 if (ret)
01926 {
01927 memset (ret, 0, sizeof (*ret));
01928 ret->id = sec->id;
01929 ret->r_sym = ELFNN_R_SYM (rel->r_info);
01930 *slot = ret;
01931 }
01932 return ret;
01933 }
01934
01935
01936
01937
01938 static struct elfNN_ia64_dyn_sym_info *
01939 get_dyn_sym_info (ia64_info, h, abfd, rel, create)
01940 struct elfNN_ia64_link_hash_table *ia64_info;
01941 struct elf_link_hash_entry *h;
01942 bfd *abfd;
01943 const Elf_Internal_Rela *rel;
01944 bfd_boolean create;
01945 {
01946 struct elfNN_ia64_dyn_sym_info **pp;
01947 struct elfNN_ia64_dyn_sym_info *dyn_i;
01948 bfd_vma addend = rel ? rel->r_addend : 0;
01949
01950 if (h)
01951 pp = &((struct elfNN_ia64_link_hash_entry *)h)->info;
01952 else
01953 {
01954 struct elfNN_ia64_local_hash_entry *loc_h;
01955
01956 loc_h = get_local_sym_hash (ia64_info, abfd, rel, create);
01957 if (!loc_h)
01958 {
01959 BFD_ASSERT (!create);
01960 return NULL;
01961 }
01962
01963 pp = &loc_h->info;
01964 }
01965
01966 for (dyn_i = *pp; dyn_i && dyn_i->addend != addend; dyn_i = *pp)
01967 pp = &dyn_i->next;
01968
01969 if (dyn_i == NULL && create)
01970 {
01971 dyn_i = ((struct elfNN_ia64_dyn_sym_info *)
01972 bfd_zalloc (abfd, (bfd_size_type) sizeof *dyn_i));
01973 *pp = dyn_i;
01974 dyn_i->addend = addend;
01975 }
01976
01977 return dyn_i;
01978 }
01979
01980 static asection *
01981 get_got (abfd, info, ia64_info)
01982 bfd *abfd;
01983 struct bfd_link_info *info;
01984 struct elfNN_ia64_link_hash_table *ia64_info;
01985 {
01986 asection *got;
01987 bfd *dynobj;
01988
01989 got = ia64_info->got_sec;
01990 if (!got)
01991 {
01992 flagword flags;
01993
01994 dynobj = ia64_info->root.dynobj;
01995 if (!dynobj)
01996 ia64_info->root.dynobj = dynobj = abfd;
01997 if (!_bfd_elf_create_got_section (dynobj, info))
01998 return 0;
01999
02000 got = bfd_get_section_by_name (dynobj, ".got");
02001 BFD_ASSERT (got);
02002 ia64_info->got_sec = got;
02003
02004
02005 if (!bfd_set_section_alignment (abfd, got, 3))
02006 return 0;
02007
02008 flags = bfd_get_section_flags (abfd, got);
02009 bfd_set_section_flags (abfd, got, SEC_SMALL_DATA | flags);
02010 }
02011
02012 return got;
02013 }
02014
02015
02016
02017
02018
02019
02020 static asection *
02021 get_fptr (abfd, info, ia64_info)
02022 bfd *abfd;
02023 struct bfd_link_info *info;
02024 struct elfNN_ia64_link_hash_table *ia64_info;
02025 {
02026 asection *fptr;
02027 bfd *dynobj;
02028
02029 fptr = ia64_info->fptr_sec;
02030 if (!fptr)
02031 {
02032 dynobj = ia64_info->root.dynobj;
02033 if (!dynobj)
02034 ia64_info->root.dynobj = dynobj = abfd;
02035
02036 fptr = bfd_make_section (dynobj, ".opd");
02037 if (!fptr
02038 || !bfd_set_section_flags (dynobj, fptr,
02039 (SEC_ALLOC
02040 | SEC_LOAD
02041 | SEC_HAS_CONTENTS
02042 | SEC_IN_MEMORY
02043 | (info->pie ? 0 : SEC_READONLY)
02044 | SEC_LINKER_CREATED))
02045 || !bfd_set_section_alignment (abfd, fptr, 4))
02046 {
02047 BFD_ASSERT (0);
02048 return NULL;
02049 }
02050
02051 ia64_info->fptr_sec = fptr;
02052
02053 if (info->pie)
02054 {
02055 asection *fptr_rel;
02056 fptr_rel = bfd_make_section(dynobj, ".rela.opd");
02057 if (fptr_rel == NULL
02058 || !bfd_set_section_flags (dynobj, fptr_rel,
02059 (SEC_ALLOC | SEC_LOAD
02060 | SEC_HAS_CONTENTS
02061 | SEC_IN_MEMORY
02062 | SEC_LINKER_CREATED
02063 | SEC_READONLY))
02064 || !bfd_set_section_alignment (abfd, fptr_rel, 3))
02065 {
02066 BFD_ASSERT (0);
02067 return NULL;
02068 }
02069
02070 ia64_info->rel_fptr_sec = fptr_rel;
02071 }
02072 }
02073
02074 return fptr;
02075 }
02076
02077 static asection *
02078 get_pltoff (abfd, info, ia64_info)
02079 bfd *abfd;
02080 struct bfd_link_info *info ATTRIBUTE_UNUSED;
02081 struct elfNN_ia64_link_hash_table *ia64_info;
02082 {
02083 asection *pltoff;
02084 bfd *dynobj;
02085
02086 pltoff = ia64_info->pltoff_sec;
02087 if (!pltoff)
02088 {
02089 dynobj = ia64_info->root.dynobj;
02090 if (!dynobj)
02091 ia64_info->root.dynobj = dynobj = abfd;
02092
02093 pltoff = bfd_make_section (dynobj, ELF_STRING_ia64_pltoff);
02094 if (!pltoff
02095 || !bfd_set_section_flags (dynobj, pltoff,
02096 (SEC_ALLOC
02097 | SEC_LOAD
02098 | SEC_HAS_CONTENTS
02099 | SEC_IN_MEMORY
02100 | SEC_SMALL_DATA
02101 | SEC_LINKER_CREATED))
02102 || !bfd_set_section_alignment (abfd, pltoff, 4))
02103 {
02104 BFD_ASSERT (0);
02105 return NULL;
02106 }
02107
02108 ia64_info->pltoff_sec = pltoff;
02109 }
02110
02111 return pltoff;
02112 }
02113
02114 static asection *
02115 get_reloc_section (abfd, ia64_info, sec, create)
02116 bfd *abfd;
02117 struct elfNN_ia64_link_hash_table *ia64_info;
02118 asection *sec;
02119 bfd_boolean create;
02120 {
02121 const char *srel_name;
02122 asection *srel;
02123 bfd *dynobj;
02124
02125 srel_name = (bfd_elf_string_from_elf_section
02126 (abfd, elf_elfheader(abfd)->e_shstrndx,
02127 elf_section_data(sec)->rel_hdr.sh_name));
02128 if (srel_name == NULL)
02129 return NULL;
02130
02131 BFD_ASSERT ((strncmp (srel_name, ".rela", 5) == 0
02132 && strcmp (bfd_get_section_name (abfd, sec),
02133 srel_name+5) == 0)
02134 || (strncmp (srel_name, ".rel", 4) == 0
02135 && strcmp (bfd_get_section_name (abfd, sec),
02136 srel_name+4) == 0));
02137
02138 dynobj = ia64_info->root.dynobj;
02139 if (!dynobj)
02140 ia64_info->root.dynobj = dynobj = abfd;
02141
02142 srel = bfd_get_section_by_name (dynobj, srel_name);
02143 if (srel == NULL && create)
02144 {
02145 srel = bfd_make_section (dynobj, srel_name);
02146 if (srel == NULL
02147 || !bfd_set_section_flags (dynobj, srel,
02148 (SEC_ALLOC
02149 | SEC_LOAD
02150 | SEC_HAS_CONTENTS
02151 | SEC_IN_MEMORY
02152 | SEC_LINKER_CREATED
02153 | SEC_READONLY))
02154 || !bfd_set_section_alignment (dynobj, srel, 3))
02155 return NULL;
02156 }
02157
02158 return srel;
02159 }
02160
02161 static bfd_boolean
02162 count_dyn_reloc (bfd *abfd, struct elfNN_ia64_dyn_sym_info *dyn_i,
02163 asection *srel, int type, bfd_boolean reltext)
02164 {
02165 struct elfNN_ia64_dyn_reloc_entry *rent;
02166
02167 for (rent = dyn_i->reloc_entries; rent; rent = rent->next)
02168 if (rent->srel == srel && rent->type == type)
02169 break;
02170
02171 if (!rent)
02172 {
02173 rent = ((struct elfNN_ia64_dyn_reloc_entry *)
02174 bfd_alloc (abfd, (bfd_size_type) sizeof (*rent)));
02175 if (!rent)
02176 return FALSE;
02177
02178 rent->next = dyn_i->reloc_entries;
02179 rent->srel = srel;
02180 rent->type = type;
02181 rent->count = 0;
02182 dyn_i->reloc_entries = rent;
02183 }
02184 rent->reltext = reltext;
02185 rent->count++;
02186
02187 return TRUE;
02188 }
02189
02190 static bfd_boolean
02191 elfNN_ia64_check_relocs (abfd, info, sec, relocs)
02192 bfd *abfd;
02193 struct bfd_link_info *info;
02194 asection *sec;
02195 const Elf_Internal_Rela *relocs;
02196 {
02197 struct elfNN_ia64_link_hash_table *ia64_info;
02198 const Elf_Internal_Rela *relend;
02199 Elf_Internal_Shdr *symtab_hdr;
02200 const Elf_Internal_Rela *rel;
02201 asection *got, *fptr, *srel, *pltoff;
02202
02203 if (info->relocatable)
02204 return TRUE;
02205
02206 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
02207 ia64_info = elfNN_ia64_hash_table (info);
02208
02209 got = fptr = srel = pltoff = NULL;
02210
02211 relend = relocs + sec->reloc_count;
02212 for (rel = relocs; rel < relend; ++rel)
02213 {
02214 enum {
02215 NEED_GOT = 1,
02216 NEED_GOTX = 2,
02217 NEED_FPTR = 4,
02218 NEED_PLTOFF = 8,
02219 NEED_MIN_PLT = 16,
02220 NEED_FULL_PLT = 32,
02221 NEED_DYNREL = 64,
02222 NEED_LTOFF_FPTR = 128,
02223 NEED_TPREL = 256,
02224 NEED_DTPMOD = 512,
02225 NEED_DTPREL = 1024
02226 };
02227
02228 struct elf_link_hash_entry *h = NULL;
02229 unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
02230 struct elfNN_ia64_dyn_sym_info *dyn_i;
02231 int need_entry;
02232 bfd_boolean maybe_dynamic;
02233 int dynrel_type = R_IA64_NONE;
02234
02235 if (r_symndx >= symtab_hdr->sh_info)
02236 {
02237
02238
02239 long indx = r_symndx - symtab_hdr->sh_info;
02240 h = elf_sym_hashes (abfd)[indx];
02241 while (h->root.type == bfd_link_hash_indirect
02242 || h->root.type == bfd_link_hash_warning)
02243 h = (struct elf_link_hash_entry *) h->root.u.i.link;
02244
02245 h->ref_regular = 1;
02246 }
02247
02248
02249
02250
02251
02252 maybe_dynamic = FALSE;
02253 if (h && ((!info->executable
02254 && (!info->symbolic
02255 || info->unresolved_syms_in_shared_libs == RM_IGNORE))
02256 || !h->def_regular
02257 || h->root.type == bfd_link_hash_defweak))
02258 maybe_dynamic = TRUE;
02259
02260 need_entry = 0;
02261 switch (ELFNN_R_TYPE (rel->r_info))
02262 {
02263 case R_IA64_TPREL64MSB:
02264 case R_IA64_TPREL64LSB:
02265 if (info->shared || maybe_dynamic)
02266 need_entry = NEED_DYNREL;
02267 dynrel_type = R_IA64_TPREL64LSB;
02268 if (info->shared)
02269 info->flags |= DF_STATIC_TLS;
02270 break;
02271
02272 case R_IA64_LTOFF_TPREL22:
02273 need_entry = NEED_TPREL;
02274 if (info->shared)
02275 info->flags |= DF_STATIC_TLS;
02276 break;
02277
02278 case R_IA64_DTPREL64MSB:
02279 case R_IA64_DTPREL64LSB:
02280 if (info->shared || maybe_dynamic)
02281 need_entry = NEED_DYNREL;
02282 dynrel_type = R_IA64_DTPREL64LSB;
02283 break;
02284
02285 case R_IA64_LTOFF_DTPREL22:
02286 need_entry = NEED_DTPREL;
02287 break;
02288
02289 case R_IA64_DTPMOD64MSB:
02290 case R_IA64_DTPMOD64LSB:
02291 if (info->shared || maybe_dynamic)
02292 need_entry = NEED_DYNREL;
02293 dynrel_type = R_IA64_DTPMOD64LSB;
02294 break;
02295
02296 case R_IA64_LTOFF_DTPMOD22:
02297 need_entry = NEED_DTPMOD;
02298 break;
02299
02300 case R_IA64_LTOFF_FPTR22:
02301 case R_IA64_LTOFF_FPTR64I:
02302 case R_IA64_LTOFF_FPTR32MSB:
02303 case R_IA64_LTOFF_FPTR32LSB:
02304 case R_IA64_LTOFF_FPTR64MSB:
02305 case R_IA64_LTOFF_FPTR64LSB:
02306 need_entry = NEED_FPTR | NEED_GOT | NEED_LTOFF_FPTR;
02307 break;
02308
02309 case R_IA64_FPTR64I:
02310 case R_IA64_FPTR32MSB:
02311 case R_IA64_FPTR32LSB:
02312 case R_IA64_FPTR64MSB:
02313 case R_IA64_FPTR64LSB:
02314 if (info->shared || h)
02315 need_entry = NEED_FPTR | NEED_DYNREL;
02316 else
02317 need_entry = NEED_FPTR;
02318 dynrel_type = R_IA64_FPTR64LSB;
02319 break;
02320
02321 case R_IA64_LTOFF22:
02322 case R_IA64_LTOFF64I:
02323 need_entry = NEED_GOT;
02324 break;
02325
02326 case R_IA64_LTOFF22X:
02327 need_entry = NEED_GOTX;
02328 break;
02329
02330 case R_IA64_PLTOFF22:
02331 case R_IA64_PLTOFF64I:
02332 case R_IA64_PLTOFF64MSB:
02333 case R_IA64_PLTOFF64LSB:
02334 need_entry = NEED_PLTOFF;
02335 if (h)
02336 {
02337 if (maybe_dynamic)
02338 need_entry |= NEED_MIN_PLT;
02339 }
02340 else
02341 {
02342 (*info->callbacks->warning)
02343 (info, _("@pltoff reloc against local symbol"), 0,
02344 abfd, 0, (bfd_vma) 0);
02345 }
02346 break;
02347
02348 case R_IA64_PCREL21B:
02349 case R_IA64_PCREL60B:
02350
02351
02352
02353
02354 if (maybe_dynamic && rel->r_addend == 0)
02355 need_entry = NEED_FULL_PLT;
02356 break;
02357
02358 case R_IA64_IMM14:
02359 case R_IA64_IMM22:
02360 case R_IA64_IMM64:
02361 case R_IA64_DIR32MSB:
02362 case R_IA64_DIR32LSB:
02363 case R_IA64_DIR64MSB:
02364 case R_IA64_DIR64LSB:
02365
02366 if (info->shared || maybe_dynamic)
02367 need_entry = NEED_DYNREL;
02368 dynrel_type = R_IA64_DIR64LSB;
02369 break;
02370
02371 case R_IA64_IPLTMSB:
02372 case R_IA64_IPLTLSB:
02373
02374 if (info->shared || maybe_dynamic)
02375 need_entry = NEED_DYNREL;
02376 dynrel_type = R_IA64_IPLTLSB;
02377 break;
02378
02379 case R_IA64_PCREL22:
02380 case R_IA64_PCREL64I:
02381 case R_IA64_PCREL32MSB:
02382 case R_IA64_PCREL32LSB:
02383 case R_IA64_PCREL64MSB:
02384 case R_IA64_PCREL64LSB:
02385 if (maybe_dynamic)
02386 need_entry = NEED_DYNREL;
02387 dynrel_type = R_IA64_PCREL64LSB;
02388 break;
02389 }
02390
02391 if (!need_entry)
02392 continue;
02393
02394 if ((need_entry & NEED_FPTR) != 0
02395 && rel->r_addend)
02396 {
02397 (*info->callbacks->warning)
02398 (info, _("non-zero addend in @fptr reloc"), 0,
02399 abfd, 0, (bfd_vma) 0);
02400 }
02401
02402 dyn_i = get_dyn_sym_info (ia64_info, h, abfd, rel, TRUE);
02403
02404
02405 dyn_i->h = h;
02406
02407
02408 if (need_entry & (NEED_GOT | NEED_GOTX | NEED_TPREL
02409 | NEED_DTPMOD | NEED_DTPREL))
02410 {
02411 if (!got)
02412 {
02413 got = get_got (abfd, info, ia64_info);
02414 if (!got)
02415 return FALSE;
02416 }
02417 if (need_entry & NEED_GOT)
02418 dyn_i->want_got = 1;
02419 if (need_entry & NEED_GOTX)
02420 dyn_i->want_gotx = 1;
02421 if (need_entry & NEED_TPREL)
02422 dyn_i->want_tprel = 1;
02423 if (need_entry & NEED_DTPMOD)
02424 dyn_i->want_dtpmod = 1;
02425 if (need_entry & NEED_DTPREL)
02426 dyn_i->want_dtprel = 1;
02427 }
02428 if (need_entry & NEED_FPTR)
02429 {
02430 if (!fptr)
02431 {
02432 fptr = get_fptr (abfd, info, ia64_info);
02433 if (!fptr)
02434 return FALSE;
02435 }
02436
02437
02438
02439
02440 if (!h && info->shared)
02441 {
02442 if (! (bfd_elf_link_record_local_dynamic_symbol
02443 (info, abfd, (long) r_symndx)))
02444 return FALSE;
02445 }
02446
02447 dyn_i->want_fptr = 1;
02448 }
02449 if (need_entry & NEED_LTOFF_FPTR)
02450 dyn_i->want_ltoff_fptr = 1;
02451 if (need_entry & (NEED_MIN_PLT | NEED_FULL_PLT))
02452 {
02453 if (!ia64_info->root.dynobj)
02454 ia64_info->root.dynobj = abfd;
02455 h->needs_plt = 1;
02456 dyn_i->want_plt = 1;
02457 }
02458 if (need_entry & NEED_FULL_PLT)
02459 dyn_i->want_plt2 = 1;
02460 if (need_entry & NEED_PLTOFF)
02461 {
02462
02463
02464 if (!pltoff)
02465 {
02466 pltoff = get_pltoff (abfd, info, ia64_info);
02467 if (!pltoff)
02468 return FALSE;
02469 }
02470
02471 dyn_i->want_pltoff = 1;
02472 }
02473 if ((need_entry & NEED_DYNREL) && (sec->flags & SEC_ALLOC))
02474 {
02475 if (!srel)
02476 {
02477 srel = get_reloc_section (abfd, ia64_info, sec, TRUE);
02478 if (!srel)
02479 return FALSE;
02480 }
02481 if (!count_dyn_reloc (abfd, dyn_i, srel, dynrel_type,
02482 (sec->flags & SEC_READONLY) != 0))
02483 return FALSE;
02484 }
02485 }
02486
02487 return TRUE;
02488 }
02489
02490
02491
02492
02493 static bfd_boolean
02494 allocate_global_data_got (dyn_i, data)
02495 struct elfNN_ia64_dyn_sym_info *dyn_i;
02496 PTR data;
02497 {
02498 struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
02499
02500 if ((dyn_i->want_got || dyn_i->want_gotx)
02501 && ! dyn_i->want_fptr
02502 && elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info, 0))
02503 {
02504 dyn_i->got_offset = x->ofs;
02505 x->ofs += 8;
02506 }
02507 if (dyn_i->want_tprel)
02508 {
02509 dyn_i->tprel_offset = x->ofs;
02510 x->ofs += 8;
02511 }
02512 if (dyn_i->want_dtpmod)
02513 {
02514 if (elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info, 0))
02515 {
02516 dyn_i->dtpmod_offset = x->ofs;
02517 x->ofs += 8;
02518 }
02519 else
02520 {
02521 struct elfNN_ia64_link_hash_table *ia64_info;
02522
02523 ia64_info = elfNN_ia64_hash_table (x->info);
02524 if (ia64_info->self_dtpmod_offset == (bfd_vma) -1)
02525 {
02526 ia64_info->self_dtpmod_offset = x->ofs;
02527 x->ofs += 8;
02528 }
02529 dyn_i->dtpmod_offset = ia64_info->self_dtpmod_offset;
02530 }
02531 }
02532 if (dyn_i->want_dtprel)
02533 {
02534 dyn_i->dtprel_offset = x->ofs;
02535 x->ofs += 8;
02536 }
02537 return TRUE;
02538 }
02539
02540
02541
02542 static bfd_boolean
02543 allocate_global_fptr_got (dyn_i, data)
02544 struct elfNN_ia64_dyn_sym_info *dyn_i;
02545 PTR data;
02546 {
02547 struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
02548
02549 if (dyn_i->want_got
02550 && dyn_i->want_fptr
02551 && elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info, R_IA64_FPTR64LSB))
02552 {
02553 dyn_i->got_offset = x->ofs;
02554 x->ofs += 8;
02555 }
02556 return TRUE;
02557 }
02558
02559
02560
02561 static bfd_boolean
02562 allocate_local_got (dyn_i, data)
02563 struct elfNN_ia64_dyn_sym_info *dyn_i;
02564 PTR data;
02565 {
02566 struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
02567
02568 if ((dyn_i->want_got || dyn_i->want_gotx)
02569 && !elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info, 0))
02570 {
02571 dyn_i->got_offset = x->ofs;
02572 x->ofs += 8;
02573 }
02574 return TRUE;
02575 }
02576
02577
02578
02579 static long
02580 global_sym_index (h)
02581 struct elf_link_hash_entry *h;
02582 {
02583 struct elf_link_hash_entry **p;
02584 bfd *obj;
02585
02586 BFD_ASSERT (h->root.type == bfd_link_hash_defined
02587 || h->root.type == bfd_link_hash_defweak);
02588
02589 obj = h->root.u.def.section->owner;
02590 for (p = elf_sym_hashes (obj); *p != h; ++p)
02591 continue;
02592
02593 return p - elf_sym_hashes (obj) + elf_tdata (obj)->symtab_hdr.sh_info;
02594 }
02595
02596
02597
02598
02599 static bfd_boolean
02600 allocate_fptr (dyn_i, data)
02601 struct elfNN_ia64_dyn_sym_info *dyn_i;
02602 PTR data;
02603 {
02604 struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
02605
02606 if (dyn_i->want_fptr)
02607 {
02608 struct elf_link_hash_entry *h = dyn_i->h;
02609
02610 if (h)
02611 while (h->root.type == bfd_link_hash_indirect
02612 || h->root.type == bfd_link_hash_warning)
02613 h = (struct elf_link_hash_entry *) h->root.u.i.link;
02614
02615 if (!x->info->executable
02616 && (!h
02617 || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
02618 || h->root.type != bfd_link_hash_undefweak))
02619 {
02620 if (h && h->dynindx == -1)
02621 {
02622 BFD_ASSERT ((h->root.type == bfd_link_hash_defined)
02623 || (h->root.type == bfd_link_hash_defweak));
02624
02625 if (!bfd_elf_link_record_local_dynamic_symbol
02626 (x->info, h->root.u.def.section->owner,
02627 global_sym_index (h)))
02628 return FALSE;
02629 }
02630
02631 dyn_i->want_fptr = 0;
02632 }
02633 else if (h == NULL || h->dynindx == -1)
02634 {
02635 dyn_i->fptr_offset = x->ofs;
02636 x->ofs += 16;
02637 }
02638 else
02639 dyn_i->want_fptr = 0;
02640 }
02641 return TRUE;
02642 }
02643
02644
02645
02646 static bfd_boolean
02647 allocate_plt_entries (dyn_i, data)
02648 struct elfNN_ia64_dyn_sym_info *dyn_i;
02649 PTR data;
02650 {
02651 struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
02652
02653 if (dyn_i->want_plt)
02654 {
02655 struct elf_link_hash_entry *h = dyn_i->h;
02656
02657 if (h)
02658 while (h->root.type == bfd_link_hash_indirect
02659 || h->root.type == bfd_link_hash_warning)
02660 h = (struct elf_link_hash_entry *) h->root.u.i.link;
02661
02662
02663 if (elfNN_ia64_dynamic_symbol_p (h, x->info, 0))
02664 {
02665 bfd_size_type offset = x->ofs;
02666 if (offset == 0)
02667 offset = PLT_HEADER_SIZE;
02668 dyn_i->plt_offset = offset;
02669 x->ofs = offset + PLT_MIN_ENTRY_SIZE;
02670
02671 dyn_i->want_pltoff = 1;
02672 }
02673 else
02674 {
02675 dyn_i->want_plt = 0;
02676 dyn_i->want_plt2 = 0;
02677 }
02678 }
02679 return TRUE;
02680 }
02681
02682
02683
02684 static bfd_boolean
02685 allocate_plt2_entries (dyn_i, data)
02686 struct elfNN_ia64_dyn_sym_info *dyn_i;
02687 PTR data;
02688 {
02689 struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
02690
02691 if (dyn_i->want_plt2)
02692 {
02693 struct elf_link_hash_entry *h = dyn_i->h;
02694 bfd_size_type ofs = x->ofs;
02695
02696 dyn_i->plt2_offset = ofs;
02697 x->ofs = ofs + PLT_FULL_ENTRY_SIZE;
02698
02699 while (h->root.type == bfd_link_hash_indirect
02700 || h->root.type == bfd_link_hash_warning)
02701 h = (struct elf_link_hash_entry *) h->root.u.i.link;
02702 dyn_i->h->plt.offset = ofs;
02703 }
02704 return TRUE;
02705 }
02706
02707
02708
02709
02710
02711
02712 static bfd_boolean
02713 allocate_pltoff_entries (dyn_i, data)
02714 struct elfNN_ia64_dyn_sym_info *dyn_i;
02715 PTR data;
02716 {
02717 struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
02718
02719 if (dyn_i->want_pltoff)
02720 {
02721 dyn_i->pltoff_offset = x->ofs;
02722 x->ofs += 16;
02723 }
02724 return TRUE;
02725 }
02726
02727
02728
02729
02730 static bfd_boolean
02731 allocate_dynrel_entries (dyn_i, data)
02732 struct elfNN_ia64_dyn_sym_info *dyn_i;
02733 PTR data;
02734 {
02735 struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
02736 struct elfNN_ia64_link_hash_table *ia64_info;
02737 struct elfNN_ia64_dyn_reloc_entry *rent;
02738 bfd_boolean dynamic_symbol, shared, resolved_zero;
02739
02740 ia64_info = elfNN_ia64_hash_table (x->info);
02741
02742
02743 dynamic_symbol = elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info, 0);
02744
02745 shared = x->info->shared;
02746 resolved_zero = (dyn_i->h
02747 && ELF_ST_VISIBILITY (dyn_i->h->other)
02748 && dyn_i->h->root.type == bfd_link_hash_undefweak);
02749
02750
02751
02752 for (rent = dyn_i->reloc_entries; rent; rent = rent->next)
02753 {
02754 int count = rent->count;
02755
02756 switch (rent->type)
02757 {
02758 case R_IA64_FPTR64LSB:
02759
02760
02761
02762
02763 if (dyn_i->want_fptr && !x->info->pie)
02764 continue;
02765 break;
02766 case R_IA64_PCREL64LSB:
02767 if (!dynamic_symbol)
02768 continue;
02769 break;
02770 case R_IA64_DIR64LSB:
02771 if (!dynamic_symbol && !shared)
02772 continue;
02773 break;
02774 case R_IA64_IPLTLSB:
02775 if (!dynamic_symbol && !shared)
02776 continue;
02777
02778
02779 if (!dynamic_symbol)
02780 count *= 2;
02781 break;
02782 case R_IA64_TPREL64LSB:
02783 case R_IA64_DTPREL64LSB:
02784 case R_IA64_DTPMOD64LSB:
02785 break;
02786 default:
02787 abort ();
02788 }
02789 if (rent->reltext)
02790 ia64_info->reltext = 1;
02791 rent->srel->size += sizeof (ElfNN_External_Rela) * count;
02792 }
02793
02794
02795
02796 if ((!resolved_zero
02797 && (dynamic_symbol || shared)
02798 && (dyn_i->want_got || dyn_i->want_gotx))
02799 || (dyn_i->want_ltoff_fptr
02800 && dyn_i->h
02801 && dyn_i->h->dynindx != -1))
02802 {
02803 if (!dyn_i->want_ltoff_fptr
02804 || !x->info->pie
02805 || dyn_i->h == NULL
02806 || dyn_i->h->root.type != bfd_link_hash_undefweak)
02807 ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela);
02808 }
02809 if ((dynamic_symbol || shared) && dyn_i->want_tprel)
02810 ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela);
02811 if (dynamic_symbol && dyn_i->want_dtpmod)
02812 ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela);
02813 if (dynamic_symbol && dyn_i->want_dtprel)
02814 ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela);
02815 if (ia64_info->rel_fptr_sec && dyn_i->want_fptr)
02816 {
02817 if (dyn_i->h == NULL || dyn_i->h->root.type != bfd_link_hash_undefweak)
02818 ia64_info->rel_fptr_sec->size += sizeof (ElfNN_External_Rela);
02819 }
02820
02821 if (!resolved_zero && dyn_i->want_pltoff)
02822 {
02823 bfd_size_type t = 0;
02824
02825
02826
02827
02828 if (dynamic_symbol)
02829 t = sizeof (ElfNN_External_Rela);
02830 else if (shared)
02831 t = 2 * sizeof (ElfNN_External_Rela);
02832
02833 ia64_info->rel_pltoff_sec->size += t;
02834 }
02835
02836 return TRUE;
02837 }
02838
02839 static bfd_boolean
02840 elfNN_ia64_adjust_dynamic_symbol (info, h)
02841 struct bfd_link_info *info ATTRIBUTE_UNUSED;
02842 struct elf_link_hash_entry *h;
02843 {
02844
02845
02846
02847
02848
02849
02850 if (h->u.weakdef != NULL)
02851 {
02852 BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
02853 || h->u.weakdef->root.type == bfd_link_hash_defweak);
02854 h->root.u.def.section = h->u.weakdef->root.u.def.section;
02855 h->root.u.def.value = h->u.weakdef->root.u.def.value;
02856 return TRUE;
02857 }
02858
02859
02860
02861
02862
02863
02864
02865
02866 return TRUE;
02867 }
02868
02869 static bfd_boolean
02870 elfNN_ia64_size_dynamic_sections (output_bfd, info)
02871 bfd *output_bfd ATTRIBUTE_UNUSED;
02872 struct bfd_link_info *info;
02873 {
02874 struct elfNN_ia64_allocate_data data;
02875 struct elfNN_ia64_link_hash_table *ia64_info;
02876 asection *sec;
02877 bfd *dynobj;
02878 bfd_boolean relplt = FALSE;
02879
02880 dynobj = elf_hash_table(info)->dynobj;
02881 ia64_info = elfNN_ia64_hash_table (info);
02882 ia64_info->self_dtpmod_offset = (bfd_vma) -1;
02883 BFD_ASSERT(dynobj != NULL);
02884 data.info = info;
02885
02886
02887 if (ia64_info->root.dynamic_sections_created
02888 && info->executable)
02889 {
02890 sec = bfd_get_section_by_name (dynobj, ".interp");
02891 BFD_ASSERT (sec != NULL);
02892 sec->contents = (bfd_byte *) ELF_DYNAMIC_INTERPRETER;
02893 sec->size = strlen (ELF_DYNAMIC_INTERPRETER) + 1;
02894 }
02895
02896
02897
02898 if (ia64_info->got_sec)
02899 {
02900 data.ofs = 0;
02901 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_data_got, &data);
02902 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_fptr_got, &data);
02903 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_local_got, &data);
02904 ia64_info->got_sec->size = data.ofs;
02905 }
02906
02907
02908
02909 if (ia64_info->fptr_sec)
02910 {
02911 data.ofs = 0;
02912 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_fptr, &data);
02913 ia64_info->fptr_sec->size = data.ofs;
02914 }
02915
02916
02917
02918
02919
02920
02921 data.ofs = 0;
02922 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_plt_entries, &data);
02923
02924 ia64_info->minplt_entries = 0;
02925 if (data.ofs)
02926 {
02927 ia64_info->minplt_entries
02928 = (data.ofs - PLT_HEADER_SIZE) / PLT_MIN_ENTRY_SIZE;
02929 }
02930
02931
02932 data.ofs = (data.ofs + 31) & (bfd_vma) -32;
02933
02934 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_plt2_entries, &data);
02935 if (data.ofs != 0 || ia64_info->root.dynamic_sections_created)
02936 {
02937
02938
02939
02940
02941 BFD_ASSERT (ia64_info->root.dynamic_sections_created);
02942
02943 ia64_info->plt_sec->size = data.ofs;
02944
02945
02946
02947 sec = bfd_get_section_by_name (dynobj, ".got.plt");
02948 sec->size = 8 * PLT_RESERVED_WORDS;
02949 }
02950
02951
02952
02953 if (ia64_info->pltoff_sec)
02954 {
02955 data.ofs = 0;
02956 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_pltoff_entries, &data);
02957 ia64_info->pltoff_sec->size = data.ofs;
02958 }
02959
02960 if (ia64_info->root.dynamic_sections_created)
02961 {
02962
02963
02964
02965 if (info->shared && ia64_info->self_dtpmod_offset != (bfd_vma) -1)
02966 ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela);
02967 elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_dynrel_entries, &data);
02968 }
02969
02970
02971
02972 for (sec = dynobj->sections; sec != NULL; sec = sec->next)
02973 {
02974 bfd_boolean strip;
02975
02976 if (!(sec->flags & SEC_LINKER_CREATED))
02977 continue;
02978
02979
02980
02981
02982
02983
02984
02985
02986
02987 strip = (sec->size == 0);
02988
02989 if (sec == ia64_info->got_sec)
02990 strip = FALSE;
02991 else if (sec == ia64_info->rel_got_sec)
02992 {
02993 if (strip)
02994 ia64_info->rel_got_sec = NULL;
02995 else
02996
02997
02998 sec->reloc_count = 0;
02999 }
03000 else if (sec == ia64_info->fptr_sec)
03001 {
03002 if (strip)
03003 ia64_info->fptr_sec = NULL;
03004 }
03005 else if (sec == ia64_info->rel_fptr_sec)
03006 {
03007 if (strip)
03008 ia64_info->rel_fptr_sec = NULL;
03009 else
03010
03011
03012 sec->reloc_count = 0;
03013 }
03014 else if (sec == ia64_info->plt_sec)
03015 {
03016 if (strip)
03017 ia64_info->plt_sec = NULL;
03018 }
03019 else if (sec == ia64_info->pltoff_sec)
03020 {
03021 if (strip)
03022 ia64_info->pltoff_sec = NULL;
03023 }
03024 else if (sec == ia64_info->rel_pltoff_sec)
03025 {
03026 if (strip)
03027 ia64_info->rel_pltoff_sec = NULL;
03028 else
03029 {
03030 relplt = TRUE;
03031
03032
03033 sec->reloc_count = 0;
03034 }
03035 }
03036 else
03037 {
03038 const char *name;
03039
03040
03041
03042 name = bfd_get_section_name (dynobj, sec);
03043
03044 if (strcmp (name, ".got.plt") == 0)
03045 strip = FALSE;
03046 else if (strncmp (name, ".rel", 4) == 0)
03047 {
03048 if (!strip)
03049 {
03050
03051
03052 sec->reloc_count = 0;
03053 }
03054 }
03055 else
03056 continue;
03057 }
03058
03059 if (strip)
03060 _bfd_strip_section_from_output (info, sec);
03061 else
03062 {
03063
03064 sec->contents = (bfd_byte *) bfd_zalloc (dynobj, sec->size);
03065 if (sec->contents == NULL && sec->size != 0)
03066 return FALSE;
03067 }
03068 }
03069
03070 if (elf_hash_table (info)->dynamic_sections_created)
03071 {
03072
03073
03074
03075
03076 if (info->executable)
03077 {
03078
03079
03080 #define add_dynamic_entry(TAG, VAL) \
03081 _bfd_elf_add_dynamic_entry (info, TAG, VAL)
03082
03083 if (!add_dynamic_entry (DT_DEBUG, 0))
03084 return FALSE;
03085 }
03086
03087 if (!add_dynamic_entry (DT_IA_64_PLT_RESERVE, 0))
03088 return FALSE;
03089 if (!add_dynamic_entry (DT_PLTGOT, 0))
03090 return FALSE;
03091
03092 if (relplt)
03093 {
03094 if (!add_dynamic_entry (DT_PLTRELSZ, 0)
03095 || !add_dynamic_entry (DT_PLTREL, DT_RELA)
03096 || !add_dynamic_entry (DT_JMPREL, 0))
03097 return FALSE;
03098 }
03099
03100 if (!add_dynamic_entry (DT_RELA, 0)
03101 || !add_dynamic_entry (DT_RELASZ, 0)
03102 || !add_dynamic_entry (DT_RELAENT, sizeof (ElfNN_External_Rela)))
03103 return FALSE;
03104
03105 if (ia64_info->reltext)
03106 {
03107 if (!add_dynamic_entry (DT_TEXTREL, 0))
03108 return FALSE;
03109 info->flags |= DF_TEXTREL;
03110 }
03111 }
03112
03113
03114
03115 return TRUE;
03116 }
03117
03118 static bfd_reloc_status_type
03119 elfNN_ia64_install_value (hit_addr, v, r_type)
03120 bfd_byte *hit_addr;
03121 bfd_vma v;
03122 unsigned int r_type;
03123 {
03124 const struct ia64_operand *op;
03125 int bigendian = 0, shift = 0;
03126 bfd_vma t0, t1, insn, dword;
03127 enum ia64_opnd opnd;
03128 const char *err;
03129 size_t size = 8;
03130 #ifdef BFD_HOST_U_64_BIT
03131 BFD_HOST_U_64_BIT val = (BFD_HOST_U_64_BIT) v;
03132 #else
03133 bfd_vma val = v;
03134 #endif
03135
03136 opnd = IA64_OPND_NIL;
03137 switch (r_type)
03138 {
03139 case R_IA64_NONE:
03140 case R_IA64_LDXMOV:
03141 return bfd_reloc_ok;
03142
03143
03144
03145 case R_IA64_IMM14:
03146 case R_IA64_TPREL14:
03147 case R_IA64_DTPREL14:
03148 opnd = IA64_OPND_IMM14;
03149 break;
03150
03151 case R_IA64_PCREL21F: opnd = IA64_OPND_TGT25; break;
03152 case R_IA64_PCREL21M: opnd = IA64_OPND_TGT25b; break;
03153 case R_IA64_PCREL60B: opnd = IA64_OPND_TGT64; break;
03154 case R_IA64_PCREL21B:
03155 case R_IA64_PCREL21BI:
03156 opnd = IA64_OPND_TGT25c;
03157 break;
03158
03159 case R_IA64_IMM22:
03160 case R_IA64_GPREL22:
03161 case R_IA64_LTOFF22:
03162 case R_IA64_LTOFF22X:
03163 case R_IA64_PLTOFF22:
03164 case R_IA64_PCREL22:
03165 case R_IA64_LTOFF_FPTR22:
03166 case R_IA64_TPREL22:
03167 case R_IA64_DTPREL22:
03168 case R_IA64_LTOFF_TPREL22:
03169 case R_IA64_LTOFF_DTPMOD22:
03170 case R_IA64_LTOFF_DTPREL22:
03171 opnd = IA64_OPND_IMM22;
03172 break;
03173
03174 case R_IA64_IMM64:
03175 case R_IA64_GPREL64I:
03176 case R_IA64_LTOFF64I:
03177 case R_IA64_PLTOFF64I:
03178 case R_IA64_PCREL64I:
03179 case R_IA64_FPTR64I:
03180 case R_IA64_LTOFF_FPTR64I:
03181 case R_IA64_TPREL64I:
03182 case R_IA64_DTPREL64I:
03183 opnd = IA64_OPND_IMMU64;
03184 break;
03185
03186
03187
03188 case R_IA64_DIR32MSB:
03189 case R_IA64_GPREL32MSB:
03190 case R_IA64_FPTR32MSB:
03191 case R_IA64_PCREL32MSB:
03192 case R_IA64_LTOFF_FPTR32MSB:
03193 case R_IA64_SEGREL32MSB:
03194 case R_IA64_SECREL32MSB:
03195 case R_IA64_LTV32MSB:
03196 case R_IA64_DTPREL32MSB:
03197 size = 4; bigendian = 1;
03198 break;
03199
03200 case R_IA64_DIR32LSB:
03201 case R_IA64_GPREL32LSB:
03202 case R_IA64_FPTR32LSB:
03203 case R_IA64_PCREL32LSB:
03204 case R_IA64_LTOFF_FPTR32LSB:
03205 case R_IA64_SEGREL32LSB:
03206 case R_IA64_SECREL32LSB:
03207 case R_IA64_LTV32LSB:
03208 case R_IA64_DTPREL32LSB:
03209 size = 4; bigendian = 0;
03210 break;
03211
03212 case R_IA64_DIR64MSB:
03213 case R_IA64_GPREL64MSB:
03214 case R_IA64_PLTOFF64MSB:
03215 case R_IA64_FPTR64MSB:
03216 case R_IA64_PCREL64MSB:
03217 case R_IA64_LTOFF_FPTR64MSB:
03218 case R_IA64_SEGREL64MSB:
03219 case R_IA64_SECREL64MSB:
03220 case R_IA64_LTV64MSB:
03221 case R_IA64_TPREL64MSB:
03222 case R_IA64_DTPMOD64MSB:
03223 case R_IA64_DTPREL64MSB:
03224 size = 8; bigendian = 1;
03225 break;
03226
03227 case R_IA64_DIR64LSB:
03228 case R_IA64_GPREL64LSB:
03229 case R_IA64_PLTOFF64LSB:
03230 case R_IA64_FPTR64LSB:
03231 case R_IA64_PCREL64LSB:
03232 case R_IA64_LTOFF_FPTR64LSB:
03233 case R_IA64_SEGREL64LSB:
03234 case R_IA64_SECREL64LSB:
03235 case R_IA64_LTV64LSB:
03236 case R_IA64_TPREL64LSB:
03237 case R_IA64_DTPMOD64LSB:
03238 case R_IA64_DTPREL64LSB:
03239 size = 8; bigendian = 0;
03240 break;
03241
03242
03243 default:
03244 return bfd_reloc_notsupported;
03245 }
03246
03247 switch (opnd)
03248 {
03249 case IA64_OPND_IMMU64:
03250 hit_addr -= (long) hit_addr & 0x3;
03251 t0 = bfd_getl64 (hit_addr);
03252 t1 = bfd_getl64 (hit_addr + 8);
03253
03254
03255
03256
03257
03258
03259
03260 t0 &= ~(0x3ffffLL << 46);
03261 t1 &= ~(0x7fffffLL
03262 | (( (0x07fLL << 13) | (0x1ffLL << 27)
03263 | (0x01fLL << 22) | (0x001LL << 21)
03264 | (0x001LL << 36)) << 23));
03265
03266 t0 |= ((val >> 22) & 0x03ffffLL) << 46;
03267 t1 |= ((val >> 40) & 0x7fffffLL) << 0;
03268 t1 |= ( (((val >> 0) & 0x07f) << 13)
03269 | (((val >> 7) & 0x1ff) << 27)
03270 | (((val >> 16) & 0x01f) << 22)
03271 | (((val >> 21) & 0x001) << 21)
03272 | (((val >> 63) & 0x001) << 36)) << 23;
03273
03274 bfd_putl64 (t0, hit_addr);
03275 bfd_putl64 (t1, hit_addr + 8);
03276 break;
03277
03278 case IA64_OPND_TGT64:
03279 hit_addr -= (long) hit_addr & 0x3;
03280 t0 = bfd_getl64 (hit_addr);
03281 t1 = bfd_getl64 (hit_addr + 8);
03282
03283
03284
03285
03286
03287
03288
03289 t0 &= ~(0x3ffffLL << 46);
03290 t1 &= ~(0x7fffffLL
03291 | ((1LL << 36 | 0xfffffLL << 13) << 23));
03292
03293 val >>= 4;
03294 t0 |= ((val >> 20) & 0xffffLL) << 2 << 46;
03295 t1 |= ((val >> 36) & 0x7fffffLL) << 0;
03296 t1 |= ((((val >> 0) & 0xfffffLL) << 13)
03297 | (((val >> 59) & 0x1LL) << 36)) << 23;
03298
03299 bfd_putl64 (t0, hit_addr);
03300 bfd_putl64 (t1, hit_addr + 8);
03301 break;
03302
03303 default:
03304 switch ((long) hit_addr & 0x3)
03305 {
03306 case 0: shift = 5; break;
03307 case 1: shift = 14; hit_addr += 3; break;
03308 case 2: shift = 23; hit_addr += 6; break;
03309 case 3: return bfd_reloc_notsupported;
03310 }
03311 dword = bfd_getl64 (hit_addr);
03312 insn = (dword >> shift) & 0x1ffffffffffLL;
03313
03314 op = elf64_ia64_operands + opnd;
03315 err = (*op->insert) (op, val, (ia64_insn *)& insn);
03316 if (err)
03317 return bfd_reloc_overflow;
03318
03319 dword &= ~(0x1ffffffffffLL << shift);
03320 dword |= (insn << shift);
03321 bfd_putl64 (dword, hit_addr);
03322 break;
03323
03324 case IA64_OPND_NIL:
03325
03326 if (bigendian)
03327 if (size == 4)
03328 bfd_putb32 (val, hit_addr);
03329 else
03330 bfd_putb64 (val, hit_addr);
03331 else
03332 if (size == 4)
03333 bfd_putl32 (val, hit_addr);
03334 else
03335 bfd_putl64 (val, hit_addr);
03336 break;
03337 }
03338
03339 return bfd_reloc_ok;
03340 }
03341
03342 static void
03343 elfNN_ia64_install_dyn_reloc (abfd, info, sec, srel, offset, type,
03344 dynindx, addend)
03345 bfd *abfd;
03346 struct bfd_link_info *info;
03347 asection *sec;
03348 asection *srel;
03349 bfd_vma offset;
03350 unsigned int type;
03351 long dynindx;
03352 bfd_vma addend;
03353 {
03354 Elf_Internal_Rela outrel;
03355 bfd_byte *loc;
03356
03357 BFD_ASSERT (dynindx != -1);
03358 outrel.r_info = ELFNN_R_INFO (dynindx, type);
03359 outrel.r_addend = addend;
03360 outrel.r_offset = _bfd_elf_section_offset (abfd, info, sec, offset);
03361 if (outrel.r_offset >= (bfd_vma) -2)
03362 {
03363
03364
03365 outrel.r_info = ELFNN_R_INFO (0, R_IA64_NONE);
03366 outrel.r_addend = 0;
03367 outrel.r_offset = 0;
03368 }
03369 else
03370 outrel.r_offset += sec->output_section->vma + sec->output_offset;
03371
03372 loc = srel->contents;
03373 loc += srel->reloc_count++ * sizeof (ElfNN_External_Rela);
03374 bfd_elfNN_swap_reloca_out (abfd, &outrel, loc);
03375 BFD_ASSERT (sizeof (ElfNN_External_Rela) * srel->reloc_count <= srel->size);
03376 }
03377
03378
03379
03380
03381 static bfd_vma
03382 set_got_entry (abfd, info, dyn_i, dynindx, addend, value, dyn_r_type)
03383 bfd *abfd;
03384 struct bfd_link_info *info;
03385 struct elfNN_ia64_dyn_sym_info *dyn_i;
03386 long dynindx;
03387 bfd_vma addend;
03388 bfd_vma value;
03389 unsigned int dyn_r_type;
03390 {
03391 struct elfNN_ia64_link_hash_table *ia64_info;
03392 asection *got_sec;
03393 bfd_boolean done;
03394 bfd_vma got_offset;
03395
03396 ia64_info = elfNN_ia64_hash_table (info);
03397 got_sec = ia64_info->got_sec;
03398
03399 switch (dyn_r_type)
03400 {
03401 case R_IA64_TPREL64LSB:
03402 done = dyn_i->tprel_done;
03403 dyn_i->tprel_done = TRUE;
03404 got_offset = dyn_i->tprel_offset;
03405 break;
03406 case R_IA64_DTPMOD64LSB:
03407 if (dyn_i->dtpmod_offset != ia64_info->self_dtpmod_offset)
03408 {
03409 done = dyn_i->dtpmod_done;
03410 dyn_i->dtpmod_done = TRUE;
03411 }
03412 else
03413 {
03414 done = ia64_info->self_dtpmod_done;
03415 ia64_info->self_dtpmod_done = TRUE;
03416 dynindx = 0;
03417 }
03418 got_offset = dyn_i->dtpmod_offset;
03419 break;
03420 case R_IA64_DTPREL64LSB:
03421 done = dyn_i->dtprel_done;
03422 dyn_i->dtprel_done = TRUE;
03423 got_offset = dyn_i->dtprel_offset;
03424 break;
03425 default:
03426 done = dyn_i->got_done;
03427 dyn_i->got_done = TRUE;
03428 got_offset = dyn_i->got_offset;
03429 break;
03430 }
03431
03432 BFD_ASSERT ((got_offset & 7) == 0);
03433
03434 if (! done)
03435 {
03436
03437 bfd_put_64 (abfd, value, got_sec->contents + got_offset);
03438
03439
03440 if (((info->shared
03441 && (!dyn_i->h
03442 || ELF_ST_VISIBILITY (dyn_i->h->other) == STV_DEFAULT
03443 || dyn_i->h->root.type != bfd_link_hash_undefweak)
03444 && dyn_r_type != R_IA64_DTPREL64LSB)
03445 || elfNN_ia64_dynamic_symbol_p (dyn_i->h, info, dyn_r_type)
03446 || (dynindx != -1 && dyn_r_type == R_IA64_FPTR64LSB))
03447 && (!dyn_i->want_ltoff_fptr
03448 || !info->pie
03449 || !dyn_i->h
03450 || dyn_i->h->root.type != bfd_link_hash_undefweak))
03451 {
03452 if (dynindx == -1
03453 && dyn_r_type != R_IA64_TPREL64LSB
03454 && dyn_r_type != R_IA64_DTPMOD64LSB
03455 && dyn_r_type != R_IA64_DTPREL64LSB)
03456 {
03457 dyn_r_type = R_IA64_REL64LSB;
03458 dynindx = 0;
03459 addend = value;
03460 }
03461
03462 if (bfd_big_endian (abfd))
03463 {
03464 switch (dyn_r_type)
03465 {
03466 case R_IA64_REL64LSB:
03467 dyn_r_type = R_IA64_REL64MSB;
03468 break;
03469 case R_IA64_DIR64LSB:
03470 dyn_r_type = R_IA64_DIR64MSB;
03471 break;
03472 case R_IA64_FPTR64LSB:
03473 dyn_r_type = R_IA64_FPTR64MSB;
03474 break;
03475 case R_IA64_TPREL64LSB:
03476 dyn_r_type = R_IA64_TPREL64MSB;
03477 break;
03478 case R_IA64_DTPMOD64LSB:
03479 dyn_r_type = R_IA64_DTPMOD64MSB;
03480 break;
03481 case R_IA64_DTPREL64LSB:
03482 dyn_r_type = R_IA64_DTPREL64MSB;
03483 break;
03484 default:
03485 BFD_ASSERT (FALSE);
03486 break;
03487 }
03488 }
03489
03490 elfNN_ia64_install_dyn_reloc (abfd, NULL, got_sec,
03491 ia64_info->rel_got_sec,
03492 got_offset, dyn_r_type,
03493 dynindx, addend);
03494 }
03495 }
03496
03497
03498 value = (got_sec->output_section->vma
03499 + got_sec->output_offset
03500 + got_offset);
03501
03502 return value;
03503 }
03504
03505
03506
03507
03508 static bfd_vma
03509 set_fptr_entry (abfd, info, dyn_i, value)
03510 bfd *abfd;
03511 struct bfd_link_info *info;
03512 struct elfNN_ia64_dyn_sym_info *dyn_i;
03513 bfd_vma value;
03514 {
03515 struct elfNN_ia64_link_hash_table *ia64_info;
03516 asection *fptr_sec;
03517
03518 ia64_info = elfNN_ia64_hash_table (info);
03519 fptr_sec = ia64_info->fptr_sec;
03520
03521 if (!dyn_i->fptr_done)
03522 {
03523 dyn_i->fptr_done = 1;
03524
03525
03526 bfd_put_64 (abfd, value, fptr_sec->contents + dyn_i->fptr_offset);
03527 bfd_put_64 (abfd, _bfd_get_gp_value (abfd),
03528 fptr_sec->contents + dyn_i->fptr_offset + 8);
03529 if (ia64_info->rel_fptr_sec)
03530 {
03531 Elf_Internal_Rela outrel;
03532 bfd_byte *loc;
03533
03534 if (bfd_little_endian (abfd))
03535 outrel.r_info = ELFNN_R_INFO (0, R_IA64_IPLTLSB);
03536 else
03537 outrel.r_info = ELFNN_R_INFO (0, R_IA64_IPLTMSB);
03538 outrel.r_addend = value;
03539 outrel.r_offset = (fptr_sec->output_section->vma
03540 + fptr_sec->output_offset
03541 + dyn_i->fptr_offset);
03542 loc = ia64_info->rel_fptr_sec->contents;
03543 loc += ia64_info->rel_fptr_sec->reloc_count++
03544 * sizeof (ElfNN_External_Rela);
03545 bfd_elfNN_swap_reloca_out (abfd, &outrel, loc);
03546 }
03547 }
03548
03549
03550 value = (fptr_sec->output_section->vma
03551 + fptr_sec->output_offset
03552 + dyn_i->fptr_offset);
03553
03554 return value;
03555 }
03556
03557
03558
03559
03560 static bfd_vma
03561 set_pltoff_entry (abfd, info, dyn_i, value, is_plt)
03562 bfd *abfd;
03563 struct bfd_link_info *info;
03564 struct elfNN_ia64_dyn_sym_info *dyn_i;
03565 bfd_vma value;
03566 bfd_boolean is_plt;
03567 {
03568 struct elfNN_ia64_link_hash_table *ia64_info;
03569 asection *pltoff_sec;
03570
03571 ia64_info = elfNN_ia64_hash_table (info);
03572 pltoff_sec = ia64_info->pltoff_sec;
03573
03574
03575
03576 if ((! dyn_i->want_plt || is_plt)
03577 && !dyn_i->pltoff_done)
03578 {
03579 bfd_vma gp = _bfd_get_gp_value (abfd);
03580
03581
03582 bfd_put_64 (abfd, value, pltoff_sec->contents + dyn_i->pltoff_offset);
03583 bfd_put_64 (abfd, gp, pltoff_sec->contents + dyn_i->pltoff_offset + 8);
03584
03585
03586 if (!is_plt
03587 && info->shared
03588 && (!dyn_i->h
03589 || ELF_ST_VISIBILITY (dyn_i->h->other) == STV_DEFAULT
03590 || dyn_i->h->root.type != bfd_link_hash_undefweak))
03591 {
03592 unsigned int dyn_r_type;
03593
03594 if (bfd_big_endian (abfd))
03595 dyn_r_type = R_IA64_REL64MSB;
03596 else
03597 dyn_r_type = R_IA64_REL64LSB;
03598
03599 elfNN_ia64_install_dyn_reloc (abfd, NULL, pltoff_sec,
03600 ia64_info->rel_pltoff_sec,
03601 dyn_i->pltoff_offset,
03602 dyn_r_type, 0, value);
03603 elfNN_ia64_install_dyn_reloc (abfd, NULL, pltoff_sec,
03604 ia64_info->rel_pltoff_sec,
03605 dyn_i->pltoff_offset + 8,
03606 dyn_r_type, 0, gp);
03607 }
03608
03609 dyn_i->pltoff_done = 1;
03610 }
03611
03612
03613 value = (pltoff_sec->output_section->vma
03614 + pltoff_sec->output_offset
03615 + dyn_i->pltoff_offset);
03616
03617 return value;
03618 }
03619
03620
03621
03622
03623
03624
03625 static bfd_vma
03626 elfNN_ia64_tprel_base (info)
03627 struct bfd_link_info *info;
03628 {
03629 asection *tls_sec = elf_hash_table (info)->tls_sec;
03630
03631 BFD_ASSERT (tls_sec != NULL);
03632 return tls_sec->vma - align_power ((bfd_vma) 16, tls_sec->alignment_power);
03633 }
03634
03635
03636
03637
03638
03639 static bfd_vma
03640 elfNN_ia64_dtprel_base (info)
03641 struct bfd_link_info *info;
03642 {
03643 BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
03644 return elf_hash_table (info)->tls_sec->vma;
03645 }
03646
03647
03648
03649
03650
03651 static bfd *elfNN_ia64_unwind_entry_compare_bfd;
03652
03653 static int
03654 elfNN_ia64_unwind_entry_compare (a, b)
03655 const PTR a;
03656 const PTR b;
03657 {
03658 bfd_vma av, bv;
03659
03660 av = bfd_get_64 (elfNN_ia64_unwind_entry_compare_bfd, a);
03661 bv = bfd_get_64 (elfNN_ia64_unwind_entry_compare_bfd, b);
03662
03663 return (av < bv ? -1 : av > bv ? 1 : 0);
03664 }
03665
03666
03667 static bfd_boolean
03668 elfNN_ia64_choose_gp (abfd, info)
03669 bfd *abfd;
03670 struct bfd_link_info *info;
03671 {
03672 bfd_vma min_vma = (bfd_vma) -1, max_vma = 0;
03673 bfd_vma min_short_vma = min_vma, max_short_vma = 0;
03674 struct elf_link_hash_entry *gp;
03675 bfd_vma gp_val;
03676 asection *os;
03677 struct elfNN_ia64_link_hash_table *ia64_info;
03678
03679 ia64_info = elfNN_ia64_hash_table (info);
03680
03681
03682
03683 for (os = abfd->sections; os ; os = os->next)
03684 {
03685 bfd_vma lo, hi;
03686
03687 if ((os->flags & SEC_ALLOC) == 0)
03688 continue;
03689
03690 lo = os->vma;
03691 hi = os->vma + os->size;
03692 if (hi < lo)
03693 hi = (bfd_vma) -1;
03694
03695 if (min_vma > lo)
03696 min_vma = lo;
03697 if (max_vma < hi)
03698 max_vma = hi;
03699 if (os->flags & SEC_SMALL_DATA)
03700 {
03701 if (min_short_vma > lo)
03702 min_short_vma = lo;
03703 if (max_short_vma < hi)
03704 max_short_vma = hi;
03705 }
03706 }
03707
03708
03709 gp = elf_link_hash_lookup (elf_hash_table (info), "__gp", FALSE,
03710 FALSE, FALSE);
03711
03712 if (gp
03713 && (gp->root.type == bfd_link_hash_defined
03714 || gp->root.type == bfd_link_hash_defweak))
03715 {
03716 asection *gp_sec = gp->root.u.def.section;
03717 gp_val = (gp->root.u.def.value
03718 + gp_sec->output_section->vma
03719 + gp_sec->output_offset);
03720 }
03721 else
03722 {
03723
03724
03725 asection *got_sec = ia64_info->got_sec;
03726
03727
03728 if (got_sec)
03729 gp_val = got_sec->output_section->vma;
03730 else if (max_short_vma != 0)
03731 gp_val = min_short_vma;
03732 else
03733 gp_val = min_vma;
03734
03735
03736
03737 if (max_vma - min_vma < 0x400000
03738 && max_vma - gp_val <= 0x200000
03739 && gp_val - min_vma > 0x200000)
03740 gp_val = min_vma + 0x200000;
03741 else if (max_short_vma != 0)
03742 {
03743
03744 if (max_short_vma - gp_val >= 0x200000)
03745 gp_val = min_short_vma + 0x200000;
03746
03747
03748 if (gp_val > max_vma)
03749 gp_val = max_vma - 0x200000 + 8;
03750 }
03751 }
03752
03753
03754
03755
03756 if (max_short_vma != 0)
03757 {
03758 if (max_short_vma - min_short_vma >= 0x400000)
03759 {
03760 (*_bfd_error_handler)
03761 (_("%s: short data segment overflowed (0x%lx >= 0x400000)"),
03762 bfd_get_filename (abfd),
03763 (unsigned long) (max_short_vma - min_short_vma));
03764 return FALSE;
03765 }
03766 else if ((gp_val > min_short_vma
03767 && gp_val - min_short_vma > 0x200000)
03768 || (gp_val < max_short_vma
03769 && max_short_vma - gp_val >= 0x200000))
03770 {
03771 (*_bfd_error_handler)
03772 (_("%s: __gp does not cover short data segment"),
03773 bfd_get_filename (abfd));
03774 return FALSE;
03775 }
03776 }
03777
03778 _bfd_set_gp_value (abfd, gp_val);
03779
03780 return TRUE;
03781 }
03782
03783 static bfd_boolean
03784 elfNN_ia64_final_link (abfd, info)
03785 bfd *abfd;
03786 struct bfd_link_info *info;
03787 {
03788 struct elfNN_ia64_link_hash_table *ia64_info;
03789 asection *unwind_output_sec;
03790
03791 ia64_info = elfNN_ia64_hash_table (info);
03792
03793
03794 if (!info->relocatable)
03795 {
03796 bfd_vma gp_val = _bfd_get_gp_value (abfd);
03797 struct elf_link_hash_entry *gp;
03798
03799 if (gp_val == 0)
03800 {
03801 if (! elfNN_ia64_choose_gp (abfd, info))
03802 return FALSE;
03803 gp_val = _bfd_get_gp_value (abfd);
03804 }
03805
03806 gp = elf_link_hash_lookup (elf_hash_table (info), "__gp", FALSE,
03807 FALSE, FALSE);
03808 if (gp)
03809 {
03810 gp->root.type = bfd_link_hash_defined;
03811 gp->root.u.def.value = gp_val;
03812 gp->root.u.def.section = bfd_abs_section_ptr;
03813 }
03814 }
03815
03816
03817
03818
03819 unwind_output_sec = NULL;
03820 if (!info->relocatable)
03821 {
03822 asection *s = bfd_get_section_by_name (abfd, ELF_STRING_ia64_unwind);
03823 if (s)
03824 {
03825 unwind_output_sec = s->output_section;
03826 unwind_output_sec->contents
03827 = bfd_malloc (unwind_output_sec->size);
03828 if (unwind_output_sec->contents == NULL)
03829 return FALSE;
03830 }
03831 }
03832
03833
03834 if (!bfd_elf_final_link (abfd, info))
03835 return FALSE;
03836
03837 if (unwind_output_sec)
03838 {
03839 elfNN_ia64_unwind_entry_compare_bfd = abfd;
03840 qsort (unwind_output_sec->contents,
03841 (size_t) (unwind_output_sec->size / 24),
03842 24,
03843 elfNN_ia64_unwind_entry_compare);
03844
03845 if (! bfd_set_section_contents (abfd, unwind_output_sec,
03846 unwind_output_sec->contents, (bfd_vma) 0,
03847 unwind_output_sec->size))
03848 return FALSE;
03849 }
03850
03851 return TRUE;
03852 }
03853
03854 static bfd_boolean
03855 elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
03856 contents, relocs, local_syms, local_sections)
03857 bfd *output_bfd;
03858 struct bfd_link_info *info;
03859 bfd *input_bfd;
03860 asection *input_section;
03861 bfd_byte *contents;
03862 Elf_Internal_Rela *relocs;
03863 Elf_Internal_Sym *local_syms;
03864 asection **local_sections;
03865 {
03866 struct elfNN_ia64_link_hash_table *ia64_info;
03867 Elf_Internal_Shdr *symtab_hdr;
03868 Elf_Internal_Rela *rel;
03869 Elf_Internal_Rela *relend;
03870 asection *srel;
03871 bfd_boolean ret_val = TRUE;
03872 bfd_vma gp_val;
03873
03874 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
03875 ia64_info = elfNN_ia64_hash_table (info);
03876
03877
03878 if (info->relocatable)
03879 {
03880 bfd_vma flags;
03881
03882 flags = elf_section_data(input_section)->this_hdr.sh_flags;
03883 flags &= SHF_IA_64_NORECOV;
03884
03885 elf_section_data(input_section->output_section)
03886 ->this_hdr.sh_flags |= flags;
03887 return TRUE;
03888 }
03889
03890 gp_val = _bfd_get_gp_value (output_bfd);
03891 srel = get_reloc_section (input_bfd, ia64_info, input_section, FALSE);
03892
03893 rel = relocs;
03894 relend = relocs + input_section->reloc_count;
03895 for (; rel < relend; ++rel)
03896 {
03897 struct elf_link_hash_entry *h;
03898 struct elfNN_ia64_dyn_sym_info *dyn_i;
03899 bfd_reloc_status_type r;
03900 reloc_howto_type *howto;
03901 unsigned long r_symndx;
03902 Elf_Internal_Sym *sym;
03903 unsigned int r_type;
03904 bfd_vma value;
03905 asection *sym_sec;
03906 bfd_byte *hit_addr;
03907 bfd_boolean dynamic_symbol_p;
03908 bfd_boolean undef_weak_ref;
03909
03910 r_type = ELFNN_R_TYPE (rel->r_info);
03911 if (r_type > R_IA64_MAX_RELOC_CODE)
03912 {
03913 (*_bfd_error_handler)
03914 (_("%B: unknown relocation type %d"),
03915 input_bfd, (int) r_type);
03916 bfd_set_error (bfd_error_bad_value);
03917 ret_val = FALSE;
03918 continue;
03919 }
03920
03921 howto = lookup_howto (r_type);
03922 r_symndx = ELFNN_R_SYM (rel->r_info);
03923 h = NULL;
03924 sym = NULL;
03925 sym_sec = NULL;
03926 undef_weak_ref = FALSE;
03927
03928 if (r_symndx < symtab_hdr->sh_info)
03929 {
03930
03931 asection *msec;
03932 sym = local_syms + r_symndx;
03933 sym_sec = local_sections[r_symndx];
03934 msec = sym_sec;
03935 value = _bfd_elf_rela_local_sym (output_bfd, sym, &msec, rel);
03936 if ((sym_sec->flags & SEC_MERGE)
03937 && ELF_ST_TYPE (sym->st_info) == STT_SECTION
03938 && sym_sec->sec_info_type == ELF_INFO_TYPE_MERGE)
03939 {
03940 struct elfNN_ia64_local_hash_entry *loc_h;
03941
03942 loc_h = get_local_sym_hash (ia64_info, input_bfd, rel, FALSE);
03943 if (loc_h && ! loc_h->sec_merge_done)
03944 {
03945 struct elfNN_ia64_dyn_sym_info *dynent;
03946
03947 for (dynent = loc_h->info; dynent; dynent = dynent->next)
03948 {
03949 msec = sym_sec;
03950 dynent->addend =
03951 _bfd_merged_section_offset (output_bfd, &msec,
03952 elf_section_data (msec)->
03953 sec_info,
03954 sym->st_value
03955 + dynent->addend);
03956 dynent->addend -= sym->st_value;
03957 dynent->addend += msec->output_section->vma
03958 + msec->output_offset
03959 - sym_sec->output_section->vma
03960 - sym_sec->output_offset;
03961 }
03962 loc_h->sec_merge_done = 1;
03963 }
03964 }
03965 }
03966 else
03967 {
03968 bfd_boolean unresolved_reloc;
03969 bfd_boolean warned;
03970 struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
03971
03972 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
03973 r_symndx, symtab_hdr, sym_hashes,
03974 h, sym_sec, value,
03975 unresolved_reloc, warned);
03976
03977 if (h->root.type == bfd_link_hash_undefweak)
03978 undef_weak_ref = TRUE;
03979 else if (warned)
03980 continue;
03981 }
03982
03983 hit_addr = contents + rel->r_offset;
03984 value += rel->r_addend;
03985 dynamic_symbol_p = elfNN_ia64_dynamic_symbol_p (h, info, r_type);
03986
03987 switch (r_type)
03988 {
03989 case R_IA64_NONE:
03990 case R_IA64_LDXMOV:
03991 continue;
03992
03993 case R_IA64_IMM14:
03994 case R_IA64_IMM22:
03995 case R_IA64_IMM64:
03996 case R_IA64_DIR32MSB:
03997 case R_IA64_DIR32LSB:
03998 case R_IA64_DIR64MSB:
03999 case R_IA64_DIR64LSB:
04000
04001 if ((dynamic_symbol_p || info->shared)
04002 && r_symndx != 0
04003 && (input_section->flags & SEC_ALLOC) != 0)
04004 {
04005 unsigned int dyn_r_type;
04006 long dynindx;
04007 bfd_vma addend;
04008
04009 BFD_ASSERT (srel != NULL);
04010
04011 switch (r_type)
04012 {
04013 case R_IA64_IMM14:
04014 case R_IA64_IMM22:
04015 case R_IA64_IMM64:
04016
04017
04018 (*_bfd_error_handler)
04019 (_("%B: non-pic code with imm relocation against dynamic symbol `%s'"),
04020 input_bfd,
04021 h->root.root.string);
04022 ret_val = FALSE;
04023 continue;
04024
04025 default:
04026 break;
04027 }
04028
04029
04030
04031 dyn_r_type = r_type;
04032 if (dynamic_symbol_p)
04033 {
04034 dynindx = h->dynindx;
04035 addend = rel->r_addend;
04036 value = 0;
04037 }
04038 else
04039 {
04040 switch (r_type)
04041 {
04042 case R_IA64_DIR32MSB:
04043 dyn_r_type = R_IA64_REL32MSB;
04044 break;
04045 case R_IA64_DIR32LSB:
04046 dyn_r_type = R_IA64_REL32LSB;
04047 break;
04048 case R_IA64_DIR64MSB:
04049 dyn_r_type = R_IA64_REL64MSB;
04050 break;
04051 case R_IA64_DIR64LSB:
04052 dyn_r_type = R_IA64_REL64LSB;
04053 break;
04054
04055 default:
04056 break;
04057 }
04058 dynindx = 0;
04059 addend = value;
04060 }
04061
04062 elfNN_ia64_install_dyn_reloc (output_bfd, info, input_section,
04063 srel, rel->r_offset, dyn_r_type,
04064 dynindx, addend);
04065 }
04066
04067
04068 case R_IA64_LTV32MSB:
04069 case R_IA64_LTV32LSB:
04070 case R_IA64_LTV64MSB:
04071 case R_IA64_LTV64LSB:
04072 r = elfNN_ia64_install_value (hit_addr, value, r_type);
04073 break;
04074
04075 case R_IA64_GPREL22:
04076 case R_IA64_GPREL64I:
04077 case R_IA64_GPREL32MSB:
04078 case R_IA64_GPREL32LSB:
04079 case R_IA64_GPREL64MSB:
04080 case R_IA64_GPREL64LSB:
04081 if (dynamic_symbol_p)
04082 {
04083 (*_bfd_error_handler)
04084 (_("%B: @gprel relocation against dynamic symbol %s"),
04085 input_bfd, h->root.root.string);
04086 ret_val = FALSE;
04087 continue;
04088 }
04089 value -= gp_val;
04090 r = elfNN_ia64_install_value (hit_addr, value, r_type);
04091 break;
04092
04093 case R_IA64_LTOFF22:
04094 case R_IA64_LTOFF22X:
04095 case R_IA64_LTOFF64I:
04096 dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
04097 value = set_got_entry (input_bfd, info, dyn_i, (h ? h->dynindx : -1),
04098 rel->r_addend, value, R_IA64_DIR64LSB);
04099 value -= gp_val;
04100 r = elfNN_ia64_install_value (hit_addr, value, r_type);
04101 break;
04102
04103 case R_IA64_PLTOFF22:
04104 case R_IA64_PLTOFF64I:
04105 case R_IA64_PLTOFF64MSB:
04106 case R_IA64_PLTOFF64LSB:
04107 dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
04108 value = set_pltoff_entry (output_bfd, info, dyn_i, value, FALSE);
04109 value -= gp_val;
04110 r = elfNN_ia64_install_value (hit_addr, value, r_type);
04111 break;
04112
04113 case R_IA64_FPTR64I:
04114 case R_IA64_FPTR32MSB:
04115 case R_IA64_FPTR32LSB:
04116 case R_IA64_FPTR64MSB:
04117 case R_IA64_FPTR64LSB:
04118 dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
04119 if (dyn_i->want_fptr)
04120 {
04121 if (!undef_weak_ref)
04122 value = set_fptr_entry (output_bfd, info, dyn_i, value);
04123 }
04124 if (!dyn_i->want_fptr || info->pie)
04125 {
04126 long dynindx;
04127 unsigned int dyn_r_type = r_type;
04128 bfd_vma addend = rel->r_addend;
04129
04130
04131
04132
04133 if (dyn_i->want_fptr)
04134 {
04135 if (r_type == R_IA64_FPTR64I)
04136 {
04137
04138
04139
04140
04141
04142
04143 (*_bfd_error_handler)
04144 (_("%B: linking non-pic code in a position independent executable"),
04145 input_bfd);
04146 ret_val = FALSE;
04147 continue;
04148 }
04149 dynindx = 0;
04150 addend = value;
04151 dyn_r_type = r_type + R_IA64_REL64LSB - R_IA64_FPTR64LSB;
04152 }
04153 else if (h)
04154 {
04155 if (h->dynindx != -1)
04156 dynindx = h->dynindx;
04157 else
04158 dynindx = (_bfd_elf_link_lookup_local_dynindx
04159 (info, h->root.u.def.section->owner,
04160 global_sym_index (h)));
04161 value = 0;
04162 }
04163 else
04164 {
04165 dynindx = (_bfd_elf_link_lookup_local_dynindx
04166 (info, input_bfd, (long) r_symndx));
04167 value = 0;
04168 }
04169
04170 elfNN_ia64_install_dyn_reloc (output_bfd, info, input_section,
04171 srel, rel->r_offset, dyn_r_type,
04172 dynindx, addend);
04173 }
04174
04175 r = elfNN_ia64_install_value (hit_addr, value, r_type);
04176 break;
04177
04178 case R_IA64_LTOFF_FPTR22:
04179 case R_IA64_LTOFF_FPTR64I:
04180 case R_IA64_LTOFF_FPTR32MSB:
04181 case R_IA64_LTOFF_FPTR32LSB:
04182 case R_IA64_LTOFF_FPTR64MSB:
04183 case R_IA64_LTOFF_FPTR64LSB:
04184 {
04185 long dynindx;
04186
04187 dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
04188 if (dyn_i->want_fptr)
04189 {
04190 BFD_ASSERT (h == NULL || h->dynindx == -1);
04191 if (!undef_weak_ref)
04192 value = set_fptr_entry (output_bfd, info, dyn_i, value);
04193 dynindx = -1;
04194 }
04195 else
04196 {
04197
04198
04199 if (h)
04200 {
04201 if (h->dynindx != -1)
04202 dynindx = h->dynindx;
04203 else
04204 dynindx = (_bfd_elf_link_lookup_local_dynindx
04205 (info, h->root.u.def.section->owner,
04206 global_sym_index (h)));
04207 }
04208 else
04209 dynindx = (_bfd_elf_link_lookup_local_dynindx
04210 (info, input_bfd, (long) r_symndx));
04211 value = 0;
04212 }
04213
04214 value = set_got_entry (output_bfd, info, dyn_i, dynindx,
04215 rel->r_addend, value, R_IA64_FPTR64LSB);
04216 value -= gp_val;
04217 r = elfNN_ia64_install_value (hit_addr, value, r_type);
04218 }
04219 break;
04220
04221 case R_IA64_PCREL32MSB:
04222 case R_IA64_PCREL32LSB:
04223 case R_IA64_PCREL64MSB:
04224 case R_IA64_PCREL64LSB:
04225
04226 if (dynamic_symbol_p && r_symndx != 0)
04227 {
04228 BFD_ASSERT (srel != NULL);
04229
04230 elfNN_ia64_install_dyn_reloc (output_bfd, info, input_section,
04231 srel, rel->r_offset, r_type,
04232 h->dynindx, rel->r_addend);
04233 }
04234 goto finish_pcrel;
04235
04236 case R_IA64_PCREL21B:
04237 case R_IA64_PCREL60B:
04238
04239 dyn_i = NULL;
04240 if (h)
04241 dyn_i = get_dyn_sym_info (ia64_info, h, NULL, NULL, FALSE);
04242
04243 if (dyn_i && dyn_i->want_plt2)
04244 {
04245
04246 BFD_ASSERT (rel->r_addend == 0);
04247
04248 value = (ia64_info->plt_sec->output_section->vma
04249 + ia64_info->plt_sec->output_offset
04250 + dyn_i->plt2_offset);
04251 }
04252 else
04253 {
04254
04255
04256 BFD_ASSERT (undef_weak_ref || sym_sec->output_section != NULL);
04257
04258
04259
04260
04261
04262 if (undef_weak_ref)
04263 continue;
04264 }
04265 goto finish_pcrel;
04266
04267 case R_IA64_PCREL21BI:
04268 case R_IA64_PCREL21F:
04269 case R_IA64_PCREL21M:
04270 case R_IA64_PCREL22:
04271 case R_IA64_PCREL64I:
04272
04273
04274
04275
04276 if (dynamic_symbol_p)
04277 {
04278 const char *msg;
04279
04280 if (r_type == R_IA64_PCREL21BI)
04281 msg = _("%B: @internal branch to dynamic symbol %s");
04282 else if (r_type == R_IA64_PCREL21F || r_type == R_IA64_PCREL21M)
04283 msg = _("%B: speculation fixup to dynamic symbol %s");
04284 else
04285 msg = _("%B: @pcrel relocation against dynamic symbol %s");
04286 (*_bfd_error_handler) (msg, input_bfd, h->root.root.string);
04287 ret_val = FALSE;
04288 continue;
04289 }
04290 goto finish_pcrel;
04291
04292 finish_pcrel:
04293
04294 value -= (input_section->output_section->vma
04295 + input_section->output_offset
04296 + rel->r_offset) & ~ (bfd_vma) 0x3;
04297 r = elfNN_ia64_install_value (hit_addr, value, r_type);
04298 break;
04299
04300 case R_IA64_SEGREL32MSB:
04301 case R_IA64_SEGREL32LSB:
04302 case R_IA64_SEGREL64MSB:
04303 case R_IA64_SEGREL64LSB:
04304 if (r_symndx == 0)
04305 {
04306
04307
04308 r = bfd_reloc_ok;
04309 }
04310 else
04311 {
04312 struct elf_segment_map *m;
04313 Elf_Internal_Phdr *p;
04314
04315
04316 for (m = elf_tdata (output_bfd)->segment_map,
04317 p = elf_tdata (output_bfd)->phdr;
04318 m != NULL;
04319 m = m->next, p++)
04320 {
04321 int i;
04322 for (i = m->count - 1; i >= 0; i--)
04323 if (m->sections[i] == input_section->output_section)
04324 break;
04325 if (i >= 0)
04326 break;
04327 }
04328
04329 if (m == NULL)
04330 {
04331 r = bfd_reloc_notsupported;
04332 }
04333 else
04334 {
04335
04336
04337 if (value > p->p_vaddr)
04338 value -= p->p_vaddr;
04339 else
04340 value = 0;
04341 r = elfNN_ia64_install_value (hit_addr, value, r_type);
04342 }
04343 break;
04344 }
04345
04346 case R_IA64_SECREL32MSB:
04347 case R_IA64_SECREL32LSB:
04348 case R_IA64_SECREL64MSB:
04349 case R_IA64_SECREL64LSB:
04350
04351
04352 if (sym_sec)
04353 value -= sym_sec->output_section->vma;
04354 r = elfNN_ia64_install_value (hit_addr, value, r_type);
04355 break;
04356
04357 case R_IA64_IPLTMSB:
04358 case R_IA64_IPLTLSB:
04359
04360 if ((dynamic_symbol_p || info->shared)
04361 && (input_section->flags & SEC_ALLOC) != 0)
04362 {
04363 BFD_ASSERT (srel != NULL);
04364
04365
04366
04367 if (!dynamic_symbol_p)
04368 {
04369 unsigned int dyn_r_type;
04370
04371 if (r_type == R_IA64_IPLTMSB)
04372 dyn_r_type = R_IA64_REL64MSB;
04373 else
04374 dyn_r_type = R_IA64_REL64LSB;
04375
04376 elfNN_ia64_install_dyn_reloc (output_bfd, info,
04377 input_section,
04378 srel, rel->r_offset,
04379 dyn_r_type, 0, value);
04380 elfNN_ia64_install_dyn_reloc (output_bfd, info,
04381 input_section,
04382 srel, rel->r_offset + 8,
04383 dyn_r_type, 0, gp_val);
04384 }
04385 else
04386 elfNN_ia64_install_dyn_reloc (output_bfd, info, input_section,
04387 srel, rel->r_offset, r_type,
04388 h->dynindx, rel->r_addend);
04389 }
04390
04391 if (r_type == R_IA64_IPLTMSB)
04392 r_type = R_IA64_DIR64MSB;
04393 else
04394 r_type = R_IA64_DIR64LSB;
04395 elfNN_ia64_install_value (hit_addr, value, r_type);
04396 r = elfNN_ia64_install_value (hit_addr + 8, gp_val, r_type);
04397 break;
04398
04399 case R_IA64_TPREL14:
04400 case R_IA64_TPREL22:
04401 case R_IA64_TPREL64I:
04402 value -= elfNN_ia64_tprel_base (info);
04403 r = elfNN_ia64_install_value (hit_addr, value, r_type);
04404 break;
04405
04406 case R_IA64_DTPREL14:
04407 case R_IA64_DTPREL22:
04408 case R_IA64_DTPREL64I:
04409 case R_IA64_DTPREL64LSB:
04410 case R_IA64_DTPREL64MSB:
04411 value -= elfNN_ia64_dtprel_base (info);
04412 r = elfNN_ia64_install_value (hit_addr, value, r_type);
04413 break;
04414
04415 case R_IA64_LTOFF_TPREL22:
04416 case R_IA64_LTOFF_DTPMOD22:
04417 case R_IA64_LTOFF_DTPREL22:
04418 {
04419 int got_r_type;
04420 long dynindx = h ? h->dynindx : -1;
04421 bfd_vma r_addend = rel->r_addend;
04422
04423 switch (r_type)
04424 {
04425 default:
04426 case R_IA64_LTOFF_TPREL22:
04427 if (!dynamic_symbol_p)
04428 {
04429 if (!info->shared)
04430 value -= elfNN_ia64_tprel_base (info);
04431 else
04432 {
04433 r_addend += value - elfNN_ia64_dtprel_base (info);
04434 dynindx = 0;
04435 }
04436 }
04437 got_r_type = R_IA64_TPREL64LSB;
04438 break;
04439 case R_IA64_LTOFF_DTPMOD22:
04440 if (!dynamic_symbol_p && !info->shared)
04441 value = 1;
04442 got_r_type = R_IA64_DTPMOD64LSB;
04443 break;
04444 case R_IA64_LTOFF_DTPREL22:
04445 if (!dynamic_symbol_p)
04446 value -= elfNN_ia64_dtprel_base (info);
04447 got_r_type = R_IA64_DTPREL64LSB;
04448 break;
04449 }
04450 dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
04451 value = set_got_entry (input_bfd, info, dyn_i, dynindx, r_addend,
04452 value, got_r_type);
04453 value -= gp_val;
04454 r = elfNN_ia64_install_value (hit_addr, value, r_type);
04455 }
04456 break;
04457
04458 default:
04459 r = bfd_reloc_notsupported;
04460 break;
04461 }
04462
04463 switch (r)
04464 {
04465 case bfd_reloc_ok:
04466 break;
04467
04468 case bfd_reloc_undefined:
04469
04470
04471
04472 (*info->callbacks->undefined_symbol)
04473 (info, "__gp", input_bfd, input_section, rel->r_offset, 1);
04474 return FALSE;
04475
04476 case bfd_reloc_notsupported:
04477 {
04478 const char *name;
04479
04480 if (h)
04481 name = h->root.root.string;
04482 else
04483 {
04484 name = bfd_elf_string_from_elf_section (input_bfd,
04485 symtab_hdr->sh_link,
04486 sym->st_name);
04487 if (name == NULL)
04488 return FALSE;
04489 if (*name == '\0')
04490 name = bfd_section_name (input_bfd, input_section);
04491 }
04492 if (!(*info->callbacks->warning) (info, _("unsupported reloc"),
04493 name, input_bfd,
04494 input_section, rel->r_offset))
04495 return FALSE;
04496 ret_val = FALSE;
04497 }
04498 break;
04499
04500 case bfd_reloc_dangerous:
04501 case bfd_reloc_outofrange:
04502 case bfd_reloc_overflow:
04503 default:
04504 {
04505 const char *name;
04506
04507 if (h)
04508 name = NULL;
04509 else
04510 {
04511 name = bfd_elf_string_from_elf_section (input_bfd,
04512 symtab_hdr->sh_link,
04513 sym->st_name);
04514 if (name == NULL)
04515 return FALSE;
04516 if (*name == '\0')
04517 name = bfd_section_name (input_bfd, sym_sec);
04518 }
04519
04520 switch (r_type)
04521 {
04522 case R_IA64_PCREL21B:
04523 case R_IA64_PCREL21BI:
04524 case R_IA64_PCREL21M:
04525 case R_IA64_PCREL21F:
04526 if (is_elf_hash_table (info->hash))
04527 {
04528
04529
04530
04531 (*_bfd_error_handler)
04532 (_("%B: Can't relax br (%s) to `%s' at 0x%lx in section `%A' with size 0x%lx (> 0x1000000)."),
04533 input_bfd, input_section, howto->name, name,
04534 rel->r_offset, input_section->size);
04535 break;
04536 }
04537 default:
04538 if (!(*info->callbacks->reloc_overflow) (info,
04539 &h->root,
04540 name,
04541 howto->name,
04542 (bfd_vma) 0,
04543 input_bfd,
04544 input_section,
04545 rel->r_offset))
04546 return FALSE;
04547 break;
04548 }
04549
04550 ret_val = FALSE;
04551 }
04552 break;
04553 }
04554 }
04555
04556 return ret_val;
04557 }
04558
04559 static bfd_boolean
04560 elfNN_ia64_finish_dynamic_symbol (output_bfd, info, h, sym)
04561 bfd *output_bfd;
04562 struct bfd_link_info *info;
04563 struct elf_link_hash_entry *h;
04564 Elf_Internal_Sym *sym;
04565 {
04566 struct elfNN_ia64_link_hash_table *ia64_info;
04567 struct elfNN_ia64_dyn_sym_info *dyn_i;
04568
04569 ia64_info = elfNN_ia64_hash_table (info);
04570 dyn_i = get_dyn_sym_info (ia64_info, h, NULL, NULL, FALSE);
04571
04572
04573 if (dyn_i && dyn_i->want_plt)
04574 {
04575 Elf_Internal_Rela outrel;
04576 bfd_byte *loc;
04577 asection *plt_sec;
04578 bfd_vma plt_addr, pltoff_addr, gp_val, index;
04579
04580 gp_val = _bfd_get_gp_value (output_bfd);
04581
04582
04583
04584 index = (dyn_i->plt_offset - PLT_HEADER_SIZE) / PLT_MIN_ENTRY_SIZE;
04585 plt_sec = ia64_info->plt_sec;
04586 loc = plt_sec->contents + dyn_i->plt_offset;
04587
04588 memcpy (loc, plt_min_entry, PLT_MIN_ENTRY_SIZE);
04589 elfNN_ia64_install_value (loc, index, R_IA64_IMM22);
04590 elfNN_ia64_install_value (loc+2, -dyn_i->plt_offset, R_IA64_PCREL21B);
04591
04592 plt_addr = (plt_sec->output_section->vma
04593 + plt_sec->output_offset
04594 + dyn_i->plt_offset);
04595 pltoff_addr = set_pltoff_entry (output_bfd, info, dyn_i, plt_addr, TRUE);
04596
04597
04598 if (dyn_i->want_plt2)
04599 {
04600 loc = plt_sec->contents + dyn_i->plt2_offset;
04601
04602 memcpy (loc, plt_full_entry, PLT_FULL_ENTRY_SIZE);
04603 elfNN_ia64_install_value (loc, pltoff_addr - gp_val, R_IA64_IMM22);
04604
04605
04606
04607
04608
04609 if (!h->def_regular)
04610 sym->st_shndx = SHN_UNDEF;
04611 }
04612
04613
04614 outrel.r_offset = pltoff_addr;
04615 if (bfd_little_endian (output_bfd))
04616 outrel.r_info = ELFNN_R_INFO (h->dynindx, R_IA64_IPLTLSB);
04617 else
04618 outrel.r_info = ELFNN_R_INFO (h->dynindx, R_IA64_IPLTMSB);
04619 outrel.r_addend = 0;
04620
04621
04622
04623
04624
04625
04626
04627
04628
04629
04630
04631
04632
04633 loc = ia64_info->rel_pltoff_sec->contents;
04634 loc += ((ia64_info->rel_pltoff_sec->reloc_count + index)
04635 * sizeof (ElfNN_External_Rela));
04636 bfd_elfNN_swap_reloca_out (output_bfd, &outrel, loc);
04637 }
04638
04639
04640 if (strcmp (h->root.root.string, "_DYNAMIC") == 0
04641 || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0
04642 || strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0)
04643 sym->st_shndx = SHN_ABS;
04644
04645 return TRUE;
04646 }
04647
04648 static bfd_boolean
04649 elfNN_ia64_finish_dynamic_sections (abfd, info)
04650 bfd *abfd;
04651 struct bfd_link_info *info;
04652 {
04653 struct elfNN_ia64_link_hash_table *ia64_info;
04654 bfd *dynobj;
04655
04656 ia64_info = elfNN_ia64_hash_table (info);
04657 dynobj = ia64_info->root.dynobj;
04658
04659 if (elf_hash_table (info)->dynamic_sections_created)
04660 {
04661 ElfNN_External_Dyn *dyncon, *dynconend;
04662 asection *sdyn, *sgotplt;
04663 bfd_vma gp_val;
04664
04665 sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
04666 sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
04667 BFD_ASSERT (sdyn != NULL);
04668 dyncon = (ElfNN_External_Dyn *) sdyn->contents;
04669 dynconend = (ElfNN_External_Dyn *) (sdyn->contents + sdyn->size);
04670
04671 gp_val = _bfd_get_gp_value (abfd);
04672
04673 for (; dyncon < dynconend; dyncon++)
04674 {
04675 Elf_Internal_Dyn dyn;
04676
04677 bfd_elfNN_swap_dyn_in (dynobj, dyncon, &dyn);
04678
04679 switch (dyn.d_tag)
04680 {
04681 case DT_PLTGOT:
04682 dyn.d_un.d_ptr = gp_val;
04683 break;
04684
04685 case DT_PLTRELSZ:
04686 dyn.d_un.d_val = (ia64_info->minplt_entries
04687 * sizeof (ElfNN_External_Rela));
04688 break;
04689
04690 case DT_JMPREL:
04691
04692 dyn.d_un.d_ptr = (ia64_info->rel_pltoff_sec->output_section->vma
04693 + ia64_info->rel_pltoff_sec->output_offset
04694 + (ia64_info->rel_pltoff_sec->reloc_count
04695 * sizeof (ElfNN_External_Rela)));
04696 break;
04697
04698 case DT_IA_64_PLT_RESERVE:
04699 dyn.d_un.d_ptr = (sgotplt->output_section->vma
04700 + sgotplt->output_offset);
04701 break;
04702
04703 case DT_RELASZ:
04704
04705
04706 dyn.d_un.d_val -= (ia64_info->minplt_entries
04707 * sizeof (ElfNN_External_Rela));
04708 break;
04709 }
04710
04711 bfd_elfNN_swap_dyn_out (abfd, &dyn, dyncon);
04712 }
04713
04714
04715 if (ia64_info->plt_sec)
04716 {
04717 bfd_byte *loc = ia64_info->plt_sec->contents;
04718 bfd_vma pltres;
04719
04720 memcpy (loc, plt_header, PLT_HEADER_SIZE);
04721
04722 pltres = (sgotplt->output_section->vma
04723 + sgotplt->output_offset
04724 - gp_val);
04725
04726 elfNN_ia64_install_value (loc+1, pltres, R_IA64_GPREL22);
04727 }
04728 }
04729
04730 return TRUE;
04731 }
04732
04733
04734
04735
04736 static bfd_boolean
04737 elfNN_ia64_set_private_flags (abfd, flags)
04738 bfd *abfd;
04739 flagword flags;
04740 {
04741 BFD_ASSERT (!elf_flags_init (abfd)
04742 || elf_elfheader (abfd)->e_flags == flags);
04743
04744 elf_elfheader (abfd)->e_flags = flags;
04745 elf_flags_init (abfd) = TRUE;
04746 return TRUE;
04747 }
04748
04749
04750
04751 static bfd_boolean
04752 elfNN_ia64_merge_private_bfd_data (ibfd, obfd)
04753 bfd *ibfd, *obfd;
04754 {
04755 flagword out_flags;
04756 flagword in_flags;
04757 bfd_boolean ok = TRUE;
04758
04759
04760 if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
04761 || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
04762 return FALSE;
04763
04764 in_flags = elf_elfheader (ibfd)->e_flags;
04765 out_flags = elf_elfheader (obfd)->e_flags;
04766
04767 if (! elf_flags_init (obfd))
04768 {
04769 elf_flags_init (obfd) = TRUE;
04770 elf_elfheader (obfd)->e_flags = in_flags;
04771
04772 if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
04773 && bfd_get_arch_info (obfd)->the_default)
04774 {
04775 return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
04776 bfd_get_mach (ibfd));
04777 }
04778
04779 return TRUE;
04780 }
04781
04782
04783 if (in_flags == out_flags)
04784 return TRUE;
04785
04786
04787 if (!(in_flags & EF_IA_64_REDUCEDFP) && (out_flags & EF_IA_64_REDUCEDFP))
04788 elf_elfheader (obfd)->e_flags &= ~EF_IA_64_REDUCEDFP;
04789
04790 if ((in_flags & EF_IA_64_TRAPNIL) != (out_flags & EF_IA_64_TRAPNIL))
04791 {
04792 (*_bfd_error_handler)
04793 (_("%B: linking trap-on-NULL-dereference with non-trapping files"),
04794 ibfd);
04795
04796 bfd_set_error (bfd_error_bad_value);
04797 ok = FALSE;
04798 }
04799 if ((in_flags & EF_IA_64_BE) != (out_flags & EF_IA_64_BE))
04800 {
04801 (*_bfd_error_handler)
04802 (_("%B: linking big-endian files with little-endian files"),
04803 ibfd);
04804
04805 bfd_set_error (bfd_error_bad_value);
04806 ok = FALSE;
04807 }
04808 if ((in_flags & EF_IA_64_ABI64) != (out_flags & EF_IA_64_ABI64))
04809 {
04810 (*_bfd_error_handler)
04811 (_("%B: linking 64-bit files with 32-bit files"),
04812 ibfd);
04813
04814 bfd_set_error (bfd_error_bad_value);
04815 ok = FALSE;
04816 }
04817 if ((in_flags & EF_IA_64_CONS_GP) != (out_flags & EF_IA_64_CONS_GP))
04818 {
04819 (*_bfd_error_handler)
04820 (_("%B: linking constant-gp files with non-constant-gp files"),
04821 ibfd);
04822
04823 bfd_set_error (bfd_error_bad_value);
04824 ok = FALSE;
04825 }
04826 if ((in_flags & EF_IA_64_NOFUNCDESC_CONS_GP)
04827 != (out_flags & EF_IA_64_NOFUNCDESC_CONS_GP))
04828 {
04829 (*_bfd_error_handler)
04830 (_("%B: linking auto-pic files with non-auto-pic files"),
04831 ibfd);
04832
04833 bfd_set_error (bfd_error_bad_value);
04834 ok = FALSE;
04835 }
04836
04837 return ok;
04838 }
04839
04840 static bfd_boolean
04841 elfNN_ia64_print_private_bfd_data (abfd, ptr)
04842 bfd *abfd;
04843 PTR ptr;
04844 {
04845 FILE *file = (FILE *) ptr;
04846 flagword flags = elf_elfheader (abfd)->e_flags;
04847
04848 BFD_ASSERT (abfd != NULL && ptr != NULL);
04849
04850 fprintf (file, "private flags = %s%s%s%s%s%s%s%s\n",
04851 (flags & EF_IA_64_TRAPNIL) ? "TRAPNIL, " : "",
04852 (flags & EF_IA_64_EXT) ? "EXT, " : "",
04853 (flags & EF_IA_64_BE) ? "BE, " : "LE, ",
04854 (flags & EF_IA_64_REDUCEDFP) ? "REDUCEDFP, " : "",
04855 (flags & EF_IA_64_CONS_GP) ? "CONS_GP, " : "",
04856 (flags & EF_IA_64_NOFUNCDESC_CONS_GP) ? "NOFUNCDESC_CONS_GP, " : "",
04857 (flags & EF_IA_64_ABSOLUTE) ? "ABSOLUTE, " : "",
04858 (flags & EF_IA_64_ABI64) ? "ABI64" : "ABI32");
04859
04860 _bfd_elf_print_private_bfd_data (abfd, ptr);
04861 return TRUE;
04862 }
04863
04864 static enum elf_reloc_type_class
04865 elfNN_ia64_reloc_type_class (rela)
04866 const Elf_Internal_Rela *rela;
04867 {
04868 switch ((int) ELFNN_R_TYPE (rela->r_info))
04869 {
04870 case R_IA64_REL32MSB:
04871 case R_IA64_REL32LSB:
04872 case R_IA64_REL64MSB:
04873 case R_IA64_REL64LSB:
04874 return reloc_class_relative;
04875 case R_IA64_IPLTMSB:
04876 case R_IA64_IPLTLSB:
04877 return reloc_class_plt;
04878 case R_IA64_COPY:
04879 return reloc_class_copy;
04880 default:
04881 return reloc_class_normal;
04882 }
04883 }
04884
04885 static struct bfd_elf_special_section const elfNN_ia64_special_sections[]=
04886 {
04887 { ".sbss", 5, -1, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_IA_64_SHORT },
04888 { ".sdata", 6, -1, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_IA_64_SHORT },
04889 { NULL, 0, 0, 0, 0 }
04890 };
04891
04892 static bfd_boolean
04893 elfNN_ia64_hpux_vec (const bfd_target *vec)
04894 {
04895 extern const bfd_target bfd_elfNN_ia64_hpux_big_vec;
04896 return (vec == & bfd_elfNN_ia64_hpux_big_vec);
04897 }
04898
04899 static void
04900 elfNN_hpux_post_process_headers (abfd, info)
04901 bfd *abfd;
04902 struct bfd_link_info *info ATTRIBUTE_UNUSED;
04903 {
04904 Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd);
04905
04906 i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_HPUX;
04907 i_ehdrp->e_ident[EI_ABIVERSION] = 1;
04908 }
04909
04910 bfd_boolean
04911 elfNN_hpux_backend_section_from_bfd_section (abfd, sec, retval)
04912 bfd *abfd ATTRIBUTE_UNUSED;
04913 asection *sec;
04914 int *retval;
04915 {
04916 if (bfd_is_com_section (sec))
04917 {
04918 *retval = SHN_IA_64_ANSI_COMMON;
04919 return TRUE;
04920 }
04921 return FALSE;
04922 }
04923
04924 static void
04925 elfNN_hpux_backend_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
04926 asymbol *asym)
04927 {
04928 elf_symbol_type *elfsym = (elf_symbol_type *) asym;;
04929
04930 switch (elfsym->internal_elf_sym.st_shndx)
04931 {
04932 case SHN_IA_64_ANSI_COMMON:
04933 asym->section = bfd_com_section_ptr;
04934 asym->value = elfsym->internal_elf_sym.st_size;
04935 asym->flags &= ~BSF_GLOBAL;
04936 break;
04937 }
04938 }
04939
04940
04941 #define TARGET_LITTLE_SYM bfd_elfNN_ia64_little_vec
04942 #define TARGET_LITTLE_NAME "elfNN-ia64-little"
04943 #define TARGET_BIG_SYM bfd_elfNN_ia64_big_vec
04944 #define TARGET_BIG_NAME "elfNN-ia64-big"
04945 #define ELF_ARCH bfd_arch_ia64
04946 #define ELF_MACHINE_CODE EM_IA_64
04947 #define ELF_MACHINE_ALT1 1999
04948 #define ELF_MACHINE_ALT2 1998
04949 #define ELF_MAXPAGESIZE 0x10000
04950
04951 #define elf_backend_section_from_shdr \
04952 elfNN_ia64_section_from_shdr
04953 #define elf_backend_section_flags \
04954 elfNN_ia64_section_flags
04955 #define elf_backend_fake_sections \
04956 elfNN_ia64_fake_sections
04957 #define elf_backend_final_write_processing \
04958 elfNN_ia64_final_write_processing
04959 #define elf_backend_add_symbol_hook \
04960 elfNN_ia64_add_symbol_hook
04961 #define elf_backend_additional_program_headers \
04962 elfNN_ia64_additional_program_headers
04963 #define elf_backend_modify_segment_map \
04964 elfNN_ia64_modify_segment_map
04965 #define elf_info_to_howto \
04966 elfNN_ia64_info_to_howto
04967
04968 #define bfd_elfNN_bfd_reloc_type_lookup \
04969 elfNN_ia64_reloc_type_lookup
04970 #define bfd_elfNN_bfd_is_local_label_name \
04971 elfNN_ia64_is_local_label_name
04972 #define bfd_elfNN_bfd_relax_section \
04973 elfNN_ia64_relax_section
04974
04975
04976 #define bfd_elfNN_bfd_link_hash_table_create \
04977 elfNN_ia64_hash_table_create
04978 #define bfd_elfNN_bfd_link_hash_table_free \
04979 elfNN_ia64_hash_table_free
04980 #define elf_backend_create_dynamic_sections \
04981 elfNN_ia64_create_dynamic_sections
04982 #define elf_backend_check_relocs \
04983 elfNN_ia64_check_relocs
04984 #define elf_backend_adjust_dynamic_symbol \
04985 elfNN_ia64_adjust_dynamic_symbol
04986 #define elf_backend_size_dynamic_sections \
04987 elfNN_ia64_size_dynamic_sections
04988 #define elf_backend_relocate_section \
04989 elfNN_ia64_relocate_section
04990 #define elf_backend_finish_dynamic_symbol \
04991 elfNN_ia64_finish_dynamic_symbol
04992 #define elf_backend_finish_dynamic_sections \
04993 elfNN_ia64_finish_dynamic_sections
04994 #define bfd_elfNN_bfd_final_link \
04995 elfNN_ia64_final_link
04996
04997 #define bfd_elfNN_bfd_merge_private_bfd_data \
04998 elfNN_ia64_merge_private_bfd_data
04999 #define bfd_elfNN_bfd_set_private_flags \
05000 elfNN_ia64_set_private_flags
05001 #define bfd_elfNN_bfd_print_private_bfd_data \
05002 elfNN_ia64_print_private_bfd_data
05003
05004 #define elf_backend_plt_readonly 1
05005 #define elf_backend_want_plt_sym 0
05006 #define elf_backend_plt_alignment 5
05007 #define elf_backend_got_header_size 0
05008 #define elf_backend_want_got_plt 1
05009 #define elf_backend_may_use_rel_p 1
05010 #define elf_backend_may_use_rela_p 1
05011 #define elf_backend_default_use_rela_p 1
05012 #define elf_backend_want_dynbss 0
05013 #define elf_backend_copy_indirect_symbol elfNN_ia64_hash_copy_indirect
05014 #define elf_backend_hide_symbol elfNN_ia64_hash_hide_symbol
05015 #define elf_backend_reloc_type_class elfNN_ia64_reloc_type_class
05016 #define elf_backend_rela_normal 1
05017 #define elf_backend_special_sections elfNN_ia64_special_sections
05018
05019
05020
05021
05022
05023
05024 #define elf_backend_link_order_error_handler NULL
05025
05026 #include "elfNN-target.h"
05027
05028
05029
05030 #undef TARGET_LITTLE_SYM
05031 #undef TARGET_LITTLE_NAME
05032 #undef TARGET_BIG_SYM
05033 #define TARGET_BIG_SYM bfd_elfNN_ia64_hpux_big_vec
05034 #undef TARGET_BIG_NAME
05035 #define TARGET_BIG_NAME "elfNN-ia64-hpux-big"
05036
05037
05038
05039 #undef elf_backend_post_process_headers
05040 #define elf_backend_post_process_headers elfNN_hpux_post_process_headers
05041
05042 #undef elf_backend_section_from_bfd_section
05043 #define elf_backend_section_from_bfd_section elfNN_hpux_backend_section_from_bfd_section
05044
05045 #undef elf_backend_symbol_processing
05046 #define elf_backend_symbol_processing elfNN_hpux_backend_symbol_processing
05047
05048 #undef elf_backend_want_p_paddr_set_to_zero
05049 #define elf_backend_want_p_paddr_set_to_zero 1
05050
05051 #undef ELF_MAXPAGESIZE
05052 #define ELF_MAXPAGESIZE 0x1000
05053
05054 #undef elfNN_bed
05055 #define elfNN_bed elfNN_ia64_hpux_bed
05056
05057 #include "elfNN-target.h"
05058
05059 #undef elf_backend_want_p_paddr_set_to_zero