diff options
author | Alan Modra <amodra@gmail.com> | 2017-02-28 10:38:51 +1030 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2017-02-28 13:20:21 +1030 |
commit | 4ef97a1b459849ad190244c36b36d45bdd078030 (patch) | |
tree | 3d3e947ad822afec5592b9af6abb1a532fd4c2f2 /bfd/elf32-nios2.c | |
parent | 7ba71655a425ac44721f97cc0ad7922ca15bce43 (diff) | |
download | binutils-gdb-4ef97a1b459849ad190244c36b36d45bdd078030.tar.gz |
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.
Diffstat (limited to 'bfd/elf32-nios2.c')
-rw-r--r-- | bfd/elf32-nios2.c | 154 |
1 files changed, 53 insertions, 101 deletions
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; } |