Пример #1
0
        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();
        }
Пример #2
0
        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();
        }
Пример #3
0
        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();
        }
Пример #4
0
 public Decompiler(Function function)
 {
     Function     = function;
     Script       = function.Script;
     Instructions = function.Instructions.ToList();
 }
Пример #5
0
 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
                });