Improve inspect and add skeleton for VM
This commit is contained in:
parent
a78851c220
commit
e76d2cb187
|
|
@ -1,3 +1,3 @@
|
||||||
# microLua
|
# microLua
|
||||||
|
|
||||||
LuaJIT bytecode interpreter written in Lua.
|
LuaJIT bytecode interpreter written in LuaJIT.
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,59 @@
|
||||||
local readbc = require('readbc')
|
local readbc = require('readbc')
|
||||||
local opcodes = require('opcodes')
|
local opcodes = require('opcodes')
|
||||||
|
|
||||||
fp = io.open('tests/test1.luo')
|
local function inspect_proto(proto)
|
||||||
header = readbc.read_header(fp)
|
print('\n-- proto --')
|
||||||
proto = readbc.read_proto(fp)
|
-- print('Debug: ' .. proto.debug)
|
||||||
fp:close()
|
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
|
print('-- bytecode --')
|
||||||
local decoded = opcodes.decode(proto.bcins[i])
|
for i = 1, #proto.bcins do
|
||||||
local def = opcodes.defs[decoded.id]
|
local decoded = opcodes.decode(proto.bcins[i])
|
||||||
print(def.name)
|
if opcodes.defs[decoded.id] ~= nil then
|
||||||
print(decoded.a)
|
local def = opcodes.defs[decoded.id]
|
||||||
print(decoded.d)
|
-- 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
|
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()
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,12 @@
|
||||||
local readbc = require('readbc')
|
local readbc = require('readbc')
|
||||||
|
local vm = require('vm')
|
||||||
|
local VM = vm.VM
|
||||||
|
|
||||||
fp = io.open('tests/test1.luo')
|
fp = io.open('tests/test1.luo')
|
||||||
header = readbc.read_header(fp)
|
header = readbc.read_header(fp)
|
||||||
proto = readbc.read_proto(fp)
|
proto = readbc.read_proto(fp)
|
||||||
fo:close()
|
fp:close()
|
||||||
|
|
||||||
print(#proto.bcins)
|
vm = VM.new()
|
||||||
|
vm:set_proto(proto)
|
||||||
|
vm:run()
|
||||||
|
|
|
||||||
|
|
@ -77,8 +77,8 @@ local function decode(ins)
|
||||||
-- TODO: endianess
|
-- TODO: endianess
|
||||||
local id = bit.band(ins, 0xff)
|
local id = bit.band(ins, 0xff)
|
||||||
local a = bit.band(ins, 0xff00) / 0x100
|
local a = bit.band(ins, 0xff00) / 0x100
|
||||||
local b = bit.band(ins, 0xff0000) / 0x10000
|
local c = bit.band(ins, 0xff0000) / 0x10000
|
||||||
local c = bit.band(ins, 0xff000000) / 0x1000000
|
local b = bit.band(ins, 0xff000000) / 0x1000000
|
||||||
local d = bit.band(ins, 0xffff0000) / 0x10000
|
local d = bit.band(ins, 0xffff0000) / 0x10000
|
||||||
return {
|
return {
|
||||||
id = id,
|
id = id,
|
||||||
|
|
@ -91,5 +91,6 @@ end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
defs = Opcodes_defs,
|
defs = Opcodes_defs,
|
||||||
|
Mode = Mode,
|
||||||
decode = decode,
|
decode = decode,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
11
readbc.lua
11
readbc.lua
|
|
@ -3,7 +3,7 @@
|
||||||
local bit=require('bit')
|
local bit=require('bit')
|
||||||
|
|
||||||
local HEADER_MAGIC = {27, string.byte('L'), string.byte('J')}
|
local HEADER_MAGIC = {27, string.byte('L'), string.byte('J')}
|
||||||
local HEADER_FLAG_STRIP = 0x02
|
local FLAG_STRIP = 0x02
|
||||||
|
|
||||||
local function read_u8(fp)
|
local function read_u8(fp)
|
||||||
return string.byte(fp:read(1))
|
return string.byte(fp:read(1))
|
||||||
|
|
@ -67,9 +67,12 @@ local function read_header(fp)
|
||||||
local flags = read_uleb128(fp)
|
local flags = read_uleb128(fp)
|
||||||
|
|
||||||
local name
|
local name
|
||||||
if bit.band(flags, HEADER_FLAG_STRIP) ~= 0 then
|
local stripped
|
||||||
|
if bit.band(flags, FLAG_STRIP) ~= 0 then
|
||||||
|
stripped = true
|
||||||
name = ''
|
name = ''
|
||||||
else
|
else
|
||||||
|
stripped = false
|
||||||
local nameLen = read_uleb128(fp)
|
local nameLen = read_uleb128(fp)
|
||||||
name = fp:read(nameLen)
|
name = fp:read(nameLen)
|
||||||
end
|
end
|
||||||
|
|
@ -77,7 +80,7 @@ local function read_header(fp)
|
||||||
return {
|
return {
|
||||||
magic = magic,
|
magic = magic,
|
||||||
version = version,
|
version = version,
|
||||||
flags = flags,
|
stripped = stripped,
|
||||||
name = name,
|
name = name,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
@ -103,7 +106,7 @@ local function read_proto(fp)
|
||||||
local debugLen = 0
|
local debugLen = 0
|
||||||
local debugInfo = nil
|
local debugInfo = nil
|
||||||
|
|
||||||
if bit.band(flags, HEADER_FLAG_STRIP) ~= 0 then
|
if bit.band(flags, FLAG_STRIP) ~= 0 then
|
||||||
debugLen = read_uleb128(fp)
|
debugLen = read_uleb128(fp)
|
||||||
|
|
||||||
-- TODO: is this correct?
|
-- TODO: is this correct?
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
local x = 1
|
||||||
|
local y = 2
|
||||||
|
local z = x^y
|
||||||
|
return z
|
||||||
36
vm.lua
36
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
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue