96 lines
3.3 KiB
Python
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)
|