Bug 28398

Summary: binutils: ld: KEEP ignored
Product: binutils Reporter: Heinrich Schuchardt <xypron.glpk>
Component: ldAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED INVALID    
Severity: normal CC: jrtc27, xypron.glpk
Priority: P2    
Version: 2.37   
Target Milestone: ---   
Host: Target:
Build: Last reconfirmed:
Attachments: Test files

Description Heinrich Schuchardt 2021-09-30 01:00:28 UTC
Created attachment 13684 [details]
Test files

I am running ld on RISC-V or riscv64-linux-gnu-ld on x86_64

Ubuntu package version:
binutils-riscv64-linux-gnu 2.37-7ubuntu1
binutils 2.37-7ubuntu1

SUSE package version:
binutils-2.37-1.1.riscv64

I have a linker script with a KEEP() statement

grep -GHrn KEEP *.ld
fw_dynamic.elf.ld:48:  KEEP(*(SORT(.sbilist*)))

and a static library with multiple sections .sbilist* with non-zero size:

objdump -h libplatsbi.a | grep sbilist
  3 .sbilist_fdtreset_1_ 00000000  0000000000000000  0000000000000000  000001b0  2**3
  4 .sbilist_fdtreset_3_ 00000000  0000000000000000  0000000000000000  000001b0  2**3
  6 .sbilist_fdtreset_2_gpio_poweroff 00000010  0000000000000000  0000000000000000  00000498  2**3
  7 .discard.sbilist 00000010  0000000000000000  0000000000000000  000004a8  2**3
  8 .sbilist_fdtreset_2_gpio_reset 00000010  0000000000000000  0000000000000000  000004b8  2**3
  5 .sbilist_fdtreset_2_htif 00000010  0000000000000000  0000000000000000  000000a0  2**3
  6 .discard.sbilist 00000008  0000000000000000  0000000000000000  000000b0  2**3
  5 .sbilist_fdtreset_2_sifive 00000010  0000000000000000  0000000000000000  000000d0  2**3
  6 .discard.sbilist 00000008  0000000000000000  0000000000000000  000000e0  2**3
  6 .sbilist_fdtreset_2_sunxi_wdt 00000010  0000000000000000  0000000000000000  000001d8  2**3
  7 .discard.sbilist 00000008  0000000000000000  0000000000000000  000001e8  2**3
  6 .sbilist_fdtreset_2_thead 00000010  0000000000000000  0000000000000000  000006e8  2**3
  7 .discard.sbilist 00000008  0000000000000000  0000000000000000  000006f8  2**3

When linking using the linker script

ld -T fw_dynamic.elf.ld \
fw_dynamic.o  libplatsbi.a \
-o fw_dynamic.elf

only referenced .sbilist* sections ends up in the elf file.

objdump -h fw_dynamic.elf | grep sbilist
  6 .sbilist      00000010  0000000080021ba0  0000000080021ba0  00022ba0  2**3

The expected behavior is that unreferenced sections .sbilist* are retained due to the KEEP statement.

The test files are appended.
Comment 1 Heinrich Schuchardt 2021-09-30 01:03:20 UTC
add me to cc
Comment 2 Heinrich Schuchardt 2021-09-30 01:04:43 UTC
set component: ld
Comment 3 Jessica Clarke 2021-09-30 13:48:12 UTC
1. That's because you need -Wl,--whole-archive to include all .o files in the .a
2. Don't put a dot in the section names, make them valid C identifiers and use the linker-generated __start_$section/__stop_$section names
3. You will need -Wl,-z,nostart-stop-gc for LLD 13+ because the maintainer decided breaking coding patterns that have worked for decades is fine (binutils also accepts the flag as of 2.37 but does not currently default to the broken behaviour)

If you want a BSD-2-Clause-licensed linker set implementation you can grab sys/sys/linker_set.h from FreeBSD and alter it however you like.
Comment 4 Alan Modra 2021-10-13 03:23:26 UTC
> The expected behavior is that unreferenced sections .sbilist* are retained due to > the KEEP statement.
Your expectation is not correct.  KEEP is for controlling garbage collection of sections part of objects loaded by ld.  The behaviour of unix archives is orthogonal to this, as Jessica commented.