From d800d334dc37d6764d85eba4f1d9b0b7bc6d3677 Mon Sep 17 00:00:00 2001 From: Enrico Lumetti Date: Sat, 7 May 2022 23:04:26 +0200 Subject: [PATCH] Implement enough to read bytecode instructions --- microLua.lua | 3 +- readbc.lua | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 96 insertions(+), 4 deletions(-) diff --git a/microLua.lua b/microLua.lua index 02e9e11..98104f7 100644 --- a/microLua.lua +++ b/microLua.lua @@ -2,4 +2,5 @@ local readbc = require('readbc') fp = io.open('tests/test1.luo') header = readbc.read_header(fp) -print(header.name) +proto = readbc.read_proto(fp) +print(#proto.bcins) diff --git a/readbc.lua b/readbc.lua index 70994f5..af4fc05 100644 --- a/readbc.lua +++ b/readbc.lua @@ -5,13 +5,53 @@ local bit=require('bit') local HEADER_MAGIC = {27, string.byte('L'), string.byte('J')} local HEADER_FLAG_STRIP = 0x02 +local function read_u8(fp) + return string.byte(fp:read(1)) +end + +local function read_u16(fp) + -- TODO: endianess + local b1 = read_u8(fp) + local b2 = read_u8(fp) + + return bit.bor(b2*0x100, b1) +end + +local function read_u32(fp) + -- TODO: endianess + local h1 = read_u16(fp) + local h2 = read_u16(fp) + + return bit.bor(h2*0x10000, h1) +end + +local function read_u8n(fp, n) + return { string.byte(fp:read(n), 1, n) } +end + +local function read_u16n(fp, n) + local res = {} + for i = 1, n do + res[i] = read_u16(fp) + end + return res +end + +local function read_u32n(fp, n) + local res = {} + for i = 1, n do + res[i] = read_u32(fp) + end + return res +end + local function read_uleb128(fp) local last_byte = false local res = 0 local shift = 0 -- the bytes are read from the LSB to the MSB while not last_byte do - local uleb_byte = string.byte(fp:read(1)) + local uleb_byte = read_u8(fp) res = bit.bor(res, bit.lshift(bit.band(uleb_byte, 0x7f), shift)) if bit.band(uleb_byte, 0x80) == 0 then @@ -22,8 +62,8 @@ local function read_uleb128(fp) end local function read_header(fp) - local magic = { string.byte(fp:read(3), 1, 3) } - local version = string.byte(fp:read(1)) + local magic = read_u8n(fp, 3) + local version = read_u8(fp) local flags = read_uleb128(fp) local name @@ -43,6 +83,57 @@ local function read_header(fp) end local function read_proto(fp) + local length = read_uleb128(fp) + -- if the the last read proto was the last one + -- we have reached the end marker, which is a zero + -- this overlaps with a uleb128 zero representation + if length == 0 then + return + end + + -- read proto header + local flags = read_u8(fp) + local numparams = read_u8(fp) + local framesize = read_u8(fp) + local numuv = read_u8(fp) + local numkgc = read_uleb128(fp) + local numkn = read_uleb128(fp) + local numbc = read_uleb128(fp) + + local debugLen = 0 + local debugInfo = nil + + if bit.band(flags, HEADER_FLAG_STRIP) ~= 0 then + debugLen = read_uleb128(fp) + + -- TODO: is this correct? + if debugLen ~= 0 then + local firstLine = read_uleb128(fp) + local numLine = read_uleb128(fp) + debugInfo = { + firstLine = firstLine, + numLine = numLine, + } + end + end + + local bcins = read_u32n(fp, numbc) + local uvdata = read_u16n(fp, numuv) + -- local kgc + -- local numkn + + return { + flags = flags, + numparams = numparams, + framsize = framesize, + numuv = numuv, + numkgc = numkgc, + numkn = numkn, + numbc = numbc, + debugInfo = debugInfo, + bcins = bcins, + uvdata = uvdata, + } end return {