diff options
author | 2024-02-16 22:33:29 +1030 | |
---|---|---|
committer | 2024-02-16 22:49:08 +1030 | |
commit | 900c0f0aa3d78cd9e67ccd26fbc86224cef4c5b1 (patch) | |
tree | 43015e2d92b43869954c865182c8877633fe4287 /bfd | |
parent | Update how-to-make-a-release document to reference new git repository for the... (diff) | |
download | binutils-gdb-900c0f0aa3d78cd9e67ccd26fbc86224cef4c5b1.tar.gz binutils-gdb-900c0f0aa3d78cd9e67ccd26fbc86224cef4c5b1.tar.bz2 binutils-gdb-900c0f0aa3d78cd9e67ccd26fbc86224cef4c5b1.zip |
PR27597, nios: assertion fail in nios2_elf32_install_imm16
The assertion in nios2_elf32_install_imm16 triggers when the PLT is
twice the maximum allowable size for a branch from PLTn to reach
.PLTresolve, and on no other call to nios2_elf32_install_imm16. That
makes the assertion completely useless. We can handle a PIC PLT
exceeding 0x8000 in size by bouncing branches that won't reach through
previous branches.
PR 27597
* elf32-nios2.c (nios2_elf32_install_imm16): Delete BFD_ASSERT.
(nios2_build_one_stub): Don't bother masking value passed to
nios2_elf32_install_imm16.
(nios2_elf32_finish_dynamic_symbol): Likewise. Handle overflow
of PLTn branch to .PLTresolve by bouncing through prior branches.
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/elf32-nios2.c | 40 |
1 files changed, 24 insertions, 16 deletions
diff --git a/bfd/elf32-nios2.c b/bfd/elf32-nios2.c index bebf4239958..7f61e2f8507 100644 --- a/bfd/elf32-nios2.c +++ b/bfd/elf32-nios2.c @@ -1878,8 +1878,6 @@ nios2_elf32_install_imm16 (asection *sec, bfd_vma offset, bfd_vma value) { bfd_vma word = bfd_get_32 (sec->owner, sec->contents + offset); - BFD_ASSERT (value <= 0xffff || ((bfd_signed_vma) value) >= -0xffff); - bfd_put_32 (sec->owner, word | ((value & 0xffff) << 6), sec->contents + offset); } @@ -2518,7 +2516,7 @@ nios2_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg ATTRIBUTE_U nios2_elf32_install_imm16 (stub_sec, hsh->stub_offset, hiadj (sym_value)); nios2_elf32_install_imm16 (stub_sec, hsh->stub_offset + 4, - (sym_value & 0xffff)); + sym_value); stub_sec->size += 12; break; default: @@ -4986,16 +4984,28 @@ nios2_elf32_finish_dynamic_symbol (bfd *output_bfd, /* Emit the PLT entry. */ if (bfd_link_pic (info)) { + bfd_vma br_offset; + nios2_elf32_install_data (splt, nios2_so_plt_entry, h->plt.offset, 3); plt_index = (h->plt.offset - 24) / 12; got_offset = (plt_index + 3) * 4; nios2_elf32_install_imm16 (splt, h->plt.offset, - hiadj(plt_index * 4)); + hiadj (plt_index * 4)); nios2_elf32_install_imm16 (splt, h->plt.offset + 4, - (plt_index * 4) & 0xffff); - nios2_elf32_install_imm16 (splt, h->plt.offset + 8, - 0xfff4 - h->plt.offset); + plt_index * 4); + br_offset = -(h->plt.offset + 12); + /* If this plt entry is too far away from the start of .plt + for the "br" to reach .PLTresolve, bounce through one or + more of the previous "br" instructions. */ + if (br_offset < (bfd_vma) -32768) + { + br_offset += 32768 / 12 * 12 - 4; + while (br_offset < (bfd_vma) -32768) + br_offset += 32768 / 12 * 12; + } + nios2_elf32_install_imm16 (splt, h->plt.offset + 8, br_offset); + got_address = (sgotplt->output_section->vma + sgotplt->output_offset + got_offset); @@ -5014,9 +5024,8 @@ nios2_elf32_finish_dynamic_symbol (bfd *output_bfd, nios2_elf32_install_data (splt, nios2_plt_entry, h->plt.offset, 3); got_address = (sgotplt->output_section->vma + sgotplt->output_offset + got_offset); - nios2_elf32_install_imm16 (splt, h->plt.offset, hiadj(got_address)); - nios2_elf32_install_imm16 (splt, h->plt.offset + 4, - got_address & 0xffff); + nios2_elf32_install_imm16 (splt, h->plt.offset, hiadj (got_address)); + nios2_elf32_install_imm16 (splt, h->plt.offset + 4, got_address); /* Fill in the entry in the global offset table. */ bfd_put_32 (output_bfd, @@ -5217,8 +5226,8 @@ nios2_elf32_finish_dynamic_sections (bfd *output_bfd, BFD_ASSERT ((got_pcrel & 0xf) == 0); nios2_elf32_install_data (splt, nios2_so_plt0_entry, 0, 6); nios2_elf32_install_imm16 (splt, 4, hiadj (got_pcrel)); - nios2_elf32_install_imm16 (splt, 12, got_pcrel & 0xffff); - nios2_elf32_install_imm16 (splt, 16, (got_pcrel + 4) & 0xffff); + nios2_elf32_install_imm16 (splt, 12, got_pcrel); + nios2_elf32_install_imm16 (splt, 16, got_pcrel + 4); } else { @@ -5240,14 +5249,13 @@ nios2_elf32_finish_dynamic_sections (bfd *output_bfd, nios2_elf32_install_data (splt, nios2_plt0_entry, res_size, 7); nios2_elf32_install_imm16 (splt, res_size, hiadj (res_start)); - nios2_elf32_install_imm16 (splt, res_size + 4, - res_start & 0xffff); + nios2_elf32_install_imm16 (splt, res_size + 4, res_start); nios2_elf32_install_imm16 (splt, res_size + 12, hiadj (got_address)); nios2_elf32_install_imm16 (splt, res_size + 16, - (got_address + 4) & 0xffff); + got_address + 4); nios2_elf32_install_imm16 (splt, res_size + 20, - (got_address + 8) & 0xffff); + got_address + 8); } } } |