"""Read-only Go pclntab and direct-call inventory for an explicitly selected PE. This recovers compiled function names and machine-code call edges, not source code or proof that a handler succeeds. CmdIDs require separate wire evidence. """ import argparse import hashlib import json import pathlib import struct from capstone import Cs, CS_ARCH_X86, CS_MODE_64 from capstone.x86 import X86_OP_IMM def dump(path, output): data = path.read_bytes() pe = struct.unpack_from('= 0: try: nfunc, nfiles, text, names, cu, files, pctab, pcln = struct.unpack_from('<8Q', data, start+8) if 0 < nfunc < 1000000 and 0 < nfiles < 1000000 and start+pcln+(nfunc+1)*8 < len(data): if text == 0: text = image_base+next(rva for name,rva,_,_ in sections if name == '.text') offset(text) candidates.append((start, nfunc, text, names, pcln)) except (ValueError, struct.error): pass start += 8 if len(candidates) != 1: raise ValueError(f'Expected one valid Go1.20+ pclntab, found {len(candidates)}') header, nfunc, text, names, pcln = candidates[0] funcs = [] for i in range(nfunc): entry, info = struct.unpack_from('