This repository has been archived on 2026-09-16. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Syplheed-Reborn/tools/re-capture/trigger_watch.sh
Sylpheed RE agent 761dcd004c re: the JIT context is in %rsi; but the re-run could not locate the mission
From Canary's own source (x64_emitter.cc:881) GetContextReg() returns rsi, so at
any JIT instruction %rsi is the PPCContext* -- which is also why the faulting
instruction read 0x110(%rsi), a guest register load. That is the way past the
watchpoint's ceiling: the guest register file is available at the write, and a
0x82xxxxxx word picked out of it resolves against sylpheed.db to name the caller.
trigger_watch.sh now dumps x/128wx  instead of a useless host backtrace.

The re-run then failed for an unrelated and unexplained reason: it reached
flight, the pilot bound, the guest was animating, and find_mission returned
NOTFOUND. Narrowed: the .ssb header is absent from guest memory (0 hits where
earlier runs hit immediately), ADN110 is absent too, but the manifest string
'Stage02.ssb' IS present at 0xBDA6C50B. So memory is readable and the manifest
is loaded while the script is not, in a mission that is flying.

No explanation offered. The cheap discriminator for next time is to poll for the
header from the moment flight starts and record when it appears, instead of
sampling once.
2026-08-25 19:03:33 +00:00

61 lines
2.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# Find what WRITES the trigger-queue count, by watching the word rather than
# hunting the instruction statically.
#
# The static hunt failed (isl-builtins.md): the only writes to `+20` in the
# container's code are block initialisations, yet the count demonstrably moves
# 0 -> 1 -> 2 during a mission. A watchpoint names the writer directly.
#
# The address translation is the fiddly part, so it is explicit:
# guest VA -> file offset via gmem.va_to_off
# file offset -> HOST address via the /dev/shm/xenia_memory_* mapping in
# /proc/<pid>/maps: host = map_start - map_off + off
# gdb debugs the HOST process, so a guest VA cannot be watched directly.
set -u
export HOME=/sylph-home/re SDL_AUDIODRIVER=dummy DISPLAY=:98
export PYTHONPATH=/sylph-home/.local/lib/python3.12/site-packages
export XENIA_BIN=/sylph-home/re/bin/gdb-wrap/xenia_canary
SD="$(cd "$(dirname "$0")" && pwd)"; export SD
CMD=/tmp/gdb-cmd; OUT=/tmp/gdb-out.log
WATCH_S="${1:-240}"
sleepfor(){ python3 -c "import time,sys; time.sleep(float(sys.argv[1]))" "$1"; }
"$SD/launch_mission.sh" fly || { echo "BOOT FAILED"; exit 1; }
CFG=/tmp/nav-tw.json
for t in 1 2 3; do
python3 "$SD/pad.py" set "rt=1" >/dev/null 2>&1; sleepfor 3
python3 "$SD/pad.py" clear >/dev/null 2>&1
if python3 "$SD/entities2.py" self 0x130 "$CFG" >/dev/null 2>&1; then
SYLPH_HUNT=1 SYLPH_KEEPOUT=1400 nohup python3 "$SD/pilot.py" "$CFG" 900 \
</dev/null >/tmp/tw-pilot.log 2>&1 & echo "--- pilot flying"; break
fi
done
HOSTADDR=$(python3 "$SD/host_addr.py" 2>/tmp/tw-addr.err)
echo "--- translation: $(cat /tmp/tw-addr.err)"
echo "--- host addr: $HOSTADDR"
case "$HOSTADDR" in 0x*) ;; *) echo "could not translate"; exit 2;; esac
pid=$(pgrep -x gdb | head -1); before=$(wc -c < "$OUT")
kill -INT "$pid"; sleepfor 3
{ echo 'echo === WATCH SET ===\n'
echo "watch *(unsigned int*)$HOSTADDR"
echo "continue"; } >> "$CMD"
echo "--- watching ${WATCH_S}s"
sleepfor "$WATCH_S"
kill -INT "$pid"; sleepfor 3
# The host stack is useless here: the write happens in JIT-compiled guest code,
# which is unsymbolised and not host-unwindable. But Xenia's x64 backend keeps
# the guest context in %rsi (x64_emitter.cc: `GetContextReg() { return rsi; }`),
# so the guest register file is right there. Dump it and pick out the words that
# look like guest code addresses (0x82xxxxxx) -- the guest LR is among them, and
# that names the calling guest function.
{ echo 'echo === WHO WROTE IT ===\n'; echo 'x/3i $pc'
echo 'info registers rsi rdi'
echo 'echo === GUEST CONTEXT ===\n'
echo 'x/128wx $rsi'
echo 'echo === END ===\n'; echo 'delete'; echo 'continue'; } >> "$CMD"
sleepfor 10
tail -c +$((before + 1)) "$OUT" | grep -vE '^\s*$' | tail -60
echo "TRIGGER WATCH DONE"