/// <summary> /// Handles the usage of phi variables. /// </summary> /// <param name="instructionOffset">The offset of the instruction, that pops the phi variable from the stack.</param> /// <param name="record">The VariableDefineUseRecord associated with the instruction.</param> /// <param name="variableNode">The node in the craph corresponding to the phi variable.</param> /// <param name="nodes"> The graph. </param> protected override void OnPhiVariableUsed(int instructionOffset, ClassHierarchyNode variableNode) { Instruction instr = offsetToInstruction[instructionOffset]; if (instr.OpCode.Code == Code.Dup || instr.OpCode.Code == Code.Pop) { ///No information regarding the type of the phi variable can be extracted from pop/dup instructions return; } ///Get the use type of the phi variable. ClassHierarchyNode typeNode = GetUseExpressionTypeNode(instr, variableNode.Variable); if (instr.OpCode.Code == Code.Switch) { variableNode.AddSupertype(typeNode); resultingGraph.Add(typeNode); return; } ///It is possible, that a phi variable is being used with another one. This case needs special care. if (typeNode.NodeType.FullName == "System.Int32" && OnlyPhiVariablesUsed(offsetToExpression[instr.Offset])) { ///Only phi variables were part of the expression. List <ClassHierarchyNode> phiVariableNodes = GetUsedPhiVariableNodes(instr.Offset); for (int i = 0; i < phiVariableNodes.Count; i++) { for (int j = i + 1; j < phiVariableNodes.Count; j++) { ///Add edge between the phi variables. phiVariableNodes[i].AddSupertype(phiVariableNodes[j]); phiVariableNodes[j].AddSupertype(phiVariableNodes[i]); } } if (IsArithmeticOperation(instr.OpCode.Code)) { for (int i = 0; i < phiVariableNodes.Count; i++) { notPossibleBooleanNodes.Add(phiVariableNodes[i]); ClassHierarchyNode integerTypeNode = GetTypeNode(typeSystem.Int32); if (!integerTypeNode.CanAssignTo.Contains(phiVariableNodes[i])) { integerTypeNode.CanAssignTo.Add(phiVariableNodes[i]); phiVariableNodes[i].SubTypes.Add(integerTypeNode); } } } return; } variableNode.AddSupertype(typeNode); resultingGraph.Add(typeNode); }
protected override void OnPhiVariableUsed(int instructionOffset, ClassHierarchyNode variableNode) { V_0 = this.offsetToInstruction.get_Item(instructionOffset); if (V_0.get_OpCode().get_Code() == 36 || V_0.get_OpCode().get_Code() == 37) { return; } V_1 = this.GetUseExpressionTypeNode(V_0, variableNode.get_Variable()); if (V_0.get_OpCode().get_Code() == 68) { variableNode.AddSupertype(V_1); dummyVar0 = this.resultingGraph.Add(V_1); return; } if (!String.op_Equality(V_1.get_NodeType().get_FullName(), "System.Int32") || !this.OnlyPhiVariablesUsed(this.offsetToExpression.get_Item(V_0.get_Offset()))) { variableNode.AddSupertype(V_1); dummyVar2 = this.resultingGraph.Add(V_1); return; } V_3 = this.GetUsedPhiVariableNodes(V_0.get_Offset()); V_4 = 0; while (V_4 < V_3.get_Count()) { V_5 = V_4 + 1; while (V_5 < V_3.get_Count()) { V_3.get_Item(V_4).AddSupertype(V_3.get_Item(V_5)); V_3.get_Item(V_5).AddSupertype(V_3.get_Item(V_4)); V_5 = V_5 + 1; } V_4 = V_4 + 1; } if (this.IsArithmeticOperation(V_0.get_OpCode().get_Code())) { V_6 = 0; while (V_6 < V_3.get_Count()) { dummyVar1 = this.notPossibleBooleanNodes.Add(V_3.get_Item(V_6)); V_7 = this.GetTypeNode(this.typeSystem.get_Int32()); if (!V_7.get_CanAssignTo().Contains(V_3.get_Item(V_6))) { V_7.get_CanAssignTo().Add(V_3.get_Item(V_6)); V_3.get_Item(V_6).get_SubTypes().Add(V_7); } V_6 = V_6 + 1; } } return; }
/// <summary> /// Handles the assignment of phi variables. /// </summary> /// <param name="instructionOffset">The offset of the instruction, that put the value on the stack.</param> /// <param name="variableNode">The graph node corresponding to the phi variable.</param> /// <param name="nodes">The graph.</param> protected override void OnPhiVariableAssigned(int instructionOffset, ClassHierarchyNode variableNode) { /// This key should allways be present. Expression instructionExpression = offsetToExpression[instructionOffset]; /// Determine the type of the assigned value. TypeReference assignedType = instructionExpression.ExpressionType; if (instructionExpression is LiteralExpression) { int literal = (int)((instructionExpression as LiteralExpression).Value); if (literal == 0 || literal == 1) { assignedType = typeSystem.Boolean; } else if (literal <= byte.MaxValue && literal >= byte.MinValue) { assignedType = typeSystem.Byte; } else if (literal < char.MaxValue && literal >= char.MinValue) { /// Both char and short can be used here. assignedType = typeSystem.Char; } } /// Add the edge in the graph. ClassHierarchyNode supertypeNode = GetTypeNode(assignedType); supertypeNode.AddSupertype(variableNode); resultingGraph.Add(supertypeNode); }
/// <summary> /// Adds an edge from <paramref name="smallerType"/> to <paramref name="biggerType"/>. /// </summary> /// <param name="biggerTypeNode">The type the edge points to.</param> /// <param name="smallerTypeNode">The type the edge comes from.</param> private void AddEdge(ClassHierarchyNode biggerTypeNode, ClassHierarchyNode smallerTypeNode) { // smallerTypeNode can assign to BiggerTypeNode smallerTypeNode.AddSupertype(biggerTypeNode); resultingGraph.Add(smallerTypeNode); resultingGraph.Add(biggerTypeNode); }
private void AddEdge(ClassHierarchyNode biggerTypeNode, ClassHierarchyNode smallerTypeNode) { smallerTypeNode.AddSupertype(biggerTypeNode); dummyVar0 = this.resultingGraph.Add(smallerTypeNode); dummyVar1 = this.resultingGraph.Add(biggerTypeNode); return; }
/// <summary> /// Builds the hierarchy between the hard nodes. /// </summary> /// <param name="hardNodes">Collection of the hard nodes.</param> protected virtual void BuildUpHardNodesHierarchy(IEnumerable <ClassHierarchyNode> hardNodes) { Queue <ClassHierarchyNode> queuedNodes = new Queue <ClassHierarchyNode>(hardNodes); HashSet <ClassHierarchyNode> processedNodes = new HashSet <ClassHierarchyNode>(); while (queuedNodes.Count > 0) { ClassHierarchyNode currentType = queuedNodes.Dequeue(); processedNodes.Add(currentType); resultingGraph.Add(currentType); TypeDefinition currentNodeType = currentType.NodeType.Resolve(); TypeReference baseTypeRef = null; if (currentNodeType == null) { continue; } baseTypeRef = currentNodeType.BaseType; if (baseTypeRef != null) { ClassHierarchyNode baseType = GetTypeNode(baseTypeRef); currentType.AddSupertype(baseType); if (!processedNodes.Contains(baseType)) { queuedNodes.Enqueue(baseType); } } if (currentNodeType.IsInterface) { ClassHierarchyNode objectNode = GetTypeNode(typeSystem.Object); currentType.AddSupertype(objectNode); } IEnumerable <TypeReference> interfaces = currentType.NodeType.Resolve().Interfaces; foreach (TypeReference interfaceRef in interfaces) { ClassHierarchyNode implementedInterface = GetTypeNode(interfaceRef); currentType.AddSupertype(implementedInterface); if (!processedNodes.Contains(implementedInterface)) { queuedNodes.Enqueue(implementedInterface); } } } AddObjectClassNodeIfMIssing(); }
/// <summary> /// Handles the usage of phi variables. /// </summary> /// <param name="instructionOffset">The offset of the instruction, that pops the phi variable from the stack.</param> /// <param name="record">The VariableDefineUseRecord associated with the instruction.</param> /// <param name="variableNode">The node in the craph corresponding to the phi variable.</param> /// <param name="nodes"> The graph. </param> protected override void OnPhiVariableUsed(int instructionOffset, ClassHierarchyNode variableNode) { Instruction instr = offsetToInstruction[instructionOffset]; if (instr.OpCode.Code == Code.Dup || instr.OpCode.Code == Code.Pop) { ///No information regarding the type of the phi variable can be extracted from pop/dup instructions return; } ///Get the use type of the phi variable. ClassHierarchyNode typeNode = GetUseExpressionTypeNode(instr, variableNode.Variable); if (instr.OpCode.Code == Code.Switch) { variableNode.AddSupertype(typeNode); resultingGraph.Add(typeNode); return; } ///It is possible, that a phi variable is being used with another one. This case needs special care. if (typeNode.NodeType.FullName == "System.Int32" && OnlyPhiVariablesUsed(offsetToExpression[instr.Offset])) { ///Only phi variables were part of the expression. List<ClassHierarchyNode> phiVariableNodes = GetUsedPhiVariableNodes(instr.Offset); for (int i = 0; i < phiVariableNodes.Count; i++) { for (int j = i + 1; j < phiVariableNodes.Count; j++) { ///Add edge between the phi variables. phiVariableNodes[i].AddSupertype(phiVariableNodes[j]); phiVariableNodes[j].AddSupertype(phiVariableNodes[i]); } } if (IsArithmeticOperation(instr.OpCode.Code)) { for (int i = 0; i < phiVariableNodes.Count; i++) { notPossibleBooleanNodes.Add(phiVariableNodes[i]); ClassHierarchyNode integerTypeNode = GetTypeNode(typeSystem.Int32); if (!integerTypeNode.CanAssignTo.Contains(phiVariableNodes[i])) { integerTypeNode.CanAssignTo.Add(phiVariableNodes[i]); phiVariableNodes[i].SubTypes.Add(integerTypeNode); } } } return; } variableNode.AddSupertype(typeNode); resultingGraph.Add(typeNode); }