Gold on PowerPC checks/merges long double FP ABI tag across shared libraries

Alan Modra amodra@gmail.com
Sat Dec 14 11:29:00 GMT 2019


On Tue, Dec 10, 2019 at 05:16:03PM +0100, Daniel Kolesa wrote:
> Hello,
> 
> I'm sending this here because I'm not sure how much of an intended
> behavior this is. 
> 
> So, here's the problem: gold on PowerPC (either 32/64/64le) checks
> and merges the FP ABI tag across shared libraries as well as across
> regular object files . This is different from what bfd behaves like,
> which only checks and merges it for actual object files.

This change from 2001 intending to ignore empty relocatable object
files, https://sourceware.org/ml/binutils/2001-01/msg00238.html, is
why the bfd linker ignore shared libraries.  (ELF shared library 
sections are removed by bfd_section_list_clear at bfd/elflink.c:4244.)

I think it very likely that it is entirely accidental that shared
library attributes are ignored by ld.bfd.  This would leave us open to
linking with ABI incompatible libraries.

> I suspect that the bfd behavior is correct here - for one, static
> and shared linking behavior should be the same, and also sometimes
> you need an external shared library compiled with 128-bit FP ABI and
> your application with 64-bit FP ABI and know the symbols won't be
> used.

Actually, I think the bfd behaviour is a bug.  I agree that it is a
problem when a shared library provides some FP functions that you
don't use (and thus might not be extracted from an archive when
linking).  Conversely, if you do use the functions wrongly, it would
be nice to be warned as you would if extracting relocatable object
from an archive.

> Notable cases include the musl libc, which only supports 64-bit long
> double, but libgcc_s.so still needs to be compiled with 128-bit FP
> ABI in order to include the IBM softfp emulation functions for
> TFmode; or, glibc supports both 64-bit and 128-bit long double ABI
> at once and will redirect the symbols depending on what you compile
> your thing with.
> 
> Example:
> 
> $ echo "void foo(long double x) {}" > test.c       
> $ gcc test.c -o test.so -shared -mlong-double-64  
> $ gcc test.c -o test.so -shared -mlong-double-64 -fuse-ld=gold
> /bin/ld.gold: error: /tmp/ccsHdyhv.o uses 64-bit long double, /usr/lib/gcc/powerpc64le-linux-gnu/9.2.0/../../../../lib/libgcc_s.so.1 uses 128-bit long double
> /bin/ld.gold: error: /tmp/ccsHdyhv.o uses 64-bit long double, /usr/lib/libc.so.6 uses 128-bit long double
> collect2: error: ld returned 1 exit status
> $ gcc test.c -o test.so -shared -mlong-double-64 -fuse-ld=gold -static-libgcc
> /bin/ld.gold: error: /tmp/cc3AcDER.o uses 64-bit long double, /usr/lib/libc.so.6 uses 128-bit long double
> collect2: error: ld returned 1 exit status

You do of course have --no-warn-mismatch to silence to warning.

-- 
Alan Modra
Australia Development Lab, IBM



More information about the Binutils mailing list