From e76d2cb18790b8c43fbb174f8523e7e678896883 Mon Sep 17 00:00:00 2001 From: Enrico Lumetti Date: Sun, 8 May 2022 09:56:37 +0200 Subject: [PATCH] Improve inspect and add skeleton for VM --- README.md | 2 +- inspectbc.lua | 64 +++++++++++++++++++++++++++++++++++++++++-------- microLua.lua | 8 +++++-- opcodes.lua | 5 ++-- readbc.lua | 11 +++++---- tests/test2.lua | 4 ++++ vm.lua | 36 ++++++++++++++++++++++++++++ 7 files changed, 111 insertions(+), 19 deletions(-) create mode 100644 tests/test2.lua diff --git a/README.md b/README.md index 73bd702..3cf19b6 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ # microLua -LuaJIT bytecode interpreter written in Lua. \ No newline at end of file +LuaJIT bytecode interpreter written in LuaJIT. diff --git a/inspectbc.lua b/inspectbc.lua index f150416..aea6a4d 100644 --- a/inspectbc.lua +++ b/inspectbc.lua @@ -1,15 +1,59 @@ local readbc = require('readbc') local opcodes = require('opcodes') -fp = io.open('tests/test1.luo') -header = readbc.read_header(fp) -proto = readbc.read_proto(fp) -fp:close() +local function inspect_proto(proto) + print('\n-- proto --') + -- print('Debug: ' .. proto.debug) + print('Params: ' .. proto.numparams) + print('Frame Size: ' .. proto.framesize) + print('#Upvalues: ' .. proto.numuv) + print('#kgc: ' .. proto.numkgc) + print('#bcins: ' .. proto.numbc) -for i = 1, #proto.bcins do - local decoded = opcodes.decode(proto.bcins[i]) - local def = opcodes.defs[decoded.id] - print(def.name) - print(decoded.a) - print(decoded.d) + print('-- bytecode --') + for i = 1, #proto.bcins do + local decoded = opcodes.decode(proto.bcins[i]) + if opcodes.defs[decoded.id] ~= nil then + local def = opcodes.defs[decoded.id] + -- check for ABC or AD format + if def.b == opcodes.Mode.none then + print(string.format('%s\t A: %s\tB: %s\t C: %s', def.name, decoded.a, decoded.b, decoded.c)) + else + print(string.format('%s\t A: %s\tD: %s', def.name, decoded.a, decoded.d)) + end + else + print('UNKNOWN OPCODE') + end + end end + +local function inspect(fp) + local header = readbc.read_header(fp) + + print('-- header --') + print('Name: ' .. header.name) + print(string.format('Bytecode Version: %s', header.version)) + print('Stripped: ' .. (header.stripped and 'yes' or 'no')) + + local proto = readbc.read_proto(fp) + while proto ~= nil do + inspect_proto(proto) + proto = readbc.read_proto(fp) + end +end + +local arg = {...} +if arg[1] == nil then + print('Please pass a LuaJIT bytecode file as command line argument') + return 1 +end + +local fp = io.open(arg[1]) +if fp == nil then + print('Could not open path ' .. arg[1]) + return 1 +end + +inspect(fp) + +fp:close() diff --git a/microLua.lua b/microLua.lua index 2067113..24669f9 100644 --- a/microLua.lua +++ b/microLua.lua @@ -1,8 +1,12 @@ local readbc = require('readbc') +local vm = require('vm') +local VM = vm.VM fp = io.open('tests/test1.luo') header = readbc.read_header(fp) proto = readbc.read_proto(fp) -fo:close() +fp:close() -print(#proto.bcins) +vm = VM.new() +vm:set_proto(proto) +vm:run() diff --git a/opcodes.lua b/opcodes.lua index c84d449..62f4e27 100644 --- a/opcodes.lua +++ b/opcodes.lua @@ -77,8 +77,8 @@ local function decode(ins) -- TODO: endianess local id = bit.band(ins, 0xff) local a = bit.band(ins, 0xff00) / 0x100 - local b = bit.band(ins, 0xff0000) / 0x10000 - local c = bit.band(ins, 0xff000000) / 0x1000000 + local c = bit.band(ins, 0xff0000) / 0x10000 + local b = bit.band(ins, 0xff000000) / 0x1000000 local d = bit.band(ins, 0xffff0000) / 0x10000 return { id = id, @@ -91,5 +91,6 @@ end return { defs = Opcodes_defs, + Mode = Mode, decode = decode, } diff --git a/readbc.lua b/readbc.lua index 98ce53e..386dde2 100644 --- a/readbc.lua +++ b/readbc.lua @@ -3,7 +3,7 @@ local bit=require('bit') local HEADER_MAGIC = {27, string.byte('L'), string.byte('J')} -local HEADER_FLAG_STRIP = 0x02 +local FLAG_STRIP = 0x02 local function read_u8(fp) return string.byte(fp:read(1)) @@ -67,9 +67,12 @@ local function read_header(fp) local flags = read_uleb128(fp) local name - if bit.band(flags, HEADER_FLAG_STRIP) ~= 0 then + local stripped + if bit.band(flags, FLAG_STRIP) ~= 0 then + stripped = true name = '' else + stripped = false local nameLen = read_uleb128(fp) name = fp:read(nameLen) end @@ -77,7 +80,7 @@ local function read_header(fp) return { magic = magic, version = version, - flags = flags, + stripped = stripped, name = name, } end @@ -103,7 +106,7 @@ local function read_proto(fp) local debugLen = 0 local debugInfo = nil - if bit.band(flags, HEADER_FLAG_STRIP) ~= 0 then + if bit.band(flags, FLAG_STRIP) ~= 0 then debugLen = read_uleb128(fp) -- TODO: is this correct? diff --git a/tests/test2.lua b/tests/test2.lua new file mode 100644 index 0000000..1506407 --- /dev/null +++ b/tests/test2.lua @@ -0,0 +1,4 @@ +local x = 1 +local y = 2 +local z = x^y +return z diff --git a/vm.lua b/vm.lua index 8b13789..8379e25 100644 --- a/vm.lua +++ b/vm.lua @@ -1 +1,37 @@ +local opcodes = require('opcodes') +local function set_proto(self, proto) + self.proto = proto +end + +local function step(self) + if self.pc >= self.proto.numbc then + return false + end + local ins = self.proto.bcins[self.pc+1] + local decop = opcodes.decode(ins) + print(opcodes.defs[decop.id].name) + + self.pc = self.pc + 1 + return true +end + +local function run(self) + while self:step() do + end +end + +local VM = { + new = function() + return { + set_proto = set_proto, + step = step, + run = run, + pc = 0, + } + end +} + +return { + VM = VM +}