X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felfxx-sparc.c;h=5ef29eac28382bcd1937800573ab02814125cd71;hb=refs%2Fheads%2Fconcurrent-displaced-stepping-2020-04-01;hp=adc9ed3f3ab1f54873b1aec77bc736273c9314c6;hpb=07d6d2b8345ef3dc82eab49635acac9ee67dbb18;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elfxx-sparc.c b/bfd/elfxx-sparc.c index adc9ed3f3a..5ef29eac28 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-2020 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,18 @@ _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_set_error (bfd_error_bad_value); + return FALSE; + } + return TRUE; } @@ -673,9 +680,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. */ @@ -683,18 +690,18 @@ struct _bfd_sparc_elf_link_hash_entry { struct elf_link_hash_entry elf; - /* Track dynamic relocs copied for this symbol. */ - struct elf_dyn_relocs *dyn_relocs; - #define GOT_UNKNOWN 0 #define GOT_NORMAL 1 #define GOT_TLS_GD 2 #define GOT_TLS_IE 3 unsigned char tls_type; - /* Symbol has GOT or PLT relocations. */ + /* Symbol has GOT or PLT relocations. */ unsigned int has_got_reloc : 1; + /* Symbol has old-style, non-relaxable GOT relocations. */ + unsigned int has_old_style_got_reloc : 1; + /* Symbol has non-GOT/non-PLT relocations in text sections. */ unsigned int has_non_got_reloc : 1; @@ -750,6 +757,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); } @@ -1017,7 +1025,6 @@ link_hash_newfunc (struct bfd_hash_entry *entry, struct _bfd_sparc_elf_link_hash_entry *eh; eh = (struct _bfd_sparc_elf_link_hash_entry *) entry; - eh->dyn_relocs = NULL; eh->tls_type = GOT_UNKNOWN; eh->has_got_reloc = 0; eh->has_non_got_reloc = 0; @@ -1125,7 +1132,7 @@ struct bfd_link_hash_table * _bfd_sparc_elf_link_hash_table_create (bfd *abfd) { struct _bfd_sparc_elf_link_hash_table *ret; - bfd_size_type amt = sizeof (struct _bfd_sparc_elf_link_hash_table); + size_t amt = sizeof (struct _bfd_sparc_elf_link_hash_table); ret = (struct _bfd_sparc_elf_link_hash_table *) bfd_zmalloc (amt); if (ret == NULL) @@ -1252,15 +1259,14 @@ create_ifunc_sections (bfd *abfd, struct bfd_link_info *info) s = bfd_make_section_with_flags (abfd, ".iplt", pltflags); if (s == NULL - || ! bfd_set_section_alignment (abfd, s, bed->plt_alignment)) + || !bfd_set_section_alignment (s, bed->plt_alignment)) return FALSE; htab->iplt = s; s = bfd_make_section_with_flags (abfd, ".rela.iplt", flags | SEC_READONLY); if (s == NULL - || ! bfd_set_section_alignment (abfd, s, - bed->s->log_file_align)) + || !bfd_set_section_alignment (s, bed->s->log_file_align)) return FALSE; htab->irelplt = s; @@ -1279,39 +1285,7 @@ _bfd_sparc_elf_copy_indirect_symbol (struct bfd_link_info *info, edir = (struct _bfd_sparc_elf_link_hash_entry *) dir; eind = (struct _bfd_sparc_elf_link_hash_entry *) ind; - if (eind->dyn_relocs != NULL) - { - if (edir->dyn_relocs != NULL) - { - struct elf_dyn_relocs **pp; - struct elf_dyn_relocs *p; - - /* 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; ) - { - struct elf_dyn_relocs *q; - - for (q = edir->dyn_relocs; q != NULL; q = q->next) - if (q->sec == p->sec) - { - q->pc_count += p->pc_count; - q->count += p->count; - *pp = p->next; - break; - } - if (q == NULL) - pp = &p->next; - } - *pp = edir->dyn_relocs; - } - - edir->dyn_relocs = eind->dyn_relocs; - 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 +1305,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 +1313,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 +1383,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 +1391,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 +1420,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 +1491,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 +1499,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 +1529,34 @@ _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; - } - old_tls_type = _bfd_sparc_elf_local_got_tls_type (abfd) [r_symndx]; + 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,45 +1564,42 @@ _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; + { + eh->has_got_reloc = 1; + if (r_type == R_SPARC_GOT10 + || r_type == R_SPARC_GOT13 + || r_type == R_SPARC_GOT22) + eh->has_old_style_got_reloc = 1; + } break; 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 +1612,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 +1628,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; @@ -1812,7 +1755,7 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, /* If this is a global symbol, we count the number of relocations we need for this symbol. */ if (h != NULL) - head = &((struct _bfd_sparc_elf_link_hash_entry *) h)->dyn_relocs; + head = &h->dyn_relocs; else { /* Track dynamic relocs needed for local syms too. @@ -1833,7 +1776,7 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, p = *head; if (p == NULL || p->sec != sec) { - bfd_size_type amt = sizeof *p; + size_t amt = sizeof *p; p = ((struct elf_dyn_relocs *) bfd_alloc (htab->elf.dynobj, amt)); if (p == NULL) @@ -1858,9 +1801,7 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, break; case R_SPARC_GNU_VTENTRY: - BFD_ASSERT (h != NULL); - if (h != NULL - && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) + if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) return FALSE; break; @@ -1891,9 +1832,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)) { @@ -1949,23 +1888,6 @@ _bfd_sparc_elf_fixup_symbol (struct bfd_link_info *info, return TRUE; } -/* 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 = _bfd_sparc_elf_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 @@ -2009,8 +1931,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 @@ -2062,7 +1984,7 @@ _bfd_sparc_elf_adjust_dynamic_symbol (struct bfd_link_info *info, /* If we don't find any dynamic relocs in read-only sections, then we'll be keeping the dynamic relocs and avoiding the copy reloc. */ - if (!readonly_dynrelocs (h)) + if (!_bfd_elf_readonly_dynrelocs (h)) { h->non_got_ref = 0; return TRUE; @@ -2129,12 +2051,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 +2163,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,27 +2181,31 @@ 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 h->got.offset = (bfd_vma) -1; - if (eh->dyn_relocs == NULL) + if (h->dyn_relocs == NULL) return TRUE; /* In the shared -Bsymbolic case, discard space allocated for @@ -2296,7 +2220,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) { struct elf_dyn_relocs **pp; - for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) + for (pp = &h->dyn_relocs; (p = *pp) != NULL; ) { p->count -= p->pc_count; p->pc_count = 0; @@ -2311,7 +2235,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) { struct elf_dyn_relocs **pp; - for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) + for (pp = &h->dyn_relocs; (p = *pp) != NULL; ) { if (strcmp (p->sec->output_section->name, ".tls_vars") == 0) *pp = p->next; @@ -2322,7 +2246,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) /* Also discard relocs on undefined weak syms with non-default visibility or in PIE. */ - if (eh->dyn_relocs != NULL + if (h->dyn_relocs != NULL && h->root.type == bfd_link_hash_undefweak) { /* An undefined weak symbol is never @@ -2337,7 +2261,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) can branch to 0 without PLT. */ struct elf_dyn_relocs **pp; - for (pp = &eh->dyn_relocs; (p = *pp) != NULL;) + for (pp = &h->dyn_relocs; (p = *pp) != NULL;) if (p->pc_count == 0) *pp = p->next; else @@ -2347,7 +2271,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) pp = &p->next; } - if (eh->dyn_relocs != NULL) + if (h->dyn_relocs != NULL) { /* Make sure undefined weak symbols are output as dynamic symbols in PIEs for dynamic non-GOT @@ -2357,7 +2281,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) } } else - eh->dyn_relocs = NULL; + h->dyn_relocs = NULL; } /* Make sure undefined weak symbols are output as a dynamic @@ -2385,12 +2309,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; @@ -2402,13 +2325,13 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) goto keep; } - eh->dyn_relocs = NULL; + h->dyn_relocs = NULL; keep: ; } /* Finally, allocate space. */ - for (p = eh->dyn_relocs; p != NULL; p = p->next) + for (p = h->dyn_relocs; p != NULL; p = p->next) { asection *sreloc = elf_section_data (p->sec)->sreloc; sreloc->size += p->count * SPARC_ELF_RELA_BYTES (htab); @@ -2436,33 +2359,6 @@ allocate_local_dynrelocs (void **slot, void *inf) return allocate_dynrelocs (h, inf); } -/* Set DF_TEXTREL if we find any dynamic relocs that apply to - read-only sections. */ - -static bfd_boolean -maybe_set_textrel (struct elf_link_hash_entry *h, void *info_p) -{ - asection *sec; - - if (h->root.type == bfd_link_hash_indirect) - return TRUE; - - sec = readonly_dynrelocs (h); - if (sec != NULL) - { - struct bfd_link_info *info = (struct bfd_link_info *) info_p; - - 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; - } - return TRUE; -} - /* Return true if the dynamic symbol for a given section should be omitted when creating a shared library. */ @@ -2477,7 +2373,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 +2449,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); } } @@ -2717,7 +2613,8 @@ _bfd_sparc_elf_size_dynamic_sections (bfd *output_bfd, /* 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, maybe_set_textrel, info); + elf_link_hash_traverse (&htab->elf, + _bfd_elf_maybe_set_textrel, info); if (info->flags & DF_TEXTREL) { @@ -2795,7 +2692,7 @@ _bfd_sparc_elf_new_section_hook (bfd *abfd, asection *sec) if (!sec->used_by_bfd) { struct _bfd_sparc_elf_section_data *sdata; - bfd_size_type amt = sizeof (*sdata); + size_t amt = sizeof (*sdata); sdata = bfd_zalloc (abfd, amt); if (sdata == NULL) @@ -2968,8 +2865,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 +2928,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 +3029,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 +3038,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 +3063,28 @@ _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, + if it isn't also subject to another, old-style GOT relocation. + See also the handling of these GOT relocations just below. */ + if (h != NULL + && h->dynindx == -1 + && !h->forced_local + && h->root.type != bfd_link_hash_undefweak + && !eh->has_old_style_got_reloc + && (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,19 +3137,17 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, off &= ~1; else { - SPARC_ELF_PUT_WORD (htab, output_bfd, relocation, - htab->elf.sgot->contents + off); - h->got.offset |= 1; - + /* 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); + h->got.offset |= 1; } } else @@ -3244,25 +3167,22 @@ _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; - } - - SPARC_ELF_PUT_WORD (htab, output_bfd, relocation, - htab->elf.sgot->contents + off); + relative_reloc = TRUE; + else + SPARC_ELF_PUT_WORD (htab, output_bfd, relocation, + htab->elf.sgot->contents + off); local_got_offsets[r_symndx] |= 1; } } 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 @@ -3271,8 +3191,14 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, outrel.r_info = SPARC_ELF_R_INFO (htab, NULL, 0, R_SPARC_RELATIVE); outrel.r_addend = relocation; - relocation = 0; sparc_elf_append_rela (output_bfd, s, &outrel); + /* Versions of glibc ld.so at least up to 2.26 wrongly + add the section contents to the value calculated for + a RELATIVE reloc. Zero the contents to work around + this bug. */ + relocation = 0; + SPARC_ELF_PUT_WORD (htab, output_bfd, relocation, + htab->elf.sgot->contents + off); } relocation = htab->elf.sgot->output_offset + off - got_base; @@ -3379,8 +3305,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 @@ -3388,9 +3313,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) @@ -3477,7 +3402,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; } @@ -3530,7 +3454,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; @@ -3552,40 +3476,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) { @@ -3696,7 +3599,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; @@ -3707,14 +3611,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: @@ -3722,28 +3631,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; } @@ -3751,6 +3654,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 */ @@ -3760,20 +3664,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; } @@ -3836,12 +3742,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: @@ -3849,21 +3757,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); @@ -3874,6 +3784,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); @@ -3911,10 +3822,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); @@ -4149,7 +4061,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, if (r == bfd_reloc_continue) { -do_relocation: + do_relocation: r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents, rel->r_offset, relocation, rel->r_addend); @@ -4173,8 +4085,7 @@ do_relocation: || r_type == R_SPARC_UA32 || r_type == R_SPARC_DISP32) && (((input_section->flags & SEC_DEBUGGING) != 0 - && strcmp (bfd_section_name (input_bfd, - input_section), + && strcmp (bfd_section_name (input_section), ".stab") == 0) || _bfd_elf_section_offset (output_bfd, info, input_section, @@ -4203,7 +4114,7 @@ do_relocation: if (name == NULL) return FALSE; if (*name == '\0') - name = bfd_section_name (input_bfd, sec); + name = bfd_section_name (sec); } (*info->callbacks->reloc_overflow) (info, (h ? &h->root : NULL), name, howto->name, @@ -4322,7 +4233,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); @@ -4333,7 +4244,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) { @@ -4458,8 +4369,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. */ @@ -4473,12 +4383,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; @@ -4514,8 +4426,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) @@ -4799,6 +4711,24 @@ _bfd_sparc_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *i BFD_ASSERT (htab != NULL); dynobj = htab->elf.dynobj; + /* We arranged in size_dynamic_sections to put the STT_REGISTER + entries at the end of the dynlocal list, so they came at the end + of the local symbols in the symtab. Except that they aren't + STB_LOCAL, so we need to back up symtab->sh_info. */ + if (ABI_64_P (output_bfd) + && elf_hash_table (info)->dynlocal) + { + asection *dynsymsec = bfd_get_linker_section (dynobj, ".dynsym"); + struct elf_link_local_dynamic_entry *e; + + for (e = elf_hash_table (info)->dynlocal; e ; e = e->next) + if (e->input_indx == -1) + break; + if (e) + elf_section_data (dynsymsec->output_section)->this_hdr.sh_info + = e->dynindx; + } + sdyn = bfd_get_linker_section (dynobj, ".dynamic"); if (elf_hash_table (info)->dynamic_sections_created)