Undefined use of weak symbols in gnulib
Alan Modra
amodra@gmail.com
Mon May 3 01:44:54 GMT 2021
On Tue, Apr 27, 2021 at 07:53:16AM +0200, Florian Weimer via Binutils wrote:
> So the net effect is this:
>
> if (pthread_mutexattr_gettype != NULL)
> pthread_once (control, callback);
>
> Dynamic linking with weak symbols is not very well-defined. On x86-64,
> the link editor produces the expected dynamic symbol relocation for the
> pthread_once call. On other targets (notably POWER), no dynamic
> relocation is produced, and the code will crash if
> pthread_mutexattr_gettype is ever defined.
Yes, this construct is not handled in ppc32 and ppc64 ld. It also
doesn't work with some combination of compiler flags on x86. Don't
allow yourself to be fooled by only testing with compilers that
default to -fpie..
For example, this on x86_64 with gcc-11 (and previous versions).
$ cat ~/src/tmp/weakfunc2.c
extern void func1 (void) __attribute__((weak));
extern void func2 (void) __attribute__((weak));
int
main (void)
{
if (func1)
func2 ();
return 0;
}
$ gcc -O2 -c -fno-pie ~/src/tmp/weakfunc2.c
$ gas/as-new -o empty.o /dev/null
$ ld/ld-new -shared -o empty.so empty.o
$ ld/ld-new -o weakfunc2 weakfunc2.o empty.so
ld/ld-new: warning: cannot find entry symbol _start; defaulting to 0000000000401020
$ binutils/nm-new --dynamic weakfunc2
w func2
So func1 is resolved to zero at link time. Well, I guess that isn't
unexpected. powerpc-linux and powerpc64-linux (both ABIs) have
further problems that I'll fix. In particular the above testcase
ought to work even though it looks wrong to test func1 non-NULL and
then call func2. Slightly less weird is
if (func1)
{
func1 ();
func2 ();
}
which might be reasonable user code when it is known that func1 and
func2 both exist or are both NULL. ppc gets that one wrong too.
--
Alan Modra
Australia Development Lab, IBM
More information about the Binutils
mailing list