#!/usr/bin/env bash
# Phase 6.2 UBSan-min smoke probe: build + link + run under MAME.
#
# Usage:
#   bash tests/ubsan/runUbsanProbe.sh
#
# What this verifies:
#   - clang accepts -fsanitize=undefined -fsanitize-minimal-runtime on
#     the w65816 target.
#   - Nine exercised UB kinds (add-overflow / shift-out-of-bounds /
#     divrem-overflow / sub-overflow / mul-overflow / negate-overflow /
#     pointer-overflow / load-invalid-value / out-of-bounds) instrument
#     as expected -- the handler-fired byte flips inside the per-kind
#     handler override.
#   - The recovering minimal runtime returns to the caller cleanly, so
#     the probe continues writing sentinels past each UB site.
#   - runtime/ubsan.o links + resolves the other handler kinds without
#     pulling in console code that the probe doesn't need.

set -eu
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
OUT="$SCRIPT_DIR/build"
RT="$PROJECT_ROOT/runtime"

cd "$SCRIPT_DIR"
rm -rf "$OUT"
bash "$SCRIPT_DIR/build.sh"

# Link. crt0.o + the probe + ubsan.o + libgcc.o (for the i16 div+rem
# helpers triggerDivByZero needs).  We deliberately do NOT link libc.o
# -- the probe sets memory sentinels directly, doesn't call printf, and
# pulling libc.o in would also pull snprintf.o (~9 KB) for no benefit.
"$PROJECT_ROOT/tools/link816" -o ubsanProbe.bin \
    --text-base 0x1000 --bss-base 0xA000 --map ubsanProbe.map \
    "$RT/crt0.o" \
    "$OUT/ubsanProbe.o" \
    "$RT/ubsan.o" \
    "$RT/libgcc.o"

ls -la ubsanProbe.bin
echo ""

# Sentinels (one per recoverable handler exercised, plus a tail
# liveness sentinel).  Each is a 16-bit write at $025000+kind*2.
#   $025000 = 0xC0DE     add-overflow handler fired
#   $025002 = 0xC0DF     shift-out-of-bounds handler fired
#   $025004 = 0xC0E0     divrem-overflow handler fired
#   $025006 = 0xC0E1     sub-overflow handler fired
#   $025008 = 0xC0E2     mul-overflow handler fired
#   $02500A = 0xC0E3     negate-overflow handler fired
#   $02500C = 0xC0E4     pointer-overflow handler fired
#   $02500E = 0xC0E5     load-invalid-value handler fired
#   $025010 = 0xC0E6     out-of-bounds handler fired
#   $025012 = 0xC0DA     all nine recovered and main reached its tail
bash "$PROJECT_ROOT/scripts/runInMame.sh" \
    "$SCRIPT_DIR/ubsanProbe.bin" \
    --check \
        0x025000=C0DE 0x025002=C0DF 0x025004=C0E0 \
        0x025006=C0E1 0x025008=C0E2 0x02500A=C0E3 \
        0x02500C=C0E4 0x02500E=C0E5 0x025010=C0E6 \
        0x025012=C0DA
