#!/usr/bin/env python3 """Phase 0 helper: dump a wasm module's imports, exports, and dylink.0 custom section (memory/table size requirements). Doubles as the reference for the loader's dylink.0 parsing (ยง6 step 4).""" import sys, struct def uleb(buf, pos): result = 0 shift = 0 while True: b = buf[pos] pos += 1 result |= (b & 0x7f) << shift if not (b & 0x80): return result, pos shift += 7 def name(buf, pos): n, pos = uleb(buf, pos) return buf[pos:pos+n].decode("utf-8", "replace"), pos + n def limits(buf, pos): flags = buf[pos]; pos += 1 mn, pos = uleb(buf, pos) mx = None if flags & 1: mx, pos = uleb(buf, pos) return (mn, mx), pos KIND = {0: "func", 1: "table", 2: "memory", 3: "global"} VALTYPE = {0x7f: "i32", 0x7e: "i64", 0x7d: "f32", 0x7c: "f64", 0x70: "funcref", 0x6f: "externref"} def main(fn): buf = open(fn, "rb").read() assert buf[:8] == b"\0asm\x01\0\0\0", "not a wasm module" pos = 8 while pos < len(buf): sec_id = buf[pos]; pos += 1 size, pos = uleb(buf, pos) end = pos + size if sec_id == 0: sname, p = name(buf, pos) if sname == "dylink.0": print("== dylink.0 ==") while p < end: sub = buf[p]; p += 1 sublen, p = uleb(buf, p) subend = p + sublen if sub == 1: # WASM_DYLINK_MEM_INFO memsize, p2 = uleb(buf, p) memalign, p2 = uleb(buf, p2) tabsize, p2 = uleb(buf, p2) tabalign, p2 = uleb(buf, p2) print(f" mem_info: memsize={memsize} memalign=2^{memalign} tablesize={tabsize} tablealign=2^{tabalign}") else: print(f" subsection type={sub} len={sublen}") p = subend elif sname in ("uce.abi",): print(f"== custom section {sname} ({end - p} bytes) ==") elif sec_id == 2: count, p = uleb(buf, pos) print(f"== imports ({count}) ==") for _ in range(count): mod, p = name(buf, p) nm, p = name(buf, p) kind = buf[p]; p += 1 detail = "" if kind == 0: _, p = uleb(buf, p) elif kind == 1: et = buf[p]; p += 1 lim, p = limits(buf, p) detail = f" {VALTYPE.get(et, hex(et))} {lim}" elif kind == 2: lim, p = limits(buf, p) detail = f" {lim}" elif kind == 3: vt = buf[p]; p += 1 mut = buf[p]; p += 1 detail = f" {VALTYPE.get(vt, hex(vt))}{' mut' if mut else ''}" print(f" {KIND.get(kind, kind):6} {mod}.{nm}{detail}") elif sec_id == 7: count, p = uleb(buf, pos) print(f"== exports ({count}) ==") for _ in range(count): nm, p = name(buf, p) kind = buf[p]; p += 1 _, p = uleb(buf, p) print(f" {KIND.get(kind, kind):6} {nm}") pos = end if __name__ == "__main__": for fn in sys.argv[1:]: print(f"### {fn}") main(fn)