commit 1efa2147dd0ec3bd57642a4c5b232dd9939ef80e
parent 4548dddafb2cc83dc09923a26c7780f25ad2222f
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Thu, 16 Jul 2026 10:45:54 -0700
test: close hosted target and RISC-V audit gates
Diffstat:
10 files changed, 566 insertions(+), 15 deletions(-)
diff --git a/mk/test.mk b/mk/test.mk
@@ -71,6 +71,8 @@ TEST_TARGETS = \
test-driver-cpio \
test-driver-cas \
test-driver-cc \
+ test-driver-targets \
+ test-driver-native-macos-sdk \
test-driver-stack-protector \
test-driver-help \
test-driver-build \
@@ -109,6 +111,8 @@ TEST_TARGETS = \
test-libc-musl \
test-libc-musl-rv64 \
test-link \
+ test-link-compat \
+ test-link-riscv-flags \
test-link-reloc-uleb128 \
test-link-reloc-desc \
test-link-reloc-apply \
@@ -334,7 +338,7 @@ test-images:
test-cf-corpus-selftest:
@bash test/lib/kit_corpus_selftest.sh
-test-driver: test-driver-help test-driver-cc test-driver-stack-protector test-driver-build test-driver-build-coord test-driver-ar test-driver-cpio test-driver-cas test-driver-strip test-driver-objcopy test-driver-objdump test-driver-pkg test-driver-strings test-driver-tools test-driver-diagnostics test-driver-wasm
+test-driver: test-driver-help test-driver-cc test-driver-targets test-driver-native-macos-sdk test-driver-stack-protector test-driver-build test-driver-build-coord test-driver-ar test-driver-cpio test-driver-cas test-driver-strip test-driver-objcopy test-driver-objdump test-driver-pkg test-driver-strings test-driver-tools test-driver-diagnostics test-driver-wasm
test-driver-help: bin
@KIT=$(abspath $(BIN)) sh test/driver/help_uniform.sh
@@ -342,6 +346,12 @@ test-driver-help: bin
test-driver-cc: bin
@KIT=$(abspath $(BIN)) sh test/driver/run.sh
+test-driver-targets: bin
+ @KIT=$(abspath $(BIN)) sh test/driver/targets.sh
+
+test-driver-native-macos-sdk: bin
+ @KIT=$(abspath $(BIN)) sh test/driver/native_macos_sdk.sh
+
test-driver-stack-protector: bin
@KIT=$(abspath $(BIN)) sh test/driver/stack_protector.sh
@@ -1056,10 +1066,18 @@ test-coff-windows-vm: bin rt-x86_64-pc-windows rt-aarch64-windows windows-ucrt-s
# The parse/asm/macho harnesses select a cross-target via KIT_TEST_ARCH
# (default aa64); the link rt dependency is resolved through the shared
# _TEST_RT_<arch> map defined above (near test-rt-runtime).
-test-link: lib $(ROUNDTRIP_BIN) $(ROUNDTRIP_BIN_MACHO) $(LINK_EXE_RUNNER) \
+test-link-compat: bin $(LINK_COMPAT_TEST_BIN)
+ $(LINK_COMPAT_TEST_BIN)
+ KIT=$(abspath $(BIN)) sh test/link/compat-driver.sh
+
+test-link-riscv-flags: bin
+ KIT=$(abspath $(BIN)) sh test/link/riscv-flags.sh
+
+test-link: bin $(ROUNDTRIP_BIN) $(ROUNDTRIP_BIN_MACHO) $(LINK_EXE_RUNNER) \
$(JIT_RUNNER) $(LINK_SCRIPT_TEST_BIN) $(LINK_COMPAT_TEST_BIN)
$(LINK_SCRIPT_TEST_BIN)
$(LINK_COMPAT_TEST_BIN)
+ KIT=$(abspath $(BIN)) sh test/link/compat-driver.sh
bash test/link/run.sh
# x64 ELF link/reloc-application coverage. test-link defaults to aa64, so
diff --git a/test/api/target_test.c b/test/api/target_test.c
@@ -297,6 +297,20 @@ static void check_target_profile_registry(void) {
"registry distinguishes Linux libc profiles");
EXPECT(kit_target_profile_lookup("wasm32-wasi") != NULL,
"compiled-in Wasm profile is registered");
+ EXPECT((kit_target_profile_lookup("linux-glibc-aa64")->capabilities &
+ KIT_TARGET_CAP_SHARED) != 0 &&
+ (kit_target_profile_lookup("android-aa64")->capabilities &
+ KIT_TARGET_CAP_SHARED) != 0,
+ "ELF hosted profiles advertise shipped shared linking");
+ EXPECT((kit_target_profile_lookup("windows-aa64")->capabilities &
+ KIT_TARGET_CAP_SHARED) == 0 &&
+ (kit_target_profile_lookup("windows-x64")->capabilities &
+ KIT_TARGET_CAP_SHARED) == 0 &&
+ (kit_target_profile_lookup("macos-aa64")->capabilities &
+ KIT_TARGET_CAP_SHARED) == 0 &&
+ (kit_target_profile_lookup("macos-x64")->capabilities &
+ KIT_TARGET_CAP_SHARED) == 0,
+ "Mach-O/COFF profiles do not advertise rejected shared output");
EXPECT(kit_target_profile_lookup("definitely-not-a-target") == NULL,
"unknown profile is absent");
EXPECT(KIT_TARGET_PROFILE_REGISTRY_VERSION == 1u,
diff --git a/test/audit/release/modules/standalone.sh b/test/audit/release/modules/standalone.sh
@@ -171,6 +171,51 @@ audit_standalone_support_discovery() {
audit_expect_exit 0
audit_expect_stderr_empty
fi
+
+ # An explicit bad root is authoritative even though the copied release has
+ # a valid sibling support tree.
+ audit_case_step_exec invalid-explicit-support \
+ "$AUDIT_STANDALONE_RELOC/bin/kit" cc \
+ --support-dir "$CASE_DIR/work/missing support" \
+ -c "$AUDIT_STANDALONE_SOURCE_DIR/native sdk malloc.c" \
+ -o "$CASE_DIR/artifacts/invalid-explicit.o"
+ audit_expect_exit 1
+ audit_expect_stderr_nonempty
+ if grep -F -q "support dir not found" "$CASE_ACTIVE_DIR/stderr"; then
+ audit_check_pass "invalid explicit support root is diagnosed"
+ else
+ audit_check_fail "invalid explicit support root diagnostic is missing"
+ fi
+ if [ ! -e "$CASE_DIR/artifacts/invalid-explicit.o" ]; then
+ audit_check_pass "invalid explicit support root produced no output"
+ else
+ audit_check_fail "invalid explicit support root produced output"
+ fi
+
+ # Put otherwise-valid support layouts in the invocation cwd, but run an
+ # orphaned binary whose executable-relative candidates are both absent.
+ # Canonical discovery must fail rather than revive the removed cwd/source-
+ # checkout fallbacks.
+ mkdir -p "$CASE_DIR/work/orphan/bin"
+ cp "$AUDIT_STANDALONE_RELOC/bin/kit" "$CASE_DIR/work/orphan/bin/kit"
+ ln -s "$AUDIT_STANDALONE_RELOC/support" "$CASE_DIR/work/support"
+ ln -s "$AUDIT_STANDALONE_RELOC/support/rt" "$CASE_DIR/work/rt"
+ audit_case_step_exec no-cwd-fallback "$CASE_DIR/work/orphan/bin/kit" cc \
+ -c "$AUDIT_STANDALONE_SOURCE_DIR/native sdk malloc.c" \
+ -o "$CASE_DIR/artifacts/orphan.o"
+ audit_expect_exit 1
+ audit_expect_stderr_nonempty
+ if grep -F -q "support dir not found" "$CASE_ACTIVE_DIR/stderr"; then
+ audit_check_pass "orphaned binary ignores cwd support/source trees"
+ else
+ audit_check_fail "orphaned binary used cwd support/source fallback"
+ fi
+ if [ ! -e "$CASE_DIR/artifacts/orphan.o" ]; then
+ audit_check_pass "orphaned binary produced no output"
+ else
+ audit_check_fail "orphaned binary unexpectedly produced output"
+ fi
+
audit_expect_file_empty "$CASE_DIR/artifacts/sentinel.log"
audit_case_finish
}
diff --git a/test/cross/cases/native_activity.c b/test/cross/cases/native_activity.c
@@ -1,6 +1,15 @@
#include <android/native_activity.h>
#include <stddef.h>
+#ifndef __ANDROID_API__
+#error "Android hosted profile must define __ANDROID_API__"
+#endif
+#ifdef KIT_EXPECT_ANDROID_API
+#if __ANDROID_API__ != KIT_EXPECT_ANDROID_API
+#error "Android hosted profile selected the wrong API level"
+#endif
+#endif
+
void ANativeActivity_onCreate(ANativeActivity* activity, void* saved_state,
size_t saved_state_size) {
(void)saved_state;
diff --git a/test/driver/native_macos_sdk.sh b/test/driver/native_macos_sdk.sh
@@ -0,0 +1,165 @@
+#!/bin/sh
+# Native macOS hosted-SDK policy and precedence acceptance (KIT-P0-002).
+
+set -u
+
+script_dir=$(CDPATH= cd -- "$(dirname "$0")" && pwd)
+repo_root=$(CDPATH= cd -- "$script_dir/../.." && pwd)
+KIT=${KIT:-$repo_root/build/kit}
+KIT_KIT_DIR=$repo_root/test/lib
+. "$repo_root/test/lib/kit_sh_kit.sh"
+
+kit_require_kit native-macos-sdk
+kit_report_init
+kit_workdir native-macos-sdk
+work=$KIT_WORK
+
+if [ "$(uname -s 2>/dev/null || printf unknown)" != Darwin ]; then
+ skip_test native-macos-sdk "requires a Darwin host with a macOS SDK"
+ kit_summary native-macos-sdk
+ kit_exit
+fi
+
+mkdir -p "$work/sentinel-bin"
+cat > "$work/sentinel-bin/xcrun" <<'EOF'
+#!/bin/sh
+printf 'xcrun invoked: %s\n' "$*" >> "$KIT_XCRUN_SENTINEL_LOG"
+exit 99
+EOF
+chmod +x "$work/sentinel-bin/xcrun"
+: > "$work/xcrun.log"
+isolated_path=$work/sentinel-bin:/usr/bin:/bin
+
+cat > "$work/hosted.c" <<'EOF'
+#include <stdlib.h>
+#ifndef __APPLE__
+#error native macOS hosted predefines are missing
+#endif
+int kit_native_sdk_marker = 2026060;
+int main(void) {
+ void *p = malloc(8);
+ if (!p) return 1;
+ free(p);
+ return 0;
+}
+EOF
+cat > "$work/freestanding.c" <<'EOF'
+int kit_freestanding_probe(void) { return 0; }
+EOF
+cat > "$work/start.c" <<'EOF'
+void _start(void) {}
+EOF
+
+run_ok print-internal /usr/bin/env -u KIT_SYSROOT \
+ PATH="$isolated_path" KIT_XCRUN_SENTINEL_LOG="$work/xcrun.log" \
+ "$KIT" cc -print-sysroot
+internal_sdk=$(sed -n '1p' "$work/print-internal.out")
+if [ -n "$internal_sdk" ] && [ -d "$internal_sdk" ]; then
+ ok internal-sdk-exists
+else
+ printf 'reported SDK: %s\n' "$internal_sdk" > "$work/internal-sdk.diag"
+ not_ok internal-sdk-exists "$work/internal-sdk.diag"
+fi
+
+run_ok print-env /usr/bin/env KIT_SYSROOT="$internal_sdk" \
+ PATH="$isolated_path" KIT_XCRUN_SENTINEL_LOG="$work/xcrun.log" \
+ "$KIT" cc -print-sysroot
+if [ "$(sed -n '1p' "$work/print-env.out")" = "$internal_sdk" ]; then
+ ok env-sysroot-precedence
+else
+ not_ok env-sysroot-precedence "$work/print-env.out"
+fi
+
+explicit_sdk="$work/Explicit SDK With Spaces"
+ln -s "$internal_sdk" "$explicit_sdk"
+run_ok print-explicit /usr/bin/env KIT_SYSROOT="$internal_sdk" \
+ PATH="$isolated_path" KIT_XCRUN_SENTINEL_LOG="$work/xcrun.log" \
+ "$KIT" cc --sysroot "$explicit_sdk" -print-sysroot
+if [ "$(sed -n '1p' "$work/print-explicit.out")" = "$explicit_sdk" ]; then
+ ok explicit-sysroot-wins
+else
+ not_ok explicit-sysroot-wins "$work/print-explicit.out"
+fi
+run_ok explicit-root-compile-link /usr/bin/env KIT_SYSROOT="$internal_sdk" \
+ PATH="$isolated_path" KIT_XCRUN_SENTINEL_LOG="$work/xcrun.log" \
+ "$KIT" cc --sysroot "$explicit_sdk" "$work/hosted.c" \
+ -o "$work/explicit-root-program"
+run_ok explicit-root-run "$work/explicit-root-program"
+
+run_fail invalid-explicit-no-fallback /usr/bin/env KIT_SYSROOT="$internal_sdk" \
+ PATH="$isolated_path" KIT_XCRUN_SENTINEL_LOG="$work/xcrun.log" \
+ "$KIT" cc --sysroot "$work/missing-sdk" -print-sysroot
+contains invalid-explicit-diagnostic "$work/invalid-explicit-no-fallback.err" \
+ "sysroot not found: $work/missing-sdk"
+
+for row in 'aa64 aarch64-apple-darwin' 'x64 x86_64-apple-darwin'; do
+ set -- $row
+ tag=$1
+ target=$2
+ common_env="PATH=$isolated_path"
+ : "$common_env"
+
+ run_ok "$tag-cc" /usr/bin/env -u KIT_SYSROOT \
+ PATH="$isolated_path" KIT_XCRUN_SENTINEL_LOG="$work/xcrun.log" \
+ "$KIT" cc -target "$target" "$work/hosted.c" \
+ -o "$work/$tag-cc-program"
+ run_ok "$tag-check" /usr/bin/env -u KIT_SYSROOT \
+ PATH="$isolated_path" KIT_XCRUN_SENTINEL_LOG="$work/xcrun.log" \
+ "$KIT" check -target "$target" "$work/hosted.c"
+ run_ok "$tag-cpp" /usr/bin/env -u KIT_SYSROOT \
+ PATH="$isolated_path" KIT_XCRUN_SENTINEL_LOG="$work/xcrun.log" \
+ "$KIT" cpp -target "$target" "$work/hosted.c" \
+ -o "$work/$tag-hosted.i"
+ contains "$tag-cpp-marker" "$work/$tag-hosted.i" \
+ "kit_native_sdk_marker"
+ run_ok "$tag-build-obj" /usr/bin/env -u KIT_SYSROOT \
+ PATH="$isolated_path" KIT_XCRUN_SENTINEL_LOG="$work/xcrun.log" \
+ "$KIT" build-obj -target "$target" "$work/hosted.c" \
+ -o "$work/$tag-build.o"
+ run_ok "$tag-build-lib" /usr/bin/env -u KIT_SYSROOT \
+ PATH="$isolated_path" KIT_XCRUN_SENTINEL_LOG="$work/xcrun.log" \
+ "$KIT" build-lib -target "$target" "$work/hosted.c" \
+ -o "$work/lib$tag.a"
+ run_ok "$tag-build-exe" /usr/bin/env -u KIT_SYSROOT \
+ PATH="$isolated_path" KIT_XCRUN_SENTINEL_LOG="$work/xcrun.log" \
+ "$KIT" build-exe -target "$target" "$work/hosted.c" \
+ -o "$work/$tag-build-program"
+done
+
+run_ok native-cc-run "$work/aa64-cc-program"
+run_ok native-build-exe-run "$work/aa64-build-program"
+
+# Both freestanding opt-outs must avoid SDK resolution even when KIT_SYSROOT
+# is an invalid authoritative value.
+run_ok freestanding-opt-out /usr/bin/env KIT_SYSROOT="$work/missing-sdk" \
+ PATH="$isolated_path" KIT_XCRUN_SENTINEL_LOG="$work/xcrun.log" \
+ "$KIT" cc -target aarch64-apple-darwin -ffreestanding -nostdinc \
+ -c "$work/freestanding.c" -o "$work/freestanding.o"
+
+run_ok direct-ld-object /usr/bin/env -u KIT_SYSROOT \
+ PATH="$isolated_path" KIT_XCRUN_SENTINEL_LOG="$work/xcrun.log" \
+ "$KIT" cc -target aarch64-apple-darwin -ffreestanding -nostdinc \
+ -c "$work/start.c" -o "$work/start.o"
+run_ok direct-ld-unhosted /usr/bin/env KIT_SYSROOT="$work/missing-sdk" \
+ PATH="$isolated_path" KIT_XCRUN_SENTINEL_LOG="$work/xcrun.log" \
+ "$KIT" ld -e _start "$work/start.o" -o "$work/direct-ld"
+run_fail direct-ld-hosted-needs-sdk /usr/bin/env \
+ KIT_SYSROOT="$work/missing-sdk" PATH="$isolated_path" \
+ KIT_XCRUN_SENTINEL_LOG="$work/xcrun.log" \
+ "$KIT" ld -lc -e _start "$work/start.o" -o "$work/direct-ld-hosted"
+contains direct-ld-hosted-sdk-diagnostic \
+ "$work/direct-ld-hosted-needs-sdk.err" "sysroot not found"
+
+run_fail cross-os-does-not-borrow-sdk /usr/bin/env -u KIT_SYSROOT \
+ PATH="$isolated_path" KIT_XCRUN_SENTINEL_LOG="$work/xcrun.log" \
+ "$KIT" cc -target aarch64-linux-gnu -lc "$work/hosted.c" \
+ -o "$work/cross-linux"
+
+if [ ! -s "$work/xcrun.log" ]; then
+ ok no-xcrun-dependency
+else
+ not_ok no-xcrun-dependency "$work/xcrun.log"
+fi
+
+kit_summary native-macos-sdk
+kit_exit
diff --git a/test/driver/run.sh b/test/driver/run.sh
@@ -504,6 +504,7 @@ fi
# (independent of a native SDK). The Linux expansion uses the standard FHS
# sysroot layout: libc/kernel headers under <sysroot>/usr/include (plus the
# glibc multiarch subdir) and libraries under <sysroot>/usr/lib.
+mkdir -p "$work/sr"
if KIT_SYSROOT="$work/sr" "$KIT" cc -print-search-dirs -lc -target x86_64-linux \
> "$work/cc-searchdirs.out" 2> "$work/cc-searchdirs.err" &&
grep -q "$work/sr/usr/lib" "$work/cc-searchdirs.out" &&
@@ -516,11 +517,12 @@ else
fi
# ---- cc -print-sysroot echoes the effective explicit sysroot ----
-if [ "$("$KIT" cc -print-sysroot --sysroot /opt/sdkx 2>/dev/null)" = "/opt/sdkx" ] &&
- [ "$(KIT_SYSROOT=/opt/sdky "$KIT" cc -print-sysroot 2>/dev/null)" = "/opt/sdky" ]; then
+mkdir -p "$work/sdkx" "$work/sdky"
+if [ "$("$KIT" cc -print-sysroot --sysroot "$work/sdkx" 2>/dev/null)" = "$work/sdkx" ] &&
+ [ "$(KIT_SYSROOT="$work/sdky" "$KIT" cc -print-sysroot 2>/dev/null)" = "$work/sdky" ]; then
ok "cc-print-sysroot"
else
- "$KIT" cc -print-sysroot --sysroot /opt/sdkx > "$work/cc-psysroot.diag" 2>&1
+ "$KIT" cc -print-sysroot --sysroot "$work/sdkx" > "$work/cc-psysroot.diag" 2>&1
not_ok "cc-print-sysroot" "$work/cc-psysroot.diag"
fi
diff --git a/test/driver/targets.sh b/test/driver/targets.sh
@@ -0,0 +1,105 @@
+#!/bin/sh
+# Public target-profile registry and `kit targets` acceptance (KIT-P1-001).
+
+set -u
+
+script_dir=$(CDPATH= cd -- "$(dirname "$0")" && pwd)
+repo_root=$(CDPATH= cd -- "$script_dir/../.." && pwd)
+KIT=${KIT:-$repo_root/build/kit}
+KIT_KIT_DIR=$repo_root/test/lib
+. "$repo_root/test/lib/kit_sh_kit.sh"
+
+kit_require_kit driver-targets
+kit_report_init
+kit_workdir driver-targets
+work=$KIT_WORK
+
+audited='linux-glibc-aa64 linux-glibc-x64 linux-glibc-rv64
+linux-musl-aa64 linux-musl-x64 linux-musl-rv64
+freebsd-aa64 freebsd-x64 freebsd-rv64
+windows-aa64 windows-x64 android-aa64 macos-aa64 macos-x64
+freestanding-aa64 freestanding-x64 freestanding-rv64 freestanding-rv32
+freestanding-arm32'
+
+run_ok tsv "$KIT" targets --format=tsv
+if awk -F '\t' '
+ NR == 1 { if ($0 != "# kit-targets-v1") exit 1; next }
+ NR == 2 {
+ if ($0 != "selector\ttriple\tarch\tos\tobject\thosted\tlibc\tsysroot\tcapabilities\tprovisioning") exit 1
+ next
+ }
+ NF != 10 { exit 1 }
+ { if (seen[$1]++) exit 1; records++ }
+ END { if (records < 19) exit 1 }
+ ' "$work/tsv.out"; then
+ ok tsv-schema-and-unique-records
+else
+ not_ok tsv-schema-and-unique-records "$work/tsv.out"
+fi
+
+for selector in $audited; do
+ if awk -F '\t' -v want="$selector" '$1 == want { found = 1 }
+ END { exit found ? 0 : 1 }' "$work/tsv.out"; then
+ ok "registry-$selector"
+ else
+ not_ok "registry-$selector" "$work/tsv.out"
+ fi
+done
+
+if awk -F '\t' '$1 == "wasm32-wasi" { wasi = 1 }
+ $1 == "wasm32-freestanding" { bare = 1 }
+ END { exit wasi && bare ? 0 : 1 }' "$work/tsv.out"; then
+ ok registry-compiled-wasm-extras
+else
+ not_ok registry-compiled-wasm-extras "$work/tsv.out"
+fi
+
+if awk -F '\t' '
+ NR <= 2 { next }
+ $1 ~ /^(windows|macos|ios)/ && ("," $9 ",") ~ /,shared,/ { exit 1 }
+ $1 ~ /^(linux-(glibc|musl)|freebsd)-/ &&
+ ("," $9 ",") !~ /,shared,/ { exit 1 }
+ $1 == "android-aa64" && ("," $9 ",") !~ /,shared,/ { exit 1 }
+ ' "$work/tsv.out"; then
+ ok registry-shared-capability-matches-driver
+else
+ not_ok registry-shared-capability-matches-driver "$work/tsv.out"
+fi
+
+run_ok triples "$KIT" targets --format=triple
+if awk -F '\t' 'NR > 2 { print $2 }' "$work/tsv.out" |
+ cmp -s - "$work/triples.out"; then
+ ok triple-format-matches-registry
+else
+ not_ok triple-format-matches-registry "$work/triples.out"
+fi
+
+run_ok human "$KIT" targets
+contains human-header "$work/human.out" "CAPABILITIES [PROVISION]"
+contains human-separates-provisioning "$work/human.out" "[sysroot]"
+
+run_ok detail-selector "$KIT" targets linux-glibc-aa64
+run_ok detail-triple "$KIT" targets aarch64-linux-gnu
+same_file detail-selector-and-triple \
+ "$work/detail-selector.out" "$work/detail-triple.out"
+for field in architecture os object-format pointer hosted-model libc-model \
+ sysroot-model capabilities provisioning; do
+ contains "detail-$field" "$work/detail-selector.out" "$field:"
+done
+
+run_ok hosted-list /usr/bin/env KIT="$KIT" "$repo_root/scripts/hosted.sh" list
+if [ "$(wc -l < "$work/hosted-list.out" | tr -d ' ')" -eq 19 ]; then
+ ok hosted-list-count
+else
+ not_ok hosted-list-count "$work/hosted-list.out"
+fi
+for selector in $audited; do
+ if grep -Fx "$selector" "$work/hosted-list.out" >/dev/null 2>&1; then
+ ok "hosted-list-$selector"
+ else
+ not_ok "hosted-list-$selector" "$work/hosted-list.out"
+ fi
+done
+
+kit_summary driver-targets
+kit_exit
diff --git a/test/link/compat-driver.sh b/test/link/compat-driver.sh
@@ -0,0 +1,67 @@
+#!/bin/sh
+# Driver-side target selection checks for the public link-session
+# compatibility boundary (KIT-P0-004). The C unit covers raw bytes,
+# in-memory builders, archives, and DSO inputs for ELF/Mach-O/COFF; this
+# focused shell layer pins explicit -target authority and implicit first-input
+# inference in `kit ld`.
+
+set -u
+
+script_dir=$(CDPATH= cd -- "$(dirname "$0")" && pwd)
+repo_root=$(CDPATH= cd -- "$script_dir/../.." && pwd)
+KIT=${KIT:-$repo_root/build/kit}
+KIT_KIT_DIR=$repo_root/test/lib
+. "$repo_root/test/lib/kit_sh_kit.sh"
+
+kit_require_kit link-compat-driver
+kit_report_init
+kit_workdir link-compat-driver
+work=$KIT_WORK
+
+fixture=$repo_root/test/cross/cases/exit.c
+
+run_ok x64-object "$KIT" cc -target x86_64-none-elf -ffreestanding \
+ -c "$fixture" -o "$KIT_WORK/x64.o"
+run_ok aa64-object "$KIT" cc -target aarch64-none-elf -ffreestanding \
+ -c "$fixture" -o "$KIT_WORK/aa64.o"
+
+# An explicit target is authoritative. This used to be overwritten by the
+# first object immediately before the public link session was created.
+run_fail explicit-target-authoritative "$KIT" ld \
+ -target aarch64-none-elf -r -o "$KIT_WORK/explicit-mismatch.o" \
+ "$KIT_WORK/x64.o"
+contains explicit-target-names-input \
+ "$KIT_WORK/explicit-target-authoritative.err" "$KIT_WORK/x64.o"
+contains explicit-target-expected-arch \
+ "$KIT_WORK/explicit-target-authoritative.err" "expected arch=aarch64"
+contains explicit-target-actual-arch \
+ "$KIT_WORK/explicit-target-authoritative.err" "got arch=x86_64"
+
+run_ok explicit-target-match "$KIT" ld -target aarch64-none-elf -r \
+ -o "$KIT_WORK/explicit-match.o" "$KIT_WORK/aa64.o"
+
+# Without -target, the first target-bearing object selects the effective
+# target and the same public boundary rejects a later disagreement.
+run_fail inferred-first-target "$KIT" ld -r \
+ -o "$KIT_WORK/inferred-mismatch.o" "$KIT_WORK/x64.o" "$KIT_WORK/aa64.o"
+contains inferred-first-names-input "$KIT_WORK/inferred-first-target.err" \
+ "$KIT_WORK/aa64.o"
+contains inferred-first-expected-arch "$KIT_WORK/inferred-first-target.err" \
+ "expected arch=x86_64"
+contains inferred-first-actual-arch "$KIT_WORK/inferred-first-target.err" \
+ "got arch=aarch64"
+
+# Archive validation must inspect every member before symbol selection, so a
+# foreign second member cannot hide behind an unreferenced archive entry.
+run_ok mixed-archive "$KIT" ar rcs "$KIT_WORK/libmixed.a" \
+ "$KIT_WORK/x64.o" "$KIT_WORK/aa64.o"
+run_fail archive-foreign-member "$KIT" ld -target x86_64-none-elf -r \
+ --whole-archive "$KIT_WORK/libmixed.a" \
+ -o "$KIT_WORK/archive-mismatch.o"
+contains archive-names-container "$KIT_WORK/archive-foreign-member.err" \
+ "$KIT_WORK/libmixed.a"
+contains archive-names-member "$KIT_WORK/archive-foreign-member.err" \
+ "aa64.o"
+
+kit_summary link-compat-driver
+kit_exit
diff --git a/test/link/riscv-flags.sh b/test/link/riscv-flags.sh
@@ -0,0 +1,109 @@
+#!/bin/sh
+# RISC-V psABI ELF e_flags merge/oracle coverage (KIT-P1-004).
+
+set -u
+
+script_dir=$(CDPATH= cd -- "$(dirname "$0")" && pwd)
+repo_root=$(CDPATH= cd -- "$script_dir/../.." && pwd)
+KIT=${KIT:-$repo_root/build/kit}
+KIT_KIT_DIR=$repo_root/test/lib
+. "$repo_root/test/lib/kit_sh_kit.sh"
+
+kit_require_kit riscv-flags
+kit_report_init
+kit_workdir riscv-flags
+work=$KIT_WORK
+
+READELF=$(command -v llvm-readelf 2>/dev/null || command -v readelf 2>/dev/null || true)
+if [ -z "$READELF" ]; then
+ skip_test riscv-flags "llvm-readelf/readelf is required as the independent oracle"
+ kit_summary riscv-flags
+ kit_exit
+fi
+
+main_src=$repo_root/test/tier1/kitchen/cross/shared_main.c
+dep_src=$repo_root/test/tier1/kitchen/cross/shared_dep.c
+
+check_flags() {
+ label=$1
+ file=$2
+ want=$3
+ if "$READELF" -h "$file" > "$work/$label.readelf" \
+ 2> "$work/$label.readelf.err" &&
+ grep -E "Flags:[[:space:]]*$want([,[:space:]]|$)" \
+ "$work/$label.readelf" >/dev/null 2>&1; then
+ ok "$label"
+ else
+ {
+ printf 'expected ELF flags %s\n' "$want"
+ sed 's/^/readelf: /' "$work/$label.readelf" 2>/dev/null
+ sed 's/^/err: /' "$work/$label.readelf.err" 2>/dev/null
+ } > "$work/$label.diag"
+ not_ok "$label" "$work/$label.diag"
+ fi
+}
+
+build_variant() {
+ tag=$1
+ triple=$2
+ march=$3
+ mabi=$4
+ want=$5
+
+ run_ok "$tag-main" "$KIT" cc -target "$triple" -march="$march" \
+ -mabi="$mabi" -ffreestanding -c "$main_src" -o "$work/$tag-main.o"
+ run_ok "$tag-dep" "$KIT" cc -target "$triple" -march="$march" \
+ -mabi="$mabi" -ffreestanding -c "$dep_src" -o "$work/$tag-dep.o"
+ run_ok "$tag-relocatable" "$KIT" ld -r -o "$work/$tag-merged.o" \
+ "$work/$tag-main.o" "$work/$tag-dep.o"
+ check_flags "$tag-relocatable-flags" "$work/$tag-merged.o" "$want"
+ run_ok "$tag-final" "$KIT" cc -target "$triple" -march="$march" \
+ -mabi="$mabi" -nostdlib -Wl,-e,main "$work/$tag-main.o" \
+ "$work/$tag-dep.o" -o "$work/$tag.elf"
+ check_flags "$tag-final-flags" "$work/$tag.elf" "$want"
+}
+
+build_variant rv32-soft riscv32-none-elf \
+ rv32imac_zicsr_zifencei ilp32 0x1
+build_variant rv32-single riscv32-none-elf \
+ rv32imafc_zicsr_zifencei ilp32f 0x3
+build_variant rv64-soft riscv64-none-elf \
+ rv64imac_zicsr_zifencei lp64 0x1
+build_variant rv64-double riscv64-none-elf \
+ rv64imafdc_zicsr_zifencei lp64d 0x5
+
+run_fail rv32-mixed-float "$KIT" ld -r -o "$work/rv32-mixed.o" \
+ "$work/rv32-soft-main.o" "$work/rv32-single-dep.o"
+contains rv32-mixed-names-first "$work/rv32-mixed-float.err" \
+ "rv32-soft-main.o"
+contains rv32-mixed-float-diagnostic "$work/rv32-mixed-float.err" \
+ "float ABI mismatch"
+
+run_fail rv64-mixed-float "$KIT" ld -r -o "$work/rv64-mixed.o" \
+ "$work/rv64-soft-main.o" "$work/rv64-double-dep.o"
+contains rv64-mixed-names-first "$work/rv64-mixed-float.err" \
+ "rv64-soft-main.o"
+contains rv64-mixed-float-diagnostic "$work/rv64-mixed-float.err" \
+ "float ABI mismatch"
+
+# RVC is a mergeable presence bit. A non-C object remains unmarked on its own,
+# then combining it with a C-enabled peer retains RVC in partial and final
+# links while preserving the agreed double-float ABI.
+run_ok rv64-double-noc-main "$KIT" cc -target riscv64-none-elf \
+ -march=rv64imafd_zicsr_zifencei -mabi=lp64d -ffreestanding \
+ -c "$main_src" -o "$work/rv64-double-noc-main.o"
+check_flags rv64-double-noc-object-flags \
+ "$work/rv64-double-noc-main.o" 0x4
+run_ok rv64-rvc-merge-relocatable "$KIT" ld -r \
+ -o "$work/rv64-rvc-merged.o" "$work/rv64-double-noc-main.o" \
+ "$work/rv64-double-dep.o"
+check_flags rv64-rvc-merge-relocatable-flags \
+ "$work/rv64-rvc-merged.o" 0x5
+run_ok rv64-rvc-merge-final "$KIT" cc -target riscv64-none-elf \
+ -march=rv64imafdc_zicsr_zifencei -mabi=lp64d -nostdlib -Wl,-e,main \
+ "$work/rv64-double-noc-main.o" "$work/rv64-double-dep.o" \
+ -o "$work/rv64-rvc-merged.elf"
+check_flags rv64-rvc-merge-final-flags "$work/rv64-rvc-merged.elf" 0x5
+
+kit_summary riscv-flags
+kit_exit
diff --git a/test/tier1/cross/run.sh b/test/tier1/cross/run.sh
@@ -134,23 +134,40 @@ hosted_lane() {
fi
}
+android_api_lane() {
+ local sysroot="$1" api="$2" label="android-aa64:api$2" triple dir pp obj so
+ triple="aarch64-linux-android$api"
+ dir="$WORK/$label"
+ mkdir -p "$dir"
+ pp="$dir/native_activity.i"
+ obj="$dir/native_activity.o"
+ so="$dir/libkit_native_activity.so"
+ run_cmd "$label:cpp" "$dir/cpp.log" \
+ "$KIT" cpp -target "$triple" --sysroot "$sysroot" \
+ -DKIT_EXPECT_ANDROID_API="$api" "$CASES/native_activity.c" -o "$pp" || return 0
+ run_cmd "$label:cc" "$dir/cc.log" \
+ "$KIT" cc -target "$triple" --sysroot "$sysroot" -O1 -fPIC \
+ -DKIT_EXPECT_ANDROID_API="$api" -c "$CASES/native_activity.c" -o "$obj" || return 0
+ run_cmd "$label:ld" "$dir/ld.log" \
+ "$KIT" cc -target "$triple" --sysroot "$sysroot" -shared \
+ "$obj" -landroid -o "$so" || return 0
+ if [ -s "$pp" ] && [ -s "$so" ]; then
+ kit_pass "$label"
+ else
+ kit_fail "$label" "preprocessed/shared artifact missing"
+ fi
+}
+
android_lane() {
- local token=android-aa64 label=android-aa64 sysroot dir obj so
+ local token=android-aa64 label=android-aa64 sysroot
match_selector "$token" || return 0
sysroot="$(hosted_path "$token")"
if [ -z "$sysroot" ] || [ ! -d "$sysroot" ]; then
kit_skip "$label" "Android NDK sysroot not provisioned; run: make provision TARGET=$token"
return 0
fi
- dir="$WORK/$label"
- mkdir -p "$dir"
- obj="$dir/native_activity.o"
- so="$dir/libkit_native_activity.so"
- run_cmd "$label:cc" "$dir/cc.log" \
- "$HOSTED" cc "$token" -O1 -fPIC -c "$CASES/native_activity.c" -o "$obj" || return 0
- run_cmd "$label:ld" "$dir/ld.log" \
- "$HOSTED" cc "$token" -shared "$obj" -landroid -o "$so" || return 0
- if [ -s "$so" ]; then kit_pass "$label"; else kit_fail "$label" "shared object missing"; fi
+ android_api_lane "$sysroot" 21
+ android_api_lane "$sysroot" 35
android_shared_lane "$sysroot"
}