/// <summary> /// Creates a chunk from a Lua proto /// </summary> /// <param name="p"></param> public Chunk(Lua.Proto p) { Name = p.source.str.ToString(); MaxStackSize = p.maxstacksize; Vararg = p.is_vararg; ArgumentCount = p.numparams; UpvalueCount = p.nups; LastLine = (ulong)p.lastlinedefined; FirstLine = (uint)p.linedefined; foreach (uint instr in p.code) { Instructions.Add(Instruction.From(instr)); } foreach (Lua.lua_TValue k in p.k) { if (k.tt == Lua.LUA_TNIL) { Constants.Add(new Constant(ConstantType.Nil, null)); } else if (k.tt == Lua.LUA_TBOOLEAN) { Constants.Add(new Constant(ConstantType.Bool, (int)k.value.p != 0)); } else if (k.tt == Lua.LUA_TNUMBER) { Constants.Add(new Constant(ConstantType.Number, k.value.n)); } else if (k.tt == Lua.LUA_TSTRING) { Constants.Add(new Constant(ConstantType.String, k.value.p.ToString())); } } if (p.protos != null) { foreach (Lua.Proto p2 in p.protos) { Protos.Add(new Chunk(p2)); } } foreach (Lua.LocVar l in p.locvars) { Locals.Add(new Local(l.varname.str.ToString(), l.startpc, l.endpc)); } foreach (Lua.TString upval in p.upvalues) { Upvalues.Add(new Upvalue(upval.str.ToString())); } for (int i = 0; i < p.lineinfo.Length; i++) { Instructions[i].LineNumber = p.lineinfo[i]; } }
void check(Lua.Proto s, Variable v, int index) { if (Addresses.ContainsKey(s) == false) { Addresses.Add(s, new Dictionary <Variable, int>()); } if (Addresses[s].ContainsKey(v) == false) { Addresses[s].Add(v, index); } }
int getOrCreate(Lua.Proto s, Variable v) { if (indexes.ContainsKey(s) == false) { indexes.Add(s, 0); } if (Addresses[s].ContainsKey(v) == false) { check(s, v, indexes[s]++); } else { return(Addresses[s][v]); } return(Addresses[s][v]); }
public string Decompile(Lua.Proto f) { this.f = f; foreach (uint cd in f.code) { Lua.OpCode op = Lua.GET_OPCODE(cd); Lua.OpMode mode = Lua.getOpMode(op); int a = Lua.GETARG_A(cd); int b = Lua.GETARG_B(cd); int c = Lua.GETARG_C(cd); int bx = Lua.GETARG_Bx(cd); switch (op) { case Lua.OpCode.OP_MOVE: emitName(a); emit(" = "); emitName(b); break; case Lua.OpCode.OP_LOADK: emitName(a); emit(" = "); emitConst(bx, true); break; case Lua.OpCode.OP_LOADBOOL: emitName(a); emit(" = "); if (b == 0) emit("false"); else emit("true"); break; case Lua.OpCode.OP_LOADNIL: for (int _ = a; _ < b; _++) { emitName(_); emit(" = nil"); } break; case Lua.OpCode.OP_GETUPVAL: emitName(a); emit(" = "); emit(f.upvalues[b].str.ToString()); break; case Lua.OpCode.OP_GETGLOBAL: emit(getName(a)); emit(" = "); emitConst(bx, false); break; case Lua.OpCode.OP_GETTABLE: emitName(a); emit(" = "); emitName(b); emit("["); emitRegOrConst(c); emit("]"); break; case Lua.OpCode.OP_SETGLOBAL: emitConst(bx, false); emit(" = "); emitName(a); break; case Lua.OpCode.OP_SETUPVAL: emit(f.upvalues[b].str.ToString()); emit(" = "); emitName(a); break; case Lua.OpCode.OP_SETTABLE: emitName(a); emit("["); emitRegOrConst(b); emit("] = "); emitRegOrConst(c); break; case Lua.OpCode.OP_NEWTABLE: emitName(a); emit(" = { }"); break; case Lua.OpCode.OP_SELF: // A B C, R(A+1) := R(B); R(A) := R(B)[RK(C)] emitName(a + 1); emit(" = "); emitName(b); emitName(a); emit(" = "); emitName(b); emit("["); emitRegOrConst(c); emit("]"); break; case Lua.OpCode.OP_ADD: // A B C, R(A) := RK(B) + RK(C) emitName(a); emit(" = "); emitRegOrConst(b); emit(" + "); emitRegOrConst(c); break; case Lua.OpCode.OP_SUB: // A B C, R(A) := RK(B) - RK(C) emitName(a); emit(" = "); emitRegOrConst(b); emit(" - "); emitRegOrConst(c); break; case Lua.OpCode.OP_MUL: // A B C, R(A) := RK(B) * RK(C) emitName(a); emit(" = "); emitRegOrConst(b); emit(" * "); emitRegOrConst(c); break; case Lua.OpCode.OP_DIV: // A B C, R(A) := RK(B) / RK(C) emitName(a); emit(" = "); emitRegOrConst(b); emit(" / "); emitRegOrConst(c); break; case Lua.OpCode.OP_MOD: // A B C, R(A) := RK(B) % RK(C) emitName(a); emit(" = "); emitRegOrConst(b); emit(" % "); emitRegOrConst(c); break; case Lua.OpCode.OP_POW: // A B C, R(A) := RK(B) ^ RK(C) emitName(a); emit(" = "); emitRegOrConst(b); emit(" ^ "); emitRegOrConst(c); break; case Lua.OpCode.OP_UNM: //A B, R(A) := -R(B) emitName(a); emit(" = -"); emitName(b); break; case Lua.OpCode.OP_NOT: //A B, R(A) := -R(B) emitName(a); emit(" = not "); emitName(b); break; case Lua.OpCode.OP_LEN: //A B, R(A) := #R(B) emitName(a); emit(" = #"); emitName(b); break; case Lua.OpCode.OP_CONCAT: // A B C, R(A) := R(B).. ... ..R(C) emitName(a); emit(" = "); for (int _ = b; _ < c; _++) { emitName(_); if (_ != c) emit(" .. "); } emitName(c); break; case Lua.OpCode.OP_JMP: emit("-- JMP Opcode not supported\r\n"); int x = Lua.GETARG_sBx(cd); emit("-- JMP " + x); break; case Lua.OpCode.OP_EQ: // A B C, if ((RK(B) == RK(C)) ~= A) then pc++ emit("if ("); emitRegOrConst(b); emit(" == "); emitRegOrConst(c); emit(") ~= "); emit(a != 0 ? "true" : "false"); emit(" then"); break; case Lua.OpCode.OP_LT: // A B C, if ((RK(B) < RK(C)) ~= A) then pc++ emit("if ("); emitRegOrConst(b); emit(" < "); emitRegOrConst(c); emit(") ~= "); emit(a != 0 ? "true" : "false"); emit(" then"); break; case Lua.OpCode.OP_LE: // A B C, if ((RK(B) == RK(C)) ~= A) then pc++ emit("if ("); emitRegOrConst(b); emit(" <= "); emitRegOrConst(c); emit(") ~= "); emit(a != 0 ? "true" : "false"); emit(" then"); break; case Lua.OpCode.OP_TEST: // A C, if not (R(A) <=> C) then pc++ emit("if not ("); emitName(a); emit(" <= "); emitName(c); emit(" or "); emitName(a); emit(" >= "); emitName(c); emit(") then \r\n"); emit("-- Unsupported: pc++"); break; case Lua.OpCode.OP_TESTSET: // A B C, if (R(B) <=> C) then R(A) := R(B) else pc++ emit("if "); emitName(b); emit(" <= "); emitName(c); emit(" or "); emitName(b); emit(" >= "); emitName(c); emit(" then \r\n"); emitName(a); emit(" = "); emitName(b); emit("\r\nend"); break; case Lua.OpCode.OP_CALL: // A B C, R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) bool wroteName = false; for (int _ = a; _ < (a + c) - 2; _++) { wroteName = true; if (_ != (a + c) - 2) emit(", "); } //emitName((a + c) - 2); if (wroteName) emit(" = "); emitName(a); emit("("); for (int _ = a + 1; _ < (a + b) - 1; _++) { emitName(_); if (_ != (a + b) - 1) emit(", "); } emitName(a + b - 1); emit(")"); break; case Lua.OpCode.OP_TAILCALL: // A B C, return R(A)(R(A+1), ... ,R(A+B-1)) emit("return "); emitName(a); emit("("); for (int _ = a + 1; _ < a + b - 1; _++) { emitName(_); if (_ != a + b - 1) emit(", "); } emit(")"); break; case Lua.OpCode.OP_RETURN: // A B, return R(A), ... ,R(A+B-2) emit("return "); for (int _ = a; _ < a + b - 2; _++) { emitName(_); if (_ != a + b - 2) emit(", "); } break; case Lua.OpCode.OP_FORLOOP: emit("-- Unsupported Opcode: FORPREP"); break; case Lua.OpCode.OP_FORPREP: emit("-- Unsupported Opcode: FORPREP"); break; case Lua.OpCode.OP_TFORLOOP: /* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++ */ for (int _ = a + 3; _ < a + 2 + c; _++) { emitName(_); if (_ != a + 2 + c) emit(", "); } emit(" = "); emitName(a); emit("("); emitName(a + 1); emit(", "); emitName(a + 2); emit(")\r\nif "); emitName(a + 3); emit(" ~= nil then "); emitName(a + 2); emit(" = "); emitName(a + 3); emit(" end"); break; case Lua.OpCode.OP_SETLIST: emit("-- Unsupported Opcode: SETLIST"); break; case Lua.OpCode.OP_CLOSE: // A, close all variables in the stack up to (>=) R(A) emit("-- Unsupported Opcode: CLOSE"); break; case Lua.OpCode.OP_CLOSURE: // A Bx, R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) emit("-- Unsupported Opcode: CLOSURE"); break; case Lua.OpCode.OP_VARARG: // A B, R(A), R(A+1), ..., R(A+B-1) = vararg for (int _ = a; _ < a + b - 1; _++) { emitName(_); if (_ != a + b - 1) emit(", "); } emit(" = ..."); break; default: break; } emit("\r\n"); } return sb.ToString(); }
public LuaFile(Lua.Proto p) { Main = new Chunk(p); }
public string Decompile(Lua.Proto f) { this.f = f; foreach (uint cd in f.code) { Lua.OpCode op = Lua.GET_OPCODE(cd); Lua.OpMode mode = Lua.getOpMode(op); int a = Lua.GETARG_A(cd); int b = Lua.GETARG_B(cd); int c = Lua.GETARG_C(cd); int bx = Lua.GETARG_Bx(cd); switch (op) { case Lua.OpCode.OP_MOVE: emitName(a); emit(" = "); emitName(b); break; case Lua.OpCode.OP_LOADK: emitName(a); emit(" = "); emitConst(bx, true); break; case Lua.OpCode.OP_LOADBOOL: emitName(a); emit(" = "); if (b == 0) { emit("false"); } else { emit("true"); } break; case Lua.OpCode.OP_LOADNIL: for (int _ = a; _ < b; _++) { emitName(_); emit(" = nil"); } break; case Lua.OpCode.OP_GETUPVAL: emitName(a); emit(" = "); emit(f.upvalues[b].str.ToString()); break; case Lua.OpCode.OP_GETGLOBAL: emit(getName(a)); emit(" = "); emitConst(bx, false); break; case Lua.OpCode.OP_GETTABLE: emitName(a); emit(" = "); emitName(b); emit("["); emitRegOrConst(c); emit("]"); break; case Lua.OpCode.OP_SETGLOBAL: emitConst(bx, false); emit(" = "); emitName(a); break; case Lua.OpCode.OP_SETUPVAL: emit(f.upvalues[b].str.ToString()); emit(" = "); emitName(a); break; case Lua.OpCode.OP_SETTABLE: emitName(a); emit("["); emitRegOrConst(b); emit("] = "); emitRegOrConst(c); break; case Lua.OpCode.OP_NEWTABLE: emitName(a); emit(" = { }"); break; case Lua.OpCode.OP_SELF: // A B C, R(A+1) := R(B); R(A) := R(B)[RK(C)] emitName(a + 1); emit(" = "); emitName(b); emitName(a); emit(" = "); emitName(b); emit("["); emitRegOrConst(c); emit("]"); break; case Lua.OpCode.OP_ADD: // A B C, R(A) := RK(B) + RK(C) emitName(a); emit(" = "); emitRegOrConst(b); emit(" + "); emitRegOrConst(c); break; case Lua.OpCode.OP_SUB: // A B C, R(A) := RK(B) - RK(C) emitName(a); emit(" = "); emitRegOrConst(b); emit(" - "); emitRegOrConst(c); break; case Lua.OpCode.OP_MUL: // A B C, R(A) := RK(B) * RK(C) emitName(a); emit(" = "); emitRegOrConst(b); emit(" * "); emitRegOrConst(c); break; case Lua.OpCode.OP_DIV: // A B C, R(A) := RK(B) / RK(C) emitName(a); emit(" = "); emitRegOrConst(b); emit(" / "); emitRegOrConst(c); break; case Lua.OpCode.OP_MOD: // A B C, R(A) := RK(B) % RK(C) emitName(a); emit(" = "); emitRegOrConst(b); emit(" % "); emitRegOrConst(c); break; case Lua.OpCode.OP_POW: // A B C, R(A) := RK(B) ^ RK(C) emitName(a); emit(" = "); emitRegOrConst(b); emit(" ^ "); emitRegOrConst(c); break; case Lua.OpCode.OP_UNM: //A B, R(A) := -R(B) emitName(a); emit(" = -"); emitName(b); break; case Lua.OpCode.OP_NOT: //A B, R(A) := -R(B) emitName(a); emit(" = not "); emitName(b); break; case Lua.OpCode.OP_LEN: //A B, R(A) := #R(B) emitName(a); emit(" = #"); emitName(b); break; case Lua.OpCode.OP_CONCAT: // A B C, R(A) := R(B).. ... ..R(C) emitName(a); emit(" = "); for (int _ = b; _ < c; _++) { emitName(_); if (_ != c) { emit(" .. "); } } emitName(c); break; case Lua.OpCode.OP_JMP: emit("-- JMP Opcode not supported\r\n"); int x = Lua.GETARG_sBx(cd); emit("-- JMP " + x); break; case Lua.OpCode.OP_EQ: // A B C, if ((RK(B) == RK(C)) ~= A) then pc++ emit("if ("); emitRegOrConst(b); emit(" == "); emitRegOrConst(c); emit(") ~= "); emit(a != 0 ? "true" : "false"); emit(" then"); break; case Lua.OpCode.OP_LT: // A B C, if ((RK(B) < RK(C)) ~= A) then pc++ emit("if ("); emitRegOrConst(b); emit(" < "); emitRegOrConst(c); emit(") ~= "); emit(a != 0 ? "true" : "false"); emit(" then"); break; case Lua.OpCode.OP_LE: // A B C, if ((RK(B) == RK(C)) ~= A) then pc++ emit("if ("); emitRegOrConst(b); emit(" <= "); emitRegOrConst(c); emit(") ~= "); emit(a != 0 ? "true" : "false"); emit(" then"); break; case Lua.OpCode.OP_TEST: // A C, if not (R(A) <=> C) then pc++ emit("if not ("); emitName(a); emit(" <= "); emitName(c); emit(" or "); emitName(a); emit(" >= "); emitName(c); emit(") then \r\n"); emit("-- Unsupported: pc++"); break; case Lua.OpCode.OP_TESTSET: // A B C, if (R(B) <=> C) then R(A) := R(B) else pc++ emit("if "); emitName(b); emit(" <= "); emitName(c); emit(" or "); emitName(b); emit(" >= "); emitName(c); emit(" then \r\n"); emitName(a); emit(" = "); emitName(b); emit("\r\nend"); break; case Lua.OpCode.OP_CALL: // A B C, R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) bool wroteName = false; for (int _ = a; _ < (a + c) - 2; _++) { wroteName = true; if (_ != (a + c) - 2) { emit(", "); } } //emitName((a + c) - 2); if (wroteName) { emit(" = "); } emitName(a); emit("("); for (int _ = a + 1; _ < (a + b) - 1; _++) { emitName(_); if (_ != (a + b) - 1) { emit(", "); } } emitName(a + b - 1); emit(")"); break; case Lua.OpCode.OP_TAILCALL: // A B C, return R(A)(R(A+1), ... ,R(A+B-1)) emit("return "); emitName(a); emit("("); for (int _ = a + 1; _ < a + b - 1; _++) { emitName(_); if (_ != a + b - 1) { emit(", "); } } emit(")"); break; case Lua.OpCode.OP_RETURN: // A B, return R(A), ... ,R(A+B-2) emit("return "); for (int _ = a; _ < a + b - 2; _++) { emitName(_); if (_ != a + b - 2) { emit(", "); } } break; case Lua.OpCode.OP_FORLOOP: emit("-- Unsupported Opcode: FORPREP"); break; case Lua.OpCode.OP_FORPREP: emit("-- Unsupported Opcode: FORPREP"); break; case Lua.OpCode.OP_TFORLOOP: /* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); * if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++ */ for (int _ = a + 3; _ < a + 2 + c; _++) { emitName(_); if (_ != a + 2 + c) { emit(", "); } } emit(" = "); emitName(a); emit("("); emitName(a + 1); emit(", "); emitName(a + 2); emit(")\r\nif "); emitName(a + 3); emit(" ~= nil then "); emitName(a + 2); emit(" = "); emitName(a + 3); emit(" end"); break; case Lua.OpCode.OP_SETLIST: emit("-- Unsupported Opcode: SETLIST"); break; case Lua.OpCode.OP_CLOSE: // A, close all variables in the stack up to (>=) R(A) emit("-- Unsupported Opcode: CLOSE"); break; case Lua.OpCode.OP_CLOSURE: // A Bx, R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) emit("-- Unsupported Opcode: CLOSURE"); break; case Lua.OpCode.OP_VARARG: // A B, R(A), R(A+1), ..., R(A+B-1) = vararg for (int _ = a; _ < a + b - 1; _++) { emitName(_); if (_ != a + b - 1) { emit(", "); } } emit(" = ..."); break; case Lua.OpCode.OP_RSHIFT: // A B C, R(A) := RK(B) >> RK(C) emitName(a); emit(" = "); emitRegOrConst(b); emit(" >> "); emitRegOrConst(c); break; case Lua.OpCode.OP_LSHIFT: // A B C, R(A) := RK(B) << RK(C) emitName(a); emit(" = "); emitRegOrConst(b); emit(" << "); emitRegOrConst(c); break; case Lua.OpCode.OP_BITAND: // A B C, R(A) := RK(B) & RK(C) emitName(a); emit(" = "); emitRegOrConst(b); emit(" & "); emitRegOrConst(c); break; case Lua.OpCode.OP_BITOR: // A B C, R(A) := RK(B) | RK(C) emitName(a); emit(" = "); emitRegOrConst(b); emit(" ^| "); emitRegOrConst(c); break; default: break; } emit("\r\n"); } return(sb.ToString()); }
public int ToReg(Lua.Proto p, Variable v) { return(getOrCreate(p, v)); }
public Compiler() { current = main; }