X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felfxx-ia64.c;h=2e34a3071c6fcd465fb63b167222cd6b7c621944;hb=f7460f5f7689262ad24e7e28c9d6662169cd3549;hp=481834bb4db5db9c16001271a43421d4ff3eba7a;hpb=a4bd839069db2337a6d8e219782aff38875699a7;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elfxx-ia64.c b/bfd/elfxx-ia64.c index 481834bb4d..2e34a3071c 100644 --- a/bfd/elfxx-ia64.c +++ b/bfd/elfxx-ia64.c @@ -111,6 +111,10 @@ struct elfNN_ia64_local_hash_entry { struct bfd_hash_entry root; struct elfNN_ia64_dyn_sym_info *info; + + /* True if this hash entry's addends was translated for + SHF_MERGE optimization. */ + unsigned sec_merge_done : 1; }; struct elfNN_ia64_local_hash_table @@ -138,6 +142,7 @@ struct elfNN_ia64_link_hash_table asection *rel_pltoff_sec; /* dynamic relocation section for same */ bfd_size_type minplt_entries; /* number of minplt entries */ + unsigned reltext : 1; /* are there relocs against readonly sections? */ struct elfNN_ia64_local_hash_table loc_hash_table; }; @@ -161,6 +166,8 @@ static boolean is_unwind_section_name PARAMS ((const char *)); static boolean elfNN_ia64_section_from_shdr PARAMS ((bfd *, ElfNN_Internal_Shdr *, char *)); +static boolean elfNN_ia64_section_flags + PARAMS ((flagword *, ElfNN_Internal_Shdr *)); static boolean elfNN_ia64_fake_sections PARAMS ((bfd *abfd, ElfNN_Internal_Shdr *hdr, asection *sec)); static void elfNN_ia64_final_write_processing @@ -169,7 +176,7 @@ static boolean elfNN_ia64_add_symbol_hook PARAMS ((bfd *abfd, struct bfd_link_info *info, const Elf_Internal_Sym *sym, const char **namep, flagword *flagsp, asection **secp, bfd_vma *valp)); -static boolean elfNN_ia64_aix_vec +static boolean elfNN_ia64_aix_vec PARAMS ((const bfd_target *vec)); static boolean elfNN_ia64_aix_add_symbol_hook PARAMS ((bfd *abfd, struct bfd_link_info *info, const Elf_Internal_Sym *sym, @@ -179,6 +186,8 @@ static boolean elfNN_ia64_aix_link_add_symbols PARAMS ((bfd *abfd, struct bfd_link_info *info)); static int elfNN_ia64_additional_program_headers PARAMS ((bfd *abfd)); +static boolean elfNN_ia64_modify_segment_map + PARAMS ((bfd *)); static boolean elfNN_ia64_is_local_label_name PARAMS ((bfd *abfd, const char *name)); static boolean elfNN_ia64_dynamic_symbol_p @@ -192,17 +201,28 @@ static struct bfd_hash_entry *elfNN_ia64_new_loc_hash_entry 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 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 *)); static struct bfd_link_hash_table *elfNN_ia64_hash_table_create PARAMS ((bfd *abfd)); static struct elfNN_ia64_local_hash_entry *elfNN_ia64_local_hash_lookup PARAMS ((struct elfNN_ia64_local_hash_table *table, const char *string, boolean create, boolean copy)); +static boolean elfNN_ia64_global_dyn_sym_thunk + PARAMS ((struct bfd_hash_entry *, PTR)); +static boolean elfNN_ia64_local_dyn_sym_thunk + PARAMS ((struct bfd_hash_entry *, PTR)); static void elfNN_ia64_dyn_sym_traverse PARAMS ((struct elfNN_ia64_link_hash_table *ia64_info, boolean (*func) (struct elfNN_ia64_dyn_sym_info *, PTR), PTR info)); static 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, 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, @@ -227,7 +247,7 @@ static boolean elfNN_ia64_check_relocs const Elf_Internal_Rela *relocs)); static boolean elfNN_ia64_adjust_dynamic_symbol PARAMS ((struct bfd_link_info *info, struct elf_link_hash_entry *h)); -static unsigned long global_sym_index +static long global_sym_index PARAMS ((struct elf_link_hash_entry *h)); static boolean allocate_fptr PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data)); @@ -265,6 +285,8 @@ 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, boolean)); +static int elfNN_ia64_unwind_entry_compare + PARAMS ((const PTR, const PTR)); static boolean elfNN_ia64_final_link PARAMS ((bfd *abfd, struct bfd_link_info *info)); static boolean elfNN_ia64_relocate_section @@ -285,6 +307,8 @@ static boolean elfNN_ia64_merge_private_bfd_data PARAMS ((bfd *ibfd, bfd *obfd)); static 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 *)); /* ia64-specific relocation */ @@ -531,7 +555,8 @@ elfNN_ia64_info_to_howto (abfd, bfd_reloc, elf_reloc) arelent *bfd_reloc; ElfNN_Internal_Rela *elf_reloc; { - bfd_reloc->howto = lookup_howto (ELFNN_R_TYPE (elf_reloc->r_info)); + bfd_reloc->howto + = lookup_howto ((unsigned int) ELFNN_R_TYPE (elf_reloc->r_info)); } #define PLT_HEADER_SIZE (3 * 16) @@ -697,7 +722,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) goto error_return; free_extsyms = extsyms; if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || (bfd_read (extsyms, 1, symtab_hdr->sh_size, abfd) + || (bfd_bread (extsyms, symtab_hdr->sh_size, abfd) != symtab_hdr->sh_size)) goto error_return; } @@ -708,6 +733,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) Elf_Internal_Sym isym; asection *tsec; struct one_fixup *f; + bfd_size_type amt; if (ELFNN_R_TYPE (irel->r_info) != (int) R_IA64_PCREL21B) continue; @@ -775,7 +801,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) roff = irel->r_offset; reladdr = (sec->output_section->vma + sec->output_offset - + roff) & -4; + + roff) & (bfd_vma) -4; /* If the branch is in range, no need to do anything. */ if ((bfd_signed_vma) (symaddr - reladdr) >= -0x1000000 @@ -799,7 +825,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) make a copy of the FULL_PLT entry. Otherwise, we'll have to use a `brl' insn to get where we're going. */ - int size; + size_t size; if (tsec == ia64_info->plt_sec) size = sizeof (plt_full_entry); @@ -813,11 +839,12 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) } /* Resize the current section to make room for the new branch. */ - trampoff = (sec->_cooked_size + 15) & -16; - contents = (bfd_byte *) bfd_realloc (contents, trampoff + size); + trampoff = (sec->_cooked_size + 15) & (bfd_vma) -16; + amt = trampoff + size; + contents = (bfd_byte *) bfd_realloc (contents, amt); if (contents == NULL) goto error_return; - sec->_cooked_size = trampoff + size; + sec->_cooked_size = amt; if (tsec == ia64_info->plt_sec) { @@ -845,7 +872,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) } /* Record the fixup so we don't do it again this section. */ - f = (struct one_fixup *) bfd_malloc (sizeof (*f)); + f = (struct one_fixup *) bfd_malloc ((bfd_size_type) sizeof (*f)); f->next = fixups; f->tsec = tsec; f->toff = toff; @@ -861,7 +888,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) /* Fix up the existing branch to hit the trampoline. Hope like hell this doesn't overflow too. */ if (elfNN_ia64_install_value (abfd, contents + roff, - f->trampoff - (roff & -4), + f->trampoff - (roff & (bfd_vma) -4), R_IA64_PCREL21B) != bfd_reloc_ok) goto error_return; @@ -902,7 +929,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) else { /* Cache the symbols for elf_link_input_bfd. */ - symtab_hdr->contents = extsyms; + symtab_hdr->contents = (unsigned char *) extsyms; } } @@ -1116,7 +1143,7 @@ elfNN_ia64_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) { if (sym->st_shndx == SHN_COMMON && !info->relocateable - && sym->st_size <= (unsigned) bfd_get_gp_size (abfd)) + && sym->st_size <= elf_gp_size (abfd)) { /* Common symbols less than or equal to -G nn bytes are automatically put into .sbss. */ @@ -1146,7 +1173,7 @@ elfNN_ia64_aix_vec (const bfd_target *vec) extern const bfd_target bfd_elfNN_ia64_aix_little_vec; extern const bfd_target bfd_elfNN_ia64_aix_big_vec; - return (/**/vec == & bfd_elfNN_ia64_aix_little_vec + return (/**/vec == & bfd_elfNN_ia64_aix_little_vec || vec == & bfd_elfNN_ia64_aix_big_vec); } @@ -1170,25 +1197,26 @@ elfNN_ia64_aix_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) no one else should use it b/c it is undocumented. */ struct elf_link_hash_entry *h; - h = (struct elf_link_hash_entry *) bfd_link_hash_lookup (info->hash, *namep, false, false, false); - if (h == NULL) + h = elf_link_hash_lookup (elf_hash_table (info), *namep, + false, false, false); + if (h == NULL) { struct elf_backend_data *bed; struct elfNN_ia64_link_hash_table *ia64_info; bed = get_elf_backend_data (abfd); ia64_info = elfNN_ia64_hash_table (info); - + if (!(_bfd_generic_link_add_one_symbol - (info, abfd, *namep, BSF_GLOBAL, + (info, abfd, *namep, BSF_GLOBAL, bfd_get_section_by_name (abfd, ".bss"), bed->got_symbol_offset, (const char *) NULL, false, bed->collect, (struct bfd_link_hash_entry **) &h))) return false; - + h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR; h->type = STT_OBJECT; - + if (! _bfd_elf_link_record_dynamic_symbol (info, h)) return false; } @@ -1198,15 +1226,15 @@ elfNN_ia64_aix_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) else if (sym->st_shndx == SHN_LOOS) { int i; - + /* SHN_AIX_SYSCALL: Treat this as any other symbol. The special symbol is only relevant when compiling code for extended system calls. - Replace the "special" section with .text, if possible. + Replace the "special" section with .text, if possible. Note that these symbols are always assumed to be in .text. */ for (i = 1; i < elf_elfheader (abfd)->e_shnum; i++) { - asection * sec = bfd_section_from_elf_index (abfd, i); - + asection * sec = bfd_section_from_elf_index (abfd, (unsigned) i); + if (sec && strcmp (sec->name, ".text") == 0) { *secp = sec; @@ -1216,14 +1244,14 @@ elfNN_ia64_aix_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) if (*secp == NULL) *secp = bfd_abs_section_ptr; - + *valp = sym->st_size; - + return true; } - else + else { - return elfNN_ia64_add_symbol_hook (abfd, info, sym, + return elfNN_ia64_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp); } } @@ -1285,7 +1313,8 @@ elfNN_ia64_modify_segment_map (abfd) break; if (m == NULL) { - m = (struct elf_segment_map *) bfd_zalloc (abfd, sizeof *m); + m = ((struct elf_segment_map *) + bfd_zalloc (abfd, (bfd_size_type) sizeof *m)); if (m == NULL) return false; @@ -1320,7 +1349,8 @@ elfNN_ia64_modify_segment_map (abfd) if (m == NULL) { - m = (struct elf_segment_map *) bfd_zalloc (abfd, sizeof *m); + m = ((struct elf_segment_map *) + bfd_zalloc (abfd, (bfd_size_type) sizeof *m)); if (m == NULL) return false; @@ -1407,7 +1437,7 @@ elfNN_ia64_dynamic_symbol_p (h, info) || h->root.type == bfd_link_hash_defweak) return true; - if ((info->shared && !info->symbolic) + if ((info->shared && (!info->symbolic || info->allow_shlib_undefined)) || ((h->elf_link_hash_flags & (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR)) == (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR))) @@ -1489,8 +1519,8 @@ elfNN_ia64_hash_copy_indirect (xdir, xind) { struct elfNN_ia64_link_hash_entry *dir, *ind; - dir = (struct elfNN_ia64_link_hash_entry *)xdir; - ind = (struct elfNN_ia64_link_hash_entry *)xind; + dir = (struct elfNN_ia64_link_hash_entry *) xdir; + ind = (struct elfNN_ia64_link_hash_entry *) xind; /* Copy down any references that we may have already seen to the symbol which just became indirect. */ @@ -1501,6 +1531,9 @@ elfNN_ia64_hash_copy_indirect (xdir, xind) | ELF_LINK_HASH_REF_REGULAR | ELF_LINK_HASH_REF_REGULAR_NONWEAK)); + if (ind->root.root.type != bfd_link_hash_indirect) + return; + /* Copy over the got and plt data. This would have been done by check_relocs. */ @@ -1557,7 +1590,7 @@ elfNN_ia64_hash_table_create (abfd) { struct elfNN_ia64_link_hash_table *ret; - ret = bfd_alloc (abfd, sizeof (*ret)); + ret = bfd_zalloc (abfd, (bfd_size_type) sizeof (*ret)); if (!ret) return 0; if (!_bfd_elf_link_hash_table_init (&ret->root, abfd, @@ -1693,6 +1726,32 @@ elfNN_ia64_create_dynamic_sections (abfd, info) return true; } +/* 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; + boolean create; +{ + char *addr_name; + size_t len; + + /* Construct a string for use in the elfNN_ia64_local_hash_table. + name describes what was once anonymous memory. */ + + len = sizeof (void*)*2 + 1 + sizeof (bfd_vma)*4 + 1 + 1; + len += 10; /* %p slop */ + + addr_name = alloca (len); + sprintf (addr_name, "%p:%lx", + (void *) abfd, (unsigned long) ELFNN_R_SYM (rel->r_info)); + + /* Collect the canonical entry data for this address. */ + return elfNN_ia64_local_hash_lookup (&ia64_info->loc_hash_table, + addr_name, create, create); +} + /* Find and/or create a descriptor for dynamic symbol info. This will vary based on global or local symbol, and the addend to the reloc. */ @@ -1713,21 +1772,8 @@ get_dyn_sym_info (ia64_info, h, abfd, rel, create) else { struct elfNN_ia64_local_hash_entry *loc_h; - char *addr_name; - size_t len; - - /* Construct a string for use in the elfNN_ia64_local_hash_table. - The name describes what was once anonymous memory. */ - - len = sizeof (void*)*2 + 1 + sizeof (bfd_vma)*4 + 1 + 1; - len += 10; /* %p slop */ - - addr_name = alloca (len); - sprintf (addr_name, "%p:%lx", (void *) abfd, ELFNN_R_SYM (rel->r_info)); - /* Collect the canonical entry data for this address. */ - loc_h = elfNN_ia64_local_hash_lookup (&ia64_info->loc_hash_table, - addr_name, create, create); + loc_h = get_local_sym_hash (ia64_info, abfd, rel, create); BFD_ASSERT (loc_h); pp = &loc_h->info; @@ -1738,8 +1784,8 @@ get_dyn_sym_info (ia64_info, h, abfd, rel, create) if (dyn_i == NULL && create) { - dyn_i = (struct elfNN_ia64_dyn_sym_info *) - bfd_zalloc (abfd, sizeof *dyn_i); + dyn_i = ((struct elfNN_ia64_dyn_sym_info *) + bfd_zalloc (abfd, (bfd_size_type) sizeof *dyn_i)); *pp = dyn_i; dyn_i->addend = addend; } @@ -1901,6 +1947,9 @@ get_reloc_section (abfd, ia64_info, sec, create) return NULL; } + if (sec->flags & SEC_READONLY) + ia64_info->reltext = 1; + return srel; } @@ -1919,8 +1968,8 @@ count_dyn_reloc (abfd, dyn_i, srel, type) if (!rent) { - rent = (struct elfNN_ia64_dyn_reloc_entry *) - bfd_alloc (abfd, sizeof (*rent)); + rent = ((struct elfNN_ia64_dyn_reloc_entry *) + bfd_alloc (abfd, (bfd_size_type) sizeof (*rent))); if (!rent) return false; @@ -1994,7 +2043,8 @@ 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 = false; - if (h && ((info->shared && ! info->symbolic) + if (h && ((info->shared + && (!info->symbolic || info->allow_shlib_undefined)) || ! (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) || h->root.type == bfd_link_hash_defweak || elfNN_ia64_aix_vec (abfd->xvec))) @@ -2050,7 +2100,7 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs) { (*info->callbacks->warning) (info, _("@pltoff reloc against local symbol"), 0, - abfd, 0, 0); + abfd, 0, (bfd_vma) 0); } break; @@ -2108,7 +2158,7 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs) { (*info->callbacks->warning) (info, _("non-zero addend in @fptr reloc"), 0, - abfd, 0, 0); + abfd, 0, (bfd_vma) 0); } dyn_i = get_dyn_sym_info (ia64_info, h, abfd, rel, true); @@ -2144,7 +2194,7 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs) || elfNN_ia64_aix_vec (abfd->xvec))) { if (! (_bfd_elfNN_link_record_local_dynamic_symbol - (info, abfd, r_symndx))) + (info, abfd, (long) r_symndx))) return false; } @@ -2249,7 +2299,7 @@ allocate_local_got (dyn_i, data) /* Search for the index of a global symbol in it's defining object file. */ -static unsigned long +static long global_sym_index (h) struct elf_link_hash_entry *h; { @@ -2520,7 +2570,6 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info) struct elfNN_ia64_link_hash_table *ia64_info; asection *sec; bfd *dynobj; - boolean reltext = false; boolean relplt = false; dynobj = elf_hash_table(info)->dynobj; @@ -2574,7 +2623,7 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info) } /* Align the pointer for the plt2 entries. */ - data.ofs = (data.ofs + 31) & -32; + data.ofs = (data.ofs + 31) & (bfd_vma) -32; elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_plt2_entries, &data); if (data.ofs != 0) @@ -2677,24 +2726,6 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info) { if (!strip) { - const char *outname; - asection *target; - - /* If this relocation section applies to a read only - section, then we probably need a DT_TEXTREL entry. */ - outname = bfd_get_section_name (output_bfd, - sec->output_section); - if (outname[4] == 'a') - outname += 5; - else - outname += 4; - - target = bfd_get_section_by_name (output_bfd, outname); - if (target != NULL - && (target->flags & SEC_READONLY) != 0 - && (target->flags & SEC_ALLOC) != 0) - reltext = true; - /* We use the reloc_count field as a counter if we need to copy relocs into the output file. */ sec->reloc_count = 0; @@ -2709,7 +2740,7 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info) else { /* Allocate memory for the section contents. */ - sec->contents = (bfd_byte *) bfd_zalloc(dynobj, sec->_raw_size); + sec->contents = (bfd_byte *) bfd_zalloc (dynobj, sec->_raw_size); if (sec->contents == NULL && sec->_raw_size != 0) return false; } @@ -2725,32 +2756,34 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info) { /* The DT_DEBUG entry is filled in by the dynamic linker and used by the debugger. */ - if (!bfd_elfNN_add_dynamic_entry (info, DT_DEBUG, 0)) +#define add_dynamic_entry(TAG, VAL) \ + bfd_elfNN_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL)) + + if (!add_dynamic_entry (DT_DEBUG, 0)) return false; } - if (! bfd_elfNN_add_dynamic_entry (info, DT_IA_64_PLT_RESERVE, 0)) + if (!add_dynamic_entry (DT_IA_64_PLT_RESERVE, 0)) return false; - if (! bfd_elfNN_add_dynamic_entry (info, DT_PLTGOT, 0)) + if (!add_dynamic_entry (DT_PLTGOT, 0)) return false; if (relplt) { - if (! bfd_elfNN_add_dynamic_entry (info, DT_PLTRELSZ, 0) - || ! bfd_elfNN_add_dynamic_entry (info, DT_PLTREL, DT_RELA) - || ! bfd_elfNN_add_dynamic_entry (info, DT_JMPREL, 0)) + if (!add_dynamic_entry (DT_PLTRELSZ, 0) + || !add_dynamic_entry (DT_PLTREL, DT_RELA) + || !add_dynamic_entry (DT_JMPREL, 0)) return false; } - if (! bfd_elfNN_add_dynamic_entry (info, DT_RELA, 0) - || ! bfd_elfNN_add_dynamic_entry (info, DT_RELASZ, 0) - || ! bfd_elfNN_add_dynamic_entry (info, DT_RELAENT, - sizeof (ElfNN_External_Rela))) + if (!add_dynamic_entry (DT_RELA, 0) + || !add_dynamic_entry (DT_RELASZ, 0) + || !add_dynamic_entry (DT_RELAENT, sizeof (ElfNN_External_Rela))) return false; - if (reltext) + if (ia64_info->reltext) { - if (! bfd_elfNN_add_dynamic_entry (info, DT_TEXTREL, 0)) + if (!add_dynamic_entry (DT_TEXTREL, 0)) return false; info->flags |= DF_TEXTREL; } @@ -2762,10 +2795,10 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info) } static bfd_reloc_status_type -elfNN_ia64_install_value (abfd, hit_addr, val, r_type) +elfNN_ia64_install_value (abfd, hit_addr, v, r_type) bfd *abfd; bfd_byte *hit_addr; - bfd_vma val; + bfd_vma v; unsigned int r_type; { const struct ia64_operand *op; @@ -2774,6 +2807,11 @@ elfNN_ia64_install_value (abfd, hit_addr, val, r_type) enum ia64_opnd opnd; const char *err; size_t size = 8; +#ifdef BFD_HOST_U_64_BIT + BFD_HOST_U_64_BIT val = (BFD_HOST_U_64_BIT) v; +#else + bfd_vma val = v; +#endif opnd = IA64_OPND_NIL; switch (r_type) @@ -2935,7 +2973,7 @@ elfNN_ia64_install_value (abfd, hit_addr, val, r_type) insn = (dword >> shift) & 0x1ffffffffffLL; op = elf64_ia64_operands + opnd; - err = (*op->insert) (op, val, &insn); + err = (*op->insert) (op, val, (ia64_insn *)& insn); if (err) return bfd_reloc_overflow; @@ -3188,8 +3226,8 @@ static bfd *elfNN_ia64_unwind_entry_compare_bfd; static int elfNN_ia64_unwind_entry_compare (a, b) - PTR a; - PTR b; + const PTR a; + const PTR b; { bfd_vma av, bv; @@ -3350,11 +3388,13 @@ elfNN_ia64_final_link (abfd, info) if (unwind_output_sec) { elfNN_ia64_unwind_entry_compare_bfd = abfd; - qsort (unwind_output_sec->contents, unwind_output_sec->_raw_size / 24, - 24, elfNN_ia64_unwind_entry_compare); + qsort (unwind_output_sec->contents, + (size_t) (unwind_output_sec->_raw_size / 24), + 24, + elfNN_ia64_unwind_entry_compare); if (! bfd_set_section_contents (abfd, unwind_output_sec, - unwind_output_sec->contents, 0, + unwind_output_sec->contents, (bfd_vma) 0, unwind_output_sec->_raw_size)) return false; } @@ -3422,7 +3462,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, { (*_bfd_error_handler) (_("%s: unknown relocation type %d"), - bfd_get_filename (input_bfd), (int)r_type); + bfd_archive_filename (input_bfd), (int)r_type); bfd_set_error (bfd_error_bad_value); ret_val = false; continue; @@ -3460,9 +3500,38 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, /* Reloc against local symbol. */ sym = local_syms + r_symndx; sym_sec = local_sections[r_symndx]; - value = (sym_sec->output_section->vma - + sym_sec->output_offset - + sym->st_value); + value = _bfd_elf_rela_local_sym (output_bfd, sym, sym_sec, rel); + if ((sym_sec->flags & SEC_MERGE) + && ELF_ST_TYPE (sym->st_info) == STT_SECTION + && elf_section_data (sym_sec)->merge_info) + { + struct elfNN_ia64_local_hash_entry *loc_h; + + loc_h = get_local_sym_hash (ia64_info, input_bfd, rel, false); + if (loc_h && ! loc_h->sec_merge_done) + { + struct elfNN_ia64_dyn_sym_info *dynent; + asection *msec; + + for (dynent = loc_h->info; dynent; dynent = dynent->next) + { + msec = sym_sec; + dynent->addend = + _bfd_merged_section_offset (output_bfd, &msec, + elf_section_data (msec)-> + merge_info, + sym->st_value + + dynent->addend, + (bfd_vma) 0); + dynent->addend -= sym->st_value; + dynent->addend += msec->output_section->vma + + msec->output_offset + - sym_sec->output_section->vma + - sym_sec->output_offset; + } + loc_h->sec_merge_done = 1; + } + } } else { @@ -3498,7 +3567,8 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, } else if (h->root.type == bfd_link_hash_undefweak) undef_weak_ref = true; - else if (info->shared && !info->symbolic + else if (info->shared + && (!info->symbolic || info->allow_shlib_undefined) && !info->no_undefined && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) ; @@ -3536,8 +3606,9 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, if ((dynamic_symbol_p || info->shared || (elfNN_ia64_aix_vec (info->hash->creator) /* Don't emit relocs for __GLOB_DATA_PTR on AIX. */ - && (!h || strcmp (h->root.root.string, + && (!h || strcmp (h->root.root.string, "__GLOB_DATA_PTR") != 0))) + && r_symndx != 0 && (input_section->flags & SEC_ALLOC) != 0) { unsigned int dyn_r_type; @@ -3581,7 +3652,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, shared libraries. Hork. */ (*_bfd_error_handler) (_("%s: linking non-pic code in a shared library"), - bfd_get_filename (input_bfd)); + bfd_archive_filename (input_bfd)); ret_val = false; continue; } @@ -3614,7 +3685,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, { (*_bfd_error_handler) (_("%s: @gprel relocation against dynamic symbol %s"), - bfd_get_filename (input_bfd), h->root.root.string); + bfd_archive_filename (input_bfd), h->root.root.string); ret_val = false; continue; } @@ -3672,7 +3743,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, else { dynindx = (_bfd_elf_link_lookup_local_dynindx - (info, input_bfd, r_symndx)); + (info, input_bfd, (long) r_symndx)); } elfNN_ia64_install_dyn_reloc (output_bfd, info, input_section, @@ -3716,7 +3787,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, } else dynindx = (_bfd_elf_link_lookup_local_dynindx - (info, input_bfd, r_symndx)); + (info, input_bfd, (long) r_symndx)); value = 0; } @@ -3732,8 +3803,9 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, case R_IA64_PCREL64MSB: case R_IA64_PCREL64LSB: /* Install a dynamic relocation for this reloc. */ - if (dynamic_symbol_p - || elfNN_ia64_aix_vec (info->hash->creator)) + if ((dynamic_symbol_p + || elfNN_ia64_aix_vec (info->hash->creator)) + && r_symndx != 0) { BFD_ASSERT (srel != NULL); @@ -3752,7 +3824,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, { (*_bfd_error_handler) (_("%s: dynamic relocation against speculation fixup"), - bfd_get_filename (input_bfd)); + bfd_archive_filename (input_bfd)); ret_val = false; continue; } @@ -3760,7 +3832,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, { (*_bfd_error_handler) (_("%s: speculation fixup against undefined weak symbol"), - bfd_get_filename (input_bfd)); + bfd_archive_filename (input_bfd)); ret_val = false; continue; } @@ -3811,47 +3883,48 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, case R_IA64_SEGREL32LSB: case R_IA64_SEGREL64MSB: case R_IA64_SEGREL64LSB: - { - 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] == sym_sec->output_section) + 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] == sym_sec->output_section) + break; + if (i >= 0) break; - if (i >= 0) - break; - } - - if (m == NULL) - { - /* If the input section was discarded from the output, then - do nothing. */ + } - if (bfd_is_abs_section (sym_sec->output_section)) - r = bfd_reloc_ok; - else + if (m == NULL) + { r = bfd_reloc_notsupported; - } - else - { - /* The VMA of the segment is the vaddr of the associated - program header. */ - if (value > p->p_vaddr) - value -= p->p_vaddr; - else - value = 0; - r = elfNN_ia64_install_value (output_bfd, hit_addr, value, - r_type); - } - break; - } + } + else + { + /* The VMA of the segment is the vaddr of the associated + program header. */ + if (value > p->p_vaddr) + value -= p->p_vaddr; + else + value = 0; + r = elfNN_ia64_install_value (output_bfd, hit_addr, value, + r_type); + } + break; + } case R_IA64_SECREL32MSB: case R_IA64_SECREL32LSB: @@ -3970,7 +4043,8 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, name = bfd_section_name (input_bfd, input_section); } if (!(*info->callbacks->reloc_overflow) (info, name, - howto->name, 0, + howto->name, + (bfd_vma) 0, input_bfd, input_section, rel->r_offset)) @@ -4240,7 +4314,7 @@ elfNN_ia64_merge_private_bfd_data (ibfd, obfd) { (*_bfd_error_handler) (_("%s: linking trap-on-NULL-dereference with non-trapping files"), - bfd_get_filename (ibfd)); + bfd_archive_filename (ibfd)); bfd_set_error (bfd_error_bad_value); ok = false; @@ -4249,7 +4323,7 @@ elfNN_ia64_merge_private_bfd_data (ibfd, obfd) { (*_bfd_error_handler) (_("%s: linking big-endian files with little-endian files"), - bfd_get_filename (ibfd)); + bfd_archive_filename (ibfd)); bfd_set_error (bfd_error_bad_value); ok = false; @@ -4258,7 +4332,7 @@ elfNN_ia64_merge_private_bfd_data (ibfd, obfd) { (*_bfd_error_handler) (_("%s: linking 64-bit files with 32-bit files"), - bfd_get_filename (ibfd)); + bfd_archive_filename (ibfd)); bfd_set_error (bfd_error_bad_value); ok = false; @@ -4267,7 +4341,7 @@ elfNN_ia64_merge_private_bfd_data (ibfd, obfd) { (*_bfd_error_handler) (_("%s: linking constant-gp files with non-constant-gp files"), - bfd_get_filename (ibfd)); + bfd_archive_filename (ibfd)); bfd_set_error (bfd_error_bad_value); ok = false; @@ -4277,7 +4351,7 @@ elfNN_ia64_merge_private_bfd_data (ibfd, obfd) { (*_bfd_error_handler) (_("%s: linking auto-pic files with non-auto-pic files"), - bfd_get_filename (ibfd)); + bfd_archive_filename (ibfd)); bfd_set_error (bfd_error_bad_value); ok = false; @@ -4309,6 +4383,27 @@ elfNN_ia64_print_private_bfd_data (abfd, ptr) _bfd_elf_print_private_bfd_data (abfd, ptr); return true; } + +static enum elf_reloc_type_class +elfNN_ia64_reloc_type_class (rela) + const Elf_Internal_Rela *rela; +{ + switch ((int) ELFNN_R_TYPE (rela->r_info)) + { + case R_IA64_REL32MSB: + case R_IA64_REL32LSB: + case R_IA64_REL64MSB: + case R_IA64_REL64LSB: + return reloc_class_relative; + case R_IA64_IPLTMSB: + case R_IA64_IPLTLSB: + return reloc_class_plt; + case R_IA64_COPY: + return reloc_class_copy; + default: + return reloc_class_normal; + } +} #define TARGET_LITTLE_SYM bfd_elfNN_ia64_little_vec #define TARGET_LITTLE_NAME "elfNN-ia64-little" @@ -4385,6 +4480,7 @@ elfNN_ia64_print_private_bfd_data (abfd, ptr) #define elf_backend_want_dynbss 0 #define elf_backend_copy_indirect_symbol elfNN_ia64_hash_copy_indirect #define elf_backend_hide_symbol elfNN_ia64_hash_hide_symbol +#define elf_backend_reloc_type_class elfNN_ia64_reloc_type_class #include "elfNN-target.h"