From 6e063dc95562219945dbcb1826c657af4a9e70c3 Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Sat, 29 Feb 2020 21:39:40 -0600 Subject: [PATCH] Initial commit with a substantial amount of code --- Makefile | 7 + clib/buffered_file.h | 56 +++ clib/parse_helper.c | 115 +++++++ clib/parse_helper.so | Bin 0 -> 16936 bytes conf.lua | 6 + data/add.wasm | Bin 0 -> 90 bytes data/main.wasm | Bin 0 -> 1048 bytes data/test.bin | 1 + decompile.lua | 714 +++++++++++++++++++++++++++++++++++++++ docs/todo | 2 + lualib/oop.lua | 316 +++++++++++++++++ lualib/pprint.lua | 475 ++++++++++++++++++++++++++ main.lua | 271 +++++++++++++++ res/FiraCode-Regular.ttf | Bin 0 -> 290360 bytes testing.lua | 11 + ui.lua | 438 ++++++++++++++++++++++++ utils.lua | 101 ++++++ 17 files changed, 2513 insertions(+) create mode 100644 Makefile create mode 100644 clib/buffered_file.h create mode 100644 clib/parse_helper.c create mode 100755 clib/parse_helper.so create mode 100644 conf.lua create mode 100644 data/add.wasm create mode 100755 data/main.wasm create mode 100644 data/test.bin create mode 100644 decompile.lua create mode 100644 docs/todo create mode 100755 lualib/oop.lua create mode 100644 lualib/pprint.lua create mode 100644 main.lua create mode 100644 res/FiraCode-Regular.ttf create mode 100644 testing.lua create mode 100644 ui.lua create mode 100644 utils.lua diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4218884 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +clib/%.o: clib/%.c clib/*.h + gcc -DLUA51_TARGET -O2 -o $@ -fPIC -c $< -llua + +clib/%.so: clib/%.o + gcc -shared -o $@ $< -llua + +all: clib/parse_helper.so diff --git a/clib/buffered_file.h b/clib/buffered_file.h new file mode 100644 index 0000000..91ee50c --- /dev/null +++ b/clib/buffered_file.h @@ -0,0 +1,56 @@ +#ifndef BUFFERED_FILE_H +#define BUFFERED_FILE_H + +#include +#include +#include + +#define BUFFERED_FILE_BUFF_SIZE 4096 +typedef struct { + FILE* fp; + int buff_ptr; + char buff[BUFFERED_FILE_BUFF_SIZE]; +} buffered_file; + +buffered_file* buffered_file_open(const char* filepath) { + buffered_file* bf = (buffered_file*) malloc(sizeof(buffered_file)); + + bf->fp = fopen(filepath, "r"); + if (bf->fp == NULL) { + return NULL; + } + bf->buff_ptr = BUFFERED_FILE_BUFF_SIZE; + + return bf; +} + +bool buffered_file_empty(buffered_file* bf) { + return bf->buff_ptr >= BUFFERED_FILE_BUFF_SIZE && feof(bf->fp); +} + +unsigned char buffered_file_read_byte(buffered_file* bf) { + if (buffered_file_empty(bf)) return 0; + + if (bf->buff_ptr >= BUFFERED_FILE_BUFF_SIZE) { + // Need to read more data + fread(bf->buff, BUFFERED_FILE_BUFF_SIZE, 1, bf->fp); + bf->buff_ptr = 0; + } + + return bf->buff[bf->buff_ptr++]; +} + +unsigned char buffered_file_peek_byte(buffered_file* bf) { + if (buffered_file_empty(bf)) return 0; + + if (bf->buff_ptr >= BUFFERED_FILE_BUFF_SIZE) { + // Need to read more data + fread(bf->buff, BUFFERED_FILE_BUFF_SIZE, 1, bf->fp); + bf->buff_ptr = 0; + } + + return bf->buff[bf->buff_ptr]; +} + + +#endif diff --git a/clib/parse_helper.c b/clib/parse_helper.c new file mode 100644 index 0000000..63cd19f --- /dev/null +++ b/clib/parse_helper.c @@ -0,0 +1,115 @@ +#include +#ifdef LUA51_TARGET + #include + #include + #include +#else + #include + #include + #include +#endif + +#include "buffered_file.h" + +#define new(class, var) class* var = (class*) malloc(sizeof(class)); +#define LUA_FUNCTION(fname) int fname(lua_State *L) + +typedef struct { + buffered_file* file; +} Parser; + +LUA_FUNCTION(open_file) { + const char *filepath = lua_tostring(L, 1); + + new(Parser, parser); + parser->file = buffered_file_open(filepath); + + lua_pushlightuserdata(L, parser); + return 1; +} + +LUA_FUNCTION(is_file_empty) { + Parser* parser = (Parser*) lua_touserdata(L, 1); + + lua_pushboolean(L, buffered_file_empty(parser->file) == 1); + return 1; +} + +LUA_FUNCTION(read_byte) { + Parser* parser = (Parser*) lua_touserdata(L, 1); + + unsigned char byte = buffered_file_read_byte(parser->file); + + lua_pushinteger(L, byte); + return 1; +} + +LUA_FUNCTION(peek_byte) { + Parser* parser = (Parser*) lua_touserdata(L, 1); + + unsigned char byte = buffered_file_peek_byte(parser->file); + + lua_pushinteger(L, byte); + return 1; +} + +LUA_FUNCTION(parse_uleb128) { + Parser* parser = (Parser*) lua_touserdata(L, 1); + + unsigned long long result = 0; + int shift = 0; + unsigned char byte; + + while (1) { + byte = buffered_file_read_byte(parser->file); + result |= (byte & 0x7f) << shift; + if ((byte & 0x80) == 0) + break; + + shift += 7; + } + lua_pushnumber(L, result); + return 1; +} + +LUA_FUNCTION(parse_sleb128) { + Parser* parser = (Parser*) lua_touserdata(L, 1); + int size = lua_tointeger(L, 2); + + long long result = 0; + int shift = 0; + + unsigned char byte; + + do { + byte = buffered_file_read_byte(parser->file); + result |= (byte & 0x7f) << shift; + shift += 7; + } while ((byte & 0x80) != 0); + + if ((shift < size) && (byte & 0x40) > 0) + result |= (~0ll << shift); + + lua_pushnumber(L, (double) result); + return 1; +} + +int luaopen_parse_helper(lua_State* L) { + const luaL_Reg functions[] = { + { "open_file", open_file }, + { "read_byte", read_byte }, + { "peek_byte", peek_byte }, + { "is_file_empty", is_file_empty }, + + { "parse_uleb128", parse_uleb128 }, + { "parse_sleb128", parse_sleb128 }, + { NULL, NULL }, + }; + +#ifdef LUA51_TARGET + luaL_register(L, "parse_helper", functions); +#else + luaL_newlib(L, functions); +#endif + return 1; +} diff --git a/clib/parse_helper.so b/clib/parse_helper.so new file mode 100755 index 0000000000000000000000000000000000000000..50ce0d0731eecaf0c3df4633b53b782285311a67 GIT binary patch literal 16936 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 C{7{wv literal 0 HcmV?d00001 diff --git a/conf.lua b/conf.lua new file mode 100644 index 0000000..3521b8e --- /dev/null +++ b/conf.lua @@ -0,0 +1,6 @@ +function love.conf(t) + t.window.title = "TBD" + t.window.width = 1200 + t.window.height = 900 + t.window.resizable = false +end diff --git a/data/add.wasm b/data/add.wasm new file mode 100644 index 0000000000000000000000000000000000000000..67b8441d5b4fa28cd53853ceb80c6a5b42967b0a GIT binary patch literal 90 zcmWN6o9F=`EN literal 0 HcmV?d00001 diff --git a/data/main.wasm b/data/main.wasm new file mode 100755 index 0000000000000000000000000000000000000000..1c41dc82d29da8f1cb0e262d87b36e3d1675ee7a GIT binary patch literal 1048 zcmY*XO>fjN5S_8(d^v3mXAVw%DM*L|5(iG}OW{KM130wX?W$^;HZ;2xa6s8V!cRj& z;>eF!o}H#GtE@GC^Je_!*)(5WGZFF2{4^Qxqf-$U#-H%<5cXJQ%rQdoBhMDy&8lmc zvh6NNB%I|<)nB^Hn>Dez zTVJ-TqMzTKpPY4FOUa1j5eXC}b;&AKLaL0Vl1xeJ(t-US(pcYyB}UurHq!%z4SAun zlGE$ub=Q9vl=HLlXIdUG50)%9wGcBoLnw}S*rMb;kw?(fRFT&D1)u@7Ju>Mf2y z%#M$GBts8VB(psYh+5RSq_F}`o+Lf}mwt`p8y15j$1Ui!a7oQk23v6m890BG0eu{0 zd9>ni1lAqzI%U zkjx{}1Vq~0skW(0o7f^o+Ll(E0&-#iYY%V3J=7H*sI-;M+Xm#y7Htz|4U+MAtgz+e p2fWc!3~$sJSK+QJTRHU!4l8ubFsF_W>p2-b1p^9JV|I+t{{WGesek|g literal 0 HcmV?d00001 diff --git a/data/test.bin b/data/test.bin new file mode 100644 index 0000000..39e9efe --- /dev/null +++ b/data/test.bin @@ -0,0 +1 @@ +À»x \ No newline at end of file diff --git a/decompile.lua b/decompile.lua new file mode 100644 index 0000000..fee1557 --- /dev/null +++ b/decompile.lua @@ -0,0 +1,714 @@ +-- Recursive decent parser for the WASM v1.0 binary format +-- Brendan Hansen 2020 + +-- Look in clib folder for C-based libraries +package.cpath = package.cpath .. [[;./clib/?.so]] + +import { + parse_helper = "parse_helper"; + pprint = "lualib.pprint"; + + build_str = "utils:build_str"; +} + +VAL_TYPES = { + i32 = "i32", + i64 = "i64", + f32 = "f32", + f64 = "f64" +} + +function parse_valtype(r) + local val = r:read_byte() + + local valtypes_map = { + [0x7f] = VAL_TYPES.i32; + [0x7E] = VAL_TYPES.i64; + [0x7D] = VAL_TYPES.f32; + [0x7C] = VAL_TYPES.f64; + } + + return valtypes_map[val] +end + +function parse_vector(tp) + return function(r) + local n = r:read_uint(32) + + local v = {} + for i=1, n do + table.insert(v, tp(r)) + end + + return v + end +end + +function parse_byte(r) + return r:read_byte() +end + +function parse_name(r) + local name = parse_vector(parse_byte)(r) + return name +end + +function parse_blocktype(r) + if r:peek_byte() == 0x40 then + r:read_byte() + return {} + else + return { parse_valtype(r) } + end +end + +function parse_functype(r) + assert(r:read_byte() == 0x60, "functype expected 0x60 as first byte") + + local params = parse_vector(parse_valtype)(r) + local results = parse_vector(parse_valtype)(r) + + return { param_types = params, result_types = results } +end + +function parse_limits(r) + local t = r:read_byte() + + local min = r:read_uint(32) + local max = nil + if t == 0x01 then + max = r:read_uint(32) + end + + return { min = min, max = max } +end + +function parse_memtype(r) + local lims = parse_limits(r) + + return lims +end + +function parse_tabletype(r) + local elemtype = parse_elemtype(r) + local limits = parse_limits(r) + + return { lim = limits, et = elemtype } +end + +function parse_elemtype(r) + assert(r:read_byte() == 0x70, "elemtype should be 0x70") + return "funcref" +end + +function parse_globaltype(r) + local valtype = parse_valtype(r) + local ismut = parse_mut(r) == 0x01 + + return { t = valtype, m = ismut } +end + +function parse_mut(r) + local v = r:read_byte() + assert(v == 0x00 or v == 0x01, "mut should be 0x00 or 0x01") + return v +end + +function parse_instr(r) + local instr = r:read_byte() + + return match(instr) { + [0x00] = function() return { "unreachable" } end; + [0x01] = function() return { "nop" } end; + [0x02] = function() + local rt = parse_blocktype(r) + local instrs = {} + + while true do + if r:peek_byte() == 0x0B then + r:read_byte() + break + else + table.insert(instrs, parse_instr(r)) + end + end + + return { "block", rt = rt, instrs = instrs } + end; + [0x03] = function() + local rt = parse_blocktype(r) + local instrs = {} + + while true do + if r:peek_byte() == 0x0B then + r:read_byte() + break + else + table.insert(instrs, parse_instr(r)) + end + end + + return { "loop", rt = rt, instrs = instrs } + end; + [0x04] = function() + local rt = parse_blocktype(r) + local instrs = {} + local else_instrs = {} + local inelse = false + + while true do + local peek = r:peek_byte() + if peek == 0x0B then + r:read_byte() + break + elseif peek == 0x05 then + r:read_byte() + inelse = true + else + if not inelse then + table.insert(instrs, parse_instr(r)) + else + table.insert(else_instrs, parse_instr(r)) + end + end + end + + return { "if", rt = rt, instrs = instrs, else_instrs = else_instrs } + end; + + [0x0C] = function() return { "br", x = parse_labelidx(r) } end; + [0x0D] = function() return { "br_if", x = parse_labelidx(r) } end; + [0x0E] = function() + local labels = parse_vector(parse_labelidx)(r) + local labeln = parse_labelidx(r) + + return { "br_table", labels = labels, labeln = labeln } + end; + + [0x0F] = function() return { "return" } end; + + [0x10] = function() return { "call", x = parse_funcidx(r) } end; + [0x11] = function() + local x = parse_typeidx(r) + assert(r:read_byte() ~= 0x00, "call_indirect expects 0x00 at end") + return { "call_indirect", x = x } + end; + + [0x1A] = function() return { "drop" } end; + [0x1B] = function() return { "select" } end; + + [0x20] = function() return { "local.get", x = parse_localidx(r) } end; + [0x21] = function() return { "local.set", x = parse_localidx(r) } end; + [0x22] = function() return { "local.tee", x = parse_localidx(r) } end; + [0x23] = function() return { "global.get", x = parse_globalidx(r) } end; + [0x24] = function() return { "global.set", x = parse_globalidx(r) } end; + + [0x28] = function() return { "i32.load", x = parse_memarg(r) } end; + [0x29] = function() return { "i64.load", x = parse_memarg(r) } end; + [0x2A] = function() return { "f32.load", x = parse_memarg(r) } end; + [0x2B] = function() return { "f64.load", x = parse_memarg(r) } end; + [0x2C] = function() return { "i32.load8_s", x = parse_memarg(r) } end; + [0x2D] = function() return { "i32.load8_u", x = parse_memarg(r) } end; + [0x2E] = function() return { "i32.load16_s", x = parse_memarg(r) } end; + [0x2F] = function() return { "i32.load16_u", x = parse_memarg(r) } end; + [0x30] = function() return { "i64.load8_s", x = parse_memarg(r) } end; + [0x31] = function() return { "i64.load8_u", x = parse_memarg(r) } end; + [0x32] = function() return { "i64.load16_s", x = parse_memarg(r) } end; + [0x33] = function() return { "i64.load16_u", x = parse_memarg(r) } end; + [0x34] = function() return { "i64.load32_s", x = parse_memarg(r) } end; + [0x35] = function() return { "i64.load32_u", x = parse_memarg(r) } end; + [0x36] = function() return { "i32.store", x = parse_memarg(r) } end; + [0x37] = function() return { "i64.store", x = parse_memarg(r) } end; + [0x38] = function() return { "f32.store", x = parse_memarg(r) } end; + [0x39] = function() return { "f64.store", x = parse_memarg(r) } end; + [0x3A] = function() return { "i32.store8", x = parse_memarg(r) } end; + [0x3B] = function() return { "i32.store16", x = parse_memarg(r) } end; + [0x3C] = function() return { "i64.store8", x = parse_memarg(r) } end; + [0x3D] = function() return { "i64.store16", x = parse_memarg(r) } end; + [0x3E] = function() return { "i64.store32", x = parse_memarg(r) } end; + [0x3F] = function() + assert(r:read_byte() == 0x00, "memory.size expects 0x00") + return { "memory.size" } + end; + [0x40] = function() + assert(r:read_byte() == 0x00, "memory.grow expects 0x00") + return { "memory.grow" } + end; + + [0x41] = function() return { "i32.const", x = r:read_sint(32) } end; + [0x42] = function() return { "i64.const", x = r:read_sint(64) } end; + [0x43] = function() return { "f32.const", x = r:read_float(32) } end; + [0x44] = function() return { "f64.const", x = r:read_float(64) } end; + + [0x45] = function() return { "i32.eqz" } end; + [0x46] = function() return { "i32.eq" } end; + [0x47] = function() return { "i32.ne" } end; + [0x48] = function() return { "i32.lt_s" } end; + [0x49] = function() return { "i32.lt_u" } end; + [0x4A] = function() return { "i32.gt_s" } end; + [0x4B] = function() return { "i32.gt_u" } end; + [0x4C] = function() return { "i32.le_s" } end; + [0x4D] = function() return { "i32.le_u" } end; + [0x4E] = function() return { "i32.ge_s" } end; + [0x4F] = function() return { "i32.ge_u" } end; + [0x50] = function() return { "i64.eqz" } end; + [0x51] = function() return { "i64.eq" } end; + [0x52] = function() return { "i64.ne" } end; + [0x53] = function() return { "i64.lt_s" } end; + [0x54] = function() return { "i64.lt_u" } end; + [0x55] = function() return { "i64.gt_s" } end; + [0x56] = function() return { "i64.gt_u" } end; + [0x57] = function() return { "i64.le_s" } end; + [0x58] = function() return { "i64.le_u" } end; + [0x59] = function() return { "i64.ge_s" } end; + [0x5A] = function() return { "i64.ge_u" } end; + [0x5B] = function() return { "f32.eq" } end; + [0x5C] = function() return { "f32.ne" } end; + [0x5D] = function() return { "f32.lt" } end; + [0x5E] = function() return { "f32.gt" } end; + [0x5F] = function() return { "f32.le" } end; + [0x60] = function() return { "f32.ge" } end; + [0x61] = function() return { "f64.eq" } end; + [0x62] = function() return { "f64.ne" } end; + [0x63] = function() return { "f64.lt" } end; + [0x64] = function() return { "f64.gt" } end; + [0x65] = function() return { "f64.le" } end; + [0x66] = function() return { "f64.ge" } end; + [0x67] = function() return { "i32.clz" } end; + [0x68] = function() return { "i32.ctz" } end; + [0x69] = function() return { "i32.popcnt" } end; + [0x6A] = function() return { "i32.add" } end; + [0x6B] = function() return { "i32.sub" } end; + [0x6C] = function() return { "i32.mul" } end; + [0x6D] = function() return { "i32.div_s" } end; + [0x6E] = function() return { "i32.div_u" } end; + [0x6F] = function() return { "i32.rem_s" } end; + [0x70] = function() return { "i32.rem_u" } end; + [0x71] = function() return { "i32.and" } end; + [0x72] = function() return { "i32.or" } end; + [0x73] = function() return { "i32.xor" } end; + [0x74] = function() return { "i32.shl" } end; + [0x75] = function() return { "i32.shr_s" } end; + [0x76] = function() return { "i32.shr_u" } end; + [0x77] = function() return { "i32.rotl" } end; + [0x78] = function() return { "i32.rotr" } end; + [0x79] = function() return { "i64.clz" } end; + [0x7A] = function() return { "i64.ctz" } end; + [0x7B] = function() return { "i64.popcnt" } end; + [0x7C] = function() return { "i64.add" } end; + [0x7D] = function() return { "i64.sub" } end; + [0x7E] = function() return { "i64.mul" } end; + [0x7F] = function() return { "i64.div_s" } end; + [0x80] = function() return { "i64.div_u" } end; + [0x81] = function() return { "i64.rem_s" } end; + [0x82] = function() return { "i64.rem_u" } end; + [0x83] = function() return { "i64.and" } end; + [0x84] = function() return { "i64.or" } end; + [0x85] = function() return { "i64.xor" } end; + [0x86] = function() return { "i64.shl" } end; + [0x87] = function() return { "i64.shr_s" } end; + [0x88] = function() return { "i64.shr_u" } end; + [0x89] = function() return { "i64.rotl" } end; + [0x8A] = function() return { "i64.rotr" } end; + [0x8B] = function() return { "f32.abs" } end; + [0x8C] = function() return { "f32.neg" } end; + [0x8D] = function() return { "f32.ceil" } end; + [0x8E] = function() return { "f32.floor" } end; + [0x8F] = function() return { "f32.trunc" } end; + [0x90] = function() return { "f32.nearest" } end; + [0x91] = function() return { "f32.sqrt" } end; + [0x92] = function() return { "f32.add" } end; + [0x93] = function() return { "f32.sub" } end; + [0x94] = function() return { "f32.mul" } end; + [0x95] = function() return { "f32.div" } end; + [0x96] = function() return { "f32.min" } end; + [0x97] = function() return { "f32.max" } end; + [0x98] = function() return { "f32.copysign" } end; + [0x99] = function() return { "f64.abs" } end; + [0x9A] = function() return { "f64.neg" } end; + [0x9B] = function() return { "f64.ceil" } end; + [0x9C] = function() return { "f64.floor" } end; + [0x9D] = function() return { "f64.trunc" } end; + [0x9E] = function() return { "f64.nearest" } end; + [0x9F] = function() return { "f64.sqrt" } end; + [0xA0] = function() return { "f64.add" } end; + [0xA1] = function() return { "f64.sub" } end; + [0xA2] = function() return { "f64.mul" } end; + [0xA3] = function() return { "f64.div" } end; + [0xA4] = function() return { "f64.min" } end; + [0xA5] = function() return { "f64.max" } end; + [0xA6] = function() return { "f64.copysign" } end; + + [0xA7] = function() return { "i32.wrap_i64" } end; + [0xA8] = function() return { "i32.trunc_f32_s" } end; + [0xA9] = function() return { "i32.trunc_f32_u" } end; + [0xAA] = function() return { "i32.trunc_f64_s" } end; + [0xAB] = function() return { "i32.trunc_f64_u" } end; + [0xAC] = function() return { "i64.extend_i32_s" } end; + [0xAD] = function() return { "i64.extend_i32_u" } end; + [0xAE] = function() return { "i64.trunc_f32_s" } end; + [0xAF] = function() return { "i64.trunc_f32_u" } end; + [0xB0] = function() return { "i64.trunc_f64_s" } end; + [0xB1] = function() return { "i64.trunc_f64_u" } end; + [0xB2] = function() return { "f32.convert_i32_s" } end; + [0xB3] = function() return { "f32.convert_i32_u" } end; + [0xB4] = function() return { "f32.convert_i64_s" } end; + [0xB5] = function() return { "f32.convert_i64_u" } end; + [0xB6] = function() return { "f32.demote_f64" } end; + [0xB7] = function() return { "f64.convert_i32_s" } end; + [0xB8] = function() return { "f64.convert_i32_u" } end; + [0xB9] = function() return { "f64.convert_i64_s" } end; + [0xBA] = function() return { "f64.convert_i64_u" } end; + [0xBB] = function() return { "f64.promote_f32" } end; + [0xBC] = function() return { "i32.reinterpret_f32" } end; + [0xBD] = function() return { "i64.reinterpret_f64" } end; + [0xBE] = function() return { "f32.reinterpret_i32" } end; + [0xBF] = function() return { "f64.reinterpret_i64" } end; + } +end + +function parse_memarg(r) + local a = r:read_uint(32) + local o = r:read_uint(32) + + return { "memarg"; align = a; offset = o } +end + +function parse_expr(r) + local instrs = {} + while true do + if r:peek_byte() == 0x0B then + r:read_byte() + break + else + table.insert(instrs, parse_instr(r)) + end + end + + return instrs +end + +function parse_typeidx(r) return r:read_uint(32) end +function parse_funcidx(r) return r:read_uint(32) end +function parse_tableidx(r) return r:read_uint(32) end +function parse_memidx(r) return r:read_uint(32) end +function parse_globalidx(r) return r:read_uint(32) end +function parse_localidx(r) return r:read_uint(32) end +function parse_labelidx(r) return r:read_uint(32) end + +function parse_section(r, expectN, B) + if r:peek_byte() ~= expectN then return end + + local N = r:read_byte() + local size = r:read_uint(32) + local cont = B(r) + + return { "section", contents = cont, size = size } +end + +function parse_customsec(r) + local csect = parse_section(r, 0, parse_custom) + if not csect then return nil end + + for i=1, csect.size do + -- Discard csect.size bytes + r:read_byte() + end + return csect +end + +function parse_custom(r) + local name = parse_name(r) + + return { "custom", name = name } +end + +function parse_typesec(r) + return parse_section(r, 1, parse_vector(parse_functype)) +end + +function parse_importsec(r) + return parse_section(r, 2, parse_vector(parse_import)) +end + +function parse_import(r) + local mod = parse_name(r) + local nm = parse_name(r) + local d = parse_importdesc(r) + + return { "import", mod = mod, name = nm, desc = d } +end + +function parse_importdesc(r) + local t = r:read_byte() + if t == 0x00 then return { "func", x = parse_typeidx(r) } + elseif t == 0x01 then return { "table", tt = parse_tabletype(r) } + elseif t == 0x02 then return { "mem", mt = parse_memtype(r) } + elseif t == 0x03 then return { "global", gt = parse_globaltype(r) } + end + + error("bad importdesc") +end + +function parse_funcsec(r) + return parse_section(r, 3, parse_vector(parse_typeidx)) +end + +function parse_tablesec(r) + return parse_section(r, 4, parse_vector(parse_table)) +end + +function parse_table(r) + local tt = parse_tabletype(r) + return { "table", type_ = tt } +end + +function parse_memsec(r) + return parse_section(r, 5, parse_vector(parse_mem)) +end + +function parse_mem(r) + local mt = parse_memtype(r) + return { "mem", type_ = mt } +end + +function parse_globalsec(r) + return parse_section(r, 6, parse_vector(parse_global)) +end + +function parse_global(r) + local gt = parse_globaltype(r) + local e = parse_expr(r) + return { "global", type_ = gt, init = e } +end + +function parse_exportsec(r) + return parse_section(r, 7, parse_vector(parse_export)) +end + +function parse_export(r) + local nm = parse_name(r) + local d = parse_exportdesc(r) + return { "export", name = nm, desc = d } +end + +function parse_exportdesc(r) + local t = r:read_byte() + if t == 0x00 then return { "func", x = parse_typeidx(r) } + elseif t == 0x01 then return { "table", tt = parse_tableidx(r) } + elseif t == 0x02 then return { "mem", mt = parse_memidx(r) } + elseif t == 0x03 then return { "global", gt = parse_globalidx(r) } + end + + error("bad exportdesc: ", t) +end + +function parse_startsec(r) + return parse_section(r, 8, parse_start) +end + +function parse_start(r) + local x = parse_funcidx(r) + return { "start", func = x } +end + +function parse_elemsec(r) + return parse_section(r, 9, parse_vector(parse_elem)) +end + +function parse_elem(r) + local x = parse_tableidx(r) + local e = parse_expr(r) + local y = parse_vector(parse_funcidx)(r) + + return { "elem", table = x, offset = e, init = y } +end + +function parse_codesec(r) + return parse_section(r, 10, parse_vector(parse_code)) +end + +function parse_code(r) + local size = r:read_uint(32) + local code = parse_func(r) + return code +end + +function parse_func(r) + local t = parse_vector(parse_locals)(r) + local e = parse_expr(r) + + local localidx = 0 + local locals = {} + for _, v in ipairs(t) do + for _, l in ipairs(v) do + l.localidx = localidx + table.insert(locals, l) + localidx = localidx + 1 + end + end + + return { "func", locals = locals, body = e } +end + +function parse_locals(r) + local n = r:read_uint(32) + local t = parse_valtype(r) + + --TODO: Make a list of values with names like local0, local1, ... + + local locals = {} + for i = 0, n - 1 do + table.insert(locals, { + name = "local" .. i, + type_ = t, + localidx = i + }) + end + + return locals +end + +function parse_datasec(r) + return parse_section(r, 11, parse_vector(parse_data)) +end + +function parse_data(r) + local x = parse_memidx(r) + local e = parse_expr(r) + local b = parse_vector(parse_byte)(r) + + return { "data", data = x, offset = e, init = b } +end + +function parse_magic(r) + assert(r:read_byte() == 0x00, "magic string is wrong") + assert(r:read_byte() == 0x61, "magic string is wrong") + assert(r:read_byte() == 0x73, "magic string is wrong") + assert(r:read_byte() == 0x6D, "magic string is wrong") +end + +function parse_version(r) + assert(r:read_byte() == 0x01, "version is wrong") + assert(r:read_byte() == 0x00, "version is wrong") + assert(r:read_byte() == 0x00, "version is wrong") + assert(r:read_byte() == 0x00, "version is wrong") +end + +function parse_module(r) + parse_magic(r) + parse_version(r) + + local functypes = parse_typesec(r) + local imports = parse_importsec(r) + local typeidxs = parse_funcsec(r) + local tables = parse_tablesec(r) + local mems = parse_memsec(r) + local globals = parse_globalsec(r) + local exports = parse_exportsec(r) + local start = parse_startsec(r) + local elems = parse_elemsec(r) + local codes = parse_codesec(r) + local data = parse_datasec(r) + + local funcs = {} + local funcidx = 0 + + if imports then + for k, v in ipairs(imports.contents) do + if v.desc[1] == "func" then + funcs[funcidx] = { + name = build_str(v.mod) .. "." .. build_str(v.name); + funcidx = funcidx; + type_ = functypes.contents[v.desc.x + 1]; + } + funcidx = funcidx + 1 + end + end + end + + if codes then + for i=1, #codes.contents do + local locals = codes.contents[i].locals; + local type_ = functypes.contents[typeidxs.contents[i] + 1]; + local param_types = type_.param_types; + + local new_locals = {} + local new_local_idx = 0 + for _, p in ipairs(param_types) do + table.insert(new_locals, { + name = "param" .. new_local_idx, + type_ = p; + localidx = new_local_idx + }) + new_local_idx = new_local_idx + 1 + end + for _, l in ipairs(locals) do + l.localidx = new_local_idx + table.insert(new_locals, l) + new_local_idx = new_local_idx + 1 + end + + funcs[funcidx] = { + funcidx = funcidx; + name = "func" .. funcidx; + type_ = functypes.contents[typeidxs.contents[i] + 1]; + locals = new_locals; + body = codes.contents[i].body + } + funcidx = funcidx + 1 + end + end + + return { + "module"; + types = functypes; + tables = tables; + mems = mems; + globals = globas; + exports = exports; + start = start; + elems = elems; + data = data; + imports = imports; + funcs = funcs; + } +end + + +-- Reader util class used for interfacing +-- with the parse_helper c library +class "Reader" { + init = function(self, filename) + self.wasm_file = parse_helper.open_file(filename) + end; + + read_byte = function(self) + return parse_helper.read_byte(self.wasm_file) + end; + + peek_byte = function(self) + return parse_helper.peek_byte(self.wasm_file) + end; + + -- NOTE: N is unused + read_uint = function(self, N) + return parse_helper.parse_uleb128(self.wasm_file) + end; + + read_sint = function(self, N) + return parse_helper.parse_sleb128(self.wasm_file, N) + end; + + read_float = function(self, N) + return 0.0; + end; +} + +function decompile(filepath) + local reader = Reader(filepath) + + return parse_module(reader) +end + +return module { decompile; VAL_TYPES = VAL_TYPES } diff --git a/docs/todo b/docs/todo new file mode 100644 index 0000000..f3fb67e --- /dev/null +++ b/docs/todo @@ -0,0 +1,2 @@ +After experimenting with using Lua for the parser, I think it will be better to write the parser in C / C++ +and then have a function that converts all the data to a lua table that will be used for visualization / examination. diff --git a/lualib/oop.lua b/lualib/oop.lua new file mode 100755 index 0000000..bf4a9e8 --- /dev/null +++ b/lualib/oop.lua @@ -0,0 +1,316 @@ +--Under MIT License +--Originally developed by Brendan Hansen +--Copyright 2017 + +--[[ found on http://lua-users.org/lists/lua-l/2010-06/msg00314.html ]] +setfenv = setfenv or function(f, t) + f = (type(f) == 'function' and f or debug.getinfo(f + 1, 'f').func) + local name + local up = 0 + repeat + up = up + 1 + name = debug.getupvalue(f, up) + until name == '_ENV' or name == nil + if name then + debug.upvaluejoin(f, up, function() return t end, 1) -- use unique upvalue, set it to f + end +end + +getfenv = getfenv or function(fn) + local i = 1 + while true do + local name, val = debug.getupvalue(fn, i) + if name == "_ENV" then + return val + elseif not name then + break + end + i = i + 1 + end +end + +local function helper(obj, super, f) + return function(...) + local a = { ... } + local data = a[#a] + local env = getfenv(2) + + data.extends = super + env[obj] = f(data) + end +end + + +--[[ + Module System + "imports" are defined by: + import { + NAME = "path.to.lua.file"; + NAME = "path.to.lua.file:specific_import"; + NAME = "path.to.lua.file:"; --this uses the default export (see below) + } + + "exports" are defined by: + return module { + the_default_export_variable; + other_export=some_value; + } +]] + +local ALL_DEPS = {} +function import(reqs) + local function convertPath(req) + local r = req + if req:find(":") ~= nil then + r = req:sub(1, req:find(":") - 1) + end + r = r:gsub("%.", "/") + return r + end + + local function getField(req) + if req:find(":") ~= nil then + if req:sub(-1) == ":" then + return "default" + else + return req:sub(req:find(":")+1) + end + else + return nil + end + end + + local dep = {} + for name, req in pairs(reqs) do + if type(req) ~= "string" then + error "Please use strings for referencing modules" + end + + local mod = require(convertPath(req)) + dep[name] = mod + + if type(mod) == "table" then + local field = getField(req) + if field ~= nil then + if mod[field] ~= nil then + dep[name] = mod[field] + else + dep[name] = nil + end + end + end + end + + local newenv = setmetatable({}, { + __index = function(_, k) + local v = dep[k] + if v == nil then v = _G[k] end + return v + end; + __newindex = function(_, k, v) + dep[k] = v; + end; + }) + setfenv(2, newenv) +end + +function module(exp) + exp["default"] = exp[1] + exp[1] = nil + return exp +end + +--[[ + Data - basically tables that can only hold numbers, strings, bools, tables, or nil (no functions) +]] +function data(d) + for k, v in pairs(d) do + if type(v) == "function" then + d[k] = nil + end + end + return d +end + +--[[ + Factories - basically tables that can only hold functions, normally static +]] +function factory(f) + for k, v in pairs(f) do + if type(v) ~= "function" then + f[k] = nil + end + end + return f +end + +--[[ + Classes - factories with a initializer and a self-reference, and are allowed to hold variables + + Initialize with "init" + Create new instance by calling name of class + local ClassName = class { ... } + local ClassName = Base.extend { ... } + local instance_a = ClassName(args) + + Can also declare classes as + class "ClassName" { ... } + or + class "ClassName extends Base" { ... } + or + class "ClassName" ["Base"] { ... } +]] +function class(obj) + if type(obj) == "string" then + local sub, super = obj:match "(%w+) +extends +(%w+)" + if sub then obj = sub end + + if super then + return helper(obj, super, class) + else + local o = {} + o = setmetatable(o, { + __call = helper(obj, nil, class); + + __index = function(_, super) + return helper(obj, super, class) + end; + }) + return o + end + end + + local cls = {} + if obj.extends ~= nil then + for k, v in pairs(obj.extends) do + cls[k] = v + end + end + + for k, v in pairs(obj) do + if k ~= "extends" then + cls[k] = v + end + end + + cls = setmetatable(cls, { + __call = function(_, ...) + local o = {} + local mt = {} + + for k, v in pairs(cls) do + if k:sub(0, 2) == "__" then + mt[k] = v + end + end + + mt.__index = cls + o = setmetatable(o, mt) + + if cls.init then + cls.init(o, ...) + end + + return o + end + }) + + cls.extend = function(d) + d.extends = cls + return class(d) + end + + return cls; +end + +--[[ + Singleton - a single instance of a class +]] +function singleton(obj) + return (class(obj))() +end + +function enum(obj) + if type(obj) == "string" then + return helper(obj, nil, enum) + end + + local i = 0 + for k, v in pairs(obj) do + obj[k] = nil + if type(v) == "string" then + obj[v] = i + i = i + 1 + end + end + return obj +end + +function interface(fns) + if type(fns) == "string" then + local sub, super = fns:match "(%w+) +extends +(%w+)" + if sub then fns = sub end + + if super then + return helper(fns, super, interface) + else + local int = {} + int = setmetatable(int, { + __call = helper(fns, nil, interface); + + __index = function(_, super) + return helper(fns, super, interface) + end; + }) + return int + end + end + + local int = {} + for k, v in pairs(fns) do + if type(v) == "string" then + int[v] = function(self) end + end + end + + if fns.extends then + for k, v in pairs(fns.extends) do + if type(v) == "function" then + int[k] = function(self) end + end + end + end + + local mt = { + __call = function(_, ...) + error "Interfaces cannot be instatiated with a constructor" + end; + } + int = setmetatable(int, mt) + + return int +end + +function match(var) + return function(tab) + local ran = false + for k, v in pairs(tab) do + if k ~= "default" and var == k then + return v() + end + end + + if tab["default"] then + tab["default"]() + end + end +end + +function with(o) + return function(tab) + for k, v in pairs(tab) do + o[k] = v + end + return o + end +end diff --git a/lualib/pprint.lua b/lualib/pprint.lua new file mode 100644 index 0000000..2245484 --- /dev/null +++ b/lualib/pprint.lua @@ -0,0 +1,475 @@ +local pprint = { VERSION = '0.1' } + +local depth = 1 + +pprint.defaults = { + -- If set to number N, then limit table recursion to N deep. + depth_limit = false, + -- type display trigger, hide not useful datatypes by default + -- custom types are treated as table + show_nil = true, + show_boolean = true, + show_number = true, + show_string = true, + show_table = true, + show_function = false, + show_thread = false, + show_userdata = false, + -- additional display trigger + show_metatable = false, -- show metatable + show_all = false, -- override other show settings and show everything + use_tostring = false, -- use __tostring to print table if available + filter_function = nil, -- called like callback(value[,key, parent]), return truty value to hide + object_cache = 'local', -- cache blob and table to give it a id, 'local' cache per print, 'global' cache + -- per process, falsy value to disable (might cause infinite loop) + -- format settings + indent_size = 2, -- indent for each nested table level + level_width = 80, -- max width per indent level + wrap_string = true, -- wrap string when it's longer than level_width + wrap_array = false, -- wrap every array elements + sort_keys = true, -- sort table keys +} + +local TYPES = { + ['nil'] = 1, ['boolean'] = 2, ['number'] = 3, ['string'] = 4, + ['table'] = 5, ['function'] = 6, ['thread'] = 7, ['userdata'] = 8 +} + +-- seems this is the only way to escape these, as lua don't know how to map char '\a' to 'a' +local ESCAPE_MAP = { + ['\a'] = '\\a', ['\b'] = '\\b', ['\f'] = '\\f', ['\n'] = '\\n', ['\r'] = '\\r', + ['\t'] = '\\t', ['\v'] = '\\v', ['\\'] = '\\\\', +} + +-- generic utilities +local function escape(s) + s = s:gsub('([%c\\])', ESCAPE_MAP) + local dq = s:find('"') + local sq = s:find("'") + if dq and sq then + return s:gsub('"', '\\"'), '"' + elseif sq then + return s, '"' + else + return s, "'" + end +end + +local function is_plain_key(key) + return type(key) == 'string' and key:match('^[%a_][%a%d_]*$') +end + +local CACHE_TYPES = { + ['table'] = true, ['function'] = true, ['thread'] = true, ['userdata'] = true +} + +-- cache would be populated to be like: +-- { +-- function = { `fun1` = 1, _cnt = 1 }, -- object id +-- table = { `table1` = 1, `table2` = 2, _cnt = 2 }, +-- visited_tables = { `table1` = 7, `table2` = 8 }, -- visit count +-- } +-- use weakrefs to avoid accidentall adding refcount +local function cache_apperance(obj, cache, option) + if not cache.visited_tables then + cache.visited_tables = setmetatable({}, {__mode = 'k'}) + end + local t = type(obj) + + -- TODO can't test filter_function here as we don't have the ix and key, + -- might cause different results? + -- respect show_xxx and filter_function to be consistent with print results + if (not TYPES[t] and not option.show_table) + or (TYPES[t] and not option['show_'..t]) then + return + end + + if CACHE_TYPES[t] or TYPES[t] == nil then + if not cache[t] then + cache[t] = setmetatable({}, {__mode = 'k'}) + cache[t]._cnt = 0 + end + if not cache[t][obj] then + cache[t]._cnt = cache[t]._cnt + 1 + cache[t][obj] = cache[t]._cnt + end + end + if t == 'table' or TYPES[t] == nil then + if cache.visited_tables[obj] == false then + -- already printed, no need to mark this and its children anymore + return + elseif cache.visited_tables[obj] == nil then + cache.visited_tables[obj] = 1 + else + -- visited already, increment and continue + cache.visited_tables[obj] = cache.visited_tables[obj] + 1 + return + end + for k, v in pairs(obj) do + cache_apperance(k, cache, option) + cache_apperance(v, cache, option) + end + local mt = getmetatable(obj) + if mt and option.show_metatable then + cache_apperance(mt, cache, option) + end + end +end + +-- makes 'foo2' < 'foo100000'. string.sub makes substring anyway, no need to use index based method +local function str_natural_cmp(lhs, rhs) + while #lhs > 0 and #rhs > 0 do + local lmid, lend = lhs:find('%d+') + local rmid, rend = rhs:find('%d+') + if not (lmid and rmid) then return lhs < rhs end + + local lsub = lhs:sub(1, lmid-1) + local rsub = rhs:sub(1, rmid-1) + if lsub ~= rsub then + return lsub < rsub + end + + local lnum = tonumber(lhs:sub(lmid, lend)) + local rnum = tonumber(rhs:sub(rmid, rend)) + if lnum ~= rnum then + return lnum < rnum + end + + lhs = lhs:sub(lend+1) + rhs = rhs:sub(rend+1) + end + return lhs < rhs +end + +local function cmp(lhs, rhs) + local tleft = type(lhs) + local tright = type(rhs) + if tleft == 'number' and tright == 'number' then return lhs < rhs end + if tleft == 'string' and tright == 'string' then return str_natural_cmp(lhs, rhs) end + if tleft == tright then return str_natural_cmp(tostring(lhs), tostring(rhs)) end + + -- allow custom types + local oleft = TYPES[tleft] or 9 + local oright = TYPES[tright] or 9 + return oleft < oright +end + +-- setup option with default +local function make_option(option) + if option == nil then + option = {} + end + for k, v in pairs(pprint.defaults) do + if option[k] == nil then + option[k] = v + end + if option.show_all then + for t, _ in pairs(TYPES) do + option['show_'..t] = true + end + option.show_metatable = true + end + end + return option +end + +-- override defaults and take effects for all following calls +function pprint.setup(option) + pprint.defaults = make_option(option) +end + +-- format lua object into a string +function pprint.pformat(obj, option, printer) + option = make_option(option) + local buf = {} + local function default_printer(s) + table.insert(buf, s) + end + printer = printer or default_printer + + local cache + if option.object_cache == 'global' then + -- steal the cache into a local var so it's not visible from _G or anywhere + -- still can't avoid user explicitly referentce pprint._cache but it shouldn't happen anyway + cache = pprint._cache or {} + pprint._cache = nil + elseif option.object_cache == 'local' then + cache = {} + end + + local last = '' -- used for look back and remove trailing comma + local status = { + indent = '', -- current indent + len = 0, -- current line length + } + + local wrapped_printer = function(s) + printer(last) + last = s + end + + local function _indent(d) + status.indent = string.rep(' ', d + #(status.indent)) + end + + local function _n(d) + wrapped_printer('\n') + wrapped_printer(status.indent) + if d then + _indent(d) + end + status.len = 0 + return true -- used to close bracket correctly + end + + local function _p(s, nowrap) + status.len = status.len + #s + if not nowrap and status.len > option.level_width then + _n() + wrapped_printer(s) + status.len = #s + else + wrapped_printer(s) + end + end + + local formatter = {} + local function format(v) + local f = formatter[type(v)] + f = f or formatter.table -- allow patched type() + if option.filter_function and option.filter_function(v, nil, nil) then + return '' + else + return f(v) + end + end + + local function tostring_formatter(v) + return tostring(v) + end + + local function number_formatter(n) + return n == math.huge and '[[math.huge]]' or tostring(n) + end + + local function nop_formatter(v) + return '' + end + + local function make_fixed_formatter(t, has_cache) + if has_cache then + return function (v) + return string.format('[[%s %d]]', t, cache[t][v]) + end + else + return function (v) + return '[['..t..']]' + end + end + end + + local function string_formatter(s, force_long_quote) + local s, quote = escape(s) + local quote_len = force_long_quote and 4 or 2 + if quote_len + #s + status.len > option.level_width then + _n() + -- only wrap string when is longer than level_width + if option.wrap_string and #s + quote_len > option.level_width then + -- keep the quotes together + _p('[[') + while #s + status.len >= option.level_width do + local seg = option.level_width - status.len + _p(string.sub(s, 1, seg), true) + _n() + s = string.sub(s, seg+1) + end + _p(s) -- print the remaining parts + return ']]' + end + end + + return force_long_quote and '[['..s..']]' or quote..s..quote + end + + local function table_formatter(t) + if option.use_tostring then + local mt = getmetatable(t) + if mt and mt.__tostring then + return string_formatter(tostring(t), true) + end + end + + local print_header_ix = nil + local ttype = type(t) + if option.object_cache then + local cache_state = cache.visited_tables[t] + local tix = cache[ttype][t] + -- FIXME should really handle `cache_state == nil` + -- as user might add things through filter_function + if cache_state == false then + -- already printed, just print the the number + return string_formatter(string.format('%s %d', ttype, tix), true) + elseif cache_state > 1 then + -- appeared more than once, print table header with number + print_header_ix = tix + cache.visited_tables[t] = false + else + -- appeared exactly once, print like a normal table + end + end + + local limit = tonumber(option.depth_limit) + if limit and depth > limit then + if print_header_ix then + return string.format('[[%s %d]]...', ttype, print_header_ix) + end + return string_formatter(tostring(t), true) + end + + local tlen = #t + local wrapped = false + _p('{') + _indent(option.indent_size) + _p(string.rep(' ', option.indent_size - 1)) + if print_header_ix then + _p(string.format('--[[%s %d]] ', ttype, print_header_ix)) + end + for ix = 1,tlen do + local v = t[ix] + if formatter[type(v)] == nop_formatter or + (option.filter_function and option.filter_function(v, ix, t)) then + -- pass + else + if option.wrap_array then + wrapped = _n() + end + depth = depth+1 + _p(format(v)..', ') + depth = depth-1 + end + end + + -- hashmap part of the table, in contrast to array part + local function is_hash_key(k) + if type(k) ~= 'number' then + return true + end + + local numkey = math.floor(tonumber(k)) + if numkey ~= k or numkey > tlen or numkey <= 0 then + return true + end + end + + local function print_kv(k, v, t) + -- can't use option.show_x as obj may contain custom type + if formatter[type(v)] == nop_formatter or + formatter[type(k)] == nop_formatter or + (option.filter_function and option.filter_function(v, k, t)) then + return + end + wrapped = _n() + if is_plain_key(k) then + _p(k, true) + else + _p('[') + -- [[]] type string in key is illegal, needs to add spaces inbetween + local k = format(k) + if string.match(k, '%[%[') then + _p(' '..k..' ', true) + else + _p(k, true) + end + _p(']') + end + _p(' = ', true) + depth = depth+1 + _p(format(v), true) + depth = depth-1 + _p(',', true) + end + + if option.sort_keys then + local keys = {} + for k, _ in pairs(t) do + if is_hash_key(k) then + table.insert(keys, k) + end + end + table.sort(keys, cmp) + for _, k in ipairs(keys) do + print_kv(k, t[k], t) + end + else + for k, v in pairs(t) do + if is_hash_key(k) then + print_kv(k, v, t) + end + end + end + + if option.show_metatable then + local mt = getmetatable(t) + if mt then + print_kv('__metatable', mt, t) + end + end + + _indent(-option.indent_size) + -- make { } into {} + last = string.gsub(last, '^ +$', '') + -- peek last to remove trailing comma + last = string.gsub(last, ',%s*$', ' ') + if wrapped then + _n() + end + _p('}') + + return '' + end + + -- set formatters + formatter['nil'] = option.show_nil and tostring_formatter or nop_formatter + formatter['boolean'] = option.show_boolean and tostring_formatter or nop_formatter + formatter['number'] = option.show_number and number_formatter or nop_formatter -- need to handle math.huge + formatter['function'] = option.show_function and make_fixed_formatter('function', option.object_cache) or nop_formatter + formatter['thread'] = option.show_thread and make_fixed_formatter('thread', option.object_cache) or nop_formatter + formatter['userdata'] = option.show_userdata and make_fixed_formatter('userdata', option.object_cache) or nop_formatter + formatter['string'] = option.show_string and string_formatter or nop_formatter + formatter['table'] = option.show_table and table_formatter or nop_formatter + + if option.object_cache then + -- needs to visit the table before start printing + cache_apperance(obj, cache, option) + end + + _p(format(obj)) + printer(last) -- close the buffered one + + -- put cache back if global + if option.object_cache == 'global' then + pprint._cache = cache + end + + return table.concat(buf) +end + +-- pprint all the arguments +function pprint.pprint( ... ) + local args = {...} + -- select will get an accurate count of array len, counting trailing nils + local len = select('#', ...) + for ix = 1,len do + pprint.pformat(args[ix], nil, io.write) + io.write('\n') + end +end + +setmetatable(pprint, { + __call = function (_, ...) + pprint.pprint(...) + end +}) + +return pprint + diff --git a/main.lua b/main.lua new file mode 100644 index 0000000..1dc3e36 --- /dev/null +++ b/main.lua @@ -0,0 +1,271 @@ +-- Required to use the import and class statements +require "lualib.oop" + +import { + decompile = "decompile:"; + VAL_TYPES = "decompile:VAL_TYPES"; + + Ui = "ui:Ui"; + UiRegion = "ui:UiRegion"; + ScrollingUiRegion = "ui:ScrollingUiRegion"; + DraggableRect = "ui:DraggableRect"; + + render_text = "ui:render_text"; + + pprint = "lualib.pprint"; +} + +function build_func_header_text(func, mod) + local text = {} + + table.insert(text, { text = "[" .. func.funcidx .. "] ", color = { 0, 0, 0 } }) + table.insert(text, { text = func.name, color = { 0, 0, 1 } }) + table.insert(text, { text = ": ", color = { 0, 0, 0 } }) + + local type_ = func.type_ + for _, t in ipairs(type_.param_types) do + table.insert(text, { text = t .. " ", color = { 0, 0, 0 } }) + end + + if #type_.param_types == 0 then + table.insert(text, { text = "void ", color = { 0, 0, 0 } }) + end + + table.insert(text, { text = "-> ", color = { 0, 0, 0 } }) + + for _, t in ipairs(type_.result_types) do + table.insert(text, { text = t .. " ", color = { 0, 0, 0 } }) + end + + + if #type_.result_types == 0 then + table.insert(text, { text = "void", color = { 0, 0, 0 } }) + end + + table.insert(text, { newline = true }) + + return text +end + +local line = 1 + +function add_line_number(textlist, newline) + if newline == nil then newline = true end + table.insert(textlist, { newline = newline }) + table.insert(textlist, { text = ("%4d"):format(line), color = { 0.3, 0.3, 0.3 }, background = { 0.7, 0.7, 0.7 }, post_indent = true }) + table.insert(textlist, { text = " ", color = { 0, 0, 0 }, post_indent = true }) + line = line + 1 +end + +function instr_to_text(textlist, instr, func, mod) + if instr[1] == "block" then + table.insert(textlist, { text = "block", color = { 1, 0, 0 }, change_indent = 1 }) + for _, ins in ipairs(instr.instrs) do + add_line_number(textlist) + instr_to_text(textlist, ins, func, mod) + end + table.insert(textlist, { change_indent = -1 }) + + elseif instr[1] == "loop" then + table.insert(textlist, { text = "loop", color = { 1, 0, 0 }, change_indent = 1 }) + for _, ins in ipairs(instr.instrs) do + add_line_number(textlist) + instr_to_text(textlist, ins, func, mod) + end + table.insert(textlist, { change_indent = -1 }) + + elseif instr[1] == "if" then + table.insert(textlist, { text = "if", color = { 1, 0, 0 }, change_indent = 1 }) + for _, ins in ipairs(instr.instrs) do + add_line_number(textlist) + instr_to_text(textlist, ins, func, mod) + end + table.insert(textlist, { change_indent = -1 }) + + if #instr.else_instrs > 0 then + add_line_number(textlist) + table.insert(textlist, { text = "else", color = { 1, 0, 0 }, change_indent = 1 }) + for _, ins in ipairs(instr.instrs) do + add_line_number(textlist) + instr_to_text(textlist, ins, func, mod) + end + table.insert(textlist, { change_indent = -1 }) + end + + elseif instr[1] == "call" then + table.insert(textlist, { text = instr[1] .. " ", color = { 0, 0, 1 } }) + table.insert(textlist, { text = mod.funcs[instr.x].name, color = { 0, 0.5, 0 } }) + + elseif instr[1]:match("local") then + table.insert(textlist, { text = instr[1] .. " ", color = { 0, 0, 1 } }) + table.insert(textlist, { text = func.locals[instr.x + 1].name, color = { 0, 0.5, 0 } }) + + else + table.insert(textlist, { text = instr[1] .. " ", color = { 0, 0, 1 } }) + if instr.x then + if type(instr.x) == "table" then + if instr.x[1] == "memarg" then + table.insert(textlist, { + text = ("align=0x%03x offset=0x%08x"):format(instr.x.align, instr.x.offset); + color = { 0, 0.5, 0 } + }) + end + else + table.insert(textlist, { text = tostring(instr.x), color = { 0, 0.5, 0 } }) + end + end + end + + return line +end + +function build_func_body_text(func, mod) + local text = {} + line = 1 + + table.insert(text, { text = "Locals:", color = { 0, 0, 1 }, newline = true, change_indent = 2 }) + for _, loc in ipairs(func.locals) do + table.insert(text, { text = loc.type_ .. " " .. loc.name, color = { 0, 0, 0 }, newline = true }) + end + + if #func.locals == 0 then + table.insert(text, { text = "no locals", color = { 1, 0, 0 }, newline = true }) + end + + table.insert(text, { newline = true, change_indent = -2 }) + table.insert(text, { text = "Body:", color = { 0, 0, 1 } }) + + for _, instr in ipairs(func.body) do + add_line_number(text) + instr_to_text(text, instr, func, mod) + end + + -- table.remove(text, #text) + + return text +end + +class "FunctionBlock" [DraggableRect] { + init = function(self, func, x, y) + DraggableRect.init(self, x, y, 400, 400) + + self.header_text = build_func_header_text(func, mod) + self.body_text = build_func_body_text(func, mod) + self.scroll = 0 + end; + + onwheel = function(self, _, dy) + self.scroll = self.scroll - dy * 10; + if self.scroll < 0 then self.scroll = 0 end + end; + + ondrag = function(self, button, x, y, dx, dy) + DraggableRect.ondrag(self, button, x, y, dx, dy) + + if button == 2 then + self.rect.w = math.max(100, x) + self.rect.h = math.max(22, y) + end + end; + + draw = function(self) + love.graphics.setColor(0, 0, 0) + love.graphics.rectangle("fill", 0, 0, self.rect.w, self.rect.h) + love.graphics.setColor(1, 1, 1) + love.graphics.rectangle("fill", 2, 2, self.rect.w - 4, self.rect.h - 4) + love.graphics.setColor(0.8, 0.8, 0.8) + love.graphics.rectangle("fill", 2, 2, self.rect.w - 4, 18) + + local sx, sy = love.graphics.transformPoint(0, 0) + love.graphics.intersectScissor(sx, sy, self.rect.w, self.rect.h) + local x, y = render_text(2, 2, self.header_text) + + local sx, sy = love.graphics.transformPoint(2, y - 1) + love.graphics.intersectScissor(sx, sy, self.rect.w - 4, self.rect.h - 22) + render_text(2, y + 4 - self.scroll, self.body_text) + end; +} + +mod = nil +ui = nil +function love.load() + ui = Ui() + + mod = decompile(arg[2]) + + ui_region = ScrollingUiRegion() + ui_region.rect.x = 0 + ui_region.rect.y = 0 + ui_region.rect.w = 1200 + ui_region.rect.h = 900 + ui_region.background_color = { 0.1, 0.1, 0.1 } + ui_region.line_color = { 0.2, 0.2, 0.2 } + + -- ui_region:add_object(DraggableRect(100, 100, 100, 100)) + -- ui_region:add_object(DraggableRect(200, 100, 100, 100)) + -- ui_region:add_object(DraggableRect(300, 100, 100, 100)) + -- ui_region:add_object(DraggableRect(400, 100, 300, 100)) + + local x = 0 + local y = 0 + for _, func in pairs(mod.funcs) do + if func.body then + local block = FunctionBlock(func, x, y) + block.order = 600 - y + ui_region:add_object(block) + y = y + 20 + end + end + + ui:add_region(ui_region) + + -- bottom_bar_region = UiRegion() + -- bottom_bar_region.rect.x = 0 + -- bottom_bar_region.rect.y = 800 + -- bottom_bar_region.rect.w = 1200 + -- bottom_bar_region.rect.h = 100 + -- bottom_bar_region.layer = 1 + -- bottom_bar_region.background_color = { 1, 0, 0 } + + -- ui:add_region(bottom_bar_region) +end + +function love.update(dt) + if love.keyboard.isDown "escape" then + love.event.quit() + end + + ui:update(dt) +end + +function love.mousepressed(x, y, button) + ui:onmousedown(button, x, y) +end + +function love.mousereleased(x, y, button) + ui:onmouseup(button, x, y) +end + +function love.mousemoved(x, y, dx, dy) + ui:onmousemove(x, y, dx, dy) +end + +function love.wheelmoved(dx, dy) + ui:onmousewheel(dx, dy) +end + +function love.keypressed(key) + ui:onkeydown(key) +end + +function love.keyreleased(key) + ui:onkeyup(key) +end + +function love.resize(w, h) + ui:onresize(w, h) +end + +function love.draw() + ui:draw() +end diff --git a/res/FiraCode-Regular.ttf b/res/FiraCode-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..97c1159ec0c20176ef1176227485386b35c80b06 GIT binary patch literal 290360 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 csG@@+QAPAJ=uROh6_ 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 literal 0 HcmV?d00001 diff --git a/testing.lua b/testing.lua new file mode 100644 index 0000000..6f76fe2 --- /dev/null +++ b/testing.lua @@ -0,0 +1,11 @@ +require "lualib.oop" + +import { + decompile = "decompile:"; + build_str = "utils:build_str"; + pprint = "lualib.pprint"; +} + +local mod = decompile("./data/main.wasm") +pprint(mod) + diff --git a/ui.lua b/ui.lua new file mode 100644 index 0000000..c9aa260 --- /dev/null +++ b/ui.lua @@ -0,0 +1,438 @@ +import { + Rectangle = "utils:Rectangle"; + uuid = "utils:uuidv4"; + revipairs = "utils:revipairs"; +} + +class "Ui" { + init = function(self) + self.regions = {} + self.active_region = nil + end; + + add_region = function(self, region) + table.insert(self.regions, region) + table.sort(self.regions) + end; + + onmousedown = function(self, button, x, y) + local region = nil + for _, r in revipairs(self.regions) do + if r.rect:contains(x, y) then + region = r + break + end + end + + if region ~= nil then + region:onmousedown(button, x - region.rect.x, y - region.rect.y) + end + end; + + onmouseup = function(self, button, x, y) + local region = nil + for _, r in revipairs(self.regions) do + if r.rect:contains(x, y) then + region = r + break + end + end + + if region ~= nil then + region:onmouseup(button, x - region.rect.x, y - region.rect.y) + end + end; + + onmousemove = function(self, x, y, dx, dy) + local region = nil + for _, r in revipairs(self.regions) do + if r.rect:contains(x, y) then + region = r + break + end + end + + if region ~= nil then + if region ~= self.active_region then + if self.active_region ~= nil then + self.active_region:onmouseleave() + end + + region:onmouseenter() + end + region:onmousemove(x - region.rect.x, y - region.rect.y, dx, dy) + end + + self.active_region = region + end; + + onmousewheel = function(self, dx, dy) + if not self.active_region then return end + self.active_region:onmousewheel(dx, dy) + end; + + onkeydown = function(self, key) + if not self.active_region then return end + self.active_region:onkeydown(key) + end; + + onkeyup = function(self, key) + if not self.active_region then return end + self.active_region:onkeyup(key) + end; + + onresize = function(self, new_width, new_height) + end; + + update = function(self, dt) + for _, region in ipairs(self.regions) do + region:update(dt); + end + end; + + draw = function(self) + for _, region in ipairs(self.regions) do + love.graphics.push() + love.graphics.setScissor(region.rect.x, region.rect.y, region.rect.w, region.rect.h) + love.graphics.translate(region.rect.x, region.rect.y) + region:draw() + love.graphics.pop() + end + end; +} + +class "UiRegion" { + init = function(self) + self.active = false + + self.selected_object = nil + self.objects = {} + + self.rect = Rectangle(0, 0, 0, 0) + self.background_color = { 0, 0, 0 } + self.layer = 0 + + -- Internals + self.is_mouse_down = false + self.fire_onclick = false + end; + + add_object = function(self, obj) + table.insert(self.objects, obj) + end; + + -- Used for sorting in the Ui + __lt = function(self, other) + return self.layer < other.layer + end; + + _obj_rect = function(self, obj) + return obj.rect + end; + + onmousedown = function(self, button, x, y) + self.is_mouse_down = button + self.fire_onclick = true + local new_selected = nil + + for _, obj in revipairs(self.objects) do + if self:_obj_rect(obj):contains(x, y) then + new_selected = obj + break + end + end + + if self.selected_object ~= new_selected then + if self.selected_object ~= nil then + self.selected_object:onunselect() + end + + self.selected_object = new_selected + + if self.selected_object ~= nil then + self.selected_object.order = 0 + + for _, obj in ipairs(self.objects) do + if obj ~= self.selected_obj then + obj.order = obj.order + 1 + end + end + + table.sort(self.objects, function(a, b) + return a.order > b.order + end) + + self.selected_object:onselect() + end + end + end; + + onmouseup = function(self, button, x, y) + self.is_mouse_down = false + + if self.selected_object ~= nil and self.fire_onclick then + local obj_rect = self:_obj_rect(self.selected_object) + self.selected_object:onclick(button, x - obj_rect.x, y - obj_rect.y) + end + end; + onmousemove = function(self, x, y, dx, dy) + if self.is_mouse_down and self.selected_object ~= nil then + local obj_rect = self:_obj_rect(self.selected_object) + self.selected_object:ondrag(self.is_mouse_down, x - obj_rect.x, y - obj_rect.y, dx, dy) + self.fire_onclick = false + end + end; + onmouseenter = function(self) + self.active = true + end; + + onmouseleave = function(self) + self.active = false; + self.is_mouse_down = false + self.fire_onclick = false + self.selected_object = nil + end; + + onmousewheel = function(self, dx, dy) + if self.selected_object ~= nil then + self.selected_object:onwheel(dx, dy) + end + end; + + onkeydown = function(self, key) end; + onkeyup = function(self, key) end; + + update = function(self, dt) + for _, obj in ipairs(self.objects) do + obj:update(dt) + end + end; + + draw = function(self) + if self.background_color ~= nil then + love.graphics.setColor(self.background_color) + love.graphics.rectangle("fill", 0, 0, self.rect.w, self.rect.h) + end + + for _, obj in ipairs(self.objects) do + love.graphics.push() + love.graphics.translate(obj.rect.x, obj.rect.y) + obj:draw() + love.graphics.setScissor() + love.graphics.pop() + end + end; +} + +class "ScrollingUiRegion" [UiRegion] { + init = function(self) + UiRegion.init(self) + + self.offset = { x = 0; y = 0; } + self.line_color = { 0, 0, 0 } + + self.zoom = 1 + end; + + _obj_rect = function(self, obj) + return Rectangle( + obj.rect.x + self.offset.x, + obj.rect.y + self.offset.y, + obj.rect.w, obj.rect.h) + end; + + onmousemove = function(self, x, y, dx, dy) + UiRegion.onmousemove(self, x, y, dx, dy) + + if self.is_mouse_down and self.selected_object == nil then + self.offset.x = self.offset.x + dx + self.offset.y = self.offset.y + dy + end + end; + + onmousewheel = function(self, dx, dy) + UiRegion.onmousewheel(self, dx, dy) + + if self.selected_object == nil then + self.zoom = self.zoom * (dy > 0 and 1.05 or (1 / 1.05)) + if self.zoom >= 1 then self.zoom = 1 end + end + end; + + update = function(self, dt) + UiRegion.update(self, dt) + + if self.active then + local speed = 300 + if love.keyboard.isDown "left" then + self.offset.x = self.offset.x + speed * dt + end + if love.keyboard.isDown "right" then + self.offset.x = self.offset.x - speed * dt + end + if love.keyboard.isDown "up" then + self.offset.y = self.offset.y + speed * dt + end + if love.keyboard.isDown "down" then + self.offset.y = self.offset.y - speed * dt + end + end + end; + + draw = function(self) + love.graphics.push() + + if self.background_color ~= nil then + love.graphics.setColor(self.background_color) + love.graphics.rectangle("fill", 0, 0, self.rect.w, self.rect.h) + end + local tmpbgcolor = self.background_color + self.background_color = nil + + local xoff = self.offset.x + local yoff = self.offset.y + local spacing = 64 + + while xoff >= spacing do xoff = xoff - spacing end + while yoff >= spacing do yoff = yoff - spacing end + while xoff <= -spacing do xoff = xoff + spacing end + while yoff <= -spacing do yoff = yoff + spacing end + + love.graphics.setColor(self.line_color) + for x = 0, 40 do + love.graphics.line(x * spacing + xoff, 0, x * spacing + xoff, self.rect.h) + end + for y = 0, 40 do + love.graphics.line(0, y * spacing + yoff, self.rect.w, y * spacing + yoff) + end + + love.graphics.translate(self.offset.x, self.offset.y) + UiRegion.draw(self) + love.graphics.pop() + + self.background_color = tmpbgcolor + end; +} + +class "UiObject" { + init = function(self) + self.rect = Rectangle(0, 0, 0, 0) + self.uuid = uuid() + self.selected = false + self.order = math.random(1, 128) + end; + + onclick = function(self, button, x, y) end; + ondrag = function(self, button, x, y, dx, dy) end; + onwheel = function(self, dx, dy) end; + + onselect = function(self) + self.selected = true + end; + onunselect = function(self) + self.selected = false + end; + + onkey = function(self, button) end; + + update = function(dt) end; + draw = function() end; +} + +class "DraggableRect" [UiObject] { + init = function(self, x, y, w, h) + UiObject.init(self) + + self.rect = Rectangle(x, y, w, h) + end; + + ondrag = function(self, button, x, y, dx, dy) + if button == 1 then + self.rect.x = self.rect.x + dx + self.rect.y = self.rect.y + dy + end + end; + + draw = function(self) + if self.selected then + love.graphics.setColor(0, 0, 1) + love.graphics.rectangle("fill", -2, -2, self.rect.w + 4, self.rect.h + 4) + end + love.graphics.setColor(1, 1, 1) + love.graphics.rectangle("fill", 0, 0, self.rect.w, self.rect.h) + + render_text(0, 0, { + { text = "1 Hello ", color = { 1, 0, 0 } }; + { text = "world", color = { 0, 0, 1 } }; + { newline = true }; + { text = "2 Nother line", color = { 0, 0.5, 0 } }; + { newline = true }; + { newline = true }; + { text = "3 nother Nother line", color = { 0, 0.5, 0 } }; + }) + end; +} + +programming_font = false +function render_text(x, y, text) + if not programming_font then + programming_font = love.graphics.newFont("res/FiraCode-Regular.ttf", 14) + love.graphics.setFont(programming_font) + end + + local origx = x + local fheight = programming_font:getHeight() + local indent_level = 0 + local indentation = "" + local fresh_newline = true + + for _, txt in ipairs(text) do + if txt.text then + local printed = txt.text + if fresh_newline then + if txt.post_indent then + printed = txt.text .. indentation + else + printed = indentation .. txt.text + end + fresh_newline = false + end + + if txt.background then + love.graphics.setColor(txt.background) + love.graphics.rectangle("fill", x, y, programming_font:getWidth(txt.text), fheight + 2); + end + + love.graphics.setColor(txt.color) + love.graphics.print(printed, x, y) + + x = x + programming_font:getWidth(printed) + end + + if txt.newline then + y = y + fheight + 2; + x = origx + fresh_newline = true + end + + if txt.change_indent then + indent_level = indent_level + txt.change_indent + indentation = "" + for i=1,indent_level do + indentation = indentation .. " " + end + end + end + + return x, y +end + +return module { + Ui = Ui; + UiRegion = UiRegion; + ScrollingUiRegion = ScrollingUiRegion; + UiObject = UiObject; + DraggableRect = DraggableRect; + + render_text = render_text; +} diff --git a/utils.lua b/utils.lua new file mode 100644 index 0000000..ec4b5e0 --- /dev/null +++ b/utils.lua @@ -0,0 +1,101 @@ +import {} + +-- This is unsued in favor of the C equivalent +function buffered_read(file, buffer_size) + buffer_size = buffer_size or 4 * 1024 + + local buffer = {} + local ptr = -1 + + return coroutine.wrap(function() + while true do + if ptr <= 0 or ptr >= buffer_size then + ptr = 0 + local str = file:read(buffer_size) + if not str then break end + + buffer = {} + for c in (str or ''):gmatch '.' do + buffer[#buffer + 1] = c + end + end + + ptr = ptr + 1 + if ptr > #buffer then break end + coroutine.yield(buffer[ptr]:byte()) + end + return + end) +end + +function build_str(tbl_int) + if #tbl_int < 30 then + return string.char(unpack(tbl_int)) + else + -- This is slower but may be needed for long strings + local str = "" + for _, c in ipairs(tbl_int) do + str = str .. string.char(c) + end + return str + end +end + +function uuidv4() + local template ='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx' + return string.gsub(template, '[xy]', function (c) + local v = (c == 'x') and math.random(0, 0xf) or math.random(8, 0xb) + return string.format('%x', v) + end) +end + +function revipairs(t) + local max = 1 + while t[max] ~= nil do + max = max + 1 + end + local function ripairs_it(t, i) + i = i - 1 + local v = t[i] + if v ~= nil then + return i, v + else + return nil + end + end + return ripairs_it, t, max +end + +class "Rectangle" { + init = function(self, x, y, w, h) + self.x = x + self.y = y + self.w = w + self.h = h + end; + + contains = function(self, x, y) + return x >= self.x and x <= self.x + self.w + and y >= self.y and y <= self.y + self.h + end; + + intersects = function(self, other) + return self.x <= other.x + other.w + and self.x + self.w >= other.x + and self.y <= other.y + other.h + and self.y + self.h >= other.y + end; + + __lt = function(self, other) return self:intersects(other) end +} + +return module { + buffered_read = buffered_read; + build_str = build_str; + + uuidv4 = uuidv4; + + revipairs = revipairs; + + Rectangle = Rectangle; +} -- 2.25.1