Bug 26762 - -Wl,--as-needed removes strong symbols in favour of weak symbols
Summary: -Wl,--as-needed removes strong symbols in favour of weak symbols
Status: RESOLVED NOTABUG
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: 2.34
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-10-20 22:53 UTC by Sergei Trofimovich
Modified: 2020-12-19 04:51 UTC (History)
2 users (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 Sergei Trofimovich 2020-10-20 22:53:43 UTC
Original bug was a failed attempt to build llvm-11 with LDFLAGS="-flto -Wl,--as-needed": https://bugs.gentoo.org/749162.

There std::call_once is implemented via weak pthread_once() symbol: https://gcc.gnu.org/PR55394. Presence of -Wl,--as-needed removes libpthread.so and breaks the program at runtime as pthread_once() has to have a real implementation. gcc plans to fix std::call_once by avoiding pthread_once() for unrelated reason (solving it will take a while).

But the problem seems to be more general when local weak symbols are used to probe presence of a real implementation dynamically.

What do you think of changing 'ld' to prefer strong symbols from shared libraries and keeping DT_NEEDED entries even if local object files define weak symbols?

Toy example:

$ cat a.c
// gcc a.c -o a -Wl,--as-needed -pthread && ./a
#include <stdio.h>
#include <pthread.h>

static pthread_once_t once = PTHREAD_ONCE_INIT;

static __typeof(pthread_once) __gthrw_pthread_once __attribute__ ((__weakref__("pthread_once"), __copy__ (pthread_once)));

static void ir(void)
{
    printf("foo\n");
}

int main(void)
{
    if (__gthrw_pthread_once)
        __gthrw_pthread_once(&once, &ir);
}
$ gcc a.c -o a -Wl,--as-needed -pthread -fuse-ld=bfd && ./a
$ gcc a.c -o a -Wl,--as-needed -pthread -fuse-ld=gold && ./a
$ gcc a.c -o a -Wl,--as-needed -pthread -fuse-ld=lld && ./a

$ gcc a.c -o a -Wl,--no-as-needed -pthread -fuse-ld=bfd && ./a
foo

Ideally all 4 tests should call pthread_once from libpthread.so.0 instead of calling local weak reference.

Thanks!
Comment 1 H.J. Lu 2020-10-21 12:18:24 UTC
It is done on purpose.  libpthread.so.0 should be referenced by non-weak
binding since weak reference means optional.
Comment 2 Sergei Trofimovich 2020-10-21 18:15:32 UTC
Aha, we'll try to find another workaround downstream then.

Thank you!
Comment 3 Cary Coutant 2020-12-19 04:51:19 UTC
This old thread might be relevant:

https://sourceware.org/pipermail/binutils/2018-June/103245.html