package pacx

// idaScript is the text/template for pacx.py. FORWARD/INVERSE are embedded as a
// JSON blob loaded with json.loads so C++ symbols with metacharacters survive
// intact. Addresses are stored as file (unslid) VM addresses and rebased into
// the live database relative to KERNEL_BASE.
const idaScript = `# pacx.py - generated by ipsw kernel cpp pacx
# kernelcache: {{.Kernelcache}}
# Authenticated C++ vtable (offset, pac) index. No call-site scan is performed;
# pacx_annotate only comments the known vtable slots.
import json

try:
    import idaapi
    import idc
except ImportError:
    idaapi = None
    idc = None

KERNEL_BASE = {{.KernelBase}}
FORWARD = json.loads(r"""{{.Forward}}""")
INVERSE = json.loads(r"""{{.Inverse}}""")


def _rebase(addr):
    if idaapi is None:
        return addr
    return addr - KERNEL_BASE + idaapi.get_imagebase()


def pacx_candidates(offset, pac):
    """Return the candidate targets for a call-site (offset, pac) pair."""
    for f in FORWARD:
        if f["offset"] == offset and f["pac"] == pac:
            return f["candidates"]
    return []


def pacx_xrefs(target):
    """Return every authenticated slot that references target (file VM addr)."""
    for inv in INVERSE:
        if inv["target"] == target:
            return inv["keys"]
    return []


def pacx_annotate():
    """Comment every known authenticated vtable slot in the database."""
    if idc is None:
        print("pacx: no IDA runtime; nothing to annotate")
        return 0
    n = 0
    for f in FORWARD:
        for c in f["candidates"]:
            ea = _rebase(c["slot_addr"])
            label = c["symbol"] if c["symbol"] else ("0x%x" % c["target"])
            idc.set_cmt(ea, "pacx off=0x%x pac=0x%x -> %s" % (f["offset"], f["pac"], label), 0)
            n += 1
    print("pacx: annotated %d slots" % n)
    return n


if __name__ == "__main__":
    pacx_annotate()
`

// r2Script is the text/template for pacx.r2. CCu adds a unique comment on each
// authenticated slot; f defines a flag on each target function.
const r2Script = `# pacx.r2 - generated by ipsw kernel cpp pacx
# kernelcache: {{.Kernelcache}}
{{range .Comments}}CCu {{.Text}} @ {{.Addr}}
{{end}}{{range .Flags}}f {{.Name}} = {{.Addr}}
{{end}}`
