X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felfxx-tilegx.c;h=19c55417ab24301bb02e7e5faa2ce66de4e7bae3;hb=63c1f59d665542359de4737e3e48033c588f44dc;hp=e22188b76926a4df3dd1e2025b4bc105efcd90f2;hpb=5ec61378372b535bfadce78ffa5832623b2ac99c;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elfxx-tilegx.c b/bfd/elfxx-tilegx.c index e22188b769..19c55417ab 100644 --- a/bfd/elfxx-tilegx.c +++ b/bfd/elfxx-tilegx.c @@ -1,5 +1,5 @@ /* TILE-Gx-specific support for ELF. - Copyright 2011, 2012 Free Software Foundation, Inc. + Copyright (C) 2011-2017 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -72,11 +72,11 @@ static reloc_howto_type tilegx_elf_howto_table [] = /* This reloc does nothing. */ HOWTO (R_TILEGX_NONE, /* type */ 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ + 3, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ + complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_TILEGX_NONE", /* name */ FALSE, /* partial_inplace */ @@ -855,10 +855,6 @@ struct tilegx_elf_link_hash_table void (*put_word) (bfd *, bfd_vma, void *); const char *dynamic_interpreter; - /* Short-cuts to get to dynamic linker sections. */ - asection *sdynbss; - asection *srelbss; - /* Whether LE transition has been disabled for some of the sections. */ bfd_boolean disable_le_transition; @@ -921,7 +917,7 @@ tilegx_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, { unsigned int i; - for (i = ARRAY_SIZE (tilegx_reloc_map); --i;) + for (i = ARRAY_SIZE (tilegx_reloc_map); i--;) { const reloc_map * entry; @@ -1220,7 +1216,7 @@ tilegx64_short_plt_entry[PLT_ENTRY_SIZE] = }; /* Reuse an existing info 10 bundle. */ -static const bfd_byte const *tilegx64_plt_tail_entry = +static const bfd_byte *const tilegx64_plt_tail_entry = &tilegx64_short_plt_entry[4 * TILEGX_BUNDLE_SIZE_IN_BYTES]; static const bfd_byte @@ -1265,7 +1261,7 @@ tilegx32_short_plt_entry[PLT_ENTRY_SIZE] = }; /* Reuse an existing info 10 bundle. */ -static const bfd_byte const *tilegx32_plt_tail_entry = +static const bfd_byte *const tilegx32_plt_tail_entry = &tilegx64_short_plt_entry[4 * TILEGX_BUNDLE_SIZE_IN_BYTES]; static int @@ -1439,8 +1435,7 @@ tilegx_elf_create_got_section (bfd *abfd, struct bfd_link_info *info) struct elf_link_hash_table *htab = elf_hash_table (info); /* This function may be called more than once. */ - s = bfd_get_linker_section (abfd, ".got"); - if (s != NULL) + if (htab->sgot != NULL) return TRUE; flags = bed->dynamic_sec_flags; @@ -1501,26 +1496,10 @@ bfd_boolean tilegx_elf_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info) { - struct tilegx_elf_link_hash_table *htab; - - htab = tilegx_elf_hash_table (info); - BFD_ASSERT (htab != NULL); - if (!tilegx_elf_create_got_section (dynobj, info)) return FALSE; - if (!_bfd_elf_create_dynamic_sections (dynobj, info)) - return FALSE; - - htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss"); - if (!info->shared) - htab->srelbss = bfd_get_linker_section (dynobj, ".rela.bss"); - - if (!htab->elf.splt || !htab->elf.srelplt || !htab->sdynbss - || (!info->shared && !htab->srelbss)) - abort (); - - return TRUE; + return _bfd_elf_create_dynamic_sections (dynobj, info); } /* Copy the extra info we tack onto an elf_link_hash_entry. */ @@ -1643,7 +1622,7 @@ static int tilegx_elf_tls_transition (struct bfd_link_info *info, int r_type, int is_local, bfd_boolean disable_le_transition) { - if (info->shared) + if (!bfd_link_executable (info)) return r_type; if (is_local && !disable_le_transition) @@ -1669,7 +1648,7 @@ tilegx_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, int num_relocs; bfd_boolean has_tls_gd_or_ie = FALSE, has_tls_add = FALSE; - if (info->relocatable) + if (bfd_link_relocatable (info)) return TRUE; htab = tilegx_elf_hash_table (info); @@ -1716,7 +1695,7 @@ tilegx_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, for (rel = relocs; rel < rel_end; rel++) { unsigned int r_type; - unsigned long r_symndx; + unsigned int r_symndx; struct elf_link_hash_entry *h; int tls_type; @@ -1725,8 +1704,9 @@ tilegx_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr)) { - (*_bfd_error_handler) (_("%B: bad symbol index: %d"), - abfd, r_symndx); + /* xgettext:c-format */ + _bfd_error_handler (_("%B: bad symbol index: %d"), + abfd, r_symndx); return FALSE; } @@ -1750,7 +1730,7 @@ tilegx_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_TILEGX_IMM16_X1_HW0_LAST_TLS_LE: case R_TILEGX_IMM16_X0_HW1_LAST_TLS_LE: case R_TILEGX_IMM16_X1_HW1_LAST_TLS_LE: - if (info->shared) + if (!bfd_link_executable (info)) goto r_tilegx_plt32; break; @@ -1760,7 +1740,7 @@ tilegx_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_TILEGX_IMM16_X1_HW0_LAST_TLS_GD: case R_TILEGX_IMM16_X0_HW1_LAST_TLS_GD: case R_TILEGX_IMM16_X1_HW1_LAST_TLS_GD: - BFD_ASSERT (info->shared); + BFD_ASSERT (bfd_link_pic (info)); tls_type = GOT_TLS_GD; goto have_got_reference; @@ -1771,7 +1751,7 @@ tilegx_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_TILEGX_IMM16_X0_HW1_LAST_TLS_IE: case R_TILEGX_IMM16_X1_HW1_LAST_TLS_IE: tls_type = GOT_TLS_IE; - if (info->shared) + if (!bfd_link_executable (info)) info->flags |= DF_STATIC_TLS; goto have_got_reference; @@ -1828,7 +1808,8 @@ tilegx_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, tls_type = old_tls_type; else { - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%B: `%s' accessed both as normal and thread local symbol"), abfd, h ? h->root.root.string : ""); return FALSE; @@ -1852,7 +1833,7 @@ tilegx_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, break; case R_TILEGX_TLS_GD_CALL: - if (info->shared) + if (!bfd_link_executable (info)) { /* These are basically R_TILEGX_JUMPOFF_X1_PLT relocs against __tls_get_addr. */ @@ -1971,7 +1952,7 @@ tilegx_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, h->non_got_ref = 1; r_tilegx_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. */ @@ -1999,14 +1980,14 @@ tilegx_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 && (! tilegx_elf_howto_table[r_type].pc_relative || (h != NULL && (! info->symbolic || 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 @@ -2107,203 +2088,61 @@ tilegx_elf_gc_mark_hook (asection *sec, if (h != NULL) { switch (TILEGX_ELF_R_TYPE (rel->r_info)) - { - case R_TILEGX_GNU_VTINHERIT: - case R_TILEGX_GNU_VTENTRY: - break; - } + { + case R_TILEGX_GNU_VTINHERIT: + case R_TILEGX_GNU_VTENTRY: + return NULL; + } } - return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); -} - -/* Update the got entry reference counts for the section being removed. */ -bfd_boolean -tilegx_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info, - asection *sec, const Elf_Internal_Rela *relocs) -{ - struct tilegx_elf_link_hash_table *htab; - Elf_Internal_Shdr *symtab_hdr; - struct elf_link_hash_entry **sym_hashes; - bfd_signed_vma *local_got_refcounts; - const Elf_Internal_Rela *rel, *relend; - - if (info->relocatable) - return TRUE; - - BFD_ASSERT (is_tilegx_elf (abfd) || sec->reloc_count == 0); - - elf_section_data (sec)->local_dynrel = NULL; - - htab = tilegx_elf_hash_table (info); - BFD_ASSERT (htab != NULL); - symtab_hdr = &elf_symtab_hdr (abfd); - sym_hashes = elf_sym_hashes (abfd); - local_got_refcounts = elf_local_got_refcounts (abfd); - - relend = relocs + sec->reloc_count; - for (rel = relocs; rel < relend; rel++) + /* 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)) { - unsigned long r_symndx; - unsigned int r_type; - struct elf_link_hash_entry *h = NULL; + struct bfd_link_hash_entry *bh; - r_symndx = TILEGX_ELF_R_SYMNDX (htab, rel->r_info); - if (r_symndx >= symtab_hdr->sh_info) + switch (TILEGX_ELF_R_TYPE (rel->r_info)) { - struct tilegx_elf_link_hash_entry *eh; - struct tilegx_elf_dyn_relocs **pp; - struct tilegx_elf_dyn_relocs *p; - - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - while (h->root.type == bfd_link_hash_indirect - || h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - eh = (struct tilegx_elf_link_hash_entry *) h; - for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) - if (p->sec == sec) - { - /* Everything must go for SEC. */ - *pp = p->next; - break; - } + case R_TILEGX_TLS_GD_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. */ + bh = NULL; + if (! _bfd_generic_link_add_one_symbol (info, sec->owner, + "__tls_get_addr", 0, + bfd_und_section_ptr, + 0, NULL, FALSE, + FALSE, &bh)) + return NULL; + h = (struct elf_link_hash_entry *) bh; + BFD_ASSERT (h != NULL); + h->mark = 1; + if (h->is_weakalias) + weakdef (h)->mark = 1; + sym = NULL; } + } - r_type = TILEGX_ELF_R_TYPE (rel->r_info); - r_type = tilegx_elf_tls_transition (info, r_type, h != NULL, - sec->sec_flg0); - switch (r_type) - { - case R_TILEGX_IMM16_X0_HW0_GOT: - case R_TILEGX_IMM16_X1_HW0_GOT: - case R_TILEGX_IMM16_X0_HW0_LAST_GOT: - case R_TILEGX_IMM16_X1_HW0_LAST_GOT: - case R_TILEGX_IMM16_X0_HW1_LAST_GOT: - case R_TILEGX_IMM16_X1_HW1_LAST_GOT: - case R_TILEGX_IMM16_X0_HW0_TLS_GD: - case R_TILEGX_IMM16_X1_HW0_TLS_GD: - case R_TILEGX_IMM16_X0_HW0_LAST_TLS_GD: - case R_TILEGX_IMM16_X1_HW0_LAST_TLS_GD: - case R_TILEGX_IMM16_X0_HW1_LAST_TLS_GD: - case R_TILEGX_IMM16_X1_HW1_LAST_TLS_GD: - case R_TILEGX_IMM16_X0_HW0_TLS_IE: - case R_TILEGX_IMM16_X1_HW0_TLS_IE: - case R_TILEGX_IMM16_X0_HW0_LAST_TLS_IE: - case R_TILEGX_IMM16_X1_HW0_LAST_TLS_IE: - case R_TILEGX_IMM16_X0_HW1_LAST_TLS_IE: - case R_TILEGX_IMM16_X1_HW1_LAST_TLS_IE: - if (h != NULL) - { - if (h->got.refcount > 0) - h->got.refcount--; - } - else - { - if (local_got_refcounts && - local_got_refcounts[r_symndx] > 0) - local_got_refcounts[r_symndx]--; - } - break; + return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); +} - case R_TILEGX_64_PCREL: - case R_TILEGX_32_PCREL: - case R_TILEGX_16_PCREL: - case R_TILEGX_8_PCREL: - case R_TILEGX_IMM16_X0_HW0_PCREL: - case R_TILEGX_IMM16_X1_HW0_PCREL: - case R_TILEGX_IMM16_X0_HW1_PCREL: - case R_TILEGX_IMM16_X1_HW1_PCREL: - case R_TILEGX_IMM16_X0_HW2_PCREL: - case R_TILEGX_IMM16_X1_HW2_PCREL: - case R_TILEGX_IMM16_X0_HW3_PCREL: - case R_TILEGX_IMM16_X1_HW3_PCREL: - case R_TILEGX_IMM16_X0_HW0_LAST_PCREL: - case R_TILEGX_IMM16_X1_HW0_LAST_PCREL: - case R_TILEGX_IMM16_X0_HW1_LAST_PCREL: - case R_TILEGX_IMM16_X1_HW1_LAST_PCREL: - case R_TILEGX_IMM16_X0_HW2_LAST_PCREL: - case R_TILEGX_IMM16_X1_HW2_LAST_PCREL: - if (h != NULL - && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) - break; - /* Fall through. */ +/* Find dynamic relocs for H that apply to read-only sections. */ - case R_TILEGX_64: - case R_TILEGX_32: - case R_TILEGX_16: - case R_TILEGX_8: - case R_TILEGX_HW0: - case R_TILEGX_HW1: - case R_TILEGX_HW2: - case R_TILEGX_HW3: - case R_TILEGX_HW0_LAST: - case R_TILEGX_HW1_LAST: - case R_TILEGX_HW2_LAST: - case R_TILEGX_COPY: - case R_TILEGX_GLOB_DAT: - case R_TILEGX_JMP_SLOT: - case R_TILEGX_RELATIVE: - case R_TILEGX_BROFF_X1: - case R_TILEGX_JUMPOFF_X1: - case R_TILEGX_IMM8_X0: - case R_TILEGX_IMM8_Y0: - case R_TILEGX_IMM8_X1: - case R_TILEGX_IMM8_Y1: - case R_TILEGX_DEST_IMM8_X1: - case R_TILEGX_MT_IMM14_X1: - case R_TILEGX_MF_IMM14_X1: - case R_TILEGX_MMSTART_X0: - case R_TILEGX_MMEND_X0: - case R_TILEGX_SHAMT_X0: - case R_TILEGX_SHAMT_X1: - case R_TILEGX_SHAMT_Y0: - case R_TILEGX_SHAMT_Y1: - case R_TILEGX_IMM16_X0_HW0: - case R_TILEGX_IMM16_X1_HW0: - case R_TILEGX_IMM16_X0_HW1: - case R_TILEGX_IMM16_X1_HW1: - case R_TILEGX_IMM16_X0_HW2: - case R_TILEGX_IMM16_X1_HW2: - case R_TILEGX_IMM16_X0_HW3: - case R_TILEGX_IMM16_X1_HW3: - case R_TILEGX_IMM16_X0_HW0_LAST: - case R_TILEGX_IMM16_X1_HW0_LAST: - case R_TILEGX_IMM16_X0_HW1_LAST: - case R_TILEGX_IMM16_X1_HW1_LAST: - case R_TILEGX_IMM16_X0_HW2_LAST: - case R_TILEGX_IMM16_X1_HW2_LAST: - if (info->shared) - break; - /* Fall through. */ +static asection * +readonly_dynrelocs (struct elf_link_hash_entry *h) +{ + struct tilegx_elf_dyn_relocs *p; - case R_TILEGX_JUMPOFF_X1_PLT: - case R_TILEGX_IMM16_X0_HW0_PLT_PCREL: - case R_TILEGX_IMM16_X1_HW0_PLT_PCREL: - case R_TILEGX_IMM16_X0_HW1_PLT_PCREL: - case R_TILEGX_IMM16_X1_HW1_PLT_PCREL: - case R_TILEGX_IMM16_X0_HW2_PLT_PCREL: - case R_TILEGX_IMM16_X1_HW2_PLT_PCREL: - case R_TILEGX_IMM16_X0_HW3_PLT_PCREL: - case R_TILEGX_IMM16_X1_HW3_PLT_PCREL: - case R_TILEGX_IMM16_X0_HW0_LAST_PLT_PCREL: - case R_TILEGX_IMM16_X1_HW0_LAST_PLT_PCREL: - case R_TILEGX_IMM16_X0_HW1_LAST_PLT_PCREL: - case R_TILEGX_IMM16_X1_HW1_LAST_PLT_PCREL: - case R_TILEGX_IMM16_X0_HW2_LAST_PLT_PCREL: - case R_TILEGX_IMM16_X1_HW2_LAST_PLT_PCREL: - if (h != NULL) - { - if (h->plt.refcount > 0) - h->plt.refcount--; - } - break; + for (p = tilegx_elf_hash_entry (h)->dyn_relocs; p != NULL; p = p->next) + { + asection *s = p->sec->output_section; - default: - break; - } + if (s != NULL && (s->flags & SEC_READONLY) != 0) + return p->sec; } - - return TRUE; + return NULL; } /* Adjust a symbol defined by a dynamic object and referenced by a @@ -2320,7 +2159,7 @@ tilegx_elf_adjust_dynamic_symbol (struct bfd_link_info *info, struct tilegx_elf_link_hash_entry * eh; struct tilegx_elf_dyn_relocs *p; bfd *dynobj; - asection *s; + asection *s, *srel; htab = tilegx_elf_hash_table (info); BFD_ASSERT (htab != NULL); @@ -2330,7 +2169,7 @@ tilegx_elf_adjust_dynamic_symbol (struct bfd_link_info *info, /* Make sure we know what is going on here. */ BFD_ASSERT (dynobj != NULL && (h->needs_plt - || h->u.weakdef != NULL + || h->is_weakalias || (h->def_dynamic && h->ref_regular && !h->def_regular))); @@ -2363,12 +2202,12 @@ tilegx_elf_adjust_dynamic_symbol (struct bfd_link_info *info, /* If this is a weak symbol, and there is a real definition, the processor independent code will have arranged for us to see the real definition first, and we can just use the same value. */ - if (h->u.weakdef != NULL) + if (h->is_weakalias) { - BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined - || h->u.weakdef->root.type == bfd_link_hash_defweak); - h->root.u.def.section = h->u.weakdef->root.u.def.section; - h->root.u.def.value = h->u.weakdef->root.u.def.value; + struct elf_link_hash_entry *def = weakdef (h); + BFD_ASSERT (def->root.type == bfd_link_hash_defined); + h->root.u.def.section = def->root.u.def.section; + h->root.u.def.value = def->root.u.def.value; return TRUE; } @@ -2379,7 +2218,7 @@ tilegx_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 @@ -2424,13 +2263,23 @@ tilegx_elf_adjust_dynamic_symbol (struct bfd_link_info *info, to copy the initial value out of the dynamic object and into the runtime process image. We need to remember the offset into the .rel.bss section we are going to use. */ + if ((h->root.u.def.section->flags & SEC_READONLY) != 0) + { + s = htab->elf.sdynrelro; + srel = htab->elf.sreldynrelro; + } + else + { + s = htab->elf.sdynbss; + srel = htab->elf.srelbss; + } if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0) { - htab->srelbss->size += TILEGX_ELF_RELA_BYTES (htab); + srel->size += TILEGX_ELF_RELA_BYTES (htab); h->needs_copy = 1; } - return _bfd_elf_adjust_dynamic_copy (h, htab->sdynbss); + return _bfd_elf_adjust_dynamic_copy (info, h, s); } /* Allocate space in .plt, .got and associated reloc sections for @@ -2463,7 +2312,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *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)) { asection *s = htab->elf.splt; @@ -2480,7 +2329,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *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; @@ -2512,7 +2361,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) requiring no TLS entry. */ if (h->got.refcount > 0 && !htab->disable_le_transition - && !info->shared + && bfd_link_executable (info) && h->dynindx == -1 && tilegx_elf_hash_entry(h)->tls_type == GOT_TLS_IE) h->got.offset = (bfd_vma) -1; @@ -2542,7 +2391,9 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) TLS_GD needs two if local symbol and two if global. */ if (tls_type == GOT_TLS_GD || tls_type == GOT_TLS_IE) htab->elf.srelgot->size += 2 * TILEGX_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 += TILEGX_ELF_RELA_BYTES (htab); } else @@ -2558,7 +2409,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *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)) { @@ -2580,7 +2431,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) if (eh->dyn_relocs != NULL && h->root.type == bfd_link_hash_undefweak) { - if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT) + if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT + || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)) eh->dyn_relocs = NULL; /* Make sure undefined weak symbols are output as a dynamic @@ -2636,28 +2488,29 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) return TRUE; } -/* Find any dynamic relocs that apply to read-only sections. */ +/* Set DF_TEXTREL if we find any dynamic relocs that apply to + read-only sections. */ static bfd_boolean -readonly_dynrelocs (struct elf_link_hash_entry *h, void *inf) +maybe_set_textrel (struct elf_link_hash_entry *h, void *info_p) { - struct tilegx_elf_link_hash_entry *eh; - struct tilegx_elf_dyn_relocs *p; + asection *sec; - eh = (struct tilegx_elf_link_hash_entry *) h; - for (p = eh->dyn_relocs; p != NULL; p = p->next) - { - asection *s = p->sec->output_section; + if (h->root.type == bfd_link_hash_indirect) + return TRUE; - if (s != NULL && (s->flags & SEC_READONLY) != 0) - { - struct bfd_link_info *info = (struct bfd_link_info *) inf; + sec = readonly_dynrelocs (h); + if (sec != NULL) + { + struct bfd_link_info *info = (struct bfd_link_info *) info_p; - info->flags |= DF_TEXTREL; + info->flags |= DF_TEXTREL; + info->callbacks->minfo + (_("%B: dynamic relocation against `%T' in read-only section `%A'\n"), + sec->owner, h->root.root.string, sec); - /* Not an error, just cut short the traversal. */ - return FALSE; - } + /* Not an error, just cut short the traversal. */ + return FALSE; } return TRUE; } @@ -2696,7 +2549,7 @@ tilegx_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, 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_linker_section (dynobj, ".interp"); BFD_ASSERT (s != NULL); @@ -2707,7 +2560,7 @@ tilegx_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, /* 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; @@ -2738,7 +2591,12 @@ tilegx_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, srel = elf_section_data (p->sec)->sreloc; srel->size += p->count * TILEGX_ELF_RELA_BYTES (htab); if ((p->sec->output_section->flags & SEC_READONLY) != 0) - info->flags |= DF_TEXTREL; + { + info->flags |= DF_TEXTREL; + + info->callbacks->minfo (_("%B: dynamic relocation in read-only section `%A'\n"), + p->sec->owner, p->sec); + } } } } @@ -2761,7 +2619,7 @@ tilegx_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, s->size += TILEGX_ELF_WORD_BYTES (htab); if (*local_tls_type == GOT_TLS_GD) s->size += TILEGX_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 += TILEGX_ELF_RELA_BYTES (htab); @@ -2817,7 +2675,8 @@ tilegx_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, if (s == htab->elf.splt || s == htab->elf.sgot || s == htab->elf.sgotplt - || s == htab->sdynbss) + || s == htab->elf.sdynbss + || s == htab->elf.sdynrelro) { /* Strip this section if we don't need it; see the comment below. */ @@ -2873,7 +2732,7 @@ tilegx_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, #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; @@ -2896,7 +2755,7 @@ tilegx_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, /* If any dynamic relocs apply to a read-only section, then we need a DT_TEXTREL entry. */ if ((info->flags & DF_TEXTREL) == 0) - elf_link_hash_traverse (&htab->elf, readonly_dynrelocs, info); + elf_link_hash_traverse (&htab->elf, maybe_set_textrel, info); if (info->flags & DF_TEXTREL) { @@ -2977,7 +2836,7 @@ static const bfd_byte insn_mask_X1[] = { /* Mask to extract the bits corresponding to an instruction in a specific pipe of a bundle, minus the destination operand and the first source operand. */ -static const bfd_byte insn_mask_X0_no_dest_no_srca[] = { +static const bfd_byte insn_mask_X0_no_dest_no_srca[] = { 0x00, 0xf0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00 }; @@ -3094,6 +2953,7 @@ tilegx_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, Elf_Internal_Shdr *symtab_hdr; struct elf_link_hash_entry **sym_hashes; bfd_vma *local_got_offsets; + bfd_vma got_base; asection *sreloc; Elf_Internal_Rela *rel; Elf_Internal_Rela *relend; @@ -3105,6 +2965,11 @@ tilegx_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, sym_hashes = elf_sym_hashes (input_bfd); local_got_offsets = elf_local_got_offsets (input_bfd); + if (elf_hash_table (info)->hgot == NULL) + got_base = 0; + else + got_base = elf_hash_table (info)->hgot->root.u.def.value; + sreloc = elf_section_data (input_section)->sreloc; rel = relocs; @@ -3125,7 +2990,7 @@ tilegx_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, const char *name; bfd_vma off; bfd_boolean is_plt = FALSE; - + bfd_boolean resolved_to_zero; bfd_boolean unresolved_reloc; r_type = TILEGX_ELF_R_TYPE (rel->r_info); @@ -3134,14 +2999,7 @@ tilegx_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, continue; if ((unsigned int)r_type >= ARRAY_SIZE (tilegx_elf_howto_table)) - { - /* Not clear if we need to check here, but just be paranoid. */ - (*_bfd_error_handler) - (_("%B: unrecognized relocation (0x%x) in section `%A'"), - input_bfd, r_type, input_section); - bfd_set_error (bfd_error_bad_value); - return FALSE; - } + return _bfd_unrecognized_reloc (input_bfd, input_section, r_type); howto = tilegx_elf_howto_table + r_type; @@ -3159,12 +3017,13 @@ tilegx_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, } else { - bfd_boolean warned; + bfd_boolean warned ATTRIBUTE_UNUSED; + bfd_boolean ignored ATTRIBUTE_UNUSED; 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 @@ -3181,7 +3040,7 @@ tilegx_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, rel, 1, relend, howto, 0, contents); - if (info->relocatable) + if (bfd_link_relocatable (info)) continue; if (h != NULL) @@ -3212,9 +3071,9 @@ tilegx_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, else if (h != NULL) tls_type = tilegx_elf_hash_entry(h)->tls_type; - is_tls_iele = (! info->shared || tls_type == GOT_TLS_IE); + is_tls_iele = (bfd_link_executable (info) || tls_type == GOT_TLS_IE); is_tls_le = is_tls_iele && (!input_section->sec_flg0 - && !info->shared + && bfd_link_executable (info) && (h == NULL || h->dynindx == -1)); if (r_type == R_TILEGX_TLS_GD_CALL) @@ -3359,7 +3218,7 @@ tilegx_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, break; case R_TILEGX_TLS_IE_LOAD: if (!input_section->sec_flg0 - && !info->shared + && bfd_link_executable (info) && (h == NULL || h->dynindx == -1)) { /* IE -> LE */ @@ -3385,6 +3244,9 @@ tilegx_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, break; } + resolved_to_zero = (h != NULL + && UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)); + switch (r_type) { case R_TILEGX_IMM16_X0_HW0_GOT: @@ -3406,8 +3268,10 @@ tilegx_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, 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 @@ -3448,7 +3312,7 @@ tilegx_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, off &= ~1; else { - if (info->shared) + if (bfd_link_pic (info)) { asection *s; Elf_Internal_Rela outrel; @@ -3473,7 +3337,7 @@ tilegx_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, local_got_offsets[r_symndx] |= 1; } } - relocation = off; + relocation = off - got_base; break; case R_TILEGX_JUMPOFF_X1_PLT: @@ -3578,13 +3442,14 @@ tilegx_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, if ((input_section->flags & SEC_ALLOC) == 0) break; - if ((info->shared + if ((bfd_link_pic (info) && (h == NULL - || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT + || (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT + && !resolved_to_zero) || h->root.type != bfd_link_hash_undefweak) && (! howto->pc_relative || !SYMBOL_CALLS_LOCAL (info, h))) - || (!info->shared + || (!bfd_link_pic (info) && h != NULL && h->dynindx != -1 && !h->non_got_ref @@ -3637,7 +3502,7 @@ tilegx_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, else if (h != NULL && h->dynindx != -1 && (! is_plt - || !info->shared + || !bfd_link_pic (info) || !SYMBOLIC_BIND (info, h) || !h->def_regular)) { @@ -3692,7 +3557,7 @@ tilegx_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, if (indx == 0) { BFD_FAIL (); - (*_bfd_error_handler) + _bfd_error_handler (_("%B: probably compiled without -fPIC?"), input_bfd); bfd_set_error (bfd_error_bad_value); @@ -3720,7 +3585,7 @@ tilegx_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, case R_TILEGX_IMM16_X1_HW0_LAST_TLS_LE: case R_TILEGX_IMM16_X0_HW1_LAST_TLS_LE: case R_TILEGX_IMM16_X1_HW1_LAST_TLS_LE: - if (info->shared) + if (!bfd_link_executable (info)) { Elf_Internal_Rela outrel; bfd_boolean skip; @@ -3772,7 +3637,9 @@ tilegx_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, else if (h != NULL) { tls_type = tilegx_elf_hash_entry(h)->tls_type; - if (!info->shared && h->dynindx == -1 && tls_type == GOT_TLS_IE) + if (bfd_link_executable (info) + && h->dynindx == -1 + && tls_type == GOT_TLS_IE) r_type = (!input_section->sec_flg0 ? tilegx_tls_translate_to_le (r_type) : tilegx_tls_translate_to_ie (r_type)); @@ -3823,8 +3690,10 @@ tilegx_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, bfd_boolean dyn; dyn = htab->elf.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))) { indx = h->dynindx; @@ -3833,7 +3702,7 @@ tilegx_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, /* The GOT entries have not been initialized yet. Do it now, and emit any relocations. */ - if ((info->shared || indx != 0) + if ((bfd_link_pic (info) || indx != 0) && (h == NULL || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT || h->root.type != bfd_link_hash_undefweak)) @@ -3920,7 +3789,7 @@ tilegx_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, if (off >= (bfd_vma) -2) abort (); - relocation = off; + relocation = off - got_base; unresolved_reloc = FALSE; howto = tilegx_elf_howto_table + r_type; break; @@ -3937,11 +3806,12 @@ tilegx_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, && h->def_dynamic) && _bfd_elf_section_offset (output_bfd, info, input_section, rel->r_offset) != (bfd_vma) -1) - (*_bfd_error_handler) - (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"), + _bfd_error_handler + /* xgettext:c-format */ + (_("%B(%A+%#Lx): unresolvable %s relocation against symbol `%s'"), input_bfd, input_section, - (long) rel->r_offset, + rel->r_offset, howto->name, h->root.root.string); @@ -4003,15 +3873,14 @@ tilegx_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, switch (r) { case bfd_reloc_overflow: - r = info->callbacks->reloc_overflow + (*info->callbacks->reloc_overflow) (info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0, input_bfd, input_section, rel->r_offset); break; case bfd_reloc_undefined: - r = info->callbacks->undefined_symbol - (info, name, input_bfd, input_section, rel->r_offset, - TRUE); + (*info->callbacks->undefined_symbol) + (info, name, input_bfd, input_section, rel->r_offset, TRUE); break; case bfd_reloc_outofrange: @@ -4032,11 +3901,8 @@ tilegx_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, } if (msg) - r = info->callbacks->warning - (info, msg, name, input_bfd, input_section, rel->r_offset); - - if (! r) - return FALSE; + (*info->callbacks->warning) (info, msg, name, input_bfd, + input_section, rel->r_offset); } } @@ -4138,7 +4004,7 @@ tilegx_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) && (info->symbolic || h->dynindx == -1) && h->def_regular) { @@ -4167,7 +4033,10 @@ tilegx_elf_finish_dynamic_symbol (bfd *output_bfd, /* This symbols needs a copy reloc. Set it up. */ BFD_ASSERT (h->dynindx != -1); - s = htab->srelbss; + if (h->root.u.def.section == htab->elf.sdynrelro) + s = htab->elf.sreldynrelro; + else + s = htab->elf.srelbss; BFD_ASSERT (s != NULL); rela.r_offset = (h->root.u.def.value @@ -4259,7 +4128,7 @@ tilegx_elf_finish_dynamic_sections (bfd *output_bfd, ret = tilegx_finish_dyn (output_bfd, info, dynobj, sdyn, splt); - if (ret != TRUE) + if (!ret) return ret; /* Fill in the head and tail entries in the procedure linkage table. */ @@ -4279,17 +4148,17 @@ tilegx_elf_finish_dynamic_sections (bfd *output_bfd, entry size. */ pad_size = PLT_ENTRY_SIZE - PLT_HEADER_SIZE - PLT_TAIL_SIZE; memset (splt->contents + splt->size - pad_size, 0, pad_size); - } - elf_section_data (splt->output_section)->this_hdr.sh_entsize - = PLT_ENTRY_SIZE; + elf_section_data (splt->output_section)->this_hdr.sh_entsize + = PLT_ENTRY_SIZE; + } } if (htab->elf.sgotplt) { if (bfd_is_abs_section (htab->elf.sgotplt->output_section)) { - (*_bfd_error_handler) + _bfd_error_handler (_("discarded output section: `%A'"), htab->elf.sgotplt); return FALSE; } @@ -4303,10 +4172,10 @@ tilegx_elf_finish_dynamic_sections (bfd *output_bfd, TILEGX_ELF_PUT_WORD (htab, output_bfd, (bfd_vma) 0, htab->elf.sgotplt->contents + GOT_ENTRY_SIZE (htab)); - } - elf_section_data (htab->elf.sgotplt->output_section)->this_hdr.sh_entsize = - GOT_ENTRY_SIZE (htab); + elf_section_data (htab->elf.sgotplt->output_section)->this_hdr.sh_entsize = + GOT_ENTRY_SIZE (htab); + } } if (htab->elf.sgot) @@ -4320,10 +4189,10 @@ tilegx_elf_finish_dynamic_sections (bfd *output_bfd, 0); TILEGX_ELF_PUT_WORD (htab, output_bfd, val, htab->elf.sgot->contents); - } - elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = - GOT_ENTRY_SIZE (htab); + elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = + GOT_ENTRY_SIZE (htab); + } } return TRUE; @@ -4342,7 +4211,9 @@ tilegx_elf_plt_sym_val (bfd_vma i, const asection *plt, } enum elf_reloc_type_class -tilegx_reloc_type_class (const Elf_Internal_Rela *rela) +tilegx_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED, + const asection *rel_sec ATTRIBUTE_UNUSED, + const Elf_Internal_Rela *rela) { switch ((int) TILEGX_ELF_R_TYPE (rela->r_info)) { @@ -4387,14 +4258,16 @@ tilegx_additional_program_headers (bfd *abfd, bfd_boolean -_bfd_tilegx_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd) +_bfd_tilegx_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) { + bfd *obfd = info->output_bfd; const char *targ1 = bfd_get_target (ibfd); const char *targ2 = bfd_get_target (obfd); if (strcmp (targ1, targ2) != 0) { - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%B: Cannot link together %s and %s objects."), ibfd, targ1, targ2); bfd_set_error (bfd_error_bad_value);