|
@@ -0,0 +1,125 @@
|
|
|
+From 900c0f0aa3d78cd9e67ccd26fbc86224cef4c5b1 Mon Sep 17 00:00:00 2001
|
|
|
+From: Alan Modra <amodra@gmail.com>
|
|
|
+Date: Fri, 16 Feb 2024 22:33:29 +1030
|
|
|
+Subject: [PATCH] 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.
|
|
|
+
|
|
|
+Upstream: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=900c0f0aa3d78cd9e67ccd26fbc86224cef4c5b1
|
|
|
+
|
|
|
+Signed-off-by: Giulio Benetti <giulio.benetti@benettiengineering.com>
|
|
|
+---
|
|
|
+ bfd/elf32-nios2.c | 40 ++++++++++++++++++++++++----------------
|
|
|
+ 1 file 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);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+--
|
|
|
+2.34.1
|
|
|
+
|