uce/spikes/wasm-phase0/wasm_inspect.py
2026-06-12 11:40:26 +00:00

96 lines
3.3 KiB
Python

#!/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)