X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felfxx-ia64.c;h=e0c70c11aeb86a4afdff9c75e7188ed6d5eb8d39;hb=7ac4ac061926872510858e0ff8e37673b5de28d5;hp=c8dd9c49b95eb3df8f3f8a219de4bce20a415b83;hpb=7dcb9820ee9e265f0696fc5aa65e71fde8faed03;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elfxx-ia64.c b/bfd/elfxx-ia64.c index c8dd9c49b9..e0c70c11ae 100644 --- a/bfd/elfxx-ia64.c +++ b/bfd/elfxx-ia64.c @@ -1,5 +1,6 @@ /* IA-64 support for 64-bit ELF - Copyright 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 + Free Software Foundation, Inc. Contributed by David Mosberger-Tang This file is part of BFD, the Binary File Descriptor library. @@ -24,6 +25,8 @@ #include "elf-bfd.h" #include "opcode/ia64.h" #include "elf/ia64.h" +#include "objalloc.h" +#include "hashtab.h" /* THE RULES for all the stuff the linker creates -- @@ -51,7 +54,7 @@ descriptor for a MIN_PLT entry, and requires one IPLT reloc. MIN_PLT Created by PLTOFF entries against dynamic symbols. This - does not reqire dynamic relocations. */ + does not require dynamic relocations. */ #define NELEMS(a) ((int) (sizeof (a) / sizeof ((a)[0]))) @@ -79,7 +82,7 @@ struct elfNN_ia64_dyn_sym_info bfd_vma dtpmod_offset; bfd_vma dtprel_offset; - /* The symbol table entry, if any, that this was derrived from. */ + /* The symbol table entry, if any, that this was derived from. */ struct elf_link_hash_entry *h; /* Used to count non-got, non-plt relocations for delayed sizing @@ -90,6 +93,9 @@ struct elfNN_ia64_dyn_sym_info asection *srel; int type; int count; + + /* Is this reloc against readonly section? */ + bfd_boolean reltext; } *reloc_entries; /* TRUE when the section contents have been updated. */ @@ -115,7 +121,8 @@ struct elfNN_ia64_dyn_sym_info struct elfNN_ia64_local_hash_entry { - struct bfd_hash_entry root; + int id; + unsigned int r_sym; struct elfNN_ia64_dyn_sym_info *info; /* TRUE if this hash entry's addends was translated for @@ -123,12 +130,6 @@ struct elfNN_ia64_local_hash_entry unsigned sec_merge_done : 1; }; -struct elfNN_ia64_local_hash_table -{ - struct bfd_hash_table root; - /* No additional fields for now. */ -}; - struct elfNN_ia64_link_hash_entry { struct elf_link_hash_entry root; @@ -153,7 +154,8 @@ struct elfNN_ia64_link_hash_table unsigned self_dtpmod_done : 1;/* has self DTPMOD entry been finished? */ bfd_vma self_dtpmod_offset; /* .got offset to self DTPMOD entry */ - struct elfNN_ia64_local_hash_table loc_hash_table; + htab_t loc_hash_table; + void *loc_hash_memory; }; struct elfNN_ia64_allocate_data @@ -178,35 +180,29 @@ 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 *abfd, bfd_byte *contents, bfd_vma off)); + 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_from_shdr PARAMS ((bfd *, Elf_Internal_Shdr *, const char *)); static bfd_boolean elfNN_ia64_section_flags - PARAMS ((flagword *, Elf_Internal_Shdr *)); + 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, const Elf_Internal_Sym *sym, + 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 *)); + PARAMS ((bfd *, struct bfd_link_info *)); static bfd_boolean elfNN_ia64_is_local_label_name PARAMS ((bfd *abfd, const char *name)); static bfd_boolean elfNN_ia64_dynamic_symbol_p PARAMS ((struct elf_link_hash_entry *h, struct bfd_link_info *info, int)); -static bfd_boolean elfNN_ia64_local_hash_table_init - PARAMS ((struct elfNN_ia64_local_hash_table *ht, bfd *abfd, - new_hash_entry_func new)); -static struct bfd_hash_entry *elfNN_ia64_new_loc_hash_entry - PARAMS ((struct bfd_hash_entry *entry, struct bfd_hash_table *table, - const char *string)); 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)); @@ -215,15 +211,17 @@ static void elfNN_ia64_hash_copy_indirect 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 struct elfNN_ia64_local_hash_entry *elfNN_ia64_local_hash_lookup - PARAMS ((struct elfNN_ia64_local_hash_table *table, const char *string, - bfd_boolean create, bfd_boolean copy)); +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 bfd_boolean elfNN_ia64_local_dyn_sym_thunk - PARAMS ((struct bfd_hash_entry *, PTR)); +static int elfNN_ia64_local_dyn_sym_thunk + PARAMS ((void **, PTR)); 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), @@ -249,9 +247,6 @@ static asection *get_pltoff static asection *get_reloc_section PARAMS ((bfd *abfd, struct elfNN_ia64_link_hash_table *ia64_info, asection *sec, bfd_boolean create)); -static bfd_boolean count_dyn_reloc - PARAMS ((bfd *abfd, struct elfNN_ia64_dyn_sym_info *dyn_i, - asection *srel, int type)); static bfd_boolean elfNN_ia64_check_relocs PARAMS ((bfd *abfd, struct bfd_link_info *info, asection *sec, const Elf_Internal_Rela *relocs)); @@ -278,7 +273,7 @@ static bfd_boolean allocate_dynrel_entries 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 *abfd, bfd_byte *hit_addr, bfd_vma val, unsigned int r_type)); + 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, @@ -446,21 +441,21 @@ static reloc_howto_type ia64_howto_table[] = IA64_HOWTO (R_IA64_TPREL14, "TPREL14", 0, FALSE, FALSE), IA64_HOWTO (R_IA64_TPREL22, "TPREL22", 0, FALSE, FALSE), IA64_HOWTO (R_IA64_TPREL64I, "TPREL64I", 0, FALSE, FALSE), - IA64_HOWTO (R_IA64_TPREL64MSB, "TPREL64MSB", 8, FALSE, FALSE), - IA64_HOWTO (R_IA64_TPREL64LSB, "TPREL64LSB", 8, FALSE, FALSE), + IA64_HOWTO (R_IA64_TPREL64MSB, "TPREL64MSB", 4, FALSE, FALSE), + IA64_HOWTO (R_IA64_TPREL64LSB, "TPREL64LSB", 4, FALSE, FALSE), IA64_HOWTO (R_IA64_LTOFF_TPREL22, "LTOFF_TPREL22", 0, FALSE, FALSE), - IA64_HOWTO (R_IA64_DTPMOD64MSB, "TPREL64MSB", 8, FALSE, FALSE), - IA64_HOWTO (R_IA64_DTPMOD64LSB, "TPREL64LSB", 8, FALSE, FALSE), + IA64_HOWTO (R_IA64_DTPMOD64MSB, "TPREL64MSB", 4, FALSE, FALSE), + IA64_HOWTO (R_IA64_DTPMOD64LSB, "TPREL64LSB", 4, FALSE, FALSE), IA64_HOWTO (R_IA64_LTOFF_DTPMOD22, "LTOFF_DTPMOD22", 0, FALSE, FALSE), IA64_HOWTO (R_IA64_DTPREL14, "DTPREL14", 0, FALSE, FALSE), IA64_HOWTO (R_IA64_DTPREL22, "DTPREL22", 0, FALSE, FALSE), IA64_HOWTO (R_IA64_DTPREL64I, "DTPREL64I", 0, FALSE, FALSE), - IA64_HOWTO (R_IA64_DTPREL32MSB, "DTPREL32MSB", 4, FALSE, FALSE), - IA64_HOWTO (R_IA64_DTPREL32LSB, "DTPREL32LSB", 4, FALSE, FALSE), - IA64_HOWTO (R_IA64_DTPREL64MSB, "DTPREL64MSB", 8, FALSE, FALSE), - IA64_HOWTO (R_IA64_DTPREL64LSB, "DTPREL64LSB", 8, FALSE, FALSE), + IA64_HOWTO (R_IA64_DTPREL32MSB, "DTPREL32MSB", 2, FALSE, FALSE), + IA64_HOWTO (R_IA64_DTPREL32LSB, "DTPREL32LSB", 2, FALSE, FALSE), + IA64_HOWTO (R_IA64_DTPREL64MSB, "DTPREL64MSB", 4, FALSE, FALSE), + IA64_HOWTO (R_IA64_DTPREL64LSB, "DTPREL64LSB", 4, FALSE, FALSE), IA64_HOWTO (R_IA64_LTOFF_DTPREL22, "LTOFF_DTPREL22", 0, FALSE, FALSE), }; @@ -641,7 +636,7 @@ static const bfd_byte plt_min_entry[PLT_MIN_ENTRY_SIZE] = static const bfd_byte plt_full_entry[PLT_FULL_ENTRY_SIZE] = { 0x0b, 0x78, 0x00, 0x02, 0x00, 0x24, /* [MMI] addl r15=0,r1;; */ - 0x00, 0x41, 0x3c, 0x30, 0x28, 0xc0, /* ld8 r16=[r15],8 */ + 0x00, 0x41, 0x3c, 0x70, 0x29, 0xc0, /* ld8.acq r16=[r15],8*/ 0x01, 0x08, 0x00, 0x84, /* mov r14=r1;; */ 0x11, 0x08, 0x00, 0x1e, 0x18, 0x10, /* [MIB] ld8 r1=[r15] */ 0x60, 0x80, 0x04, 0x80, 0x03, 0x00, /* mov b6=r16 */ @@ -656,6 +651,58 @@ static const bfd_byte oor_brl[16] = 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* brl.sptk.few tgt;; */ 0x00, 0x00, 0x00, 0xc0 }; + +static const bfd_byte oor_ip[48] = +{ + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MLX] nop.m 0 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, /* movl r15=0 */ + 0x01, 0x00, 0x00, 0x60, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MII] nop.m 0 */ + 0x00, 0x01, 0x00, 0x60, 0x00, 0x00, /* mov r16=ip;; */ + 0xf2, 0x80, 0x00, 0x80, /* add r16=r15,r16;; */ + 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MIB] nop.m 0 */ + 0x60, 0x80, 0x04, 0x80, 0x03, 0x00, /* mov b6=r16 */ + 0x60, 0x00, 0x80, 0x00 /* br b6;; */ +}; + +static size_t oor_branch_size = sizeof (oor_brl); + +void +bfd_elfNN_ia64_after_parse (int itanium) +{ + oor_branch_size = itanium ? sizeof (oor_ip) : sizeof (oor_brl); +} + +static void +elfNN_ia64_relax_brl (bfd_byte *contents, bfd_vma off) +{ + int template; + bfd_byte *hit_addr; + bfd_vma t0, t1, i0, i1, i2; + + hit_addr = (bfd_byte *) (contents + off); + hit_addr -= (long) hit_addr & 0x3; + t0 = bfd_getl64 (hit_addr); + t1 = bfd_getl64 (hit_addr + 8); + + /* Keep the instruction in slot 0. */ + i0 = (t0 >> 5) & 0x1ffffffffffLL; + /* Use nop.b for slot 1. */ + i1 = 0x4000000000LL; + /* For slot 2, turn brl into br by masking out bit 40. */ + i2 = (t1 >> 23) & 0x0ffffffffffLL; + + /* Turn a MLX bundle into a MBB bundle with the same stop-bit + variety. */ + template = 0x12; + if ((t0 & 0x1fLL) == 5) + template += 1; + t0 = (i1 << 46) | (i0 << 5) | template; + t1 = (i2 << 23) | (i1 >> 18); + + bfd_putl64 (t0, hit_addr); + bfd_putl64 (t1, hit_addr + 8); +} /* These functions do relaxation for IA-64 ELF. */ @@ -691,22 +738,17 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) *again = FALSE; /* Don't even try to relax for non-ELF outputs. */ - if (link_info->hash->creator->flavour != bfd_target_elf_flavour) + if (!is_elf_hash_table (link_info->hash)) return FALSE; /* Nothing to do if there are no relocations or there is no need for the relax finalize pass. */ if ((sec->flags & SEC_RELOC) == 0 || sec->reloc_count == 0 - || (link_info->relax_finalizing + || (!link_info->need_relax_finalize && sec->need_finalize_relax == 0)) return TRUE; - /* If this is the first time we have been called for this section, - initialize the cooked size. */ - if (sec->_cooked_size == 0) - sec->_cooked_size = sec->_raw_size; - symtab_hdr = &elf_tdata (abfd)->symtab_hdr; /* Load the relocations for this section. */ @@ -724,12 +766,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) contents = elf_section_data (sec)->this_hdr.contents; else { - contents = (bfd_byte *) bfd_malloc (sec->_raw_size); - if (contents == NULL) - goto error_return; - - if (! bfd_get_section_contents (abfd, sec, contents, - (file_ptr) 0, sec->_raw_size)) + if (!bfd_malloc_and_get_section (abfd, sec, &contents)) goto error_return; } @@ -742,6 +779,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) bfd_size_type amt; bfd_boolean is_branch; struct elfNN_ia64_dyn_sym_info *dyn_i; + char symtype; switch (r_type) { @@ -749,14 +787,31 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) case R_IA64_PCREL21BI: case R_IA64_PCREL21M: case R_IA64_PCREL21F: - if (link_info->relax_finalizing) + /* In the finalize pass, all br relaxations are done. We can + skip it. */ + if (!link_info->need_relax_finalize) continue; is_branch = TRUE; break; + case R_IA64_PCREL60B: + /* We can't optimize brl to br before the finalize pass since + br relaxations will increase the code size. Defer it to + the finalize pass. */ + if (link_info->need_relax_finalize) + { + sec->need_finalize_relax = 1; + continue; + } + is_branch = TRUE; + break; + case R_IA64_LTOFF22X: case R_IA64_LDXMOV: - if (!link_info->relax_finalizing) + /* We can't relax ldx/mov before the finalize pass since + br relaxations will increase the code size. Defer it to + the finalize pass. */ + if (link_info->need_relax_finalize) { sec->need_finalize_relax = 1; continue; @@ -788,7 +843,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) isym = isymbuf + ELFNN_R_SYM (irel->r_info); if (isym->st_shndx == SHN_UNDEF) - continue; /* We can't do anthing with undefined symbols. */ + continue; /* We can't do anything with undefined symbols. */ else if (isym->st_shndx == SHN_ABS) tsec = bfd_abs_section_ptr; else if (isym->st_shndx == SHN_COMMON) @@ -800,6 +855,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) toff = isym->st_value; dyn_i = get_dyn_sym_info (ia64_info, NULL, abfd, irel, FALSE); + symtype = ELF_ST_TYPE (isym->st_info); } else { @@ -836,7 +892,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) else { - /* We can't do anthing with undefined symbols. */ + /* We can't do anything with undefined symbols. */ if (h->root.type == bfd_link_hash_undefined || h->root.type == bfd_link_hash_undefweak) continue; @@ -844,13 +900,38 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) tsec = h->root.u.def.section; toff = h->root.u.def.value; } + + symtype = h->type; } if (tsec->sec_info_type == ELF_INFO_TYPE_MERGE) - toff = _bfd_merged_section_offset (abfd, &tsec, - elf_section_data (tsec)->sec_info, - toff + irel->r_addend, - (bfd_vma) 0); + { + /* At this stage in linking, no SEC_MERGE symbol has been + adjusted, so all references to such symbols need to be + passed through _bfd_merged_section_offset. (Later, in + relocate_section, all SEC_MERGE symbols *except* for + section symbols have been adjusted.) + + gas may reduce relocations against symbols in SEC_MERGE + sections to a relocation against the section symbol when + the original addend was zero. When the reloc is against + a section symbol we should include the addend in the + offset passed to _bfd_merged_section_offset, since the + location of interest is the original symbol. On the + other hand, an access to "sym+addend" where "sym" is not + a section symbol should not include the addend; Such an + access is presumed to be an offset from "sym"; The + location of interest is just "sym". */ + if (symtype == STT_SECTION) + toff += irel->r_addend; + + toff = _bfd_merged_section_offset (abfd, &tsec, + elf_section_data (tsec)->sec_info, + toff); + + if (symtype != STT_SECTION) + toff += irel->r_addend; + } else toff += irel->r_addend; @@ -860,6 +941,8 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) if (is_branch) { + bfd_signed_vma offset; + reladdr = (sec->output_section->vma + sec->output_offset + roff) & (bfd_vma) -4; @@ -867,8 +950,40 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) /* If the branch is in range, no need to do anything. */ if ((bfd_signed_vma) (symaddr - reladdr) >= -0x1000000 && (bfd_signed_vma) (symaddr - reladdr) <= 0x0FFFFF0) + { + /* If the 60-bit branch is in 21-bit range, optimize it. */ + if (r_type == R_IA64_PCREL60B) + { + elfNN_ia64_relax_brl (contents, roff); + + irel->r_info + = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), + R_IA64_PCREL21B); + + /* If the original relocation offset points to slot + 1, change it to slot 2. */ + if ((irel->r_offset & 3) == 1) + irel->r_offset += 1; + } + + continue; + } + else if (r_type == R_IA64_PCREL60B) continue; + /* We can't put a trampoline in a .init/.fini section. Issue + an error. */ + if (strcmp (sec->output_section->name, ".init") == 0 + || strcmp (sec->output_section->name, ".fini") == 0) + { + (*_bfd_error_handler) + (_("%s: Can't relax br at 0x%lx in section `%s'. Please use brl or indirect branch."), + bfd_archive_filename (sec->owner), + (unsigned long) roff, sec->name); + bfd_set_error (bfd_error_bad_value); + goto error_return; + } + /* If the branch and target are in the same section, you've got one honking big section and we can't help you. You'll get an error message later. */ @@ -891,17 +1006,22 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) if (tsec == ia64_info->plt_sec) size = sizeof (plt_full_entry); else - { - size = sizeof (oor_brl); - } + size = oor_branch_size; /* Resize the current section to make room for the new branch. */ - trampoff = (sec->_cooked_size + 15) & (bfd_vma) -16; + trampoff = (sec->size + 15) & (bfd_vma) -16; + + /* If trampoline is out of range, there is nothing we + can do. */ + offset = trampoff - (roff & (bfd_vma) -4); + if (offset < -0x1000000 || offset > 0x0FFFFF0) + continue; + amt = trampoff + size; contents = (bfd_byte *) bfd_realloc (contents, amt); if (contents == NULL) goto error_return; - sec->_cooked_size = amt; + sec->size = amt; if (tsec == ia64_info->plt_sec) { @@ -914,10 +1034,22 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) } else { - memcpy (contents + trampoff, oor_brl, size); - irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info), - R_IA64_PCREL60B); - irel->r_offset = trampoff + 2; + if (size == sizeof (oor_ip)) + { + memcpy (contents + trampoff, oor_ip, size); + irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info), + R_IA64_PCREL64I); + irel->r_addend -= 16; + irel->r_offset = trampoff + 2; + } + else + { + memcpy (contents + trampoff, oor_brl, size); + irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info), + R_IA64_PCREL60B); + irel->r_offset = trampoff + 2; + } + } /* Record the fixup so we don't do it again this section. */ @@ -931,15 +1063,19 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) } else { + /* If trampoline is out of range, there is nothing we + can do. */ + offset = f->trampoff - (roff & (bfd_vma) -4); + if (offset < -0x1000000 || offset > 0x0FFFFF0) + continue; + /* Nop out the reloc, since we're finalizing things here. */ irel->r_info = ELFNN_R_INFO (0, R_IA64_NONE); } - /* 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 & (bfd_vma) -4), - r_type) != bfd_reloc_ok) + /* Fix up the existing branch to hit the trampoline. */ + if (elfNN_ia64_install_value (contents + roff, offset, r_type) + != bfd_reloc_ok) goto error_return; changed_contents = TRUE; @@ -978,7 +1114,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) } else { - elfNN_ia64_relax_ldxmov (abfd, contents, roff); + elfNN_ia64_relax_ldxmov (contents, roff); irel->r_info = ELFNN_R_INFO (0, R_IA64_NONE); changed_contents = TRUE; changed_relocs = TRUE; @@ -1041,13 +1177,12 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_data_got, &data); elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_fptr_got, &data); elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_local_got, &data); - ia64_info->got_sec->_raw_size = data.ofs; - ia64_info->got_sec->_cooked_size = data.ofs; + ia64_info->got_sec->size = data.ofs; /* ??? Resize .rela.got too. */ } - if (link_info->relax_finalizing) + if (!link_info->need_relax_finalize) sec->need_finalize_relax = 0; *again = changed_contents || changed_relocs; @@ -1066,8 +1201,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) } static void -elfNN_ia64_relax_ldxmov (abfd, contents, off) - bfd *abfd; +elfNN_ia64_relax_ldxmov (contents, off) bfd_byte *contents; bfd_vma off; { @@ -1083,7 +1217,7 @@ elfNN_ia64_relax_ldxmov (abfd, contents, off) abort (); } - dword = bfd_get_64 (abfd, contents + off); + dword = bfd_getl64 (contents + off); insn = (dword >> shift) & 0x1ffffffffffLL; r1 = (insn >> 6) & 127; @@ -1095,7 +1229,7 @@ elfNN_ia64_relax_ldxmov (abfd, contents, off) dword &= ~(0x1ffffffffffLL << shift); dword |= (insn << shift); - bfd_put_64 (abfd, dword, contents + off); + bfd_putl64 (dword, contents + off); } /* Return TRUE if NAME is an unwind table section name. */ @@ -1165,7 +1299,7 @@ elfNN_ia64_section_from_shdr (abfd, hdr, name) static bfd_boolean elfNN_ia64_section_flags (flags, hdr) flagword *flags; - Elf_Internal_Shdr *hdr; + const Elf_Internal_Shdr *hdr; { if (hdr->sh_flags & SHF_IA_64_SHORT) *flags |= SEC_SMALL_DATA; @@ -1324,7 +1458,7 @@ static bfd_boolean elfNN_ia64_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) bfd *abfd; struct bfd_link_info *info; - const Elf_Internal_Sym *sym; + Elf_Internal_Sym *sym; const char **namep ATTRIBUTE_UNUSED; flagword *flagsp ATTRIBUTE_UNUSED; asection **secp; @@ -1379,8 +1513,9 @@ elfNN_ia64_additional_program_headers (abfd) } static bfd_boolean -elfNN_ia64_modify_segment_map (abfd) +elfNN_ia64_modify_segment_map (abfd, info) bfd *abfd; + struct bfd_link_info *info ATTRIBUTE_UNUSED; { struct elf_segment_map *m, **pm; Elf_Internal_Shdr *hdr; @@ -1520,44 +1655,6 @@ elfNN_ia64_dynamic_symbol_p (h, info, r_type) return _bfd_elf_dynamic_symbol_p (h, info, ignore_protected); } -static bfd_boolean -elfNN_ia64_local_hash_table_init (ht, abfd, new) - struct elfNN_ia64_local_hash_table *ht; - bfd *abfd ATTRIBUTE_UNUSED; - new_hash_entry_func new; -{ - memset (ht, 0, sizeof (*ht)); - return bfd_hash_table_init (&ht->root, new); -} - -static struct bfd_hash_entry* -elfNN_ia64_new_loc_hash_entry (entry, table, string) - struct bfd_hash_entry *entry; - struct bfd_hash_table *table; - const char *string; -{ - struct elfNN_ia64_local_hash_entry *ret; - ret = (struct elfNN_ia64_local_hash_entry *) entry; - - /* Allocate the structure if it has not already been allocated by a - subclass. */ - if (!ret) - ret = bfd_hash_allocate (table, sizeof (*ret)); - - if (!ret) - return 0; - - /* Initialize our local data. All zeros, and definitely easier - than setting a handful of bit fields. */ - memset (ret, 0, sizeof (*ret)); - - /* Call the allocation method of the superclass. */ - ret = ((struct elfNN_ia64_local_hash_entry *) - bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); - - return (struct bfd_hash_entry *) ret; -} - static struct bfd_hash_entry* elfNN_ia64_new_elf_hash_entry (entry, table, string) struct bfd_hash_entry *entry; @@ -1604,7 +1701,8 @@ elfNN_ia64_hash_copy_indirect (bed, xdir, xind) (ind->root.elf_link_hash_flags & (ELF_LINK_HASH_REF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR - | ELF_LINK_HASH_REF_REGULAR_NONWEAK)); + | ELF_LINK_HASH_REF_REGULAR_NONWEAK + | ELF_LINK_HASH_NEEDS_PLT)); if (ind->root.root.type != bfd_link_hash_indirect) return; @@ -1657,6 +1755,33 @@ 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; +{ + struct elfNN_ia64_local_hash_entry *entry + = (struct elfNN_ia64_local_hash_entry *) ptr; + + return (((entry->id & 0xff) << 24) | ((entry->id & 0xff00) << 8)) + ^ entry->r_sym ^ (entry->id >> 16); +} + +/* Compare local hash entries. */ + +static int +elfNN_ia64_local_htab_eq (ptr1, ptr2) + const void *ptr1, *ptr2; +{ + struct elfNN_ia64_local_hash_entry *entry1 + = (struct elfNN_ia64_local_hash_entry *) ptr1; + struct elfNN_ia64_local_hash_entry *entry2 + = (struct elfNN_ia64_local_hash_entry *) ptr2; + + return entry1->id == entry2->id && entry1->r_sym == entry2->r_sym; +} + /* Create the derived linker hash table. The IA-64 ELF port uses this derived hash table to keep information specific to the IA-64 ElF linker (without using static variables). */ @@ -1678,8 +1803,10 @@ elfNN_ia64_hash_table_create (abfd) return 0; } - if (!elfNN_ia64_local_hash_table_init (&ret->loc_hash_table, abfd, - elfNN_ia64_new_loc_hash_entry)) + ret->loc_hash_table = htab_try_create (1024, elfNN_ia64_local_htab_hash, + elfNN_ia64_local_htab_eq, NULL); + ret->loc_hash_memory = objalloc_create (); + if (!ret->loc_hash_table || !ret->loc_hash_memory) { free (ret); return 0; @@ -1688,16 +1815,19 @@ elfNN_ia64_hash_table_create (abfd) return &ret->root.root; } -/* Look up an entry in a Alpha ELF linker hash table. */ +/* Destroy IA-64 linker hash table. */ -static INLINE struct elfNN_ia64_local_hash_entry * -elfNN_ia64_local_hash_lookup(table, string, create, copy) - struct elfNN_ia64_local_hash_table *table; - const char *string; - bfd_boolean create, copy; +static void +elfNN_ia64_hash_table_free (hash) + struct bfd_link_hash_table *hash; { - return ((struct elfNN_ia64_local_hash_entry *) - bfd_hash_lookup (&table->root, string, create, copy)); + struct elfNN_ia64_link_hash_table *ia64_info + = (struct elfNN_ia64_link_hash_table *) hash; + if (ia64_info->loc_hash_table) + htab_delete (ia64_info->loc_hash_table); + if (ia64_info->loc_hash_memory) + objalloc_free ((struct objalloc *) ia64_info->loc_hash_memory); + _bfd_generic_link_hash_table_free (hash); } /* Traverse both local and global hash tables. */ @@ -1729,20 +1859,20 @@ elfNN_ia64_global_dyn_sym_thunk (xentry, xdata) } static bfd_boolean -elfNN_ia64_local_dyn_sym_thunk (xentry, xdata) - struct bfd_hash_entry *xentry; +elfNN_ia64_local_dyn_sym_thunk (slot, xdata) + void **slot; PTR xdata; { struct elfNN_ia64_local_hash_entry *entry - = (struct elfNN_ia64_local_hash_entry *) xentry; + = (struct elfNN_ia64_local_hash_entry *) *slot; struct elfNN_ia64_dyn_sym_traverse_data *data = (struct elfNN_ia64_dyn_sym_traverse_data *) xdata; struct elfNN_ia64_dyn_sym_info *dyn_i; for (dyn_i = entry->info; dyn_i; dyn_i = dyn_i->next) if (! (*data->func) (dyn_i, data->data)) - return FALSE; - return TRUE; + return 0; + return 1; } static void @@ -1758,8 +1888,8 @@ elfNN_ia64_dyn_sym_traverse (ia64_info, func, data) elf_link_hash_traverse (&ia64_info->root, elfNN_ia64_global_dyn_sym_thunk, &xdata); - bfd_hash_traverse (&ia64_info->loc_hash_table.root, - elfNN_ia64_local_dyn_sym_thunk, &xdata); + htab_traverse (ia64_info->loc_hash_table, + elfNN_ia64_local_dyn_sym_thunk, &xdata); } static bfd_boolean @@ -1821,22 +1951,33 @@ get_local_sym_hash (ia64_info, abfd, rel, create) const Elf_Internal_Rela *rel; bfd_boolean create; { - struct elfNN_ia64_local_hash_entry *ret; + struct elfNN_ia64_local_hash_entry e, *ret; asection *sec = abfd->sections; - char addr_name [34]; + hashval_t h = (((sec->id & 0xff) << 24) | ((sec->id & 0xff00) << 8)) + ^ ELFNN_R_SYM (rel->r_info) ^ (sec->id >> 16); + void **slot; - BFD_ASSERT ((sizeof (sec->id)*2 + 1 + sizeof (unsigned long)*2 + 1) <= 34); - BFD_ASSERT (sec); + e.id = sec->id; + e.r_sym = ELFNN_R_SYM (rel->r_info); + slot = htab_find_slot_with_hash (ia64_info->loc_hash_table, &e, h, + create ? INSERT : NO_INSERT); - /* Construct a string for use in the elfNN_ia64_local_hash_table. - name describes what was once anonymous memory. */ + if (!slot) + return NULL; - sprintf (addr_name, "%x:%lx", - sec->id, (unsigned long) ELFNN_R_SYM (rel->r_info)); + if (*slot) + return (struct elfNN_ia64_local_hash_entry *) *slot; - /* Collect the canonical entry data for this address. */ - ret = elfNN_ia64_local_hash_lookup (&ia64_info->loc_hash_table, - addr_name, create, create); + ret = (struct elfNN_ia64_local_hash_entry *) + objalloc_alloc ((struct objalloc *) ia64_info->loc_hash_memory, + sizeof (struct elfNN_ia64_local_hash_entry)); + if (ret) + { + memset (ret, 0, sizeof (*ret)); + ret->id = sec->id; + ret->r_sym = ELFNN_R_SYM (rel->r_info); + *slot = ret; + } return ret; } @@ -1921,7 +2062,7 @@ get_got (abfd, info, ia64_info) } /* Create function descriptor section (.opd). This section is called .opd - because it contains "official prodecure descriptors". The "official" + because it contains "official procedure descriptors". The "official" refers to the fact that these descriptors are used when taking the address of a procedure, thus ensuring a unique address for each procedure. */ @@ -1961,9 +2102,9 @@ get_fptr (abfd, info, ia64_info) if (info->pie) { asection *fptr_rel; - fptr_rel = bfd_make_section(abfd, ".rela.opd"); + fptr_rel = bfd_make_section(dynobj, ".rela.opd"); if (fptr_rel == NULL - || !bfd_set_section_flags (abfd, fptr_rel, + || !bfd_set_section_flags (dynobj, fptr_rel, (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY @@ -2063,18 +2204,12 @@ get_reloc_section (abfd, ia64_info, sec, create) return NULL; } - if (sec->flags & SEC_READONLY) - ia64_info->reltext = 1; - return srel; } static bfd_boolean -count_dyn_reloc (abfd, dyn_i, srel, type) - bfd *abfd; - struct elfNN_ia64_dyn_sym_info *dyn_i; - asection *srel; - int type; +count_dyn_reloc (bfd *abfd, struct elfNN_ia64_dyn_sym_info *dyn_i, + asection *srel, int type, bfd_boolean reltext) { struct elfNN_ia64_dyn_reloc_entry *rent; @@ -2095,6 +2230,7 @@ count_dyn_reloc (abfd, dyn_i, srel, type) rent->count = 0; dyn_i->reloc_entries = rent; } + rent->reltext = reltext; rent->count++; return TRUE; @@ -2111,7 +2247,7 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs) const Elf_Internal_Rela *relend; Elf_Internal_Shdr *symtab_hdr; const Elf_Internal_Rela *rel; - asection *got, *fptr, *srel; + asection *got, *fptr, *srel, *pltoff; if (info->relocatable) return TRUE; @@ -2119,7 +2255,7 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs) symtab_hdr = &elf_tdata (abfd)->symtab_hdr; ia64_info = elfNN_ia64_hash_table (info); - got = fptr = srel = NULL; + got = fptr = srel = pltoff = NULL; relend = relocs + sec->reloc_count; for (rel = relocs; rel < relend; ++rel) @@ -2351,7 +2487,7 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs) dynamic symbol table. */ if (!h && info->shared) { - if (! (_bfd_elfNN_link_record_local_dynamic_symbol + if (! (bfd_elf_link_record_local_dynamic_symbol (info, abfd, (long) r_symndx))) return FALSE; } @@ -2370,7 +2506,18 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs) if (need_entry & NEED_FULL_PLT) dyn_i->want_plt2 = 1; if (need_entry & NEED_PLTOFF) - dyn_i->want_pltoff = 1; + { + /* This is needed here, in case @pltoff is used in a non-shared + link. */ + if (!pltoff) + { + pltoff = get_pltoff (abfd, info, ia64_info); + if (!pltoff) + return FALSE; + } + + dyn_i->want_pltoff = 1; + } if ((need_entry & NEED_DYNREL) && (sec->flags & SEC_ALLOC)) { if (!srel) @@ -2379,7 +2526,8 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs) if (!srel) return FALSE; } - if (!count_dyn_reloc (abfd, dyn_i, srel, dynrel_type)) + if (!count_dyn_reloc (abfd, dyn_i, srel, dynrel_type, + (sec->flags & SEC_READONLY) != 0)) return FALSE; } } @@ -2522,7 +2670,7 @@ allocate_fptr (dyn_i, data) BFD_ASSERT ((h->root.type == bfd_link_hash_defined) || (h->root.type == bfd_link_hash_defweak)); - if (!_bfd_elfNN_link_record_local_dynamic_symbol + if (!bfd_elf_link_record_local_dynamic_symbol (x->info, h->root.u.def.section->owner, global_sym_index (h))) return FALSE; @@ -2686,7 +2834,9 @@ allocate_dynrel_entries (dyn_i, data) default: abort (); } - rent->srel->_raw_size += sizeof (ElfNN_External_Rela) * count; + if (rent->reltext) + ia64_info->reltext = 1; + rent->srel->size += sizeof (ElfNN_External_Rela) * count; } /* Take care of the GOT and PLT relocations. */ @@ -2702,18 +2852,18 @@ allocate_dynrel_entries (dyn_i, data) || !x->info->pie || dyn_i->h == NULL || dyn_i->h->root.type != bfd_link_hash_undefweak) - ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela); + ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela); } if ((dynamic_symbol || shared) && dyn_i->want_tprel) - ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela); + ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela); if (dynamic_symbol && dyn_i->want_dtpmod) - ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela); + ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela); if (dynamic_symbol && dyn_i->want_dtprel) - ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela); + ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela); if (ia64_info->rel_fptr_sec && dyn_i->want_fptr) { if (dyn_i->h == NULL || dyn_i->h->root.type != bfd_link_hash_undefweak) - ia64_info->rel_fptr_sec->_raw_size += sizeof (ElfNN_External_Rela); + ia64_info->rel_fptr_sec->size += sizeof (ElfNN_External_Rela); } if (!resolved_zero && dyn_i->want_pltoff) @@ -2728,7 +2878,7 @@ allocate_dynrel_entries (dyn_i, data) else if (shared) t = 2 * sizeof (ElfNN_External_Rela); - ia64_info->rel_pltoff_sec->_raw_size += t; + ia64_info->rel_pltoff_sec->size += t; } return TRUE; @@ -2788,7 +2938,7 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info) sec = bfd_get_section_by_name (dynobj, ".interp"); BFD_ASSERT (sec != NULL); sec->contents = (bfd_byte *) ELF_DYNAMIC_INTERPRETER; - sec->_raw_size = strlen (ELF_DYNAMIC_INTERPRETER) + 1; + sec->size = strlen (ELF_DYNAMIC_INTERPRETER) + 1; } /* Allocate the GOT entries. */ @@ -2799,7 +2949,7 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info) elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_data_got, &data); elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_fptr_got, &data); elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_local_got, &data); - ia64_info->got_sec->_raw_size = data.ofs; + ia64_info->got_sec->size = data.ofs; } /* Allocate the FPTR entries. */ @@ -2808,7 +2958,7 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info) { data.ofs = 0; elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_fptr, &data); - ia64_info->fptr_sec->_raw_size = data.ofs; + ia64_info->fptr_sec->size = data.ofs; } /* Now that we've seen all of the input files, we can decide which @@ -2830,16 +2980,20 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info) data.ofs = (data.ofs + 31) & (bfd_vma) -32; elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_plt2_entries, &data); - if (data.ofs != 0) + if (data.ofs != 0 || ia64_info->root.dynamic_sections_created) { + /* FIXME: we always reserve the memory for dynamic linker even if + there are no PLT entries since dynamic linker may assume the + reserved memory always exists. */ + BFD_ASSERT (ia64_info->root.dynamic_sections_created); - ia64_info->plt_sec->_raw_size = data.ofs; + ia64_info->plt_sec->size = data.ofs; /* If we've got a .plt, we need some extra memory for the dynamic linker. We stuff these in .got.plt. */ sec = bfd_get_section_by_name (dynobj, ".got.plt"); - sec->_raw_size = 8 * PLT_RESERVED_WORDS; + sec->size = 8 * PLT_RESERVED_WORDS; } /* Allocate the PLTOFF entries. */ @@ -2848,7 +3002,7 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info) { data.ofs = 0; elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_pltoff_entries, &data); - ia64_info->pltoff_sec->_raw_size = data.ofs; + ia64_info->pltoff_sec->size = data.ofs; } if (ia64_info->root.dynamic_sections_created) @@ -2857,7 +3011,7 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info) required. */ if (info->shared && ia64_info->self_dtpmod_offset != (bfd_vma) -1) - ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela); + ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela); elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_dynrel_entries, &data); } @@ -2878,7 +3032,7 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info) function which decides whether anything needs to go into these sections. */ - strip = (sec->_raw_size == 0); + strip = (sec->size == 0); if (sec == ia64_info->got_sec) strip = FALSE; @@ -2896,6 +3050,15 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info) if (strip) ia64_info->fptr_sec = NULL; } + else if (sec == ia64_info->rel_fptr_sec) + { + if (strip) + ia64_info->rel_fptr_sec = NULL; + else + /* We use the reloc_count field as a counter if we need to + copy relocs into the output file. */ + sec->reloc_count = 0; + } else if (sec == ia64_info->plt_sec) { if (strip) @@ -2946,8 +3109,8 @@ 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); - if (sec->contents == NULL && sec->_raw_size != 0) + sec->contents = (bfd_byte *) bfd_zalloc (dynobj, sec->size); + if (sec->contents == NULL && sec->size != 0) return FALSE; } } @@ -2963,7 +3126,7 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info) /* The DT_DEBUG entry is filled in by the dynamic linker and used by the debugger. */ #define add_dynamic_entry(TAG, VAL) \ - bfd_elfNN_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL)) + _bfd_elf_add_dynamic_entry (info, TAG, VAL) if (!add_dynamic_entry (DT_DEBUG, 0)) return FALSE; @@ -3001,8 +3164,7 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info) } static bfd_reloc_status_type -elfNN_ia64_install_value (abfd, hit_addr, v, r_type) - bfd *abfd; +elfNN_ia64_install_value (hit_addr, v, r_type) bfd_byte *hit_addr; bfd_vma v; unsigned int r_type; @@ -3134,8 +3296,8 @@ elfNN_ia64_install_value (abfd, hit_addr, v, r_type) { case IA64_OPND_IMMU64: hit_addr -= (long) hit_addr & 0x3; - t0 = bfd_get_64 (abfd, hit_addr); - t1 = bfd_get_64 (abfd, hit_addr + 8); + t0 = bfd_getl64 (hit_addr); + t1 = bfd_getl64 (hit_addr + 8); /* tmpl/s: bits 0.. 5 in t0 slot 0: bits 5..45 in t0 @@ -3157,14 +3319,14 @@ elfNN_ia64_install_value (abfd, hit_addr, v, r_type) | (((val >> 21) & 0x001) << 21) /* ic */ | (((val >> 63) & 0x001) << 36)) << 23; /* i */ - bfd_put_64 (abfd, t0, hit_addr); - bfd_put_64 (abfd, t1, hit_addr + 8); + bfd_putl64 (t0, hit_addr); + bfd_putl64 (t1, hit_addr + 8); break; case IA64_OPND_TGT64: hit_addr -= (long) hit_addr & 0x3; - t0 = bfd_get_64 (abfd, hit_addr); - t1 = bfd_get_64 (abfd, hit_addr + 8); + t0 = bfd_getl64 (hit_addr); + t1 = bfd_getl64 (hit_addr + 8); /* tmpl/s: bits 0.. 5 in t0 slot 0: bits 5..45 in t0 @@ -3182,8 +3344,8 @@ elfNN_ia64_install_value (abfd, hit_addr, v, r_type) t1 |= ((((val >> 0) & 0xfffffLL) << 13) /* imm20b */ | (((val >> 59) & 0x1LL) << 36)) << 23; /* i */ - bfd_put_64 (abfd, t0, hit_addr); - bfd_put_64 (abfd, t1, hit_addr + 8); + bfd_putl64 (t0, hit_addr); + bfd_putl64 (t1, hit_addr + 8); break; default: @@ -3194,7 +3356,7 @@ elfNN_ia64_install_value (abfd, hit_addr, v, r_type) case 2: shift = 23; hit_addr += 6; break; case 3: return bfd_reloc_notsupported; /* shouldn't happen... */ } - dword = bfd_get_64 (abfd, hit_addr); + dword = bfd_getl64 (hit_addr); insn = (dword >> shift) & 0x1ffffffffffLL; op = elf64_ia64_operands + opnd; @@ -3204,7 +3366,7 @@ elfNN_ia64_install_value (abfd, hit_addr, v, r_type) dword &= ~(0x1ffffffffffLL << shift); dword |= (insn << shift); - bfd_put_64 (abfd, dword, hit_addr); + bfd_putl64 (dword, hit_addr); break; case IA64_OPND_NIL: @@ -3258,8 +3420,7 @@ elfNN_ia64_install_dyn_reloc (abfd, info, sec, srel, offset, type, loc = srel->contents; loc += srel->reloc_count++ * sizeof (ElfNN_External_Rela); bfd_elfNN_swap_reloca_out (abfd, &outrel, loc); - BFD_ASSERT (sizeof (ElfNN_External_Rela) * srel->reloc_count - <= srel->_cooked_size); + BFD_ASSERT (sizeof (ElfNN_External_Rela) * srel->reloc_count <= srel->size); } /* Store an entry for target address TARGET_ADDR in the linkage table @@ -3513,12 +3674,10 @@ static bfd_vma elfNN_ia64_tprel_base (info) struct bfd_link_info *info; { - struct elf_link_tls_segment *tls_segment - = elf_hash_table (info)->tls_segment; + asection *tls_sec = elf_hash_table (info)->tls_sec; - BFD_ASSERT (tls_segment != NULL); - return (tls_segment->start - - align_power ((bfd_vma) 16, tls_segment->align)); + BFD_ASSERT (tls_sec != NULL); + return tls_sec->vma - align_power ((bfd_vma) 16, tls_sec->alignment_power); } /* Return the base VMA address which should be subtracted from real addresses @@ -3529,8 +3688,8 @@ static bfd_vma elfNN_ia64_dtprel_base (info) struct bfd_link_info *info; { - BFD_ASSERT (elf_hash_table (info)->tls_segment != NULL); - return elf_hash_table (info)->tls_segment->start; + BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL); + return elf_hash_table (info)->tls_sec->vma; } /* Called through qsort to sort the .IA_64.unwind section during a @@ -3577,7 +3736,7 @@ elfNN_ia64_choose_gp (abfd, info) continue; lo = os->vma; - hi = os->vma + os->_raw_size; + hi = os->vma + os->size; if (hi < lo) hi = (bfd_vma) -1; @@ -3713,27 +3872,27 @@ elfNN_ia64_final_link (abfd, info) { unwind_output_sec = s->output_section; unwind_output_sec->contents - = bfd_malloc (unwind_output_sec->_raw_size); + = bfd_malloc (unwind_output_sec->size); if (unwind_output_sec->contents == NULL) return FALSE; } } /* Invoke the regular ELF backend linker to do all the work. */ - if (!bfd_elfNN_bfd_final_link (abfd, info)) + if (!bfd_elf_final_link (abfd, info)) return FALSE; if (unwind_output_sec) { elfNN_ia64_unwind_entry_compare_bfd = abfd; qsort (unwind_output_sec->contents, - (size_t) (unwind_output_sec->_raw_size / 24), + (size_t) (unwind_output_sec->size / 24), 24, elfNN_ia64_unwind_entry_compare); if (! bfd_set_section_contents (abfd, unwind_output_sec, unwind_output_sec->contents, (bfd_vma) 0, - unwind_output_sec->_raw_size)) + unwind_output_sec->size)) return FALSE; } @@ -3817,9 +3976,11 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, if (r_symndx < symtab_hdr->sh_info) { /* Reloc against local symbol. */ + asection *msec; sym = local_syms + r_symndx; sym_sec = local_sections[r_symndx]; - value = _bfd_elf_rela_local_sym (output_bfd, sym, sym_sec, rel); + msec = sym_sec; + value = _bfd_elf_rela_local_sym (output_bfd, sym, &msec, rel); if ((sym_sec->flags & SEC_MERGE) && ELF_ST_TYPE (sym->st_info) == STT_SECTION && sym_sec->sec_info_type == ELF_INFO_TYPE_MERGE) @@ -3830,7 +3991,6 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, 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) { @@ -3840,8 +4000,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, elf_section_data (msec)-> sec_info, sym->st_value - + dynent->addend, - (bfd_vma) 0); + + dynent->addend); dynent->addend -= sym->st_value; dynent->addend += msec->output_section->vma + msec->output_offset @@ -3856,12 +4015,12 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, { bfd_boolean unresolved_reloc; bfd_boolean warned; + struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd); - RELOC_FOR_GLOBAL_SYMBOL (h, elf_sym_hashes (input_bfd), - r_symndx, - symtab_hdr, value, sym_sec, - unresolved_reloc, info, - warned); + RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, + r_symndx, symtab_hdr, sym_hashes, + h, sym_sec, value, + unresolved_reloc, warned); if (h->root.type == bfd_link_hash_undefweak) undef_weak_ref = TRUE; @@ -3897,6 +4056,24 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, BFD_ASSERT (srel != NULL); + switch (r_type) + { + case R_IA64_IMM14: + case R_IA64_IMM22: + case R_IA64_IMM64: + /* ??? People shouldn't be doing non-pic code in + shared libraries nor dynamic executables. */ + (*_bfd_error_handler) + (_("%s: non-pic code with imm relocation against dynamic symbol `%s'"), + bfd_archive_filename (input_bfd), + h->root.root.string); + ret_val = FALSE; + continue; + + default: + break; + } + /* If we don't need dynamic symbol lookup, find a matching RELATIVE relocation. */ dyn_r_type = r_type; @@ -3924,17 +4101,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, break; default: - /* We can't represent this without a dynamic symbol. - Adjust the relocation to be against an output - section symbol, which are always present in the - dynamic symbol table. */ - /* ??? People shouldn't be doing non-pic code in - shared libraries. Hork. */ - (*_bfd_error_handler) - (_("%s: linking non-pic code in a shared library"), - bfd_archive_filename (input_bfd)); - ret_val = FALSE; - continue; + break; } dynindx = 0; addend = value; @@ -3950,7 +4117,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, case R_IA64_LTV32LSB: case R_IA64_LTV64MSB: case R_IA64_LTV64LSB: - r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type); + r = elfNN_ia64_install_value (hit_addr, value, r_type); break; case R_IA64_GPREL22: @@ -3968,7 +4135,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, continue; } value -= gp_val; - r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type); + r = elfNN_ia64_install_value (hit_addr, value, r_type); break; case R_IA64_LTOFF22: @@ -3978,7 +4145,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, value = set_got_entry (input_bfd, info, dyn_i, (h ? h->dynindx : -1), rel->r_addend, value, R_IA64_DIR64LSB); value -= gp_val; - r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type); + r = elfNN_ia64_install_value (hit_addr, value, r_type); break; case R_IA64_PLTOFF22: @@ -3988,7 +4155,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE); value = set_pltoff_entry (output_bfd, info, dyn_i, value, FALSE); value -= gp_val; - r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type); + r = elfNN_ia64_install_value (hit_addr, value, r_type); break; case R_IA64_FPTR64I: @@ -4053,7 +4220,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, dynindx, addend); } - r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type); + r = elfNN_ia64_install_value (hit_addr, value, r_type); break; case R_IA64_LTOFF_FPTR22: @@ -4095,7 +4262,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, value = set_got_entry (output_bfd, info, dyn_i, dynindx, rel->r_addend, value, R_IA64_FPTR64LSB); value -= gp_val; - r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type); + r = elfNN_ia64_install_value (hit_addr, value, r_type); } break; @@ -4176,7 +4343,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, value -= (input_section->output_section->vma + input_section->output_offset + rel->r_offset) & ~ (bfd_vma) 0x3; - r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type); + r = elfNN_ia64_install_value (hit_addr, value, r_type); break; case R_IA64_SEGREL32MSB: @@ -4220,8 +4387,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, value -= p->p_vaddr; else value = 0; - r = elfNN_ia64_install_value (output_bfd, hit_addr, value, - r_type); + r = elfNN_ia64_install_value (hit_addr, value, r_type); } break; } @@ -4235,7 +4401,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, value -= input_section->output_section->vma; else value = 0; - r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type); + r = elfNN_ia64_install_value (hit_addr, value, r_type); break; case R_IA64_IPLTMSB: @@ -4276,16 +4442,15 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, r_type = R_IA64_DIR64MSB; else r_type = R_IA64_DIR64LSB; - elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type); - r = elfNN_ia64_install_value (output_bfd, hit_addr + 8, gp_val, - r_type); + elfNN_ia64_install_value (hit_addr, value, r_type); + r = elfNN_ia64_install_value (hit_addr + 8, gp_val, r_type); break; case R_IA64_TPREL14: case R_IA64_TPREL22: case R_IA64_TPREL64I: value -= elfNN_ia64_tprel_base (info); - r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type); + r = elfNN_ia64_install_value (hit_addr, value, r_type); break; case R_IA64_DTPREL14: @@ -4294,7 +4459,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, case R_IA64_DTPREL64LSB: case R_IA64_DTPREL64MSB: value -= elfNN_ia64_dtprel_base (info); - r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type); + r = elfNN_ia64_install_value (hit_addr, value, r_type); break; case R_IA64_LTOFF_TPREL22: @@ -4336,8 +4501,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, value = set_got_entry (input_bfd, info, dyn_i, dynindx, r_addend, value, got_r_type); value -= gp_val; - r = elfNN_ia64_install_value (output_bfd, hit_addr, value, - r_type); + r = elfNN_ia64_install_value (hit_addr, value, r_type); } break; @@ -4448,9 +4612,8 @@ elfNN_ia64_finish_dynamic_symbol (output_bfd, info, h, sym) loc = plt_sec->contents + dyn_i->plt_offset; memcpy (loc, plt_min_entry, PLT_MIN_ENTRY_SIZE); - elfNN_ia64_install_value (output_bfd, loc, index, R_IA64_IMM22); - elfNN_ia64_install_value (output_bfd, loc+2, -dyn_i->plt_offset, - R_IA64_PCREL21B); + elfNN_ia64_install_value (loc, index, R_IA64_IMM22); + elfNN_ia64_install_value (loc+2, -dyn_i->plt_offset, R_IA64_PCREL21B); plt_addr = (plt_sec->output_section->vma + plt_sec->output_offset @@ -4463,13 +4626,12 @@ elfNN_ia64_finish_dynamic_symbol (output_bfd, info, h, sym) loc = plt_sec->contents + dyn_i->plt2_offset; memcpy (loc, plt_full_entry, PLT_FULL_ENTRY_SIZE); - elfNN_ia64_install_value (output_bfd, loc, pltoff_addr - gp_val, - R_IA64_IMM22); + elfNN_ia64_install_value (loc, pltoff_addr - gp_val, R_IA64_IMM22); /* Mark the symbol as undefined, rather than as defined in the plt section. Leave the value alone. */ /* ??? We didn't redefine it in adjust_dynamic_symbol in the - first place. But perhaps elflink.h did some for us. */ + first place. But perhaps elflink.c did some for us. */ if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) sym->st_shndx = SHN_UNDEF; } @@ -4530,7 +4692,7 @@ elfNN_ia64_finish_dynamic_sections (abfd, info) sgotplt = bfd_get_section_by_name (dynobj, ".got.plt"); BFD_ASSERT (sdyn != NULL); dyncon = (ElfNN_External_Dyn *) sdyn->contents; - dynconend = (ElfNN_External_Dyn *) (sdyn->contents + sdyn->_raw_size); + dynconend = (ElfNN_External_Dyn *) (sdyn->contents + sdyn->size); gp_val = _bfd_get_gp_value (abfd); @@ -4587,7 +4749,7 @@ elfNN_ia64_finish_dynamic_sections (abfd, info) + sgotplt->output_offset - gp_val); - elfNN_ia64_install_value (abfd, loc+1, pltres, R_IA64_GPREL22); + elfNN_ia64_install_value (loc+1, pltres, R_IA64_GPREL22); } } @@ -4784,6 +4946,23 @@ elfNN_hpux_backend_section_from_bfd_section (abfd, sec, retval) } return FALSE; } + +static void +elfNN_hpux_backend_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED, + asymbol *asym) +{ + elf_symbol_type *elfsym = (elf_symbol_type *) asym;; + + switch (elfsym->internal_elf_sym.st_shndx) + { + case SHN_IA_64_ANSI_COMMON: + asym->section = bfd_com_section_ptr; + asym->value = elfsym->internal_elf_sym.st_size; + asym->flags &= ~BSF_GLOBAL; + break; + } +} + #define TARGET_LITTLE_SYM bfd_elfNN_ia64_little_vec #define TARGET_LITTLE_NAME "elfNN-ia64-little" @@ -4822,6 +5001,8 @@ elfNN_hpux_backend_section_from_bfd_section (abfd, sec, retval) /* Stuff for the BFD linker: */ #define bfd_elfNN_bfd_link_hash_table_create \ elfNN_ia64_hash_table_create +#define bfd_elfNN_bfd_link_hash_table_free \ + elfNN_ia64_hash_table_free #define elf_backend_create_dynamic_sections \ elfNN_ia64_create_dynamic_sections #define elf_backend_check_relocs \ @@ -4850,7 +5031,6 @@ elfNN_hpux_backend_section_from_bfd_section (abfd, sec, retval) #define elf_backend_want_plt_sym 0 #define elf_backend_plt_alignment 5 #define elf_backend_got_header_size 0 -#define elf_backend_plt_header_size PLT_HEADER_SIZE #define elf_backend_want_got_plt 1 #define elf_backend_may_use_rel_p 1 #define elf_backend_may_use_rela_p 1 @@ -4881,6 +5061,9 @@ elfNN_hpux_backend_section_from_bfd_section (abfd, sec, retval) #undef elf_backend_section_from_bfd_section #define elf_backend_section_from_bfd_section elfNN_hpux_backend_section_from_bfd_section +#undef elf_backend_symbol_processing +#define elf_backend_symbol_processing elfNN_hpux_backend_symbol_processing + #undef elf_backend_want_p_paddr_set_to_zero #define elf_backend_want_p_paddr_set_to_zero 1