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); }
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; } } }
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); }
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; } } } } }
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; } } }