X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felf32-s390.c;h=b0f87523d4249dfebc1da724469b9603b8e09f3c;hb=63c1f59d665542359de4737e3e48033c588f44dc;hp=ae8b5b969f0875062bb5e04e2f3615d36255cee1;hpb=e81830c5c61a8665c098189d069cc68b0df113d3;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-s390.c b/bfd/elf32-s390.c index ae8b5b969f..b0f87523d4 100644 --- a/bfd/elf32-s390.c +++ b/bfd/elf32-s390.c @@ -1,5 +1,5 @@ /* IBM S/390-specific support for 32-bit ELF - Copyright (C) 2000-2016 Free Software Foundation, Inc. + Copyright (C) 2000-2017 Free Software Foundation, Inc. Contributed by Carl B. Pedersen and Martin Schwidefsky. This file is part of BFD, the Binary File Descriptor library. @@ -945,7 +945,7 @@ elf_s390_check_relocs (bfd *abfd, for (rel = relocs; rel < rel_end; rel++) { unsigned int r_type; - unsigned long r_symndx; + unsigned int r_symndx; struct elf_link_hash_entry *h; r_symndx = ELF32_R_SYM (rel->r_info); @@ -993,10 +993,6 @@ elf_s390_check_relocs (bfd *abfd, 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; - - /* PR15323, ref flags aren't set for references in the same - object. */ - h->root.non_ir_ref = 1; } /* Create got section and local_got_refcounts array if they @@ -1401,180 +1397,6 @@ elf_s390_gc_mark_hook (asection *sec, } -/* Update the got entry reference counts for the section being removed. */ - -static bfd_boolean -elf_s390_gc_sweep_hook (bfd *abfd, - struct bfd_link_info *info, - asection *sec, - const Elf_Internal_Rela *relocs) -{ - struct elf_s390_link_hash_table *htab; - Elf_Internal_Shdr *symtab_hdr; - struct elf_link_hash_entry **sym_hashes; - bfd_signed_vma *local_got_refcounts; - const Elf_Internal_Rela *rel, *relend; - - if (bfd_link_relocatable (info)) - return TRUE; - - htab = elf_s390_hash_table (info); - if (htab == NULL) - return FALSE; - - elf_section_data (sec)->local_dynrel = NULL; - - symtab_hdr = &elf_symtab_hdr (abfd); - sym_hashes = elf_sym_hashes (abfd); - local_got_refcounts = elf_local_got_refcounts (abfd); - - relend = relocs + sec->reloc_count; - for (rel = relocs; rel < relend; rel++) - { - unsigned long r_symndx; - unsigned int r_type; - struct elf_link_hash_entry *h = NULL; - - r_symndx = ELF32_R_SYM (rel->r_info); - if (r_symndx >= symtab_hdr->sh_info) - { - struct elf_s390_link_hash_entry *eh; - struct elf_dyn_relocs **pp; - struct elf_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) - if (p->sec == sec) - { - /* Everything must go for SEC. */ - *pp = p->next; - break; - } - } - else - { - Elf_Internal_Sym *isym; - - /* A local symbol. */ - isym = bfd_sym_from_r_symndx (&htab->sym_cache, - abfd, r_symndx); - if (isym == NULL) - return FALSE; - - if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC) - { - struct plt_entry *plt = elf_s390_local_plt (abfd); - if (plt[r_symndx].plt.refcount > 0) - plt[r_symndx].plt.refcount--; - } - } - - r_type = ELF32_R_TYPE (rel->r_info); - r_type = elf_s390_tls_transition (info, r_type, h != NULL); - switch (r_type) - { - case R_390_TLS_LDM32: - if (elf_s390_hash_table (info)->tls_ldm_got.refcount > 0) - elf_s390_hash_table (info)->tls_ldm_got.refcount -= 1; - break; - - case R_390_GOTOFF16: - case R_390_GOTOFF32: - if (h != NULL && s390_is_ifunc_symbol_p (h) && h->def_regular) - { - h->plt.refcount--; - break; - } - - case R_390_GOTPC: - case R_390_GOTPCDBL: - break; - - case R_390_TLS_GD32: - case R_390_TLS_IE32: - case R_390_TLS_GOTIE12: - case R_390_TLS_GOTIE20: - case R_390_TLS_GOTIE32: - case R_390_TLS_IEENT: - case R_390_GOT12: - case R_390_GOT16: - case R_390_GOT20: - case R_390_GOT32: - case R_390_GOTENT: - if (h != NULL) - { - if (h->got.refcount > 0) - h->got.refcount -= 1; - } - else if (local_got_refcounts != NULL) - { - if (local_got_refcounts[r_symndx] > 0) - local_got_refcounts[r_symndx] -= 1; - } - break; - - case R_390_8: - case R_390_12: - case R_390_16: - case R_390_20: - case R_390_32: - case R_390_PC16: - case R_390_PC12DBL: - case R_390_PC16DBL: - case R_390_PC24DBL: - case R_390_PC32DBL: - case R_390_PC32: - if (bfd_link_pic (info)) - break; - /* Fall through. */ - - case R_390_PLT12DBL: - case R_390_PLT16DBL: - case R_390_PLT24DBL: - case R_390_PLT32DBL: - case R_390_PLT32: - case R_390_PLTOFF16: - case R_390_PLTOFF32: - if (h != NULL) - { - if (h->plt.refcount > 0) - h->plt.refcount -= 1; - } - break; - - case R_390_GOTPLT12: - case R_390_GOTPLT16: - case R_390_GOTPLT20: - case R_390_GOTPLT32: - case R_390_GOTPLTENT: - if (h != NULL) - { - if (h->plt.refcount > 0) - { - ((struct elf_s390_link_hash_entry *) h)->gotplt_refcount--; - h->plt.refcount -= 1; - } - } - else if (local_got_refcounts != NULL) - { - if (local_got_refcounts[r_symndx] > 0) - local_got_refcounts[r_symndx] -= 1; - } - break; - - default: - break; - } - } - - return TRUE; -} - /* Make sure we emit a GOT entry if the symbol was supposed to have a PLT entry but we found we will not create any. Called when we find we will not have any PLT for this symbol, by for example @@ -1597,6 +1419,23 @@ elf_s390_adjust_gotplt (struct elf_s390_link_hash_entry *h) h->gotplt_refcount = -1; } +/* Find dynamic relocs for H that apply to read-only sections. */ + +static asection * +readonly_dynrelocs (struct elf_link_hash_entry *h) +{ + struct elf_dyn_relocs *p; + + for (p = elf_s390_hash_entry (h)->dyn_relocs; p != NULL; p = p->next) + { + asection *s = p->sec->output_section; + + if (s != NULL && (s->flags & SEC_READONLY) != 0) + return p->sec; + } + return NULL; +} + /* Adjust a symbol defined by a dynamic object and referenced by a regular object. The current definition is in some section of the dynamic object, but we're not including those sections. We have to @@ -1688,14 +1527,14 @@ elf_s390_adjust_dynamic_symbol (struct bfd_link_info *info, /* 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->u.weakdef != NULL) + if (h->is_weakalias) { - 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; + struct elf_link_hash_entry *def = weakdef (h); + BFD_ASSERT (def->root.type == bfd_link_hash_defined); + h->root.u.def.section = def->root.u.def.section; + h->root.u.def.value = def->root.u.def.value; if (ELIMINATE_COPY_RELOCS || info->nocopyreloc) - h->non_got_ref = h->u.weakdef->non_got_ref; + h->non_got_ref = def->non_got_ref; return TRUE; } @@ -1947,7 +1786,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) if (eh->dyn_relocs != NULL && h->root.type == bfd_link_hash_undefweak) { - if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT) + if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT + || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)) eh->dyn_relocs = NULL; /* Make sure undefined weak symbols are output as a dynamic @@ -2004,28 +1844,29 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) return TRUE; } -/* Find any dynamic relocs that apply to read-only sections. */ +/* Set DF_TEXTREL if we find any dynamic relocs that apply to + read-only sections. */ static bfd_boolean -readonly_dynrelocs (struct elf_link_hash_entry *h, void * inf) +maybe_set_textrel (struct elf_link_hash_entry *h, void *info_p) { - struct elf_s390_link_hash_entry *eh; - struct elf_dyn_relocs *p; + asection *sec; - eh = (struct elf_s390_link_hash_entry *) h; - for (p = eh->dyn_relocs; p != NULL; p = p->next) - { - asection *s = p->sec->output_section; + if (h->root.type == bfd_link_hash_indirect) + return TRUE; - if (s != NULL && (s->flags & SEC_READONLY) != 0) - { - struct bfd_link_info *info = (struct bfd_link_info *) inf; + sec = readonly_dynrelocs (h); + if (sec != NULL) + { + struct bfd_link_info *info = (struct bfd_link_info *) info_p; - info->flags |= DF_TEXTREL; + info->flags |= DF_TEXTREL; + info->callbacks->minfo + (_("%B: dynamic relocation against `%T' in read-only section `%A'\n"), + sec->owner, h->root.root.string, sec); - /* Not an error, just cut short the traversal. */ - return FALSE; - } + /* Not an error, just cut short the traversal. */ + return FALSE; } return TRUE; } @@ -2253,7 +2094,7 @@ elf_s390_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, /* If any dynamic relocs apply to a read-only section, then we need a DT_TEXTREL entry. */ if ((info->flags & DF_TEXTREL) == 0) - elf_link_hash_traverse (&htab->elf, readonly_dynrelocs, info); + elf_link_hash_traverse (&htab->elf, maybe_set_textrel, info); if ((info->flags & DF_TEXTREL) != 0) { @@ -2307,10 +2148,10 @@ invalid_tls_insn (bfd *input_bfd, howto = elf_howto_table + ELF32_R_TYPE (rel->r_info); _bfd_error_handler /* xgettext:c-format */ - (_("%B(%A+0x%lx): invalid instruction for TLS relocation %s"), + (_("%B(%A+%#Lx): invalid instruction for TLS relocation %s"), input_bfd, input_section, - (long) rel->r_offset, + rel->r_offset, howto->name); bfd_set_error (bfd_error_bad_value); } @@ -2357,6 +2198,7 @@ elf_s390_relocate_section (bfd *output_bfd, bfd_reloc_status_type r; int tls_type; asection *base_got = htab->elf.sgot; + bfd_boolean resolved_to_zero; r_type = ELF32_R_TYPE (rel->r_info); if (r_type == (int) R_390_GNU_VTINHERIT @@ -2448,6 +2290,9 @@ elf_s390_relocate_section (bfd *output_bfd, if (bfd_link_relocatable (info)) continue; + resolved_to_zero = (h != NULL + && UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)); + switch (r_type) { case R_390_GOTPLT12: @@ -2774,7 +2619,7 @@ elf_s390_relocate_section (bfd *output_bfd, && s390_is_ifunc_symbol_p (h) && h->def_regular) { - if (!bfd_link_pic (info) || !h->non_got_ref) + if (!bfd_link_pic (info)) { /* For a non-shared object STT_GNU_IFUNC symbol must go through PLT. */ @@ -2836,7 +2681,8 @@ elf_s390_relocate_section (bfd *output_bfd, if ((bfd_link_pic (info) && (h == NULL - || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT + || (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT + && !resolved_to_zero) || h->root.type != bfd_link_hash_undefweak) && ((r_type != R_390_PC16 && r_type != R_390_PC12DBL @@ -3231,7 +3077,6 @@ elf_s390_relocate_section (bfd *output_bfd, unsigned int insn, ry; insn = bfd_get_32 (input_bfd, contents + rel->r_offset); - ry = 0; if ((insn & 0xff00f000) == 0x58000000) /* l %rx,0(%ry,0) -> lr %rx,%ry + bcr 0,0 */ ry = (insn & 0x000f0000); @@ -3245,7 +3090,10 @@ elf_s390_relocate_section (bfd *output_bfd, /* l %rx,0(%r12,%ry) -> lr %rx,%ry + bcr 0,0 */ ry = (insn & 0x0000f000) << 4; else - invalid_tls_insn (input_bfd, input_section, rel); + { + invalid_tls_insn (input_bfd, input_section, rel); + return FALSE; + } insn = 0x18000700 | (insn & 0x00f00000) | ry; bfd_put_32 (output_bfd, insn, contents + rel->r_offset); } @@ -3258,7 +3106,10 @@ elf_s390_relocate_section (bfd *output_bfd, if ((insn & 0xff000fff) != 0x4d000000 && (insn & 0xffff0000) != 0xc0e50000 && (insn & 0xff000000) != 0x0d000000) - invalid_tls_insn (input_bfd, input_section, rel); + { + invalid_tls_insn (input_bfd, input_section, rel); + return FALSE; + } if (!bfd_link_pic (info) && (h == NULL || h->dynindx == -1)) { if ((insn & 0xff000000) == 0x0d000000) @@ -3287,7 +3138,10 @@ elf_s390_relocate_section (bfd *output_bfd, /* If basr is used in the pic case to invoke _tls_get_offset, something went wrong before. */ if ((insn & 0xff000000) == 0x0d000000) - invalid_tls_insn (input_bfd, input_section, rel); + { + invalid_tls_insn (input_bfd, input_section, rel); + return FALSE; + } if ((insn & 0xff000000) == 0x4d000000) { @@ -3317,7 +3171,10 @@ elf_s390_relocate_section (bfd *output_bfd, if ((insn & 0xff000fff) != 0x4d000000 && (insn & 0xffff0000) != 0xc0e50000 && (insn & 0xff000000) != 0x0d000000) - invalid_tls_insn (input_bfd, input_section, rel); + { + invalid_tls_insn (input_bfd, input_section, rel); + return FALSE; + } if ((insn & 0xff000000) == 0x0d000000) { @@ -3358,10 +3215,10 @@ elf_s390_relocate_section (bfd *output_bfd, rel->r_offset) != (bfd_vma) -1) _bfd_error_handler /* xgettext:c-format */ - (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"), + (_("%B(%A+%#Lx): unresolvable %s relocation against symbol `%s'"), input_bfd, input_section, - (long) rel->r_offset, + rel->r_offset, howto->name, h->root.root.string); @@ -3415,9 +3272,9 @@ elf_s390_relocate_section (bfd *output_bfd, { _bfd_error_handler /* xgettext:c-format */ - (_("%B(%A+0x%lx): reloc against `%s': error %d"), + (_("%B(%A+%#Lx): reloc against `%s': error %d"), input_bfd, input_section, - (long) rel->r_offset, name, (int) r); + rel->r_offset, name, (int) r); return FALSE; } } @@ -3785,7 +3642,7 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd, RELATIVE reloc. The entry in the global offset table will already have been initialized in the relocate_section function. */ - if (!h->def_regular) + if (!(h->def_regular || ELF_COMMON_DEF_P (h))) return FALSE; BFD_ASSERT((h->got.offset & 1) != 0); rela.r_info = ELF32_R_INFO (0, R_390_RELATIVE); @@ -3827,7 +3684,7 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd, + h->root.u.def.section->output_offset); rela.r_info = ELF32_R_INFO (h->dynindx, R_390_COPY); rela.r_addend = 0; - if ((h->root.u.def.section->flags & SEC_READONLY) != 0) + if (h->root.u.def.section == htab->elf.sdynrelro) s = htab->elf.sreldynrelro; else s = htab->elf.srelbss; @@ -3930,7 +3787,9 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd, break; case DT_PLTRELSZ: - dyn.d_un.d_val = htab->elf.srelplt->size + htab->elf.irelplt->size; + dyn.d_un.d_val = htab->elf.srelplt->size; + if (htab->elf.irelplt) + dyn.d_un.d_val += htab->elf.irelplt->size; break; } @@ -3988,6 +3847,9 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd, symtab_hdr = &elf_symtab_hdr (ibfd); + if (!is_s390_elf (ibfd)) + continue; + local_plt = elf_s390_local_plt (ibfd); if (local_plt != NULL) for (i = 0; i < symtab_hdr->sh_info; i++) @@ -4188,7 +4050,6 @@ elf32_s390_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) #define elf_backend_finish_dynamic_sections elf_s390_finish_dynamic_sections #define elf_backend_finish_dynamic_symbol elf_s390_finish_dynamic_symbol #define elf_backend_gc_mark_hook elf_s390_gc_mark_hook -#define elf_backend_gc_sweep_hook elf_s390_gc_sweep_hook #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 @@ -4203,4 +4064,6 @@ elf32_s390_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) #define bfd_elf32_mkobject elf_s390_mkobject #define elf_backend_object_p elf_s390_object_p +#define elf_backend_linux_prpsinfo32_ugid16 TRUE + #include "elf32-target.h"