Beispiel #1
0
 public void AddInstruction(uint pILOffset, IRInstruction pInstruction)
 {
     pInstruction.ILOffset     = (int)pILOffset;
     pInstruction.IRIndex      = (uint)Instructions.Count;
     pInstruction.ParentMethod = this;
     Instructions.Add(pInstruction);
 }
Beispiel #2
0
 public void AddInstruction(uint pILOffset, IRInstruction pInstruction)
 {
     pInstruction.ILOffset = (int)pILOffset;
     pInstruction.IRIndex = (uint)Instructions.Count;
     pInstruction.ParentMethod = this;
     Instructions.Add(pInstruction);
 }
Beispiel #3
0
 /// <summary>
 /// This does a shallow copy of all of the members of the
 /// abstract IRInstruction class to the specified instruction.
 /// </summary>
 /// <param name="i">The instruction to copy to.</param>
 /// <param name="newMethod">The method this instruction will be added to.</param>
 /// <returns><see cref="i"/></returns>
 protected IRInstruction CopyTo(IRInstruction i, IRMethod newMethod)
 {
     i.ILOffset = this.ILOffset;
     i.IRIndex = this.IRIndex;
     i.Opcode = this.Opcode;
     i.ParentMethod = newMethod;
     i.Destination = this.Destination.Clone();
     foreach (IRLinearizedLocation t in this.Sources)
     {
         i.Sources.Add(t.Clone());
     }
     return i;
 }
Beispiel #4
0
 /// <summary>
 /// This does a shallow copy of all of the members of the
 /// abstract IRInstruction class to the specified instruction.
 /// </summary>
 /// <param name="i">The instruction to copy to.</param>
 /// <param name="newMethod">The method this instruction will be added to.</param>
 /// <returns><see cref="i"/></returns>
 protected IRInstruction CopyTo(IRInstruction i, IRMethod newMethod)
 {
     i.ILOffset     = this.ILOffset;
     i.IRIndex      = this.IRIndex;
     i.Opcode       = this.Opcode;
     i.ParentMethod = newMethod;
     i.Destination  = this.Destination.Clone();
     foreach (IRLinearizedLocation t in this.Sources)
     {
         i.Sources.Add(t.Clone());
     }
     return(i);
 }
Beispiel #5
0
 public Node FindInstructionNode(IRInstruction pInstruction)
 {
     foreach (Node node in Nodes)
     {
         foreach (IRInstruction instruction in node.Instructions)
         {
             if (pInstruction == instruction)
             {
                 return(node);
             }
         }
     }
     throw new NullReferenceException();
 }
Beispiel #6
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);
        }
Beispiel #7
0
 public Node FindInstructionNode(IRInstruction pInstruction)
 {
     foreach (Node node in Nodes)
     {
         foreach (IRInstruction instruction in node.Instructions)
         {
             if (pInstruction == instruction) return node;
         }
     }
     throw new NullReferenceException();
 }
Beispiel #8
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;
                }
            }
        }
Beispiel #9
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;
                }
            }
        }