Bug 31652 - weak def in discarded comdat section becomes unreferenced undefweak with ld -r
Summary: weak def in discarded comdat section becomes unreferenced undefweak with ld -r
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: 2.43 (HEAD)
: P2 normal
Target Milestone: 2.43
Assignee: Not yet assigned to anyone
URL: https://sourceware.org/pipermail/binu...
Keywords:
Depends on:
Blocks:
 
Reported: 2024-04-18 07:42 UTC by Alexandre Oliva
Modified: 2024-04-23 16:13 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 Alexandre Oliva 2024-04-18 07:42:02 UTC
The following, say t.s, is dystilled from libstdc++-v3's floating_to_chars.o:

.section .text.foobar,"axG",@progbits,foo,comdat
.weak foo
.type foo,@function
foo:
# .dc.a undef
.size foo, . - foo
.weak bar
.set bar, foo

The weak definitions were originally implicit instantiations of to_chars_i<unsigned int128_t>, and the aliases were originally meant for abi compatibility because of changes in int128_t mangling.

The following, say m.s, is dystilled from a libstdc++-v3/testsuite/std/time/clock/system/io.cc:

.section .text.foobar,"axG",@progbits,foo,comdat
.weak foo
.type foo,@function
foo:
.size foo, . - foo
.global _start
.set _start,foo

And here's how to trigger the problem:
(simplified from the emails, dropping the unnecessary archive and linking the object file in it directly; the asm sources were also simplified, dropping bits that were meant to pull t.o from the archive)

gas/as-new t.s -o t.o && gas/as-new m.s -o m.o && ld/ld-new m.o t.o -o m -r && binutils/nm-new m | grep bar
                 w bar

Tested with 2.38, 2.42, and 2.42.50.20240413, targeting x86_64-linux-gnu, and also 2.42 targeting multiple vxworks7r2 targets.

This is probably expected behavior: the weakly-defined symbol in t.o lives in a discarded section, so it decays to weak-undefined, and it most likely goes unnoticed on systems that support undefweak.

If this were a final link, the bar symbol would be gone.  So would the undef symbol, if the reference to it in t.s were uncommented.  But because this is a relocatable link, both undefined symbols would remain.

Both of them are a problem for e.g. vxworks kernel modules, that never undergo final linking, and whose loader rejects undefined symbols, even weak ones, if they're not defined elsewhere.

I hoped --strip-discarded would get rid of undef, if not bar, but no such luck.
Comment 1 H.J. Lu 2024-04-18 12:29:59 UTC
A patch is posted at

https://sourceware.org/pipermail/binutils/2024-April/133694.html
Comment 2 Sourceware Commits 2024-04-19 02:19:48 UTC
The master branch has been updated by H.J. Lu <hjl@sourceware.org>:

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

commit eebad48efeeee858be83d754a6b1326133e51d36
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Thu Apr 18 05:28:56 2024 -0700

    elf: Strip unreferenced weak undefined symbols
    
    Linker will resolve an undefined symbol only if it is referenced by
    relocation.  Unreferenced weak undefined symbols serve no purpose.
    Weak undefined symbols appear in the dynamic symbol table only when they
    are referenced by dynamic relocation.  Mark symbols with relocation and
    strip undefined weak symbols if they don't have relocation and aren't
    in the dynamic symbol table.
    
    bfd/
    
            PR ld/31652
            * elf-bfd.h (elf_link_hash_entry): Add has_reloc.
            * elf-vxworks.c (elf_vxworks_emit_relocs): Set has_reloc.
            * elflink.c (_bfd_elf_link_output_relocs): Likewise.
            (elf_link_output_extsym): Strip undefined weak symbols if they
            don't have relocation and aren't in the dynamic symbol table.
    
    ld/
    
            PR ld/31652
            * testsuite/ld-elf/elf.exp: Run undefweak tests.
            * testsuite/ld-elf/undefweak-1.rd: New file.
            * testsuite/ld-elf/undefweak-1a.s: Likewise.
            * testsuite/ld-elf/undefweak-1b.s: Likewise.
            * testsuite/ld-x86-64/weakundef-1.nd: Likewise.
            * testsuite/ld-x86-64/weakundef-1a.s: Likewise.
            * testsuite/ld-x86-64/weakundef-1b.s: Likewise.
            * testsuite/ld-x86-64/x86-64.exp: Run undefweak tests.
Comment 3 H.J. Lu 2024-04-19 02:20:29 UTC
Fixed.
Comment 4 Sourceware Commits 2024-04-19 07:18:24 UTC
The master branch has been updated by Alan Modra <amodra@sourceware.org>:

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

commit 9cf3c87e166b2f3728ae5c50c501f64f385e349e
Author: Alan Modra <amodra@gmail.com>
Date:   Fri Apr 19 16:35:30 2024 +0930

    Re: elf: Strip unreferenced weak undefined symbols
    
            PR ld/31652
            * elflink.c (_bfd_elf_link_output_relocs): Don't segfault
            on NULL rel_hash.
Comment 5 Sourceware Commits 2024-04-23 16:13:46 UTC
The master branch has been updated by H.J. Lu <hjl@sourceware.org>:

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

commit 9b441c415c556e608e22cb9d16b500992a972b0c
Author: Olivier Hainque <hainque@adacore.com>
Date:   Mon Apr 22 02:50:28 2024 -0300

    bfd: Remove duplicate word in elf-vxworks.c
    
            PR ld/31652
            * elf-vxworks.c  (elf_vxworks_emit_relocs): Drop duplicate word.