"""Q17: enumerate EVERY switch case label in the binary, then find the ones that distinguish club subtypes. Q5's scalar scan failed its control because jump-table case labels are not instruction immediates. Ghidra, however, names them: it creates symbols of the form switchD__caseD_ (and caseD_) at each case target. Walking the symbol table therefore enumerates switch dispatch in the one form a scalar scan cannot see. Report every function whose case-value set intersects the club-subtype candidates {0x1e,0x1f,9,10,11,0x91..0x96} and print the full case set for each. CONTROL: FUN_1800d8330 must appear with case labels including 0x1e, 0x1f, 0x91..0x96, 0xe7..0xe9 and 0xec. If it does not, the symbol-based enumeration is broken and no absence claim may be made from it. """ import re import traceback try: st = prog.getSymbolTable() it = st.getAllSymbols(True) pat = re.compile(r"caseD_([0-9a-fA-F]+)$") per = {} n = 0 while it.hasNext(): s = it.next() m = pat.search(s.getName()) if not m: continue n += 1 try: v = int(m.group(1), 16) except ValueError: continue f = fm.getFunctionContaining(s.getAddress()) key = (f.getName(), int(f.getEntryPoint().getOffset())) if f else ("?", 0) per.setdefault(key, set()).add(v) print("case labels found: %d in %d functions" % (n, len(per))) CAND = {0x1E, 0x1F, 9, 10, 11, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96} print() print("=== functions whose case set meets the club-subtype candidates ===") rows = [] for (name, ent), vals in per.items(): inter = vals & CAND if len(inter) >= 2: rows.append((len(inter), name, ent, vals)) rows.sort(reverse=True) for k, name, ent, vals in rows: print(" %-26s %#x hits=%d cases=%s" % (name, ent, k, sorted("%#x" % v for v in vals))) print() print("=== control: FUN_1800d8330 ===") for (name, ent), vals in per.items(): if ent == 0x1800D8330: print(" YES cases=%s" % sorted("%#x" % v for v in vals)) except Exception: traceback.print_exc()