run.sh (4773B)
1 #!/bin/sh 2 # test/extlink/run.sh — external-linker linkability harness (Type-K mode-P). 3 # 4 # Proves that objects emitted by `kit cc` are consumable by the *system* 5 # linkers, not just kit's own `ld`: LLVM lld in its three personalities 6 # (ld.lld / lld-link / ld64.lld) plus Apple's ld on macOS. One lane per 7 # (object-format, linker); a lane is SKIPPED (never failed) when its linker 8 # or a required SDK is missing, so the suite is portable across CI hosts. 9 # 10 # Regression guard for two fixes: 11 # - COFF: .bss size must live in SizeOfRawData (not VirtualSize), else lld 12 # discards the section -> "relocation against symbol in discarded section". 13 # - Mach-O: kit no longer emits a raw __eh_frame whose FDE pc-begin reloc 14 # ld64 / ld64.lld reject ("UNSIGNED relocation must not be PC-relative"). 15 # 16 # The corpus is two TUs that reference each other across a call and a shared 17 # global (so the link exercises both a branch reloc and a data reloc). 18 19 set -u 20 21 script_dir=$(cd "$(dirname "$0")" && pwd) 22 repo_root=$(cd "$script_dir/../.." && pwd) 23 KIT_KIT_DIR="$repo_root/test/lib" 24 . "$repo_root/test/lib/kit_sh_kit.sh" 25 26 KIT="${KIT:-$repo_root/build/kit}" 27 export KIT 28 kit_require_kit extlink 29 kit_workdir extlink 30 work="$KIT_WORK" 31 kit_report_init 32 33 cat > "$work/a.c" <<'EOF' 34 extern int kx_b(int); 35 int kx_g = 7; 36 int kx_a(void) { return kx_b(kx_g) + kx_g; } 37 EOF 38 cat > "$work/b.c" <<'EOF' 39 extern int kx_g; 40 int kx_b(int x) { return x + kx_g; } 41 EOF 42 43 # compile TARGET EXT : build a.<EXT> and b.<EXT> for TARGET (empty = native). 44 # Returns nonzero (with the diagnostic in cc.err) if kit cc fails. 45 compile() { 46 _t=$1 47 _ext=$2 48 "$KIT" cc ${_t:+-target "$_t"} -O0 -c "$work/a.c" -o "$work/a.$_ext" \ 49 2>"$work/cc.err" && 50 "$KIT" cc ${_t:+-target "$_t"} -O0 -c "$work/b.c" -o "$work/b.$_ext" \ 51 2>>"$work/cc.err" 52 } 53 54 # ---- ELF: ld.lld -------------------------------------------------------- 55 if command -v ld.lld >/dev/null 2>&1; then 56 for t in aarch64-linux x86_64-linux riscv64-linux; do 57 if compile "$t" o; then 58 run_ok "elf-ld.lld-$t" ld.lld -static -no-pie -e kx_a \ 59 -o "$work/$t.elf" "$work/a.o" "$work/b.o" 60 is_executable "elf-ld.lld-$t-exe" "$work/$t.elf" 61 else 62 not_ok "elf-ld.lld-$t" "$work/cc.err" 63 fi 64 done 65 else 66 skip_test "elf-ld.lld" "ld.lld not on PATH" 67 fi 68 69 # ---- COFF: lld-link ----------------------------------------------------- 70 if command -v lld-link >/dev/null 2>&1; then 71 for t in x86_64-windows aarch64-windows; do 72 if compile "$t" obj; then 73 run_ok "coff-lld-link-$t" lld-link /dll /noentry \ 74 /export:kx_a /export:kx_b \ 75 "/out:$work/$t.dll" "$work/a.obj" "$work/b.obj" 76 else 77 not_ok "coff-lld-link-$t" "$work/cc.err" 78 fi 79 done 80 else 81 skip_test "coff-lld-link" "lld-link not on PATH" 82 fi 83 84 # ---- Mach-O: Apple ld + ld64.lld (macOS, Apple Silicon) ----------------- 85 # Needs an SDK (libSystem + crt), so gate on xcrun. x86_64-macOS has a 86 # separate, still-open __text addend-reloc bug, so restrict the native lane 87 # to arm64 hosts (see doc note); link+run a real main() through the clang 88 # driver, exercising the default Apple ld and lld end to end. 89 machos_skip="" 90 if ! command -v xcrun >/dev/null 2>&1; then 91 machos_skip="no macOS SDK (xcrun)" 92 elif [ "$(uname -m 2>/dev/null)" != "arm64" ]; then 93 machos_skip="x86_64-macOS __text reloc fix pending" 94 elif ! command -v clang >/dev/null 2>&1; then 95 machos_skip="clang not on PATH" 96 fi 97 if [ -n "$machos_skip" ]; then 98 skip_test "macho" "$machos_skip" 99 else 100 SDK=$(xcrun --show-sdk-path 2>/dev/null || echo) 101 cat > "$work/m.c" <<'EOF' 102 extern int kx_helper(int); 103 int main(void) { return kx_helper(21); } /* expect exit 42 */ 104 EOF 105 cat > "$work/mh.c" <<'EOF' 106 int kx_g2 = 0; 107 int kx_helper(int x) { kx_g2 = x; return kx_g2 * 2; } 108 EOF 109 if "$KIT" cc -O0 -c "$work/m.c" -o "$work/m.o" 2>"$work/cc.err" && 110 "$KIT" cc -O0 -c "$work/mh.c" -o "$work/mh.o" 2>>"$work/cc.err"; then 111 # Apple ld (clang's default linker). 112 if clang -isysroot "$SDK" -o "$work/m_apple" "$work/m.o" "$work/mh.o" \ 113 2>"$work/apple.err"; then 114 "$work/m_apple" 2>/dev/null 115 if [ $? -eq 42 ]; then ok "macho-apple-ld" 116 else echo "wrong exit code" >"$work/apple.err"; not_ok "macho-apple-ld" "$work/apple.err"; fi 117 else 118 not_ok "macho-apple-ld" "$work/apple.err" 119 fi 120 # ld64.lld. 121 if clang -fuse-ld=lld -isysroot "$SDK" -o "$work/m_lld" \ 122 "$work/m.o" "$work/mh.o" 2>"$work/lld.err"; then 123 "$work/m_lld" 2>/dev/null 124 if [ $? -eq 42 ]; then ok "macho-ld64.lld" 125 else echo "wrong exit code" >"$work/lld.err"; not_ok "macho-ld64.lld" "$work/lld.err"; fi 126 else 127 not_ok "macho-ld64.lld" "$work/lld.err" 128 fi 129 else 130 not_ok "macho-compile" "$work/cc.err" 131 fi 132 fi 133 134 kit_summary extlink 135 kit_exit