#!/usr/bin/env python3 """Identify every resident record by its wire instance id. Record layout established from known wire values: +0x08 id (wire instance) +0x18 resourceId +0x1c/+0x20 assetId +0x38 discardValue +0x4c cardtype +0x50 cardsubtypeid +0x5c itemState +0x60 category +0x94 teamid +0xb4 rating +0xba teamkittypetechid (u16) Walks the contiguous 0x180-stride pool around the manager slot record so records that are resident but not in any collection are still seen. Read-only. usage: probe_ids.py PID [expected_id ...] """ import re, struct, sys PID = int(sys.argv[1]) WANT = {int(a) for a in sys.argv[2:]} mem = open(f"/proc/{PID}/mem", "rb", buffering=0) def rd(a, n): mem.seek(a); return mem.read(n) def q(a): return struct.unpack("3} {'addr':>12} {'id':>10} {'resource':>9} {'ct':>3} {'sub':>4} " f"{'st':>3} {'cat':>4} {'team':>5} {'rate':>5} {'kt':>6}") found = {} k = 0 addr = lo while k < 48: try: d = dec(addr) except OSError: break if d["id"] == 0 and d["ct"] == 0: break tag = "" if d["ct"] == 7: tag = " <== CARDTYPE 7" if d["id"] in WANT: tag += " <== WANTED" found[d["id"]] = addr slot = " [manager slot]" if addr == mgr_rec else "" print(f" {k:>3} {addr:#12x} {d['id']:>10} {d['res']:>9} {d['ct']:>3} {d['sub']:>4} " f"{d['st']:>3} {d['cat']:>4} {d['team']:>5} {d['rating']:>5} {d['kt']:>6}{tag}{slot}") addr += RECSZ k += 1 if WANT: print(f"\n wanted ids: {sorted(WANT)}") for w in sorted(WANT): print(f" {w}: {'FOUND at ' + hex(found[w]) if w in found else 'NOT RESIDENT'}")