diff options
Diffstat (limited to 'src/lundump.js')
-rw-r--r-- | src/lundump.js | 85 |
1 files changed, 79 insertions, 6 deletions
diff --git a/src/lundump.js b/src/lundump.js index 1d1a959..c9481da 100644 --- a/src/lundump.js +++ b/src/lundump.js @@ -9,6 +9,8 @@ const lua_State = require('./lstate.js').lua_State; const LClosure = require('./lobject.js').LClosure; const Proto = require('./lfunc.js').Proto; +const LUAI_MAXSHORTLEN = 40; + /** * Parse Lua 5.3 bytecode * @see {@link http://www.lua.org/source/5.3/lundump.c.html|lundump.c} @@ -54,6 +56,17 @@ class BytecodeParser { return integer; } + peekInt() { + return this.dataView.getInt32(this.offset, true); + } + + readInt() { + let integer = this.peekInt(); + this.offset += 4; + + return integer; + } + peekNumber() { return this.dataView.getFloat64(this.offset, true); } @@ -66,14 +79,66 @@ class BytecodeParser { } readString(n) { + let size = typeof n !== 'undefined' ? n : this.readByte() - 1; + + if (size === 0xFF) // TODO test + this.offset += this.size_tSize; + + if (size === 0) { + return null; + } + let string = ""; - for (let i = 0; i < n; i++) + for (let i = 0; i < size; i++) string += String.fromCharCode(this.readByte()); return string; } + readInstruction() { + let ins = new DataView(new Buffer(this.instructionSize)) + for (let i = 0; i < this.instructionSize; i++) + ins.setUint8(i, this.readByte()); + + console.log(ins); + + return ins; + } + + readCode(f) { + let n = this.readInt(); + + for (let i = 0; i < n; i++) + f.code.push(this.readInstruction()); + } + + readFunction(f, psource) { + f.source = this.readString(); + if (f.source == null) /* no source in dump? */ + f.source = psource; /* reuse parent's source */ + f.linedefined = this.readInt(); + f.lastlinedefined = this.readInt(); + f.numparams = this.readByte(); + f.is_vararg = this.readByte(); + f.maxstacksize = this.readByte(); + + console.log(` + f.source = ${f.source} + f.linedefined = ${f.linedefined} + f.lastlinedefined = ${f.lastlinedefined} + f.numparams = ${f.numparams} + f.is_vararg = ${f.is_vararg} + f.maxstacksize = ${f.maxstacksize} + `); + + this.readCode(f); + // this.readConstants(f); + // this.readUpvalues(f); + // this.readProtos(f); + // this.readDebug(f); + } + checkHeader() { if (this.readString(4) !== "\x1bLua") throw new Error("bad LUA_SIGNATURE, expected '<esc>Lua'"); @@ -93,24 +158,32 @@ class BytecodeParser { this.integerSize = this.readByte(); this.numberSize = this.readByte(); + console.log(` + intSize = ${this.intSize} + size_tSize = ${this.size_tSize} + instructionSize = ${this.instructionSize} + integerSize = ${this.integerSize} + numberSize = ${this.numberSize} + `) + if (this.readInteger() !== 0x5678) throw new Error("endianness mismatch"); if (this.readNumber() !== 370.5) - throw new Error("float format mismatch in"); + throw new Error("float format mismatch"); } luaU_undump() { - checkHeader(); + this.checkHeader(); let cl = new LClosure(this.L, this.readByte()); - L.top++; + this.L.top++; cl.p = new Proto(this.L); - loadFunction(cl.p); + this.readFunction(cl.p); - assert(cl.nupvalues === cl.p.upvalues.length); + // assert(cl.nupvalues === cl.p.upvalues.length); return cl; } |