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.
This commit is contained in:
Alan Modra 2017-02-28 10:38:51 +10:30
parent 7ba71655a4
commit 4ef97a1b45
6 changed files with 94 additions and 102 deletions

View file

@ -1,3 +1,27 @@
2017-02-28 Alan Modra <amodra@gmail.com>
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 <amodra@gmail.com>
* reloc.c (BFD_RELOC_PPC_16DX_HA): New.

View file

@ -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;
}

View file

@ -1,3 +1,7 @@
2017-02-28 Alan Modra <amodra@gmail.com>
* config/tc-nios2.h (TC_FORCE_RELOCATION_SUB_LOCAL): Define.
2017-02-28 Alan Modra <amodra@gmail.com>
* config/tc-ppc.c (md_assemble): Use BFD_RELOC_PPC_16DX_HA for addpcis.

View file

@ -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. */

View file

@ -1,3 +1,7 @@
2017-02-28 Alan Modra <amodra@gmail.com>
* testsuite/ld-elf/merge.d: xfail for nios.
2017-02-28 Alan Modra <amodra@gmail.com>
* testsuite/ld-powerpc/addpcis.d: Define ext1 and ext2 at

View file

@ -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-*-*"