Bug 31158 - ld: Should --gc-sections respect RHS of a symbol assignment?
Summary: ld: Should --gc-sections respect RHS of a symbol assignment?
Status: NEW
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2023-12-13 05:48 UTC by Fangrui Song
Modified: 2023-12-15 00:12 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Fangrui Song 2023-12-13 05:48:48 UTC
cat > a.s <<e
.globl _start; _start: ret
.section .rodata.bar, "a"
.global bar; bar: .quad 0x1122334455667788
e
echo 'x = bar;' > a.t
echo 'PROVIDE(x = bar);' > b.t  # not used, but worth testing
as a.s -o a.o
ld.lld --gc-sections a.o a.t -o a.lld
ld.bfd --gc-sections a.o a.t -o a.bfd
ld.gold --gc-sections a.o a.t -o a.gold

In gold and lld, the symbol assignment `x = bar;` retains .rodata.bar while BFD doesn't:

ld.bfd: removing unused section '.rodata.bar' in file 'a.o'


Perhaps gold and lld's behavior make more sense?
Comment 1 Alan Modra 2023-12-14 01:30:02 UTC
(In reply to Fangrui Song from comment #0)
> Perhaps gold and lld's behavior make more sense?
No.  There is no use of x or bar in your testcase.

If you change it to
cat > a.s <<e
.globl _start; _start: .dc.a x
.section .rodata.bar, "a"
.global bar; bar: .quad 0x1122334455667788
e
echo 'x = bar;' > a.t
ld.bfd --gc-sections a.o a.t -o a.bfd

then .rodata.bar is kept.  I believe that is the proper behaviour, and the other linkers wrong.
Comment 2 Fangrui Song 2023-12-14 08:23:20 UTC
Interesting. BFD's behavior depends on whether the assigned symbol is referenced.
Let's enhance the test.

cat > a.s <<e
.globl _start, y1, y2
_start: .dc.a x1
.section .rodata.y1, "a"; y1: .quad 0x1122334455667788
.section .rodata.y2, "a"; y2: .quad 0x1122334455667788
e

echo 'x1 = y1; x2 = y2;' > a.t
as a.s -o a.o
ld.lld --gc-sections a.o a.t -o a.lld
ld.bfd --gc-sections a.o a.t -o a.gc.bfd
ld.bfd a.o a.t -o a.nogc.bfd
ld.gold --gc-sections a.o a.t -o a.gold

% readelf -Ws a.nogc.bfd | grep '[xy]'
Symbol table '.symtab' contains 9 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     1: 0000000000402008     0 NOTYPE  GLOBAL DEFAULT    2 y2
     2: 0000000000402008     0 NOTYPE  GLOBAL DEFAULT    2 x2
     5: 0000000000402000     0 NOTYPE  GLOBAL DEFAULT    2 x1
     8: 0000000000402000     0 NOTYPE  GLOBAL DEFAULT    2 y1
% readelf -Ws a.gc.bfd | grep '[xy]'
Symbol table '.symtab' contains 8 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     1: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS x2
     4: 0000000000402000     0 NOTYPE  GLOBAL DEFAULT    2 x1
     7: 0000000000402000     0 NOTYPE  GLOBAL DEFAULT    2 y1

x2 is non-zero in a GC link and zero in a no-GC link.
There appears unusual: a live symbol's value can be very different when GC is enabled.
Or, is this a clever trick to check whether a section is GCed?
Comment 3 Alan Modra 2023-12-15 00:12:20 UTC
I would say it's a minor bug that x2 is not removed along with y2.  I don't care to fix that though.