X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felf32-hppa.c;h=cac0a215f4d6261c28e92ebc23080d98a353d097;hb=dabf22219ebc373528239930b354ebe7d02295a6;hp=c448aac26f3b2d824ecf6a2185c0810883e22856;hpb=b1e24c0220fe6718066991999cb0a6e5b88b569d;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-hppa.c b/bfd/elf32-hppa.c index c448aac26f..cac0a215f4 100644 --- a/bfd/elf32-hppa.c +++ b/bfd/elf32-hppa.c @@ -1,6 +1,7 @@ /* BFD back-end for HP PA-RISC ELF files. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2000, 2001, - 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + Free Software Foundation, Inc. Original code by Center for Software Science @@ -14,7 +15,7 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -24,10 +25,11 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ -#include "bfd.h" #include "sysdep.h" +#include "bfd.h" #include "libbfd.h" #include "elf-bfd.h" #include "elf/hppa.h" @@ -299,8 +301,8 @@ struct elf32_hppa_link_hash_table /* Set if we need a .plt stub to support lazy dynamic linking. */ unsigned int need_plt_stub:1; - /* Small local sym to section mapping cache. */ - struct sym_sec_cache sym_sec; + /* Small local sym cache. */ + struct sym_cache sym_cache; /* Data for LDM relocations. */ union @@ -333,6 +335,15 @@ struct elf32_hppa_link_hash_table #define eh_name(eh) \ (eh ? eh->root.root.string : "") +/* Override the generic function because we want to mark our BFDs. */ + +static bfd_boolean +elf32_hppa_mkobject (bfd *abfd) +{ + return bfd_elf_allocate_object (abfd, sizeof (struct elf_obj_tdata), + HPPA_ELF_TDATA); +} + /* Assorted hash table functions. */ /* Initialize an entry in the stub hash table. */ @@ -449,7 +460,7 @@ elf32_hppa_link_hash_table_create (bfd *abfd) htab->has_17bit_branch = 0; htab->has_22bit_branch = 0; htab->need_plt_stub = 0; - htab->sym_sec.abfd = NULL; + htab->sym_cache.abfd = NULL; htab->tls_ldm_got.refcount = 0; return &htab->etab.root; @@ -1000,16 +1011,7 @@ elf32_hppa_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) htab->srelplt = bfd_get_section_by_name (abfd, ".rela.plt"); htab->sgot = bfd_get_section_by_name (abfd, ".got"); - htab->srelgot = bfd_make_section_with_flags (abfd, ".rela.got", - (SEC_ALLOC - | SEC_LOAD - | SEC_HAS_CONTENTS - | SEC_IN_MEMORY - | SEC_LINKER_CREATED - | SEC_READONLY)); - if (htab->srelgot == NULL - || ! bfd_set_section_alignment (abfd, htab->srelgot, 2)) - return FALSE; + htab->srelgot = bfd_get_section_by_name (abfd, ".rela.got"); htab->sdynbss = bfd_get_section_by_name (abfd, ".dynbss"); htab->srelbss = bfd_get_section_by_name (abfd, ".rela.bss"); @@ -1102,6 +1104,38 @@ elf32_hppa_optimized_tls_reloc (struct bfd_link_info *info ATTRIBUTE_UNUSED, return r_type; } +/* Return a pointer to the local GOT, PLT and TLS reference counts + for ABFD. Returns NULL if the storage allocation fails. */ + +static bfd_signed_vma * +hppa32_elf_local_refcounts (bfd *abfd) +{ + Elf_Internal_Shdr *symtab_hdr = &elf_tdata (abfd)->symtab_hdr; + bfd_signed_vma *local_refcounts; + + local_refcounts = elf_local_got_refcounts (abfd); + if (local_refcounts == NULL) + { + bfd_size_type size; + + /* Allocate space for local GOT and PLT reference + counts. Done this way to save polluting elf_obj_tdata + with another target specific pointer. */ + size = symtab_hdr->sh_info; + size *= 2 * sizeof (bfd_signed_vma); + /* Add in space to store the local GOT TLS types. */ + size += symtab_hdr->sh_info; + local_refcounts = bfd_zalloc (abfd, size); + if (local_refcounts == NULL) + return NULL; + elf_local_got_refcounts (abfd) = local_refcounts; + memset (hppa_elf_local_got_tls_type (abfd), GOT_UNKNOWN, + symtab_hdr->sh_info); + } + return local_refcounts; +} + + /* Look through the relocs for a section during the first phase, and calculate needed space in the global offset table, procedure linkage table, and dynamic reloc sections. At this point we haven't @@ -1277,7 +1311,9 @@ elf32_hppa_check_relocs (bfd *abfd, /* This relocation describes which C++ vtable entries are actually used. Record for later use during GC. */ case R_PARISC_GNU_VTENTRY: - if (!bfd_elf_gc_record_vtentry (abfd, sec, &hh->eh, rela->r_addend)) + BFD_ASSERT (hh != NULL); + if (hh != NULL + && !bfd_elf_gc_record_vtentry (abfd, sec, &hh->eh, rela->r_addend)) return FALSE; continue; @@ -1346,26 +1382,9 @@ elf32_hppa_check_relocs (bfd *abfd, bfd_signed_vma *local_got_refcounts; /* This is a global offset table entry for a local symbol. */ - local_got_refcounts = elf_local_got_refcounts (abfd); + local_got_refcounts = hppa32_elf_local_refcounts (abfd); if (local_got_refcounts == NULL) - { - bfd_size_type size; - - /* Allocate space for local got offsets and local - plt offsets. Done this way to save polluting - elf_obj_tdata with another target specific - pointer. */ - size = symtab_hdr->sh_info; - size *= 2 * sizeof (bfd_signed_vma); - /* Add in space to store the local GOT TLS types. */ - size += symtab_hdr->sh_info; - local_got_refcounts = bfd_zalloc (abfd, size); - if (local_got_refcounts == NULL) - return FALSE; - elf_local_got_refcounts (abfd) = local_got_refcounts; - memset (hppa_elf_local_got_tls_type (abfd), - GOT_UNKNOWN, symtab_hdr->sh_info); - } + return FALSE; local_got_refcounts[r_symndx] += 1; old_tls_type = hppa_elf_local_got_tls_type (abfd) [r_symndx]; @@ -1412,22 +1431,9 @@ elf32_hppa_check_relocs (bfd *abfd, bfd_signed_vma *local_got_refcounts; bfd_signed_vma *local_plt_refcounts; - local_got_refcounts = elf_local_got_refcounts (abfd); + local_got_refcounts = hppa32_elf_local_refcounts (abfd); if (local_got_refcounts == NULL) - { - bfd_size_type size; - - /* Allocate space for local got offsets and local - plt offsets. */ - size = symtab_hdr->sh_info; - size *= 2 * sizeof (bfd_signed_vma); - /* Add in space to store the local GOT TLS types. */ - size += symtab_hdr->sh_info; - local_got_refcounts = bfd_zalloc (abfd, size); - if (local_got_refcounts == NULL) - return FALSE; - elf_local_got_refcounts (abfd) = local_got_refcounts; - } + return FALSE; local_plt_refcounts = (local_got_refcounts + symtab_hdr->sh_info); local_plt_refcounts[r_symndx] += 1; @@ -1492,44 +1498,17 @@ elf32_hppa_check_relocs (bfd *abfd, this reloc. */ if (sreloc == NULL) { - char *name; - bfd *dynobj; - - name = (bfd_elf_string_from_elf_section - (abfd, - elf_elfheader (abfd)->e_shstrndx, - elf_section_data (sec)->rel_hdr.sh_name)); - if (name == NULL) - { - (*_bfd_error_handler) - (_("Could not find relocation section for %s"), - sec->name); - bfd_set_error (bfd_error_bad_value); - return FALSE; - } - if (htab->etab.dynobj == NULL) htab->etab.dynobj = abfd; - dynobj = htab->etab.dynobj; - sreloc = bfd_get_section_by_name (dynobj, name); + sreloc = _bfd_elf_make_dynamic_reloc_section + (sec, htab->etab.dynobj, 2, abfd, /*rela?*/ TRUE); + if (sreloc == NULL) { - flagword flags; - - flags = (SEC_HAS_CONTENTS | SEC_READONLY - | SEC_IN_MEMORY | SEC_LINKER_CREATED); - if ((sec->flags & SEC_ALLOC) != 0) - flags |= SEC_ALLOC | SEC_LOAD; - sreloc = bfd_make_section_with_flags (dynobj, - name, - flags); - if (sreloc == NULL - || !bfd_set_section_alignment (dynobj, sreloc, 2)) - return FALSE; + bfd_set_error (bfd_error_bad_value); + return FALSE; } - - elf_section_data (sec)->sreloc = sreloc; } /* If this is a global symbol, we count the number of @@ -1543,15 +1522,19 @@ elf32_hppa_check_relocs (bfd *abfd, /* Track dynamic relocs needed for local syms too. We really need local syms available to do this easily. Oh well. */ - asection *sr; void *vpp; + Elf_Internal_Sym *isym; - sr = bfd_section_from_r_symndx (abfd, &htab->sym_sec, - sec, r_symndx); - if (sr == NULL) + isym = bfd_sym_from_r_symndx (&htab->sym_cache, + abfd, r_symndx); + if (isym == NULL) return FALSE; + sr = bfd_section_from_elf_index (abfd, isym->st_shndx); + if (sr == NULL) + sr = sec; + vpp = &elf_section_data (sr)->local_dynrel; hdh_head = (struct elf32_hppa_dyn_reloc_entry **) vpp; } @@ -1619,6 +1602,9 @@ elf32_hppa_gc_sweep_hook (bfd *abfd, bfd_signed_vma *local_plt_refcounts; const Elf_Internal_Rela *rela, *relend; + if (info->relocatable) + return TRUE; + elf_section_data (sec)->local_dynrel = NULL; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; @@ -1819,7 +1805,6 @@ elf32_hppa_adjust_dynamic_symbol (struct bfd_link_info *info, { struct elf32_hppa_link_hash_table *htab; asection *sec; - unsigned int power_of_two; /* If this is a function, put it in the procedure linkage table. We will fill in the contents of the procedure linkage table later. */ @@ -1929,30 +1914,9 @@ elf32_hppa_adjust_dynamic_symbol (struct bfd_link_info *info, eh->needs_copy = 1; } - /* We need to figure out the alignment required for this symbol. I - have no idea how other ELF linkers handle this. */ - - power_of_two = bfd_log2 (eh->size); - if (power_of_two > 3) - power_of_two = 3; - - /* Apply the required alignment. */ sec = htab->sdynbss; - sec->size = BFD_ALIGN (sec->size, (bfd_size_type) (1 << power_of_two)); - if (power_of_two > bfd_get_section_alignment (htab->etab.dynobj, sec)) - { - if (! bfd_set_section_alignment (htab->etab.dynobj, sec, power_of_two)) - return FALSE; - } - /* Define the symbol as being at this point in the section. */ - eh->root.u.def.section = sec; - eh->root.u.def.value = sec->size; - - /* Increment the section size to make room for the symbol. */ - sec->size += eh->size; - - return TRUE; + return _bfd_elf_adjust_dynamic_copy (eh, sec); } /* Allocate space in the .plt for entries that won't have relocations. @@ -2983,15 +2947,20 @@ elf32_hppa_size_stubs /* It's a local symbol. */ Elf_Internal_Sym *sym; Elf_Internal_Shdr *hdr; + unsigned int shndx; sym = local_syms + r_indx; - hdr = elf_elfsections (input_bfd)[sym->st_shndx]; - sym_sec = hdr->bfd_section; if (ELF_ST_TYPE (sym->st_info) != STT_SECTION) sym_value = sym->st_value; - destination = (sym_value + irela->r_addend - + sym_sec->output_offset - + sym_sec->output_section->vma); + shndx = sym->st_shndx; + if (shndx < elf_numsections (input_bfd)) + { + hdr = elf_elfsections (input_bfd)[shndx]; + sym_sec = hdr->bfd_section; + destination = (sym_value + irela->r_addend + + sym_sec->output_offset + + sym_sec->output_section->vma); + } } else { @@ -3275,9 +3244,7 @@ elf32_hppa_final_link (bfd *abfd, struct bfd_link_info *info) /* Record the lowest address for the data and text segments. */ static void -hppa_record_segment_addr (bfd *abfd ATTRIBUTE_UNUSED, - asection *section, - void *data) +hppa_record_segment_addr (bfd *abfd, asection *section, void *data) { struct elf32_hppa_link_hash_table *htab; @@ -3285,7 +3252,12 @@ hppa_record_segment_addr (bfd *abfd ATTRIBUTE_UNUSED, if ((section->flags & (SEC_ALLOC | SEC_LOAD)) == (SEC_ALLOC | SEC_LOAD)) { - bfd_vma value = section->vma - section->filepos; + bfd_vma value; + Elf_Internal_Phdr *p; + + p = _bfd_elf_find_segment_containing_section (abfd, section->output_section); + BFD_ASSERT (p != NULL); + value = p->p_vaddr; if ((section->flags & SEC_READONLY) != 0) { @@ -3434,7 +3406,7 @@ final_link_relocate (asection *input_section, (_("%B(%A+0x%lx): %s fixup for insn 0x%x is not supported in a non-shared link"), input_bfd, input_section, - offset, + (long) offset, howto->name, insn); } @@ -3598,7 +3570,7 @@ final_link_relocate (asection *input_section, (_("%B(%A+0x%lx): cannot reach %s, recompile with -ffunction-sections"), input_bfd, input_section, - offset, + (long) offset, hsh->bh_root.string); bfd_set_error (bfd_error_bad_value); return bfd_reloc_notsupported; @@ -3651,9 +3623,6 @@ elf32_hppa_relocate_section (bfd *output_bfd, Elf_Internal_Rela *rela; Elf_Internal_Rela *relend; - if (info->relocatable) - return TRUE; - symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; htab = hppa_link_hash_table (info); @@ -3685,7 +3654,6 @@ elf32_hppa_relocate_section (bfd *output_bfd, || r_type == (unsigned int) R_PARISC_GNU_VTINHERIT) continue; - /* This is a final link. */ r_symndx = ELF32_R_SYM (rela->r_info); hh = NULL; sym = NULL; @@ -3709,7 +3677,8 @@ elf32_hppa_relocate_section (bfd *output_bfd, eh, sym_sec, relocation, unresolved_reloc, warned_undef); - if (relocation == 0 + if (!info->relocatable + && relocation == 0 && eh->root.type != bfd_link_hash_defined && eh->root.type != bfd_link_hash_defweak && eh->root.type != bfd_link_hash_undefweak) @@ -3728,6 +3697,22 @@ elf32_hppa_relocate_section (bfd *output_bfd, hh = hppa_elf_hash_entry (eh); } + if (sym_sec != NULL && elf_discarded_section (sym_sec)) + { + /* 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. */ + _bfd_clear_contents (elf_hppa_howto_table + r_type, input_bfd, + contents + rela->r_offset); + rela->r_info = 0; + rela->r_addend = 0; + continue; + } + + if (info->relocatable) + continue; + /* Do any required modifications to the relocation value, and determine what types of dynamic info we need to output, if any. */ @@ -3939,16 +3924,6 @@ elf32_hppa_relocate_section (bfd *output_bfd, case R_PARISC_DPREL14R: case R_PARISC_DPREL21L: case R_PARISC_DIR32: - /* r_symndx will be zero only for relocs against symbols - from removed linkonce sections, or sections discarded by - a linker script. */ - if (r_symndx == 0) - { - _bfd_clear_contents (elf_hppa_howto_table + r_type, input_bfd, - contents + rela->r_offset); - break; - } - if ((input_section->flags & SEC_ALLOC) == 0) break; @@ -4598,30 +4573,6 @@ elf32_hppa_finish_dynamic_sections (bfd *output_bfd, return TRUE; } -/* Tweak the OSABI field of the elf header. */ - -static void -elf32_hppa_post_process_headers (bfd *abfd, - struct bfd_link_info *info ATTRIBUTE_UNUSED) -{ - Elf_Internal_Ehdr * i_ehdrp; - - i_ehdrp = elf_elfheader (abfd); - - if (strcmp (bfd_get_target (abfd), "elf32-hppa-linux") == 0) - { - i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_LINUX; - } - else if (strcmp (bfd_get_target (abfd), "elf32-hppa-netbsd") == 0) - { - i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_NETBSD; - } - else - { - i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_HPUX; - } -} - /* Called when writing out an object file to decide the type of a symbol. */ static int @@ -4636,10 +4587,12 @@ elf32_hppa_elf_get_symbol_type (Elf_Internal_Sym *elf_sym, int type) /* Misc BFD support code. */ #define bfd_elf32_bfd_is_local_label_name elf_hppa_is_local_label_name #define bfd_elf32_bfd_reloc_type_lookup elf_hppa_reloc_type_lookup +#define bfd_elf32_bfd_reloc_name_lookup elf_hppa_reloc_name_lookup #define elf_info_to_howto elf_hppa_info_to_howto #define elf_info_to_howto_rel elf_hppa_info_to_howto_rel /* Stuff for the BFD linker. */ +#define bfd_elf32_mkobject elf32_hppa_mkobject #define bfd_elf32_bfd_final_link elf32_hppa_final_link #define bfd_elf32_bfd_link_hash_table_create elf32_hppa_link_hash_table_create #define bfd_elf32_bfd_link_hash_table_free elf32_hppa_link_hash_table_free @@ -4660,7 +4613,7 @@ elf32_hppa_elf_get_symbol_type (Elf_Internal_Sym *elf_sym, int type) #define elf_backend_grok_psinfo elf32_hppa_grok_psinfo #define elf_backend_object_p elf32_hppa_object_p #define elf_backend_final_write_processing elf_hppa_final_write_processing -#define elf_backend_post_process_headers elf32_hppa_post_process_headers +#define elf_backend_post_process_headers _bfd_elf_set_osabi #define elf_backend_get_symbol_type elf32_hppa_elf_get_symbol_type #define elf_backend_reloc_type_class elf32_hppa_reloc_type_class #define elf_backend_action_discarded elf_hppa_action_discarded @@ -4679,20 +4632,29 @@ elf32_hppa_elf_get_symbol_type (Elf_Internal_Sym *elf_sym, int type) #define ELF_ARCH bfd_arch_hppa #define ELF_MACHINE_CODE EM_PARISC #define ELF_MAXPAGESIZE 0x1000 +#define ELF_OSABI ELFOSABI_HPUX +#define elf32_bed elf32_hppa_hpux_bed #include "elf32-target.h" #undef TARGET_BIG_SYM -#define TARGET_BIG_SYM bfd_elf32_hppa_linux_vec +#define TARGET_BIG_SYM bfd_elf32_hppa_linux_vec #undef TARGET_BIG_NAME -#define TARGET_BIG_NAME "elf32-hppa-linux" +#define TARGET_BIG_NAME "elf32-hppa-linux" +#undef ELF_OSABI +#define ELF_OSABI ELFOSABI_LINUX +#undef elf32_bed +#define elf32_bed elf32_hppa_linux_bed -#define INCLUDED_TARGET_FILE 1 #include "elf32-target.h" #undef TARGET_BIG_SYM -#define TARGET_BIG_SYM bfd_elf32_hppa_nbsd_vec +#define TARGET_BIG_SYM bfd_elf32_hppa_nbsd_vec #undef TARGET_BIG_NAME -#define TARGET_BIG_NAME "elf32-hppa-netbsd" +#define TARGET_BIG_NAME "elf32-hppa-netbsd" +#undef ELF_OSABI +#define ELF_OSABI ELFOSABI_NETBSD +#undef elf32_bed +#define elf32_bed elf32_hppa_netbsd_bed #include "elf32-target.h"