X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felfxx-sparc.c;h=30daedf73050e8bc8324c0cf8da780ff818d5e06;hb=f4e0d9f40b21fb42bbf7da07917683fb1cc16e8e;hp=9a0a1a4e68ad66ea7bc3712c07b20d00c1cbab68;hpb=dbaa2011452c7ce7ca612c6298964452dce179eb;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elfxx-sparc.c b/bfd/elfxx-sparc.c index 9a0a1a4e68..30daedf730 100644 --- a/bfd/elfxx-sparc.c +++ b/bfd/elfxx-sparc.c @@ -1,6 +1,5 @@ /* SPARC-specific support for ELF - Copyright 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 - Free Software Foundation, Inc. + Copyright (C) 2005-2016 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -53,7 +52,7 @@ static bfd_reloc_status_type init_insn_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, - PTR data, asection *input_section, bfd *output_bfd, + void * data, asection *input_section, bfd *output_bfd, bfd_vma *prelocation, bfd_vma *pinsn) { bfd_vma relocation; @@ -97,7 +96,7 @@ static bfd_reloc_status_type sparc_elf_notsup_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry ATTRIBUTE_UNUSED, asymbol *symbol ATTRIBUTE_UNUSED, - PTR data ATTRIBUTE_UNUSED, + void * data ATTRIBUTE_UNUSED, asection *input_section ATTRIBUTE_UNUSED, bfd *output_bfd ATTRIBUTE_UNUSED, char **error_message ATTRIBUTE_UNUSED) @@ -109,7 +108,7 @@ sparc_elf_notsup_reloc (bfd *abfd ATTRIBUTE_UNUSED, static bfd_reloc_status_type sparc_elf_wdisp16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, - PTR data, asection *input_section, bfd *output_bfd, + void * data, asection *input_section, bfd *output_bfd, char **error_message ATTRIBUTE_UNUSED) { bfd_vma relocation; @@ -136,7 +135,7 @@ sparc_elf_wdisp16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, static bfd_reloc_status_type sparc_elf_wdisp10_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, - PTR data, asection *input_section, bfd *output_bfd, + void * data, asection *input_section, bfd *output_bfd, char **error_message ATTRIBUTE_UNUSED) { bfd_vma relocation; @@ -164,7 +163,7 @@ sparc_elf_wdisp10_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, static bfd_reloc_status_type sparc_elf_hix22_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, - PTR data, asection *input_section, bfd *output_bfd, + void * data, asection *input_section, bfd *output_bfd, char **error_message ATTRIBUTE_UNUSED) { bfd_vma relocation; @@ -190,7 +189,7 @@ sparc_elf_hix22_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, static bfd_reloc_status_type sparc_elf_lox10_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, - PTR data, asection *input_section, bfd *output_bfd, + void * data, asection *input_section, bfd *output_bfd, char **error_message ATTRIBUTE_UNUSED) { bfd_vma relocation; @@ -210,7 +209,7 @@ sparc_elf_lox10_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, static reloc_howto_type _bfd_sparc_elf_howto_table[] = { - HOWTO(R_SPARC_NONE, 0,0, 0,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", FALSE,0,0x00000000,TRUE), + HOWTO(R_SPARC_NONE, 0,3, 0,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", FALSE,0,0x00000000,TRUE), HOWTO(R_SPARC_8, 0,0, 8,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_8", FALSE,0,0x000000ff,TRUE), HOWTO(R_SPARC_16, 0,1,16,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_16", FALSE,0,0x0000ffff,TRUE), HOWTO(R_SPARC_32, 0,2,32,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_32", FALSE,0,0xffffffff,TRUE), @@ -1103,6 +1102,21 @@ elf_sparc_get_local_sym_hash (struct _bfd_sparc_elf_link_hash_table *htab, return &ret->elf; } +/* Destroy a SPARC ELF linker hash table. */ + +static void +_bfd_sparc_elf_link_hash_table_free (bfd *obfd) +{ + struct _bfd_sparc_elf_link_hash_table *htab + = (struct _bfd_sparc_elf_link_hash_table *) obfd->link.hash; + + if (htab->loc_hash_table) + htab_delete (htab->loc_hash_table); + if (htab->loc_hash_memory) + objalloc_free ((struct objalloc *) htab->loc_hash_memory); + _bfd_elf_link_hash_table_free (obfd); +} + /* Create a SPARC ELF linker hash table. */ struct bfd_link_hash_table * @@ -1169,28 +1183,14 @@ _bfd_sparc_elf_link_hash_table_create (bfd *abfd) ret->loc_hash_memory = objalloc_create (); if (!ret->loc_hash_table || !ret->loc_hash_memory) { - free (ret); + _bfd_sparc_elf_link_hash_table_free (abfd); return NULL; } + ret->elf.root.hash_table_free = _bfd_sparc_elf_link_hash_table_free; return &ret->elf.root; } -/* Destroy a SPARC ELF linker hash table. */ - -void -_bfd_sparc_elf_link_hash_table_free (struct bfd_link_hash_table *hash) -{ - struct _bfd_sparc_elf_link_hash_table *htab - = (struct _bfd_sparc_elf_link_hash_table *) hash; - - if (htab->loc_hash_table) - htab_delete (htab->loc_hash_table); - if (htab->loc_hash_memory) - objalloc_free ((struct objalloc *) htab->loc_hash_memory); - _bfd_generic_link_hash_table_free (hash); -} - /* Create .plt, .rela.plt, .got, .rela.got, .dynbss, and .rela.bss sections in DYNOBJ, and set up shortcuts to them in our hash table. */ @@ -1207,15 +1207,15 @@ _bfd_sparc_elf_create_dynamic_sections (bfd *dynobj, if (!_bfd_elf_create_dynamic_sections (dynobj, info)) return FALSE; - htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss"); - if (!info->shared) - htab->srelbss = bfd_get_section_by_name (dynobj, ".rela.bss"); + htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss"); + if (!bfd_link_pic (info)) + htab->srelbss = bfd_get_linker_section (dynobj, ".rela.bss"); if (htab->is_vxworks) { if (!elf_vxworks_create_dynamic_sections (dynobj, info, &htab->srelplt2)) return FALSE; - if (info->shared) + if (bfd_link_pic (info)) { htab->plt_header_size = 4 * ARRAY_SIZE (sparc_vxworks_shared_plt0_entry); @@ -1232,7 +1232,7 @@ _bfd_sparc_elf_create_dynamic_sections (bfd *dynobj, } if (!htab->elf.splt || !htab->elf.srelplt || !htab->sdynbss - || (!info->shared && !htab->srelbss)) + || (!bfd_link_pic (info) && !htab->srelbss)) abort (); return TRUE; @@ -1330,7 +1330,7 @@ sparc_elf_tls_transition (struct bfd_link_info *info, bfd *abfd, && ! _bfd_sparc_elf_tdata (abfd)->has_tlsgd) r_type = R_SPARC_REV32; - if (info->shared) + if (bfd_link_pic (info)) return r_type; switch (r_type) @@ -1377,7 +1377,7 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, int num_relocs; bfd_boolean checked_tlsgd = FALSE; - if (info->relocatable) + if (bfd_link_relocatable (info)) return TRUE; htab = _bfd_sparc_elf_hash_table (info); @@ -1433,7 +1433,7 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, TRUE); if (h == NULL) return FALSE; - + /* Fake a STT_GNU_IFUNC symbol. */ h->type = STT_GNU_IFUNC; h->def_regular = 1; @@ -1450,6 +1450,10 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *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; + + /* PR15323, ref flags aren't set for references in the same + object. */ + h->root.non_ir_ref = 1; } if (h && h->type == STT_GNU_IFUNC) @@ -1497,13 +1501,13 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_SPARC_TLS_LE_HIX22: case R_SPARC_TLS_LE_LOX10: - if (info->shared) + if (bfd_link_pic (info)) goto r_sparc_plt32; break; case R_SPARC_TLS_IE_HI22: case R_SPARC_TLS_IE_LO10: - if (info->shared) + if (bfd_link_pic (info)) info->flags |= DF_STATIC_TLS; /* Fall through */ @@ -1613,7 +1617,7 @@ _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 (info->shared) + if (bfd_link_pic (info)) { /* These are basically R_SPARC_TLS_WPLT30 relocs against __tls_get_addr. */ @@ -1731,7 +1735,7 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, h->non_got_ref = 1; r_sparc_plt32: - if (h != NULL && !info->shared) + if (h != NULL && !bfd_link_pic (info)) { /* We may need a .plt entry if the function this reloc refers to is in a shared lib. */ @@ -1759,19 +1763,19 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, may need to keep relocations for symbols satisfied by a dynamic library if we manage to avoid copy relocs for the symbol. */ - if ((info->shared + if ((bfd_link_pic (info) && (sec->flags & SEC_ALLOC) != 0 && (! _bfd_sparc_elf_howto_table[r_type].pc_relative || (h != NULL && (! SYMBOLIC_BIND (info, h) || h->root.type == bfd_link_hash_defweak || !h->def_regular)))) - || (!info->shared + || (!bfd_link_pic (info) && (sec->flags & SEC_ALLOC) != 0 && h != NULL && (h->root.type == bfd_link_hash_defweak || !h->def_regular)) - || (!info->shared + || (!bfd_link_pic (info) && h != NULL && h->type == STT_GNU_IFUNC)) { @@ -1873,6 +1877,29 @@ _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)) + { + switch (SPARC_ELF_R_TYPE (rel->r_info)) + { + case R_SPARC_TLS_GD_CALL: + case R_SPARC_TLS_LDM_CALL: + /* This reloc implicitly references __tls_get_addr. We know + another reloc will reference the same symbol as the one + on this reloc, so the real symbol and section will be + gc marked when processing the other reloc. That lets + us handle __tls_get_addr here. */ + h = elf_link_hash_lookup (elf_hash_table (info), "__tls_get_addr", + FALSE, FALSE, TRUE); + BFD_ASSERT (h != NULL); + h->mark = 1; + if (h->u.weakdef != NULL) + h->u.weakdef->mark = 1; + sym = NULL; + } + } + return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); } @@ -1901,7 +1928,7 @@ _bfd_sparc_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info, bfd_signed_vma *local_got_refcounts; const Elf_Internal_Rela *rel, *relend; - if (info->relocatable) + if (bfd_link_relocatable (info)) return TRUE; BFD_ASSERT (is_sparc_elf (abfd) || sec->reloc_count == 0); @@ -1943,7 +1970,7 @@ _bfd_sparc_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info, } r_type = SPARC_ELF_R_TYPE (rel->r_info); - r_type = sparc_elf_tls_transition (info, abfd, r_type, h != NULL); + r_type = sparc_elf_tls_transition (info, abfd, r_type, h == NULL); switch (r_type) { case R_SPARC_TLS_LDM_HI22: @@ -2030,7 +2057,7 @@ _bfd_sparc_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info, case R_SPARC_L44: case R_SPARC_H34: case R_SPARC_UA64: - if (info->shared) + if (bfd_link_pic (info)) break; /* Fall through. */ @@ -2131,7 +2158,7 @@ _bfd_sparc_elf_adjust_dynamic_symbol (struct bfd_link_info *info, only references to the symbol are via the global offset table. For such cases we need not do anything here; the relocations will be handled correctly by relocate_section. */ - if (info->shared) + if (bfd_link_pic (info)) return TRUE; /* If there are no references to this symbol that do not use the @@ -2184,14 +2211,14 @@ _bfd_sparc_elf_adjust_dynamic_symbol (struct bfd_link_info *info, s = htab->sdynbss; - return _bfd_elf_adjust_dynamic_copy (h, s); + return _bfd_elf_adjust_dynamic_copy (info, h, s); } /* Allocate space in .plt, .got and associated reloc sections for dynamic relocs. */ static bfd_boolean -allocate_dynrelocs (struct elf_link_hash_entry *h, PTR inf) +allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) { struct bfd_link_info *info; struct _bfd_sparc_elf_link_hash_table *htab; @@ -2220,7 +2247,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, PTR inf) return FALSE; } - if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info->shared, h) + if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h) || (h->type == STT_GNU_IFUNC && h->def_regular)) { @@ -2235,7 +2262,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, PTR inf) s->size = htab->plt_header_size; /* Allocate space for the .rela.plt.unloaded relocations. */ - if (htab->is_vxworks && !info->shared) + if (htab->is_vxworks && !bfd_link_pic (info)) htab->srelplt2->size = sizeof (Elf32_External_Rela) * 2; } @@ -2266,7 +2293,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, PTR inf) location in the .plt. This is required to make function pointers compare as equal between the normal executable and the shared library. */ - if (! info->shared + if (! bfd_link_pic (info) && !h->def_regular) { h->root.u.def.section = s; @@ -2288,7 +2315,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, PTR inf) htab->elf.sgotplt->size += 4; /* ...and for the .rela.plt.unloaded relocations. */ - if (!info->shared) + if (!bfd_link_pic (info)) htab->srelplt2->size += sizeof (Elf32_External_Rela) * 3; } } @@ -2307,7 +2334,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, PTR inf) /* If R_SPARC_TLS_IE_{HI22,LO10} symbol is now local to the binary, make it a R_SPARC_TLS_LE_{HI22,LO10} requiring no TLS entry. */ if (h->got.refcount > 0 - && !info->shared + && !bfd_link_pic (info) && h->dynindx == -1 && _bfd_sparc_elf_hash_entry(h)->tls_type == GOT_TLS_IE) h->got.offset = (bfd_vma) -1; @@ -2342,7 +2369,9 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, PTR inf) 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 (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)) + else if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, + bfd_link_pic (info), + h)) htab->elf.srelgot->size += SPARC_ELF_RELA_BYTES (htab); } else @@ -2358,7 +2387,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, PTR inf) space for pc-relative relocs that have become local due to symbol visibility changes. */ - if (info->shared) + if (bfd_link_pic (info)) { if (SYMBOL_CALLS_LOCAL (info, h)) { @@ -2471,7 +2500,7 @@ allocate_local_dynrelocs (void **slot, void *inf) /* Find any dynamic relocs that apply to read-only sections. */ static bfd_boolean -readonly_dynrelocs (struct elf_link_hash_entry *h, PTR inf) +readonly_dynrelocs (struct elf_link_hash_entry *h, void * inf) { struct _bfd_sparc_elf_link_hash_entry *eh; struct _bfd_sparc_elf_dyn_relocs *p; @@ -2530,9 +2559,9 @@ _bfd_sparc_elf_size_dynamic_sections (bfd *output_bfd, if (elf_hash_table (info)->dynamic_sections_created) { /* Set the contents of the .interp section to the interpreter. */ - if (info->executable) + if (bfd_link_executable (info) && !info->nointerp) { - s = bfd_get_section_by_name (dynobj, ".interp"); + s = bfd_get_linker_section (dynobj, ".interp"); BFD_ASSERT (s != NULL); s->size = htab->dynamic_interpreter_size; s->contents = (unsigned char *) htab->dynamic_interpreter; @@ -2541,7 +2570,7 @@ _bfd_sparc_elf_size_dynamic_sections (bfd *output_bfd, /* Set up .got offsets for local syms, and space for local dynamic relocs. */ - for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) { bfd_signed_vma *local_got; bfd_signed_vma *end_local_got; @@ -2604,7 +2633,7 @@ _bfd_sparc_elf_size_dynamic_sections (bfd *output_bfd, s->size += SPARC_ELF_WORD_BYTES (htab); if (*local_tls_type == GOT_TLS_GD) s->size += SPARC_ELF_WORD_BYTES (htab); - if (info->shared + if (bfd_link_pic (info) || *local_tls_type == GOT_TLS_GD || *local_tls_type == GOT_TLS_IE) srel->size += SPARC_ELF_RELA_BYTES (htab); @@ -2627,24 +2656,24 @@ _bfd_sparc_elf_size_dynamic_sections (bfd *output_bfd, /* Allocate global sym .plt and .got entries, and space for global sym dynamic relocs. */ - elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info); + elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, info); /* Allocate .plt and .got entries, and space for local symbols. */ htab_traverse (htab->loc_hash_table, allocate_local_dynrelocs, info); - if (! ABI_64_P (output_bfd) - && !htab->is_vxworks + if (!htab->is_vxworks && elf_hash_table (info)->dynamic_sections_created) { - /* Make space for the trailing nop in .plt. */ - if (htab->elf.splt->size > 0) - htab->elf.splt->size += 1 * SPARC_INSN_BYTES; + if (! ABI_64_P (output_bfd)) + { + /* Make space for the trailing nop in .plt. */ + if (htab->elf.splt->size > 0) + htab->elf.splt->size += 1 * SPARC_INSN_BYTES; + } /* If the .got section is more than 0x1000 bytes, we add 0x1000 to the value of _GLOBAL_OFFSET_TABLE_, so that 13 - bit relocations have a greater chance of working. - - FIXME: Make this optimization work for 64-bit too. */ + bit relocations have a greater chance of working. */ if (htab->elf.sgot->size >= 0x1000 && elf_hash_table (info)->hgot->root.u.def.value == 0) elf_hash_table (info)->hgot->root.u.def.value = 0x1000; @@ -2718,7 +2747,7 @@ _bfd_sparc_elf_size_dynamic_sections (bfd *output_bfd, #define add_dynamic_entry(TAG, VAL) \ _bfd_elf_add_dynamic_entry (info, TAG, VAL) - if (info->executable) + if (bfd_link_executable (info)) { if (!add_dynamic_entry (DT_DEBUG, 0)) return FALSE; @@ -2742,8 +2771,7 @@ _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, readonly_dynrelocs, - (PTR) info); + elf_link_hash_traverse (&htab->elf, readonly_dynrelocs, info); if (info->flags & DF_TEXTREL) { @@ -2838,7 +2866,7 @@ _bfd_sparc_elf_relax_section (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *link_info ATTRIBUTE_UNUSED, bfd_boolean *again) { - if (link_info->relocatable) + if (bfd_link_relocatable (link_info)) (*link_info->callbacks->einfo) (_("%P%F: --relax and -r may not be used together\n")); @@ -2931,7 +2959,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, sreloc = elf_section_data (input_section)->sreloc; /* We have to handle relocations in vxworks .tls_vars sections specially, because the dynamic loader is 'weird'. */ - is_vxworks_tls = (htab->is_vxworks && info->shared + is_vxworks_tls = (htab->is_vxworks && bfd_link_pic (info) && !strcmp (input_section->output_section->name, ".tls_vars")); @@ -2977,7 +3005,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, sec = local_sections[r_symndx]; relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); - if (!info->relocatable + if (!bfd_link_relocatable (info) && ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC) { /* Relocate against local STT_GNU_IFUNC symbol. */ @@ -2986,19 +3014,19 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, if (h == NULL) abort (); - /* Set STT_GNU_IFUNC symbol value. */ + /* Set STT_GNU_IFUNC symbol value. */ h->root.u.def.value = sym->st_value; h->root.u.def.section = sec; } } else { - bfd_boolean warned; + bfd_boolean warned, ignored; RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, r_symndx, symtab_hdr, sym_hashes, h, sec, relocation, - unresolved_reloc, warned); + unresolved_reloc, warned, ignored); if (warned) { /* To avoid generating warning messages about truncated @@ -3013,9 +3041,9 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, if (sec != NULL && discarded_section (sec)) RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, - rel, relend, howto, contents); + rel, 1, relend, howto, 0, contents); - if (info->relocatable) + if (bfd_link_relocatable (info)) continue; if (h != NULL @@ -3065,7 +3093,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, case R_SPARC_32: case R_SPARC_64: - if (info->shared && h->non_got_ref) + if (bfd_link_pic (info) && h->non_got_ref) { Elf_Internal_Rela outrel; bfd_vma offset; @@ -3083,7 +3111,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, if (h->dynindx == -1 || h->forced_local - || info->executable) + || bfd_link_executable (info)) { outrel.r_info = SPARC_ELF_R_INFO (htab, NULL, 0, R_SPARC_IRELATIVE); @@ -3108,7 +3136,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, case R_SPARC_HI22: case R_SPARC_LO10: /* We should only see such relocs in static links. */ - if (info->shared) + if (bfd_link_pic (info)) abort(); relocation = (plt_sec->output_section->vma + plt_sec->output_offset + h->plt.offset); @@ -3180,8 +3208,10 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, BFD_ASSERT (off != (bfd_vma) -1); dyn = elf_hash_table (info)->dynamic_sections_created; - if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) - || (info->shared + if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, + bfd_link_pic (info), + h) + || (bfd_link_pic (info) && SYMBOL_REFERENCES_LOCAL (info, h))) { /* This is actually a static link, or it is a @@ -3223,7 +3253,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, else { - if (info->shared) + if (bfd_link_pic (info)) { asection *s; Elf_Internal_Rela outrel; @@ -3279,7 +3309,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, if (h == NULL) break; } - /* PR 7027: We need similar behaviour for 64-bit binaries. */ + /* PR 7027: We need similar behaviour for 64-bit binaries. */ else if (r_type == R_SPARC_WPLT30 && h == NULL) break; else @@ -3356,13 +3386,13 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, || is_vxworks_tls) break; - if ((info->shared + if ((bfd_link_pic (info) && (h == NULL || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT || h->root.type != bfd_link_hash_undefweak) && (! howto->pc_relative || !SYMBOL_CALLS_LOCAL (info, h))) - || (!info->shared + || (!bfd_link_pic (info) && h != NULL && h->dynindx != -1 && !h->non_got_ref @@ -3438,10 +3468,10 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, memset (&outrel, 0, sizeof outrel); /* h->dynindx may be -1 if the symbol was marked to become local. */ - else if (h != NULL && - h->dynindx != -1 - && (! is_plt - || !info->shared + else if (h != NULL + && h->dynindx != -1 + && (_bfd_sparc_elf_howto_table[r_type].pc_relative + || !bfd_link_pic (info) || !SYMBOLIC_BIND (info, h) || !h->def_regular)) { @@ -3451,7 +3481,8 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, } else { - if (r_type == R_SPARC_32 || r_type == R_SPARC_64) + if ( (!ABI_64_P (output_bfd) && r_type == R_SPARC_32) + || (ABI_64_P (output_bfd) && r_type == R_SPARC_64)) { outrel.r_info = SPARC_ELF_R_INFO (htab, NULL, 0, R_SPARC_RELATIVE); @@ -3539,7 +3570,9 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, else if (h != NULL) { tls_type = _bfd_sparc_elf_hash_entry(h)->tls_type; - if (!info->shared && h->dynindx == -1 && tls_type == GOT_TLS_IE) + if (!bfd_link_pic (info) + && h->dynindx == -1 + && tls_type == GOT_TLS_IE) switch (SPARC_ELF_R_TYPE (rel->r_info)) { case R_SPARC_TLS_GD_HI22: @@ -3661,7 +3694,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, case R_SPARC_TLS_LDM_HI22: case R_SPARC_TLS_LDM_LO10: - if (! info->shared) + if (! bfd_link_pic (info)) { bfd_put_32 (output_bfd, SPARC_NOP, contents + rel->r_offset); continue; @@ -3672,7 +3705,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, case R_SPARC_TLS_LDO_HIX22: case R_SPARC_TLS_LDO_LOX10: - if (info->shared) + if (bfd_link_pic (info)) { relocation -= dtpoff_base (info); break; @@ -3684,7 +3717,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, case R_SPARC_TLS_LE_HIX22: case R_SPARC_TLS_LE_LOX10: - if (info->shared) + if (bfd_link_pic (info)) { Elf_Internal_Rela outrel; bfd_boolean skip; @@ -3716,7 +3749,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, break; case R_SPARC_TLS_LDM_CALL: - if (! info->shared) + if (! bfd_link_pic (info)) { /* mov %g0, %o0 */ bfd_put_32 (output_bfd, 0x90100000, contents + rel->r_offset); @@ -3730,13 +3763,13 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, 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 (! info->shared + if (! bfd_link_pic (info) || (r_type == R_SPARC_TLS_GD_CALL && tls_type == GOT_TLS_IE)) { Elf_Internal_Rela *rel2; bfd_vma insn; - if (!info->shared && (h == NULL || h->dynindx == -1)) + if (!bfd_link_pic (info) && (h == NULL || h->dynindx == -1)) { /* GD -> LE */ bfd_put_32 (output_bfd, SPARC_NOP, contents + rel->r_offset); @@ -3806,7 +3839,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, 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 (! info->shared || tls_type == GOT_TLS_IE) + if (! bfd_link_pic (info) || tls_type == GOT_TLS_IE) { /* add %reg1, %reg2, %reg3, %tgd_add(foo) changed into IE: @@ -3814,7 +3847,7 @@ _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) || info->shared) + if ((h != NULL && h->dynindx != -1) || bfd_link_pic (info)) relocation = insn | (ABI_64_P (output_bfd) ? 0xc0580000 : 0xc0000000); else relocation = (insn & ~0x7c000) | 0x1c000; @@ -3823,12 +3856,12 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, continue; case R_SPARC_TLS_LDM_ADD: - if (! info->shared) + if (! bfd_link_pic (info)) bfd_put_32 (output_bfd, SPARC_NOP, contents + rel->r_offset); continue; case R_SPARC_TLS_LDO_ADD: - if (! info->shared) + if (! bfd_link_pic (info)) { /* Change rs1 into %g7. */ bfd_vma insn = bfd_get_32 (input_bfd, contents + rel->r_offset); @@ -3839,7 +3872,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, case R_SPARC_TLS_IE_LD: case R_SPARC_TLS_IE_LDX: - if (! info->shared && (h == NULL || h->dynindx == -1)) + if (! bfd_link_pic (info) && (h == NULL || h->dynindx == -1)) { bfd_vma insn = bfd_get_32 (input_bfd, contents + rel->r_offset); int rs2 = insn & 0x1f; @@ -4127,7 +4160,7 @@ do_relocation: { const char *name; - /* The Solaris native linker silently disregards overflows. + /* The Solaris native linker silently disregards overflows. We don't, but this breaks stabs debugging info, whose relocations are only 32-bits wide. Ignore overflows in this case and also for discarded entries. */ @@ -4167,11 +4200,9 @@ do_relocation: if (*name == '\0') name = bfd_section_name (input_bfd, sec); } - if (! ((*info->callbacks->reloc_overflow) - (info, (h ? &h->root : NULL), name, howto->name, - (bfd_vma) 0, input_bfd, input_section, - rel->r_offset))) - return FALSE; + (*info->callbacks->reloc_overflow) + (info, (h ? &h->root : NULL), name, howto->name, + (bfd_vma) 0, input_bfd, input_section, rel->r_offset); } break; } @@ -4200,7 +4231,7 @@ sparc_vxworks_build_plt_entry (bfd *output_bfd, struct bfd_link_info *info, htab = _bfd_sparc_elf_hash_table (info); BFD_ASSERT (htab != NULL); - if (info->shared) + if (bfd_link_pic (info)) { plt_entry = sparc_vxworks_shared_plt_entry; got_base = 0; @@ -4244,7 +4275,7 @@ sparc_vxworks_build_plt_entry (bfd *output_bfd, struct bfd_link_info *info, htab->elf.sgotplt->contents + got_offset); /* Add relocations to .rela.plt.unloaded. */ - if (!info->shared) + if (!bfd_link_pic (info)) { loc = (htab->srelplt2->contents + (2 + 3 * plt_index) * sizeof (Elf32_External_Rela)); @@ -4350,7 +4381,7 @@ _bfd_sparc_elf_finish_dynamic_symbol (bfd *output_bfd, if (h == NULL || h->dynindx == -1 - || ((info->executable + || ((bfd_link_executable (info) || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT) && h->def_regular && h->type == STT_GNU_IFUNC)) @@ -4450,7 +4481,7 @@ _bfd_sparc_elf_finish_dynamic_symbol (bfd *output_bfd, the symbol was forced to be local because of a version file. The entry in the global offset table will already have been initialized in the relocate_section function. */ - if (! info->shared + if (! bfd_link_pic (info) && h->type == STT_GNU_IFUNC && h->def_regular) { @@ -4465,7 +4496,7 @@ _bfd_sparc_elf_finish_dynamic_symbol (bfd *output_bfd, + (h->got.offset & ~(bfd_vma) 1)); return TRUE; } - else if (info->shared + else if (bfd_link_pic (info) && SYMBOL_REFERENCES_LOCAL (info, h)) { asection *sec = h->root.u.def.section; @@ -4496,8 +4527,8 @@ _bfd_sparc_elf_finish_dynamic_symbol (bfd *output_bfd, /* This symbols needs a copy reloc. Set it up. */ BFD_ASSERT (h->dynindx != -1); - s = bfd_get_section_by_name (h->root.u.def.section->owner, - ".rela.bss"); + s = bfd_get_linker_section (h->root.u.def.section->owner, + ".rela.bss"); BFD_ASSERT (s != NULL); rela.r_offset = (h->root.u.def.value @@ -4512,7 +4543,7 @@ _bfd_sparc_elf_finish_dynamic_symbol (bfd *output_bfd, _GLOBAL_OFFSET_TABLE_ is not absolute: it is relative to the ".got" section. Likewise _PROCEDURE_LINKAGE_TABLE_ and ".plt". */ if (sym != NULL - && (strcmp (h->root.root.string, "_DYNAMIC") == 0 + && (h == htab->elf.hdynamic || (!htab->is_vxworks && (h == htab->elf.hgot || h == htab->elf.hplt)))) sym->st_shndx = SHN_ABS; @@ -4598,13 +4629,13 @@ sparc_finish_dyn (bfd *output_bfd, struct bfd_link_info *info, { asection *s; - s = bfd_get_section_by_name (output_bfd, name); + s = bfd_get_linker_section (dynobj, name); if (s == NULL) dyn.d_un.d_val = 0; else { if (! size) - dyn.d_un.d_ptr = s->vma; + dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; else dyn.d_un.d_val = s->size; } @@ -4719,7 +4750,7 @@ finish_local_dynamic_symbol (void **slot, void *inf) struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) *slot; struct bfd_link_info *info - = (struct bfd_link_info *) inf; + = (struct bfd_link_info *) inf; return _bfd_sparc_elf_finish_dynamic_symbol (info->output_bfd, info, h, NULL); @@ -4736,13 +4767,13 @@ _bfd_sparc_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *i BFD_ASSERT (htab != NULL); dynobj = htab->elf.dynobj; - sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); + sdyn = bfd_get_linker_section (dynobj, ".dynamic"); if (elf_hash_table (info)->dynamic_sections_created) { asection *splt; - splt = bfd_get_section_by_name (dynobj, ".plt"); + splt = htab->elf.splt; BFD_ASSERT (splt != NULL && sdyn != NULL); if (!sparc_finish_dyn (output_bfd, info, dynobj, sdyn, splt)) @@ -4753,7 +4784,7 @@ _bfd_sparc_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *i { if (htab->is_vxworks) { - if (info->shared) + if (bfd_link_pic (info)) sparc_vxworks_finish_shared_plt (output_bfd, info); else sparc_vxworks_finish_exec_plt (output_bfd, info); @@ -4767,9 +4798,10 @@ _bfd_sparc_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *i } } - elf_section_data (splt->output_section)->this_hdr.sh_entsize - = (htab->is_vxworks || !ABI_64_P (output_bfd)) - ? 0 : htab->plt_entry_size; + if (elf_section_data (splt->output_section) != NULL) + elf_section_data (splt->output_section)->this_hdr.sh_entsize + = ((htab->is_vxworks || !ABI_64_P (output_bfd)) + ? 0 : htab->plt_entry_size); } /* Set the first entry in the global offset table to the address of @@ -4799,11 +4831,49 @@ _bfd_sparc_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *i bfd_boolean _bfd_sparc_elf_object_p (bfd *abfd) { + obj_attribute *attrs = elf_known_obj_attributes (abfd)[OBJ_ATTR_GNU]; + obj_attribute *hwcaps = &attrs[Tag_GNU_Sparc_HWCAPS]; + obj_attribute *hwcaps2 = &attrs[Tag_GNU_Sparc_HWCAPS2]; + + unsigned int v9c_hwcaps_mask = ELF_SPARC_HWCAP_ASI_BLK_INIT; + unsigned int v9d_hwcaps_mask = (ELF_SPARC_HWCAP_FMAF + | ELF_SPARC_HWCAP_VIS3 + | ELF_SPARC_HWCAP_HPC); + unsigned int v9e_hwcaps_mask = (ELF_SPARC_HWCAP_AES + | ELF_SPARC_HWCAP_DES + | ELF_SPARC_HWCAP_KASUMI + | ELF_SPARC_HWCAP_CAMELLIA + | ELF_SPARC_HWCAP_MD5 + | ELF_SPARC_HWCAP_SHA1 + | ELF_SPARC_HWCAP_SHA256 + | ELF_SPARC_HWCAP_SHA512 + | ELF_SPARC_HWCAP_MPMUL + | ELF_SPARC_HWCAP_MONT + | ELF_SPARC_HWCAP_CRC32C + | ELF_SPARC_HWCAP_CBCOND + | ELF_SPARC_HWCAP_PAUSE); + unsigned int v9v_hwcaps_mask = (ELF_SPARC_HWCAP_FJFMAU + | ELF_SPARC_HWCAP_IMA); + unsigned int v9m_hwcaps2_mask = (ELF_SPARC_HWCAP2_SPARC5 + | ELF_SPARC_HWCAP2_MWAIT + | ELF_SPARC_HWCAP2_XMPMUL + | ELF_SPARC_HWCAP2_XMONT); + if (ABI_64_P (abfd)) { unsigned long mach = bfd_mach_sparc_v9; - if (elf_elfheader (abfd)->e_flags & EF_SPARC_SUN_US3) + if (hwcaps2->i & v9m_hwcaps2_mask) + mach = bfd_mach_sparc_v9m; + else if (hwcaps->i & v9v_hwcaps_mask) + mach = bfd_mach_sparc_v9v; + else if (hwcaps->i & v9e_hwcaps_mask) + mach = bfd_mach_sparc_v9e; + else if (hwcaps->i & v9d_hwcaps_mask) + mach = bfd_mach_sparc_v9d; + else if (hwcaps->i & v9c_hwcaps_mask) + mach = bfd_mach_sparc_v9c; + else if (elf_elfheader (abfd)->e_flags & EF_SPARC_SUN_US3) mach = bfd_mach_sparc_v9b; else if (elf_elfheader (abfd)->e_flags & EF_SPARC_SUN_US1) mach = bfd_mach_sparc_v9a; @@ -4813,7 +4883,22 @@ _bfd_sparc_elf_object_p (bfd *abfd) { if (elf_elfheader (abfd)->e_machine == EM_SPARC32PLUS) { - if (elf_elfheader (abfd)->e_flags & EF_SPARC_SUN_US3) + if (hwcaps2->i & v9m_hwcaps2_mask) + return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, + bfd_mach_sparc_v8plusm); + else if (hwcaps->i & v9v_hwcaps_mask) + return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, + bfd_mach_sparc_v8plusv); + else if (hwcaps->i & v9e_hwcaps_mask) + return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, + bfd_mach_sparc_v8pluse); + else if (hwcaps->i & v9d_hwcaps_mask) + return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, + bfd_mach_sparc_v8plusd); + else if (hwcaps->i & v9c_hwcaps_mask) + return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, + bfd_mach_sparc_v8plusc); + else if (elf_elfheader (abfd)->e_flags & EF_SPARC_SUN_US3) return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc_v8plusb); else if (elf_elfheader (abfd)->e_flags & EF_SPARC_SUN_US1) @@ -4883,6 +4968,14 @@ _bfd_sparc_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd) out_attr = &out_attrs[Tag_GNU_Sparc_HWCAPS]; out_attr->i |= in_attr->i; + out_attr->type = 1; + + in_attr = &in_attrs[Tag_GNU_Sparc_HWCAPS2]; + out_attr = &out_attrs[Tag_GNU_Sparc_HWCAPS2]; + + out_attr->i |= in_attr->i; + out_attr->type = 1; + /* Merge Tag_compatibility attributes and any common GNU ones. */ _bfd_elf_merge_object_attributes (ibfd, obfd);