diag-livebootstrap-qemu.sh (7226B)
1 #!/bin/sh 2 ## tools/diag-livebootstrap-qemu.sh — DIAGNOSTIC ONLY 3 ## 4 ## Runs live-bootstrap's stage0 → tcc-0.9.27 chain inside a busybox:musl 5 ## container under linux/amd64 QEMU emulation, to determine whether the 6 ## tcc-boot0-mes startup SEGV (Issue §3 in docs/TCC.md) is QEMU's fault 7 ## or specific to our build. 8 ## 9 ## **This script is diagnostic, not part of the bootstrap chain.** It 10 ## intentionally invokes live-bootstrap's M2-Planet / Mes / MesCC path 11 ## — the very chain our project replaces. Nothing it produces feeds 12 ## into the project's deliverables. Read result, then ignore. 13 ## 14 ## Outcome interpretation: 15 ## - chain reaches tcc-0.9.27 and `tcc -version` works: 16 ## QEMU is sound. Our tcc-boot0-mes SEGV is build-specific 17 ## (codegen/runtime bug). Action: backport tcc 0.9.28rc fixes 18 ## or compare disasm against live-bootstrap's tcc-boot0. 19 ## - chain SEGVs at tcc-mes / tcc-boot0 / tcc-0.9.27: 20 ## QEMU is broken for these binaries on macOS arm64. Action: 21 ## either run on native x86_64 hardware, or use the linux/386 22 ## (32-bit) path with QEMU and accept the arch mismatch. 23 ## 24 ## Setup (host): 25 ## - LIVE_BOOTSTRAP=<path>: required env var pointing at a working 26 ## live-bootstrap checkout. Distfiles are taken from 27 ## $LIVE_BOOTSTRAP/../lb-work/distfiles (the sibling layout 28 ## live-bootstrap's own scripts produce). The diagnostic also 29 ## needs tcc-0.9.27.tar.bz2; this script fetches it via curl on 30 ## first run if missing. Stage0-posix tools (M2-Planet, 31 ## mescc-tools, etc.) are bundled in 32 ## $LIVE_BOOTSTRAP/seed/stage0-posix and don't need distfiles. 33 ## 34 ## The script has no implicit `../live-bootstrap` lookup — the rest 35 ## of the build is in-tree, and this diagnostic is the sole script 36 ## that needs the upstream tree, so make the dependency explicit. 37 ## 38 ## Pipeline: 39 ## 1. (host) populate distfiles (curl tcc-0.9.27 if needed) 40 ## 2. (host) assemble rootfs at build/diag-livebootstrap/rootfs/ 41 ## - copy seed/stage0-posix/* (the hex0 binaries + M2-Planet 42 ## + mescc-tools sources) to / 43 ## - copy seed/{after,seed,preseeded}.kaem to / 44 ## - copy steps/, lib/ to / 45 ## - copy distfiles to /distfiles 46 ## - write /steps/bootstrap.cfg with ARCH=amd64, CHROOT=True 47 ## - truncate /steps/manifest after `build: tcc-0.9.27` so the 48 ## chain stops at our target instead of running 200+ builds 49 ## 3. (busybox:musl, linux/amd64) chroot into rootfs and run 50 ## /bootstrap-seeds/POSIX/AMD64/kaem-optional-seed 51 ## 52 ## Runtime: many hours under QEMU emulation on macOS arm64. Set aside a 53 ## work block. Set DIAG_PREP_ONLY=1 to do steps 1-2 and skip the run. 54 ## 55 ## Usage: 56 ## tools/diag-livebootstrap-qemu.sh 57 58 set -eu 59 60 ROOT=$(cd "$(dirname "$0")/.." && pwd) 61 : "${LIVE_BOOTSTRAP:?set LIVE_BOOTSTRAP=<path-to-live-bootstrap-checkout>}" 62 LB=$(cd "$LIVE_BOOTSTRAP" && pwd) 63 DISTFILES=${LB_DISTFILES:-$LB/../lb-work/distfiles} 64 WORK=$ROOT/build/diag-livebootstrap 65 ROOTFS=$WORK/rootfs 66 67 [ -d "$LB" ] || { echo "missing live-bootstrap at $LB" >&2; exit 1; } 68 [ -d "$DISTFILES" ] || { echo "missing distfiles at $DISTFILES (override with LB_DISTFILES=<path>)" >&2; exit 1; } 69 command -v podman >/dev/null 2>&1 || { echo "podman required" >&2; exit 2; } 70 71 # --- (1) ensure distfiles populated ---------------------------------- 72 NEED="mes-0.27.1.tar.gz tcc-0.9.26.tar.gz tcc-0.9.27.tar.bz2 nyacc-1.00.2-lb1.tar.gz" 73 for f in $NEED; do 74 if [ ! -r "$DISTFILES/$f" ]; then 75 echo "missing $DISTFILES/$f" 76 case "$f" in 77 tcc-0.9.27.tar.bz2) 78 echo "fetching from savannah..." 79 curl --fail --location \ 80 "https://download.savannah.gnu.org/releases/tinycc/$f" \ 81 -o "$DISTFILES/$f" 82 ;; 83 *) 84 echo " (cannot auto-fetch $f — please populate $DISTFILES/$f)" >&2 85 exit 1 86 ;; 87 esac 88 fi 89 done 90 echo "distfiles ok: $NEED" 91 92 # --- (2) assemble rootfs -------------------------------------------- 93 echo "=== assembling rootfs at $ROOTFS ===" 94 rm -rf "$WORK" 95 mkdir -p "$ROOTFS" 96 97 # seed/stage0-posix → / (stage0 tools, M2-Planet, mescc-tools, kaem etc) 98 cp -R "$LB/seed/stage0-posix/." "$ROOTFS/" 99 100 # seed/*.kaem → / (preseeded.kaem, seed.kaem, after.kaem) 101 cp "$LB/seed/"*.kaem "$ROOTFS/" 102 103 # Other seed files (configurator binaries, checksums) 104 cp "$LB/seed/configurator.c" "$LB/seed/configurator.amd64.checksums" "$ROOTFS/" 2>/dev/null || true 105 cp "$LB/seed/script-generator.c" "$LB/seed/script-generator.amd64.checksums" "$ROOTFS/" 2>/dev/null || true 106 107 # steps/, lib/ from live-bootstrap 108 cp -R "$LB/steps" "$ROOTFS/" 109 cp -R "$LB/lib" "$ROOTFS/" 110 111 # distfiles → /external/distfiles (live-bootstrap's steps/env sets 112 # DISTFILES=/external/distfiles, and helpers/build steps read from there) 113 mkdir -p "$ROOTFS/external/distfiles" 114 for f in $NEED; do 115 cp "$DISTFILES/$f" "$ROOTFS/external/distfiles/" 116 done 117 118 # Truncate manifest to stop after the first `build: tcc-0.9.27`. The 119 # manifest has a header comment block (lines 1-33), then build steps 120 # starting at line 34. Line 38 is the first tcc-0.9.27 build. 121 awk ' 122 /^build: tcc-0\.9\.27/ && !seen_tcc27 { 123 print 124 seen_tcc27 = 1 125 next 126 } 127 seen_tcc27 { 128 # drop everything after first tcc-0.9.27 build 129 next 130 } 131 { print } 132 ' "$LB/steps/manifest" > "$ROOTFS/steps/manifest" 133 134 # bootstrap.cfg — mirrors what rootfs.py would write for 135 # `--arch amd64 --chroot --mirrors file:///distfiles`. We disable 136 # every optional pipeline (kernels, configurator, fiwix) since this 137 # is a pass1-only diagnostic. 138 cat > "$ROOTFS/steps/bootstrap.cfg" <<'EOF' 139 ARCH=amd64 140 ARCH_DIR=AMD64 141 FORCE_TIMESTAMPS=False 142 CHROOT=True 143 UPDATE_CHECKSUMS=False 144 JOBS=2 145 SWAP_SIZE=0 146 FINAL_JOBS=2 147 INTERNAL_CI=False 148 INTERACTIVE=False 149 QEMU=False 150 BARE_METAL=False 151 DISK=sda1 152 KERNEL_BOOTSTRAP=False 153 BUILD_KERNELS=False 154 CONFIGURATOR=False 155 MIRRORS_LEN=0 156 EOF 157 158 echo "rootfs assembled." 159 du -sh "$ROOTFS" 2>/dev/null || true 160 161 if [ "${DIAG_PREP_ONLY:-0}" = "1" ]; then 162 echo "DIAG_PREP_ONLY=1 — skipping container run." 163 exit 0 164 fi 165 166 # --- (3) run kaem-optional-seed in busybox:musl under linux/amd64 ---- 167 echo 168 echo "=== launching kaem-optional-seed via busybox:musl (linux/amd64 QEMU) ===" 169 echo " long-running. ctrl-C aborts. log lines stream below." 170 echo 171 172 # busybox:musl ships chroot, sh, tar, awk, etc. — sufficient. 173 # /proc /dev /sys are mounted by podman; chroot inherits them via bind. 174 # We mount the rootfs as /work/rootfs inside the container, then chroot. 175 podman run --rm -i --platform linux/amd64 \ 176 -v "$ROOTFS":/rootfs \ 177 docker.io/library/busybox:musl sh -s <<'CONTAINER_SCRIPT' 178 set -eu 179 180 # Ensure /proc /dev /sys exist inside the chroot for kaem etc. 181 mkdir -p /rootfs/proc /rootfs/dev /rootfs/sys /rootfs/tmp 182 mount -t proc proc /rootfs/proc 2>/dev/null || true 183 mount --rbind /dev /rootfs/dev 2>/dev/null || true 184 mount --rbind /sys /rootfs/sys 2>/dev/null || true 185 186 echo "--- starting chroot kaem ---" 187 exec env -i PATH=/bin chroot /rootfs /bootstrap-seeds/POSIX/AMD64/kaem-optional-seed 188 CONTAINER_SCRIPT 189 190 rc=$? 191 echo 192 echo "=== kaem exit=$rc ===" 193 exit "$rc"