summaryrefslogtreecommitdiff
path: root/bfd/elf32-nios2.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2017-02-28 10:38:51 +1030
committerAlan Modra <amodra@gmail.com>2017-02-28 13:20:21 +1030
commit4ef97a1b459849ad190244c36b36d45bdd078030 (patch)
tree3d3e947ad822afec5592b9af6abb1a532fd4c2f2 /bfd/elf32-nios2.c
parent7ba71655a425ac44721f97cc0ad7922ca15bce43 (diff)
downloadbinutils-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.c154
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;
}