X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felfxx-sparc.c;h=849182fc8cc49659ade4ee241e902bc516c77427;hb=f657f8c4a1dc0ac69b16b1dc6eacbf5286f1f0a0;hp=98850595661dbc89878dd6223486605c109532b7;hpb=a9d44aad42e127adadbad35f23931d8d83aa40c1;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elfxx-sparc.c b/bfd/elfxx-sparc.c index 9885059566..849182fc8c 100644 --- a/bfd/elfxx-sparc.c +++ b/bfd/elfxx-sparc.c @@ -1,5 +1,5 @@ /* SPARC-specific support for ELF - Copyright (C) 2005-2017 Free Software Foundation, Inc. + Copyright (C) 2005-2018 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -311,7 +311,7 @@ static reloc_howto_type sparc_rev32_howto = HOWTO(R_SPARC_REV32, 0,2,32,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_REV32", FALSE,0,0xffffffff,TRUE); reloc_howto_type * -_bfd_sparc_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, +_bfd_sparc_elf_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code) { /* We explicitly handle each relocation type in the switch @@ -585,8 +585,10 @@ _bfd_sparc_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, default: break; } - bfd_set_error (bfd_error_bad_value); - return NULL; + /* xgettext:c-format */ + _bfd_error_handler (_("%pB: unsupported relocation type %#x"), abfd, (int) code); + bfd_set_error (bfd_error_bad_value); + return NULL; } reloc_howto_type * @@ -595,10 +597,7 @@ _bfd_sparc_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, { unsigned int i; - for (i = 0; - i < (sizeof (_bfd_sparc_elf_howto_table) - / sizeof (_bfd_sparc_elf_howto_table[0])); - i++) + for (i = 0; i < ARRAY_SIZE (_bfd_sparc_elf_howto_table); i++) if (_bfd_sparc_elf_howto_table[i].name != NULL && strcasecmp (_bfd_sparc_elf_howto_table[i].name, r_name) == 0) return &_bfd_sparc_elf_howto_table[i]; @@ -614,7 +613,8 @@ _bfd_sparc_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, } reloc_howto_type * -_bfd_sparc_elf_info_to_howto_ptr (unsigned int r_type) +_bfd_sparc_elf_info_to_howto_ptr (bfd *abfd ATTRIBUTE_UNUSED, + unsigned int r_type) { switch (r_type) { @@ -636,8 +636,10 @@ _bfd_sparc_elf_info_to_howto_ptr (unsigned int r_type) default: if (r_type >= (unsigned int) R_SPARC_max_std) { - _bfd_error_handler (_("invalid relocation type %d"), (int) r_type); - r_type = R_SPARC_NONE; + _bfd_error_handler (_("%pB: unsupported relocation type %#x"), + abfd, r_type); + bfd_set_error (bfd_error_bad_value); + return NULL; } return &_bfd_sparc_elf_howto_table[r_type]; } @@ -648,13 +650,20 @@ _bfd_sparc_elf_info_to_howto_ptr (unsigned int r_type) #define SPARC_ELF_R_TYPE(r_info) \ ((r_info) & 0xff) -void -_bfd_sparc_elf_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr, +bfd_boolean +_bfd_sparc_elf_info_to_howto (bfd *abfd, arelent *cache_ptr, Elf_Internal_Rela *dst) { unsigned int r_type = SPARC_ELF_R_TYPE (dst->r_info); - cache_ptr->howto = _bfd_sparc_elf_info_to_howto_ptr (r_type); + if ((cache_ptr->howto = _bfd_sparc_elf_info_to_howto_ptr (abfd, r_type)) == NULL) + { + _bfd_error_handler (_("%pB: unsupported relocation type %#x"), + abfd, r_type); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + return TRUE; } @@ -673,9 +682,9 @@ _bfd_sparc_elf_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr, ((EH)->elf.root.type == bfd_link_hash_undefweak \ && bfd_link_executable (INFO) \ && (_bfd_sparc_elf_hash_table (INFO)->interp == NULL \ - || !(EH)->has_got_reloc \ + || !(INFO)->dynamic_undefined_weak \ || (EH)->has_non_got_reloc \ - || !(INFO)->dynamic_undefined_weak)) + || !(EH)->has_got_reloc)) /* SPARC ELF linker hash entry. */ @@ -750,6 +759,7 @@ sparc_elf_append_rela (bfd *abfd, asection *s, Elf_Internal_Rela *rel) bfd_byte *loc; bed = get_elf_backend_data (abfd); + BFD_ASSERT (s->reloc_count * bed->s->sizeof_rela < s->size); loc = s->contents + (s->reloc_count++ * bed->s->sizeof_rela); bed->s->swap_reloca_out (abfd, rel, loc); } @@ -1310,8 +1320,7 @@ _bfd_sparc_elf_copy_indirect_symbol (struct bfd_link_info *info, eind->dyn_relocs = NULL; } - if (ind->root.type == bfd_link_hash_indirect - && dir->got.refcount <= 0) + if (ind->root.type == bfd_link_hash_indirect && dir->got.refcount <= 0) { edir->tls_type = eind->tls_type; eind->tls_type = GOT_UNKNOWN; @@ -1331,7 +1340,7 @@ sparc_elf_tls_transition (struct bfd_link_info *info, bfd *abfd, if (! ABI_64_P (abfd) && r_type == R_SPARC_TLS_GD_HI22 && ! _bfd_sparc_elf_tdata (abfd)->has_tlsgd) - r_type = R_SPARC_REV32; + return R_SPARC_REV32; if (!bfd_link_executable (info)) return r_type; @@ -1339,25 +1348,17 @@ sparc_elf_tls_transition (struct bfd_link_info *info, bfd *abfd, switch (r_type) { case R_SPARC_TLS_GD_HI22: - if (is_local) - return R_SPARC_TLS_LE_HIX22; - return R_SPARC_TLS_IE_HI22; + return is_local ? R_SPARC_TLS_LE_HIX22 : R_SPARC_TLS_IE_HI22; case R_SPARC_TLS_GD_LO10: - if (is_local) - return R_SPARC_TLS_LE_LOX10; - return R_SPARC_TLS_IE_LO10; - case R_SPARC_TLS_IE_HI22: - if (is_local) - return R_SPARC_TLS_LE_HIX22; - return r_type; - case R_SPARC_TLS_IE_LO10: - if (is_local) - return R_SPARC_TLS_LE_LOX10; - return r_type; + return is_local ? R_SPARC_TLS_LE_LOX10 : R_SPARC_TLS_IE_LO10; case R_SPARC_TLS_LDM_HI22: return R_SPARC_TLS_LE_HIX22; case R_SPARC_TLS_LDM_LO10: return R_SPARC_TLS_LE_LOX10; + case R_SPARC_TLS_IE_HI22: + return is_local ? R_SPARC_TLS_LE_HIX22 : r_type; + case R_SPARC_TLS_IE_LO10: + return is_local ? R_SPARC_TLS_LE_LOX10 : r_type; } return r_type; @@ -1417,7 +1418,7 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr)) { /* xgettext:c-format */ - _bfd_error_handler (_("%B: bad symbol index: %d"), abfd, r_symndx); + _bfd_error_handler (_("%pB: bad symbol index: %d"), abfd, r_symndx); return FALSE; } @@ -1425,16 +1426,14 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, if (r_symndx < symtab_hdr->sh_info) { /* A local symbol. */ - isym = bfd_sym_from_r_symndx (&htab->sym_cache, - abfd, r_symndx); + isym = bfd_sym_from_r_symndx (&htab->sym_cache, abfd, r_symndx); if (isym == NULL) return FALSE; /* Check relocation against local STT_GNU_IFUNC symbol. */ if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC) { - h = elf_sparc_get_local_sym_hash (htab, abfd, rel, - TRUE); + h = elf_sparc_get_local_sym_hash (htab, abfd, rel, TRUE); if (h == NULL) return FALSE; @@ -1456,13 +1455,10 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, h = (struct elf_link_hash_entry *) h->root.u.i.link; } - if (h && h->type == STT_GNU_IFUNC) + if (h && h->type == STT_GNU_IFUNC && h->def_regular) { - if (h->def_regular) - { - h->ref_regular = 1; - h->plt.refcount += 1; - } + h->ref_regular = 1; + h->plt.refcount += 1; } /* Compatibility with old R_SPARC_REV32 reloc conflicting @@ -1530,14 +1526,6 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, switch (r_type) { - default: - case R_SPARC_GOT10: - case R_SPARC_GOT13: - case R_SPARC_GOT22: - case R_SPARC_GOTDATA_OP_HIX22: - case R_SPARC_GOTDATA_OP_LOX10: - tls_type = GOT_NORMAL; - break; case R_SPARC_TLS_GD_HI22: case R_SPARC_TLS_GD_LO10: tls_type = GOT_TLS_GD; @@ -1546,6 +1534,9 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_SPARC_TLS_IE_LO10: tls_type = GOT_TLS_IE; break; + default: + tls_type = GOT_NORMAL; + break; } if (h != NULL) @@ -1573,39 +1564,33 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, _bfd_sparc_elf_local_got_tls_type (abfd) = (char *) (local_got_refcounts + symtab_hdr->sh_info); } - switch (r_type) - { - case R_SPARC_GOTDATA_OP_HIX22: - case R_SPARC_GOTDATA_OP_LOX10: - break; - default: - local_got_refcounts[r_symndx] += 1; - break; - } + if (r_type != R_SPARC_GOTDATA_OP_HIX22 + && r_type != R_SPARC_GOTDATA_OP_LOX10) + local_got_refcounts[r_symndx] += 1; + old_tls_type = _bfd_sparc_elf_local_got_tls_type (abfd) [r_symndx]; } - /* If a TLS symbol is accessed using IE at least once, - there is no point to use dynamic model for it. */ - if (old_tls_type != tls_type && old_tls_type != GOT_UNKNOWN - && (old_tls_type != GOT_TLS_GD - || tls_type != GOT_TLS_IE)) + /* If a TLS symbol is accessed using IE at least once, there is no point + in using the dynamic model for it. */ + if (old_tls_type != tls_type) { - if (old_tls_type == GOT_TLS_IE && tls_type == GOT_TLS_GD) + if (old_tls_type == GOT_UNKNOWN) + ; + else if (old_tls_type == GOT_TLS_GD && tls_type == GOT_TLS_IE) + ; + else if (old_tls_type == GOT_TLS_IE && tls_type == GOT_TLS_GD) tls_type = old_tls_type; else { _bfd_error_handler /* xgettext:c-format */ - (_("%B: `%s' accessed both as normal and thread local symbol"), + (_("%pB: `%s' accessed both as normal and thread local symbol"), abfd, h ? h->root.root.string : ""); return FALSE; } - } - if (old_tls_type != tls_type) - { if (h != NULL) _bfd_sparc_elf_hash_entry (h)->tls_type = tls_type; else @@ -1613,11 +1598,9 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, } } - if (htab->elf.sgot == NULL) - { - if (!_bfd_elf_create_got_section (htab->elf.dynobj, info)) - return FALSE; - } + if (!htab->elf.sgot + && !_bfd_elf_create_got_section (htab->elf.dynobj, info)) + return FALSE; if (eh != NULL) eh->has_got_reloc = 1; @@ -1625,33 +1608,26 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_SPARC_TLS_GD_CALL: case R_SPARC_TLS_LDM_CALL: - if (!bfd_link_executable (info)) - { - /* These are basically R_SPARC_TLS_WPLT30 relocs against - __tls_get_addr. */ - struct bfd_link_hash_entry *bh = NULL; - if (! _bfd_generic_link_add_one_symbol (info, abfd, - "__tls_get_addr", 0, - bfd_und_section_ptr, 0, - NULL, FALSE, FALSE, - &bh)) - return FALSE; - h = (struct elf_link_hash_entry *) bh; - } - else + if (bfd_link_executable (info)) break; + + /* Essentially R_SPARC_WPLT30 relocs against __tls_get_addr. */ + h = (struct elf_link_hash_entry *) + bfd_link_hash_lookup (info->hash, "__tls_get_addr", FALSE, + FALSE, TRUE); + BFD_ASSERT (h != NULL); /* Fall through */ - case R_SPARC_PLT32: case R_SPARC_WPLT30: + case R_SPARC_PLT32: + case R_SPARC_PLT64: case R_SPARC_HIPLT22: case R_SPARC_LOPLT10: case R_SPARC_PCPLT32: case R_SPARC_PCPLT22: case R_SPARC_PCPLT10: - case R_SPARC_PLT64: - /* This symbol requires a procedure linkage table entry. We - actually build the entry in adjust_dynamic_symbol, + /* This symbol requires a procedure linkage table entry. + We actually build the entry in adjust_dynamic_symbol, because this might be a case of linking PIC code without linking in any dynamic objects, in which case we don't need to generate a procedure linkage table after all. */ @@ -1664,7 +1640,7 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, reloc for a local symbol if you assemble a call from one section to another when using -K pic. We treat it as WDISP30. */ - if (ELF32_R_TYPE (rel->r_info) == R_SPARC_PLT32) + if (r_type == R_SPARC_PLT32) goto r_sparc_plt32; break; } @@ -1680,14 +1656,9 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, h->needs_plt = 1; - { - int this_r_type; + if (r_type == R_SPARC_PLT32 || r_type == R_SPARC_PLT64) + goto r_sparc_plt32; - this_r_type = SPARC_ELF_R_TYPE (rel->r_info); - if (this_r_type == R_SPARC_PLT32 - || this_r_type == R_SPARC_PLT64) - goto r_sparc_plt32; - } h->plt.refcount += 1; eh = (struct _bfd_sparc_elf_link_hash_entry *) h; @@ -1891,9 +1862,7 @@ _bfd_sparc_elf_gc_mark_hook (asection *sec, return NULL; } - /* FIXME: The test here, in check_relocs and in relocate_section - dealing with TLS optimization, ought to be !bfd_link_executable (info). */ - if (bfd_link_pic (info)) + if (!bfd_link_executable (info)) { switch (SPARC_ELF_R_TYPE (rel->r_info)) { @@ -2009,8 +1978,8 @@ _bfd_sparc_elf_adjust_dynamic_symbol (struct bfd_link_info *info, if (h->plt.refcount <= 0 || (h->type != STT_GNU_IFUNC && (SYMBOL_CALLS_LOCAL (info, h) - || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT - && h->root.type == bfd_link_hash_undefweak)))) + || (h->root.type == bfd_link_hash_undefweak + && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)))) { /* This case can occur if we saw a WPLT30 reloc in an input file, but the symbol was never referred to by a dynamic @@ -2129,12 +2098,11 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) && h->def_regular && h->ref_regular)) { - /* 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->forced_local + /* Undefined weak syms won't yet be marked as dynamic. */ + if (h->root.type == bfd_link_hash_undefweak && !resolved_to_zero - && h->root.type == bfd_link_hash_undefweak) + && h->dynindx == -1 + && !h->forced_local) { if (! bfd_elf_link_record_dynamic_symbol (info, h)) return FALSE; @@ -2242,12 +2210,11 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) bfd_boolean dyn; int tls_type = _bfd_sparc_elf_hash_entry(h)->tls_type; - /* 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->forced_local + /* Undefined weak syms won't yet be marked as dynamic. */ + if (h->root.type == bfd_link_hash_undefweak && !resolved_to_zero - && h->root.type == bfd_link_hash_undefweak) + && h->dynindx == -1 + && !h->forced_local) { if (! bfd_elf_link_record_dynamic_symbol (info, h)) return FALSE; @@ -2261,21 +2228,25 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) s->size += SPARC_ELF_WORD_BYTES (htab); dyn = htab->elf.dynamic_sections_created; /* R_SPARC_TLS_IE_{HI22,LO10} needs one dynamic relocation, - R_SPARC_TLS_GD_{HI22,LO10} needs one if local symbol and two if - global. No dynamic relocations are needed against resolved - undefined weak symbols in an executable. */ + R_SPARC_TLS_GD_{HI22,LO10} needs one if local and two if global. */ if ((tls_type == GOT_TLS_GD && h->dynindx == -1) || tls_type == GOT_TLS_IE || h->type == STT_GNU_IFUNC) htab->elf.srelgot->size += SPARC_ELF_RELA_BYTES (htab); else if (tls_type == GOT_TLS_GD) htab->elf.srelgot->size += 2 * SPARC_ELF_RELA_BYTES (htab); - else if (((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT - && !resolved_to_zero) - || h->root.type != bfd_link_hash_undefweak) - && WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, - bfd_link_pic (info), - h)) + else if ((WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info), h) + /* Even if the symbol isn't dynamic, we may generate a + reloc for the dynamic linker in PIC mode. */ + || (h->dynindx == -1 + && !h->forced_local + && h->root.type != bfd_link_hash_undefweak + && bfd_link_pic (info))) + /* No dynamic relocations are needed against resolved + undefined weak symbols in an executable. */ + && !(h->root.type == bfd_link_hash_undefweak + && (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT + || resolved_to_zero))) htab->elf.srelgot->size += SPARC_ELF_RELA_BYTES (htab); } else @@ -2385,12 +2356,11 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) && (h->root.type == bfd_link_hash_undefweak || h->root.type == bfd_link_hash_undefined)))) { - /* 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->forced_local + /* Undefined weak syms won't yet be marked as dynamic. */ + if (h->root.type == bfd_link_hash_undefweak && !resolved_to_zero - && h->root.type == bfd_link_hash_undefweak) + && h->dynindx == -1 + && !h->forced_local) { if (! bfd_elf_link_record_dynamic_symbol (info, h)) return FALSE; @@ -2454,7 +2424,7 @@ maybe_set_textrel (struct elf_link_hash_entry *h, void *info_p) info->flags |= DF_TEXTREL; info->callbacks->minfo - (_("%B: dynamic relocation against `%T' in read-only section `%A'\n"), + (_("%pB: dynamic relocation against `%pT' in read-only section `%pA'\n"), sec->owner, h->root.root.string, sec); /* Not an error, just cut short the traversal. */ @@ -2477,7 +2447,7 @@ _bfd_sparc_elf_omit_section_dynsym (bfd *output_bfd, if (strcmp (p->name, ".got") == 0) return FALSE; - return _bfd_elf_link_omit_section_dynsym (output_bfd, info, p); + return _bfd_elf_omit_section_dynsym_default (output_bfd, info, p); } /* Set the sizes of the dynamic sections. */ @@ -2553,7 +2523,7 @@ _bfd_sparc_elf_size_dynamic_sections (bfd *output_bfd, if ((p->sec->output_section->flags & SEC_READONLY) != 0) { info->flags |= DF_TEXTREL; - info->callbacks->minfo (_("%B: dynamic relocation in read-only section `%A'\n"), + info->callbacks->minfo (_("%pB: dynamic relocation in read-only section `%pA'\n"), p->sec->owner, p->sec); } } @@ -2968,8 +2938,8 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, bfd_set_error (bfd_error_bad_value); return FALSE; } - howto = _bfd_sparc_elf_howto_table + r_type; + howto = _bfd_sparc_elf_howto_table + r_type; r_symndx = SPARC_ELF_R_SYMNDX (htab, rel->r_info); h = NULL; sym = NULL; @@ -3031,7 +3001,13 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, if ((input_section->flags & SEC_ALLOC) == 0 || h->plt.offset == (bfd_vma) -1) - abort (); + { + /* If this is a SHT_NOTE section without SHF_ALLOC, treat + STT_GNU_IFUNC symbol as STT_FUNC. */ + if (elf_section_type (input_section) == SHT_NOTE) + goto skip_ifunc; + abort (); + } plt_sec = htab->elf.splt; if (! plt_sec) @@ -3126,7 +3102,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, NULL); _bfd_error_handler /* xgettext:c-format */ - (_("%B: relocation %s against STT_GNU_IFUNC " + (_("%pB: relocation %s against STT_GNU_IFUNC " "symbol `%s' isn't handled by %s"), input_bfd, _bfd_sparc_elf_howto_table[r_type].name, name, __FUNCTION__); @@ -3135,9 +3111,9 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, } } + skip_ifunc: eh = (struct _bfd_sparc_elf_link_hash_entry *) h; - resolved_to_zero = (eh != NULL - && UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, eh)); + resolved_to_zero = eh && UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, eh); switch (r_type) { @@ -3160,6 +3136,26 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, /* {ld,ldx} [%rs1 + %rs2], %rd --> add %rs1, %rs2, %rd */ relocation = 0x80000000 | (insn & 0x3e07c01f); bfd_put_32 (output_bfd, relocation, contents + rel->r_offset); + + /* If the symbol is global but not dynamic, an .rela.* slot has + been allocated for it in the GOT so output R_SPARC_NONE here. + See also the handling of other GOT relocations just below. */ + if (h != NULL + && h->dynindx == -1 + && !h->forced_local + && h->root.type != bfd_link_hash_undefweak + && (h->got.offset & 1) == 0 + && bfd_link_pic (info)) + { + asection *s = htab->elf.srelgot; + Elf_Internal_Rela outrel; + + BFD_ASSERT (s != NULL); + + memset (&outrel, 0, sizeof outrel); + sparc_elf_append_rela (output_bfd, s, &outrel); + h->got.offset |= 1; + } } continue; } @@ -3212,15 +3208,13 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, off &= ~1; else { + /* If this symbol isn't dynamic in PIC mode, treat it + like a local symbol in PIC mode below. */ if (h->dynindx == -1 && !h->forced_local && h->root.type != bfd_link_hash_undefweak && bfd_link_pic (info)) - { - /* If this symbol isn't dynamic in PIC - generate R_SPARC_RELATIVE here. */ - relative_reloc = TRUE; - } + relative_reloc = TRUE; else SPARC_ELF_PUT_WORD (htab, output_bfd, relocation, htab->elf.sgot->contents + off); @@ -3244,6 +3238,8 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, off &= ~1; else { + /* For a local symbol in PIC mode, we need to generate a + R_SPARC_RELATIVE reloc for the dynamic linker. */ if (bfd_link_pic (info)) relative_reloc = TRUE; else @@ -3255,12 +3251,9 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, if (relative_reloc) { - asection *s; + asection *s = htab->elf.srelgot; Elf_Internal_Rela outrel; - /* We need to generate a R_SPARC_RELATIVE reloc - for the dynamic linker. */ - s = htab->elf.srelgot; BFD_ASSERT (s != NULL); outrel.r_offset = (htab->elf.sgot->output_section->vma @@ -3383,8 +3376,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, case R_SPARC_H34: case R_SPARC_UA64: r_sparc_plt32: - if ((input_section->flags & SEC_ALLOC) == 0 - || is_vxworks_tls) + if ((input_section->flags & SEC_ALLOC) == 0 || is_vxworks_tls) break; /* Copy dynamic function pointer relocations. Don't generate @@ -3392,9 +3384,9 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, in PIE. */ if ((bfd_link_pic (info) && (h == NULL - || ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT - && !resolved_to_zero) - || h->root.type != bfd_link_hash_undefweak)) + || !(h->root.type == bfd_link_hash_undefweak + && (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT + || resolved_to_zero))) && (! howto->pc_relative || !SYMBOL_CALLS_LOCAL (info, h))) || (!bfd_link_pic (info) @@ -3481,7 +3473,6 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, || !SYMBOLIC_BIND (info, h) || !h->def_regular)) { - BFD_ASSERT (h->dynindx != -1); outrel.r_info = SPARC_ELF_R_INFO (htab, rel, h->dynindx, r_type); outrel.r_addend = rel->r_addend; } @@ -3534,7 +3525,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, { BFD_FAIL (); _bfd_error_handler - (_("%B: probably compiled without -fPIC?"), + (_("%pB: probably compiled without -fPIC?"), input_bfd); bfd_set_error (bfd_error_bad_value); return FALSE; @@ -3556,40 +3547,19 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, break; case R_SPARC_TLS_GD_HI22: - if (! ABI_64_P (input_bfd) - && ! _bfd_sparc_elf_tdata (input_bfd)->has_tlsgd) - { - /* R_SPARC_REV32 used the same reloc number as - R_SPARC_TLS_GD_HI22. */ - r_type = R_SPARC_REV32; - break; - } - /* Fall through */ - case R_SPARC_TLS_GD_LO10: case R_SPARC_TLS_IE_HI22: case R_SPARC_TLS_IE_LO10: - r_type = sparc_elf_tls_transition (info, input_bfd, r_type, h == NULL); - tls_type = GOT_UNKNOWN; - if (h == NULL && local_got_offsets) + r_type = sparc_elf_tls_transition (info, input_bfd, r_type, + h == NULL || h->dynindx == -1); + if (r_type == R_SPARC_REV32) + break; + if (h != NULL) + tls_type = _bfd_sparc_elf_hash_entry (h)->tls_type; + else if (local_got_offsets) tls_type = _bfd_sparc_elf_local_got_tls_type (input_bfd) [r_symndx]; - else if (h != NULL) - { - tls_type = _bfd_sparc_elf_hash_entry(h)->tls_type; - if (bfd_link_executable (info) - && h->dynindx == -1 - && tls_type == GOT_TLS_IE) - switch (SPARC_ELF_R_TYPE (rel->r_info)) - { - case R_SPARC_TLS_GD_HI22: - case R_SPARC_TLS_IE_HI22: - r_type = R_SPARC_TLS_LE_HIX22; - break; - default: - r_type = R_SPARC_TLS_LE_LOX10; - break; - } - } + else + tls_type = GOT_UNKNOWN; if (tls_type == GOT_TLS_IE) switch (r_type) { @@ -3700,7 +3670,8 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, case R_SPARC_TLS_LDM_HI22: case R_SPARC_TLS_LDM_LO10: - if (! bfd_link_pic (info)) + /* LD -> LE */ + if (bfd_link_executable (info)) { bfd_put_32 (output_bfd, SPARC_NOP, contents + rel->r_offset); continue; @@ -3711,14 +3682,19 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, case R_SPARC_TLS_LDO_HIX22: case R_SPARC_TLS_LDO_LOX10: - if (bfd_link_pic (info)) + /* LD -> LE */ + if (bfd_link_executable (info)) + { + if (r_type == R_SPARC_TLS_LDO_HIX22) + r_type = R_SPARC_TLS_LE_HIX22; + else + r_type = R_SPARC_TLS_LE_LOX10; + } + else { relocation -= dtpoff_base (info); break; } - - r_type = (r_type == R_SPARC_TLS_LDO_HIX22 - ? R_SPARC_TLS_LE_HIX22 : R_SPARC_TLS_LE_LOX10); /* Fall through. */ case R_SPARC_TLS_LE_HIX22: @@ -3726,28 +3702,22 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, if (!bfd_link_executable (info)) { Elf_Internal_Rela outrel; - bfd_boolean skip; - - BFD_ASSERT (sreloc != NULL); - skip = FALSE; - outrel.r_offset = - _bfd_elf_section_offset (output_bfd, info, input_section, - rel->r_offset); - if (outrel.r_offset == (bfd_vma) -1) - skip = TRUE; - else if (outrel.r_offset == (bfd_vma) -2) - skip = TRUE; - outrel.r_offset += (input_section->output_section->vma - + input_section->output_offset); - if (skip) + bfd_vma offset + = _bfd_elf_section_offset (output_bfd, info, input_section, + rel->r_offset); + if (offset == (bfd_vma) -1 || offset == (bfd_vma) -2) memset (&outrel, 0, sizeof outrel); else { + outrel.r_offset = offset + + input_section->output_section->vma + + input_section->output_offset; outrel.r_info = SPARC_ELF_R_INFO (htab, NULL, 0, r_type); - outrel.r_addend = relocation - dtpoff_base (info) - + rel->r_addend; + outrel.r_addend + = relocation - dtpoff_base (info) + rel->r_addend; } + BFD_ASSERT (sreloc != NULL); sparc_elf_append_rela (output_bfd, sreloc, &outrel); continue; } @@ -3755,6 +3725,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, break; case R_SPARC_TLS_LDM_CALL: + /* LD -> LE */ if (bfd_link_executable (info)) { /* mov %g0, %o0 */ @@ -3764,20 +3735,22 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, /* Fall through */ case R_SPARC_TLS_GD_CALL: - tls_type = GOT_UNKNOWN; - if (h == NULL && local_got_offsets) + if (h != NULL) + tls_type = _bfd_sparc_elf_hash_entry (h)->tls_type; + else if (local_got_offsets) tls_type = _bfd_sparc_elf_local_got_tls_type (input_bfd) [r_symndx]; - else if (h != NULL) - tls_type = _bfd_sparc_elf_hash_entry(h)->tls_type; + else + tls_type = GOT_UNKNOWN; + /* GD -> IE or LE */ if (bfd_link_executable (info) || (r_type == R_SPARC_TLS_GD_CALL && tls_type == GOT_TLS_IE)) { Elf_Internal_Rela *rel2; bfd_vma insn; - if (!bfd_link_pic (info) && (h == NULL || h->dynindx == -1)) + /* GD -> LE */ + if (bfd_link_executable (info) && (h == NULL || h->dynindx == -1)) { - /* GD -> LE */ bfd_put_32 (output_bfd, SPARC_NOP, contents + rel->r_offset); continue; } @@ -3840,12 +3813,14 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, goto r_sparc_wplt30; case R_SPARC_TLS_GD_ADD: - tls_type = GOT_UNKNOWN; - if (h == NULL && local_got_offsets) + if (h != NULL) + tls_type = _bfd_sparc_elf_hash_entry (h)->tls_type; + else if (local_got_offsets) tls_type = _bfd_sparc_elf_local_got_tls_type (input_bfd) [r_symndx]; - else if (h != NULL) - tls_type = _bfd_sparc_elf_hash_entry(h)->tls_type; - if (! bfd_link_pic (info) || tls_type == GOT_TLS_IE) + else + tls_type = GOT_UNKNOWN; + /* GD -> IE or LE */ + if (bfd_link_executable (info) || tls_type == GOT_TLS_IE) { /* add %reg1, %reg2, %reg3, %tgd_add(foo) changed into IE: @@ -3853,21 +3828,23 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, or LE: add %g7, %reg2, %reg3. */ bfd_vma insn = bfd_get_32 (input_bfd, contents + rel->r_offset); - if ((h != NULL && h->dynindx != -1) || bfd_link_pic (info)) - relocation = insn | (ABI_64_P (output_bfd) ? 0xc0580000 : 0xc0000000); - else + if (bfd_link_executable (info) && (h == NULL || h->dynindx == -1)) relocation = (insn & ~0x7c000) | 0x1c000; + else + relocation = insn | (ABI_64_P (output_bfd) ? 0xc0580000 : 0xc0000000); bfd_put_32 (output_bfd, relocation, contents + rel->r_offset); } continue; case R_SPARC_TLS_LDM_ADD: - if (! bfd_link_pic (info)) + /* LD -> LE */ + if (bfd_link_executable (info)) bfd_put_32 (output_bfd, SPARC_NOP, contents + rel->r_offset); continue; case R_SPARC_TLS_LDO_ADD: - if (! bfd_link_pic (info)) + /* LD -> LE */ + if (bfd_link_executable (info)) { /* Change rs1 into %g7. */ bfd_vma insn = bfd_get_32 (input_bfd, contents + rel->r_offset); @@ -3878,6 +3855,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, case R_SPARC_TLS_IE_LD: case R_SPARC_TLS_IE_LDX: + /* IE -> LE */ if (bfd_link_executable (info) && (h == NULL || h->dynindx == -1)) { bfd_vma insn = bfd_get_32 (input_bfd, contents + rel->r_offset); @@ -3915,10 +3893,11 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, rel->r_offset) != (bfd_vma) -1) _bfd_error_handler /* xgettext:c-format */ - (_("%B(%A+%#Lx): unresolvable %s relocation against symbol `%s'"), + (_("%pB(%pA+%#" PRIx64 "): " + "unresolvable %s relocation against symbol `%s'"), input_bfd, input_section, - rel->r_offset, + (uint64_t) rel->r_offset, howto->name, h->root.root.string); @@ -4326,7 +4305,7 @@ _bfd_sparc_elf_finish_dynamic_symbol (bfd *output_bfd, struct _bfd_sparc_elf_link_hash_table *htab; const struct elf_backend_data *bed; struct _bfd_sparc_elf_link_hash_entry *eh; - bfd_boolean local_undefweak; + bfd_boolean resolved_to_zero; htab = _bfd_sparc_elf_hash_table (info); BFD_ASSERT (htab != NULL); @@ -4337,7 +4316,7 @@ _bfd_sparc_elf_finish_dynamic_symbol (bfd *output_bfd, /* We keep PLT/GOT entries without dynamic PLT/GOT relocations for resolved undefined weak symbols in executable so that their references have value 0 at run-time. */ - local_undefweak = UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, eh); + resolved_to_zero = UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, eh); if (h->plt.offset != (bfd_vma) -1) { @@ -4462,8 +4441,7 @@ _bfd_sparc_elf_finish_dynamic_symbol (bfd *output_bfd, loc += rela_index * bed->s->sizeof_rela; bed->s->swap_reloca_out (output_bfd, &rela, loc); - if (!local_undefweak - && !h->def_regular) + if (!resolved_to_zero && !h->def_regular) { /* Mark the symbol as undefined, rather than as defined in the .plt section. Leave the value alone. */ @@ -4477,12 +4455,14 @@ _bfd_sparc_elf_finish_dynamic_symbol (bfd *output_bfd, } } - /* Don't generate dynamic GOT relocation against undefined weak - symbol in executable. */ + /* Don't generate dynamic GOT relocation against resolved undefined weak + symbols in an executable. */ if (h->got.offset != (bfd_vma) -1 && _bfd_sparc_elf_hash_entry(h)->tls_type != GOT_TLS_GD && _bfd_sparc_elf_hash_entry(h)->tls_type != GOT_TLS_IE - && !local_undefweak) + && !(h->root.type == bfd_link_hash_undefweak + && (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT + || resolved_to_zero))) { asection *sgot; asection *srela; @@ -4518,8 +4498,8 @@ _bfd_sparc_elf_finish_dynamic_symbol (bfd *output_bfd, + (h->got.offset & ~(bfd_vma) 1)); return TRUE; } - else if (bfd_link_pic (info) - && SYMBOL_REFERENCES_LOCAL (info, h)) + + if (bfd_link_pic (info) && SYMBOL_REFERENCES_LOCAL (info, h)) { asection *sec = h->root.u.def.section; if (h->type == STT_GNU_IFUNC)