X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=bfd%2Felfxx-ia64.c;h=d662c7498cc0cf2bf507e10e0eec2eadad20927e;hb=78bc95e3ba62e558030ff978725cdbbb48564f96;hp=6b3257afdf133e75858c64d4c5b99628b7d26c58;hpb=01f0fe5e0450edf168c1f612feb93cf588e4e7ea;p=binutils-gdb.git diff --git a/bfd/elfxx-ia64.c b/bfd/elfxx-ia64.c index 6b3257afdf1..d662c7498cc 100644 --- a/bfd/elfxx-ia64.c +++ b/bfd/elfxx-ia64.c @@ -1,5 +1,5 @@ /* IA-64 support for 64-bit ELF - Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. Contributed by David Mosberger-Tang @@ -7,7 +7,7 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -17,10 +17,11 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ -#include "bfd.h" #include "sysdep.h" +#include "bfd.h" #include "libbfd.h" #include "elf-bfd.h" #include "opcode/ia64.h" @@ -189,176 +190,45 @@ struct elfNN_ia64_allocate_data #define elfNN_ia64_hash_table(p) \ ((struct elfNN_ia64_link_hash_table *) ((p)->hash)) -static bfd_reloc_status_type elfNN_ia64_reloc - PARAMS ((bfd *abfd, arelent *reloc, asymbol *sym, PTR data, - asection *input_section, bfd *output_bfd, char **error_message)); -static reloc_howto_type * lookup_howto - PARAMS ((unsigned int rtype)); -static reloc_howto_type *elfNN_ia64_reloc_type_lookup - PARAMS ((bfd *abfd, bfd_reloc_code_real_type bfd_code)); -static void elfNN_ia64_info_to_howto - PARAMS ((bfd *abfd, arelent *bfd_reloc, Elf_Internal_Rela *elf_reloc)); -static bfd_boolean elfNN_ia64_relax_section - PARAMS((bfd *abfd, asection *sec, struct bfd_link_info *link_info, - bfd_boolean *again)); -static void elfNN_ia64_relax_ldxmov - PARAMS((bfd_byte *contents, bfd_vma off)); -static bfd_boolean is_unwind_section_name - PARAMS ((bfd *abfd, const char *)); -static bfd_boolean elfNN_ia64_section_flags - PARAMS ((flagword *, const Elf_Internal_Shdr *)); -static bfd_boolean elfNN_ia64_fake_sections - PARAMS ((bfd *abfd, Elf_Internal_Shdr *hdr, asection *sec)); -static void elfNN_ia64_final_write_processing - PARAMS ((bfd *abfd, bfd_boolean linker)); -static bfd_boolean elfNN_ia64_add_symbol_hook - PARAMS ((bfd *abfd, struct bfd_link_info *info, Elf_Internal_Sym *sym, - const char **namep, flagword *flagsp, asection **secp, - bfd_vma *valp)); -static int elfNN_ia64_additional_program_headers - PARAMS ((bfd *abfd)); -static bfd_boolean elfNN_ia64_modify_segment_map - PARAMS ((bfd *, struct bfd_link_info *)); -static bfd_boolean elfNN_ia64_is_local_label_name - PARAMS ((bfd *abfd, const char *name)); +static struct elfNN_ia64_dyn_sym_info * get_dyn_sym_info + (struct elfNN_ia64_link_hash_table *ia64_info, + struct elf_link_hash_entry *h, + bfd *abfd, const Elf_Internal_Rela *rel, bfd_boolean create); static bfd_boolean elfNN_ia64_dynamic_symbol_p - PARAMS ((struct elf_link_hash_entry *h, struct bfd_link_info *info, int)); -static struct bfd_hash_entry *elfNN_ia64_new_elf_hash_entry - PARAMS ((struct bfd_hash_entry *entry, struct bfd_hash_table *table, - const char *string)); -static void elfNN_ia64_hash_copy_indirect - PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *, - struct elf_link_hash_entry *)); -static void elfNN_ia64_hash_hide_symbol - PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *, bfd_boolean)); -static hashval_t elfNN_ia64_local_htab_hash PARAMS ((const void *)); -static int elfNN_ia64_local_htab_eq PARAMS ((const void *ptr1, - const void *ptr2)); -static struct bfd_link_hash_table *elfNN_ia64_hash_table_create - PARAMS ((bfd *abfd)); -static void elfNN_ia64_hash_table_free - PARAMS ((struct bfd_link_hash_table *hash)); -static bfd_boolean elfNN_ia64_global_dyn_sym_thunk - PARAMS ((struct bfd_hash_entry *, PTR)); -static int elfNN_ia64_local_dyn_sym_thunk - PARAMS ((void **, PTR)); + (struct elf_link_hash_entry *h, struct bfd_link_info *info, int); +static bfd_reloc_status_type elfNN_ia64_install_value + (bfd_byte *hit_addr, bfd_vma val, unsigned int r_type); +static bfd_boolean elfNN_ia64_choose_gp + (bfd *abfd, struct bfd_link_info *info); +static void elfNN_ia64_relax_ldxmov + (bfd_byte *contents, bfd_vma off); static void elfNN_ia64_dyn_sym_traverse - PARAMS ((struct elfNN_ia64_link_hash_table *ia64_info, - bfd_boolean (*func) (struct elfNN_ia64_dyn_sym_info *, PTR), - PTR info)); -static bfd_boolean elfNN_ia64_create_dynamic_sections - PARAMS ((bfd *abfd, struct bfd_link_info *info)); -static struct elfNN_ia64_local_hash_entry * get_local_sym_hash - PARAMS ((struct elfNN_ia64_link_hash_table *ia64_info, - bfd *abfd, const Elf_Internal_Rela *rel, bfd_boolean create)); -static struct elfNN_ia64_dyn_sym_info * get_dyn_sym_info - PARAMS ((struct elfNN_ia64_link_hash_table *ia64_info, - struct elf_link_hash_entry *h, - bfd *abfd, const Elf_Internal_Rela *rel, bfd_boolean create)); -static asection *get_got - PARAMS ((bfd *abfd, struct bfd_link_info *info, - struct elfNN_ia64_link_hash_table *ia64_info)); -static asection *get_fptr - PARAMS ((bfd *abfd, struct bfd_link_info *info, - struct elfNN_ia64_link_hash_table *ia64_info)); -static asection *get_pltoff - PARAMS ((bfd *abfd, struct bfd_link_info *info, - struct elfNN_ia64_link_hash_table *ia64_info)); -static asection *get_reloc_section - PARAMS ((bfd *abfd, struct elfNN_ia64_link_hash_table *ia64_info, - asection *sec, bfd_boolean create)); -static bfd_boolean elfNN_ia64_check_relocs - PARAMS ((bfd *abfd, struct bfd_link_info *info, asection *sec, - const Elf_Internal_Rela *relocs)); -static bfd_boolean elfNN_ia64_adjust_dynamic_symbol - PARAMS ((struct bfd_link_info *info, struct elf_link_hash_entry *h)); -static long global_sym_index - PARAMS ((struct elf_link_hash_entry *h)); -static bfd_boolean allocate_fptr - PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data)); + (struct elfNN_ia64_link_hash_table *ia64_info, + bfd_boolean (*func) (struct elfNN_ia64_dyn_sym_info *, PTR), + PTR info); static bfd_boolean allocate_global_data_got - PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data)); + (struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data); static bfd_boolean allocate_global_fptr_got - PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data)); + (struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data); static bfd_boolean allocate_local_got - PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data)); -static bfd_boolean allocate_pltoff_entries - PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data)); -static bfd_boolean allocate_plt_entries - PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data)); -static bfd_boolean allocate_plt2_entries - PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data)); -static bfd_boolean allocate_dynrel_entries - PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data)); -static bfd_boolean elfNN_ia64_size_dynamic_sections - PARAMS ((bfd *output_bfd, struct bfd_link_info *info)); -static bfd_reloc_status_type elfNN_ia64_install_value - PARAMS ((bfd_byte *hit_addr, bfd_vma val, unsigned int r_type)); -static void elfNN_ia64_install_dyn_reloc - PARAMS ((bfd *abfd, struct bfd_link_info *info, asection *sec, - asection *srel, bfd_vma offset, unsigned int type, - long dynindx, bfd_vma addend)); -static bfd_vma set_got_entry - PARAMS ((bfd *abfd, struct bfd_link_info *info, - struct elfNN_ia64_dyn_sym_info *dyn_i, long dynindx, - bfd_vma addend, bfd_vma value, unsigned int dyn_r_type)); -static bfd_vma set_fptr_entry - PARAMS ((bfd *abfd, struct bfd_link_info *info, - struct elfNN_ia64_dyn_sym_info *dyn_i, - bfd_vma value)); -static bfd_vma set_pltoff_entry - PARAMS ((bfd *abfd, struct bfd_link_info *info, - struct elfNN_ia64_dyn_sym_info *dyn_i, - bfd_vma value, bfd_boolean)); -static bfd_vma elfNN_ia64_tprel_base - PARAMS ((struct bfd_link_info *info)); -static bfd_vma elfNN_ia64_dtprel_base - PARAMS ((struct bfd_link_info *info)); -static int elfNN_ia64_unwind_entry_compare - PARAMS ((const PTR, const PTR)); -static bfd_boolean elfNN_ia64_choose_gp - PARAMS ((bfd *abfd, struct bfd_link_info *info)); -static bfd_boolean elfNN_ia64_final_link - PARAMS ((bfd *abfd, struct bfd_link_info *info)); -static bfd_boolean elfNN_ia64_relocate_section - PARAMS ((bfd *output_bfd, struct bfd_link_info *info, bfd *input_bfd, - asection *input_section, bfd_byte *contents, - Elf_Internal_Rela *relocs, Elf_Internal_Sym *local_syms, - asection **local_sections)); -static bfd_boolean elfNN_ia64_finish_dynamic_symbol - PARAMS ((bfd *output_bfd, struct bfd_link_info *info, - struct elf_link_hash_entry *h, Elf_Internal_Sym *sym)); -static bfd_boolean elfNN_ia64_finish_dynamic_sections - PARAMS ((bfd *abfd, struct bfd_link_info *info)); -static bfd_boolean elfNN_ia64_set_private_flags - PARAMS ((bfd *abfd, flagword flags)); -static bfd_boolean elfNN_ia64_merge_private_bfd_data - PARAMS ((bfd *ibfd, bfd *obfd)); -static bfd_boolean elfNN_ia64_print_private_bfd_data - PARAMS ((bfd *abfd, PTR ptr)); -static enum elf_reloc_type_class elfNN_ia64_reloc_type_class - PARAMS ((const Elf_Internal_Rela *)); + (struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data); static bfd_boolean elfNN_ia64_hpux_vec - PARAMS ((const bfd_target *vec)); -static void elfNN_hpux_post_process_headers - PARAMS ((bfd *abfd, struct bfd_link_info *info)); -bfd_boolean elfNN_hpux_backend_section_from_bfd_section - PARAMS ((bfd *abfd, asection *sec, int *retval)); + (const bfd_target *vec); +static bfd_boolean allocate_dynrel_entries + (struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data); +static asection *get_pltoff + (bfd *abfd, struct bfd_link_info *info, + struct elfNN_ia64_link_hash_table *ia64_info); /* ia64-specific relocation. */ /* Perform a relocation. Not much to do here as all the hard work is done in elfNN_ia64_final_link_relocate. */ static bfd_reloc_status_type -elfNN_ia64_reloc (abfd, reloc, sym, data, input_section, - output_bfd, error_message) - bfd *abfd ATTRIBUTE_UNUSED; - arelent *reloc; - asymbol *sym ATTRIBUTE_UNUSED; - PTR data ATTRIBUTE_UNUSED; - asection *input_section; - bfd *output_bfd; - char **error_message; +elfNN_ia64_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc, + asymbol *sym ATTRIBUTE_UNUSED, + PTR data ATTRIBUTE_UNUSED, asection *input_section, + bfd *output_bfd, char **error_message) { if (output_bfd) { @@ -484,8 +354,7 @@ static unsigned char elf_code_to_howto_index[R_IA64_MAX_RELOC_CODE + 1]; /* Given a BFD reloc type, return the matching HOWTO structure. */ static reloc_howto_type * -lookup_howto (rtype) - unsigned int rtype; +lookup_howto (unsigned int rtype) { static int inited = 0; int i; @@ -508,9 +377,8 @@ lookup_howto (rtype) } static reloc_howto_type* -elfNN_ia64_reloc_type_lookup (abfd, bfd_code) - bfd *abfd ATTRIBUTE_UNUSED; - bfd_reloc_code_real_type bfd_code; +elfNN_ia64_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, + bfd_reloc_code_real_type bfd_code) { unsigned int rtype; @@ -617,13 +485,28 @@ elfNN_ia64_reloc_type_lookup (abfd, bfd_code) return lookup_howto (rtype); } +static reloc_howto_type * +elfNN_ia64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, + const char *r_name) +{ + unsigned int i; + + for (i = 0; + i < sizeof (ia64_howto_table) / sizeof (ia64_howto_table[0]); + i++) + if (ia64_howto_table[i].name != NULL + && strcasecmp (ia64_howto_table[i].name, r_name) == 0) + return &ia64_howto_table[i]; + + return NULL; +} + /* Given a ELF reloc, return the matching HOWTO structure. */ static void -elfNN_ia64_info_to_howto (abfd, bfd_reloc, elf_reloc) - bfd *abfd ATTRIBUTE_UNUSED; - arelent *bfd_reloc; - Elf_Internal_Rela *elf_reloc; +elfNN_ia64_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, + arelent *bfd_reloc, + Elf_Internal_Rela *elf_reloc) { bfd_reloc->howto = lookup_howto ((unsigned int) ELFNN_R_TYPE (elf_reloc->r_info)); @@ -791,7 +674,7 @@ elfNN_ia64_relax_br (bfd_byte *contents, bfd_vma off) /* It should never happen. */ abort (); } - + /* We can turn br.cond/br.call into brl.cond/brl.call. */ if (!(IS_BR_COND (br_code) || IS_BR_CALL (br_code))) return FALSE; @@ -873,11 +756,9 @@ elfNN_ia64_relax_brl (bfd_byte *contents, bfd_vma off) /* These functions do relaxation for IA-64 ELF. */ static bfd_boolean -elfNN_ia64_relax_section (abfd, sec, link_info, again) - bfd *abfd; - asection *sec; - struct bfd_link_info *link_info; - bfd_boolean *again; +elfNN_ia64_relax_section (bfd *abfd, asection *sec, + struct bfd_link_info *link_info, + bfd_boolean *again) { struct one_fixup { @@ -1394,9 +1275,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) #undef skip_relax_pass_1 static void -elfNN_ia64_relax_ldxmov (contents, off) - bfd_byte *contents; - bfd_vma off; +elfNN_ia64_relax_ldxmov (bfd_byte *contents, bfd_vma off) { int shift, r1, r3; bfd_vma dword, insn; @@ -1428,22 +1307,15 @@ elfNN_ia64_relax_ldxmov (contents, off) /* Return TRUE if NAME is an unwind table section name. */ static inline bfd_boolean -is_unwind_section_name (abfd, name) - bfd *abfd; - const char *name; +is_unwind_section_name (bfd *abfd, const char *name) { - size_t len1, len2, len3; - if (elfNN_ia64_hpux_vec (abfd->xvec) && !strcmp (name, ELF_STRING_ia64_unwind_hdr)) return FALSE; - len1 = sizeof (ELF_STRING_ia64_unwind) - 1; - len2 = sizeof (ELF_STRING_ia64_unwind_info) - 1; - len3 = sizeof (ELF_STRING_ia64_unwind_once) - 1; - return ((strncmp (name, ELF_STRING_ia64_unwind, len1) == 0 - && strncmp (name, ELF_STRING_ia64_unwind_info, len2) != 0) - || strncmp (name, ELF_STRING_ia64_unwind_once, len3) == 0); + return ((CONST_STRNEQ (name, ELF_STRING_ia64_unwind) + && ! CONST_STRNEQ (name, ELF_STRING_ia64_unwind_info)) + || CONST_STRNEQ (name, ELF_STRING_ia64_unwind_once)); } /* Handle an IA-64 specific section when reading an object file. This @@ -1491,9 +1363,8 @@ elfNN_ia64_section_from_shdr (bfd *abfd, flag. */ static bfd_boolean -elfNN_ia64_section_flags (flags, hdr) - flagword *flags; - const Elf_Internal_Shdr *hdr; +elfNN_ia64_section_flags (flagword *flags, + const Elf_Internal_Shdr *hdr) { if (hdr->sh_flags & SHF_IA_64_SHORT) *flags |= SEC_SMALL_DATA; @@ -1505,10 +1376,8 @@ elfNN_ia64_section_flags (flags, hdr) section name, which is a hack, but ought to work. */ static bfd_boolean -elfNN_ia64_fake_sections (abfd, hdr, sec) - bfd *abfd ATTRIBUTE_UNUSED; - Elf_Internal_Shdr *hdr; - asection *sec; +elfNN_ia64_fake_sections (bfd *abfd, Elf_Internal_Shdr *hdr, + asection *sec) { register const char *name; @@ -1559,9 +1428,8 @@ elfNN_ia64_fake_sections (abfd, hdr, sec) object file. */ static void -elfNN_ia64_final_write_processing (abfd, linker) - bfd *abfd; - bfd_boolean linker ATTRIBUTE_UNUSED; +elfNN_ia64_final_write_processing (bfd *abfd, + bfd_boolean linker ATTRIBUTE_UNUSED) { Elf_Internal_Shdr *hdr; asection *s; @@ -1599,14 +1467,13 @@ elfNN_ia64_final_write_processing (abfd, linker) file. We use it to put .comm items in .sbss, and not .bss. */ static bfd_boolean -elfNN_ia64_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) - bfd *abfd; - struct bfd_link_info *info; - Elf_Internal_Sym *sym; - const char **namep ATTRIBUTE_UNUSED; - flagword *flagsp ATTRIBUTE_UNUSED; - asection **secp; - bfd_vma *valp; +elfNN_ia64_add_symbol_hook (bfd *abfd, + struct bfd_link_info *info, + Elf_Internal_Sym *sym, + const char **namep ATTRIBUTE_UNUSED, + flagword *flagsp ATTRIBUTE_UNUSED, + asection **secp, + bfd_vma *valp) { if (sym->st_shndx == SHN_COMMON && !info->relocatable @@ -1637,8 +1504,8 @@ elfNN_ia64_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) /* Return the number of additional phdrs we will need. */ static int -elfNN_ia64_additional_program_headers (abfd) - bfd *abfd; +elfNN_ia64_additional_program_headers (bfd *abfd, + struct bfd_link_info *info ATTRIBUTE_UNUSED) { asection *s; int ret = 0; @@ -1657,9 +1524,8 @@ elfNN_ia64_additional_program_headers (abfd) } static bfd_boolean -elfNN_ia64_modify_segment_map (abfd, info) - bfd *abfd; - struct bfd_link_info *info ATTRIBUTE_UNUSED; +elfNN_ia64_modify_segment_map (bfd *abfd, + struct bfd_link_info *info ATTRIBUTE_UNUSED) { struct elf_segment_map *m, **pm; Elf_Internal_Shdr *hdr; @@ -1742,17 +1608,30 @@ elfNN_ia64_modify_segment_map (abfd, info) } } - /* Turn on PF_IA_64_NORECOV if needed. This involves traversing all of - the input sections for each output section in the segment and testing - for SHF_IA_64_NORECOV on each. */ - for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next) + return TRUE; +} + +/* Turn on PF_IA_64_NORECOV if needed. This involves traversing all of + the input sections for each output section in the segment and testing + for SHF_IA_64_NORECOV on each. */ + +static bfd_boolean +elfNN_ia64_modify_program_headers (bfd *abfd, + struct bfd_link_info *info ATTRIBUTE_UNUSED) +{ + struct elf_obj_tdata *tdata = elf_tdata (abfd); + struct elf_segment_map *m; + Elf_Internal_Phdr *p; + + for (p = tdata->phdr, m = tdata->segment_map; m != NULL; m = m->next, p++) if (m->p_type == PT_LOAD) { int i; for (i = m->count - 1; i >= 0; --i) { struct bfd_link_order *order = m->sections[i]->map_head.link_order; - while (order) + + while (order != NULL) { if (order->type == bfd_indirect_link_order) { @@ -1760,7 +1639,7 @@ elfNN_ia64_modify_segment_map (abfd, info) bfd_vma flags = elf_section_data(is)->this_hdr.sh_flags; if (flags & SHF_IA_64_NORECOV) { - m->p_flags |= PF_IA_64_NORECOV; + p->p_flags |= PF_IA_64_NORECOV; goto found; } } @@ -1777,9 +1656,8 @@ elfNN_ia64_modify_segment_map (abfd, info) '.' are local. */ static bfd_boolean -elfNN_ia64_is_local_label_name (abfd, name) - bfd *abfd ATTRIBUTE_UNUSED; - const char *name; +elfNN_ia64_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED, + const char *name) { return name[0] == '.'; } @@ -1787,10 +1665,8 @@ elfNN_ia64_is_local_label_name (abfd, name) /* Should we do dynamic things to this symbol? */ static bfd_boolean -elfNN_ia64_dynamic_symbol_p (h, info, r_type) - struct elf_link_hash_entry *h; - struct bfd_link_info *info; - int r_type; +elfNN_ia64_dynamic_symbol_p (struct elf_link_hash_entry *h, + struct bfd_link_info *info, int r_type) { bfd_boolean ignore_protected = ((r_type & 0xf8) == 0x40 /* FPTR relocs */ @@ -1800,10 +1676,9 @@ elfNN_ia64_dynamic_symbol_p (h, info, r_type) } static struct bfd_hash_entry* -elfNN_ia64_new_elf_hash_entry (entry, table, string) - struct bfd_hash_entry *entry; - struct bfd_hash_table *table; - const char *string; +elfNN_ia64_new_elf_hash_entry (struct bfd_hash_entry *entry, + struct bfd_hash_table *table, + const char *string) { struct elfNN_ia64_link_hash_entry *ret; ret = (struct elfNN_ia64_link_hash_entry *) entry; @@ -1829,9 +1704,9 @@ elfNN_ia64_new_elf_hash_entry (entry, table, string) } static void -elfNN_ia64_hash_copy_indirect (info, xdir, xind) - struct bfd_link_info *info; - struct elf_link_hash_entry *xdir, *xind; +elfNN_ia64_hash_copy_indirect (struct bfd_link_info *info, + struct elf_link_hash_entry *xdir, + struct elf_link_hash_entry *xind) { struct elfNN_ia64_link_hash_entry *dir, *ind; @@ -1892,10 +1767,9 @@ elfNN_ia64_hash_copy_indirect (info, xdir, xind) } static void -elfNN_ia64_hash_hide_symbol (info, xh, force_local) - struct bfd_link_info *info; - struct elf_link_hash_entry *xh; - bfd_boolean force_local; +elfNN_ia64_hash_hide_symbol (struct bfd_link_info *info, + struct elf_link_hash_entry *xh, + bfd_boolean force_local) { struct elfNN_ia64_link_hash_entry *h; struct elfNN_ia64_dyn_sym_info *dyn_i; @@ -1917,8 +1791,7 @@ elfNN_ia64_hash_hide_symbol (info, xh, force_local) /* Compute a hash of a local hash entry. */ static hashval_t -elfNN_ia64_local_htab_hash (ptr) - const void *ptr; +elfNN_ia64_local_htab_hash (const void *ptr) { struct elfNN_ia64_local_hash_entry *entry = (struct elfNN_ia64_local_hash_entry *) ptr; @@ -1930,8 +1803,7 @@ elfNN_ia64_local_htab_hash (ptr) /* Compare local hash entries. */ static int -elfNN_ia64_local_htab_eq (ptr1, ptr2) - const void *ptr1, *ptr2; +elfNN_ia64_local_htab_eq (const void *ptr1, const void *ptr2) { struct elfNN_ia64_local_hash_entry *entry1 = (struct elfNN_ia64_local_hash_entry *) ptr1; @@ -1946,8 +1818,7 @@ elfNN_ia64_local_htab_eq (ptr1, ptr2) linker (without using static variables). */ static struct bfd_link_hash_table* -elfNN_ia64_hash_table_create (abfd) - bfd *abfd; +elfNN_ia64_hash_table_create (bfd *abfd) { struct elfNN_ia64_link_hash_table *ret; @@ -2023,8 +1894,7 @@ elfNN_ia64_local_dyn_info_free (void **slot, /* Destroy IA-64 linker hash table. */ static void -elfNN_ia64_hash_table_free (hash) - struct bfd_link_hash_table *hash; +elfNN_ia64_hash_table_free (struct bfd_link_hash_table *hash) { struct elfNN_ia64_link_hash_table *ia64_info = (struct elfNN_ia64_link_hash_table *) hash; @@ -2045,14 +1915,13 @@ elfNN_ia64_hash_table_free (hash) struct elfNN_ia64_dyn_sym_traverse_data { - bfd_boolean (*func) PARAMS ((struct elfNN_ia64_dyn_sym_info *, PTR)); + bfd_boolean (*func) (struct elfNN_ia64_dyn_sym_info *, PTR); PTR data; }; static bfd_boolean -elfNN_ia64_global_dyn_sym_thunk (xentry, xdata) - struct bfd_hash_entry *xentry; - PTR xdata; +elfNN_ia64_global_dyn_sym_thunk (struct bfd_hash_entry *xentry, + PTR xdata) { struct elfNN_ia64_link_hash_entry *entry = (struct elfNN_ia64_link_hash_entry *) xentry; @@ -2073,9 +1942,7 @@ elfNN_ia64_global_dyn_sym_thunk (xentry, xdata) } static bfd_boolean -elfNN_ia64_local_dyn_sym_thunk (slot, xdata) - void **slot; - PTR xdata; +elfNN_ia64_local_dyn_sym_thunk (void **slot, PTR xdata) { struct elfNN_ia64_local_hash_entry *entry = (struct elfNN_ia64_local_hash_entry *) *slot; @@ -2093,10 +1960,9 @@ elfNN_ia64_local_dyn_sym_thunk (slot, xdata) } static void -elfNN_ia64_dyn_sym_traverse (ia64_info, func, data) - struct elfNN_ia64_link_hash_table *ia64_info; - bfd_boolean (*func) PARAMS ((struct elfNN_ia64_dyn_sym_info *, PTR)); - PTR data; +elfNN_ia64_dyn_sym_traverse (struct elfNN_ia64_link_hash_table *ia64_info, + bfd_boolean (*func) (struct elfNN_ia64_dyn_sym_info *, PTR), + PTR data) { struct elfNN_ia64_dyn_sym_traverse_data xdata; @@ -2110,9 +1976,8 @@ elfNN_ia64_dyn_sym_traverse (ia64_info, func, data) } static bfd_boolean -elfNN_ia64_create_dynamic_sections (abfd, info) - bfd *abfd; - struct bfd_link_info *info; +elfNN_ia64_create_dynamic_sections (bfd *abfd, + struct bfd_link_info *info) { struct elfNN_ia64_link_hash_table *ia64_info; asection *s; @@ -2162,11 +2027,9 @@ elfNN_ia64_create_dynamic_sections (abfd, info) /* Find and/or create a hash entry for local symbol. */ static struct elfNN_ia64_local_hash_entry * -get_local_sym_hash (ia64_info, abfd, rel, create) - struct elfNN_ia64_link_hash_table *ia64_info; - bfd *abfd; - const Elf_Internal_Rela *rel; - bfd_boolean create; +get_local_sym_hash (struct elfNN_ia64_link_hash_table *ia64_info, + bfd *abfd, const Elf_Internal_Rela *rel, + bfd_boolean create) { struct elfNN_ia64_local_hash_entry e, *ret; asection *sec = abfd->sections; @@ -2208,7 +2071,7 @@ addend_compare (const void *xp, const void *yp) const struct elfNN_ia64_dyn_sym_info *y = (const struct elfNN_ia64_dyn_sym_info *) yp; - return x->addend - y->addend; + return x->addend < y->addend ? -1 : x->addend > y->addend ? 1 : 0; } /* Sort elfNN_ia64_dyn_sym_info array and remove duplicates. */ @@ -2217,37 +2080,62 @@ static unsigned int sort_dyn_sym_info (struct elfNN_ia64_dyn_sym_info *info, unsigned int count) { - bfd_vma curr, prev; - unsigned int i, dup, diff, dest, src, len; + bfd_vma curr, prev, got_offset; + unsigned int i, kept, dup, diff, dest, src, len; qsort (info, count, sizeof (*info), addend_compare); /* Find the first duplicate. */ prev = info [0].addend; + got_offset = info [0].got_offset; for (i = 1; i < count; i++) { curr = info [i].addend; if (curr == prev) - break; + { + /* For duplicates, make sure that GOT_OFFSET is valid. */ + if (got_offset == (bfd_vma) -1) + got_offset = info [i].got_offset; + break; + } + got_offset = info [i].got_offset; prev = curr; } + /* We may move a block of elements to here. */ + dest = i++; + /* Remove duplicates. */ if (i < count) { - /* We need to move a block of elements to here. */ - dest = i++; while (i < count) { + /* For duplicates, make sure that the kept one has a valid + got_offset. */ + kept = dest - 1; + if (got_offset != (bfd_vma) -1) + info [kept].got_offset = got_offset; + curr = info [i].addend; + got_offset = info [i].got_offset; /* Move a block of elements whose first one is different from the previous. */ if (curr == prev) { for (src = i + 1; src < count; src++) - if (info [src].addend != curr) - break; + { + if (info [src].addend != curr) + break; + /* For duplicates, make sure that GOT_OFFSET is + valid. */ + if (got_offset == (bfd_vma) -1) + got_offset = info [src].got_offset; + } + + /* Make sure that the kept one has a valid got_offset. */ + if (got_offset != (bfd_vma) -1) + info [kept].got_offset = got_offset; } else src = i; @@ -2255,13 +2143,25 @@ sort_dyn_sym_info (struct elfNN_ia64_dyn_sym_info *info, if (src >= count) break; - /* Find the next duplicate. */ + /* Find the next duplicate. SRC will be kept. */ prev = info [src].addend; + got_offset = info [src].got_offset; for (dup = src + 1; dup < count; dup++) { curr = info [dup].addend; if (curr == prev) - break; + { + /* Make sure that got_offset is valid. */ + if (got_offset == (bfd_vma) -1) + got_offset = info [dup].got_offset; + + /* For duplicates, make sure that the kept one has + a valid got_offset. */ + if (got_offset != (bfd_vma) -1) + info [dup - 1].got_offset = got_offset; + break; + } + got_offset = info [dup].got_offset; prev = curr; } @@ -2272,20 +2172,41 @@ sort_dyn_sym_info (struct elfNN_ia64_dyn_sym_info *info, if (len == 1 && dup < count) { /* If we only move 1 element, we combine it with the next - one. Find the next different one. */ + one. There must be at least a duplicate. Find the + next different one. */ for (diff = dup + 1, src++; diff < count; diff++, src++) - if (info [diff].addend != curr) - break; + { + if (info [diff].addend != curr) + break; + /* Make sure that got_offset is valid. */ + if (got_offset == (bfd_vma) -1) + got_offset = info [diff].got_offset; + } + + /* Makre sure that the last duplicated one has an valid + offset. */ + BFD_ASSERT (curr == prev); + if (got_offset != (bfd_vma) -1) + info [diff - 1].got_offset = got_offset; if (diff < count) { - /* Find the next duplicate. */ + /* Find the next duplicate. Track the current valid + offset. */ prev = info [diff].addend; + got_offset = info [diff].got_offset; for (dup = diff + 1; dup < count; dup++) { curr = info [dup].addend; if (curr == prev) - break; + { + /* For duplicates, make sure that GOT_OFFSET + is valid. */ + if (got_offset == (bfd_vma) -1) + got_offset = info [dup].got_offset; + break; + } + got_offset = info [dup].got_offset; prev = curr; diff++; } @@ -2302,6 +2223,19 @@ sort_dyn_sym_info (struct elfNN_ia64_dyn_sym_info *info, count = dest; } + else + { + /* When we get here, either there is no duplicate at all or + the only duplicate is the last element. */ + if (dest < count) + { + /* If the last element is a duplicate, make sure that the + kept one has a valid got_offset. We also update count. */ + if (got_offset != (bfd_vma) -1) + info [dest - 1].got_offset = got_offset; + count = dest; + } + } return count; } @@ -2323,12 +2257,9 @@ sort_dyn_sym_info (struct elfNN_ia64_dyn_sym_info *info, requires a copy which is O(N), but this only happens once. */ static struct elfNN_ia64_dyn_sym_info * -get_dyn_sym_info (ia64_info, h, abfd, rel, create) - struct elfNN_ia64_link_hash_table *ia64_info; - struct elf_link_hash_entry *h; - bfd *abfd; - const Elf_Internal_Rela *rel; - bfd_boolean create; +get_dyn_sym_info (struct elfNN_ia64_link_hash_table *ia64_info, + struct elf_link_hash_entry *h, bfd *abfd, + const Elf_Internal_Rela *rel, bfd_boolean create) { struct elfNN_ia64_dyn_sym_info **info_p, *info, *dyn_i, key; unsigned int *count_p, *sorted_count_p, *size_p; @@ -2424,8 +2355,9 @@ has_space: /* Append the new one to the array. */ dyn_i = info + count; memset (dyn_i, 0, sizeof (*dyn_i)); + dyn_i->got_offset = (bfd_vma) -1; dyn_i->addend = addend; - + /* We increment count only since the new ones are unsorted and may have duplicate. */ (*count_p)++; @@ -2464,10 +2396,8 @@ has_space: } static asection * -get_got (abfd, info, ia64_info) - bfd *abfd; - struct bfd_link_info *info; - struct elfNN_ia64_link_hash_table *ia64_info; +get_got (bfd *abfd, struct bfd_link_info *info, + struct elfNN_ia64_link_hash_table *ia64_info) { asection *got; bfd *dynobj; @@ -2504,10 +2434,8 @@ get_got (abfd, info, ia64_info) of a procedure, thus ensuring a unique address for each procedure. */ static asection * -get_fptr (abfd, info, ia64_info) - bfd *abfd; - struct bfd_link_info *info; - struct elfNN_ia64_link_hash_table *ia64_info; +get_fptr (bfd *abfd, struct bfd_link_info *info, + struct elfNN_ia64_link_hash_table *ia64_info) { asection *fptr; bfd *dynobj; @@ -2560,10 +2488,8 @@ get_fptr (abfd, info, ia64_info) } static asection * -get_pltoff (abfd, info, ia64_info) - bfd *abfd; - struct bfd_link_info *info ATTRIBUTE_UNUSED; - struct elfNN_ia64_link_hash_table *ia64_info; +get_pltoff (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED, + struct elfNN_ia64_link_hash_table *ia64_info) { asection *pltoff; bfd *dynobj; @@ -2597,11 +2523,9 @@ get_pltoff (abfd, info, ia64_info) } static asection * -get_reloc_section (abfd, ia64_info, sec, create) - bfd *abfd; - struct elfNN_ia64_link_hash_table *ia64_info; - asection *sec; - bfd_boolean create; +get_reloc_section (bfd *abfd, + struct elfNN_ia64_link_hash_table *ia64_info, + asection *sec, bfd_boolean create) { const char *srel_name; asection *srel; @@ -2613,10 +2537,10 @@ get_reloc_section (abfd, ia64_info, sec, create) if (srel_name == NULL) return NULL; - BFD_ASSERT ((strncmp (srel_name, ".rela", 5) == 0 + BFD_ASSERT ((CONST_STRNEQ (srel_name, ".rela") && strcmp (bfd_get_section_name (abfd, sec), srel_name+5) == 0) - || (strncmp (srel_name, ".rel", 4) == 0 + || (CONST_STRNEQ (srel_name, ".rel") && strcmp (bfd_get_section_name (abfd, sec), srel_name+4) == 0)); @@ -2672,11 +2596,9 @@ count_dyn_reloc (bfd *abfd, struct elfNN_ia64_dyn_sym_info *dyn_i, } static bfd_boolean -elfNN_ia64_check_relocs (abfd, info, sec, relocs) - bfd *abfd; - struct bfd_link_info *info; - asection *sec; - const Elf_Internal_Rela *relocs; +elfNN_ia64_check_relocs (bfd *abfd, struct bfd_link_info *info, + asection *sec, + const Elf_Internal_Rela *relocs) { struct elfNN_ia64_link_hash_table *ia64_info; const Elf_Internal_Rela *relend; @@ -2733,7 +2655,7 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs) have yet been processed. Do something with what we know, as this may help reduce memory usage and processing time later. */ maybe_dynamic = (h && ((!info->executable - && (!info->symbolic + && (!SYMBOLIC_BIND (info, h) || info->unresolved_syms_in_shared_libs == RM_IGNORE)) || !h->def_regular || h->root.type == bfd_link_hash_defweak)); @@ -2878,7 +2800,7 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs) } /* Now, we only do lookup without insertion, which is very fast - with the modified get_dyn_sym_info. */ + with the modified get_dyn_sym_info. */ for (rel = relocs; rel < relend; ++rel) { struct elfNN_ia64_dyn_sym_info *dyn_i; @@ -2905,7 +2827,7 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs) have yet been processed. Do something with what we know, as this may help reduce memory usage and processing time later. */ maybe_dynamic = (h && ((!info->executable - && (!info->symbolic + && (!SYMBOLIC_BIND (info, h) || info->unresolved_syms_in_shared_libs == RM_IGNORE)) || !h->def_regular || h->root.type == bfd_link_hash_defweak)); @@ -3132,9 +3054,8 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs) external GOT entries first. */ static bfd_boolean -allocate_global_data_got (dyn_i, data) - struct elfNN_ia64_dyn_sym_info *dyn_i; - PTR data; +allocate_global_data_got (struct elfNN_ia64_dyn_sym_info *dyn_i, + PTR data) { struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data; @@ -3181,9 +3102,8 @@ allocate_global_data_got (dyn_i, data) /* Next, allocate all the GOT entries used by LTOFF_FPTR relocs. */ static bfd_boolean -allocate_global_fptr_got (dyn_i, data) - struct elfNN_ia64_dyn_sym_info *dyn_i; - PTR data; +allocate_global_fptr_got (struct elfNN_ia64_dyn_sym_info *dyn_i, + PTR data) { struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data; @@ -3200,9 +3120,8 @@ allocate_global_fptr_got (dyn_i, data) /* Lastly, allocate all the GOT entries for local data. */ static bfd_boolean -allocate_local_got (dyn_i, data) - struct elfNN_ia64_dyn_sym_info *dyn_i; - PTR data; +allocate_local_got (struct elfNN_ia64_dyn_sym_info *dyn_i, + PTR data) { struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data; @@ -3218,8 +3137,7 @@ allocate_local_got (dyn_i, data) /* Search for the index of a global symbol in it's defining object file. */ static long -global_sym_index (h) - struct elf_link_hash_entry *h; +global_sym_index (struct elf_link_hash_entry *h) { struct elf_link_hash_entry **p; bfd *obj; @@ -3238,9 +3156,7 @@ global_sym_index (h) in a main executable that is not exported. */ static bfd_boolean -allocate_fptr (dyn_i, data) - struct elfNN_ia64_dyn_sym_info *dyn_i; - PTR data; +allocate_fptr (struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data) { struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data; @@ -3286,9 +3202,8 @@ allocate_fptr (dyn_i, data) /* Allocate all the minimal PLT entries. */ static bfd_boolean -allocate_plt_entries (dyn_i, data) - struct elfNN_ia64_dyn_sym_info *dyn_i; - PTR data; +allocate_plt_entries (struct elfNN_ia64_dyn_sym_info *dyn_i, + PTR data) { struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data; @@ -3324,9 +3239,8 @@ allocate_plt_entries (dyn_i, data) /* Allocate all the full PLT entries. */ static bfd_boolean -allocate_plt2_entries (dyn_i, data) - struct elfNN_ia64_dyn_sym_info *dyn_i; - PTR data; +allocate_plt2_entries (struct elfNN_ia64_dyn_sym_info *dyn_i, + PTR data) { struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data; @@ -3352,9 +3266,8 @@ allocate_plt2_entries (dyn_i, data) ??? Relaxation might be able to determine that they are. */ static bfd_boolean -allocate_pltoff_entries (dyn_i, data) - struct elfNN_ia64_dyn_sym_info *dyn_i; - PTR data; +allocate_pltoff_entries (struct elfNN_ia64_dyn_sym_info *dyn_i, + PTR data) { struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data; @@ -3370,9 +3283,8 @@ allocate_pltoff_entries (dyn_i, data) to be dynamic. */ static bfd_boolean -allocate_dynrel_entries (dyn_i, data) - struct elfNN_ia64_dyn_sym_info *dyn_i; - PTR data; +allocate_dynrel_entries (struct elfNN_ia64_dyn_sym_info *dyn_i, + PTR data) { struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data; struct elfNN_ia64_link_hash_table *ia64_info; @@ -3487,9 +3399,8 @@ allocate_dynrel_entries (dyn_i, data) } static bfd_boolean -elfNN_ia64_adjust_dynamic_symbol (info, h) - struct bfd_link_info *info ATTRIBUTE_UNUSED; - struct elf_link_hash_entry *h; +elfNN_ia64_adjust_dynamic_symbol (struct bfd_link_info *info ATTRIBUTE_UNUSED, + struct elf_link_hash_entry *h) { /* ??? Undefined symbols with PLT entries should be re-defined to be the PLT entry. */ @@ -3517,9 +3428,8 @@ elfNN_ia64_adjust_dynamic_symbol (info, h) } static bfd_boolean -elfNN_ia64_size_dynamic_sections (output_bfd, info) - bfd *output_bfd ATTRIBUTE_UNUSED; - struct bfd_link_info *info; +elfNN_ia64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, + struct bfd_link_info *info) { struct elfNN_ia64_allocate_data data; struct elfNN_ia64_link_hash_table *ia64_info; @@ -3694,7 +3604,7 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info) if (strcmp (name, ".got.plt") == 0) strip = FALSE; - else if (strncmp (name, ".rel", 4) == 0) + else if (CONST_STRNEQ (name, ".rel")) { if (!strip) { @@ -3767,10 +3677,8 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info) } static bfd_reloc_status_type -elfNN_ia64_install_value (hit_addr, v, r_type) - bfd_byte *hit_addr; - bfd_vma v; - unsigned int r_type; +elfNN_ia64_install_value (bfd_byte *hit_addr, bfd_vma v, + unsigned int r_type) { const struct ia64_operand *op; int bigendian = 0, shift = 0; @@ -3992,16 +3900,10 @@ elfNN_ia64_install_value (hit_addr, v, r_type) } static void -elfNN_ia64_install_dyn_reloc (abfd, info, sec, srel, offset, type, - dynindx, addend) - bfd *abfd; - struct bfd_link_info *info; - asection *sec; - asection *srel; - bfd_vma offset; - unsigned int type; - long dynindx; - bfd_vma addend; +elfNN_ia64_install_dyn_reloc (bfd *abfd, struct bfd_link_info *info, + asection *sec, asection *srel, + bfd_vma offset, unsigned int type, + long dynindx, bfd_vma addend) { Elf_Internal_Rela outrel; bfd_byte *loc; @@ -4031,14 +3933,10 @@ elfNN_ia64_install_dyn_reloc (abfd, info, sec, srel, offset, type, and return the gp-relative address of the linkage table entry. */ static bfd_vma -set_got_entry (abfd, info, dyn_i, dynindx, addend, value, dyn_r_type) - bfd *abfd; - struct bfd_link_info *info; - struct elfNN_ia64_dyn_sym_info *dyn_i; - long dynindx; - bfd_vma addend; - bfd_vma value; - unsigned int dyn_r_type; +set_got_entry (bfd *abfd, struct bfd_link_info *info, + struct elfNN_ia64_dyn_sym_info *dyn_i, + long dynindx, bfd_vma addend, bfd_vma value, + unsigned int dyn_r_type) { struct elfNN_ia64_link_hash_table *ia64_info; asection *got_sec; @@ -4175,11 +4073,9 @@ set_got_entry (abfd, info, dyn_i, dynindx, addend, value, dyn_r_type) address and its global pointer. Return the descriptor's address. */ static bfd_vma -set_fptr_entry (abfd, info, dyn_i, value) - bfd *abfd; - struct bfd_link_info *info; - struct elfNN_ia64_dyn_sym_info *dyn_i; - bfd_vma value; +set_fptr_entry (bfd *abfd, struct bfd_link_info *info, + struct elfNN_ia64_dyn_sym_info *dyn_i, + bfd_vma value) { struct elfNN_ia64_link_hash_table *ia64_info; asection *fptr_sec; @@ -4227,12 +4123,9 @@ set_fptr_entry (abfd, info, dyn_i, value) and its global pointer. Return the descriptor's address. */ static bfd_vma -set_pltoff_entry (abfd, info, dyn_i, value, is_plt) - bfd *abfd; - struct bfd_link_info *info; - struct elfNN_ia64_dyn_sym_info *dyn_i; - bfd_vma value; - bfd_boolean is_plt; +set_pltoff_entry (bfd *abfd, struct bfd_link_info *info, + struct elfNN_ia64_dyn_sym_info *dyn_i, + bfd_vma value, bfd_boolean is_plt) { struct elfNN_ia64_link_hash_table *ia64_info; asection *pltoff_sec; @@ -4292,12 +4185,9 @@ set_pltoff_entry (abfd, info, dyn_i, value, is_plt) is assigned offset round(2 * size of pointer, PT_TLS p_align). */ static bfd_vma -elfNN_ia64_tprel_base (info) - struct bfd_link_info *info; +elfNN_ia64_tprel_base (struct bfd_link_info *info) { asection *tls_sec = elf_hash_table (info)->tls_sec; - - BFD_ASSERT (tls_sec != NULL); return tls_sec->vma - align_power ((bfd_vma) ARCH_SIZE / 4, tls_sec->alignment_power); } @@ -4307,10 +4197,8 @@ elfNN_ia64_tprel_base (info) This is PT_TLS segment p_vaddr. */ static bfd_vma -elfNN_ia64_dtprel_base (info) - struct bfd_link_info *info; +elfNN_ia64_dtprel_base (struct bfd_link_info *info) { - BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL); return elf_hash_table (info)->tls_sec->vma; } @@ -4321,9 +4209,7 @@ elfNN_ia64_dtprel_base (info) static bfd *elfNN_ia64_unwind_entry_compare_bfd; static int -elfNN_ia64_unwind_entry_compare (a, b) - const PTR a; - const PTR b; +elfNN_ia64_unwind_entry_compare (const PTR a, const PTR b) { bfd_vma av, bv; @@ -4335,9 +4221,7 @@ elfNN_ia64_unwind_entry_compare (a, b) /* Make sure we've got ourselves a nice fat __gp value. */ static bfd_boolean -elfNN_ia64_choose_gp (abfd, info) - bfd *abfd; - struct bfd_link_info *info; +elfNN_ia64_choose_gp (bfd *abfd, struct bfd_link_info *info) { bfd_vma min_vma = (bfd_vma) -1, max_vma = 0; bfd_vma min_short_vma = min_vma, max_short_vma = 0; @@ -4358,7 +4242,7 @@ elfNN_ia64_choose_gp (abfd, info) continue; lo = os->vma; - hi = os->vma + os->size; + hi = os->vma + (os->rawsize ? os->rawsize : os->size); if (hi < lo) hi = (bfd_vma) -1; @@ -4453,9 +4337,7 @@ elfNN_ia64_choose_gp (abfd, info) } static bfd_boolean -elfNN_ia64_final_link (abfd, info) - bfd *abfd; - struct bfd_link_info *info; +elfNN_ia64_final_link (bfd *abfd, struct bfd_link_info *info) { struct elfNN_ia64_link_hash_table *ia64_info; asection *unwind_output_sec; @@ -4524,16 +4406,14 @@ elfNN_ia64_final_link (abfd, info) } static bfd_boolean -elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, - contents, relocs, local_syms, local_sections) - bfd *output_bfd; - struct bfd_link_info *info; - bfd *input_bfd; - asection *input_section; - bfd_byte *contents; - Elf_Internal_Rela *relocs; - Elf_Internal_Sym *local_syms; - asection **local_sections; +elfNN_ia64_relocate_section (bfd *output_bfd, + struct bfd_link_info *info, + bfd *input_bfd, + asection *input_section, + bfd_byte *contents, + Elf_Internal_Rela *relocs, + Elf_Internal_Sym *local_syms, + asection **local_sections) { struct elfNN_ia64_link_hash_table *ia64_info; Elf_Internal_Shdr *symtab_hdr; @@ -4556,7 +4436,6 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, elf_section_data(input_section->output_section) ->this_hdr.sh_flags |= flags; - return TRUE; } gp_val = _bfd_get_gp_value (output_bfd); @@ -4605,7 +4484,8 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, sym_sec = local_sections[r_symndx]; msec = sym_sec; value = _bfd_elf_rela_local_sym (output_bfd, sym, &msec, rel); - if ((sym_sec->flags & SEC_MERGE) + if (!info->relocatable + && (sym_sec->flags & SEC_MERGE) != 0 && ELF_ST_TYPE (sym->st_info) == STT_SECTION && sym_sec->sec_info_type == ELF_INFO_TYPE_MERGE) { @@ -4634,9 +4514,15 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, - sym_sec->output_section->vma - sym_sec->output_offset; } - - qsort (loc_h->info, loc_h->count, - sizeof (*loc_h->info), addend_compare); + + /* We may have introduced duplicated entries. We need + to remove them properly. */ + count = sort_dyn_sym_info (loc_h->info, loc_h->count); + if (count != loc_h->count) + { + loc_h->count = count; + loc_h->sorted_count = count; + } loc_h->sec_merge_done = 1; } @@ -4659,6 +4545,20 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, continue; } + /* For relocs against symbols from removed linkonce sections, + or sections discarded by a linker script, we just want the + section contents zeroed. Avoid any special processing. */ + if (sym_sec != NULL && elf_discarded_section (sym_sec)) + { + _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset); + rel->r_info = 0; + rel->r_addend = 0; + continue; + } + + if (info->relocatable) + continue; + hit_addr = contents + rel->r_offset; value += rel->r_addend; dynamic_symbol_p = elfNN_ia64_dynamic_symbol_p (h, info, r_type); @@ -4990,32 +4890,12 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, case R_IA64_SEGREL32LSB: case R_IA64_SEGREL64MSB: case R_IA64_SEGREL64LSB: - if (r_symndx == 0) - { - /* If the input section was discarded from the output, then - do nothing. */ - r = bfd_reloc_ok; - } - else { - struct elf_segment_map *m; - Elf_Internal_Phdr *p; - /* Find the segment that contains the output_section. */ - for (m = elf_tdata (output_bfd)->segment_map, - p = elf_tdata (output_bfd)->phdr; - m != NULL; - m = m->next, p++) - { - int i; - for (i = m->count - 1; i >= 0; i--) - if (m->sections[i] == input_section->output_section) - break; - if (i >= 0) - break; - } + Elf_Internal_Phdr *p = _bfd_elf_find_segment_containing_section + (output_bfd, input_section->output_section); - if (m == NULL) + if (p == NULL) { r = bfd_reloc_notsupported; } @@ -5088,6 +4968,8 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, case R_IA64_TPREL14: case R_IA64_TPREL22: case R_IA64_TPREL64I: + if (elf_hash_table (info)->tls_sec == NULL) + goto missing_tls_sec; value -= elfNN_ia64_tprel_base (info); r = elfNN_ia64_install_value (hit_addr, value, r_type); break; @@ -5099,6 +4981,8 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, case R_IA64_DTPREL32MSB: case R_IA64_DTPREL64LSB: case R_IA64_DTPREL64MSB: + if (elf_hash_table (info)->tls_sec == NULL) + goto missing_tls_sec; value -= elfNN_ia64_dtprel_base (info); r = elfNN_ia64_install_value (hit_addr, value, r_type); break; @@ -5117,6 +5001,8 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, case R_IA64_LTOFF_TPREL22: if (!dynamic_symbol_p) { + if (elf_hash_table (info)->tls_sec == NULL) + goto missing_tls_sec; if (!info->shared) value -= elfNN_ia64_tprel_base (info); else @@ -5134,7 +5020,11 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, break; case R_IA64_LTOFF_DTPREL22: if (!dynamic_symbol_p) - value -= elfNN_ia64_dtprel_base (info); + { + if (elf_hash_table (info)->tls_sec == NULL) + goto missing_tls_sec; + value -= elfNN_ia64_dtprel_base (info); + } got_r_type = R_IA64_DTPRELNNLSB; break; } @@ -5185,6 +5075,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, case bfd_reloc_outofrange: case bfd_reloc_overflow: default: +missing_tls_sec: { const char *name; @@ -5196,6 +5087,25 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, switch (r_type) { + case R_IA64_TPREL14: + case R_IA64_TPREL22: + case R_IA64_TPREL64I: + case R_IA64_DTPREL14: + case R_IA64_DTPREL22: + case R_IA64_DTPREL64I: + case R_IA64_DTPREL32LSB: + case R_IA64_DTPREL32MSB: + case R_IA64_DTPREL64LSB: + case R_IA64_DTPREL64MSB: + case R_IA64_LTOFF_TPREL22: + case R_IA64_LTOFF_DTPMOD22: + case R_IA64_LTOFF_DTPREL22: + (*_bfd_error_handler) + (_("%B: missing TLS section for relocation %s against `%s' at 0x%lx in section `%A'."), + input_bfd, input_section, howto->name, name, + rel->r_offset); + break; + case R_IA64_PCREL21B: case R_IA64_PCREL21BI: case R_IA64_PCREL21M: @@ -5234,11 +5144,10 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, } static bfd_boolean -elfNN_ia64_finish_dynamic_symbol (output_bfd, info, h, sym) - bfd *output_bfd; - struct bfd_link_info *info; - struct elf_link_hash_entry *h; - Elf_Internal_Sym *sym; +elfNN_ia64_finish_dynamic_symbol (bfd *output_bfd, + struct bfd_link_info *info, + struct elf_link_hash_entry *h, + Elf_Internal_Sym *sym) { struct elfNN_ia64_link_hash_table *ia64_info; struct elfNN_ia64_dyn_sym_info *dyn_i; @@ -5323,9 +5232,8 @@ elfNN_ia64_finish_dynamic_symbol (output_bfd, info, h, sym) } static bfd_boolean -elfNN_ia64_finish_dynamic_sections (abfd, info) - bfd *abfd; - struct bfd_link_info *info; +elfNN_ia64_finish_dynamic_sections (bfd *abfd, + struct bfd_link_info *info) { struct elfNN_ia64_link_hash_table *ia64_info; bfd *dynobj; @@ -5411,9 +5319,7 @@ elfNN_ia64_finish_dynamic_sections (abfd, info) /* Function to keep IA-64 specific file flags. */ static bfd_boolean -elfNN_ia64_set_private_flags (abfd, flags) - bfd *abfd; - flagword flags; +elfNN_ia64_set_private_flags (bfd *abfd, flagword flags) { BFD_ASSERT (!elf_flags_init (abfd) || elf_elfheader (abfd)->e_flags == flags); @@ -5426,8 +5332,7 @@ elfNN_ia64_set_private_flags (abfd, flags) /* Merge backend specific data from an object file to the output object file when linking. */ static bfd_boolean -elfNN_ia64_merge_private_bfd_data (ibfd, obfd) - bfd *ibfd, *obfd; +elfNN_ia64_merge_private_bfd_data (bfd *ibfd, bfd *obfd) { flagword out_flags; flagword in_flags; @@ -5515,9 +5420,7 @@ elfNN_ia64_merge_private_bfd_data (ibfd, obfd) } static bfd_boolean -elfNN_ia64_print_private_bfd_data (abfd, ptr) - bfd *abfd; - PTR ptr; +elfNN_ia64_print_private_bfd_data (bfd *abfd, PTR ptr) { FILE *file = (FILE *) ptr; flagword flags = elf_elfheader (abfd)->e_flags; @@ -5539,8 +5442,7 @@ elfNN_ia64_print_private_bfd_data (abfd, ptr) } static enum elf_reloc_type_class -elfNN_ia64_reloc_type_class (rela) - const Elf_Internal_Rela *rela; +elfNN_ia64_reloc_type_class (const Elf_Internal_Rela *rela) { switch ((int) ELFNN_R_TYPE (rela->r_info)) { @@ -5561,9 +5463,9 @@ elfNN_ia64_reloc_type_class (rela) static const struct bfd_elf_special_section elfNN_ia64_special_sections[] = { - { ".sbss", 5, -1, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_IA_64_SHORT }, - { ".sdata", 6, -1, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_IA_64_SHORT }, - { NULL, 0, 0, 0, 0 } + { STRING_COMMA_LEN (".sbss"), -1, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_IA_64_SHORT }, + { STRING_COMMA_LEN (".sdata"), -1, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_IA_64_SHORT }, + { NULL, 0, 0, 0, 0 } }; static bfd_boolean @@ -5590,7 +5492,7 @@ elfNN_ia64_object_p (bfd *abfd) if (elf_sec_group (sec) == NULL && ((sec->flags & (SEC_LINK_ONCE | SEC_CODE | SEC_GROUP)) == (SEC_LINK_ONCE | SEC_CODE)) - && strncmp (sec->name, ".gnu.linkonce.t.", 16) == 0) + && CONST_STRNEQ (sec->name, ".gnu.linkonce.t.")) { name = sec->name + 16; @@ -5667,21 +5569,18 @@ elfNN_ia64_hpux_vec (const bfd_target *vec) } static void -elfNN_hpux_post_process_headers (abfd, info) - bfd *abfd; - struct bfd_link_info *info ATTRIBUTE_UNUSED; +elfNN_hpux_post_process_headers (bfd *abfd, + struct bfd_link_info *info ATTRIBUTE_UNUSED) { Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd); - i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_HPUX; + i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi; i_ehdrp->e_ident[EI_ABIVERSION] = 1; } -bfd_boolean -elfNN_hpux_backend_section_from_bfd_section (abfd, sec, retval) - bfd *abfd ATTRIBUTE_UNUSED; - asection *sec; - int *retval; +static bfd_boolean +elfNN_hpux_backend_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED, + asection *sec, int *retval) { if (bfd_is_com_section (sec)) { @@ -5717,6 +5616,7 @@ elfNN_hpux_backend_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED, #define ELF_MACHINE_ALT1 1999 /* EAS2.3 */ #define ELF_MACHINE_ALT2 1998 /* EAS2.2 */ #define ELF_MAXPAGESIZE 0x10000 /* 64KB */ +#define ELF_COMMONPAGESIZE 0x4000 /* 16KB */ #define elf_backend_section_from_shdr \ elfNN_ia64_section_from_shdr @@ -5732,11 +5632,15 @@ elfNN_hpux_backend_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED, elfNN_ia64_additional_program_headers #define elf_backend_modify_segment_map \ elfNN_ia64_modify_segment_map +#define elf_backend_modify_program_headers \ + elfNN_ia64_modify_program_headers #define elf_info_to_howto \ elfNN_ia64_info_to_howto #define bfd_elfNN_bfd_reloc_type_lookup \ elfNN_ia64_reloc_type_lookup +#define bfd_elfNN_bfd_reloc_name_lookup \ + elfNN_ia64_reloc_name_lookup #define bfd_elfNN_bfd_is_local_label_name \ elfNN_ia64_is_local_label_name #define bfd_elfNN_bfd_relax_section \ @@ -5758,6 +5662,8 @@ elfNN_hpux_backend_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED, elfNN_ia64_adjust_dynamic_symbol #define elf_backend_size_dynamic_sections \ elfNN_ia64_size_dynamic_sections +#define elf_backend_omit_section_dynsym \ + ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true) #define elf_backend_relocate_section \ elfNN_ia64_relocate_section #define elf_backend_finish_dynamic_symbol \ @@ -5789,6 +5695,7 @@ elfNN_hpux_backend_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED, #define elf_backend_reloc_type_class elfNN_ia64_reloc_type_class #define elf_backend_rela_normal 1 #define elf_backend_special_sections elfNN_ia64_special_sections +#define elf_backend_default_execstack 0 /* FIXME: PR 290: The Intel C compiler generates SHT_IA_64_UNWIND with SHF_LINK_ORDER. But it doesn't set the sh_link or sh_info fields. @@ -5822,8 +5729,9 @@ elfNN_hpux_backend_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED, #undef elf_backend_want_p_paddr_set_to_zero #define elf_backend_want_p_paddr_set_to_zero 1 -#undef ELF_MAXPAGESIZE -#define ELF_MAXPAGESIZE 0x1000 /* 1K */ +#undef ELF_COMMONPAGESIZE +#undef ELF_OSABI +#define ELF_OSABI ELFOSABI_HPUX #undef elfNN_bed #define elfNN_bed elfNN_ia64_hpux_bed