diff mbox series

[v3,2/9] package/binutils: add local patches to fix Nios2 bug 27597

Message ID 20240306213606.2149683-3-giulio.benetti@benettiengineering.com
State New
Headers show
Series Patch and remove Nios2 binutils bug 27597 | expand

Commit Message

Giulio Benetti March 6, 2024, 9:35 p.m. UTC
These backported patches fix Nios2 linker bug 27597 that affects packages
gdal, kf5-kcoreaddons, libgeos, libcamera, pistache.

Signed-off-by: Giulio Benetti <giulio.benetti@benettiengineering.com>
---
V2->V3:
* rebase binutils patch against 216e99e9b4fd4c015443bfe15c7be3f06b21fe86
  since binutils version 2.39 has been dropped while version 2.42 has been
  added
---
 ...ertion-fail-in-nios2_elf32_install_i.patch | 125 ++++++++++++++++++
 ...ertion-fail-in-nios2_elf32_install_i.patch | 125 ++++++++++++++++++
 ...ertion-fail-in-nios2_elf32_install_i.patch | 125 ++++++++++++++++++
 3 files changed, 375 insertions(+)
 create mode 100644 package/binutils/2.40/0003-PR27597-nios-assertion-fail-in-nios2_elf32_install_i.patch
 create mode 100644 package/binutils/2.41/0003-PR27597-nios-assertion-fail-in-nios2_elf32_install_i.patch
 create mode 100644 package/binutils/2.42/0003-PR27597-nios-assertion-fail-in-nios2_elf32_install_i.patch
diff mbox series

Patch

diff --git a/package/binutils/2.40/0003-PR27597-nios-assertion-fail-in-nios2_elf32_install_i.patch b/package/binutils/2.40/0003-PR27597-nios-assertion-fail-in-nios2_elf32_install_i.patch
new file mode 100644
index 0000000000..4753ae13c4
--- /dev/null
+++ b/package/binutils/2.40/0003-PR27597-nios-assertion-fail-in-nios2_elf32_install_i.patch
@@ -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
+
diff --git a/package/binutils/2.41/0003-PR27597-nios-assertion-fail-in-nios2_elf32_install_i.patch b/package/binutils/2.41/0003-PR27597-nios-assertion-fail-in-nios2_elf32_install_i.patch
new file mode 100644
index 0000000000..4753ae13c4
--- /dev/null
+++ b/package/binutils/2.41/0003-PR27597-nios-assertion-fail-in-nios2_elf32_install_i.patch
@@ -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
+
diff --git a/package/binutils/2.42/0003-PR27597-nios-assertion-fail-in-nios2_elf32_install_i.patch b/package/binutils/2.42/0003-PR27597-nios-assertion-fail-in-nios2_elf32_install_i.patch
new file mode 100644
index 0000000000..4753ae13c4
--- /dev/null
+++ b/package/binutils/2.42/0003-PR27597-nios-assertion-fail-in-nios2_elf32_install_i.patch
@@ -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
+