X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;ds=sidebyside;f=bfd%2Felf32-s390.c;h=67cc059c55903110b1bf2b7ebd2362234d3945eb;hb=377caf49a5881bb23084de3e9bcaa1812327119f;hp=597b4cda6307c7dc864135e348e19d3566012d66;hpb=eea6121ac0cb22524c627017191ca09825e3d702;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-s390.c b/bfd/elf32-s390.c index 597b4cda63..67cc059c55 100644 --- a/bfd/elf32-s390.c +++ b/bfd/elf32-s390.c @@ -1,12 +1,13 @@ /* IBM S/390-specific support for 32-bit ELF - Copyright 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 + Free Software Foundation, Inc. Contributed by Carl B. Pedersen and Martin Schwidefsky. This file is part of BFD, the Binary File Descriptor library. 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, @@ -16,11 +17,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., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ -#include "bfd.h" #include "sysdep.h" +#include "bfd.h" #include "bfdlink.h" #include "libbfd.h" #include "elf-bfd.h" @@ -40,17 +41,11 @@ static bfd_boolean create_got_section static bfd_boolean elf_s390_create_dynamic_sections PARAMS((bfd *, struct bfd_link_info *)); static void elf_s390_copy_indirect_symbol - PARAMS ((const struct elf_backend_data *, struct elf_link_hash_entry *, + PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *, struct elf_link_hash_entry *)); static bfd_boolean elf_s390_check_relocs PARAMS ((bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *)); -static asection *elf_s390_gc_mark_hook - PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *, - struct elf_link_hash_entry *, Elf_Internal_Sym *)); -static bfd_boolean elf_s390_gc_sweep_hook - PARAMS ((bfd *, struct bfd_link_info *, asection *, - const Elf_Internal_Rela *)); struct elf_s390_link_hash_entry; static void elf_s390_adjust_gotplt PARAMS ((struct elf_s390_link_hash_entry *)); @@ -72,8 +67,6 @@ static enum elf_reloc_type_class elf_s390_reloc_type_class PARAMS ((const Elf_Internal_Rela *)); static bfd_boolean elf_s390_finish_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *)); -static bfd_boolean elf_s390_mkobject - PARAMS ((bfd *)); static bfd_boolean elf_s390_object_p PARAMS ((bfd *)); static bfd_boolean elf_s390_grok_prstatus @@ -341,6 +334,25 @@ elf_s390_reloc_type_lookup (abfd, code) return 0; } +static reloc_howto_type * +elf_s390_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, + const char *r_name) +{ + unsigned int i; + + for (i = 0; i < sizeof (elf_howto_table) / sizeof (elf_howto_table[0]); i++) + if (elf_howto_table[i].name != NULL + && strcasecmp (elf_howto_table[i].name, r_name) == 0) + return &elf_howto_table[i]; + + if (strcasecmp (elf32_s390_vtinherit_howto.name, r_name) == 0) + return &elf32_s390_vtinherit_howto; + if (strcasecmp (elf32_s390_vtentry_howto.name, r_name) == 0) + return &elf32_s390_vtentry_howto; + + return NULL; +} + /* We need to use ELF32_R_TYPE so we have our own copy of this function, and elf32-s390.c has its own copy. */ @@ -350,7 +362,8 @@ elf_s390_info_to_howto (abfd, cache_ptr, dst) arelent *cache_ptr; Elf_Internal_Rela *dst; { - switch (ELF32_R_TYPE(dst->r_info)) + unsigned int r_type = ELF32_R_TYPE(dst->r_info); + switch (r_type) { case R_390_GNU_VTINHERIT: cache_ptr->howto = &elf32_s390_vtinherit_howto; @@ -361,8 +374,13 @@ elf_s390_info_to_howto (abfd, cache_ptr, dst) break; default: - BFD_ASSERT (ELF32_R_TYPE(dst->r_info) < (unsigned int) R_390_max); - cache_ptr->howto = &elf_howto_table[ELF32_R_TYPE(dst->r_info)]; + if (r_type >= sizeof (elf_howto_table) / sizeof (elf_howto_table[0])) + { + (*_bfd_error_handler) (_("%B: invalid relocation type %d"), + abfd, (int) r_type); + r_type = R_390_NONE; + } + cache_ptr->howto = &elf_howto_table[r_type]; } } @@ -398,7 +416,6 @@ s390_elf_ldisp_reloc (abfd, reloc_entry, symbol, data, input_section, reloc_howto_type *howto = reloc_entry->howto; bfd_vma relocation; bfd_vma insn; - bfd_size_type sz; if (output_bfd != (bfd *) NULL && (symbol->flags & BSF_SECTION_SYM) == 0 @@ -412,8 +429,7 @@ s390_elf_ldisp_reloc (abfd, reloc_entry, symbol, data, input_section, if (output_bfd != NULL) return bfd_reloc_continue; - sz = input_section->rawsize ? input_section->rawsize : input_section->size; - if (reloc_entry->address > sz) + if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) return bfd_reloc_outofrange; relocation = (symbol->value @@ -673,14 +689,16 @@ struct elf_s390_obj_tdata (elf_s390_tdata (abfd)->local_got_tls_type) static bfd_boolean -elf_s390_mkobject (abfd) - bfd *abfd; +elf_s390_mkobject (bfd *abfd) { - bfd_size_type amt = sizeof (struct elf_s390_obj_tdata); - abfd->tdata.any = bfd_zalloc (abfd, amt); if (abfd->tdata.any == NULL) - return FALSE; - return TRUE; + { + bfd_size_type amt = sizeof (struct elf_s390_obj_tdata); + abfd->tdata.any = bfd_zalloc (abfd, amt); + if (abfd->tdata.any == NULL) + return FALSE; + } + return bfd_elf_mkobject (abfd); } static bfd_boolean @@ -766,7 +784,8 @@ elf_s390_link_hash_table_create (abfd) if (ret == NULL) return NULL; - if (! _bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc)) + if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc, + sizeof (struct elf_s390_link_hash_entry))) { free (ret); return NULL; @@ -804,12 +823,13 @@ create_got_section (dynobj, info) if (!htab->sgot || !htab->sgotplt) abort (); - htab->srelgot = bfd_make_section (dynobj, ".rela.got"); + htab->srelgot = bfd_make_section_with_flags (dynobj, ".rela.got", + (SEC_ALLOC | SEC_LOAD + | SEC_HAS_CONTENTS + | SEC_IN_MEMORY + | SEC_LINKER_CREATED + | SEC_READONLY)); if (htab->srelgot == NULL - || ! bfd_set_section_flags (dynobj, htab->srelgot, - (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS - | SEC_IN_MEMORY | SEC_LINKER_CREATED - | SEC_READONLY)) || ! bfd_set_section_alignment (dynobj, htab->srelgot, 2)) return FALSE; return TRUE; @@ -849,8 +869,8 @@ elf_s390_create_dynamic_sections (dynobj, info) /* Copy the extra info we tack onto an elf_link_hash_entry. */ static void -elf_s390_copy_indirect_symbol (bed, dir, ind) - const struct elf_backend_data *bed; +elf_s390_copy_indirect_symbol (info, dir, ind) + struct bfd_link_info *info; struct elf_link_hash_entry *dir, *ind; { struct elf_s390_link_hash_entry *edir, *eind; @@ -865,10 +885,7 @@ elf_s390_copy_indirect_symbol (bed, dir, ind) struct elf_s390_dyn_relocs **pp; struct elf_s390_dyn_relocs *p; - if (ind->root.type == bfd_link_hash_indirect) - abort (); - - /* Add reloc counts against the weak sym to the strong sym + /* Add reloc counts against the indirect sym to the direct sym list. Merge any entries against the same section. */ for (pp = &eind->dyn_relocs; (p = *pp) != NULL; ) { @@ -901,17 +918,18 @@ elf_s390_copy_indirect_symbol (bed, dir, ind) if (ELIMINATE_COPY_RELOCS && ind->root.type != bfd_link_hash_indirect - && (dir->elf_link_hash_flags & ELF_LINK_HASH_DYNAMIC_ADJUSTED) != 0) - /* If called to transfer flags for a weakdef during processing - of elf_adjust_dynamic_symbol, don't copy ELF_LINK_NON_GOT_REF. - We clear it ourselves for ELIMINATE_COPY_RELOCS. */ - dir->elf_link_hash_flags |= - (ind->elf_link_hash_flags & (ELF_LINK_HASH_REF_DYNAMIC - | ELF_LINK_HASH_REF_REGULAR - | ELF_LINK_HASH_REF_REGULAR_NONWEAK - | ELF_LINK_HASH_NEEDS_PLT)); + && dir->dynamic_adjusted) + { + /* If called to transfer flags for a weakdef during processing + of elf_adjust_dynamic_symbol, don't copy non_got_ref. + We clear it ourselves for ELIMINATE_COPY_RELOCS. */ + dir->ref_dynamic |= ind->ref_dynamic; + dir->ref_regular |= ind->ref_regular; + dir->ref_regular_nonweak |= ind->ref_regular_nonweak; + dir->needs_plt |= ind->needs_plt; + } else - _bfd_elf_link_hash_copy_indirect (bed, dir, ind); + _bfd_elf_link_hash_copy_indirect (info, dir, ind); } static int @@ -982,16 +1000,20 @@ elf_s390_check_relocs (abfd, info, sec, relocs) if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr)) { - (*_bfd_error_handler) (_("%s: bad symbol index: %d"), - bfd_archive_filename (abfd), - r_symndx); + (*_bfd_error_handler) (_("%B: bad symbol index: %d"), + abfd, r_symndx); return FALSE; } if (r_symndx < symtab_hdr->sh_info) h = NULL; else - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + { + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + while (h->root.type == bfd_link_hash_indirect + || h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + } /* Create got section and local_got_refcounts array if they are needed. */ @@ -1071,7 +1093,7 @@ elf_s390_check_relocs (abfd, info, sec, relocs) creating a procedure linkage table entry. */ if (h != NULL) { - h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; + h->needs_plt = 1; h->plt.refcount += 1; } break; @@ -1092,7 +1114,7 @@ elf_s390_check_relocs (abfd, info, sec, relocs) if (h != NULL) { ((struct elf_s390_link_hash_entry *) h)->gotplt_refcount++; - h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; + h->needs_plt = 1; h->plt.refcount += 1; } else @@ -1160,8 +1182,8 @@ elf_s390_check_relocs (abfd, info, sec, relocs) if (old_tls_type == GOT_NORMAL || tls_type == GOT_NORMAL) { (*_bfd_error_handler) - (_("%s: `%s' accessed both as normal and thread local symbol"), - bfd_archive_filename (abfd), h->root.root.string); + (_("%B: `%s' accessed both as normal and thread local symbol"), + abfd, h->root.root.string); return FALSE; } if (old_tls_type > tls_type) @@ -1201,7 +1223,7 @@ elf_s390_check_relocs (abfd, info, sec, relocs) sections have not yet been mapped to output sections. Tentatively set the flag for now, and correct in adjust_dynamic_symbol. */ - h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF; + h->non_got_ref = 1; /* We may need a .plt entry if the function this reloc refers to is in a shared lib. */ @@ -1238,15 +1260,13 @@ elf_s390_check_relocs (abfd, info, sec, relocs) || (h != NULL && (! info->symbolic || h->root.type == bfd_link_hash_defweak - || (h->elf_link_hash_flags - & ELF_LINK_HASH_DEF_REGULAR) == 0)))) + || !h->def_regular)))) || (ELIMINATE_COPY_RELOCS && !info->shared && (sec->flags & SEC_ALLOC) != 0 && h != NULL && (h->root.type == bfd_link_hash_defweak - || (h->elf_link_hash_flags - & ELF_LINK_HASH_DEF_REGULAR) == 0))) + || !h->def_regular))) { struct elf_s390_dyn_relocs *p; struct elf_s390_dyn_relocs **head; @@ -1266,13 +1286,13 @@ elf_s390_check_relocs (abfd, info, sec, relocs) if (name == NULL) return FALSE; - if (strncmp (name, ".rela", 5) != 0 + if (! CONST_STRNEQ (name, ".rela") || strcmp (bfd_get_section_name (abfd, sec), name + 5) != 0) { (*_bfd_error_handler) - (_("%s: bad relocation section name `%s\'"), - bfd_archive_filename (abfd), name); + (_("%B: bad relocation section name `%s\'"), + abfd, name); } if (htab->elf.dynobj == NULL) @@ -1284,13 +1304,14 @@ elf_s390_check_relocs (abfd, info, sec, relocs) { flagword flags; - sreloc = bfd_make_section (dynobj, name); 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_flags (dynobj, sreloc, flags) || ! bfd_set_section_alignment (dynobj, sreloc, 2)) return FALSE; } @@ -1309,14 +1330,15 @@ elf_s390_check_relocs (abfd, info, sec, relocs) We really need local syms available to do this easily. Oh well. */ asection *s; + void *vpp; s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, sec, r_symndx); if (s == NULL) return FALSE; - head = ((struct elf_s390_dyn_relocs **) - &elf_section_data (s)->local_dynrel); + vpp = &elf_section_data (s)->local_dynrel; + head = (struct elf_s390_dyn_relocs **) vpp; } p = *head; @@ -1370,50 +1392,30 @@ elf_s390_check_relocs (abfd, info, sec, relocs) relocation. */ static asection * -elf_s390_gc_mark_hook (sec, info, rel, h, sym) - asection *sec; - struct bfd_link_info *info ATTRIBUTE_UNUSED; - Elf_Internal_Rela *rel; - struct elf_link_hash_entry *h; - Elf_Internal_Sym *sym; +elf_s390_gc_mark_hook (asection *sec, + struct bfd_link_info *info, + Elf_Internal_Rela *rel, + struct elf_link_hash_entry *h, + Elf_Internal_Sym *sym) { if (h != NULL) - { - switch (ELF32_R_TYPE (rel->r_info)) - { - case R_390_GNU_VTINHERIT: - case R_390_GNU_VTENTRY: - break; - - default: - switch (h->root.type) - { - case bfd_link_hash_defined: - case bfd_link_hash_defweak: - return h->root.u.def.section; + switch (ELF32_R_TYPE (rel->r_info)) + { + case R_390_GNU_VTINHERIT: + case R_390_GNU_VTENTRY: + return NULL; + } + return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); - case bfd_link_hash_common: - return h->root.u.c.p->section; - - default: - break; - } - } - } - else - return bfd_section_from_elf_index (sec->owner, sym->st_shndx); - - return NULL; } /* Update the got entry reference counts for the section being removed. */ static bfd_boolean -elf_s390_gc_sweep_hook (abfd, info, sec, relocs) - bfd *abfd; - struct bfd_link_info *info; - asection *sec; - const Elf_Internal_Rela *relocs; +elf_s390_gc_sweep_hook (bfd *abfd, + struct bfd_link_info *info, + asection *sec, + const Elf_Internal_Rela *relocs) { Elf_Internal_Shdr *symtab_hdr; struct elf_link_hash_entry **sym_hashes; @@ -1441,6 +1443,9 @@ elf_s390_gc_sweep_hook (abfd, info, sec, relocs) struct elf_s390_dyn_relocs *p; h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + while (h->root.type == bfd_link_hash_indirect + || h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; eh = (struct elf_s390_link_hash_entry *) h; for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) @@ -1577,18 +1582,17 @@ elf_s390_adjust_dynamic_symbol (info, h) { struct elf_s390_link_hash_table *htab; asection *s; - 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 (although we could actually do it here). */ if (h->type == STT_FUNC - || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0) + || h->needs_plt) { if (h->plt.refcount <= 0 || (! info->shared - && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0 - && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0 + && !h->def_dynamic + && !h->ref_dynamic && h->root.type != bfd_link_hash_undefweak && h->root.type != bfd_link_hash_undefined)) { @@ -1598,7 +1602,7 @@ elf_s390_adjust_dynamic_symbol (info, h) such a case, we don't actually need to build a procedure linkage table, and we can just do a PC32 reloc instead. */ h->plt.offset = (bfd_vma) -1; - h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; + h->needs_plt = 0; elf_s390_adjust_gotplt((struct elf_s390_link_hash_entry *) h); } @@ -1615,16 +1619,14 @@ elf_s390_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; if (ELIMINATE_COPY_RELOCS || info->nocopyreloc) - h->elf_link_hash_flags - = ((h->elf_link_hash_flags & ~ELF_LINK_NON_GOT_REF) - | (h->weakdef->elf_link_hash_flags & ELF_LINK_NON_GOT_REF)); + h->non_got_ref = h->u.weakdef->non_got_ref; return TRUE; } @@ -1640,13 +1642,13 @@ elf_s390_adjust_dynamic_symbol (info, h) /* If there are no references to this symbol that do not use the GOT, we don't need to generate a copy reloc. */ - if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0) + if (!h->non_got_ref) return TRUE; /* If -z nocopyreloc was given, we won't generate them either. */ if (info->nocopyreloc) { - h->elf_link_hash_flags &= ~ELF_LINK_NON_GOT_REF; + h->non_got_ref = 0; return TRUE; } @@ -1667,11 +1669,18 @@ elf_s390_adjust_dynamic_symbol (info, h) we'll be keeping the dynamic relocs and avoiding the copy reloc. */ if (p == NULL) { - h->elf_link_hash_flags &= ~ELF_LINK_NON_GOT_REF; + h->non_got_ref = 0; return TRUE; } } + if (h->size == 0) + { + (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"), + h->root.root.string); + return TRUE; + } + /* We must allocate the symbol in our .dynbss section, which will become part of the .bss section of the executable. There will be an entry for this symbol in the .dynsym section. The dynamic @@ -1690,32 +1699,12 @@ elf_s390_adjust_dynamic_symbol (info, h) if ((h->root.u.def.section->flags & SEC_ALLOC) != 0) { htab->srelbss->size += sizeof (Elf32_External_Rela); - h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY; + h->needs_copy = 1; } - /* We need to figure out the alignment required for this symbol. I - have no idea how ELF linkers handle this. */ - power_of_two = bfd_log2 (h->size); - if (power_of_two > 3) - power_of_two = 3; - - /* Apply the required alignment. */ s = htab->sdynbss; - s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two)); - if (power_of_two > bfd_get_section_alignment (htab->elf.dynobj, s)) - { - if (! bfd_set_section_alignment (htab->elf.dynobj, s, power_of_two)) - return FALSE; - } - /* Define the symbol as being at this point in the section. */ - h->root.u.def.section = s; - h->root.u.def.value = s->size; - - /* Increment the section size to make room for the symbol. */ - s->size += h->size; - - return TRUE; + return _bfd_elf_adjust_dynamic_copy (h, s); } /* Allocate space in .plt, .got and associated reloc sections for @@ -1751,7 +1740,7 @@ allocate_dynrelocs (h, inf) /* Make sure this symbol is output as a dynamic symbol. Undefined weak syms won't yet be marked as dynamic. */ if (h->dynindx == -1 - && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) + && !h->forced_local) { if (! bfd_elf_link_record_dynamic_symbol (info, h)) return FALSE; @@ -1775,7 +1764,7 @@ allocate_dynrelocs (h, inf) pointers compare as equal between the normal executable and the shared library. */ if (! info->shared - && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) + && !h->def_regular) { h->root.u.def.section = s; h->root.u.def.value = h->plt.offset; @@ -1794,14 +1783,14 @@ allocate_dynrelocs (h, inf) else { h->plt.offset = (bfd_vma) -1; - h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; + h->needs_plt = 0; elf_s390_adjust_gotplt((struct elf_s390_link_hash_entry *) h); } } else { h->plt.offset = (bfd_vma) -1; - h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; + h->needs_plt = 0; elf_s390_adjust_gotplt((struct elf_s390_link_hash_entry *) h); } @@ -1834,7 +1823,7 @@ allocate_dynrelocs (h, inf) /* Make sure this symbol is output as a dynamic symbol. Undefined weak syms won't yet be marked as dynamic. */ if (h->dynindx == -1 - && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) + && !h->forced_local) { if (! bfd_elf_link_record_dynamic_symbol (info, h)) return FALSE; @@ -1892,9 +1881,21 @@ allocate_dynrelocs (h, inf) /* Also discard relocs on undefined weak syms with non-default visibility. */ - if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT + if (eh->dyn_relocs != NULL && h->root.type == bfd_link_hash_undefweak) - eh->dyn_relocs = NULL; + { + if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT) + eh->dyn_relocs = NULL; + + /* Make sure undefined weak symbols are output as a dynamic + symbol in PIEs. */ + else if (h->dynindx == -1 + && !h->forced_local) + { + if (! bfd_elf_link_record_dynamic_symbol (info, h)) + return FALSE; + } + } } else if (ELIMINATE_COPY_RELOCS) { @@ -1902,9 +1903,9 @@ allocate_dynrelocs (h, inf) symbols which turn out to need copy relocs or are not dynamic. */ - if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0 - && (((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0 - && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) + if (!h->non_got_ref + && ((h->def_dynamic + && !h->def_regular) || (htab->elf.dynamic_sections_created && (h->root.type == bfd_link_hash_undefweak || h->root.type == bfd_link_hash_undefined)))) @@ -1912,7 +1913,7 @@ allocate_dynrelocs (h, inf) /* Make sure this symbol is output as a dynamic symbol. Undefined weak syms won't yet be marked as dynamic. */ if (h->dynindx == -1 - && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) + && !h->forced_local) { if (! bfd_elf_link_record_dynamic_symbol (info, h)) return FALSE; @@ -2020,10 +2021,7 @@ elf_s390_size_dynamic_sections (output_bfd, info) { struct elf_s390_dyn_relocs *p; - for (p = *((struct elf_s390_dyn_relocs **) - &elf_section_data (s)->local_dynrel); - p != NULL; - p = p->next) + for (p = elf_section_data (s)->local_dynrel; p != NULL; p = p->next) { if (!bfd_is_abs_section (p->sec) && bfd_is_abs_section (p->sec->output_section)) @@ -2094,12 +2092,13 @@ elf_s390_size_dynamic_sections (output_bfd, info) if (s == htab->splt || s == htab->sgot - || s == htab->sgotplt) + || s == htab->sgotplt + || s == htab->sdynbss) { /* Strip this section if we don't need it; see the comment below. */ } - else if (strncmp (bfd_get_section_name (dynobj, s), ".rela", 5) == 0) + else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rela")) { if (s->size != 0) relocs = TRUE; @@ -2126,10 +2125,13 @@ elf_s390_size_dynamic_sections (output_bfd, info) function which decides whether anything needs to go into these sections. */ - _bfd_strip_section_from_output (info, s); + s->flags |= SEC_EXCLUDE; continue; } + if ((s->flags & SEC_HAS_CONTENTS) == 0) + continue; + /* Allocate memory for the section contents. We use bfd_zalloc here in case unused entries are not reclaimed before the section's contents are written out. This should not happen, @@ -2233,11 +2235,12 @@ invalid_tls_insn (input_bfd, input_section, rel) howto = elf_howto_table + ELF32_R_TYPE (rel->r_info); (*_bfd_error_handler) - (_("%s(%s+0x%lx): invalid instruction for TLS relocation %s"), - bfd_archive_filename (input_bfd), - bfd_get_section_name (input_bfd, input_section), + (_("%B(%A+0x%lx): invalid instruction for TLS relocation %s"), + input_bfd, + input_section, (long) rel->r_offset, howto->name); + bfd_set_error (bfd_error_bad_value); } /* Relocate a 390 ELF section. */ @@ -2261,9 +2264,6 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, Elf_Internal_Rela *rel; Elf_Internal_Rela *relend; - if (info->relocatable) - return TRUE; - htab = elf_s390_hash_table (info); symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; sym_hashes = elf_sym_hashes (input_bfd); @@ -2298,7 +2298,6 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, howto = elf_howto_table + r_type; r_symndx = ELF32_R_SYM (rel->r_info); - /* This is a final link. */ h = NULL; sym = NULL; sec = NULL; @@ -2319,6 +2318,20 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, unresolved_reloc, warned); } + if (sec != NULL && elf_discarded_section (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 (howto, input_bfd, contents + rel->r_offset); + rel->r_info = 0; + rel->r_addend = 0; + continue; + } + + if (info->relocatable) + continue; + switch (r_type) { case R_390_GOTPLT12: @@ -2375,8 +2388,8 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, || (info->shared && (info->symbolic || h->dynindx == -1 - || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL)) - && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)) + || h->forced_local) + && h->def_regular) || (ELF_ST_VISIBILITY (h->other) && h->root.type == bfd_link_hash_undefweak)) { @@ -2535,11 +2548,7 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, case R_390_PC16DBL: case R_390_PC32DBL: case R_390_PC32: - /* 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 - || (input_section->flags & SEC_ALLOC) == 0) + if ((input_section->flags & SEC_ALLOC) == 0) break; if ((info->shared @@ -2556,11 +2565,9 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, && !info->shared && h != NULL && h->dynindx != -1 - && (h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0 - && (((h->elf_link_hash_flags - & ELF_LINK_HASH_DEF_DYNAMIC) != 0 - && (h->elf_link_hash_flags - & ELF_LINK_HASH_DEF_REGULAR) == 0) + && !h->non_got_ref + && ((h->def_dynamic + && !h->def_regular) || h->root.type == bfd_link_hash_undefweak || h->root.type == bfd_link_hash_undefined))) { @@ -2596,8 +2603,7 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, || r_type == R_390_PC32 || !info->shared || !info->symbolic - || (h->elf_link_hash_flags - & ELF_LINK_HASH_DEF_REGULAR) == 0)) + || !h->def_regular)) { outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); outrel.r_addend = rel->r_addend; @@ -2628,14 +2634,18 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, osec = sec->output_section; sindx = elf_section_data (osec)->dynindx; - BFD_ASSERT (sindx > 0); + if (sindx == 0) + { + osec = htab->elf.text_index_section; + sindx = elf_section_data (osec)->dynindx; + } + BFD_ASSERT (sindx != 0); /* We are turning this relocation into one against a section symbol, so subtract out the output section's address but not the offset of the input section in the output section. */ - outrel.r_addend -= osec->vma; } outrel.r_info = ELF32_R_INFO (sindx, r_type); @@ -2899,7 +2909,7 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, continue; case R_390_TLS_LDO32: - if (info->shared || (input_section->flags & SEC_CODE) == 0) + if (info->shared) relocation -= dtpoff_base (info); else /* When converting LDO to LE, we must negate. */ @@ -2955,16 +2965,44 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, unsigned int insn; insn = bfd_get_32 (input_bfd, contents + rel->r_offset); - if ((insn & 0xff000fff) != 0x4d000000) + if ((insn & 0xff000fff) != 0x4d000000 && + (insn & 0xffff0000) != 0xc0e50000) invalid_tls_insn (input_bfd, input_section, rel); if (!info->shared && (h == NULL || h->dynindx == -1)) - /* GD->LE transition. - bas %r14,0(%rx,%r13) -> bc 0,0 */ - insn = 0x47000000; + { + if ((insn & 0xff000000) == 0x4d000000) + { + /* GD->LE transition. + bas %r14,0(%rx,%r13) -> bc 0,0 */ + insn = 0x47000000; + } + else + { + /* GD->LE transition. + brasl %r14,_tls_get_addr@plt -> brcl 0,. */ + insn = 0xc0040000; + bfd_put_16 (output_bfd, 0x0000, + contents + rel->r_offset + 4); + } + } else - /* GD->IE transition. - bas %r14,0(%rx,%r13) -> l %r2,0(%r2,%r12) */ - insn = 0x5822c000; + { + if ((insn & 0xff000000) == 0x4d000000) + { + /* GD->IE transition. + bas %r14,0(%rx,%r13) -> l %r2,0(%r2,%r12) */ + insn = 0x5822c000; + } + else + { + /* GD->IE transition. + brasl %r14,__tls_get_addr@plt -> + l %r2,0(%r2,%r12) ; bcr 0,0 */ + insn = 0x5822c000; + bfd_put_16 (output_bfd, 0x0700, + contents + rel->r_offset + 4); + } + } bfd_put_32 (output_bfd, insn, contents + rel->r_offset); } else if (r_type == R_390_TLS_LDCALL) @@ -2974,11 +3012,23 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, unsigned int insn; insn = bfd_get_32 (input_bfd, contents + rel->r_offset); - if ((insn & 0xff000fff) != 0x4d000000) + if ((insn & 0xff000fff) != 0x4d000000 && + (insn & 0xffff0000) != 0xc0e50000) invalid_tls_insn (input_bfd, input_section, rel); - /* LD->LE transition. - bas %r14,0(%rx,%r13) -> bc 0,0 */ - insn = 0x47000000; + if ((insn & 0xff000000) == 0x4d000000) + { + /* LD->LE transition. + bas %r14,0(%rx,%r13) -> bc 0,0 */ + insn = 0x47000000; + } + else + { + /* LD->LE transition. + brasl %r14,__tls_get_addr@plt -> brcl 0,. */ + insn = 0xc0040000; + bfd_put_16 (output_bfd, 0x0000, + contents + rel->r_offset + 4); + } bfd_put_32 (output_bfd, insn, contents + rel->r_offset); } } @@ -2993,12 +3043,13 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, not process them. */ if (unresolved_reloc && !((input_section->flags & SEC_DEBUGGING) != 0 - && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0)) + && h->def_dynamic)) (*_bfd_error_handler) - (_("%s(%s+0x%lx): unresolvable relocation against symbol `%s'"), - bfd_archive_filename (input_bfd), - bfd_get_section_name (input_bfd, input_section), + (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"), + input_bfd, + input_section, (long) rel->r_offset, + howto->name, h->root.root.string); if (r_type == R_390_20 @@ -3038,16 +3089,16 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, { if (! ((*info->callbacks->reloc_overflow) - (info, name, howto->name, (bfd_vma) 0, - input_bfd, input_section, rel->r_offset))) + (info, (h ? &h->root : NULL), name, howto->name, + (bfd_vma) 0, input_bfd, input_section, + rel->r_offset))) return FALSE; } else { (*_bfd_error_handler) - (_("%s(%s+0x%lx): reloc against `%s': error %d"), - bfd_archive_filename (input_bfd), - bfd_get_section_name (input_bfd, input_section), + (_("%B(%A+0x%lx): reloc against `%s': error %d"), + input_bfd, input_section, (long) rel->r_offset, name, (int) r); return FALSE; } @@ -3198,7 +3249,7 @@ elf_s390_finish_dynamic_symbol (output_bfd, info, h, sym) loc = htab->srelplt->contents + plt_index * sizeof (Elf32_External_Rela); bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); - if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) + if (!h->def_regular) { /* Mark the symbol as undefined, rather than as defined in the .plt section. Leave the value alone. This is a clue @@ -3235,8 +3286,8 @@ elf_s390_finish_dynamic_symbol (output_bfd, info, h, sym) if (info->shared && (info->symbolic || h->dynindx == -1 - || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL)) - && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)) + || h->forced_local) + && h->def_regular) { BFD_ASSERT((h->got.offset & 1) != 0); rela.r_info = ELF32_R_INFO (0, R_390_RELATIVE); @@ -3257,7 +3308,7 @@ elf_s390_finish_dynamic_symbol (output_bfd, info, h, sym) bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); } - if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0) + if (h->needs_copy) { Elf_Internal_Rela rela; bfd_byte *loc; @@ -3282,8 +3333,8 @@ elf_s390_finish_dynamic_symbol (output_bfd, info, h, sym) /* Mark some specially defined symbols as absolute. */ if (strcmp (h->root.root.string, "_DYNAMIC") == 0 - || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0 - || strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0) + || h == htab->elf.hgot + || h == htab->elf.hplt) sym->st_shndx = SHN_ABS; return TRUE; @@ -3487,6 +3538,7 @@ elf_s390_plt_sym_val (bfd_vma i, const asection *plt, #define bfd_elf32_bfd_is_local_label_name elf_s390_is_local_label_name #define bfd_elf32_bfd_link_hash_table_create elf_s390_link_hash_table_create #define bfd_elf32_bfd_reloc_type_lookup elf_s390_reloc_type_lookup +#define bfd_elf32_bfd_reloc_name_lookup elf_s390_reloc_name_lookup #define elf_backend_adjust_dynamic_symbol elf_s390_adjust_dynamic_symbol #define elf_backend_check_relocs elf_s390_check_relocs @@ -3499,6 +3551,7 @@ elf_s390_plt_sym_val (bfd_vma i, const asection *plt, #define elf_backend_reloc_type_class elf_s390_reloc_type_class #define elf_backend_relocate_section elf_s390_relocate_section #define elf_backend_size_dynamic_sections elf_s390_size_dynamic_sections +#define elf_backend_init_index_section _bfd_elf_init_1_index_section #define elf_backend_reloc_type_class elf_s390_reloc_type_class #define elf_backend_grok_prstatus elf_s390_grok_prstatus #define elf_backend_plt_sym_val elf_s390_plt_sym_val