kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

windows-ucrt-hosted-smoke.sh (16914B)


      1 #!/usr/bin/env bash
      2 # test/coff/windows-ucrt-hosted-smoke.sh — Type-K (mode P) hosted Windows UCRT
      3 # smoke, on the shared scripted-shell kit (test/lib/kit_sh_kit.sh).
      4 #
      5 # One program per UCRT surface (Sleep, windows.h coverage, runtime, UCRT stdio,
      6 # imported-data, TLS, GUI WinMain) is built with `kit cc` for both
      7 # x86_64-windows and aarch64-windows; the link-level checks inspect the PE
      8 # import directory via `kit objdump -p` (run_ok + contains), and a negative
      9 # check asserts no legacy CRT DLL is imported directly. The Wine runtime check
     10 # is run conditionally and self-skips when podman/Wine are absent.
     11 #
     12 # Serial by design (mode P): all programs share one $work sandbox.
     13 #
     14 # Self-skip: prints SKIP and exits 0 when no llvm-mingw UCRT sysroot is found.
     15 set -u
     16 
     17 ROOT=${KIT_TEST_ROOT:-$(cd "$(dirname "$0")/../.." && pwd)}
     18 KIT=${KIT:-"$ROOT/build/kit"}
     19 SDK=${KIT_SYSROOT:-}
     20 
     21 KIT_KIT_DIR="$ROOT/test/lib"
     22 . "$ROOT/test/lib/kit_sh_kit.sh"
     23 kit_report_init
     24 
     25 LABEL_SUITE=windows-ucrt-hosted-smoke
     26 
     27 find_sdk() {
     28   local arch=$1
     29   local d
     30   for d in \
     31     "${XDG_CACHE_HOME:-$HOME/.cache}"/kit/sysroots/windows/*/ucrt/"$arch"-w64-mingw32 \
     32     "$ROOT"/build/llvm-mingw/*/ucrt/"$arch"-w64-mingw32 \
     33     /tmp/llvm-mingw*/llvm-mingw-*-ucrt-*/"$arch"-w64-mingw32 \
     34     /tmp/llvm-mingw*/"$arch"-w64-mingw32 \
     35     /private/tmp/llvm-mingw*/llvm-mingw-*-ucrt-*/"$arch"-w64-mingw32 \
     36     /private/tmp/llvm-mingw*/"$arch"-w64-mingw32; do
     37     if [ -d "$d/lib" ] && [ -r "$d/include/windows.h" ]; then
     38       printf '%s\n' "$d"
     39       return 0
     40     fi
     41   done
     42   return 1
     43 }
     44 
     45 sdk_for_arch() {
     46   local arch=$1
     47   local base
     48   if [ -n "$SDK" ]; then
     49     if [ "$(basename "$SDK")" = "$arch-w64-mingw32" ]; then
     50       printf '%s\n' "$SDK"
     51       return 0
     52     fi
     53     base=$(dirname "$SDK")
     54     if [ -d "$base/$arch-w64-mingw32/lib" ] &&
     55        [ -r "$base/$arch-w64-mingw32/include/windows.h" ]; then
     56       printf '%s\n' "$base/$arch-w64-mingw32"
     57       return 0
     58     fi
     59   fi
     60   find_sdk "$arch"
     61 }
     62 
     63 # kit presence: was a hard FAIL+exit 1 in the original. Preserve that verdict.
     64 if [ ! -x "$KIT" ]; then
     65   kit_fail "$LABEL_SUITE/kit-present" "kit binary not found: $KIT"
     66   kit_summary "$LABEL_SUITE"
     67   kit_exit
     68 fi
     69 
     70 TMP=${TMPDIR:-/tmp}
     71 work=$(mktemp -d "$TMP/kit-windows-ucrt-smoke.XXXXXX")
     72 WORK_REAL=$(cd "$work" && pwd -P)
     73 trap 'rm -rf "$work"' EXIT
     74 
     75 CONSOLE_C=$work/windows-h.c
     76 HEADER_C=$work/windows-h-coverage.c
     77 RUNTIME_C=$work/runtime.c
     78 STDIO_C=$work/stdio.c
     79 IMPORTDATA_C=$work/import-data.c
     80 GUI_C=$work/gui.c
     81 TLS_C=$work/tls.c
     82 
     83 cat >"$CONSOLE_C" <<'SRC'
     84 #include <windows.h>
     85 int main(void) { Sleep(1); return 0; }
     86 SRC
     87 
     88 cat >"$HEADER_C" <<'SRC'
     89 #include <windows.h>
     90 #include <fileapi.h>
     91 #include <processthreadsapi.h>
     92 #include <synchapi.h>
     93 #include <errhandlingapi.h>
     94 #include <winuser.h>
     95 
     96 _Static_assert(sizeof(long) == 4, "windows long is LLP64");
     97 _Static_assert(sizeof(WCHAR) == 2, "WCHAR is UTF-16");
     98 _Static_assert(sizeof(void*) == 8, "PE32+ pointer size");
     99 
    100 static DWORD WINAPI thread_proc(LPVOID ctx) {
    101   return (DWORD)(ULONG_PTR)ctx;
    102 }
    103 
    104 static BOOL CALLBACK enum_windows_proc(HWND hwnd, LPARAM lparam) {
    105   RECT r;
    106   POINT p;
    107   WINDOWPLACEMENT wp;
    108   ZeroMemory(&wp, sizeof(wp));
    109   wp.length = sizeof(wp);
    110   GetClientRect(hwnd, &r);
    111   p.x = r.left;
    112   p.y = r.top;
    113   ClientToScreen(hwnd, &p);
    114   SetLastError((DWORD)lparam);
    115   return TRUE;
    116 }
    117 
    118 int main(void) {
    119   HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
    120   DWORD wrote = 0;
    121   const char msg[] = "windows coverage\n";
    122   WriteFile(out, msg, sizeof(msg) - 1, &wrote, NULL);
    123 
    124   SECURITY_ATTRIBUTES sa;
    125   ZeroMemory(&sa, sizeof(sa));
    126   sa.nLength = sizeof(sa);
    127   sa.bInheritHandle = FALSE;
    128 
    129   WCHAR tmp_path[MAX_PATH];
    130   WCHAR file_path[MAX_PATH];
    131   GetTempPathW(MAX_PATH, tmp_path);
    132   GetTempFileNameW(tmp_path, L"cfr", 0, file_path);
    133   HANDLE h = CreateFileW(file_path, GENERIC_READ | GENERIC_WRITE, 0, &sa,
    134                          CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL);
    135   if (h != INVALID_HANDLE_VALUE) {
    136     LARGE_INTEGER pos;
    137     pos.QuadPart = 0;
    138     SetFilePointerEx(h, pos, NULL, FILE_BEGIN);
    139     CloseHandle(h);
    140     DeleteFileW(file_path);
    141   }
    142 
    143   CRITICAL_SECTION cs;
    144   InitializeCriticalSection(&cs);
    145   EnterCriticalSection(&cs);
    146   LeaveCriticalSection(&cs);
    147   DeleteCriticalSection(&cs);
    148 
    149   DWORD tid = 0;
    150   HANDLE th = CreateThread(NULL, 0, thread_proc, (LPVOID)(ULONG_PTR)3, 0, &tid);
    151   if (th) {
    152     WaitForSingleObject(th, INFINITE);
    153     CloseHandle(th);
    154   }
    155 
    156   EnumWindows(enum_windows_proc, 0);
    157   MessageBoxW(NULL, L"", L"", MB_OK | MB_SETFOREGROUND);
    158   return 0;
    159 }
    160 SRC
    161 
    162 cat >"$RUNTIME_C" <<'SRC'
    163 #include <windows.h>
    164 #include <stdlib.h>
    165 #include <string.h>
    166 
    167 static int cmp_ints(const void *a, const void *b) {
    168   int ia = *(const int *)a;
    169   int ib = *(const int *)b;
    170   return (ia > ib) - (ia < ib);
    171 }
    172 
    173 static int has_env(char **envp, const char *prefix) {
    174   size_t n = strlen(prefix);
    175   if (!envp) return 0;
    176   for (; *envp; ++envp) {
    177     if (strncmp(*envp, prefix, n) == 0) return 1;
    178   }
    179   return 0;
    180 }
    181 
    182 int main(int argc, char **argv, char **envp) {
    183   if (argc < 3) return 10;
    184   if (strcmp(argv[1], "alpha") != 0 || strcmp(argv[2], "beta") != 0) return 11;
    185   if (!has_env(envp, "KIT_WIN_PROBE=present")) return 12;
    186 
    187   HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
    188   HANDLE err = GetStdHandle(STD_ERROR_HANDLE);
    189   DWORD wrote = 0;
    190   WriteFile(out, "stdout-ok\n", 10, &wrote, 0);
    191   WriteFile(err, "stderr-ok\n", 10, &wrote, 0);
    192 
    193   HANDLE heap = GetProcessHeap();
    194   char *mem = (char *)HeapAlloc(heap, 0, 32);
    195   if (!mem) return 13;
    196   strcpy(mem, "heap-ok");
    197   if (strcmp(mem, "heap-ok") != 0) return 14;
    198   HeapFree(heap, 0, mem);
    199 
    200   int vals[4] = {4, 1, 3, 2};
    201   qsort(vals, 4, sizeof(vals[0]), cmp_ints);
    202   if (vals[0] != 1 || vals[3] != 4) return 15;
    203 
    204   SetLastError(1234);
    205   if (GetLastError() != 1234) return 16;
    206 
    207   char dir[MAX_PATH];
    208   char path[MAX_PATH];
    209   if (!GetTempPathA(MAX_PATH, dir)) return 17;
    210   wsprintfA(path, "%skit-runtime-%lu.tmp", dir,
    211             (unsigned long)GetCurrentProcessId());
    212   HANDLE f = CreateFileA(path, GENERIC_READ | GENERIC_WRITE, 0, 0,
    213                          CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, 0);
    214   if (f == INVALID_HANDLE_VALUE) return 18;
    215   if (!WriteFile(f, "file-ok", 7, &wrote, 0) || wrote != 7) return 19;
    216   SetFilePointer(f, 0, 0, FILE_BEGIN);
    217   char buf[8];
    218   DWORD got = 0;
    219   memset(buf, 0, sizeof(buf));
    220   if (!ReadFile(f, buf, 7, &got, 0)) return 20;
    221   CloseHandle(f);
    222   DeleteFileA(path);
    223   if (got != 7 || strcmp(buf, "file-ok") != 0) return 21;
    224   return 0;
    225 }
    226 SRC
    227 
    228 cat >"$STDIO_C" <<'SRC'
    229 #define _INC_STDIO_S
    230 #include <stdio.h>
    231 
    232 int main(void) {
    233   puts("puts-ok");
    234   fputs("fputs-ok\n", stdout);
    235   printf("printf-ok\n");
    236   fflush(stdout);
    237   return 0;
    238 }
    239 SRC
    240 
    241 cat >"$IMPORTDATA_C" <<'SRC'
    242 #include <windows.h>
    243 
    244 extern char **__dcrt_initial_narrow_environment;
    245 
    246 int main(void) {
    247   HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
    248   DWORD wrote = 0;
    249   WriteFile(out, "importdata\n", 11, &wrote, 0);
    250   if (&__dcrt_initial_narrow_environment == 0) return 10;
    251   if (__dcrt_initial_narrow_environment == 0) return 11;
    252   return 0;
    253 }
    254 SRC
    255 
    256 cat >"$GUI_C" <<'SRC'
    257 #include <windows.h>
    258 int WINAPI WinMain(HINSTANCE hinst, HINSTANCE prev, LPSTR cmd, int show) {
    259   (void)hinst;
    260   (void)prev;
    261   (void)cmd;
    262   (void)show;
    263   return 0;
    264 }
    265 SRC
    266 
    267 cat >"$TLS_C" <<'SRC'
    268 struct tlsdir {
    269   unsigned long long start;
    270   unsigned long long end;
    271   unsigned long long index;
    272   unsigned long long callbacks;
    273   unsigned int zero_fill;
    274   unsigned int characteristics;
    275 };
    276 
    277 extern unsigned char __ImageBase;
    278 extern const struct tlsdir _tls_used;
    279 
    280 _Thread_local int tls_init = 7;
    281 _Thread_local int tls_zero;
    282 
    283 static unsigned int rd32(const unsigned char *p) {
    284   return (unsigned int)p[0] |
    285          ((unsigned int)p[1] << 8) |
    286          ((unsigned int)p[2] << 16) |
    287          ((unsigned int)p[3] << 24);
    288 }
    289 
    290 static int check_tls_directory(void) {
    291   const unsigned char *image = &__ImageBase;
    292   unsigned int pe = rd32(image + 0x3c);
    293   const unsigned char *opt = image + pe + 4 + 20;
    294   const unsigned char *dir = opt + 112 + 9 * 8;
    295   unsigned int tls_rva = rd32(dir);
    296   unsigned int tls_size = rd32(dir + 4);
    297   if (tls_size != 40) return 34;
    298   if ((const unsigned char *)&_tls_used != image + tls_rva) return 35;
    299   if (_tls_used.start == 0 || _tls_used.end <= _tls_used.start) return 36;
    300   if (_tls_used.index == 0) return 37;
    301   if (_tls_used.zero_fill != 0 || _tls_used.characteristics != 0) return 38;
    302   return 0;
    303 }
    304 
    305 static int bump(void) {
    306   tls_zero += 3;
    307   tls_init += tls_zero;
    308   return tls_init;
    309 }
    310 
    311 int main(void) {
    312   int dir = check_tls_directory();
    313   if (dir) return dir;
    314   int a = bump();
    315   int b = bump();
    316   if (a != 10) return 31;
    317   if (b != 16) return 32;
    318   if (tls_zero != 6) return 33;
    319   return 0;
    320 }
    321 SRC
    322 
    323 # ---- assert helpers (mode-P verbs, $work-confined) -------------------------
    324 
    325 # no_legacy_crt_imports NAME DUMP : pass iff DUMP imports no msvcrt/ucrt DLL.
    326 no_legacy_crt_imports() {
    327   local name=$1 dump=$2
    328   if grep -Eiq 'DLL Name: (msvcrt|ucrt)\.dll' "$dump"; then
    329     grep -Ei 'DLL Name: (msvcrt|ucrt)\.dll' "$dump" > "$work/$name.diag"
    330     not_ok "$name" "$work/$name.diag"
    331   else
    332     ok "$name"
    333   fi
    334 }
    335 
    336 # not_contains NAME FILE NEEDLE : pass iff NEEDLE is absent from FILE.
    337 not_contains() {
    338   local name=$1 file=$2 needle=$3
    339   if grep -Fq "$needle" "$file"; then
    340     { printf 'unexpected text: %s\n' "$needle"; } > "$work/$name.diag"
    341     not_ok "$name" "$work/$name.diag"
    342   else
    343     ok "$name"
    344   fi
    345 }
    346 
    347 # matches NAME FILE EREGEX : pass iff FILE has a line matching EREGEX.
    348 matches() {
    349   local name=$1 file=$2 re=$3
    350   if grep -Eq "$re" "$file"; then ok "$name"
    351   else { printf 'no line matched: %s\n' "$re"; } > "$work/$name.diag"; not_ok "$name" "$work/$name.diag"; fi
    352 }
    353 
    354 # run_wine_if_available LABEL IMAGE POD_ARCH EXE [ARGS...] : conditional Wine
    355 # run. Self-skips (kit_skip) when podman or the container image is absent;
    356 # otherwise pass iff the program exits 0 under Wine.
    357 run_wine_if_available() {
    358   local label=$1 image=$2 pod_arch=$3 exe=$4
    359   shift 4
    360   case "$pod_arch" in
    361     amd64)
    362       if [ -n "${KIT_WINDOWS_VM_X64:-${KIT_WINDOWS_VM_AMD64:-}}" ]; then
    363         if KIT_WIN_PROBE=present "$ROOT/scripts/windows_vm.sh" run x64 "$exe" "$@" \
    364             > "$work/$label-vm.out" 2> "$work/$label-vm.err"; then
    365           ok "$label-vm"
    366         else
    367           not_ok "$label-vm" "$work/$label-vm.err"
    368         fi
    369         return 0
    370       fi
    371       ;;
    372     arm64)
    373       if [ -n "${KIT_WINDOWS_VM_AARCH64:-${KIT_WINDOWS_VM_ARM64:-}}" ]; then
    374         if KIT_WIN_PROBE=present "$ROOT/scripts/windows_vm.sh" run aarch64 "$exe" "$@" \
    375             > "$work/$label-vm.out" 2> "$work/$label-vm.err"; then
    376           ok "$label-vm"
    377         else
    378           not_ok "$label-vm" "$work/$label-vm.err"
    379         fi
    380         return 0
    381       fi
    382       ;;
    383   esac
    384   if ! command -v podman >/dev/null 2>&1; then
    385     skip_test "$label-wine" "podman unavailable"
    386     return 0
    387   fi
    388   if ! podman image exists "$image" >/dev/null 2>&1; then
    389     skip_test "$label-wine" "$image unavailable"
    390     return 0
    391   fi
    392   if podman run --rm --arch "$pod_arch" -v "$WORK_REAL:/probe:ro" "$image" \
    393       bash -lc "
    394         export WINEDEBUG=-all WINEPREFIX=/tmp/wineprefix KIT_WIN_PROBE=present
    395         timeout 120s /usr/lib/wine/wine64 /probe/$(basename "$exe") $*
    396         rc=\$?
    397         echo \"$label exit=\$rc\"
    398         test \"\$rc\" -eq 0
    399       " > "$work/$label-wine.out" 2> "$work/$label-wine.err"; then
    400     ok "$label-wine"
    401   else
    402     not_ok "$label-wine" "$work/$label-wine.err"
    403   fi
    404 }
    405 
    406 ran=0
    407 for arch in x86_64 aarch64; do
    408   case "$arch" in
    409     x86_64)
    410       target=x86_64-windows
    411       label=x64
    412       image=localhost/kit-wine-amd64
    413       pod_arch=amd64
    414       ;;
    415     aarch64)
    416       target=aarch64-windows
    417       label=aarch64
    418       image=localhost/kit-wine-arm64
    419       pod_arch=arm64
    420       ;;
    421   esac
    422 
    423   if ! ARCH_SDK=$(sdk_for_arch "$arch"); then
    424     skip_test "$LABEL_SUITE/$label-sysroot" "no $arch llvm-mingw UCRT sysroot"
    425     continue
    426   fi
    427   # Discovered-but-invalid sysroot was a hard FAIL+exit 1 originally.
    428   if [ ! -r "$ARCH_SDK/include/windows.h" ] ||
    429      [ ! -r "$ARCH_SDK/lib/libucrt.a" ]; then
    430     echo "invalid UCRT llvm-mingw sysroot: $ARCH_SDK" > "$work/$label-sysroot.diag"
    431     not_ok "$LABEL_SUITE/$label-sysroot" "$work/$label-sysroot.diag"
    432     kit_summary "$LABEL_SUITE"
    433     kit_exit
    434   fi
    435 
    436   ran=1
    437   CONSOLE_EXE=$work/windows-h-$arch.exe
    438   CONSOLE_DUMP=$work/windows-h-$arch.dump
    439   HEADER_EXE=$work/windows-h-coverage-$arch.exe
    440   HEADER_DUMP=$work/windows-h-coverage-$arch.dump
    441   RUNTIME_EXE=$work/runtime-$arch.exe
    442   RUNTIME_DUMP=$work/runtime-$arch.dump
    443   STDIO_EXE=$work/stdio-$arch.exe
    444   STDIO_DUMP=$work/stdio-$arch.dump
    445   IMPORTDATA_EXE=$work/import-data-$arch.exe
    446   IMPORTDATA_DUMP=$work/import-data-$arch.dump
    447   TLS_EXE=$work/tls-$arch.exe
    448   TLS_DUMP=$work/tls-$arch.dump
    449   GUI_EXE=$work/gui-$arch.exe
    450   GUI_DUMP=$work/gui-$arch.dump
    451 
    452   # build_dump NAME EXE DUMP -- CC_ARGS... : build EXE, then `objdump -p` it
    453   # into DUMP. Returns 0 only if both the EXE and the DUMP were produced, so
    454   # the per-program import asserts below run iff the link round-tripped.
    455   build_dump() {
    456     local bn=$1 exe=$2 dump=$3; shift 3
    457     [ "$1" = "--" ] && shift
    458     run_ok "$bn-build" "$KIT" cc -target "$target" --sysroot "$ARCH_SDK" "$@" -o "$exe"
    459     [ -f "$exe" ] || return 1
    460     run_ok "$bn-objdump" "$KIT" objdump -p "$exe"
    461     [ -s "$work/$bn-objdump.out" ] || return 1
    462     cp "$work/$bn-objdump.out" "$dump"
    463   }
    464 
    465   # ---- console Sleep ----
    466   if build_dump "$label-console" "$CONSOLE_EXE" "$CONSOLE_DUMP" -- -mconsole "$CONSOLE_C"; then
    467     no_legacy_crt_imports "$label-console-no-legacy-crt" "$CONSOLE_DUMP"
    468     not_contains "$label-console-no-weak-set-app-type" "$CONSOLE_DUMP" "Name:     __set_app_type"
    469     contains "$label-console-kernel32" "$CONSOLE_DUMP" "DLL Name: KERNEL32.dll"
    470     contains "$label-console-sleep" "$CONSOLE_DUMP" "Name:     Sleep"
    471     contains "$label-console-crt-runtime-dll" "$CONSOLE_DUMP" "DLL Name: api-ms-win-crt-runtime-l1-1-0.dll"
    472     contains "$label-console-set-app-type" "$CONSOLE_DUMP" "Name:     _set_app_type"
    473     run_wine_if_available "$label-console-Sleep" "$image" "$pod_arch" "$CONSOLE_EXE"
    474   fi
    475 
    476   # ---- windows.h coverage ----
    477   if build_dump "$label-header" "$HEADER_EXE" "$HEADER_DUMP" -- -mconsole "$HEADER_C"; then
    478     no_legacy_crt_imports "$label-header-no-legacy-crt" "$HEADER_DUMP"
    479     contains "$label-header-CreateFileW" "$HEADER_DUMP" "Name:     CreateFileW"
    480     contains "$label-header-CreateThread" "$HEADER_DUMP" "Name:     CreateThread"
    481     contains "$label-header-WaitForSingleObject" "$HEADER_DUMP" "Name:     WaitForSingleObject"
    482     contains "$label-header-MessageBoxW" "$HEADER_DUMP" "Name:     MessageBoxW"
    483   fi
    484 
    485   # ---- runtime ----
    486   if build_dump "$label-runtime" "$RUNTIME_EXE" "$RUNTIME_DUMP" -- "$RUNTIME_C"; then
    487     no_legacy_crt_imports "$label-runtime-no-legacy-crt" "$RUNTIME_DUMP"
    488     contains "$label-runtime-HeapAlloc" "$RUNTIME_DUMP" "Name:     HeapAlloc"
    489     contains "$label-runtime-CreateFileA" "$RUNTIME_DUMP" "Name:     CreateFileA"
    490     contains "$label-runtime-qsort" "$RUNTIME_DUMP" "Name:     qsort"
    491     run_wine_if_available "$label-runtime" "$image" "$pod_arch" "$RUNTIME_EXE" alpha beta
    492   fi
    493 
    494   # ---- UCRT stdio ----
    495   if build_dump "$label-stdio" "$STDIO_EXE" "$STDIO_DUMP" -- "$STDIO_C"; then
    496     no_legacy_crt_imports "$label-stdio-no-legacy-crt" "$STDIO_DUMP"
    497     contains "$label-stdio-crt-stdio-dll" "$STDIO_DUMP" "DLL Name: api-ms-win-crt-stdio-l1-1-0.dll"
    498     contains "$label-stdio-fflush" "$STDIO_DUMP" "Name:     fflush"
    499     run_wine_if_available "$label-UCRT-stdio" "$image" "$pod_arch" "$STDIO_EXE"
    500   fi
    501 
    502   # ---- imported-data ----
    503   if build_dump "$label-importdata" "$IMPORTDATA_EXE" "$IMPORTDATA_DUMP" -- "$IMPORTDATA_C"; then
    504     no_legacy_crt_imports "$label-importdata-no-legacy-crt" "$IMPORTDATA_DUMP"
    505     contains "$label-importdata-crt-private-dll" "$IMPORTDATA_DUMP" "DLL Name: api-ms-win-crt-private-l1-1-0.dll"
    506     contains "$label-importdata-dcrt-env" "$IMPORTDATA_DUMP" "Name:     __dcrt_initial_narrow_environment"
    507     run_wine_if_available "$label-imported-data" "$image" "$pod_arch" "$IMPORTDATA_EXE"
    508   fi
    509 
    510   # ---- TLS ----
    511   if build_dump "$label-tls" "$TLS_EXE" "$TLS_DUMP" -- "$TLS_C"; then
    512     no_legacy_crt_imports "$label-tls-no-legacy-crt" "$TLS_DUMP"
    513     matches "$label-tls-directory" "$TLS_DUMP" \
    514       '^[[:space:]]*9[[:space:]]+TLS[[:space:]]+0x[0-9a-fA-F]+[[:space:]]+0x00000028'
    515   fi
    516 
    517   # ---- GUI WinMain ----
    518   if build_dump "$label-gui" "$GUI_EXE" "$GUI_DUMP" -- -mwindows "$GUI_C"; then
    519     contains "$label-gui-subsystem" "$GUI_DUMP" "Subsystem:           2  (WINDOWS_GUI)"
    520     no_legacy_crt_imports "$label-gui-no-legacy-crt" "$GUI_DUMP"
    521   fi
    522 
    523   run_wine_if_available "$label-TLS" "$image" "$pod_arch" "$TLS_EXE"
    524 done
    525 
    526 if [ "$ran" -eq 0 ]; then
    527   skip_test "$LABEL_SUITE" "set KIT_SYSROOT or install llvm-mingw UCRT under /tmp/llvm-mingw*"
    528 fi
    529 
    530 kit_summary "$LABEL_SUITE"
    531 kit_exit