/// <summary> /// Returns a decompiled chunk, with info based upon a default LuaFile /// </summary> /// <param name="chunk"></param> /// <returns></returns> public static Chunk DisassembleChunk(string c) { chunk = c; index = 0; file = new LuaFile(); loadNumber = PlatformConfig.GetNumberTypeConvertFrom(file); if (chunk == null || string.IsNullOrWhiteSpace(chunk)) { throw new Exception("chunk is empty"); } return(ReadFunction()); }
/// <summary> /// Returns a disassembled LuaFile /// </summary> /// <param name="c"></param> /// <returns></returns> public static LuaFile Disassemble(string c) { chunk = c; index = 0; file = new LuaFile(); Disassembler.loadNumber = null; if (chunk == null || string.IsNullOrWhiteSpace(chunk)) { throw new Exception("chunk is empty"); } file.Identifier = GetString(4); // \027Lua if (file.Identifier != (char)27 + "Lua") { throw new Exception("Not a valid Lua bytecode chunk"); } file.Version = ReadInt8(); // 0x51 if (file.Version != 0x51) { throw new Exception(string.Format("Invalid bytecode version, 0x51 expected, got 0x{0:X}", file.Version)); } int fmt = ReadInt8(); file.Format = fmt == 0 ? Format.Official : Format.Unofficial; file.FormatNumber = fmt; if (file.Format == Format.Unofficial) { throw new Exception("Unknown binary chunk format"); } file.BigEndian = ReadInt8() == 0; file.IntegerSize = ReadInt8(); file.SizeT = ReadInt8(); file.InstructionSize = ReadInt8(); file.NumberSize = ReadInt8(); file.IsFloatingPointNumbers = ReadInt8() == 0; loadNumber = PlatformConfig.GetNumberTypeConvertFrom(file); if (file.InstructionSize != 4) { throw new Exception("Unsupported instruction size '" + file.InstructionSize + "', expected '4'"); } file.Main = ReadFunction(); return(file); }
public string Compile(LuaFile file) { Func <double, string> DumpNumber = PlatformConfig.GetNumberTypeConvertTo(file); Func <int, string> DumpInt = new Func <int, string>(delegate(int num) { string v = ""; for (int i = 1; i < file.IntegerSize; i++) { v = v + (char)(num % 256); num = (int)Math.Floor((double)num / 256); } return(v); }); Func <string, string> DumpString = new Func <string, string>(delegate(string s) { int len = file.SizeT; if (s == null || s.Length == 0) { return("\0".Repeat(len)); } else { return(DumpInt(s.Length + 1) + s + "\0"); } }); string c = ""; c = c + DumpString(Name); c = c + DumpInt((int)FirstLine); c = c + DumpInt((int)LastLine); c = c + (char)UpvalueCount; c = c + (char)ArgumentCount; c = c + (char)Vararg; c = c + (char)MaxStackSize; // Instructions c = c + DumpInt(Instructions.Count); foreach (Instruction i in Instructions) { c = c + DumpBinary.Opcode(i); } // Constants c = c + DumpInt(Constants.Count); foreach (Constant cnst in Constants) { if (cnst.Type == ConstantType.Nil) { c = c + (char)0; } else if (cnst.Type == ConstantType.Bool) { c = c + (char)1; c = c + (char)((bool)cnst.Value ? 1 : 0); } else if (cnst.Type == ConstantType.Number) { c = c + (char)3; c = c + DumpNumber((long)cnst.Value); } else if (cnst.Type == ConstantType.String) { c = c + (char)4; c = c + DumpString((string)cnst.Value); } else { throw new Exception("Invalid constant type: " + cnst.Type.ToString()); } } // Protos c = c + DumpInt(Protos.Count); foreach (Chunk ch in Protos) { c = c + ch.Compile(file); } // Line Numbers c = c + DumpInt(Instructions.Count); foreach (Instruction i in Instructions) { c = c = DumpInt(i.LineNumber); } // Locals c = c + DumpInt(Locals.Count); foreach (Local l in Locals) { c = c + DumpString(l.Name); c = c + DumpInt(l.StartPC); c = c + DumpInt(l.EndPC); } // Upvalues c = c + DumpInt(Upvalues.Count); foreach (Upvalue v in Upvalues) { c = c + DumpString(v.Name); } return(c); }