"""D3 Q11: fix the failed control from Q10.

Q10's control was INVALID BY CONSTRUCTION, not a scan failure: xrefs_to(0x1801a7260)
reported two DATA references, but those live at 0x180284468 / 0x180300d1c which are
4-byte RVA entries (RVA of the function is 0x1a7260) in the exception/unwind tables,
so an 8-byte-pointer search can never find them. Re-do the control properly and then
answer the real question: what is the slot INDEX of FUN_1800e2a40 in the table that
contains it?  The action-flag attribution needs index 8 (= vtable +0x40).

CONTROL (valid this time): the same 8-byte pointer search must find FUN_18013fe00,
which we know sits nowhere in a vtable, AND must find the item vtable 0x1801eaac0's
own three slots.  Concretely: read 0x1801eaac0 and confirm its slots are .text
addresses -- an 8-byte-pointer table we have already relied on.
"""
import struct, traceback
try:
    print("### the 4-byte RVA check that explains the Q10 control failure")
    for a in (0x180284468, 0x180300d1c):
        try:
            v = dword(a)
            print("   %#x -> dword %#x  (RVA of 0x1801a7260 is 0x1a7260)" % (a, v))
        except Exception as e:
            print("   %#x unreadable %s" % (a, e))

    print()
    print("### CONTROL: the known item vtable 0x1801eaac0")
    for k in range(4):
        t = qword(0x1801eaac0 + k*8)
        print("   slot %+#4x %#x %s" % (k*8, t, fname(t) if 0x180000000 <= t < 0x181000000 else ""))

    print()
    print("### walk back from 0x180215b50 to the start of its pointer table")
    a = 0x180215b50
    start = a
    while True:
        p = a - 8
        try:
            t = qword(p)
        except Exception:
            break
        if not (0x180001000 <= t < 0x1801d0000):
            break
        start = p
        a = p
        if 0x180215b50 - start > 0x800:
            break
    print("   table start %#x, FUN_1800e2a40 is at %#x -> slot %#x (index %d)"
          % (start, 0x180215b50, 0x180215b50 - start, (0x180215b50 - start)//8))
    for off in range(0, 0x180215b50 - start + 0x40, 8):
        t = qword(start + off)
        print("   %+#6x %#x %s" % (off, t, fname(t) if 0x180000000 <= t < 0x181000000 else ""))
except Exception:
    traceback.print_exc()
