Re: llvm ld vs binutils ld

From: Dimitry Andric <dim_at_FreeBSD.org>
Date: Sat, 27 Jan 2024 21:29:34 UTC
On 27 Jan 2024, at 18:08, Steve Kargl <sgk@troutmask.apl.washington.edu> wrote:
> 
> In an attempt to cleanup a bit of src/lib/msun, I ran into
> a small issue that I cannot explain at the moment.  If I have
> /usr/bin/ld in my path prior to /usr/local/bin/ld everything
> works
> 
> % which ld
> /usr/bin/ld
> % make clean && make cleandepend
> % make
> 
> and I have a libm.so.5.  But if /usr/local/bin/ld is found, I
> see
> 
> % cd msun
> % make clean && make cleandepend
> % make
> ..
> ld: error: version script assignment of 'FBSD_1.0' to symbol 'fabs' \
>    failed: symbol not defined
> cc: error: linker command failed with exit code 1 (use -v to see invocation)
> *** Error code 1
> 
> Stop.
> make: stopped in /usr/src/lib/msun
> 
> % grep fabs /usr/src/lib/msun/Symbol.map 
>        fabs;
>        fabsf;
>        fabsl;
> 
> But, if one looks in msun/Makefile, one see
> 
> # FreeBSD's C library supplies these functions:
> #COMMON_SRCS+=  s_fabs.c s_frexp.c s_isnan.c s_ldexp.c s_modf.c
> 
> so fabs is not built with libm.  
> 
> % nm --dynamic /lib/libc.so.7 | grep fabs
> 00000000000ba600 T fabs
> % nm --dynamic /lib/libm.so.5 | grep fabs
> 000000000001fa90 T fabsf
> 00000000000252e0 T fabsl
> 
> 
> Is this a known issue?  Should fabs be removed from Symbol.map?

Yes, fabs is excluded in msun's Makefile:

# FreeBSD's C library supplies these functions:
#COMMON_SRCS+=  s_fabs.c s_frexp.c s_isnan.c s_ldexp.c s_modf.c

so it should not have been in Symbol.map at all. The comment is also
incorrect, since s_frexp.c and s_isnan.c *are* actually in COMMON_SRCS,
see lines 79 and 80 of the Makefile. (They are indeed also in libc, so
which one is chosen is only known by the linker. :)

It doesn't complain with lld >= 16 because of
https://cgit.freebsd.org/src/commit/?id=2ba84b4bcdd60, where it add
-Wl,--undefined-version to suppress such warnings. I added that rather
big hammer to be able to continue importing llvm 16, but I see now that
it may be better to attempt to fix all individual failures due to
missing symbols.

The reason that it still goes wrong if you put /usr/local/bin in front
of your PATH (or if you set LD explicitly to /usr/local/bin/ld) is that
/usr/bin/cc will pick /usr/bin/ld over whatever it finds in the PATH or
in the LD variable, while bsd.linker.mk still uses PATH or LD to find
the linker type and version. E.g., it concludes that the linker type is
BFD and the version is 2.40, then does not add the
-Wl,--undefined-version to allow undefined symbols.

I committed https://cgit.freebsd.org/src/commit/?id=d04e03c19a8d to
remove fabs from Symbol.map, and adjust the Makefile comment.

-Dimitry