diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5bf41a63..b117431e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4753,6 +4753,57 @@ jobs: if grep -q 'GVALFOLD' "$OUT/build.log"; then echo "ok: C\$_EXIT1 folded as globalvalue"; else echo "note: no GVALFOLD line logged"; fi echo "GATE PASS (vms-864): genuine-alpha crt0-join links zero-deferred; EM_ALPHA/ET_DYN; %LINK-S-CREATED; zero spurious MULDEF (vms-f1a)" + # vms-2655 (rung 3 of vms-b4f): the port-link recipe, opted into the rung-2 + # CRTL->RMS stdio veneer (JOINT_CRTL_RMS_VENEER=1 -- see build-joint-image.sh's + # two-pass bootstrap block), STRICT-links the crtl_rms_test.c port program + # (heap+RMS+stdio) against the veneer-wired DECC$SHR + LIBVMSRMS$SHR + LIBOTS. + # Toolchain-only (no qemu boot -- the real-executive RMS-write proof is rung 4, + # vms-f49, gated on the LLP64 width fix vms-1fc); this leg proves the LINK-time + # composition: zero deferred/undef/muldef, EM_ALPHA/ET_DYN, and the import-map + # chain showing the port image's decc$fopen binds to the SAME DECC$SHR producer + # whose own build log recorded the veneer wiring + sys$create/open/connect/put/ + # get/close bound to LIBVMSRMS$SHR (the un-fakeable proof fopen -> veneer -> RMS, + # not musl-POSIX). Reuses the toolchain image built/pulled above (cache hit). + - name: Link the port image against the CRTL->RMS veneer-wired DECC$SHR + LIBVMSRMS$SHR (vms-2655, rung 3, strict, zero-deferred) + run: | + set -euo pipefail + OUT=/tmp/joint-e2e-rms-veneer-out + JOINT_MAIN=crtl_rms_test.c JOINT_CRTL_RMS_VENEER=1 IMG=ovmx-cross-alpha-vms \ + tools/cross-alpha-vms/joint-e2e/build-joint-image.sh "$OUT" + LOG="$OUT/build.log" + # (1) the pass-2 DECC$SHR build (inside this same recipe run) wired the veneer + grep -qE "mk_decc_shr: CRTL->RMS stdio veneer wired: decc\\\$fopen/fwrite/fread/fclose -> ovmx_crtl_\* \(--use .*LIBVMSRMS\\\$SHR\.EXE\)" "$LOG" \ + || { echo "GATE FAIL (vms-2655): veneer-wired log line not seen"; exit 1; } + # (2) DECC$SHR's own pass-2 build resolved sys$create/open/connect/put/get/close + # against --use LIBVMSRMS$SHR (the real RMS substrate, not a stub) + for s in create open connect put get close; do + grep -qE "cross-image import 'sys\\\$${s}' bound to --use producer LIBVMSRMS\\\$SHR.EXE" "$LOG" \ + || { echo "GATE FAIL (vms-2655): sys\$${s} not bound to LIBVMSRMS\$SHR inside DECC\$SHR pass 2"; exit 1; } + done + # (3) the FINAL joint_e2e.exe link (after crt0 assembly) is zero-deferred/ + # undef/muldef -- scope past the producer-graph's own pre-existing + # first-light residual (LIBVMS$SHR aggregator, unrelated to this rung, + # same scoping build-decc-veneer.sh's own gate applies). + FINAL_START=$(grep -n '^-- assembling crt0.obj' "$LOG" | head -1 | cut -d: -f1) + [ -n "$FINAL_START" ] || { echo "GATE FAIL (vms-2655): crt0.obj assembly marker not found in log"; exit 1; } + TAIL=$(awk -v n="$FINAL_START" 'NR>=n' "$LOG") + echo "$TAIL" | grep -q 'LINK-F-UNDEF' && { echo "GATE FAIL (vms-2655): LINK-F-UNDEF in the final port-image link"; exit 1; } + echo "$TAIL" | grep -q 'LINK-F-MULDEF' && { echo "GATE FAIL (vms-2655): LINK-F-MULDEF in the final port-image link"; exit 1; } + echo "$TAIL" | grep -q 'LINK-W-DEFERRED' && { echo "GATE FAIL (vms-2655): LINK-W-DEFERRED in the final port-image link"; exit 1; } + echo "$TAIL" | grep -qE "LINK-S-CREATED, .*joint_e2e.exe: EVAX/Alpha ET_DYN" \ + || { echo "GATE FAIL (vms-2655): joint_e2e.exe (veneer build) not created EVAX/Alpha ET_DYN"; exit 1; } + # (4) the port image's OWN decc$fopen import binds to the pass-2 (veneer) + # DECC$SHR.EXE producer -- the chain from (1)+(2) above proves THAT + # producer's decc$fopen is the crtl_rms_stdio.c veneer, not musl-POSIX. + echo "$TAIL" | grep -qE "cross-image import 'decc\\\$fopen' bound to --use producer DECC\\\$SHR.EXE" \ + || { echo "GATE FAIL (vms-2655): port image decc\$fopen did not bind to the veneer-wired DECC\$SHR producer"; exit 1; } + readelf -h "$OUT/joint_e2e.exe" | grep -q 'Machine:.*Alpha' || { echo "GATE FAIL (vms-2655): joint_e2e.exe is not EM_ALPHA"; exit 1; } + readelf -h "$OUT/joint_e2e.exe" | grep -qE 'Type:.*DYN' || { echo "GATE FAIL (vms-2655): joint_e2e.exe is not ET_DYN"; exit 1; } + test -f "$OUT/LIBVMSRMS\$SHR.EXE" || { echo "GATE FAIL (vms-2655): LIBVMSRMS\$SHR.EXE not staged in OUTDIR"; exit 1; } + echo "GATE PASS (vms-2655): port image STRICT-links --use veneer-wired DECC\$SHR + LIBVMSRMS\$SHR + LIBOTS zero-deferred;" + echo " decc\$fopen binds to the veneer producer, whose own build resolved sys\$create/open/connect/put/get/close" + echo " against LIBVMSRMS\$SHR (real RMS substrate, not musl-POSIX); EM_ALPHA/ET_DYN; LIBVMSRMS\$SHR.EXE staged." + # vms-f1a: the EVAX/Alpha mirror of the ELF STRONG-vs-STRONG MULDEF gate # (vms-d8d, #777, run_muldef_x86_64.sh). LINK.EXE's evax_find_sym was a # linear FIRST-MATCH with no duplicate check, so two objects both STRONGLY diff --git a/tools/cross-alpha-vms/joint-e2e/README.md b/tools/cross-alpha-vms/joint-e2e/README.md index b0ea5639..fb6e78c1 100644 --- a/tools/cross-alpha-vms/joint-e2e/README.md +++ b/tools/cross-alpha-vms/joint-e2e/README.md @@ -89,6 +89,40 @@ executive to sentinel 5 (`$STATUS = C$_EXIT1 + (5-1)*8 = 0x0035A029`). Leaving `JOINT_EXTRA` empty builds the N=3 (`joint_main.c`) and N=7 (`crtl_rms_test.c`) gates byte-identically to before. +## CRTL->RMS stdio veneer variant (vms-2655, rung 3) — `JOINT_CRTL_RMS_VENEER` + +`JOINT_CRTL_RMS_VENEER=1` opts the port image's DECC$SHR into rung 2's +CRTL->RMS stdio veneer (`tools/cross-alpha-vms/decc-veneer/build-decc-veneer.sh`'s +two-pass bootstrap, composed into this recipe): pass 1 builds a bootstrap +DECC$SHR to build the OVMX producer graph through `LIBVMSRMS$SHR`; pass 2 +rebuilds DECC$SHR with `ALPHA_CRTL_RMS_USE=`, so +`decc$fopen/fwrite/fread/fclose` alias to the `crtl_rms_stdio.c` veneer +(`ovmx_crtl_*`, real `sys$create/open/connect/put/get/close` against RMS) +instead of musl's own POSIX defs. The final link adds `--use LIBVMSRMS$SHR` +(the veneer's own cross-image `sys$*` imports need a producer here too), and +`LIBVMSRMS$SHR.EXE` is staged into OUTDIR alongside `DECC$SHR.EXE`/ +`LIBOTS_SHR.EXE`: + +```sh +JOINT_MAIN=crtl_rms_test.c JOINT_CRTL_RMS_VENEER=1 IMG=ovmx-cross-alpha-vms \ + tools/cross-alpha-vms/joint-e2e/build-joint-image.sh [OUTDIR] +``` + +Default `JOINT_CRTL_RMS_VENEER=0` (unset), so every existing caller — this +script's own default invocation, and +`tools/cross-alpha/run-module-gp-activation-alpha.sh`'s `gate`/`crtl-rms-gate`/ +`mf-gate` modes (which activate on the real executive over qemu-system-alpha) +— builds byte-identically to before this change. Those real-hardware +activation gates stay on the plain (non-veneer) DECC$SHR until the LLP64 +width fix (vms-1fc) makes an RMS-routed `fopen` activation-safe on real +`/dev/vms` (rung 4, vms-f49); `JOINT_CRTL_RMS_VENEER=1` proves the LINK-time +composition only (toolchain container, no boot) — zero deferred/undef/muldef, +EM_ALPHA/ET_DYN, and the import-map chain showing the port image's +`decc$fopen` binds to the pass-2 DECC$SHR producer whose own build log +recorded both the veneer wiring and `sys$create/open/connect/put/get/close` +bound to `LIBVMSRMS$SHR` — the un-fakeable proof that fopen resolves to the +veneer, not musl-POSIX. + ## The activation round-trip (conductor / Alpha path, unchanged from before) 1. IMGACT activates joint_e2e.exe; fills `.vms$imp` (`decc$main`, diff --git a/tools/cross-alpha-vms/joint-e2e/build-joint-image.sh b/tools/cross-alpha-vms/joint-e2e/build-joint-image.sh index fda5a0d5..f8f8a3ab 100755 --- a/tools/cross-alpha-vms/joint-e2e/build-joint-image.sh +++ b/tools/cross-alpha-vms/joint-e2e/build-joint-image.sh @@ -24,8 +24,19 @@ # JOINT_MAIN=crtl_rms_test.c IMG=ovmx-cross-alpha-vms \ # tools/cross-alpha-vms/joint-e2e/build-joint-image.sh [OUTDIR] # +# JOINT_CRTL_RMS_VENEER=1 (vms-2655, rung 3 of vms-b4f; default 0, so every +# existing caller/gate is byte-identical) opts DECC$SHR into the rung-2 +# CRTL->RMS stdio veneer (two-pass bootstrap — see the JOINT_CRTL_RMS_VENEER +# block below) and adds --use LIBVMSRMS$SHR to the final link, so +# decc$fopen/fwrite/fread/fclose in whatever JOINT_MAIN builds bind to the +# veneer (ovmx_crtl_* -> real RMS system services) instead of musl-POSIX: +# +# JOINT_MAIN=crtl_rms_test.c JOINT_CRTL_RMS_VENEER=1 IMG=ovmx-cross-alpha-vms \ +# tools/cross-alpha-vms/joint-e2e/build-joint-image.sh [OUTDIR] +# # OUTDIR (default /tmp/joint-e2e-out) receives: LINK.EXE, LIBOTS_SHR.EXE, -# 'DECC$SHR.EXE', crt0.obj, joint_main.obj, joint_e2e.exe, and build.log. +# 'DECC$SHR.EXE', crt0.obj, joint_main.obj, joint_e2e.exe, build.log, and (with +# JOINT_CRTL_RMS_VENEER=1) 'LIBVMSRMS$SHR.EXE' alongside the other shareables. # # crt0.s here is a REAL alpha-dec-vms cc1 -mpointer-size=64 compile of the # GCC-port's own libgcc/config/vms/vms-ucrt0.c (GPLv3, gcc-14.2.0 — the exact @@ -72,6 +83,31 @@ for _e in $JOINT_EXTRA; do esac test -f "$HERE/$_e" || { echo "FAIL: JOINT_EXTRA source '$_e' not found in $HERE" >&2; exit 1; } done + +# JOINT_CRTL_RMS_VENEER (vms-2655, rung 3 of vms-b4f). Opt-in (default 0, so +# every existing gate/caller builds byte-identically to before). When set to +# 1, this recipe builds the port image's DECC$SHR via the SAME two-pass +# CRTL->RMS stdio-veneer bootstrap rung 2's build-decc-veneer.sh introduced +# (tools/cross-alpha-vms/decc-veneer/build-decc-veneer.sh -- read that script +# first, this composes it verbatim into this recipe's producer graph): +# pass 1 (bootstrap): DECC$SHR WITHOUT the veneer, used only to build the +# producer graph (LIBVMSSYS/PROCESS/LNM/FS/LIBVMS$SHR -> LIBVMSRMS$SHR). +# pass 2 (final): DECC$SHR WITH ALPHA_CRTL_RMS_USE=, +# so decc$fopen/fwrite/fread/fclose alias to the crtl_rms_stdio.c veneer +# (ovmx_crtl_*) instead of musl's own POSIX defs. The final joint_e2e.exe +# link then ADDS --use LIBVMSRMS$SHR (the veneer's own cross-image sys$* +# imports need a producer at THIS link too, exactly as build-decc-veneer.sh's +# step-12 test image does), and LIBVMSRMS$SHR is staged into OUTDIR +# alongside DECC$SHR/LIBOTS_SHR (the SYS$SHARE search-path set a bootable +# runtime would load all three from). This is a build-ORCHESTRATION +# opt-in confined to this recipe -- with the var unset/0, every existing +# caller (joint-e2e-alpha-crt0, run-module-gp-activation-alpha.sh's gate/ +# crtl-rms-gate/mf-gate) gets the SAME single-pass DECC$SHR + --use +# DECC$SHR/LIBOTS link as before this change, so those runtime-activation +# gates (which need the LLP64 width fix, vms-1fc, before an RMS-routed +# fopen is activation-safe on real /dev/vms -- rung 4, vms-f49) are +# unaffected. +JOINT_CRTL_RMS_VENEER=${JOINT_CRTL_RMS_VENEER:-0} mkdir -p "$OUT" # vms-430: the PT_INTERP LINK.EXE bakes into every joint_e2e.exe this script @@ -111,6 +147,7 @@ docker run --rm \ -e IMGACT_INTERP_PATH \ -e JOINT_MAIN \ -e JOINT_EXTRA \ + -e JOINT_CRTL_RMS_VENEER \ "$IMG" bash -c ' set -euxo pipefail OUT=/out @@ -171,14 +208,53 @@ DET=$(OVMX_DECC_ARCH= OVMX_DECC_DETECT_ONLY=1 \ [ "$DET" = alpha ] || { echo "FAIL (vms-2a0): auto-detect resolved [$DET], expected alpha" >&2; exit 1; } echo " OK: auto-detect resolves to alpha (container-format-aware, vms-2a0)" -echo "-- building the GENUINE alpha DECC\$SHR (OVMX_DECC_ARCH=alpha, forced) --" -OVMX_DECC_ARCH=alpha \ - NM="$PREFIX/bin/alpha-dec-vms-nm" \ - AR_HOST=ar \ - ALPHA_CC="$ALPHA_CC" \ - ALPHA_MUSL_SRC="$MUSL_SRC" \ - DECC_USE="$WORK/libots/LIBOTS_SHR.EXE" \ - sh /src/src/vmslink/mk_decc_shr.sh "$WORK/LINK.EXE" "$WORK/DECC\$SHR.EXE" "$LIBC" "$LIBGCC" +RMS="" +JOINT_CRTL_RMS_VENEER=${JOINT_CRTL_RMS_VENEER:-0} +if [ "$JOINT_CRTL_RMS_VENEER" = 1 ]; then + # ---- vms-2655 (rung 3): the two-pass CRTL->RMS veneer bootstrap, composed + # verbatim from tools/cross-alpha-vms/decc-veneer/build-decc-veneer.sh + # (the rung 2 template) into this recipe producer graph. ---- + MK=/src/src/vmslink + OTS="$WORK/libots/LIBOTS_SHR.EXE" + + echo "-- [vms-2655] DECC\$SHR pass 1 (bootstrap, no veneer) --" + OVMX_DECC_ARCH=alpha NM="$PREFIX/bin/alpha-dec-vms-nm" AR_HOST=ar \ + ALPHA_CC="$ALPHA_CC" ALPHA_MUSL_SRC="$MUSL_SRC" DECC_USE="$OTS" \ + sh "$MK/mk_decc_shr.sh" "$WORK/LINK.EXE" "$WORK/DECC1\$SHR.EXE" "$LIBC" "$LIBGCC" + DECC1="$WORK/DECC1\$SHR.EXE" + + echo "-- [vms-2655] the OVMX producer graph (rung 1, unchanged), using DECC1 --" + export ALPHA_CC ALPHA_MUSL_SRC="$MUSL_SRC" OVMX_DECC_ARCH=alpha ALPHA_OTS_USE="$OTS" + ALPHA_DECC_USE="$DECC1" sh "$MK/mk_vmssys_shr.sh" "$WORK/LINK.EXE" "$WORK/LIBVMSSYS\$SHR.EXE" + SYS="$WORK/LIBVMSSYS\$SHR.EXE" + sh "$MK/mk_vmsprocess_shr.sh" "$WORK/LINK.EXE" "$WORK/LIBVMSPROCESS\$SHR.EXE" "$DECC1" "$SYS" + PROC="$WORK/LIBVMSPROCESS\$SHR.EXE" + VMSSYS_SHR="$SYS" sh "$MK/mk_vmslnm_shr.sh" "$WORK/LINK.EXE" "$WORK/LIBVMSLNM\$SHR.EXE" "$DECC1" + LNM="$WORK/LIBVMSLNM\$SHR.EXE" + ALPHA_SYS_USE="$SYS" sh "$MK/mk_vmsfs_shr.sh" "$WORK/LINK.EXE" "$WORK/LIBVMSFS\$SHR.EXE" "$DECC1" "$LNM" + FS="$WORK/LIBVMSFS\$SHR.EXE" + sh "$MK/mk_libvms_shr.sh" "$WORK/LINK.EXE" "$WORK/LIBVMS\$SHR.EXE" "$DECC1" "$PROC" "$SYS" "$FS" + VMS="$WORK/LIBVMS\$SHR.EXE" + + echo "-- [vms-2655] LIBVMSRMS\$SHR (rung 1, unchanged) --" + sh "$MK/mk_vmsrms_shr.sh" "$WORK/LINK.EXE" "$OUT/LIBVMSRMS\$SHR.EXE" "$DECC1" "$VMS" "$FS" "$SYS" + RMS="$OUT/LIBVMSRMS\$SHR.EXE" + + echo "-- [vms-2655] DECC\$SHR pass 2 (final, CRTL->RMS stdio veneer wired, vms-ed1e) --" + OVMX_DECC_ARCH=alpha NM="$PREFIX/bin/alpha-dec-vms-nm" AR_HOST=ar \ + ALPHA_CC="$ALPHA_CC" ALPHA_MUSL_SRC="$MUSL_SRC" DECC_USE="$OTS" \ + ALPHA_CRTL_RMS_USE="$RMS" \ + sh "$MK/mk_decc_shr.sh" "$WORK/LINK.EXE" "$WORK/DECC\$SHR.EXE" "$LIBC" "$LIBGCC" +else + echo "-- building the GENUINE alpha DECC\$SHR (OVMX_DECC_ARCH=alpha, forced) --" + OVMX_DECC_ARCH=alpha \ + NM="$PREFIX/bin/alpha-dec-vms-nm" \ + AR_HOST=ar \ + ALPHA_CC="$ALPHA_CC" \ + ALPHA_MUSL_SRC="$MUSL_SRC" \ + DECC_USE="$WORK/libots/LIBOTS_SHR.EXE" \ + sh /src/src/vmslink/mk_decc_shr.sh "$WORK/LINK.EXE" "$WORK/DECC\$SHR.EXE" "$LIBC" "$LIBGCC" +fi # ---- 5. the real port crt0 + a hello main, both compiled/assembled fresh # by the REAL alpha-dec-vms cross toolchain (no object blobs checked @@ -216,11 +292,25 @@ done # OTS$DIV_UL/OTS$REM_UI against DECC$SHR alone. LINK binds only REFERENCED # imports, so adding --use LIBOTS$ is inert for programs (like this joint_main) # that emit no OTS$ call, and closes the gap for those that do. +# +# vms-2655 (rung 3): when JOINT_CRTL_RMS_VENEER=1, DECC$SHR (above) is the +# pass-2 veneer-wired build, whose decc$fopen/fwrite/fread/fclose alias to the +# crtl_rms_stdio.c veneer (ovmx_crtl_*), which itself references +# sys$create/open/connect/put/get/close -- cross-image imports that need a +# producer at THIS link too, exactly like build-decc-veneer.sh step 12s test +# image. --use LIBVMSRMS$SHR supplies it (RMS is empty/unset otherwise, so +# this is inert -- no extra --use flag -- when the veneer is not opted in). +RMS_USE_FLAG="" +[ -n "$RMS" ] && RMS_USE_FLAG="--use $RMS" "$WORK/LINK.EXE" --transfer __main \ - --use "$WORK/DECC\$SHR.EXE" --use "$WORK/libots/LIBOTS_SHR.EXE" \ + --use "$WORK/DECC\$SHR.EXE" $RMS_USE_FLAG --use "$WORK/libots/LIBOTS_SHR.EXE" \ -o "$OUT/joint_e2e.exe" "$OUT/crt0.obj" "$OUT/joint_main.obj" $EXTRA_OBJS cp "$WORK/LINK.EXE" "$WORK/DECC\$SHR.EXE" "$WORK/libots/LIBOTS_SHR.EXE" "$OUT/" +# vms-2655: LIBVMSRMS$SHR.EXE was already built directly into $OUT (above), so +# it lands in OUTDIR alongside DECC$SHR.EXE/LIBOTS_SHR.EXE -- the same +# SYS$SHARE search-path set -- with no extra copy needed when the veneer path +# built it; a plain (non-veneer) run leaves $RMS empty and stages nothing new. echo "== joint-e2e image built (genuine alpha path, vms-864) ==" ls -la "$OUT/" readelf -h "$OUT/joint_e2e.exe" | grep -E "Type|Machine|Entry"