Skip to content

Windows: Fix broken GCC ABI compatibility from move to Clang toolchain.

Tamar Christina requested to merge wip/T22166 into master

The move to the clang based toolchain broke the ABI compatibility with GCC produced libraries.

This manifests itself as link failures whenever you have any library produced by GCC in your link.

OK, so there are several things wrong here.

The first one is that:

  1. when we got rid of the wrappers, we didn't provide an alternate way to ensure we load from the inplace libs first. At the moment doing a compile in msys2 will pick the msys2 libraries instead of the ones bundled with the compiler. This will go wrong when the inplace compiler is newer than the msys2 one.
!!! systool:linker: finished in 15.63 milliseconds, allocated 0.120 megabytes
Loading unit ghc-prim-0.9.0 ... linking ... done.
Loading unit ghc-bignum-1.3 ... linking ... done.
Loading unit base-4.17.0.0 ... linking ... done.
Search directories (user):
  C:/tools/msys64/mingw64/x86_64-w64-mingw32/lib/
Search directories (gcc):
  C:/Users/pinky/source/repos/ghc/_build/mingw/lib/clang/13.0.0
  C:/Users/pinky/source/repos/ghc/_build/stage1/lib/../../mingw/x86_64-w64-mingw32/lib
  C:/Users/pinky/source/repos/ghc/_build/stage1/lib/../../mingw/lib
  C:\WINDOWS\system32
Loading object (static archive) C:/tools/msys64/mingw64/x86_64-w64-mingw32/lib/libpthread.dll.a ... done
Loading object (static archive) C:/tools/msys64/mingw64/x86_64-w64-mingw32/lib/libucrt.a ... done
final link ... done

As can be seen, it's loading pthread and ucrt from my "system" rather from inplace/mingw/x86_64-w64-mingw32/lib/libucrt.a. These two files seem to have separate formats.

  1. the loading of advapi32.dll forces a load of msvcrt.dll.
Loading dependency ADVAPI32.dll -> msvcrt.dll.

which is ok as advapi32.dll can depend on whatever runtime it wants. The problem however is since we didn't load ucrt.dll manually in the linker first we end up resolving symbols to msvcrt.dll due to link ordering:

lookupSymbol: symbol '__imp__assert' not found
warning: _assert from msvcrt.dll is linked instead of __imp__assert

etc.

  1. the ucrt that's being loaded is a GNU style import library, which.. we somehow don't detect correctly. The object file that should contain __imp_p_environ is libapi-ms-win-crt-environment-l1-1-0s00000.o. The linker logs show:
loadOc(C:\tools\msys64\mingw64\x86_64-w64-mingw32\lib\libucrt.a(#2496:libapi-ms-win-crt-environment-l1-1-0s00000.o): start
sectab offset = 20
symtab offset = 384
strtab offset = 564

COFF Type:         IMAGE_FILE_HEADER
Machine:           0x8664
# sections:        7
time/date:         0x0
symtab offset:     384
# symbols:         10
sz of opt hdr:     0
characteristics:   0x4
section name = .text (60300020)
addSection: 00007ff7b9c46018-00007ff7b9c46020 (size 8), kind 0
addProddableBlock: 000002282a19e360 00007ff7b9c46018 8
section name = .data (c0300040)
section name = .bss (c0300080)
section name = .idata$7 (c0300000)
addSection: 00007ff7b9c47018-00007ff7b9c4701c (size 4), kind 9
addProddableBlock: 000002282a19e360 00007ff7b9c47018 4
section name = .idata$5 (c0300000)
addSection: 00007ff7b9c4701c-00007ff7b9c47024 (size 8), kind 8
addProddableBlock: 000002282a19e360 00007ff7b9c4701c 8
section name = .idata$4 (c0300000)
addSection: 00007ff7b9c47024-00007ff7b9c4702c (size 8), kind 8
addProddableBlock: 000002282a19e360 00007ff7b9c47024 8
section name = .idata$6 (c0200000)
addSection: 00007ff7b9c4702c-00007ff7b9c4703c (size 16), kind 10
addProddableBlock: 000002282a19e360 00007ff7b9c4702c 16
addSection: 0000000000000000-0000000000000000 (size 0), kind 4

and no symbols are actually loaded from it while:

libapi-ms-win-crt-environment-l1-1-0s00000.o:
0000000000000000 I __imp___p__environ
0000000000000000 T __p__environ
                 U _head_lib64_libapi_ms_win_crt_environment_l1_1_0_a

and

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .text         00000008  0000000000000000  0000000000000000  0000012c  2**2
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  1 .data         00000000  0000000000000000  0000000000000000  00000000  2**2
                  ALLOC, LOAD, DATA
  2 .bss          00000000  0000000000000000  0000000000000000  00000000  2**2
                  ALLOC
  3 .idata$7      00000004  0000000000000000  0000000000000000  00000134  2**2
                  CONTENTS, RELOC
  4 .idata$5      00000008  0000000000000000  0000000000000000  00000138  2**2
                  CONTENTS, RELOC
  5 .idata$4      00000008  0000000000000000  0000000000000000  00000140  2**2
                  CONTENTS, RELOC
  6 .idata$6      00000010  0000000000000000  0000000000000000  00000148  2**1
                  CONTENTS

most of the clang produced import libraries are MSVC style, and our testsuite compiles C code to create the import library. Searching for the output for GNU style import libraries in the linker log finds none. So I suspect that during the clang support work GNU style import libs were broken and since clang doesn't produce GNU style import libs we never noticed.

The one test testing this, was marked broken in #18718 (closed) in likely an attempt to make the CI green, but doing so hid the issue. Because clang is unable to produce BFD style import lib I am forced to include a pre-compiled version of the library in the testsuite.

Lastly, there were still a lot of lingering references to the mingw math library. These are now all in ucrt so these references should be removed.

Fixes #22166 (closed) Fixes #19163

/cc @RyanGlScott

Edited by Tamar Christina

Merge request reports