kit

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

windows-vm.sh (6131B)


      1 #!/usr/bin/env bash
      2 # Windows linked-image strip acceptance. Build hosted PE32+ programs for both
      3 # shipped Windows architectures, preserve their loader imports exactly, and run
      4 # the original/--strip-debug/--strip-all images in the provisioned Windows VM.
      5 
      6 set -uo pipefail
      7 
      8 ROOT=${KIT_TEST_ROOT:-$(cd "$(dirname "$0")/../.." && pwd)}
      9 KIT=${KIT:-"$ROOT/build/kit"}
     10 VM="$ROOT/scripts/windows_vm.sh"
     11 HOST_CC=${KIT_WINDOWS_HOST_CC:-clang}
     12 LLVM_OBJDUMP=${KIT_WINDOWS_LLVM_OBJDUMP:-llvm-objdump}
     13 
     14 KIT_KIT_DIR="$ROOT/test/lib"
     15 . "$ROOT/test/lib/kit_sh_kit.sh"
     16 kit_report_init
     17 kit_require_kit strip-windows-vm
     18 kit_workdir strip-windows-vm
     19 work=$KIT_WORK
     20 
     21 for tool in "$HOST_CC" "$LLVM_OBJDUMP"; do
     22   if ! command -v "$tool" >/dev/null 2>&1; then
     23     kit_fail strip-windows-vm-tools "missing required tool: $tool"
     24     kit_summary strip-windows-vm
     25     kit_exit
     26   fi
     27 done
     28 
     29 sdk_for_arch() {
     30   local arch=$1 token triple candidate
     31   case "$arch" in
     32     x86_64) token=x64; triple=x86_64-w64-mingw32 ;;
     33     aarch64) token=aarch64; triple=aarch64-w64-mingw32 ;;
     34     *) return 1 ;;
     35   esac
     36 
     37   if [ -n "${KIT_SYSROOT:-}" ]; then
     38     for candidate in "$KIT_SYSROOT/$triple" "$KIT_SYSROOT"; do
     39       if [ -r "$candidate/include/windows.h" ] &&
     40          [ -r "$candidate/lib/libucrt.a" ]; then
     41         printf '%s\n' "$candidate"
     42         return 0
     43       fi
     44     done
     45   fi
     46 
     47   candidate=$("$ROOT/scripts/llvm_mingw_sysroot.sh" path "$token" 2>/dev/null) ||
     48     return 1
     49   [ -r "$candidate/include/windows.h" ] &&
     50     [ -r "$candidate/lib/libucrt.a" ] || return 1
     51   printf '%s\n' "$candidate"
     52 }
     53 
     54 import_dump() {
     55   local input=$1 output=$2
     56   "$KIT" objdump -p "$input" |
     57     awk '/^[[:space:]]+DLL Name:/ || /^[[:space:]]+Name:/ {
     58            sub(/^[[:space:]]+/, ""); print
     59          }' > "$output"
     60 }
     61 
     62 section_dump() {
     63   "$LLVM_OBJDUMP" -h "$1" > "$2"
     64 }
     65 
     66 assert_has_debug() {
     67   local label=$1 dump=$2
     68   if grep -E '(^|[[:space:],])\.debug_' "$dump" >/dev/null 2>&1; then
     69     ok "$label"
     70   else
     71     printf 'expected a .debug_* section\n' > "$work/$label.diag"
     72     not_ok "$label" "$work/$label.diag"
     73   fi
     74 }
     75 
     76 assert_no_debug() {
     77   local label=$1 dump=$2
     78   if grep -E '(^|[[:space:],])\.debug_' "$dump" >/dev/null 2>&1; then
     79     grep -E '(^|[[:space:],])\.debug_' "$dump" > "$work/$label.diag"
     80     not_ok "$label" "$work/$label.diag"
     81   else
     82     ok "$label"
     83   fi
     84 }
     85 
     86 run_guest() {
     87   local label=$1 vm_arch=$2 exe=$3
     88   local raw_out="$work/$label.out" raw_err="$work/$label.err"
     89   local norm_out="$work/$label.normalized.out"
     90   local norm_err="$work/$label.normalized.err"
     91 
     92   if "$VM" run "$vm_arch" "$exe" strip-probe > "$raw_out" 2> "$raw_err"; then
     93     ok "$label-status"
     94   else
     95     not_ok "$label-status" "$raw_err"
     96     return
     97   fi
     98 
     99   tr -d '\r' < "$raw_out" > "$norm_out"
    100   tr -d '\r' < "$raw_err" > "$norm_err"
    101   same_file "$label-stdout" "$work/expected.out" "$norm_out"
    102   same_file "$label-stderr" "$work/expected.err" "$norm_err"
    103 }
    104 
    105 printf 'strip-runtime-ok\nstrip-fini-ok\n' > "$work/expected.out"
    106 printf 'strip-signal-ok\n' > "$work/expected.err"
    107 
    108 for arch in x86_64 aarch64; do
    109   case "$arch" in
    110     x86_64)
    111       target=x86_64-w64-windows-gnu
    112       vm_arch=x64
    113       label=x64
    114       builtins_name=libclang_rt.builtins-x86_64.a
    115       ;;
    116     aarch64)
    117       target=aarch64-w64-windows-gnu
    118       vm_arch=aarch64
    119       label=aarch64
    120       builtins_name=libclang_rt.builtins-aarch64.a
    121       ;;
    122   esac
    123 
    124   if ! sdk=$(sdk_for_arch "$arch"); then
    125     kit_fail "$label-sysroot" "missing llvm-mingw UCRT sysroot"
    126     continue
    127   fi
    128   builtins="$sdk/lib/windows/$builtins_name"
    129   if [ ! -r "$builtins" ]; then
    130     kit_fail "$label-builtins" "missing compiler-rt archive: $builtins"
    131     continue
    132   fi
    133 
    134   original="$work/$label-original.exe"
    135   debug="$work/$label-debug.exe"
    136   all="$work/$label-all.exe"
    137 
    138   # Use an independent producer: Kit-linked PE currently carries no linked
    139   # DWARF sections, while clang/lld emits the /<string-table-offset> long names
    140   # used by real llvm-mingw images. Kit remains the sole strip transformer.
    141   run_ok "$label-build" "$HOST_CC" --target="$target" --sysroot="$sdk" \
    142       -fuse-ld=lld -nodefaultlibs -L"$sdk/lib/windows" -O1 -g -gdwarf-4 \
    143       -Wl,--subsystem,console "$ROOT/test/strip/windows_runtime.c" \
    144       -o "$original" \
    145       -lmingw32 "$builtins" -lmoldname -lmingwex -lmsvcrt -ladvapi32 \
    146       -lshell32 -luser32 -lkernel32 -lmingw32 "$builtins" -lmoldname \
    147       -lmingwex -lmsvcrt -lkernel32
    148   [ -f "$original" ] || continue
    149 
    150   run_ok "$label-sections-before" section_dump "$original" \
    151       "$work/$label-sections-before.txt"
    152   assert_has_debug "$label-debug-present-before" \
    153       "$work/$label-sections-before.txt"
    154   run_ok "$label-imports-before" import_dump "$original" \
    155       "$work/$label-imports-before.txt"
    156   contains "$label-import-kernel32" "$work/$label-imports-before.txt" \
    157       "DLL Name: KERNEL32.dll"
    158   contains "$label-import-writefile" "$work/$label-imports-before.txt" \
    159       "Name:     WriteFile"
    160   contains "$label-import-signal" "$work/$label-imports-before.txt" \
    161       "Name:     signal"
    162   contains "$label-import-raise" "$work/$label-imports-before.txt" \
    163       "Name:     raise"
    164   run_ok "$label-strip-debug" "$KIT" strip --strip-debug -o "$debug" \
    165       "$original"
    166   run_ok "$label-strip-all" "$KIT" strip --strip-all -o "$all" "$original"
    167 
    168   for variant in debug all; do
    169     case "$variant" in
    170       debug) image=$debug ;;
    171       all) image=$all ;;
    172     esac
    173     [ -f "$image" ] || continue
    174     run_ok "$label-$variant-sections" section_dump "$image" \
    175         "$work/$label-$variant-sections.txt"
    176     assert_no_debug "$label-$variant-no-debug" \
    177         "$work/$label-$variant-sections.txt"
    178     run_ok "$label-$variant-imports" import_dump "$image" \
    179         "$work/$label-$variant-imports.txt"
    180     same_file "$label-$variant-imports-preserved" \
    181         "$work/$label-imports-before.txt" "$work/$label-$variant-imports.txt"
    182   done
    183 
    184   run_guest "$label-original-run" "$vm_arch" "$original"
    185   [ ! -f "$debug" ] || run_guest "$label-debug-run" "$vm_arch" "$debug"
    186   [ ! -f "$all" ] || run_guest "$label-all-run" "$vm_arch" "$all"
    187 done
    188 
    189 kit_summary strip-windows-vm
    190 kit_exit