Improve robustness of handling of libgcc symbols
One issue that has been a consistent thorn in our side has been the interaction between libgcc
/compiler-rt
and the RTS linker. These libraries are used by the C toolchain to provide a variety of out-of-line operations (e.g. 64-bit arithmetic on 32-bit platforms, various atomic operations, etc). cc
would typically add an implicit dependency on one of these libraries during the final link to produce an executable.
However, the RTS linker is able to link objects which have not undergone a final link. To ensure that symbols provided by libgcc
can be resolved, we maintain a static list of symbols, rts/linker/RtsSymbols.c
, which are added to the RTS linker's initial symbol table. These symbols resolve to the definitions provided by the libgcc
which the compiler itself is linked against. While this approach is fairly simple, it is a maintenance nightmare: the list is manually maintained to match the exports of libgcc
, which is both quite unstable and platform-dependent. Consequently, the RtsSymbols list only contains a subset of the symbols which users might need, which has lead to rather painful problems for end users (e.g. https://github.com/haskell/text/issues/450 and the issues related to this ticket).
To work around such issues, some users have been tempted to add libgcc
explicitly to their extra-libraries:
lists. However, this is platform-dependent and causes quite a few knock-on problems (e.g. #21196 (closed)).
We need to revisit this approach. I think that ultimately we need to generate the exported symbol list by probing the system compiler's runtime. Doing this in a reasonably platform-independent is not easy, but I don't see a better alternative.