From 4ef97a1b459849ad190244c36b36d45bdd078030 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Tue, 28 Feb 2017 10:38:51 +1030 Subject: [PATCH] Nios2 dynobj handling fixes A number of places in elf32-nios.c created dynamic sections but didn't set the hash table dynobj. That meant we could have duplicate dynamic sections connected to a number of bfds, so size_dynamic_sections didn't properly discard or allocate contents. Also, the entire set of dynamic sections was created in check_relocs on seeing GOT relocs, when only .got related sections are needed, probably done to hide segfaults later in finish_dynamic_sections. The patch fixes these issues and makes the assembler emit errors when nios2 lacks the necessary pc-relative relocs for subtraction expressions, rather than silently generating bad code. eg. ld-elf/merge. I've also tidied uses of elf32_nios2_hash_table and elf_hash_table. bfd/ PR 20995 * elf32-nios2.c (nios2_elf32_relocate_section): Use htab rather than elf32_nios2_hash_table or elf_hash_table. (create_got_section): Likewise. (nios2_elf32_finish_dynamic_symbol): Likewise. (nios2_elf32_adjust_dynamic_symbol): Likewise. (nios2_elf32_size_dynamic_sections): Likewise. (nios2_elf32_check_relocs): Delete dynobj, sgot, and srelgot vars. Use htab equivalents directly instead. Don't create all dynamic sections on needing just the GOT. Use a goto rather than a fall-through with reloc test. Ensure htab->dynobj is set when making dynamic sreloc section. (nios2_elf32_finish_dynamic_sections): Delete dynobj, use htab equivalent directly instead. Don't segfault on looking for .dynamic when dynamic sections have not been created. Don't segfault on .got.plt being discarded. (nios2_elf32_size_dynamic_sections): Delete plt and got vars. Don't set "relocs" on .rela.plt. Do handle .sbss. Delete fixme and another not so relevant comment. (nios2_elf_add_symbol_hook): Delete dynobj var. If not already set, set hash table dynobj on creating .sbss. gas/ * config/tc-nios2.h (TC_FORCE_RELOCATION_SUB_LOCAL): Define. ld/ * testsuite/ld-elf/merge.d: xfail for nios. --- bfd/ChangeLog | 24 ++++++ bfd/elf32-nios2.c | 154 +++++++++++++----------------------- gas/ChangeLog | 4 + gas/config/tc-nios2.h | 8 ++ ld/ChangeLog | 4 + ld/testsuite/ld-elf/merge.d | 2 +- 6 files changed, 94 insertions(+), 102 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 2ae29b35e11..68fb27edd35 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,27 @@ +2017-02-28 Alan Modra + + PR 20995 + * elf32-nios2.c (nios2_elf32_relocate_section): Use htab + rather than elf32_nios2_hash_table or elf_hash_table. + (create_got_section): Likewise. + (nios2_elf32_finish_dynamic_symbol): Likewise. + (nios2_elf32_adjust_dynamic_symbol): Likewise. + (nios2_elf32_size_dynamic_sections): Likewise. + (nios2_elf32_check_relocs): Delete dynobj, sgot, and srelgot + vars. Use htab equivalents directly instead. Don't create + all dynamic sections on needing just the GOT. Use a goto + rather than a fall-through with reloc test. Ensure + htab->dynobj is set when making dynamic sreloc section. + (nios2_elf32_finish_dynamic_sections): Delete dynobj, use htab + equivalent directly instead. Don't segfault on looking for + .dynamic when dynamic sections have not been created. Don't + segfault on .got.plt being discarded. + (nios2_elf32_size_dynamic_sections): Delete plt and got vars. + Don't set "relocs" on .rela.plt. Do handle .sbss. Delete + fixme and another not so relevant comment. + (nios2_elf_add_symbol_hook): Delete dynobj var. If not + already set, set hash table dynobj on creating .sbss. + 2017-02-28 Alan Modra * reloc.c (BFD_RELOC_PPC_16DX_HA): New. diff --git a/bfd/elf32-nios2.c b/bfd/elf32-nios2.c index d07ef67a85e..a2045bf3667 100644 --- a/bfd/elf32-nios2.c +++ b/bfd/elf32-nios2.c @@ -3713,10 +3713,10 @@ nios2_elf32_relocate_section (bfd *output_bfd, splt = htab->root.splt; local_got_offsets = elf_local_got_offsets (input_bfd); - if (elf32_nios2_hash_table (info)->h_gp_got == NULL) + if (htab->h_gp_got == NULL) got_base = 0; else - got_base = elf32_nios2_hash_table (info)->h_gp_got->root.u.def.value; + got_base = htab->h_gp_got->root.u.def.value; for (rel = relocs; rel < relend; rel++) { @@ -3998,7 +3998,7 @@ nios2_elf32_relocate_section (bfd *output_bfd, off = h->got.offset; BFD_ASSERT (off != (bfd_vma) -1); - dyn = elf_hash_table (info)->dynamic_sections_created; + dyn = htab->root.dynamic_sections_created; if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info), h) @@ -4580,7 +4580,7 @@ create_got_section (bfd *dynobj, struct bfd_link_info *info) points to the base of the GOT while _gp_got may include a bias. */ h = _bfd_elf_define_linkage_sym (dynobj, info, htab->root.sgotplt, "_gp_got"); - elf32_nios2_hash_table (info)->h_gp_got = h; + htab->h_gp_got = h; if (h == NULL) return FALSE; @@ -4694,21 +4694,17 @@ static bfd_boolean nios2_elf32_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec, const Elf_Internal_Rela *relocs) { - bfd *dynobj; Elf_Internal_Shdr *symtab_hdr; struct elf_link_hash_entry **sym_hashes, **sym_hashes_end; const Elf_Internal_Rela *rel; const Elf_Internal_Rela *rel_end; struct elf32_nios2_link_hash_table *htab; - asection *sgot; - asection *srelgot; asection *sreloc = NULL; bfd_signed_vma *local_got_refcounts; if (bfd_link_relocatable (info)) return TRUE; - dynobj = elf_hash_table (info)->dynobj; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sym_hashes = elf_sym_hashes (abfd); sym_hashes_end = (sym_hashes @@ -4718,8 +4714,6 @@ nios2_elf32_check_relocs (bfd *abfd, struct bfd_link_info *info, local_got_refcounts = elf_local_got_refcounts (abfd); htab = elf32_nios2_hash_table (info); - sgot = htab->root.sgot; - srelgot = htab->root.srelgot; rel_end = relocs + sec->reloc_count; for (rel = relocs; rel < rel_end; rel++) @@ -4778,26 +4772,6 @@ nios2_elf32_check_relocs (bfd *abfd, struct bfd_link_info *info, break; } - if (dynobj == NULL) - { - /* Create the .got section. */ - elf_hash_table (info)->dynobj = dynobj = abfd; - nios2_elf32_create_dynamic_sections (dynobj, info); - } - - if (sgot == NULL) - { - sgot = htab->root.sgot; - BFD_ASSERT (sgot != NULL); - } - - if (srelgot == NULL - && (h != NULL || bfd_link_pic (info))) - { - srelgot = htab->root.srelgot; - BFD_ASSERT (srelgot != NULL); - } - if (h != NULL) { struct elf32_nios2_link_hash_entry *eh @@ -4856,11 +4830,7 @@ nios2_elf32_check_relocs (bfd *abfd, struct bfd_link_info *info, elf32_nios2_local_got_tls_type (abfd) [r_symndx] = tls_type; } } - /* Fall through */ - case R_NIOS2_TLS_LDM16: - if (r_type == R_NIOS2_TLS_LDM16) - htab->tls_ldm_got.refcount++; - + make_got: if (htab->root.sgot == NULL) { if (htab->root.dynobj == NULL) @@ -4870,6 +4840,10 @@ nios2_elf32_check_relocs (bfd *abfd, struct bfd_link_info *info, } break; + case R_NIOS2_TLS_LDM16: + htab->tls_ldm_got.refcount++; + goto make_got; + /* This relocation describes the C++ object vtable hierarchy. Reconstruct it for later use during GC. */ case R_NIOS2_GNU_VTINHERIT: @@ -4925,8 +4899,11 @@ nios2_elf32_check_relocs (bfd *abfd, struct bfd_link_info *info, section in dynobj and make room for this reloc. */ if (sreloc == NULL) { + if (htab->root.dynobj == NULL) + htab->root.dynobj = abfd; + sreloc = _bfd_elf_make_dynamic_reloc_section - (sec, dynobj, 2, abfd, TRUE); + (sec, htab->root.dynobj, 2, abfd, TRUE); if (sreloc == NULL) return FALSE; } @@ -5291,8 +5268,8 @@ nios2_elf32_finish_dynamic_symbol (bfd *output_bfd, /* Mark _DYNAMIC, _GLOBAL_OFFSET_TABLE_, and _gp_got as absolute. */ if (strcmp (h->root.root.string, "_DYNAMIC") == 0 - || h == elf_hash_table (info)->hgot - || h == elf32_nios2_hash_table (info)->h_gp_got) + || h == htab->root.hgot + || h == htab->h_gp_got) sym->st_shndx = SHN_ABS; return TRUE; @@ -5303,24 +5280,22 @@ static bfd_boolean nios2_elf32_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) { - bfd *dynobj; asection *sgotplt; asection *sdyn; struct elf32_nios2_link_hash_table *htab; htab = elf32_nios2_hash_table (info); - dynobj = elf_hash_table (info)->dynobj; sgotplt = htab->root.sgotplt; - BFD_ASSERT (sgotplt != NULL); - sdyn = bfd_get_linker_section (dynobj, ".dynamic"); + sdyn = NULL; - if (elf_hash_table (info)->dynamic_sections_created) + if (htab->root.dynamic_sections_created) { asection *splt; Elf32_External_Dyn *dyncon, *dynconend; splt = htab->root.splt; - BFD_ASSERT (splt != NULL && sdyn != NULL); + sdyn = bfd_get_linker_section (htab->root.dynobj, ".dynamic"); + BFD_ASSERT (splt != NULL && sdyn != NULL && sgotplt != NULL); dyncon = (Elf32_External_Dyn *) sdyn->contents; dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size); @@ -5329,7 +5304,7 @@ nios2_elf32_finish_dynamic_sections (bfd *output_bfd, Elf_Internal_Dyn dyn; asection *s; - bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn); + bfd_elf32_swap_dyn_in (htab->root.dynobj, dyncon, &dyn); switch (dyn.d_tag) { @@ -5413,8 +5388,9 @@ nios2_elf32_finish_dynamic_sections (bfd *output_bfd, } } } + /* Fill in the first three entries in the global offset table. */ - if (sgotplt->size > 0) + if (sgotplt != NULL && sgotplt->size > 0) { if (sdyn == NULL) bfd_put_32 (output_bfd, (bfd_vma) 0, sgotplt->contents); @@ -5424,9 +5400,10 @@ nios2_elf32_finish_dynamic_sections (bfd *output_bfd, sgotplt->contents); bfd_put_32 (output_bfd, (bfd_vma) 0, sgotplt->contents + 4); bfd_put_32 (output_bfd, (bfd_vma) 0, sgotplt->contents + 8); - } - elf_section_data (sgotplt->output_section)->this_hdr.sh_entsize = 4; + if (sgotplt->output_section != bfd_abs_section_ptr) + elf_section_data (sgotplt->output_section)->this_hdr.sh_entsize = 4; + } return TRUE; } @@ -5447,7 +5424,7 @@ nios2_elf32_adjust_dynamic_symbol (struct bfd_link_info *info, unsigned align2; htab = elf32_nios2_hash_table (info); - dynobj = elf_hash_table (info)->dynobj; + dynobj = htab->root.dynobj; /* Make sure we know what is going on here. */ BFD_ASSERT (dynobj != NULL @@ -5834,18 +5811,16 @@ nios2_elf32_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, { bfd *dynobj; asection *s; - bfd_boolean plt; - bfd_boolean got; bfd_boolean relocs; bfd *ibfd; struct elf32_nios2_link_hash_table *htab; htab = elf32_nios2_hash_table (info); - dynobj = elf_hash_table (info)->dynobj; + dynobj = htab->root.dynobj; BFD_ASSERT (dynobj != NULL); htab->res_n_size = 0; - if (elf_hash_table (info)->dynamic_sections_created) + if (htab->root.dynamic_sections_created) { /* Set the contents of the .interp section to the interpreter. */ if (bfd_link_executable (info) && !info->nointerp) @@ -5953,21 +5928,19 @@ nios2_elf32_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, sym dynamic relocs. */ elf_link_hash_traverse (& htab->root, allocate_dynrelocs, info); - if (elf_hash_table (info)->dynamic_sections_created) + if (htab->root.dynamic_sections_created) { /* If the .got section is more than 0x8000 bytes, we add 0x8000 to the value of _gp_got, so that 16-bit relocations have a greater chance of working. */ if (htab->root.sgot->size >= 0x8000 - && elf32_nios2_hash_table (info)->h_gp_got->root.u.def.value == 0) - elf32_nios2_hash_table (info)->h_gp_got->root.u.def.value = 0x8000; + && htab->h_gp_got->root.u.def.value == 0) + htab->h_gp_got->root.u.def.value = 0x8000; } /* The check_relocs and adjust_dynamic_symbol entry points have determined the sizes of the various dynamic sections. Allocate memory for them. */ - plt = FALSE; - got = FALSE; relocs = FALSE; for (s = dynobj->sections; s != NULL; s = s->next) { @@ -5980,51 +5953,37 @@ nios2_elf32_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, of the dynobj section names depend upon the input files. */ name = bfd_get_section_name (dynobj, s); - if (s == htab->root.splt) - { - /* Remember whether there is a PLT. */ - plt = s->size != 0; - - /* Correct for the number of res_N branches. */ - if (plt && !bfd_link_pic (info)) - { - htab->res_n_size = (s->size-28) / 3; - s->size += htab->res_n_size; - } - } - else if (CONST_STRNEQ (name, ".rela")) + if (CONST_STRNEQ (name, ".rela")) { if (s->size != 0) { - relocs = TRUE; + if (s != htab->root.srelplt) + relocs = TRUE; /* We use the reloc_count field as a counter if we need to copy relocs into the output file. */ s->reloc_count = 0; } } - else if (s == htab->root.sgot - || s == htab->root.sgotplt) + else if (s == htab->root.splt) { - if (s->size != 0) - got = TRUE; + /* Correct for the number of res_N branches. */ + if (s->size != 0 && !bfd_link_pic (info)) + { + htab->res_n_size = (s->size - 28) / 3; + s->size += htab->res_n_size; + } } - else if (s != htab->root.sdynbss + else if (s != htab->sbss + && s != htab->root.sgot + && s != htab->root.sgotplt + && s != htab->root.sdynbss && s != htab->root.sdynrelro) /* It's not one of our sections, so don't allocate space. */ continue; if (s->size == 0) { - /* If we don't need this section, strip it from the - output file. This is mostly to handle .rela.bss and - .rela.plt. We must create both sections in - create_dynamic_sections, because they must be created - before the linker maps input sections to output - sections. The linker does that before - adjust_dynamic_symbol is called, and it is that - function which decides whether anything needs to go - into these sections. */ s->flags |= SEC_EXCLUDE; continue; } @@ -6033,11 +5992,6 @@ nios2_elf32_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, continue; /* Allocate memory for the section contents. */ - /* FIXME: This should be a call to bfd_alloc not bfd_zalloc. - Unused entries should be reclaimed before the section's contents - are written out, but at the moment this does not happen. Thus in - order to prevent writing out garbage, we initialize the section's - contents to zero. */ s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size); if (s->contents == NULL) return FALSE; @@ -6048,7 +6002,7 @@ nios2_elf32_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, if (htab->res_n_size) elf_link_hash_traverse (& htab->root, adjust_dynrelocs, info); - if (elf_hash_table (info)->dynamic_sections_created) + if (htab->root.dynamic_sections_created) { /* Add some entries to the .dynamic section. We fill in the values later, in elf_nios2_finish_dynamic_sections, but we @@ -6061,10 +6015,11 @@ nios2_elf32_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, if (!bfd_link_pic (info) && !add_dynamic_entry (DT_DEBUG, 0)) return FALSE; - if (got && !add_dynamic_entry (DT_PLTGOT, 0)) + if (htab->root.sgotplt->size != 0 + && !add_dynamic_entry (DT_PLTGOT, 0)) return FALSE; - if (plt + if (htab->root.splt->size != 0 && (!add_dynamic_entry (DT_PLTRELSZ, 0) || !add_dynamic_entry (DT_PLTREL, DT_RELA) || !add_dynamic_entry (DT_JMPREL, 0))) @@ -6171,8 +6126,6 @@ nios2_elf_add_symbol_hook (bfd *abfd, asection **secp, bfd_vma *valp) { - bfd *dynobj; - if (sym->st_shndx == SHN_COMMON && !bfd_link_relocatable (info) && sym->st_size <= elf_gp_size (abfd) @@ -6187,12 +6140,11 @@ nios2_elf_add_symbol_hook (bfd *abfd, { flagword flags = SEC_IS_COMMON | SEC_LINKER_CREATED; - dynobj = elf_hash_table (info)->dynobj; - if (!dynobj) - dynobj = abfd; + if (htab->root.dynobj == NULL) + htab->root.dynobj = abfd; - htab->sbss = bfd_make_section_anyway_with_flags (dynobj, ".sbss", - flags); + htab->sbss = bfd_make_section_anyway_with_flags (htab->root.dynobj, + ".sbss", flags); if (htab->sbss == NULL) return FALSE; } diff --git a/gas/ChangeLog b/gas/ChangeLog index 30d07a877ce..821be3b9941 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,7 @@ +2017-02-28 Alan Modra + + * config/tc-nios2.h (TC_FORCE_RELOCATION_SUB_LOCAL): Define. + 2017-02-28 Alan Modra * config/tc-ppc.c (md_assemble): Use BFD_RELOC_PPC_16DX_HA for addpcis. diff --git a/gas/config/tc-nios2.h b/gas/config/tc-nios2.h index 340fd7671fa..27ae35171c9 100644 --- a/gas/config/tc-nios2.h +++ b/gas/config/tc-nios2.h @@ -101,6 +101,14 @@ extern flagword nios2_elf_section_flags (flagword, int, int); #define DIFF_EXPR_OK +/* Don't allow the generic code to convert fixups involving the + subtraction of a label in the current section to pc-relative if we + don't have the necessary pc-relative relocation. */ +#define TC_FORCE_RELOCATION_SUB_LOCAL(FIX, SEG) \ + (!((FIX)->fx_r_type == BFD_RELOC_16 \ + || (FIX)->fx_r_type == BFD_RELOC_NIOS2_LO16 \ + || (FIX)->fx_r_type == BFD_RELOC_NIOS2_HIADJ16)) + /* Nios2 ABI doesn't have 32-bit PCREL relocation, and, as relocations for CFI information will be in section other than .text, we can't use PC-biased relocs. */ diff --git a/ld/ChangeLog b/ld/ChangeLog index 99be3669e6c..b271cdb1bbb 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,7 @@ +2017-02-28 Alan Modra + + * testsuite/ld-elf/merge.d: xfail for nios. + 2017-02-28 Alan Modra * testsuite/ld-powerpc/addpcis.d: Define ext1 and ext2 at diff --git a/ld/testsuite/ld-elf/merge.d b/ld/testsuite/ld-elf/merge.d index d46acb66740..7976be11053 100644 --- a/ld/testsuite/ld-elf/merge.d +++ b/ld/testsuite/ld-elf/merge.d @@ -4,7 +4,7 @@ #xfail: "bfin-*-*" "cr16-*-*" "cris*-*-*" "crx-*-*" "d10v-*-*" "d30v-*-*" #xfail: "dlx-*-*" "fr30-*-*" "frv-*-*" "hppa*64*-*-*" "h8300-*-*" "score-*-*" #xfail: "i370-*-*" "i860-*-*" "i960-*-*" "ip2k-*-*" "iq2000-*-*" "lm32-*-*" -#xfail: "mcore-*-*" "mn102*-*-*" "ms1-*-*" "mep-*-*" "m68hc11-*-*" +#xfail: "mcore-*-*" "mn102*-*-*" "ms1-*-*" "mep-*-*" "m68hc11-*-*" "nios2-*-*" #xfail: "or32-*-*" "pj-*-*" "sparc*-*-*" "tic6x-*-*" "vax-*-*" "xstormy16-*-*" #xfail: "xtensa*-*-*" "metag-*-*" "ft32-*-*" "pru-*-*" -- 2.30.2