Example #1
0
        private void AnalyzeConditionalBranch(HLInstruction branchInstruction)
        {
            int branchOffset = branchInstruction.Instruction.Offset +
                               branchInstruction.Instruction.InstructionLength;

            CodePath parentPath = branchInstruction.ParentCodePath;

            CodePath branchCodePath = CreateCodePath("if", branchOffset, parentPath);

            branchCodePath.ParentExitInstruction = branchInstruction;

            bool condition = branchInstruction.Instruction.OpCode == OpCode.JumpFalse ? true : false;

            branchInstruction.BranchCodesPaths.Add(condition, branchCodePath);

            branchInstruction.DefaultConditional = condition;

            AnalyzeCodePath(branchCodePath);

            if (branchInstruction.NextInstruction != null &&
                branchCodePath.ParentEntryTargetInstruction != branchInstruction.NextInstruction)
            {
                // Well, shit.. we got an else block.

                CodePath branchElseCodePath = ExtractPath("if_else", branchInstruction.ParentCodePath, branchInstruction,
                                                          branchInstruction.NextInstruction,
                                                          branchCodePath.ParentEntryInstruction);

                branchInstruction.BranchCodesPaths.Add(!condition, branchElseCodePath);
            }
        }
Example #2
0
        private static void MergePath(CodePath targetPath, CodePath newPath)
        {
            HLInstruction hlInstruction = newPath.StartInstruction;

            if (targetPath.EndInstruction == null)
            {
                targetPath.StartInstruction       = hlInstruction;
                hlInstruction.PreviousInstruction = null;
            }
            else
            {
                targetPath.EndInstruction.NextInstruction = hlInstruction;
                hlInstruction.PreviousInstruction         = targetPath.EndInstruction;
            }

            while (true)
            {
                newPath.InstructionMap.Remove(hlInstruction.Instruction.Offset);
                hlInstruction.ParentCodePath = targetPath;
                targetPath.InstructionMap.Add(hlInstruction.Instruction.Offset, hlInstruction);

                if (hlInstruction.NextInstruction == null)
                {
                    break;
                }

                hlInstruction = hlInstruction.NextInstruction;
            }

            targetPath.EndInstruction = hlInstruction;
            targetPath.EndOffset      = hlInstruction.Instruction.Offset + hlInstruction.Instruction.InstructionLength;

            newPath.ParentFunction.CodePaths.Remove(newPath);
        }
Example #3
0
        public HLInstruction GetNextInstruction()
        {
            HLInstruction instruction = NextInstruction;

            if (instruction != null && instruction.UnconditionalBranch)
            {
                instruction = instruction.NextInstruction;
            }
            return(instruction);
        }
Example #4
0
        private void AnalyzeSwitchBranch(HLInstruction branchInstruction)
        {
            var sw = branchInstruction.Instruction as InstructionSwitch;

            CodePath parentPath = branchInstruction.ParentCodePath;

            var  swMap          = new Dictionary <int, CodePath>();
            bool allWereReturns = true;

            HLInstruction switchExitInstruction = branchInstruction.NextInstruction.NextInstruction;

            foreach (var item in sw.SwitchTable)
            {
                if (swMap.ContainsKey(item.Value))
                {
                    // Deal with multiple values leading to the same code path
                    branchInstruction.BranchCodesPaths.Add(item.Key, swMap[item.Value]);
                }
                else
                {
                    CodePath branchCodePath = CreateCodePath("sw_case_" + item.Key, item.Value, parentPath);
                    branchCodePath.ParentExitInstruction = branchInstruction;

                    branchInstruction.BranchCodesPaths.Add(item.Key, branchCodePath);
                    swMap.Add(item.Value, branchCodePath);

                    AnalyzeCodePath(branchCodePath);

                    if (branchCodePath.ParentEntryInstruction != null)
                    {
                        allWereReturns        = false;
                        switchExitInstruction = branchCodePath.ParentEntryInstruction;
                    }
                }
            }

            if (allWereReturns)
            {
                switchExitInstruction = null;
            }

            if (switchExitInstruction != branchInstruction.NextInstruction.NextInstruction)
            {
                // Crappy... got a default case statement that we need to extract

                CodePath branchDefaultCodePath = ExtractPath("sw_case_default", parentPath, branchInstruction, branchInstruction.NextInstruction, switchExitInstruction);

                branchInstruction.BranchCodesPaths.Add(new object(), branchDefaultCodePath);
            }
        }
Example #5
0
 private HLInstruction WriteLoopConditional(TextWriter writer, HLInstruction instruction, string indent)
 {
     // Use for loop conditions
     while (instruction != null)
     {
         if (instruction.IsConditionalBranch)
         {
             break;
         }
         WriteInstruction(writer, instruction, indent);
         instruction = instruction.GetNextInstruction();
     }
     return instruction;
 }
Example #6
0
        /// <summary>
        /// Dumps a codepath to debug
        /// </summary>
        /// <param name="path"></param>
        private static void DumpCodePath(CodePath path)
        {
            HLInstruction instruction = path.StartInstruction;

            while (instruction != null)
            {
                Debug.WriteLine(instruction.Instruction.ToString());
                if (instruction.BranchCodesPaths != null && instruction.BranchCodesPaths.Count > 0)
                {
                    foreach (var item in instruction.BranchCodesPaths)
                    {
                        Debug.WriteLine("    " + item.Key + " --> " + item.Value.Name);
                    }
                }
                instruction = instruction.NextInstruction;
            }
        }
Example #7
0
 private void WriteInstruction(TextWriter writer, HLInstruction instruction, string indent)
 {
     writer.Write(string.Format("{0}{1:x}: ", indent, instruction.Instruction.Offset));
     if (instruction.BranchFunction != null)
     {
         writer.WriteLine(string.Format("{0}()", instruction.BranchFunction.Name));
     }
     else if (instruction.ExitFunction)
     {
         writer.WriteLine("return");
     }
     else if (instruction.Instruction is InstructionNative)
     {
         writer.WriteLine(string.Format("{0}(in={1}, out={2})", instruction.Instruction.Operands[2],
                                        instruction.Instruction.Operands[0], instruction.Instruction.Operands[1]));
     }
     else
     {
         writer.WriteLine(string.Format("{0}", instruction.Instruction.GetInstructionText()));
     }
 }
        private void WriteInstruction(TextWriter writer, HLInstruction instruction, string indent)
        {
            //writer.Write(string.Format("{0}{1:x}: ", indent, instruction.Instruction.Offset));
            
            if (instruction.BranchFunction != null)
            {
                writer.Write(indent);
                writer.WriteLine(string.Format(".call {0}", instruction.BranchFunction.Name));
            }
            else if (instruction.ExitFunction)
            {

                Function parentFunction = instruction.ParentCodePath.ParentFunction;
                if (instruction.ExitFunction && instruction == parentFunction.MainCodePath.EndInstruction)
                {
                    // Don't write the default return unless we're somewhere in the middle!
                }
                else
                {
                    writer.Write(indent);
                    writer.WriteLine(".return");
                }
            }
            else if (instruction.Instruction is InstructionNative)
            {
                writer.Write(indent);
                writer.WriteLine(string.Format(".native {1} // in={2}, out={3}", instruction.Instruction.OpCode,
                                               instruction.Instruction.Operands[2], instruction.Instruction.Operands[0],
                                               instruction.Instruction.Operands[1]));
            }
            else if (instruction.UnconditionalBranch || instruction.Instruction.OpCode == OpCode.Jump)
            {
                //writer.WriteLine();
            }
            else
            {
                writer.Write(indent);
                writer.WriteLine(string.Format("{0}", instruction.Instruction.GetInstructionText()));
            }
        }
Example #9
0
        /// <summary>
        /// Extracts a sequence of instructions into a new sub codepath
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="parentPath"></param>
        /// <param name="parentExitInstruction"></param>
        /// <param name="startInstruction">inclusive</param>
        /// <param name="endInstruction">exclusive (this is where our codepath returns to)</param>
        /// <returns></returns>
        private static CodePath ExtractPath(string identifier, CodePath parentPath, HLInstruction parentExitInstruction, HLInstruction startInstruction,
                                            HLInstruction endInstruction)
        {
            CodePath toPath = CreateCodePath(identifier, startInstruction.Instruction.Offset, parentPath);

            toPath.ParentCodePath        = parentPath;
            toPath.ParentExitInstruction = parentExitInstruction;

            HLInstruction hlInstruction = startInstruction;

            while (true)
            {
                parentPath.InstructionMap.Remove(hlInstruction.Instruction.Offset);
                hlInstruction.ParentCodePath = toPath;
                toPath.InstructionMap.Add(hlInstruction.Instruction.Offset, hlInstruction);

                if (hlInstruction.NextInstruction == null || hlInstruction.NextInstruction == endInstruction)
                {
                    hlInstruction.NextInstruction = null;
                    break;
                }

                hlInstruction = hlInstruction.NextInstruction;
            }

            if (startInstruction.PreviousInstruction != null)
            {
                startInstruction.PreviousInstruction.NextInstruction = endInstruction;
            }
            else
            {
                parentPath.StartInstruction = endInstruction;
                if (endInstruction != null)
                {
                    parentPath.StartOffset = endInstruction.Instruction.Offset;
                }
            }

            if (endInstruction != null)
            {
                endInstruction.PreviousInstruction = startInstruction.PreviousInstruction;
            }
            if (endInstruction == null)
            {
                parentPath.EndInstruction = startInstruction.PreviousInstruction;
                if (parentPath.EndInstruction != null)
                {
                    parentPath.EndOffset = parentPath.EndInstruction.Instruction.Offset +
                                           parentPath.EndInstruction.Instruction.InstructionLength;
                }
                else
                {
                    parentPath.EndOffset = parentPath.StartOffset;
                }
            }

            startInstruction.PreviousInstruction = null;

            toPath.StartInstruction = startInstruction;
            toPath.EndInstruction   = hlInstruction;

            toPath.EndOffset = hlInstruction.Instruction.Offset + hlInstruction.Instruction.InstructionLength;

            if (endInstruction != null && parentPath == endInstruction.ParentCodePath)
            {
                toPath.ParentEntryInstruction = endInstruction;
            }
            else
            {
                toPath.ParentEntryInstruction = null;
            }

            return(toPath);
        }
        private void AnalyzeSwitchBranch(HLInstruction branchInstruction)
        {
            var sw = branchInstruction.Instruction as InstructionSwitch;

            CodePath parentPath = branchInstruction.ParentCodePath;

            var swMap = new Dictionary<int, CodePath>();
            bool allWereReturns = true;

            HLInstruction switchExitInstruction = branchInstruction.NextInstruction.NextInstruction;

            foreach (var item in sw.SwitchTable)
            {
                if (swMap.ContainsKey(item.Value))
                {
                    // Deal with multiple values leading to the same code path
                    branchInstruction.BranchCodesPaths.Add(item.Key, swMap[item.Value]);
                }
                else
                {
                    CodePath branchCodePath = CreateCodePath("sw_case_" + item.Key, item.Value, parentPath);
                    branchCodePath.ParentExitInstruction = branchInstruction;

                    branchInstruction.BranchCodesPaths.Add(item.Key, branchCodePath);
                    swMap.Add(item.Value, branchCodePath);

                    AnalyzeCodePath(branchCodePath);

                    if (branchCodePath.ParentEntryInstruction != null)
                    {
                        allWereReturns = false;
                        switchExitInstruction = branchCodePath.ParentEntryInstruction;
                    }
                }
            }

            if (allWereReturns)
            {
                switchExitInstruction = null;
            }

            if (switchExitInstruction != branchInstruction.NextInstruction.NextInstruction)
            {
                // Crappy... got a default case statement that we need to extract

                CodePath branchDefaultCodePath = ExtractPath("sw_case_default", parentPath, branchInstruction, branchInstruction.NextInstruction, switchExitInstruction);

                branchInstruction.BranchCodesPaths.Add(new object(), branchDefaultCodePath);
            }
        }
 private void Annotate(TextWriter writer, string indent, HLInstruction instruction)
 {
     if (_annotate)
     {
         writer.WriteLine(string.Format("{0}// {1}", indent, instruction.Instruction));
     }
 }
 private void WriteInstruction(TextWriter writer, HLInstruction instruction, string indent)
 {
     if (instruction.ProcessedStackValue != null)
     {
         if (instruction.ProcessedStackValue is ProcessedStackValueGroup)
         {
             var group = instruction.ProcessedStackValue as ProcessedStackValueGroup;
             foreach (StackValue value in group.Values)
             {
                 writer.WriteLine(string.Format("{0}{1};", indent, value));
             }
         }
         else
         {
             Function parentFunction = instruction.ParentCodePath.ParentFunction;
             if (parentFunction.ReturnCount == 0 && 
                 instruction.ExitFunction && 
                 instruction == parentFunction.MainCodePath.EndInstruction)
             {
                 // Don't write the default return unless there's a return value!
                 //writer.WriteLine(string.Format("{0}// {1};", indent, instruction.ProcessedStackValue));
             }
             else
             {
                 writer.WriteLine(string.Format("{0}{1};", indent, instruction.ProcessedStackValue));
             }
         }
     }
 }
Example #13
0
        private void AnalyzeCodePath(Stack <StackValue> stack, CodePath path, ref int tempVarIndex)
        {
            HLInstruction instruction = path.GetFirstInstruction();

            while (instruction != null)
            {
                try
                {
                    if (instruction.BranchFunction != null)
                    {
                        if (!instruction.Instruction.HasStackUsageInfo)
                        {
                            instruction.Instruction.StackIn           = instruction.BranchFunction.ParameterCount;
                            instruction.Instruction.StackOut          = instruction.BranchFunction.ReturnCount;
                            instruction.Instruction.StackLeftOver     = 0;
                            instruction.Instruction.HasStackUsageInfo = true;
                        }
                    }

                    if (instruction.UnconditionalBranch)
                    {
                        // One should not even occur
                        //Debug.Assert(false);
                    }
                    else if (instruction.ExitFunction)
                    {
                        var value = new StackValueOperation(StackValueOperationType.Return);

                        if (path.ParentFunction.ReturnCount > 0)
                        {
                            for (int i = 0; i < path.ParentFunction.ReturnCount; i++)
                            {
                                value.Operands.Add(stack.Pop());
                            }
                        }

                        instruction.ProcessedStackValue = value;
                    }
                    else if (instruction.IsConditionalBranch || instruction.IsSwitchBranch)
                    {
                        instruction.ProcessedStackValue = stack.Pop();
                    }
                    else
                    {
                        bool processDefault = false;

                        StackValueOperation   operationValue = null;
                        StackValue            tempAnyValue;
                        StackValueOperation   tempOpValue;
                        StackValueLiteral     tempLiteralValue;
                        StackValuePointerBase tempPointerValue;

                        OpCode opCode = instruction.Instruction.OpCode;
                        switch (opCode)
                        {
                        case OpCode.AddVec:
                            VectorOperation(StackValueOperationType.Add, stack);
                            break;

                        case OpCode.SubVec:
                            VectorOperation(StackValueOperationType.Sub, stack);
                            break;

                        case OpCode.MulVec:
                            VectorOperation(StackValueOperationType.Mul, stack);
                            break;

                        case OpCode.DivVec:
                            VectorOperation(StackValueOperationType.Div, stack);
                            break;

                        case OpCode.NegVec:
                            VectorOperation(StackValueOperationType.Neg, stack);
                            break;

                        case OpCode.VecFromF:
                            VectorOperation(StackValueOperationType.FromF, stack);
                            break;

                        case OpCode.PushS:
                            stack.Push(new StackValueLiteral((short)instruction.Instruction.Operands[0]));
                            break;

                        case OpCode.Push:
                            stack.Push(new StackValueLiteral((int)(uint)instruction.Instruction.Operands[0]));
                            break;

                        case OpCode.PushF:
                            stack.Push(new StackValueLiteral((float)instruction.Instruction.Operands[0]));
                            break;

                        case OpCode.PushString:
                            stack.Push(new StackValueLiteral((string)instruction.Instruction.Operands[0]));
                            break;

                        case OpCode.Dup:
                            stack.Push(stack.Peek());
                            break;

                        case OpCode.Pop:
                            tempOpValue = stack.Peek() as StackValueOperation;
                            if (tempOpValue != null && tempOpValue.OperationType == StackValueOperationType.Call)
                            {
                                operationValue = new StackValueOperation(StackValueOperationType.Pop);
                                processDefault = true;
                            }
                            break;

                        case OpCode.CallNative:
                            operationValue = new StackValueOperation(instruction.Instruction.Operands[2].ToString());
                            processDefault = true;
                            break;

                        case OpCode.Call:
                            operationValue = new StackValueOperation(instruction.BranchFunction.Name);
                            processDefault = true;
                            break;

                        case OpCode.RefGet:
                            stack.Push(new StackValueDeref(stack.Pop()));
                            break;

                        case OpCode.RefSet:
                            instruction.ProcessedStackValue = new StackValueAssign(PopPointer(stack), stack.Pop());
                            break;

                        case OpCode.RefPeekSet:
                            tempAnyValue = stack.Pop();     // value!
                            instruction.ProcessedStackValue = new StackValueAssign(PeekPointer(stack), tempAnyValue);
                            break;

                        case OpCode.ArrayExplode:
                            // This is used to either pass a structure to a native/function call
                            // or to explode the variables onto the stack to do a "shallow-copy"

                            tempPointerValue = PopPointer(stack);
                            tempLiteralValue = stack.Pop() as StackValueLiteral;
                            Debug.Assert(tempLiteralValue != null &&
                                         tempLiteralValue.ValueType == StackValueType.Integer);

                            var explodeCount = (int)tempLiteralValue.Value;
                            for (int i = 0; i < explodeCount; i++)
                            {
                                stack.Push(new StackValueDeref(new StackValuePointerIndex(tempPointerValue, i)));
                            }

                            break;

                        case OpCode.ArrayImplode:
                            // The only case this is ever used is for a shallow copy!

                            tempPointerValue = PopPointer(stack);
                            tempLiteralValue = stack.Pop() as StackValueLiteral;
                            Debug.Assert(tempLiteralValue != null &&
                                         tempLiteralValue.ValueType == StackValueType.Integer);

                            var tempStack    = new Stack <StackValue>();
                            var implodeCount = (int)tempLiteralValue.Value;
                            for (int i = implodeCount - 1; i >= 0; i--)
                            {
                                tempStack.Push(
                                    new StackValueAssign(new StackValuePointerIndex(tempPointerValue, i),
                                                         stack.Pop()));
                            }

                            var stackValueGroup = new ProcessedStackValueGroup();

                            stackValueGroup.Values.AddRange(tempStack.ToArray());
                            instruction.ProcessedStackValue = stackValueGroup;

                            break;

                        case OpCode.Var0:
                        case OpCode.Var1:
                        case OpCode.Var2:
                        case OpCode.Var3:
                        case OpCode.Var4:
                        case OpCode.Var5:
                        case OpCode.Var6:
                        case OpCode.Var7:
                            stack.Push(new StackValuePointerVar(StackValuePointerType.Stack,
                                                                (opCode - OpCode.Var0)));
                            break;

                        case OpCode.Var:
                            tempLiteralValue = stack.Pop() as StackValueLiteral;
                            Debug.Assert(tempLiteralValue != null &&
                                         tempLiteralValue.ValueType == StackValueType.Integer);

                            stack.Push(new StackValuePointerVar(StackValuePointerType.Stack,
                                                                (int)tempLiteralValue.Value));
                            break;

                        case OpCode.LocalVar:
                            tempLiteralValue = stack.Pop() as StackValueLiteral;
                            Debug.Assert(tempLiteralValue != null &&
                                         tempLiteralValue.ValueType == StackValueType.Integer);

                            stack.Push(new StackValuePointerVar(StackValuePointerType.Local,
                                                                (int)tempLiteralValue.Value));
                            break;

                        case OpCode.GlobalVar:
                            tempLiteralValue = stack.Pop() as StackValueLiteral;
                            Debug.Assert(tempLiteralValue != null &&
                                         tempLiteralValue.ValueType == StackValueType.Integer);

                            stack.Push(new StackValuePointerVar(StackValuePointerType.Global,
                                                                (int)tempLiteralValue.Value));
                            break;

                        case OpCode.ArrayRef:
                            tempPointerValue = PopPointer(stack);
                            tempLiteralValue = stack.Pop() as StackValueLiteral;
                            tempAnyValue     = stack.Pop();
                            Debug.Assert(tempPointerValue != null);
                            Debug.Assert(tempLiteralValue != null &&
                                         tempLiteralValue.ValueType == StackValueType.Integer);

                            stack.Push(new StackValuePointerArray(tempPointerValue, tempAnyValue,
                                                                  (int)tempLiteralValue.Value));
                            break;

                        case OpCode.NullObj:
                            stack.Push(new StackValuePointerVar(StackValuePointerType.Null));
                            break;

                        case OpCode.Add:
                            // Special case for pointer add
                            tempAnyValue     = stack.Pop();
                            tempPointerValue = stack.Peek() as StackValuePointerBase;

                            if (tempPointerValue != null)
                            {
                                stack.Pop();     // tempPointerValue

                                tempLiteralValue = tempAnyValue as StackValueLiteral;
                                Debug.Assert(tempLiteralValue != null && (int)tempLiteralValue.Value % 4 == 0);

                                stack.Push(new StackValuePointerIndex(tempPointerValue,
                                                                      (int)tempLiteralValue.Value / 4));
                            }
                            else
                            {
                                stack.Push(tempAnyValue);
                                operationValue = new StackValueOperation(opCode);
                                processDefault = true;
                            }
                            break;

                        case OpCode.StrCat:
                        case OpCode.StrCatI:
                        case OpCode.StrCpy:
                        case OpCode.IntToStr:
                            operationValue = new StackValueStringOperation(opCode, (byte)instruction.Instruction.Operands[0]);
                            processDefault = true;
                            break;

                        case OpCode.StrVarCpy:
                            tempPointerValue = PopPointer(stack);

                            tempLiteralValue = stack.Pop() as StackValueLiteral;

                            Debug.Assert(tempLiteralValue != null &&
                                         tempLiteralValue.ValueType == StackValueType.Integer);

                            var targetSize = (uint)(int)tempLiteralValue.Value;

                            tempLiteralValue = stack.Pop() as StackValueLiteral;

                            Debug.Assert(tempLiteralValue != null &&
                                         tempLiteralValue.ValueType == StackValueType.Integer);

                            var sourceSize = (uint)(int)tempLiteralValue.Value;

                            var popSize = sourceSize;

                            tempAnyValue = PopPointer(stack);

                            // Pop till the last one
                            for (var i = 1; i < popSize; i++)
                            {
                                tempAnyValue = PopPointer(stack);
                            }

                            operationValue = new StackValueStringOperation(opCode, targetSize, sourceSize);
                            operationValue.Operands.Add(new StackValueRef(tempAnyValue)); // 0 = source
                            operationValue.Operands.Add(tempPointerValue);                // 1 = target

                            instruction.ProcessedStackValue = operationValue;

                            break;

                        case OpCode.RefProtect:
                            tempLiteralValue = stack.Pop() as StackValueLiteral;

                            Debug.Assert(tempLiteralValue != null &&
                                         tempLiteralValue.ValueType == StackValueType.Integer);

                            var protectMode = (int)tempLiteralValue.Value;

                            Debug.Assert(protectMode == 1 || protectMode == 2 || protectMode == 5 || protectMode == 6);

                            tempLiteralValue = stack.Pop() as StackValueLiteral;

                            Debug.Assert(tempLiteralValue != null &&
                                         tempLiteralValue.ValueType == StackValueType.Integer);

                            var protectCount = (int)tempLiteralValue.Value;

                            //Debug.Assert(protectCount == 1);

                            tempPointerValue = PopPointer(stack);

                            operationValue = new StackValueOperation(StackValueOperationType.RefProtect);
                            operationValue.Operands.Add(tempPointerValue);
                            operationValue.Operands.Add(tempLiteralValue);

                            if ((protectMode & 1) != 0)
                            {
                                stack.Push(operationValue);
                            }

                            break;

                        default:
                            if (instruction.Instruction is InstructionPush)
                            {
                                // PushD special case
                                stack.Push(new StackValueLiteral((int)instruction.Instruction.Operands[0]));
                            }
                            else
                            {
                                operationValue = new StackValueOperation(opCode);
                                processDefault = true;
                            }
                            break;
                        }

                        if (processDefault)
                        {
                            Debug.Assert(instruction.Instruction.HasStackUsageInfo);

                            var stackValues = new Stack <StackValue>();
                            for (int i = 0; i < instruction.Instruction.StackIn; i++)
                            {
                                StackValue stackItem = stack.Pop();
                                stackValues.Push(stackItem);
                            }

                            operationValue.Operands.AddRange(stackValues);

                            if (instruction.Instruction.StackLeftOver > 0)
                            {
                                for (int i = 0; i < instruction.Instruction.StackLeftOver; i++)
                                {
                                    stackValues.Push(stackValues.Pop());
                                }
                            }

                            if (instruction.Instruction.StackOut > 0)
                            {
                                if (instruction.Instruction.StackOut > 1)
                                {
                                    var multiAssign = new StackValueAssignMulti(operationValue);
                                    for (int i = 0; i < instruction.Instruction.StackOut; i++)
                                    {
                                        tempPointerValue = new StackValuePointerVar(StackValuePointerType.Temporary,
                                                                                    tempVarIndex + i);
                                        multiAssign.AssignPointers.Add(tempPointerValue);
                                        stack.Push(new StackValueDeref(tempPointerValue));
                                    }
                                    tempVarIndex += instruction.Instruction.StackOut;
                                    instruction.ProcessedStackValue = multiAssign;
                                }
                                else
                                {
                                    stack.Push(operationValue);
                                }
                            }
                            else
                            {
                                instruction.ProcessedStackValue = operationValue;
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    throw new Exception(
                              "Error while decompiling instruction : " + instruction.Instruction + "\n", e);
                }

                instruction = instruction.GetNextInstruction();
            }
        }
        private void AnalyzeCodePath(CodePath path)
        {
            HLInstruction previousInstruction = null;
            var branchInstructions = new List<HLInstruction>();

            int offset = path.StartOffset;

            while (true)
            {
                if (path.ParentCodePath != null) // non main
                {
                    CodePath parentPath = path.ParentFunction.DetermineCodePathFromOffset(offset);
                    if (parentPath != null)
                    {
                        if (!path.IsInstructionOffsetInPathTree(offset))
                        {
                            // Hmm.. so the target offset is not the current tree... which is bad
                            // This can only mean a bad jump assumption before. We must somehow extract
                            // The instructions from this existing path and merge it with our parent

                            HLInstruction startInstruction = parentPath.InstructionMap[offset];
                            CodePath newPath = ExtractPath(path.ParentCodePath.Name + "_temp", parentPath,
                                                           startInstruction.PreviousInstruction, startInstruction, null);

                            // Now we can merge it with this path's parent

                            CodePath targetCodePath = FindCommonPathAncestor(path, parentPath);
                            MergePath(targetCodePath, newPath);

                            if (parentPath.ParentCodePath == targetCodePath)
                            {
                                parentPath.ParentEntryInstruction = startInstruction;
                            }
                            else
                            {
                                parentPath.ParentEntryInstruction = null;
                            }

                            // Set some variables so we know how to break out of here.

                            parentPath = targetCodePath;
                        }

                        // Okay, break out of there buddy!

                        if (parentPath == path.ParentCodePath)
                        {
                            path.ParentEntryInstruction = path.ParentCodePath.GetInstruction(offset);
                        }
                        else
                        {
                            // null = we reached the end of the code path for the parent as well!
                            path.ParentEntryInstruction = null;
                        }
                        break;
                    }

                }

                Instruction instruction = Decoder.Decode(offset);
                offset += instruction.InstructionLength;

                var hlInstruction = new HLInstruction(instruction);

                if (instruction is InstructionFnEnd)
                {
                    if (path.ParentCodePath == null)
                    {
                        // This means this is in the function root

                        path.ParentFunction.EndOffset = instruction.Offset + instruction.InstructionLength;
                        path.ParentFunction.ReturnCount = (instruction as InstructionFnEnd).ReturnCount;

                        hlInstruction.ExitFunction = true;
                    }
                    else
                    {
                        if (instruction.Offset == path.ParentFunction.EndOffset)
                        {
                            // Non root code path reached end of function
                            path.ParentEntryInstruction = null;

                            hlInstruction.ExitFunction = true;
                        }
                        else
                        {
                            // Hmm, this must be a exit function invocation
                            // We'll add it, and exit out of the loop later in the code

                            hlInstruction.ExitFunction = true;
                        }
                    }
                }
                else if (instruction is InstructionBranch)
                {
                    if (instruction.OpCode == OpCode.Call)
                    {
                        hlInstruction.BranchFunction = FunctionTargets[instruction.BranchOffset];
                    }
                    else if (instruction.OpCode == OpCode.Jump)
                    {
                        if (path.ParentCodePath != null && instruction.BranchOffset < instruction.Offset &&
                            path.ParentCodePath.GetInstruction(instruction.BranchOffset) != null)
                        {
                            // Loop!
                            hlInstruction.BranchLoopInstruction =
                                path.ParentCodePath.GetInstruction(instruction.BranchOffset);
                            hlInstruction.BranchLoopInstruction.LoopCodePath = path;

                            // The next instruction should break us out of this codepath...

                            hlInstruction.UnconditionalBranch = true;
                        }
                        else
                        {
                            // Okay, we'll just be naive for now and follow the jump
                            // It is *possible* that this jump might be for an "else" or "case default" block, in which case, we are screwed.
                            // But we will deal with this while we deal with branches
                            hlInstruction.UnconditionalBranch = true;
                            offset = instruction.BranchOffset;
                        }
                    }
                    else
                    {
                        // We got a conditional branch instruction
                        hlInstruction.IsConditionalBranch = true;
                        branchInstructions.Add(hlInstruction);
                        offset = instruction.BranchOffset;
                    }
                }
                else if (instruction is InstructionSwitch)
                {
                    hlInstruction.IsSwitchBranch = true;
                    branchInstructions.Add(hlInstruction);
                }

                hlInstruction.PreviousInstruction = previousInstruction;
                if (previousInstruction == null)
                {
                    path.StartInstruction = hlInstruction;
                }
                else
                {
                    previousInstruction.NextInstruction = hlInstruction;
                }
                previousInstruction = hlInstruction;

                hlInstruction.ParentCodePath = path;
                path.InstructionMap.Add(instruction.Offset, hlInstruction);

                if (hlInstruction.ExitFunction)
                {
                    break; // out of while loop
                }
            }

            path.EndInstruction = previousInstruction;
            path.EndOffset = offset;

            AnalyzeBranchInstructions(branchInstructions);
        }
        private void AnalyzeConditionalBranch(HLInstruction branchInstruction)
        {
            int branchOffset = branchInstruction.Instruction.Offset +
                   branchInstruction.Instruction.InstructionLength;

            CodePath parentPath = branchInstruction.ParentCodePath;

            CodePath branchCodePath = CreateCodePath("if", branchOffset, parentPath);
            branchCodePath.ParentExitInstruction = branchInstruction;

            bool condition = branchInstruction.Instruction.OpCode == OpCode.JumpFalse ? true : false;
            branchInstruction.BranchCodesPaths.Add(condition, branchCodePath);

            branchInstruction.DefaultConditional = condition;

            AnalyzeCodePath(branchCodePath);

            if (branchInstruction.NextInstruction != null &&
                branchCodePath.ParentEntryTargetInstruction != branchInstruction.NextInstruction)
            {
                // Well, shit.. we got an else block.

                CodePath branchElseCodePath = ExtractPath("if_else", branchInstruction.ParentCodePath, branchInstruction,
                                                          branchInstruction.NextInstruction,
                                                          branchCodePath.ParentEntryInstruction);

                branchInstruction.BranchCodesPaths.Add(!condition, branchElseCodePath);
            }

        }
Example #16
0
        private void AnalyzeCodePath(CodePath path)
        {
            HLInstruction previousInstruction = null;
            var           branchInstructions  = new List <HLInstruction>();

            int offset = path.StartOffset;

            while (true)
            {
                if (path.ParentCodePath != null) // non main
                {
                    CodePath parentPath = path.ParentFunction.DetermineCodePathFromOffset(offset);
                    if (parentPath != null)
                    {
                        if (!path.IsInstructionOffsetInPathTree(offset))
                        {
                            // Hmm.. so the target offset is not the current tree... which is bad
                            // This can only mean a bad jump assumption before. We must somehow extract
                            // The instructions from this existing path and merge it with our parent

                            HLInstruction startInstruction = parentPath.InstructionMap[offset];
                            CodePath      newPath          = ExtractPath(path.ParentCodePath.Name + "_temp", parentPath,
                                                                         startInstruction.PreviousInstruction, startInstruction, null);

                            // Now we can merge it with this path's parent

                            CodePath targetCodePath = FindCommonPathAncestor(path, parentPath);
                            MergePath(targetCodePath, newPath);

                            if (parentPath.ParentCodePath == targetCodePath)
                            {
                                parentPath.ParentEntryInstruction = startInstruction;
                            }
                            else
                            {
                                parentPath.ParentEntryInstruction = null;
                            }

                            // Set some variables so we know how to break out of here.

                            parentPath = targetCodePath;
                        }

                        // Okay, break out of there buddy!

                        if (parentPath == path.ParentCodePath)
                        {
                            path.ParentEntryInstruction = path.ParentCodePath.GetInstruction(offset);
                        }
                        else
                        {
                            // null = we reached the end of the code path for the parent as well!
                            path.ParentEntryInstruction = null;
                        }
                        break;
                    }
                }

                Instruction instruction = Decoder.Decode(offset);
                offset += instruction.InstructionLength;

                var hlInstruction = new HLInstruction(instruction);

                if (instruction is InstructionFnEnd)
                {
                    if (path.ParentCodePath == null)
                    {
                        // This means this is in the function root

                        path.ParentFunction.EndOffset   = instruction.Offset + instruction.InstructionLength;
                        path.ParentFunction.ReturnCount = (instruction as InstructionFnEnd).ReturnCount;

                        hlInstruction.ExitFunction = true;
                    }
                    else
                    {
                        if (instruction.Offset == path.ParentFunction.EndOffset)
                        {
                            // Non root code path reached end of function
                            path.ParentEntryInstruction = null;

                            hlInstruction.ExitFunction = true;
                        }
                        else
                        {
                            // Hmm, this must be a exit function invocation
                            // We'll add it, and exit out of the loop later in the code

                            hlInstruction.ExitFunction = true;
                        }
                    }
                }
                else if (instruction is InstructionBranch)
                {
                    if (instruction.OpCode == OpCode.Call)
                    {
                        hlInstruction.BranchFunction = FunctionTargets[instruction.BranchOffset];
                    }
                    else if (instruction.OpCode == OpCode.Jump)
                    {
                        if (path.ParentCodePath != null && instruction.BranchOffset < instruction.Offset &&
                            path.ParentCodePath.GetInstruction(instruction.BranchOffset) != null)
                        {
                            // Loop!
                            hlInstruction.BranchLoopInstruction =
                                path.ParentCodePath.GetInstruction(instruction.BranchOffset);
                            hlInstruction.BranchLoopInstruction.LoopCodePath = path;

                            // The next instruction should break us out of this codepath...

                            hlInstruction.UnconditionalBranch = true;
                        }
                        else
                        {
                            // Okay, we'll just be naive for now and follow the jump
                            // It is *possible* that this jump might be for an "else" or "case default" block, in which case, we are screwed.
                            // But we will deal with this while we deal with branches
                            hlInstruction.UnconditionalBranch = true;
                            offset = instruction.BranchOffset;
                        }
                    }
                    else
                    {
                        // We got a conditional branch instruction
                        hlInstruction.IsConditionalBranch = true;
                        branchInstructions.Add(hlInstruction);
                        offset = instruction.BranchOffset;
                    }
                }
                else if (instruction is InstructionSwitch)
                {
                    hlInstruction.IsSwitchBranch = true;
                    branchInstructions.Add(hlInstruction);
                }

                hlInstruction.PreviousInstruction = previousInstruction;
                if (previousInstruction == null)
                {
                    path.StartInstruction = hlInstruction;
                }
                else
                {
                    previousInstruction.NextInstruction = hlInstruction;
                }
                previousInstruction = hlInstruction;

                hlInstruction.ParentCodePath = path;
                path.InstructionMap.Add(instruction.Offset, hlInstruction);

                if (hlInstruction.ExitFunction)
                {
                    break; // out of while loop
                }
            }

            path.EndInstruction = previousInstruction;
            path.EndOffset      = offset;

            AnalyzeBranchInstructions(branchInstructions);
        }
        /// <summary>
        /// Extracts a sequence of instructions into a new sub codepath
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="parentPath"></param>
        /// <param name="parentExitInstruction"></param>
        /// <param name="startInstruction">inclusive</param>
        /// <param name="endInstruction">exclusive (this is where our codepath returns to)</param>
        /// <returns></returns>
        private static CodePath ExtractPath(string identifier, CodePath parentPath, HLInstruction parentExitInstruction, HLInstruction startInstruction,
                                     HLInstruction endInstruction)
        {
            CodePath toPath = CreateCodePath(identifier, startInstruction.Instruction.Offset, parentPath);
            toPath.ParentCodePath = parentPath;
            toPath.ParentExitInstruction = parentExitInstruction;

            HLInstruction hlInstruction = startInstruction;

            while (true)
            {
                parentPath.InstructionMap.Remove(hlInstruction.Instruction.Offset);
                hlInstruction.ParentCodePath = toPath;
                toPath.InstructionMap.Add(hlInstruction.Instruction.Offset, hlInstruction);

                if (hlInstruction.NextInstruction == null || hlInstruction.NextInstruction == endInstruction)
                {
                    hlInstruction.NextInstruction = null;
                    break;
                }

                hlInstruction = hlInstruction.NextInstruction;
            }

            if (startInstruction.PreviousInstruction != null)
            {
                startInstruction.PreviousInstruction.NextInstruction = endInstruction;
            }
            else
            {
                parentPath.StartInstruction = endInstruction;
                if (endInstruction != null)
                {
                    parentPath.StartOffset = endInstruction.Instruction.Offset;
                }
            }

            if (endInstruction != null)
            {
                endInstruction.PreviousInstruction = startInstruction.PreviousInstruction;
            }
            if (endInstruction == null)
            {
                parentPath.EndInstruction = startInstruction.PreviousInstruction;
                if (parentPath.EndInstruction != null)
                {
                    parentPath.EndOffset = parentPath.EndInstruction.Instruction.Offset +
                                           parentPath.EndInstruction.Instruction.InstructionLength;
                }
                else
                {
                    parentPath.EndOffset = parentPath.StartOffset;
                }
            }

            startInstruction.PreviousInstruction = null;

            toPath.StartInstruction = startInstruction;
            toPath.EndInstruction = hlInstruction;

            toPath.EndOffset = hlInstruction.Instruction.Offset + hlInstruction.Instruction.InstructionLength;

            if (endInstruction != null && parentPath == endInstruction.ParentCodePath)
            {
                toPath.ParentEntryInstruction = endInstruction;
            }
            else
            {
                toPath.ParentEntryInstruction = null;
            }

            return toPath;
        }