Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

package/binutils: add local patches to fix Nios2 bug 27597 #2

Open
wants to merge 1 commit into
base: toolchains.bootlin.com-2023.11
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
From 900c0f0aa3d78cd9e67ccd26fbc86224cef4c5b1 Mon Sep 17 00:00:00 2001
From: Alan Modra <[email protected]>
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 <[email protected]>
---
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

Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
From 900c0f0aa3d78cd9e67ccd26fbc86224cef4c5b1 Mon Sep 17 00:00:00 2001
From: Alan Modra <[email protected]>
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 <[email protected]>
---
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

Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
From 900c0f0aa3d78cd9e67ccd26fbc86224cef4c5b1 Mon Sep 17 00:00:00 2001
From: Alan Modra <[email protected]>
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 <[email protected]>
---
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