X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felfxx-ia64.c;h=917e2c3bbf7f770200e02e7543461f0475cbf2ed;hb=dfeffb9fe1d18c568b06be976da294b928753821;hp=5cc311086bab137544bae971dd22d13762972aff;hpb=560e09e9cc912370081be5cccb8d3179a78928b2;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elfxx-ia64.c b/bfd/elfxx-ia64.c index 5cc311086b..917e2c3bbf 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,39 @@ 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) + (_("%B: Can't relax br at 0x%lx in section `%A'. Please use brl or indirect branch."), + sec->owner, sec, (unsigned long) roff); + 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 +1005,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 +1033,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 +1062,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 +1113,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; @@ -990,7 +1125,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) enough that the data segment moves, which will change the GP. Reset the GP so that we re-calculate next round. We need to do this at the _beginning_ of the next round; now will not do. */ - + /* Clean up and go home. */ while (fixups) { @@ -1041,13 +1176,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 +1200,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 +1216,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 +1228,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 +1298,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; @@ -1231,9 +1364,7 @@ elfNN_ia64_final_write_processing (abfd, linker) bfd_boolean linker ATTRIBUTE_UNUSED; { Elf_Internal_Shdr *hdr; - const char *sname; - asection *text_sect, *s; - size_t len; + asection *s; for (s = abfd->sections; s; s = s->next) { @@ -1241,64 +1372,11 @@ elfNN_ia64_final_write_processing (abfd, linker) switch (hdr->sh_type) { case SHT_IA_64_UNWIND: - /* See comments in gas/config/tc-ia64.c:dot_endp on why we - have to do this. */ - sname = bfd_get_section_name (abfd, s); - len = sizeof (ELF_STRING_ia64_unwind) - 1; - if (sname && strncmp (sname, ELF_STRING_ia64_unwind, len) == 0) - { - sname += len; - - if (sname[0] == '\0') - /* .IA_64.unwind -> .text */ - text_sect = bfd_get_section_by_name (abfd, ".text"); - else - /* .IA_64.unwindFOO -> FOO */ - text_sect = bfd_get_section_by_name (abfd, sname); - } - else if (sname - && (len = sizeof (ELF_STRING_ia64_unwind_once) - 1, - strncmp (sname, ELF_STRING_ia64_unwind_once, len)) == 0) - { - /* .gnu.linkonce.ia64unw.FOO -> .gnu.linkonce.t.FOO */ - size_t len2 = sizeof (".gnu.linkonce.t.") - 1; - char *once_name = bfd_malloc (len2 + strlen (sname + len) + 1); - - if (once_name != NULL) - { - memcpy (once_name, ".gnu.linkonce.t.", len2); - strcpy (once_name + len2, sname + len); - text_sect = bfd_get_section_by_name (abfd, once_name); - free (once_name); - } - else - /* Should only happen if we run out of memory, in - which case we're probably toast anyway. Try to - cope by finding the section the slow way. */ - for (text_sect = abfd->sections; - text_sect != NULL; - text_sect = text_sect->next) - { - if (strncmp (bfd_section_name (abfd, text_sect), - ".gnu.linkonce.t.", len2) == 0 - && strcmp (bfd_section_name (abfd, text_sect) + len2, - sname + len) == 0) - break; - } - } - else - /* last resort: fall back on .text */ - text_sect = bfd_get_section_by_name (abfd, ".text"); - - if (text_sect) - { - /* The IA-64 processor-specific ABI requires setting - sh_link to the unwind section, whereas HP-UX requires - sh_info to do so. For maximum compatibility, we'll - set both for now... */ - hdr->sh_link = elf_section_data (text_sect)->this_idx; - hdr->sh_info = elf_section_data (text_sect)->this_idx; - } + /* The IA-64 processor-specific ABI requires setting sh_link + to the unwind section, whereas HP-UX requires sh_info to + do so. For maximum compatibility, we'll set both for + now... */ + hdr->sh_info = hdr->sh_link; break; } } @@ -1324,7 +1402,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 +1457,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 +1599,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; @@ -1600,11 +1641,10 @@ elfNN_ia64_hash_copy_indirect (bed, xdir, xind) /* Copy down any references that we may have already seen to the symbol which just became indirect. */ - dir->root.elf_link_hash_flags |= - (ind->root.elf_link_hash_flags - & (ELF_LINK_HASH_REF_DYNAMIC - | ELF_LINK_HASH_REF_REGULAR - | ELF_LINK_HASH_REF_REGULAR_NONWEAK)); + dir->root.ref_dynamic |= ind->root.ref_dynamic; + dir->root.ref_regular |= ind->root.ref_regular; + dir->root.ref_regular_nonweak |= ind->root.ref_regular_nonweak; + dir->root.needs_plt |= ind->root.needs_plt; if (ind->root.root.type != bfd_link_hash_indirect) return; @@ -1657,6 +1697,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 +1745,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 +1757,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 +1801,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 +1830,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 @@ -1781,6 +1853,8 @@ elfNN_ia64_create_dynamic_sections (abfd, info) { flagword flags = bfd_get_section_flags (abfd, ia64_info->got_sec); bfd_set_section_flags (abfd, ia64_info->got_sec, SEC_SMALL_DATA | flags); + /* The .got section is always aligned at 8 bytes. */ + bfd_set_section_alignment (abfd, ia64_info->got_sec, 3); } if (!get_pltoff (abfd, info, ia64_info)) @@ -1819,22 +1893,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; } @@ -1919,7 +2004,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. */ @@ -1959,9 +2044,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 @@ -2061,18 +2146,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; @@ -2093,6 +2172,7 @@ count_dyn_reloc (abfd, dyn_i, srel, type) rent->count = 0; dyn_i->reloc_entries = rent; } + rent->reltext = reltext; rent->count++; return TRUE; @@ -2109,7 +2189,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; @@ -2117,7 +2197,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) @@ -2153,7 +2233,7 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs) || h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; - h->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR; + h->ref_regular = 1; } /* We can only get preliminary data on whether a symbol is @@ -2162,8 +2242,9 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs) this may help reduce memory usage and processing time later. */ maybe_dynamic = FALSE; if (h && ((!info->executable - && (!info->symbolic || info->unresolved_syms_in_shared_libs == RM_IGNORE)) - || ! (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) + && (!info->symbolic + || info->unresolved_syms_in_shared_libs == RM_IGNORE)) + || !h->def_regular || h->root.type == bfd_link_hash_defweak)) maybe_dynamic = TRUE; @@ -2349,7 +2430,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; } @@ -2362,13 +2443,24 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs) { if (!ia64_info->root.dynobj) ia64_info->root.dynobj = abfd; - h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; + h->needs_plt = 1; dyn_i->want_plt = 1; } 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) @@ -2377,7 +2469,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; } } @@ -2520,7 +2613,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; @@ -2557,7 +2650,7 @@ allocate_plt_entries (dyn_i, data) || h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; - /* ??? Versioned symbols seem to lose ELF_LINK_HASH_NEEDS_PLT. */ + /* ??? Versioned symbols seem to lose NEEDS_PLT. */ if (elfNN_ia64_dynamic_symbol_p (h, x->info, 0)) { bfd_size_type offset = x->ofs; @@ -2684,7 +2777,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. */ @@ -2700,18 +2795,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) @@ -2726,7 +2821,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; @@ -2743,12 +2838,12 @@ elfNN_ia64_adjust_dynamic_symbol (info, h) /* If this is a weak symbol, and there is a real definition, the processor independent code will have arranged for us to see the real definition first, and we can just use the same value. */ - if (h->weakdef != NULL) + if (h->u.weakdef != NULL) { - BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined - || h->weakdef->root.type == bfd_link_hash_defweak); - h->root.u.def.section = h->weakdef->root.u.def.section; - h->root.u.def.value = h->weakdef->root.u.def.value; + BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined + || h->u.weakdef->root.type == bfd_link_hash_defweak); + h->root.u.def.section = h->u.weakdef->root.u.def.section; + h->root.u.def.value = h->u.weakdef->root.u.def.value; return TRUE; } @@ -2786,7 +2881,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. */ @@ -2797,7 +2892,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. */ @@ -2806,7 +2901,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 @@ -2828,16 +2923,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. */ @@ -2846,7 +2945,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) @@ -2855,7 +2954,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); } @@ -2876,7 +2975,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; @@ -2894,6 +2993,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) @@ -2944,8 +3052,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; } } @@ -2961,7 +3069,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; @@ -2999,8 +3107,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; @@ -3132,8 +3239,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 @@ -3155,14 +3262,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 @@ -3180,8 +3287,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: @@ -3192,7 +3299,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; @@ -3202,7 +3309,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: @@ -3256,8 +3363,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 @@ -3511,12 +3617,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 @@ -3527,8 +3631,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 @@ -3575,7 +3679,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; @@ -3711,27 +3815,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; } @@ -3798,8 +3902,8 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, if (r_type > R_IA64_MAX_RELOC_CODE) { (*_bfd_error_handler) - (_("%s: unknown relocation type %d"), - bfd_archive_filename (input_bfd), (int)r_type); + (_("%B: unknown relocation type %d"), + input_bfd, (int) r_type); bfd_set_error (bfd_error_bad_value); ret_val = FALSE; continue; @@ -3815,9 +3919,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) @@ -3828,7 +3934,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) { @@ -3838,8 +3943,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 @@ -3854,12 +3958,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; @@ -3895,6 +3999,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) + (_("%B: non-pic code with imm relocation against dynamic symbol `%s'"), + 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; @@ -3922,17 +4044,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; @@ -3948,7 +4060,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: @@ -3960,13 +4072,13 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, if (dynamic_symbol_p) { (*_bfd_error_handler) - (_("%s: @gprel relocation against dynamic symbol %s"), - bfd_archive_filename (input_bfd), h->root.root.string); + (_("%B: @gprel relocation against dynamic symbol %s"), + input_bfd, h->root.root.string); ret_val = FALSE; 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: @@ -3976,7 +4088,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: @@ -3986,7 +4098,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: @@ -4020,8 +4132,8 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, /* ??? People shouldn't be doing non-pic code in shared libraries. Hork. */ (*_bfd_error_handler) - (_("%s: linking non-pic code in a position independent executable"), - bfd_archive_filename (input_bfd)); + (_("%B: linking non-pic code in a position independent executable"), + input_bfd); ret_val = FALSE; continue; } @@ -4051,7 +4163,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: @@ -4066,7 +4178,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); if (dyn_i->want_fptr) { - BFD_ASSERT (h == NULL || h->dynindx == -1) + BFD_ASSERT (h == NULL || h->dynindx == -1); if (!undef_weak_ref) value = set_fptr_entry (output_bfd, info, dyn_i, value); dynindx = -1; @@ -4093,7 +4205,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; @@ -4150,20 +4262,19 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, case R_IA64_PCREL64I: /* The PCREL21BI reloc is specifically not intended for use with dynamic relocs. PCREL21F and PCREL21M are used for speculation - fixup code, and thus probably ought not be dynamic. The + fixup code, and thus probably ought not be dynamic. The PCREL22 and PCREL64I relocs aren't emitted as dynamic relocs. */ if (dynamic_symbol_p) { const char *msg; if (r_type == R_IA64_PCREL21BI) - msg = _("%s: @internal branch to dynamic symbol %s"); + msg = _("%B: @internal branch to dynamic symbol %s"); else if (r_type == R_IA64_PCREL21F || r_type == R_IA64_PCREL21M) - msg = _("%s: speculation fixup to dynamic symbol %s"); + msg = _("%B: speculation fixup to dynamic symbol %s"); else - msg = _("%s: @pcrel relocation against dynamic symbol %s"); - (*_bfd_error_handler) (msg, bfd_archive_filename (input_bfd), - h->root.root.string); + msg = _("%B: @pcrel relocation against dynamic symbol %s"); + (*_bfd_error_handler) (msg, input_bfd, h->root.root.string); ret_val = FALSE; continue; } @@ -4174,7 +4285,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: @@ -4218,8 +4329,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; } @@ -4233,7 +4343,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: @@ -4274,16 +4384,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: @@ -4292,7 +4401,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: @@ -4334,8 +4443,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; @@ -4389,7 +4497,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, const char *name; if (h) - name = h->root.root.string; + name = NULL; else { name = bfd_elf_string_from_elf_section (input_bfd, @@ -4398,10 +4506,10 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, if (name == NULL) return FALSE; if (*name == '\0') - name = bfd_section_name (input_bfd, input_section); + name = bfd_section_name (input_bfd, sym_sec); } - if (!(*info->callbacks->reloc_overflow) (info, name, - howto->name, + if (!(*info->callbacks->reloc_overflow) (info, &h->root, + name, howto->name, (bfd_vma) 0, input_bfd, input_section, @@ -4446,9 +4554,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 @@ -4461,14 +4568,13 @@ 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. */ - if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) + first place. But perhaps elflink.c did some for us. */ + if (!h->def_regular) sym->st_shndx = SHN_UNDEF; } @@ -4528,7 +4634,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); @@ -4585,7 +4691,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); } } @@ -4652,8 +4758,8 @@ elfNN_ia64_merge_private_bfd_data (ibfd, obfd) if ((in_flags & EF_IA_64_TRAPNIL) != (out_flags & EF_IA_64_TRAPNIL)) { (*_bfd_error_handler) - (_("%s: linking trap-on-NULL-dereference with non-trapping files"), - bfd_archive_filename (ibfd)); + (_("%B: linking trap-on-NULL-dereference with non-trapping files"), + ibfd); bfd_set_error (bfd_error_bad_value); ok = FALSE; @@ -4661,8 +4767,8 @@ elfNN_ia64_merge_private_bfd_data (ibfd, obfd) if ((in_flags & EF_IA_64_BE) != (out_flags & EF_IA_64_BE)) { (*_bfd_error_handler) - (_("%s: linking big-endian files with little-endian files"), - bfd_archive_filename (ibfd)); + (_("%B: linking big-endian files with little-endian files"), + ibfd); bfd_set_error (bfd_error_bad_value); ok = FALSE; @@ -4670,8 +4776,8 @@ elfNN_ia64_merge_private_bfd_data (ibfd, obfd) if ((in_flags & EF_IA_64_ABI64) != (out_flags & EF_IA_64_ABI64)) { (*_bfd_error_handler) - (_("%s: linking 64-bit files with 32-bit files"), - bfd_archive_filename (ibfd)); + (_("%B: linking 64-bit files with 32-bit files"), + ibfd); bfd_set_error (bfd_error_bad_value); ok = FALSE; @@ -4679,8 +4785,8 @@ elfNN_ia64_merge_private_bfd_data (ibfd, obfd) if ((in_flags & EF_IA_64_CONS_GP) != (out_flags & EF_IA_64_CONS_GP)) { (*_bfd_error_handler) - (_("%s: linking constant-gp files with non-constant-gp files"), - bfd_archive_filename (ibfd)); + (_("%B: linking constant-gp files with non-constant-gp files"), + ibfd); bfd_set_error (bfd_error_bad_value); ok = FALSE; @@ -4689,8 +4795,8 @@ elfNN_ia64_merge_private_bfd_data (ibfd, obfd) != (out_flags & EF_IA_64_NOFUNCDESC_CONS_GP)) { (*_bfd_error_handler) - (_("%s: linking auto-pic files with non-auto-pic files"), - bfd_archive_filename (ibfd)); + (_("%B: linking auto-pic files with non-auto-pic files"), + ibfd); bfd_set_error (bfd_error_bad_value); ok = FALSE; @@ -4746,12 +4852,9 @@ elfNN_ia64_reloc_type_class (rela) static struct bfd_elf_special_section const elfNN_ia64_special_sections[]= { - { ".sbss", 0, NULL, 0, - SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_IA_64_SHORT }, - { ".sdata", 0, NULL, 0, - SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_IA_64_SHORT }, - { NULL, 0, NULL, 0, - 0, 0 } + { ".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 } }; static bfd_boolean @@ -4785,6 +4888,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" @@ -4823,6 +4943,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 \ @@ -4851,7 +4973,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 @@ -4863,6 +4984,13 @@ elfNN_hpux_backend_section_from_bfd_section (abfd, sec, retval) #define elf_backend_rela_normal 1 #define elf_backend_special_sections elfNN_ia64_special_sections +/* FIXME: PR 290: The Intel C compiler generates SHT_IA_64_UNWIND with + SHF_LINK_ORDER. But it doesn't set theh sh_link or sh_info fields. + We don't want to flood users with so many error messages. We turn + off the warning for now. It will be turned on later when the Intel + compiler is fixed. */ +#define elf_backend_link_order_error_handler NULL + #include "elfNN-target.h" /* HPUX-specific vectors. */ @@ -4882,6 +5010,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