#!/bin/sh
# DF-5571 phase driver v3 — one ssh session.
# usage: df5571_run.sh <kernel-path> <tag> <db_active-addr>
VK="$1"; TAG="$2"; ADDR="$3"
OUT=/tmp/df5571-$TAG; CON=$OUT/console.log
pkill -f "$VK" 2>/dev/null; sleep 1
rm -rf $OUT; mkdir -p $OUT
rm -f /tmp/vkin; mkfifo /tmp/vkin

nohup $VK -m 256m -r /vkroot.img \
  -e vfs.root.mountfrom=ufs:vkd0s1a -n 2 \
  -s < /tmp/vkin > $CON 2>&1 &
VKP=$!
exec 9>/tmp/vkin          # open write end (vkernel is opening read side)
echo "VKPID=$VKP"
sleep 2
kill -0 $VKP 2>/dev/null || { echo VK_DIED_EARLY; tail -5 $CON; exit 2; }

waitlog() {
  i=0; while [ $i -lt $2 ]; do grep -q -- "$1" $CON 2>/dev/null && return 0
    kill -0 $VKP 2>/dev/null || { echo VK_DIED_WHILE_WAITING_FOR [$1]; return 1; }
    sleep 1; i=$((i+1)); done
  echo "TIMEOUT waiting for [$1]"; return 1
}

# --- 1) healthy userspace (vkinit -> sh on console) ------------------------
waitlog "Mounting devfs" 120 || { tail -30 $CON; exit 2; }
sleep 8
printf 'echo VKBOOT-OK\n' >&9
waitlog "VKBOOT-OK" 40 || { tail -40 $CON; exit 2; }
sleep 2

# --- 2) enter ddb: SIGQUIT -> exc_debugger -> Debugger() -> kdb_trap ------
CHILD=$(ps ax -o pid,ppid,command | awk -v p=$VKP '$2==p {print $1}' | head -1)
echo "VKCHILD=$CHILD"
kill -QUIT $CHILD
waitlog "db>" 30 || { tail -30 $CON; exit 2; }
sleep 2
printf "x/x %s\n" "$ADDR" >&9
sleep 4

# --- 3) nested fault inside ddb: call into unmapped page ------------------
printf 'call 0x10()\n' >&9
sleep 6
printf "x/x %s\n" "$ADDR" >&9
sleep 4

# --- 4) continue: leaked db_active diverts next trap to trap_fatal+ddb ----
printf 'c\n' >&9
sleep 10

# --- 5) trigger a user-mode page fault from the shell ---------------------
printf '/bin/fault\n' >&9
sleep 12
printf 'echo POSTCONT-ALIVE\n' >&9
sleep 8

echo "=== PHASE DONE ==="
pkill -f "$VK" 2>/dev/null
sleep 1
exit 0
