public Block(Block parent) { K = new K2Reg(this); //parent.PreviousBlock = this; this.PreviousBlock = parent; V = new Var2Reg(parent.V); Chunk = parent.Chunk; }
static Chunk ReadFunction() { Chunk c = new Chunk(); c.Name = ReadString(); c.FirstLine = (uint)ReadInt32(); c.LastLine = (ulong)ReadInt32(); c.UpvalueCount = ReadInt8(); // Upvalues c.ArgumentCount = ReadInt8(); c.Vararg = ReadInt8(); c.MaxStackSize = (uint)ReadInt8(); // Instructions long count = ReadInt32(); for (int i = 0; i < count; i++) { uint op = (uint)ReadInt32(); int opcode = (int)Lua.GET_OPCODE(op); //(int)Bit.Get(op, 1, 6); Instruction instr = Instruction.From(op); instr.Number = i; c.Instructions.Add(instr); } // Constants count = ReadInt32(); for (int i = 0; i < count; i++) { Constant cnst = new Constant(0, null); int t = ReadInt8(); cnst.Number = i; if (t == 0) { cnst.Type = ConstantType.Nil; cnst.Value = null; } else if (t == 1) { cnst.Type = ConstantType.Bool; cnst.Value = ReadInt8() != 0; } else if (t == 3) { cnst.Type = ConstantType.Number; cnst.Value = ReadNumber(); } else if (t == 4) { cnst.Type = ConstantType.String; cnst.Value = ReadString(); } c.Constants.Add(cnst); } // Protos count = ReadInt32(); for (int i = 0; i < count; i++) c.Protos.Add(ReadFunction()); // Line numbers count = ReadInt32(); for (int i = 0; i < count; i++) c.Instructions[i].LineNumber = ReadInt32(); // Locals count = ReadInt32(); for (int i = 0; i < count; i++) c.Locals.Add(new Local(ReadString(), ReadInt32(), ReadInt32())); // Upvalues count = ReadInt32(); for (int i = 0; i < count; i++) c.Upvalues.Add(new Upvalue(ReadString())); return c; }
public LuaFile(Lua.Proto p) { Main = new Chunk(p); }
static void decompile(Chunk chunk) { if (chunk != file.Main) { write("; Function " + chunk.Name); write(".func"); indent = indent + 1; } else write("; Main code"); write(".name \"" + chunk.Name + "\""); write(".options " + chunk.UpvalueCount + " " + chunk.ArgumentCount + " " + chunk.Vararg + " " + chunk.MaxStackSize); write("; Above contains: Upvalue count, Argument count, Vararg flag, Max Stack Size"); write(""); if (chunk.Constants.Count > 0) { write("; Constants"); foreach (Constant c in chunk.Constants) { if (c.Type == ConstantType.Nil) write(".const nil"); else if (c.Type == ConstantType.Bool) write(".const " + ((bool)c.Value ? "true" : "false")); else if (c.Type == ConstantType.Number) write(".const " + c.Value); else if (c.Type == ConstantType.String) { // escape string string v = ""; foreach (char c2 in (string)c.Value) { int ch = (int)c2; char nC = '\0'; // other chars with values > 31 are '"' (34), '\' (92) and > 126 if (ch < 32 || ch == 34 || ch == 92 || ch > 126) { if (ch >= 7 && ch <= 13) nC = "abtnvfr".Substring(ch - 6, 1)[0]; else if (ch == 34 || ch == 92) nC = c2; v = v + "\\" + nC; } else// 32 <= v <= 126 (NOT 255) v = v + c2; } write(".const \"" + v + "\""); } } } if (chunk.Locals.Count > 0) { write("; Locals"); foreach (Local l in chunk.Locals) write(".local " + l.Name); } if (chunk.Upvalues.Count > 0) { write("; Upvalues"); foreach (Upvalue u in chunk.Upvalues) write(".upval " + u.Name); } write("; Instructions"); foreach (Instruction instr in chunk.Instructions) { if (instr.OpcodeType == OpcodeType.ABC) write(instr.OpcodeName.ToLower() + " " + instr.A + " " + instr.B + " " + instr.C); else if (instr.OpcodeType == OpcodeType.ABx) write(instr.OpcodeName.ToLower() + " " + instr.A + " " + instr.Bx); else if (instr.OpcodeType == OpcodeType.AsBx) write(instr.OpcodeName.ToLower() + " " + instr.A + " " + instr.sBx); } if (chunk.Protos.Count > 0) { write("; Protos"); write(""); foreach (Chunk chunk2 in chunk.Protos) decompile(chunk2); } if (chunk != file.Main) { indent--; write(".end"); } }
public Block() { Chunk = new Chunk(); K = new K2Reg(this); }
public static void VerifyChunk(Chunk c) { foreach (Instruction i in c.Instructions) { switch (i.Opcode) { case Instruction.LuaOpcode.MOVE: assert(i.C == 0, "MOVE.C must equal 0"); assert(i.A < c.MaxStackSize, "MOVE.A out of bounds"); assert(i.B < c.MaxStackSize, "MOVE.B out of bounds"); break; case Instruction.LuaOpcode.LOADK: assert(i.A < c.MaxStackSize, "LOADK.A out of bounds"); assert(i.Bx < c.Constants.Count, "LOADK.Bx out of bounds"); break; case Instruction.LuaOpcode.LOADBOOL: assert(i.A < c.MaxStackSize, "LOADBOOL.A out of bounds"); assert(i.B < 2, "LOADBOOL.B invalid value"); assert(i.C < 2, "LOADBOOL.C invalid value"); break; case Instruction.LuaOpcode.LOADNIL: assert(i.A < c.MaxStackSize, "LOADNIL.A out of bounds"); assert(i.B < c.MaxStackSize, "LOADNIL.B out of bounds"); break; case Instruction.LuaOpcode.GETUPVAL: assert(i.A < c.MaxStackSize, "GETUPVAL.A out of bounds"); assert(i.B < c.Upvalues.Count, "GETUPVAL.B out of bounds"); break; case Instruction.LuaOpcode.GETGLOBAL: break; case Instruction.LuaOpcode.GETTABLE: break; case Instruction.LuaOpcode.SETGLOBAL: break; case Instruction.LuaOpcode.SETUPVAL: break; case Instruction.LuaOpcode.SETTABLE: break; case Instruction.LuaOpcode.NEWTABLE: break; case Instruction.LuaOpcode.SELF: break; case Instruction.LuaOpcode.ADD: break; case Instruction.LuaOpcode.SUB: break; case Instruction.LuaOpcode.MUL: break; case Instruction.LuaOpcode.DIV: break; case Instruction.LuaOpcode.MOD: break; case Instruction.LuaOpcode.POW: break; case Instruction.LuaOpcode.UNM: break; case Instruction.LuaOpcode.NOT: break; case Instruction.LuaOpcode.LEN: break; case Instruction.LuaOpcode.CONCAT: break; case Instruction.LuaOpcode.JMP: break; case Instruction.LuaOpcode.EQ: break; case Instruction.LuaOpcode.LT: break; case Instruction.LuaOpcode.LE: break; case Instruction.LuaOpcode.TEST: break; case Instruction.LuaOpcode.TESTSET: break; case Instruction.LuaOpcode.CALL: break; case Instruction.LuaOpcode.TAILCALL: break; case Instruction.LuaOpcode.RETURN: break; case Instruction.LuaOpcode.FORLOOP: break; case Instruction.LuaOpcode.FORPREP: break; case Instruction.LuaOpcode.TFORLOOP: break; case Instruction.LuaOpcode.SETLIST: break; case Instruction.LuaOpcode.CLOSE: break; case Instruction.LuaOpcode.CLOSURE: break; case Instruction.LuaOpcode.VARARG: break; default: break; } } }
public LuaFile Parse(string t) { this.text = t; file = new LuaFile(); index = 0; lineNumber = 1; func = file.Main; file.Main.Vararg = 2; file.Main.Name = "LASM Chunk"; funcStack = new Stack<Chunk>(); readWhitespace(); while (text.Length > index) { readWhitespace(); string line = ""; while (true) { if (text.Length <= index) break; char c = text[index]; if (c == '\r') { index++; if (text[index] == '\n') index++; break; } else if (c == '\n') { index++; break; } else line += c; index++; } line = line.Trim(); if (string.IsNullOrEmpty(line) || line[0] == ';') { } // do nothing. else if (line[0] == '.') parseControl(line); else { Instruction op = parseOpcode(line); op.LineNumber = lineNumber; func.Instructions.Add(op); } lineNumber++; } Instruction instr1 = func.Instructions.Count > 0 ? func.Instructions[func.Instructions.Count - 1] : null; Instruction instr2 = new Instruction("RETURN"); instr2.A = 0; instr2.B = 1; instr2.C = 0; //getmetatable(func.Instructions).__newindex(func.Instructions, func.Instructions.Count, op) if (instr1 == null || instr1.Opcode != Instruction.LuaOpcode.RETURN) func.Instructions.Add(instr2); return file; }
void parseControl(string line) { string ll = line.ToLower(); if (ll.Substring(0, 6) == ".const") { string l = line.Substring(6); l = l.Trim(); object value = readValue(l); if (value == null) func.Constants.Add(new Constant(ConstantType.Nil, null)); else if (value is bool) func.Constants.Add(new Constant(ConstantType.Bool, (bool)value)); else if (value is double) func.Constants.Add(new Constant(ConstantType.Number, (double)value)); else if (value is string) func.Constants.Add(new Constant(ConstantType.String, (string)value)); } else if (ll.Substring(0, 5) == ".name") { /// Im lazy :P string l = line.Substring(5); l = l.Trim(); if (l[0] == '"') func.Name = (string)readValue(l); else func.Name = l; } else if (ll.Substring(0, 8) == ".options") { string l = line.Substring(8); l = l.Trim(); List<int> nums = new List<int>(); // Pattern matching time! Regex r = new Regex("\\d+"); foreach (Match m in r.Matches(l)) nums.Add(int.Parse(m.Value)); func.UpvalueCount = nums.Count > 0 ? nums[0] : func.UpvalueCount; func.ArgumentCount = nums.Count > 1 ? nums[1] : func.ArgumentCount; func.Vararg = nums.Count > 2 ? nums[2] : func.Vararg; func.MaxStackSize = nums.Count > 3 ? (uint)nums[3] : func.MaxStackSize; } else if (ll.Substring(0, 6) == ".local") { string l = line.Substring(6).Trim(); if (l[0] == '"') func.Locals.Add(new Local((string)readValue(l), 0, 0)); else func.Locals.Add(new Local(l, 0, 0)); } else if (ll.Substring(0, 6) == ".upval") { string l = line.Substring(6).Trim(); if (l[0] == '"') func.Upvalues.Add(new Upvalue((string)readValue(l))); else func.Upvalues.Add(new Upvalue(l)); } else if (ll.Substring(0, 8) == ".upvalue") { string l = line.Substring(8).Trim(); if (l[0] == '"') func.Upvalues.Add(new Upvalue((string)readValue(l))); else func.Upvalues.Add(new Upvalue(l)); } else if (ll.Substring(0, 10) == ".stacksize") { string l = line.Substring(10).Trim(); uint n = uint.Parse(l); func.MaxStackSize = n; } else if (ll.Substring(0, 13) == ".maxstacksize") { string l = line.Substring(13).Trim(); uint n = uint.Parse(l); func.MaxStackSize = n; } else if (ll.Substring(0, 7) == ".vararg") { string l = line.Substring(7).Trim(); int n = int.Parse(l); func.Vararg = n; } else if (ll.Substring(0, 9) == ".function") { string l = line.Substring(9).Trim(); Chunk n = new Chunk(); n.FirstLine = (uint)lineNumber; if (l.Length > 0) if (l[0] == '"') n.Name = (string)readValue(l); else n.Name = l; func.Protos.Add(n); funcStack.Push(func); func = n; } else if (ll.Substring(0, 5) == ".func") { string l = line.Substring(5).Trim(); Chunk n = new Chunk(); n.FirstLine = (uint)lineNumber; if (l.Length > 0) if (l[0] == '"') n.Name = (string)readValue(l); else n.Name = l; func.Protos.Add(n); funcStack.Push(func); func = n; } else if (ll.Substring(0, 4) == ".end") { Chunk f = funcStack.Pop(); func.LastLine = (ulong)lineNumber; Instruction instr1 = func.Instructions.Count > 0 ? func.Instructions[func.Instructions.Count - 1] : null; Instruction instr2 = new Instruction("RETURN"); instr2.A = 0; instr2.B = 1; instr2.C = 0; if (instr1 != null && instr1.Opcode == Instruction.LuaOpcode.RETURN) { } //func.Instructions.Add(instr2); else func.Instructions.Add(instr2); func = f; } else throw new Exception("Invalid Control Label"); }
public static void VerifyChunk(Chunk c) { foreach (Instruction i in c.Instructions) { switch (i.Opcode) { case Instruction.LuaOp.MOVE: assert(i.C == 0, "MOVE.C must equal 0"); assert(i.A < c.MaxStackSize, "MOVE.A out of bounds"); assert(i.B < c.MaxStackSize, "MOVE.B out of bounds"); break; case Instruction.LuaOp.LOADK: assert(i.A < c.MaxStackSize, "LOADK.A out of bounds"); assert(i.Bx < c.Constants.Count, "LOADK.Bx out of bounds"); break; case Instruction.LuaOp.LOADBOOL: assert(i.A < c.MaxStackSize, "LOADBOOL.A out of bounds"); assert(i.B < 2, "LOADBOOL.B invalid value"); assert(i.C < 2, "LOADBOOL.C invalid value"); break; case Instruction.LuaOp.LOADNIL: assert(i.A < c.MaxStackSize, "LOADNIL.A out of bounds"); assert(i.B < c.MaxStackSize, "LOADNIL.B out of bounds"); break; case Instruction.LuaOp.GETUPVAL: assert(i.A < c.MaxStackSize, "GETUPVAL.A out of bounds"); assert(i.B < c.Upvalues.Count, "GETUPVAL.B out of bounds"); break; case Instruction.LuaOp.GETGLOBAL: break; case Instruction.LuaOp.GETTABLE: break; case Instruction.LuaOp.SETGLOBAL: break; case Instruction.LuaOp.SETUPVAL: break; case Instruction.LuaOp.SETTABLE: break; case Instruction.LuaOp.NEWTABLE: break; case Instruction.LuaOp.SELF: break; case Instruction.LuaOp.ADD: break; case Instruction.LuaOp.SUB: break; case Instruction.LuaOp.MUL: break; case Instruction.LuaOp.DIV: break; case Instruction.LuaOp.MOD: break; case Instruction.LuaOp.POW: break; case Instruction.LuaOp.UNM: break; case Instruction.LuaOp.NOT: break; case Instruction.LuaOp.LEN: break; case Instruction.LuaOp.CONCAT: break; case Instruction.LuaOp.JMP: break; case Instruction.LuaOp.EQ: break; case Instruction.LuaOp.LT: break; case Instruction.LuaOp.LE: break; case Instruction.LuaOp.TEST: break; case Instruction.LuaOp.TESTSET: break; case Instruction.LuaOp.CALL: break; case Instruction.LuaOp.TAILCALL: break; case Instruction.LuaOp.RETURN: break; case Instruction.LuaOp.FORLOOP: break; case Instruction.LuaOp.FORPREP: break; case Instruction.LuaOp.TFORLOOP: break; case Instruction.LuaOp.SETLIST: break; case Instruction.LuaOp.CLOSE: break; case Instruction.LuaOp.CLOSURE: break; case Instruction.LuaOp.VARARG: break; default: break; } } }
void dump(Chunk c) { //textBox2.Text += "; Chunk Name: " + c.Name + "\r\n"; foreach (Instruction i in c.Instructions) { switch (i.OpcodeType) { case OpcodeType.ABC: textBox2.Text += i.OpcodeName; textBox2.Text += " " + i.A; textBox2.Text += " " + i.B; textBox2.Text += " " + i.C; break; case OpcodeType.ABx: textBox2.Text += i.OpcodeName; textBox2.Text += " " + i.A; textBox2.Text += " " + i.Bx; break; case OpcodeType.AsBx: textBox2.Text += i.OpcodeName; textBox2.Text += " " + i.A; textBox2.Text += " " + i.sBx; break; default: break; } textBox2.Text += "\r\n"; } foreach (Chunk c2 in c.Protos) { //textBox2.Text += "\r\n"; dump(c2); } }