Page MenuHomeFreeBSD

Add libm dependencies to libgcc_s.so.1 version map
Needs RevisionPublic

Authored by dim on Mar 14 2020, 8:24 PM.
Tags
None
Referenced Files
Unknown Object (File)
Mon, Mar 25, 9:14 PM
Unknown Object (File)
Fri, Mar 15, 11:26 AM
Unknown Object (File)
Wed, Mar 13, 6:38 AM
Unknown Object (File)
Dec 20 2023, 1:22 AM
Unknown Object (File)
Dec 10 2023, 11:16 PM
Unknown Object (File)
Nov 10 2023, 6:59 AM
Unknown Object (File)
Oct 24 2023, 4:01 PM
Unknown Object (File)
Oct 10 2023, 8:03 PM
Subscribers

Details

Summary

In rS307231, @emaste added a few libm functions to libgcc_s.so.1. They
are required because some of compiler-rt's routines contain calls to
them, in particular for complex operations.

However, while the object files are compiled and linked into the shared
library, the functions themselves are *not* visible, due to the symbol
versioning scripts used:

$ readelf -aW libgcc_s.so.1.full | grep -E -w '(fabs|fabsf|fabsl|fmax|fmaxf|fmaxl|logb|logbf|logbl|scalbn|scalbnf|scalbnl)'
     4: 0000000000009da0    99 FUNC    LOCAL  DEFAULT   13 logbf
     5: 0000000000009e10   118 FUNC    LOCAL  DEFAULT   13 logb
     6: 0000000000009e90   106 FUNC    LOCAL  DEFAULT   13 fmaxf
     7: 0000000000009f00   128 FUNC    LOCAL  DEFAULT   13 fmax
     8: 0000000000009f80    30 FUNC    LOCAL  DEFAULT   13 fabsl
     9: 0000000000009fa0    13 FUNC    LOCAL  DEFAULT   13 fabsf
    10: 0000000000009fb0    13 FUNC    LOCAL  DEFAULT   13 fabs
   139: 0000000000010670   142 FUNC    LOCAL  DEFAULT   13 fmaxl
   140: 0000000000010590   212 FUNC    LOCAL  DEFAULT   13 logbl
   141: 0000000000010450   315 FUNC    LOCAL  DEFAULT   13 scalbnl
   144: 0000000000010700   192 FUNC    LOCAL  DEFAULT   13 scalbnf
   148: 00000000000107c0   248 FUNC    LOCAL  DEFAULT   13 scalbn

I noticed the problem, because the LLVM test suite contains a test case
for complex handling from the GCC "torture test":

https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/testsuite/gcc.c-torture/execute/complex-5.c

Attempting to compile and link this fails, with complaints about missing
scalbnf:

$ cc complex-5.c -o complex-5
...
ld: error: undefined symbol: scalbnf
>>> referenced by divsc3.c:26 (/usr/src/contrib/llvm-project/compiler-rt/lib/builtins/divsc3.c:26)
>>>               divsc3.o:(__divsc3) in archive /usr/lib/libgcc.a
>>> referenced by divsc3.c:27 (/usr/src/contrib/llvm-project/compiler-rt/lib/builtins/divsc3.c:27)
>>>               divsc3.o:(__divsc3) in archive /usr/lib/libgcc.a
>>> referenced by divsc3.c:31 (/usr/src/contrib/llvm-project/compiler-rt/lib/builtins/divsc3.c:31)
>>>               divsc3.o:(__divsc3) in archive /usr/lib/libgcc.a
>>> referenced by divsc3.c:33 (/usr/src/contrib/llvm-project/compiler-rt/lib/builtins/divsc3.c:33)
>>>               divsc3.o:(__divsc3) in archive /usr/lib/libgcc.a
cc: error: linker command failed with exit code 1 (use -v to see invocation)

It seems that we must somehow place these math symbols in a version
node, and put global: in front of them.

This is an initial attempt to do so. It adds an FBSD_1.0 version node,
similar to the one used in libm itself, and puts the math symbols in
there. There are two .map files, the first contains the symbols that are
always included, the second the ones that are excluded on arm, mips and
powerpc.

The resulting libgcc_s.so.1 now has the math functions as global
symbols:

$ readelf -aW libgcc_s.so.1.full | grep -E -w '(fabs|fabsf|fabsl|fmax|fmaxf|fmaxl|logb|logbf|logbl|scalbn|scalbnf|scalbnl)'
0000000000019750  0000009100000007 R_X86_64_JUMP_SLOT     00000000000106e0 fmaxl@@FBSD_1.0 + 0
0000000000019758  0000006f00000007 R_X86_64_JUMP_SLOT     0000000000010600 logbl@@FBSD_1.0 + 0
0000000000019760  0000002d00000007 R_X86_64_JUMP_SLOT     00000000000104c0 scalbnl@@FBSD_1.0 + 0
0000000000019768  0000009500000007 R_X86_64_JUMP_SLOT     0000000000010770 scalbnf@@FBSD_1.0 + 0
0000000000019778  0000007a00000007 R_X86_64_JUMP_SLOT     0000000000010830 scalbn@@FBSD_1.0 + 0
    26: 000000000000a020    13 FUNC    GLOBAL DEFAULT   13 fabs@@FBSD_1.0
    45: 00000000000104c0   315 FUNC    GLOBAL DEFAULT   13 scalbnl@@FBSD_1.0
    51: 000000000000a010    13 FUNC    GLOBAL DEFAULT   13 fabsf@@FBSD_1.0
    58: 0000000000009e80   118 FUNC    GLOBAL DEFAULT   13 logb@@FBSD_1.0
    74: 0000000000009ff0    30 FUNC    GLOBAL DEFAULT   13 fabsl@@FBSD_1.0
    78: 0000000000009e10    99 FUNC    GLOBAL DEFAULT   13 logbf@@FBSD_1.0
    84: 0000000000009f70   128 FUNC    GLOBAL DEFAULT   13 fmax@@FBSD_1.0
   111: 0000000000010600   212 FUNC    GLOBAL DEFAULT   13 logbl@@FBSD_1.0
   115: 0000000000009f00   106 FUNC    GLOBAL DEFAULT   13 fmaxf@@FBSD_1.0
   122: 0000000000010830   248 FUNC    GLOBAL DEFAULT   13 scalbn@@FBSD_1.0
   145: 00000000000106e0   142 FUNC    GLOBAL DEFAULT   13 fmaxl@@FBSD_1.0
   149: 0000000000010770   192 FUNC    GLOBAL DEFAULT   13 scalbnf@@FBSD_1.0
   141: 0000000000009e10    99 FUNC    GLOBAL DEFAULT   13 logbf
   142: 0000000000009e80   118 FUNC    GLOBAL DEFAULT   13 logb
   143: 0000000000009f00   106 FUNC    GLOBAL DEFAULT   13 fmaxf
   144: 0000000000009f70   128 FUNC    GLOBAL DEFAULT   13 fmax
   145: 0000000000009ff0    30 FUNC    GLOBAL DEFAULT   13 fabsl
   146: 000000000000a010    13 FUNC    GLOBAL DEFAULT   13 fabsf
   147: 000000000000a020    13 FUNC    GLOBAL DEFAULT   13 fabs
   250: 00000000000106e0   142 FUNC    GLOBAL DEFAULT   13 fmaxl
   251: 0000000000010600   212 FUNC    GLOBAL DEFAULT   13 logbl
   252: 00000000000104c0   315 FUNC    GLOBAL DEFAULT   13 scalbnl
   254: 0000000000010770   192 FUNC    GLOBAL DEFAULT   13 scalbnf
   257: 0000000000010830   248 FUNC    GLOBAL DEFAULT   13 scalbn

And linking the GCC test case against it works now.

Diff Detail

Repository
rS FreeBSD src repository - subversion
Lint
Lint Passed
Unit
No Test Coverage
Build Status
Buildable 29948
Build 27765: arc lint + arc unit

Event Timeline

logbl in libm is FBSD_1.1. Is that, or the other duplication, going to cause problems for programs linking libm?

In D24070#529328, @cem wrote:

logbl in libm is FBSD_1.1.

Ah, I didn't see that. Thanks.

Is that, or the other duplication, going to cause problems for programs linking libm?

It doesn't look like it, at least not when I link the test case involving scalbnf with -lm added on the command line. The resulting executable ends up *without* any NEEDED entry pointing to libgcc_s.so.1, since it is linked using --as-needed -lgcc_s --no-as-needed.

But that said, I am not 100% sure about this solution either. Let's say an executable uses more from libgcc_s than just these symbols, and it gets both libgcc_s.so.1 and libm.so.5 as NEEDED entries. The symbols will contain exactly the same code, but there will be one copy exported from libgcc_s.so.1, the other from libm.so.5. I assume the dynamic linker will sort this out by choosing the first matching symbol it finds? So then it would depend on the order of the NEEDED entries.

dim edited the summary of this revision. (Show Details)

Move the logbl symbol to the FBSD_1.1 version node.

kib requested changes to this revision.Mar 15 2020, 11:31 AM

This is unacceptable. libm symbols must be exported from libm only. libgcc_s should provide unwinder. Patch makes a mess of the ABI.

The compiler support symbols like __divsc3 are private to compiler implementation, should be provided by static libgcc.a and linked into each final object that use them. If anything is needed to implement these support function, then dependencies must be embedded into libgcc.a, in the private namespace (like prefixed with double-underscore).

This revision now requires changes to proceed.Mar 15 2020, 11:31 AM

Hmm, in that case we might as well roll back rS307231 and its follow-ups then, as this will not help. @emaste any ideas? Maybe we could add them to libgcc.a as weak symbols, somehow?

In D24070#529360, @dim wrote:

Hmm, in that case we might as well roll back rS307231 and its follow-ups then, as this will not help. @emaste any ideas? Maybe we could add them to libgcc.a as weak symbols, somehow?

Whatever you add to ligcc.a, needs to be in private namespace which is defined as two underscores for names. Because static linking does not support symbol versioning.