X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felfxx-ia64.c;h=0ef1a442d9ea38e319428b61f7184c822cdffc6c;hb=e4067dbb2a3368dbf908b39c5435c84d51abc9f3;hp=ed105c833e8a77dbaf0321e64ec5bfc1b9a29f89;hpb=affb4bf37a03b65825f187dfbe694470495a94bf;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elfxx-ia64.c b/bfd/elfxx-ia64.c index ed105c833e..0ef1a442d9 100644 --- a/bfd/elfxx-ia64.c +++ b/bfd/elfxx-ia64.c @@ -1,6 +1,6 @@ /* IA-64 support for 64-bit ELF Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, - 2008, 2009 Free Software Foundation, Inc. + 2008, 2009, 2010 Free Software Foundation, Inc. Contributed by David Mosberger-Tang This file is part of BFD, the Binary File Descriptor library. @@ -67,10 +67,19 @@ MIN_PLT Created by PLTOFF entries against dynamic symbols. This does not require dynamic relocations. */ +/* Only add code for vms when the vms target is enabled. This is required + because it depends on vms-lib.c for its archive format and we don't want + to compile that code if it is not used. */ +#if ARCH_SIZE == 64 && \ + (defined (HAVE_bfd_elf64_ia64_vms_vec) || defined (HAVE_all_vecs)) +#define INCLUDE_IA64_VMS +#endif + + #define NELEMS(a) ((int) (sizeof (a) / sizeof ((a)[0]))) typedef struct bfd_hash_entry *(*new_hash_entry_func) - PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); + (struct bfd_hash_entry *, struct bfd_hash_table *, const char *); /* In dynamically (linker-) created sections, we generally need to keep track of the place a symbol or expression got allocated to. This is done via hash @@ -163,23 +172,23 @@ struct elfNN_ia64_link_hash_table /* The main hash table. */ struct elf_link_hash_table root; - asection *fptr_sec; /* function descriptor table (or NULL) */ - asection *rel_fptr_sec; /* dynamic relocation section for same */ - asection *pltoff_sec; /* private descriptors for plt (or NULL) */ - asection *rel_pltoff_sec; /* dynamic relocation section for same */ + asection *fptr_sec; /* Function descriptor table (or NULL). */ + asection *rel_fptr_sec; /* Dynamic relocation section for same. */ + asection *pltoff_sec; /* Private descriptors for plt (or NULL). */ + asection *rel_pltoff_sec; /* Dynamic relocation section for same. */ - bfd_size_type minplt_entries; /* number of minplt entries */ - unsigned reltext : 1; /* are there relocs against readonly sections? */ - unsigned self_dtpmod_done : 1;/* has self DTPMOD entry been finished? */ - bfd_vma self_dtpmod_offset; /* .got offset to self DTPMOD entry */ + bfd_size_type minplt_entries; /* Number of minplt entries. */ + unsigned reltext : 1; /* Are there relocs against readonly sections? */ + unsigned self_dtpmod_done : 1;/* Has self DTPMOD entry been finished? */ + bfd_vma self_dtpmod_offset; /* .got offset to self DTPMOD entry. */ /* There are maybe R_IA64_GPREL22 relocations, including those optimized from R_IA64_LTOFF22X, against non-SHF_IA_64_SHORT sections. We need to record those sections so that we can choose a proper GP to cover all R_IA64_GPREL22 relocations. */ - asection *max_short_sec; /* maximum short output section */ - bfd_vma max_short_offset; /* maximum short offset */ - asection *min_short_sec; /* minimum short output section */ - bfd_vma min_short_offset; /* minimum short offset */ + asection *max_short_sec; /* Maximum short output section. */ + bfd_vma max_short_offset; /* Maximum short offset. */ + asection *min_short_sec; /* Minimum short output section. */ + bfd_vma min_short_offset; /* Minimum short offset. */ htab_t loc_hash_table; void *loc_hash_memory; @@ -193,7 +202,8 @@ struct elfNN_ia64_allocate_data }; #define elfNN_ia64_hash_table(p) \ - ((struct elfNN_ia64_link_hash_table *) ((p)->hash)) + (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \ + == IA64_ELF_DATA ? ((struct elfNN_ia64_link_hash_table *) ((p)->hash)) : NULL) static struct elfNN_ia64_dyn_sym_info * get_dyn_sym_info (struct elfNN_ia64_link_hash_table *ia64_info, @@ -754,8 +764,8 @@ elfNN_ia64_relax_brl (bfd_byte *contents, bfd_vma off) /* Rename some of the generic section flags to better document how they are used here. */ -#define skip_relax_pass_0 need_finalize_relax -#define skip_relax_pass_1 has_gp_reloc +#define skip_relax_pass_0 sec_flg0 +#define skip_relax_pass_1 sec_flg1 /* These functions do relaxation for IA-64 ELF. */ @@ -764,8 +774,9 @@ static void elfNN_ia64_update_short_info (asection *sec, bfd_vma offset, struct elfNN_ia64_link_hash_table *ia64_info) { - /* Skip SHF_IA_64_SHORT sections. */ - if (sec->flags & SEC_SMALL_DATA) + /* Skip ABS and SHF_IA_64_SHORT sections. */ + if (sec == bfd_abs_section_ptr + || (sec->flags & SEC_SMALL_DATA) != 0) return; if (!ia64_info->min_short_sec) @@ -842,16 +853,19 @@ elfNN_ia64_relax_section (bfd *abfd, asection *sec, || (link_info->relax_pass == 1 && sec->skip_relax_pass_1)) return TRUE; + ia64_info = elfNN_ia64_hash_table (link_info); + if (ia64_info == NULL) + return FALSE; + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; /* Load the relocations for this section. */ internal_relocs = (_bfd_elf_link_read_relocs - (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL, + (abfd, sec, NULL, (Elf_Internal_Rela *) NULL, link_info->keep_memory)); if (internal_relocs == NULL) return FALSE; - ia64_info = elfNN_ia64_hash_table (link_info); irelend = internal_relocs + sec->reloc_count; /* Get the section contents. */ @@ -1395,8 +1409,6 @@ elfNN_ia64_section_from_shdr (bfd *abfd, const char *name, int shindex) { - asection *newsect; - /* There ought to be a place to keep ELF backend specific flags, but at the moment there isn't one. We just keep track of the sections by their name, instead. Fortunately, the ABI gives @@ -1419,7 +1431,6 @@ elfNN_ia64_section_from_shdr (bfd *abfd, if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex)) return FALSE; - newsect = hdr->bfd_section; return TRUE; } @@ -1446,7 +1457,7 @@ static bfd_boolean elfNN_ia64_fake_sections (bfd *abfd, Elf_Internal_Shdr *hdr, asection *sec) { - register const char *name; + const char *name; name = bfd_get_section_name (abfd, sec); @@ -1883,21 +1894,22 @@ elfNN_ia64_local_htab_eq (const void *ptr1, const void *ptr2) derived hash table to keep information specific to the IA-64 ElF linker (without using static variables). */ -static struct bfd_link_hash_table* +static struct bfd_link_hash_table * elfNN_ia64_hash_table_create (bfd *abfd) { struct elfNN_ia64_link_hash_table *ret; ret = bfd_zmalloc ((bfd_size_type) sizeof (*ret)); if (!ret) - return 0; + return NULL; if (!_bfd_elf_link_hash_table_init (&ret->root, abfd, elfNN_ia64_new_elf_hash_entry, - sizeof (struct elfNN_ia64_link_hash_entry))) + sizeof (struct elfNN_ia64_link_hash_entry), + IA64_ELF_DATA)) { free (ret); - return 0; + return NULL; } ret->loc_hash_table = htab_try_create (1024, elfNN_ia64_local_htab_hash, @@ -1906,7 +1918,7 @@ elfNN_ia64_hash_table_create (bfd *abfd) if (!ret->loc_hash_table || !ret->loc_hash_memory) { free (ret); - return 0; + return NULL; } return &ret->root.root; @@ -2052,6 +2064,8 @@ elfNN_ia64_create_dynamic_sections (bfd *abfd, return FALSE; ia64_info = elfNN_ia64_hash_table (info); + if (ia64_info == NULL) + return FALSE; { flagword flags = bfd_get_section_flags (abfd, ia64_info->root.sgot); @@ -2134,7 +2148,7 @@ sort_dyn_sym_info (struct elfNN_ia64_dyn_sym_info *info, unsigned int count) { bfd_vma curr, prev, got_offset; - unsigned int i, kept, dup, diff, dest, src, len; + unsigned int i, kept, dupes, diff, dest, src, len; qsort (info, count, sizeof (*info), addend_compare); @@ -2199,35 +2213,35 @@ sort_dyn_sym_info (struct elfNN_ia64_dyn_sym_info *info, /* Find the next duplicate. SRC will be kept. */ prev = info [src].addend; got_offset = info [src].got_offset; - for (dup = src + 1; dup < count; dup++) + for (dupes = src + 1; dupes < count; dupes ++) { - curr = info [dup].addend; + curr = info [dupes].addend; if (curr == prev) { /* Make sure that got_offset is valid. */ if (got_offset == (bfd_vma) -1) - got_offset = info [dup].got_offset; + got_offset = info [dupes].got_offset; /* For duplicates, make sure that the kept one has a valid got_offset. */ if (got_offset != (bfd_vma) -1) - info [dup - 1].got_offset = got_offset; + info [dupes - 1].got_offset = got_offset; break; } - got_offset = info [dup].got_offset; + got_offset = info [dupes].got_offset; prev = curr; } /* How much to move. */ - len = dup - src; - i = dup + 1; + len = dupes - src; + i = dupes + 1; - if (len == 1 && dup < count) + if (len == 1 && dupes < count) { /* If we only move 1 element, we combine it with the next one. There must be at least a duplicate. Find the next different one. */ - for (diff = dup + 1, src++; diff < count; diff++, src++) + for (diff = dupes + 1, src++; diff < count; diff++, src++) { if (info [diff].addend != curr) break; @@ -2248,18 +2262,18 @@ sort_dyn_sym_info (struct elfNN_ia64_dyn_sym_info *info, offset. */ prev = info [diff].addend; got_offset = info [diff].got_offset; - for (dup = diff + 1; dup < count; dup++) + for (dupes = diff + 1; dupes < count; dupes ++) { - curr = info [dup].addend; + curr = info [dupes].addend; if (curr == prev) { /* For duplicates, make sure that GOT_OFFSET is valid. */ if (got_offset == (bfd_vma) -1) - got_offset = info [dup].got_offset; + got_offset = info [dupes].got_offset; break; } - got_offset = info [dup].got_offset; + got_offset = info [dupes].got_offset; prev = curr; diff++; } @@ -2584,7 +2598,7 @@ get_reloc_section (bfd *abfd, srel_name = (bfd_elf_string_from_elf_section (abfd, elf_elfheader(abfd)->e_shstrndx, - elf_section_data(sec)->rel_hdr.sh_name)); + _bfd_elf_single_rel_hdr (sec)->sh_name)); if (srel_name == NULL) return NULL; @@ -2679,6 +2693,8 @@ elfNN_ia64_check_relocs (bfd *abfd, struct bfd_link_info *info, symtab_hdr = &elf_tdata (abfd)->symtab_hdr; ia64_info = elfNN_ia64_hash_table (info); + if (ia64_info == NULL) + return FALSE; got = fptr = srel = pltoff = NULL; @@ -3106,7 +3122,7 @@ elfNN_ia64_check_relocs (bfd *abfd, struct bfd_link_info *info, static bfd_boolean allocate_global_data_got (struct elfNN_ia64_dyn_sym_info *dyn_i, - PTR data) + void * data) { struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data; @@ -3134,6 +3150,9 @@ allocate_global_data_got (struct elfNN_ia64_dyn_sym_info *dyn_i, struct elfNN_ia64_link_hash_table *ia64_info; ia64_info = elfNN_ia64_hash_table (x->info); + if (ia64_info == NULL) + return FALSE; + if (ia64_info->self_dtpmod_offset == (bfd_vma) -1) { ia64_info->self_dtpmod_offset = x->ofs; @@ -3154,7 +3173,7 @@ allocate_global_data_got (struct elfNN_ia64_dyn_sym_info *dyn_i, static bfd_boolean allocate_global_fptr_got (struct elfNN_ia64_dyn_sym_info *dyn_i, - PTR data) + void * data) { struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data; @@ -3343,6 +3362,8 @@ allocate_dynrel_entries (struct elfNN_ia64_dyn_sym_info *dyn_i, bfd_boolean dynamic_symbol, shared, resolved_zero; ia64_info = elfNN_ia64_hash_table (x->info); + if (ia64_info == NULL) + return FALSE; /* Note that this can't be used in relation to FPTR relocs below. */ dynamic_symbol = elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info, 0); @@ -3490,6 +3511,8 @@ elfNN_ia64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, dynobj = elf_hash_table(info)->dynobj; ia64_info = elfNN_ia64_hash_table (info); + if (ia64_info == NULL) + return FALSE; ia64_info->self_dtpmod_offset = (bfd_vma) -1; BFD_ASSERT(dynobj != NULL); data.info = info; @@ -3995,6 +4018,9 @@ set_got_entry (bfd *abfd, struct bfd_link_info *info, bfd_vma got_offset; ia64_info = elfNN_ia64_hash_table (info); + if (ia64_info == NULL) + return 0; + got_sec = ia64_info->root.sgot; switch (dyn_r_type) @@ -4132,6 +4158,9 @@ set_fptr_entry (bfd *abfd, struct bfd_link_info *info, asection *fptr_sec; ia64_info = elfNN_ia64_hash_table (info); + if (ia64_info == NULL) + return 0; + fptr_sec = ia64_info->fptr_sec; if (!dyn_i->fptr_done) @@ -4182,6 +4211,9 @@ set_pltoff_entry (bfd *abfd, struct bfd_link_info *info, asection *pltoff_sec; ia64_info = elfNN_ia64_hash_table (info); + if (ia64_info == NULL) + return 0; + pltoff_sec = ia64_info->pltoff_sec; /* Don't do anything if this symbol uses a real PLT entry. In @@ -4282,6 +4314,8 @@ elfNN_ia64_choose_gp (bfd *abfd, struct bfd_link_info *info) struct elfNN_ia64_link_hash_table *ia64_info; ia64_info = elfNN_ia64_hash_table (info); + if (ia64_info == NULL) + return FALSE; /* Find the min and max vma of all sections marked short. Also collect min and max vma of any type, for use in selecting a nice gp. */ @@ -4422,6 +4456,8 @@ elfNN_ia64_final_link (bfd *abfd, struct bfd_link_info *info) asection *unwind_output_sec; ia64_info = elfNN_ia64_hash_table (info); + if (ia64_info == NULL) + return FALSE; /* Make sure we've got ourselves a nice fat __gp value. */ if (!info->relocatable) @@ -4504,6 +4540,8 @@ elfNN_ia64_relocate_section (bfd *output_bfd, symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; ia64_info = elfNN_ia64_hash_table (info); + if (ia64_info == NULL) + return FALSE; /* Infect various flags from the input section to the output section. */ if (info->relocatable) @@ -4624,16 +4662,9 @@ elfNN_ia64_relocate_section (bfd *output_bfd, continue; } - /* For relocs against symbols from removed linkonce sections, - or sections discarded by a linker script, we just want the - section contents zeroed. Avoid any special processing. */ if (sym_sec != NULL && elf_discarded_section (sym_sec)) - { - _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset); - rel->r_info = 0; - rel->r_addend = 0; - continue; - } + RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, + rel, relend, howto, contents); if (info->relocatable) continue; @@ -4657,7 +4688,7 @@ elfNN_ia64_relocate_section (bfd *output_bfd, case R_IA64_DIR64LSB: /* Install a dynamic relocation for this reloc. */ if ((dynamic_symbol_p || info->shared) - && r_symndx != 0 + && r_symndx != STN_UNDEF && (input_section->flags & SEC_ALLOC) != 0) { unsigned int dyn_r_type; @@ -4886,7 +4917,7 @@ elfNN_ia64_relocate_section (bfd *output_bfd, case R_IA64_PCREL64MSB: case R_IA64_PCREL64LSB: /* Install a dynamic relocation for this reloc. */ - if (dynamic_symbol_p && r_symndx != 0) + if (dynamic_symbol_p && r_symndx != STN_UNDEF) { BFD_ASSERT (srel != NULL); @@ -5232,6 +5263,9 @@ elfNN_ia64_finish_dynamic_symbol (bfd *output_bfd, struct elfNN_ia64_dyn_sym_info *dyn_i; ia64_info = elfNN_ia64_hash_table (info); + if (ia64_info == NULL) + return FALSE; + dyn_i = get_dyn_sym_info (ia64_info, h, NULL, NULL, FALSE); /* Fill in the PLT data, if required. */ @@ -5240,18 +5274,18 @@ elfNN_ia64_finish_dynamic_symbol (bfd *output_bfd, Elf_Internal_Rela outrel; bfd_byte *loc; asection *plt_sec; - bfd_vma plt_addr, pltoff_addr, gp_val, index; + bfd_vma plt_addr, pltoff_addr, gp_val, plt_index; gp_val = _bfd_get_gp_value (output_bfd); /* Initialize the minimal PLT entry. */ - index = (dyn_i->plt_offset - PLT_HEADER_SIZE) / PLT_MIN_ENTRY_SIZE; + plt_index = (dyn_i->plt_offset - PLT_HEADER_SIZE) / PLT_MIN_ENTRY_SIZE; plt_sec = ia64_info->root.splt; loc = plt_sec->contents + dyn_i->plt_offset; memcpy (loc, plt_min_entry, PLT_MIN_ENTRY_SIZE); - elfNN_ia64_install_value (loc, index, R_IA64_IMM22); + elfNN_ia64_install_value (loc, plt_index, R_IA64_IMM22); elfNN_ia64_install_value (loc+2, -dyn_i->plt_offset, R_IA64_PCREL21B); plt_addr = (plt_sec->output_section->vma @@ -5296,7 +5330,7 @@ elfNN_ia64_finish_dynamic_symbol (bfd *output_bfd, PLT relocations. */ loc = ia64_info->rel_pltoff_sec->contents; - loc += ((ia64_info->rel_pltoff_sec->reloc_count + index) + loc += ((ia64_info->rel_pltoff_sec->reloc_count + plt_index) * sizeof (ElfNN_External_Rela)); bfd_elfNN_swap_reloca_out (output_bfd, &outrel, loc); } @@ -5318,6 +5352,9 @@ elfNN_ia64_finish_dynamic_sections (bfd *abfd, bfd *dynobj; ia64_info = elfNN_ia64_hash_table (info); + if (ia64_info == NULL) + return FALSE; + dynobj = ia64_info->root.dynobj; if (elf_hash_table (info)->dynamic_sections_created) @@ -5685,14 +5722,14 @@ elfNN_hpux_backend_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED, } } +#ifdef INCLUDE_IA64_VMS + static bfd_boolean elfNN_vms_section_from_shdr (bfd *abfd, Elf_Internal_Shdr *hdr, const char *name, int shindex) { - asection *newsect; - switch (hdr->sh_type) { case SHT_IA_64_VMS_TRACE: @@ -5706,7 +5743,6 @@ elfNN_vms_section_from_shdr (bfd *abfd, if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex)) return FALSE; - newsect = hdr->bfd_section; return TRUE; } @@ -5946,12 +5982,14 @@ elfNN_vms_close_and_cleanup (bfd *abfd) return _bfd_generic_close_and_cleanup (abfd); } +#endif /* INCLUDE_IA64_VMS */ #define TARGET_LITTLE_SYM bfd_elfNN_ia64_little_vec #define TARGET_LITTLE_NAME "elfNN-ia64-little" #define TARGET_BIG_SYM bfd_elfNN_ia64_big_vec #define TARGET_BIG_NAME "elfNN-ia64-big" #define ELF_ARCH bfd_arch_ia64 +#define ELF_TARGET_ID IA64_ELF_DATA #define ELF_MACHINE_CODE EM_IA_64 #define ELF_MACHINE_ALT1 1999 /* EAS2.3 */ #define ELF_MACHINE_ALT2 1998 /* EAS2.2 */ @@ -6079,6 +6117,7 @@ elfNN_vms_close_and_cleanup (bfd *abfd) #include "elfNN-target.h" /* VMS-specific vectors. */ +#ifdef INCLUDE_IA64_VMS #undef TARGET_LITTLE_SYM #define TARGET_LITTLE_SYM bfd_elfNN_ia64_vms_vec @@ -6122,4 +6161,40 @@ elfNN_vms_close_and_cleanup (bfd *abfd) #undef elfNN_bed #define elfNN_bed elfNN_ia64_vms_bed +/* Use VMS-style archives (in particular, don't use the standard coff + archive format). */ +#define bfd_elfNN_archive_functions + +#undef bfd_elfNN_archive_p +#define bfd_elfNN_archive_p _bfd_vms_lib_ia64_archive_p +#undef bfd_elfNN_write_archive_contents +#define bfd_elfNN_write_archive_contents _bfd_vms_lib_write_archive_contents +#undef bfd_elfNN_mkarchive +#define bfd_elfNN_mkarchive _bfd_vms_lib_ia64_mkarchive + +#define bfd_elfNN_archive_slurp_armap \ + _bfd_vms_lib_slurp_armap +#define bfd_elfNN_archive_slurp_extended_name_table \ + _bfd_vms_lib_slurp_extended_name_table +#define bfd_elfNN_archive_construct_extended_name_table \ + _bfd_vms_lib_construct_extended_name_table +#define bfd_elfNN_archive_truncate_arname \ + _bfd_vms_lib_truncate_arname +#define bfd_elfNN_archive_write_armap \ + _bfd_vms_lib_write_armap +#define bfd_elfNN_archive_read_ar_hdr \ + _bfd_vms_lib_read_ar_hdr +#define bfd_elfNN_archive_write_ar_hdr \ + _bfd_vms_lib_write_ar_hdr +#define bfd_elfNN_archive_openr_next_archived_file \ + _bfd_vms_lib_openr_next_archived_file +#define bfd_elfNN_archive_get_elt_at_index \ + _bfd_vms_lib_get_elt_at_index +#define bfd_elfNN_archive_generic_stat_arch_elt \ + _bfd_vms_lib_generic_stat_arch_elt +#define bfd_elfNN_archive_update_armap_timestamp \ + _bfd_vms_lib_update_armap_timestamp + #include "elfNN-target.h" + +#endif /* INCLUDE_IA64_VMS */