예제 #1
0
        private IRInstruction GetTarget(IRBranchInstruction pBranchInstruction)
        {
            IRInstruction targetInstruction = mILOffsetLookup[pBranchInstruction.TargetILOffset];

            if (targetInstruction.Opcode == IROpcode.Branch)
            {
                IRBranchInstruction targetBranchInstruction = (IRBranchInstruction)targetInstruction;
                if (targetBranchInstruction.BranchCondition == IRBranchCondition.Always)
                {
                    targetInstruction = mILOffsetLookup[targetBranchInstruction.TargetILOffset];
                    targetInstruction = GetTarget(targetBranchInstruction);
                }
            }
            return(targetInstruction);
        }
예제 #2
0
        public void FixTargetInstructions()
        {
            foreach (IRInstruction instruction in mInstructions)
            {
                switch (instruction.Opcode)
                {
                case IROpcode.Branch:
                {
                    IRBranchInstruction branchInstruction = (IRBranchInstruction)instruction;
                    branchInstruction.TargetIRInstruction = GetTarget(branchInstruction);
                    if (branchInstruction.TargetIRInstruction == null)
                    {
                        throw new NullReferenceException();
                    }
                    break;
                }

                case IROpcode.Switch:
                {
                    IRSwitchInstruction switchInstruction = (IRSwitchInstruction)instruction;
                    switchInstruction.TargetIRInstructions = new IRInstruction[switchInstruction.TargetILOffsets.Length];
                    for (int index = 0; index < switchInstruction.TargetILOffsets.Length; ++index)
                    {
                        switchInstruction.TargetIRInstructions[index] = mILOffsetLookup[switchInstruction.TargetILOffsets[index]];
                        if (switchInstruction.TargetIRInstructions[index] == null)
                        {
                            throw new NullReferenceException();
                        }
                    }
                    break;
                }

                case IROpcode.Leave:
                {
                    IRLeaveInstruction leaveInstruction = (IRLeaveInstruction)instruction;
                    leaveInstruction.TargetIRInstruction = mILOffsetLookup[leaveInstruction.TargetILOffset];
                    if (leaveInstruction.TargetIRInstruction == null)
                    {
                        throw new NullReferenceException();
                    }
                    break;
                }

                default: break;
                }
            }
        }
예제 #3
0
        public static IRControlFlowGraph Build(IRMethod pMethod)
        {
            if (pMethod.Instructions.Count == 0)
            {
                return(null);
            }

            HashSet <IRInstruction> sourceNodeBreaks      = new HashSet <IRInstruction>();
            HashSet <IRInstruction> destinationNodeBreaks = new HashSet <IRInstruction>();

            foreach (IRInstruction instruction in pMethod.Instructions)
            {
                switch (instruction.Opcode)
                {
                case IROpcode.Branch:
                {
                    IRBranchInstruction branchInstruction = (IRBranchInstruction)instruction;
                    if (!sourceNodeBreaks.Contains(instruction))
                    {
                        sourceNodeBreaks.Add(instruction);
                    }
                    if (!destinationNodeBreaks.Contains(branchInstruction.TargetIRInstruction))
                    {
                        destinationNodeBreaks.Add(branchInstruction.TargetIRInstruction);
                    }
                    break;
                }

                case IROpcode.Switch:
                {
                    IRSwitchInstruction switchInstruction = (IRSwitchInstruction)instruction;
                    if (!sourceNodeBreaks.Contains(instruction))
                    {
                        sourceNodeBreaks.Add(instruction);
                    }
                    foreach (IRInstruction targetIRInstruction in switchInstruction.TargetIRInstructions)
                    {
                        if (!destinationNodeBreaks.Contains(targetIRInstruction))
                        {
                            destinationNodeBreaks.Add(targetIRInstruction);
                        }
                    }
                    break;
                }

                case IROpcode.Leave:
                {
                    IRLeaveInstruction leaveInstruction = (IRLeaveInstruction)instruction;
                    if (!sourceNodeBreaks.Contains(instruction))
                    {
                        sourceNodeBreaks.Add(instruction);
                    }
                    if (!destinationNodeBreaks.Contains(leaveInstruction.TargetIRInstruction))
                    {
                        destinationNodeBreaks.Add(leaveInstruction.TargetIRInstruction);
                    }
                    break;
                }

                default: break;
                }
            }

            IRControlFlowGraph cfg = new IRControlFlowGraph();
            Node currentNode       = new Node(0);

            cfg.Nodes.Add(currentNode);
            foreach (IRInstruction instruction in pMethod.Instructions)
            {
                bool lastInstruction      = instruction == pMethod.Instructions[pMethod.Instructions.Count - 1];
                bool startFromSource      = sourceNodeBreaks.Contains(instruction);
                bool startFromDestination = destinationNodeBreaks.Contains(instruction);
                if (startFromSource && startFromDestination)
                {
                    if (currentNode.Instructions.Count > 0)
                    {
                        currentNode = new Node((uint)cfg.Nodes.Count);
                        cfg.Nodes.Add(currentNode);
                    }
                    currentNode.Instructions.Add(instruction);
                    currentNode = new Node((uint)cfg.Nodes.Count);
                    cfg.Nodes.Add(currentNode);
                }
                else if (startFromSource)
                {
                    currentNode.Instructions.Add(instruction);
                    currentNode = new Node((uint)cfg.Nodes.Count);
                    cfg.Nodes.Add(currentNode);
                }
                else if (startFromDestination)
                {
                    if (currentNode.Instructions.Count > 0)
                    {
                        currentNode = new Node((uint)cfg.Nodes.Count);
                        cfg.Nodes.Add(currentNode);
                    }
                    currentNode.Instructions.Add(instruction);
                }
                else
                {
                    currentNode.Instructions.Add(instruction);
                }
            }

            for (int nodeIndex = 0; nodeIndex < cfg.Nodes.Count; ++nodeIndex)
            {
                Node          node        = cfg.Nodes[nodeIndex];
                IRInstruction instruction = node.Instructions[node.Instructions.Count - 1];
                switch (instruction.Opcode)
                {
                case IROpcode.Branch:
                {
                    IRBranchInstruction branchInstruction = (IRBranchInstruction)instruction;
                    Node childNode = cfg.Nodes.Find(n => n.Instructions[0] == branchInstruction.TargetIRInstruction);
                    if (childNode == null)
                    {
                        throw new NullReferenceException();
                    }
                    if (branchInstruction.BranchCondition != IRBranchCondition.Always)
                    {
                        node.LinkTo(cfg.Nodes[nodeIndex + 1]);
                    }
                    node.LinkTo(childNode);
                    break;
                }

                case IROpcode.Switch:
                {
                    IRSwitchInstruction switchInstruction = (IRSwitchInstruction)instruction;
                    node.LinkTo(cfg.Nodes[nodeIndex + 1]);
                    foreach (IRInstruction targetInstruction in switchInstruction.TargetIRInstructions)
                    {
                        Node childNode = cfg.Nodes.Find(n => n.Instructions[0] == targetInstruction);
                        if (childNode == null)
                        {
                            throw new NullReferenceException();
                        }
                        node.LinkTo(childNode);
                    }
                    break;
                }

                case IROpcode.Leave:
                {
                    IRLeaveInstruction leaveInstruction = (IRLeaveInstruction)instruction;
                    Node childNode = cfg.Nodes.Find(n => n.Instructions[0] == leaveInstruction.TargetIRInstruction);
                    if (childNode == null)
                    {
                        throw new NullReferenceException();
                    }
                    node.LinkTo(childNode);
                    break;
                }

                case IROpcode.Throw:
                case IROpcode.Return: continue;

                default: node.LinkTo(cfg.Nodes[nodeIndex + 1]); break;
                }
            }
            return(cfg);
        }
예제 #4
0
        public IRInstruction this[int pIndex]
        {
            get
            {
                if (pIndex < 0)
                {
                    throw new IndexOutOfRangeException("An IRInstruction index cannot be less than 0!");
                }
                if (pIndex >= mInstructions.Count)
                {
                    throw new IndexOutOfRangeException("The requested IRInstruction doesn't exist!");
                }
                return(mInstructions[pIndex]);
            }
            set
            {
                if (pIndex < 0)
                {
                    throw new IndexOutOfRangeException("An IRInstruction index cannot be less than 0!");
                }
                if (pIndex >= mInstructions.Count)
                {
                    throw new IndexOutOfRangeException("The specified IRInstruction doesn't exist!");
                }
                if (mInstructions[pIndex] != value)
                {
                    if (!value.Resolved)
                    {
                        mResolvedCache = false;
                    }
                    IRInstruction oldInstruction = mInstructions[pIndex];
                    IRInstruction newInstruction = value;

                    mInstructions[pIndex] = value;
                    mILOffsetLookup[newInstruction.ILOffset] = newInstruction;
                    foreach (IRInstruction instruction in mInstructions)
                    {
                        switch (instruction.Opcode)
                        {
                        case IROpcode.Branch:
                        {
                            IRBranchInstruction branchInstruction = (IRBranchInstruction)instruction;
                            if (branchInstruction.TargetIRInstruction == oldInstruction)
                            {
                                branchInstruction.TargetIRInstruction = newInstruction;
                            }
                            break;
                        }

                        case IROpcode.Switch:
                        {
                            IRSwitchInstruction switchInstruction = (IRSwitchInstruction)instruction;
                            for (int index = 0; index < switchInstruction.TargetIRInstructions.Length; ++index)
                            {
                                if (switchInstruction.TargetIRInstructions[index] == oldInstruction)
                                {
                                    switchInstruction.TargetIRInstructions[index] = newInstruction;
                                }
                            }
                            break;
                        }

                        case IROpcode.Leave:
                        {
                            IRLeaveInstruction leaveInstruction = (IRLeaveInstruction)instruction;
                            if (leaveInstruction.TargetIRInstruction == oldInstruction)
                            {
                                leaveInstruction.TargetIRInstruction = newInstruction;
                            }
                            break;
                        }

                        default: break;
                        }
                    }
                }
            }
        }
예제 #5
0
        private void LinearizePath(MethodDefData pMethodDefData, IRInstruction pStartInstruction, Stack <IRStackObject> pStack, Queue <Tuple <IRInstruction, Stack <IRStackObject> > > pBranches)
        {
            int           stackReturn        = pStack.Count;
            IRInstruction currentInstruction = pStartInstruction;

            MethodDefData.MethodDefBodyData.MethodDefBodyExceptionData exceptionData = null;
            while (currentInstruction != null)
            {
                if (currentInstruction.Linearized && pStack.Count == stackReturn)
                {
                    break;
                }

                if ((exceptionData = Array.Find(pMethodDefData.Body.Exceptions, e => e.Flags == 0 && e.HandlerOffset == currentInstruction.ILOffset)) != null)
                {
                    IRType        exceptionType = Assembly.AppDomain.PresolveType(Assembly.File.ExpandMetadataToken(exceptionData.ClassTokenOrFilterOffset));
                    IRStackObject exceptionObj  = new IRStackObject();
                    exceptionObj.Type             = exceptionType;
                    exceptionObj.LinearizedTarget = new IRLinearizedLocation(IRLinearizedLocationType.Local);
                    exceptionObj.LinearizedTarget.Local.LocalIndex = currentInstruction.AddLinearizedLocal(pStack, exceptionType);
                    pStack.Push(exceptionObj);
                }

                currentInstruction.Linearize(pStack);
                currentInstruction.Linearized = true;
                switch (currentInstruction.Opcode)
                {
                case IROpcode.Branch:
                {
                    IRBranchInstruction branchInstruction = (IRBranchInstruction)currentInstruction;
                    if (branchInstruction.BranchCondition == IRBranchCondition.Always)
                    {
                        currentInstruction = branchInstruction.TargetIRInstruction;
                    }
                    else
                    {
                        pBranches.Enqueue(new Tuple <IRInstruction, Stack <IRStackObject> >(branchInstruction.TargetIRInstruction, pStack.Duplicate()));
                        currentInstruction = Instructions[currentInstruction.IRIndex + 1];
                    }
                    break;
                }

                case IROpcode.Switch:
                {
                    IRSwitchInstruction switchInstruction = (IRSwitchInstruction)currentInstruction;
                    foreach (IRInstruction targetInstruction in switchInstruction.TargetIRInstructions)
                    {
                        pBranches.Enqueue(new Tuple <IRInstruction, Stack <IRStackObject> >(targetInstruction, pStack.Duplicate()));
                    }
                    currentInstruction = Instructions[currentInstruction.IRIndex + 1];
                    break;
                }

                case IROpcode.Leave:
                {
                    IRLeaveInstruction leaveInstruction = (IRLeaveInstruction)currentInstruction;
                    currentInstruction = leaveInstruction.TargetIRInstruction;
                    break;
                }

                case IROpcode.Jump:
                case IROpcode.Throw:
                case IROpcode.Return: currentInstruction = null; break;

                default: currentInstruction = currentInstruction.IRIndex >= Instructions.Count ? null : Instructions[currentInstruction.IRIndex + 1]; break;
                }
            }
        }