public static void ToControlFlowGraph(MjoScript script) { if (script.Representation == MjoScriptRepresentation.ControlFlowGraph) { script.SanityCheck(); return; } if (script.Representation != MjoScriptRepresentation.SsaGraph) { throw new Exception("Unable to convert script to control flow graph representation from current state: " + script.Representation); } script.Representation = MjoScriptRepresentation.InTransition; foreach (var instruction in script.Instructions) { instruction.BeforeValues = null; instruction.PoppedValues = null; instruction.PushedValues = null; } foreach (var block in script.Blocks) { block.StartState = null; block.EndState = null; block.PhiNodes = null; } script.Representation = MjoScriptRepresentation.ControlFlowGraph; script.SanityCheck(); }
public static void ToSource(MjoScript script) { if (script.Representation == MjoScriptRepresentation.SyntaxTree) { script.SanityCheck(); return; } if (script.Representation != MjoScriptRepresentation.SsaGraph) { throw new Exception("Unable to convert script to source representation from current state: " + script.Representation); } script.Representation = MjoScriptRepresentation.InTransition; foreach (var function in script.Functions) { var node = new Decompiler(function).Decompile(); node.Accept(new DumpVisitor(), IColoredWriter.Console); Console.WriteLine(); } script.Representation = MjoScriptRepresentation.SyntaxTree; script.SanityCheck(); }
public static void ToSsaGraph(MjoScript script) { if (script.Representation == MjoScriptRepresentation.SsaGraph) { script.SanityCheck(); return; } if (script.Representation != MjoScriptRepresentation.ControlFlowGraph) { throw new Exception("Unable to convert script to ssa graph representation from current state: " + script.Representation); } script.Representation = MjoScriptRepresentation.InTransition; foreach (var function in script.Functions) { ToSsaGraph(function); } script.Representation = MjoScriptRepresentation.SsaGraph; script.SanityCheck(); }
public Decompiler(Function function) { Function = function; Script = function.Script; Instructions = function.Instructions.ToList(); }
public Function(MjoScript script, uint nameHash) { Script = script; NameHash = nameHash; }
public static void Analyze(MjoScript script) => script.Functions.ForEach(Analyze);
public static void ToControlFlowGraph(MjoScript script) { if (script.Representation == MjoScriptRepresentation.ControlFlowGraph) { script.SanityCheck(); return; } if (script.Representation != MjoScriptRepresentation.InstructionList) { throw new Exception("Unable to convert script to control flow graph representation from current state: " + script.Representation); } script.Representation = MjoScriptRepresentation.InTransition; var functionStarts = new HashSet <int>(); var functions = new List <Function>(); script.Functions = functions; // mark function start indices foreach (var functionEntry in script.FunctionIndex) { uint offset = functionEntry.Offset; int index = script.InstructionIndexFromOffset(offset); if (index < 0) { throw new Exception($"No instruction found at offset 0x{offset:x8}"); } var function = new Function(script, functionEntry.NameHash) { FirstInstructionIndex = index }; if (functionEntry.Offset == script.EntryPointOffset) { script.EntryPointFunction = function; } functions.Add(function); functionStarts.Add(index); } // find function ends foreach (var function in functions) { for (int i = function.FirstInstructionIndex; i < script.Instructions.Count; i++) { if (i + 1 == script.Instructions.Count || functionStarts.Contains(i + 1)) { function.LastInstructionIndex = i; break; } } if (function.LastInstructionIndex == -1) { throw new Exception("Unable to find last instruction"); } } foreach (var function in functions) { AnalyzeFunction(function); } script.EntryPointOffset = null; script.FunctionIndex = null; foreach (var instruction in script.Instructions) { instruction.Offset = null; instruction.Size = null; } script.Representation = MjoScriptRepresentation.ControlFlowGraph; script.SanityCheck(); }
public static void ToInstructionList(MjoScript script) { if (script.Representation == MjoScriptRepresentation.InstructionList) { script.SanityCheck(); return; } if (script.Representation != MjoScriptRepresentation.ControlFlowGraph) { throw new Exception("Unable to convert script to instruction list representation from current state: " + script.Representation); } script.Representation = MjoScriptRepresentation.InTransition; // calculate size and offset for all instructions uint offset = 0; foreach (var instruction in script.Instructions) { uint size = Assembler.GetInstructionSize(instruction); instruction.Offset = offset; instruction.Size = size; instruction.Block = null; instruction.StackState = null; offset += size; } // resolve jump and switch targets to relative offsets foreach (var instruction in script.Instructions) { if (instruction.IsJump) { Debug.Assert(instruction.JumpTarget != null); long jumpSourceOffset = instruction.Offset !.Value + instruction.Size !.Value; long jumpTargetOffset = instruction.JumpTarget.StartOffset !.Value; instruction.JumpOffset = checked ((int)(jumpTargetOffset - jumpSourceOffset)); instruction.JumpTarget = null; } else if (instruction.IsSwitch) { Debug.Assert(instruction.SwitchTargets != null); instruction.SwitchOffsets = new int[instruction.SwitchTargets.Length]; for (int i = 0; i < instruction.SwitchTargets.Length; i++) { var switchTarget = instruction.SwitchTargets[i]; Debug.Assert(switchTarget != null); long jumpSourceOffset = instruction.Offset !.Value + 2 + 2 + (i + 1) * 4; long jumpTargetOffset = switchTarget.StartOffset !.Value; instruction.SwitchOffsets[i] = checked ((int)(jumpTargetOffset - jumpSourceOffset)); } instruction.SwitchTargets = null; } instruction.SanityCheck(MjoScriptRepresentation.InstructionList); } script.FunctionIndex = new List <FunctionIndexEntry>(); foreach (var function in script.Functions) { script.FunctionIndex.Add(new FunctionIndexEntry { NameHash = function.NameHash, Offset = function.StartOffset !.Value });