Bug 27597 - nios: assertion fail in nios2_elf32_install_imm16
Summary: nios: assertion fail in nios2_elf32_install_imm16
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: 2.36
: P2 normal
Target Milestone: 2.43
Assignee: Alan Modra
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-03-17 16:27 UTC by Giulio Benetti
Modified: 2024-02-18 18:47 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Last reconfirmed: 2024-02-16 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Giulio Benetti 2021-03-17 16:27:13 UTC
When building libgeos package on Buildroot ld throws:
'''
[ 97%] Building CXX object CMakeFiles/geos.dir/src/util/math.cpp.o
[ 98%] Linking CXX shared library lib/libgeos.so
/nvme/rc-buildroot-test/scripts/instance-0/output-1/host/opt/ext-toolchain/bin/../lib/gcc/nios2-linux-gnu/7.3.1/../../../../nios2-linux-gnu/bin/ld: FDE encoding in CMakeFiles/geos.dir/src/algorithm/Angle.cpp.o(.eh_frame) prevents .eh_frame_hdr table being created.
/nvme/rc-buildroot-test/scripts/instance-0/output-1/host/opt/ext-toolchain/bin/../lib/gcc/nios2-linux-gnu/7.3.1/../../../../nios2-linux-gnu/bin/ld: FDE encoding in CMakeFiles/geos.dir/src/algorithm/Angle.cpp.o(.eh_frame) prevents .eh_frame_hdr table being created.
/nvme/rc-buildroot-test/scripts/instance-0/output-1/host/opt/ext-toolchain/bin/../lib/gcc/nios2-linux-gnu/7.3.1/../../../../nios2-linux-gnu/bin/ld: FDE encoding in CMakeFiles/geos.dir/src/algorithm/Angle.cpp.o(.eh_frame) prevents .eh_frame_hdr table being created.
/nvme/rc-buildroot-test/scripts/instance-0/output-1/host/opt/ext-toolchain/bin/../lib/gcc/nios2-linux-gnu/7.3.1/../../../../nios2-linux-gnu/bin/ld: FDE encoding in CMakeFiles/geos.dir/src/algorithm/Area.cpp.o(.eh_frame) prevents .eh_frame_hdr table being created.
/nvme/rc-buildroot-test/scripts/instance-0/output-1/host/opt/ext-toolchain/bin/../lib/gcc/nios2-linux-gnu/7.3.1/../../../../nios2-linux-gnu/bin/ld: FDE encoding in CMakeFiles/geos.dir/src/algorithm/Area.cpp.o(.eh_frame) prevents .eh_frame_hdr table being created.
/nvme/rc-buildroot-test/scripts/instance-0/output-1/host/opt/ext-toolchain/bin/../lib/gcc/nios2-linux-gnu/7.3.1/../../../../nios2-linux-gnu/bin/ld: FDE encoding in CMakeFiles/geos.dir/src/algorithm/Area.cpp.o(.eh_frame) prevents .eh_frame_hdr table being created.
/nvme/rc-buildroot-test/scripts/instance-0/output-1/host/opt/ext-toolchain/bin/../lib/gcc/nios2-linux-gnu/7.3.1/../../../../nios2-linux-gnu/bin/ld: FDE encoding in CMakeFiles/geos.dir/src/algorithm/Area.cpp.o(.eh_frame) prevents .eh_frame_hdr table being created.
/nvme/rc-buildroot-test/scripts/instance-0/output-1/host/opt/ext-toolchain/bin/../lib/gcc/nios2-linux-gnu/7.3.1/../../../../nios2-linux-gnu/bin/ld: FDE encoding in CMakeFiles/geos.dir/src/algorithm/BoundaryNodeRule.cpp.o(.eh_frame) prevents .eh_frame_hdr table being created.
/nvme/rc-buildroot-test/scripts/instance-0/output-1/host/opt/ext-toolchain/bin/../lib/gcc/nios2-linux-gnu/7.3.1/../../../../nios2-linux-gnu/bin/ld: FDE encoding in CMakeFiles/geos.dir/src/algorithm/CGAlgorithmsDD.cpp.o(.eh_frame) prevents .eh_frame_hdr table being created.
/nvme/rc-buildroot-test/scripts/instance-0/output-1/host/opt/ext-toolchain/bin/../lib/gcc/nios2-linux-gnu/7.3.1/../../../../nios2-linux-gnu/bin/ld: FDE encoding in CMakeFiles/geos.dir/src/algorithm/CGAlgorithmsDD.cpp.o(.eh_frame) prevents .eh_frame_hdr table being created.
/nvme/rc-buildroot-test/scripts/instance-0/output-1/host/opt/ext-toolchain/bin/../lib/gcc/nios2-linux-gnu/7.3.1/../../../../nios2-linux-gnu/bin/ld: Further warnings about FDE encoding preventing .eh_frame_hdr generation dropped.
/nvme/rc-buildroot-test/scripts/instance-0/output-1/host/opt/ext-toolchain/bin/../lib/gcc/nios2-linux-gnu/7.3.1/../../../../nios2-linux-gnu/bin/ld: BFD (Sourcery CodeBench Lite 2018.05-5) 2.28.51 assertion fail /scratch/sandra/nios2-linux-spring-release/obj/binutils-src-2018.05-5-nios2-linux-gnu-i686-pc-linux-gnu/bfd/elf32-nios2.c:1906
/nvme/rc-buildroot-test/scripts/instance-0/output-1/host/opt/ext-toolchain/bin/../lib/gcc/nios2-linux-gnu/7.3.1/../../../../nios2-linux-gnu/bin/ld: BFD (Sourcery CodeBench Lite 2018.05-5) 2.28.51 assertion fail /scratch/sandra/nios2-linux-spring-release/obj/binutils-src-2018.05-5-nios2-linux-gnu-i686-pc-linux-gnu/bfd/elf32-nios2.c:1906
'''

To reproduce it:

# git clone git://git.busybox.net/buildroot
# wget https://git.busybox.net/buildroot-test/tree/utils/br-reproduce-build

- modify BASE_GIT=... with your buildroot path in br-reproduce-build then:
# chmod a+x br-reproduce-build
# ./br-reproduce-build a05fdf1958f93a206c5c66c7f636b6650683626d

I've not found a work around for this bug.
Comment 1 Alan Modra 2024-02-16 06:02:44 UTC
A litte bit of source digging says the assertion failure is from the BFD_ASSERT in nios2_elf32_install_imm16, and since every call except one to that function masks the value, the assert is rather pointless.  The exception is:
	  nios2_elf32_install_imm16 (splt, h->plt.offset + 8,
				     0xfff4 - h->plt.offset);
in nios2_elf32_finish_dynamic_symbol, so it seems we have a PLT size overflow.
Comment 2 Alan Modra 2024-02-16 12:17:06 UTC
Testcase
cat > bigplt.c <<EOF
#define x(n) extern void x##n(void); x##n();
#define x10(n) x(n##0) x(n##1) x(n##2) x(n##3) x(n##4) x(n##5) x(n##6) x(n##7) x(n##8) x(n##9)
#define x100(n) x10(n##0) x10(n##1) x10(n##2) x10(n##3) x10(n##4) x10(n##5) x10(n##6) x10(n##7) x10(n##8) x10(n##9)
#define x1000(n) x100(n##0) x100(n##1) x100(n##2) x100(n##3) x100(n##4) x100(n##5) x100(n##6) x100(n##7) x100(n##8) x100(n##9)

int main (void)
{
  x1000(0);
  x1000(1);
  x1000(2);
  x1000(3);
  x1000(4);
  x1000(5);
  return 0;
}
EOF
nios2-linux-gnu-gcc -fPIC -c bigplt.c
nios2-linux-gnu-gcc -shared -o bigplt.so bigplt.o
Comment 3 Sourceware Commits 2024-02-16 12:28:29 UTC
The master branch has been updated by Alan Modra <amodra@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=900c0f0aa3d78cd9e67ccd26fbc86224cef4c5b1

commit 900c0f0aa3d78cd9e67ccd26fbc86224cef4c5b1
Author: Alan Modra <amodra@gmail.com>
Date:   Fri Feb 16 22:33:29 2024 +1030

    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.
Comment 4 Alan Modra 2024-02-16 12:36:06 UTC
Fixed
Comment 5 Giulio Benetti 2024-02-16 13:04:38 UTC
Thanks a lot Alan,

I will provide backported patches soon for Buildroot toolchains so we can reenable building packages affected by this bug.
Comment 6 Alan Modra 2024-02-17 09:29:21 UTC
Incidentally the testcase in comment #2 doesn't reproduce the assertion fail, but is enough to verify I had the calculations correct in my patch, and generates plenty of bogus PLT resolver stubs.  To see the assertion on an unpatched linker you need to extend it to over 10920 calls.

int main (void)
{
  x1000(0);
  x1000(1);
  x1000(2);
  x1000(3);
  x1000(4);
  x1000(5);
  x1000(6);
  x1000(7);
  x1000(8);
  x1000(9);
  x1000(10);
  return 0;
}
Comment 7 Giulio Benetti 2024-02-18 18:47:39 UTC
Backported, build-tested with binutils 2.39, 2.40 and 2.41 and it works correctly.
Here is the patchset for Buildroot:
https://lore.kernel.org/buildroot/20240218184536.1922309-1-giulio.benetti@benettiengineering.com/T/#m385cbbc3f86ce8672ca6f654c665178fc754a358

Thanks again!