From 04a7b7322446eae0f5da66bedc1e262a7d83419d Mon Sep 17 00:00:00 2001 From: Benoit Giannangeli Date: Thu, 2 Feb 2017 08:30:20 +0100 Subject: readHeader --- src/lfunc.js | 27 +++++++++++++++++++ src/lobject.js | 2 +- src/lstate.js | 38 +++++++++++--------------- src/lua.js | 16 +++++++++++ src/lundump.js | 85 +++++++++++++++++++++++++++++++++++++++++++++++----------- 5 files changed, 128 insertions(+), 40 deletions(-) create mode 100644 src/lfunc.js create mode 100644 src/lua.js diff --git a/src/lfunc.js b/src/lfunc.js new file mode 100644 index 0000000..faa0887 --- /dev/null +++ b/src/lfunc.js @@ -0,0 +1,27 @@ +/*jshint esversion: 6 */ +"use strict"; + +class Proto { + + constructor(L) { + this.k = []; // constants used by the function + this.p = []; // functions defined inside the function + this.code = []; // opcodes + this.cache = null; // last-created closure with this prototype + this.lineinfo = []; // map from opcodes to source lines (debug information) + this.upvalues = []; // upvalue information + this.numparams = 0; // number of fixed parameters + this.is_vararg = 0; + this.maxstacksize = 0; // number of registers needed by this function + this.locvars = []; // information about local variables (debug information) + this.linedefined = 0; // debug information + this.lastlinedefined = 0; // debug information + this.source = null; // used for debug information + } + +} + + +module.exports = { + Proto: Proto +}; \ No newline at end of file diff --git a/src/lobject.js b/src/lobject.js index 2e21f16..1858fd3 100644 --- a/src/lobject.js +++ b/src/lobject.js @@ -4,7 +4,7 @@ class LClosure { constructor(L, n) { - this.p = []; + this.p = null; this.nupvalues = n; } diff --git a/src/lstate.js b/src/lstate.js index b0002c3..979b89c 100644 --- a/src/lstate.js +++ b/src/lstate.js @@ -1,32 +1,24 @@ /*jshint esversion: 6 */ "use strict"; +const thread_status = require('./lua.js').thread_status; + class lua_State { constructor() { - // CommonHeader; - // unsigned short nci; /* number of items in 'ci' list */ - // lu_byte status; - // StkId top; /* first free slot in the stack */ - // global_State *l_G; - // CallInfo *ci; /* call info for current function */ - // const Instruction *oldpc; /* last pc traced */ - // StkId stack_last; /* last free slot in the stack */ - // StkId stack; /* stack base */ - // UpVal *openupval; /* list of open upvalues in this stack */ - // GCObject *gclist; - // struct lua_State *twups; list of threads with open upvalues - // struct lua_longjmp *errorJmp; /* current error recover point */ - // CallInfo base_ci; /* CallInfo for first level (C calling Lua) */ - // volatile lua_Hook hook; - // ptrdiff_t errfunc; /* current error handling function (stack index) */ - // int stacksize; - // int basehookcount; - // int hookcount; - // unsigned short nny; /* number of non-yieldable calls in stack */ - // unsigned short nCcalls; /* number of nested C calls */ - // l_signalT hookmask; - // lu_byte allowhook; + this.next = null; + this.stack = null; + this.ci = null; + this.nci = 0; + this.stacksize = 0; + this.twups = [this]; + this.errorJmp = null; + this.hook = null; + this.allowhook = true; + this.openupval = null; + this.nny = 1; + this.status = thread_status.LUA_OK; + this.errfunc = 0; } } diff --git a/src/lua.js b/src/lua.js new file mode 100644 index 0000000..f41991e --- /dev/null +++ b/src/lua.js @@ -0,0 +1,16 @@ +/*jshint esversion: 6 */ +"use strict"; + +const thread_status = { + LUA_OK: 0, + LUA_YIELD: 1, + LUA_ERRRUN: 2, + LUA_ERRSYNTAX: 3, + LUA_ERRMEM: 4, + LUA_ERRGCMM: 5, + LUA_ERRERR: 6 +}; + +module.exports = { + thread_status: thread_status +}; \ No newline at end of file diff --git a/src/lundump.js b/src/lundump.js index 69445d4..1d1a959 100644 --- a/src/lundump.js +++ b/src/lundump.js @@ -3,8 +3,11 @@ const DataView = require('buffer-dataview'); const fs = require('fs'); +const assert = require('assert'); + const lua_State = require('./lstate.js').lua_State; const LClosure = require('./lobject.js').LClosure; +const Proto = require('./lfunc.js').Proto; /** * Parse Lua 5.3 bytecode @@ -15,9 +18,17 @@ class BytecodeParser { /** * Initilialize bytecode parser * @constructor + * @param {lua_State} Lua state object * @param {DataView} dataView Contains the binary data */ - constructor(dataView) { + constructor(L, dataView) { + this.intSize = 4; + this.size_tSize = 8; + this.instructionSize = 4; + this.integerSize = 8; + this.numberSize = 8; + + this.L = L; this.dataView = dataView; this.offset = 0; } @@ -32,36 +43,78 @@ class BytecodeParser { return byte; } - peekWord() { - return this.dataView.getUint32(this.offset, true); + peekInteger() { + return this.dataView.getInt32(this.offset, true); + } + + readInteger() { + let integer = this.peekInteger(); + this.offset += this.integerSize; + + return integer; + } + + peekNumber() { + return this.dataView.getFloat64(this.offset, true); + } + + readNumber() { + let number = this.peekNumber(); + this.offset += this.numberSize; + + return number; } - readWord() { - let word = this.peekWord(); - this.offset += 4; + readString(n) { + let string = ""; - return word; + for (let i = 0; i < n; i++) + string += String.fromCharCode(this.readByte()); + + return string; } checkHeader() { - if (this.readByte() !== 0x1b - || this.readByte() !== 0x4c - || this.readByte() !== 0x75 - || this.readByte() !== 0x61) - throw new Error("Bad LUA_SIGNATURE, expected [1b 4c 75 61]"); + if (this.readString(4) !== "\x1bLua") + throw new Error("bad LUA_SIGNATURE, expected 'Lua'"); if (this.readByte() !== 0x53) - throw new Error("Bad Lua version, expected 5.3"); + throw new Error("bad Lua version, expected 5.3"); if (this.readByte() !== 0) - throw new Error("Supports only official PUC-Rio implementation") + throw new Error("supports only official PUC-Rio implementation"); + + if (this.readString(6) !== "\x19\x93\r\n\x1a\n") + throw new Error("bytecode corrupted"); + + this.intSize = this.readByte(); + this.size_tSize = this.readByte(); + this.instructionSize = this.readByte(); + this.integerSize = this.readByte(); + this.numberSize = this.readByte(); + + if (this.readInteger() !== 0x5678) + throw new Error("endianness mismatch"); + + if (this.readNumber() !== 370.5) + throw new Error("float format mismatch in"); + } luaU_undump() { checkHeader(); - let cl = new LClosure(L, this.readByte()); + + let cl = new LClosure(this.L, this.readByte()); + L.top++; + cl.p = new Proto(this.L); + + loadFunction(cl.p); + + assert(cl.nupvalues === cl.p.upvalues.length); return cl; } -} \ No newline at end of file +} + +module.exports = BytecodeParser; \ No newline at end of file -- cgit v1.2.3-70-g09d2