/// <summary> /// Checks whether there is a definition from the beginning to the use node /// </summary> /// <param name="fdef"></param> /// <param name="otherDefinedOffsets"></param> /// <returns></returns> private bool HasDefinitionFromRootToUseNode(DUCoverStore dcs, FieldDefUseStore fuse, HashSet <int> otherDefinedOffsets) { DEFUSE_FEASIBILITY_TYPE feasibilityVal; if (this.feasibilityDicCache.TryGetValue(fuse, out feasibilityVal)) { if (feasibilityVal == DEFUSE_FEASIBILITY_TYPE.USE_FEASIBLE) { return(false); } else { return(true); } } InstructionGraph ig = dcs.GetInstructionGraph(fuse.Method); DepthFirstTraversal dft = new DepthFirstTraversal(ig); InstructionVertex iv = ig.GetVertex(fuse.Offset); var result = dft.HasDefClearPathFromBeginning(iv, otherDefinedOffsets); if (result) { this.feasibilityDicCache[fuse] = DEFUSE_FEASIBILITY_TYPE.USE_FEASIBLE; } else { this.feasibilityDicCache[fuse] = DEFUSE_FEASIBILITY_TYPE.USE_INFEASIBLE; } return(!result); }
public void AddToDefOrUseList(Method md, int useoffset, Method unknownSideEffectMethod) { FieldDefUseStore fdus = new FieldDefUseStore(this.fd, md, useoffset); fdus.UnknownSideEffectMethod = unknownSideEffectMethod; this.defOrUseSet.Add(fdus); }
private bool UpdateDUCoverTable(Field field, out FieldDefUseStore llfs) { if (this.lastFieldDefsDic.TryGetValue(field.GlobalIndex, out llfs)) { TypeEx declType; if (!field.TryGetDeclaringType(out declType)) { logger.Error("Failed to retrieve declaring type for the field " + field.FullName); return(false); } DeclClassEntity dce; if (!this.dcs.DeclEntityDic.TryGetValue(declType.FullName, out dce)) { logger.Error("Failed to retrieve DeclClassEntity for the class " + declType.FullName); return(false); } DeclFieldEntity dfe; if (!dce.FieldEntities.TryGetValue(field.FullName, out dfe)) { logger.Error("Failed to retrieve DeclFieldEntity for the field " + field.FullName); return(false); } return(dfe.UpdateDUCoverageTable(llfs.Method, llfs.Offset, this.GetCurrentMethod(), this.currOffset)); } else { //logger.Warn("Encountered load field on " + field.FullName + " at " + this.GetCurrentMethod().FullName // + "(" + this.currOffset + ") without any field definition"); return(false); } }
public void ComputeDUCoverage(out int totalDUPairs, out int coveredDUPairs, out int totalDefs, out int coveredDefs, out int totalUses, out int coveredUses) { totalDUPairs = this.duCoverageTable.Count; coveredDUPairs = coveredDefs = coveredUses = 0; totalDefs = this.defDic.Count; totalUses = this.useDic.Count; //Computing def-uses foreach (var dcse in this.duCoverageTable.Keys) { var value = this.duCoverageTable[dcse]; if (value > 0) { coveredDUPairs++; var defpart = new FieldDefUseStore(dcse.Field, dcse.DefMethod, dcse.DefOffset); var existingDefValue = 0; if (this.defDic.TryGetValue(defpart, out existingDefValue)) { this.defDic[defpart] = existingDefValue + 1; } var usepart = new FieldDefUseStore(dcse.Field, dcse.UseMethod, dcse.UseOffset); var existingUseValue = 0; if (this.useDic.TryGetValue(usepart, out existingUseValue)) { this.useDic[usepart] = existingUseValue + 1; } } } //Computing defs. A def is considered as covered if it is exercised by one use foreach (var defvalue in this.defDic.Values) { if (defvalue > 0) { coveredDefs++; } } //Computing uses. A use is considered as covered if all its pairs with defs are covered foreach (var usevalue in this.useDic.Values) { if (usevalue >= totalDefs) { coveredUses++; } } this.TotalDUPairs = totalDUPairs; this.CoveredDUPairs = coveredDUPairs; this.TotalDefs = totalDefs; this.CoveredDefs = coveredDefs; this.TotalUses = totalUses; this.CoveredUses = coveredUses; }
/// <summary> /// Registers the last definition of the field /// </summary> /// <param name="field"></param> private void AddToFieldDefinitionStore(Field field) { var peekmethod = this.methodStack.Peek(); //Set method is already been handled if (peekmethod.ShortName.StartsWith("set_") && this.lastFieldDefsDic.ContainsKey(field.GlobalIndex)) { return; } FieldDefUseStore llfs = new FieldDefUseStore(field, this.GetCurrentMethod(), this.currOffset); this.lastFieldDefsDic[field.GlobalIndex] = llfs; }
/// <summary> /// Gets all other offsets within the method, where the field is defined /// </summary> /// <param name="method"></param> /// <param name="safeSet"></param> /// <returns></returns> private HashSet <int> GetOtherDefOffsetsInMethod(Method method, FieldDefUseStore currfdef) { HashSet <int> otherOffsets = new HashSet <int>(); foreach (var fdef in this.defDic.Keys) { if (fdef.Equals(currfdef)) { continue; } if (fdef.Method.Equals(method)) { otherOffsets.Add(fdef.Offset); } } return(otherOffsets); }
/// <summary> /// Checks whether a definition and use are in different methods /// </summary> /// <param name="dcse"></param> /// <returns></returns> private bool IsFeasibleDUCoverEntry(DUCoverStore dcs, FieldDefUseStore fdef, FieldDefUseStore fuse) { //if (fdef.Method.FullName.Contains("AddVertex") && fuse.Method.FullName.Contains("AddVertex") && fdef.Field.FullName.Contains("m_VertexOutEdges") // && fdef.Offset == 13 && fuse.Offset == 2) //{ // int i = 0; //} //check whether the def and use are in the same method if (fdef.Method.Equals(fuse.Method)) { var otherFDefOffsets = this.GetOtherDefOffsetsInMethod(fdef.Method, fdef); InstructionGraph ig = dcs.GetInstructionGraph(fdef.Method); DepthFirstTraversal dft = new DepthFirstTraversal(ig); var source = ig.GetVertex(fdef.Offset); var target = ig.GetVertex(fuse.Offset); return(dft.HasDefClearPathBetweenNodes(source, target, otherFDefOffsets)); } else { var otherFDefOffsets = this.GetOtherDefOffsetsInMethod(fdef.Method, fdef); if (otherFDefOffsets.Count > 0) { if (this.HasRedefinition(dcs, fdef, otherFDefOffsets)) { return(false); } } otherFDefOffsets = this.GetOtherDefOffsetsInMethod(fuse.Method, fdef); if (otherFDefOffsets.Count > 0) { if (this.HasDefinitionFromRootToUseNode(dcs, fuse, otherFDefOffsets)) { return(false); } } return(true); } }
public void AddToUseList(Method md, int useoffset) { FieldDefUseStore fdus = new FieldDefUseStore(this.fd, md, useoffset); this.useDic[fdus] = 0; }
private bool UpdateDUCoverTable(Field field, out FieldDefUseStore llfs) { if (this.lastFieldDefsDic.TryGetValue(field.GlobalIndex, out llfs)) { TypeEx declType; if (!field.TryGetDeclaringType(out declType)) { logger.Error("Failed to retrieve declaring type for the field " + field.FullName); return false; } DeclClassEntity dce; if (!this.dcs.DeclEntityDic.TryGetValue(declType.FullName, out dce)) { logger.Error("Failed to retrieve DeclClassEntity for the class " + declType.FullName); return false; } DeclFieldEntity dfe; if (!dce.FieldEntities.TryGetValue(field.FullName, out dfe)) { logger.Error("Failed to retrieve DeclFieldEntity for the field " + field.FullName); return false; } return dfe.UpdateDUCoverageTable(llfs.Method, llfs.Offset, this.GetCurrentMethod(), this.currOffset); } else { //logger.Warn("Encountered load field on " + field.FullName + " at " + this.GetCurrentMethod().FullName // + "(" + this.currOffset + ") without any field definition"); return false; } }
/// <summary> /// Handles a method call. /// </summary> /// <param name="method"></param> private void HandleMethodCall(Method method) { if (lastLoadedFields.Count != 0) { bool bSuccessfulUpdate = true; //handling method calls on fields of this class if (method.ShortName.StartsWith("set_")) { //Update definition table with the current offsets these fields are modified here foreach (var field in lastLoadedFields) { FieldDefUseStore fdus = new FieldDefUseStore(field, this.GetCurrentMethod(), this.currOffset); this.lastFieldDefsDic[field.GlobalIndex] = fdus; } } else if (method.ShortName.StartsWith("get_")) { //Register all usages foreach (var field in lastLoadedFields) { FieldDefUseStore fdus; this.UpdateDUCoverTable(field, out fdus); } } else { foreach (var field in lastLoadedFields) { bool defined, used; if (ses.TryGetFieldDefOrUseByMethod(this.GetCurrentMethod(), field, this.currOffset, out defined, out used)) { FieldDefUseStore fdus; if (used) { //This field is used by this method if (this.lastFieldDefsDic.ContainsKey(field.GlobalIndex)) { this.UpdateDUCoverTable(field, out fdus); } } if (defined) { //This field is defined by this method fdus = new FieldDefUseStore(field, this.GetCurrentMethod(), this.currOffset); this.lastFieldDefsDic[field.GlobalIndex] = fdus; if (used) { //Since it is both used and defined. this.UpdateDUCoverTable(field, out fdus); } } } else { //Backup option: declaring as both used and defined. //In general, control cannot come over here FieldDefUseStore fdus; if (this.lastFieldDefsDic.ContainsKey(field.GlobalIndex)) { bSuccessfulUpdate = this.UpdateDUCoverTable(field, out fdus); } if (bSuccessfulUpdate) { //Override the current definition, since this field is being modified here fdus = new FieldDefUseStore(field, this.GetCurrentMethod(), this.currOffset); this.lastFieldDefsDic[field.GlobalIndex] = fdus; //also add a self def-use this.UpdateDUCoverTable(field, out fdus); } } } } if(bSuccessfulUpdate) lastLoadedFields.Clear(); } else { var shortname = method.ShortName; if (shortname.StartsWith("set_")) { Field definedField; if (DeclEntityCollector.TryGetFieldOfSetter(method, out definedField)) { //Override if there is any previous definition of this field FieldDefUseStore fdus = new FieldDefUseStore(definedField, this.GetCurrentMethod(), this.currOffset); this.lastFieldDefsDic[definedField.GlobalIndex] = fdus; } } else if (shortname.StartsWith("get_")) { int foffset; Field usedField; if (DeclEntityCollector.TryGetFieldOfGetter(method, out usedField, out foffset)) { FieldDefUseStore llfs; this.UpdateDUCoverTable(usedField, out llfs); this.lastLoadedFields.Add(usedField); } } } }
/// <summary> /// Registers the last definition of the field /// </summary> /// <param name="field"></param> private void AddToFieldDefinitionStore(Field field) { var peekmethod = this.methodStack.Peek(); //Set method is already been handled if (peekmethod.ShortName.StartsWith("set_") && this.lastFieldDefsDic.ContainsKey(field.GlobalIndex)) return; FieldDefUseStore llfs = new FieldDefUseStore(field, this.GetCurrentMethod(), this.currOffset); this.lastFieldDefsDic[field.GlobalIndex] = llfs; }
/// <summary> /// Checks whether a definition and use are in different methods /// </summary> /// <param name="dcse"></param> /// <returns></returns> private bool IsFeasibleDUCoverEntry(DUCoverStore dcs, FieldDefUseStore fdef, FieldDefUseStore fuse) { //if (fdef.Method.FullName.Contains("AddVertex") && fuse.Method.FullName.Contains("AddVertex") && fdef.Field.FullName.Contains("m_VertexOutEdges") // && fdef.Offset == 13 && fuse.Offset == 2) //{ // int i = 0; //} //check whether the def and use are in the same method if (fdef.Method.Equals(fuse.Method)) { var otherFDefOffsets = this.GetOtherDefOffsetsInMethod(fdef.Method, fdef); InstructionGraph ig = dcs.GetInstructionGraph(fdef.Method); DepthFirstTraversal dft = new DepthFirstTraversal(ig); var source = ig.GetVertex(fdef.Offset); var target = ig.GetVertex(fuse.Offset); return dft.HasDefClearPathBetweenNodes(source, target, otherFDefOffsets); } else { var otherFDefOffsets = this.GetOtherDefOffsetsInMethod(fdef.Method, fdef); if (otherFDefOffsets.Count > 0) { if (this.HasRedefinition(dcs, fdef, otherFDefOffsets)) return false; } otherFDefOffsets = this.GetOtherDefOffsetsInMethod(fuse.Method, fdef); if (otherFDefOffsets.Count > 0) { if (this.HasDefinitionFromRootToUseNode(dcs, fuse, otherFDefOffsets)) return false; } return true; } }
/// <summary> /// Checks whether the fdef has a redefinition from the current not to the end of the method /// </summary> /// <param name="fdef"></param> /// <param name="otherDefinedOffsets"></param> /// <returns></returns> private bool HasRedefinition(DUCoverStore dcs, FieldDefUseStore fdef, HashSet<int> otherDefinedOffsets) { DEFUSE_FEASIBILITY_TYPE feasibilityVal; if (this.feasibilityDicCache.TryGetValue(fdef, out feasibilityVal)) { if (feasibilityVal == DEFUSE_FEASIBILITY_TYPE.DEF_FEASIBLE) return false; else return true; } InstructionGraph ig = dcs.GetInstructionGraph(fdef.Method); DepthFirstTraversal dft = new DepthFirstTraversal(ig); InstructionVertex iv = ig.GetVertex(fdef.Offset); var result = dft.HasDefClearPathToEnd(iv, otherDefinedOffsets); if (result) this.feasibilityDicCache[fdef] = DEFUSE_FEASIBILITY_TYPE.DEF_FEASIBLE; else this.feasibilityDicCache[fdef] = DEFUSE_FEASIBILITY_TYPE.DEF_INFEASIBLE; return !result; }
/// <summary> /// Gets all other offsets within the method, where the field is defined /// </summary> /// <param name="method"></param> /// <param name="safeSet"></param> /// <returns></returns> private HashSet<int> GetOtherDefOffsetsInMethod(Method method, FieldDefUseStore currfdef) { HashSet<int> otherOffsets = new HashSet<int>(); foreach (var fdef in this.defDic.Keys) { if (fdef.Equals(currfdef)) continue; if (fdef.Method.Equals(method)) otherOffsets.Add(fdef.Offset); } return otherOffsets; }
/// <summary> /// Handles a method call. /// </summary> /// <param name="method"></param> private void HandleMethodCall(Method method) { if (lastLoadedFields.Count != 0) { bool bSuccessfulUpdate = true; //handling method calls on fields of this class if (method.ShortName.StartsWith("set_")) { //Update definition table with the current offsets these fields are modified here foreach (var field in lastLoadedFields) { FieldDefUseStore fdus = new FieldDefUseStore(field, this.GetCurrentMethod(), this.currOffset); this.lastFieldDefsDic[field.GlobalIndex] = fdus; } } else if (method.ShortName.StartsWith("get_")) { //Register all usages foreach (var field in lastLoadedFields) { FieldDefUseStore fdus; this.UpdateDUCoverTable(field, out fdus); } } else { foreach (var field in lastLoadedFields) { bool defined, used; if (ses.TryGetFieldDefOrUseByMethod(this.GetCurrentMethod(), field, this.currOffset, out defined, out used)) { FieldDefUseStore fdus; if (used) { //This field is used by this method if (this.lastFieldDefsDic.ContainsKey(field.GlobalIndex)) { this.UpdateDUCoverTable(field, out fdus); } } if (defined) { //This field is defined by this method fdus = new FieldDefUseStore(field, this.GetCurrentMethod(), this.currOffset); this.lastFieldDefsDic[field.GlobalIndex] = fdus; if (used) { //Since it is both used and defined. this.UpdateDUCoverTable(field, out fdus); } } } else { //Backup option: declaring as both used and defined. //In general, control cannot come over here FieldDefUseStore fdus; if (this.lastFieldDefsDic.ContainsKey(field.GlobalIndex)) { bSuccessfulUpdate = this.UpdateDUCoverTable(field, out fdus); } if (bSuccessfulUpdate) { //Override the current definition, since this field is being modified here fdus = new FieldDefUseStore(field, this.GetCurrentMethod(), this.currOffset); this.lastFieldDefsDic[field.GlobalIndex] = fdus; //also add a self def-use this.UpdateDUCoverTable(field, out fdus); } } } } if (bSuccessfulUpdate) { lastLoadedFields.Clear(); } } else { var shortname = method.ShortName; if (shortname.StartsWith("set_")) { Field definedField; if (DeclEntityCollector.TryGetFieldOfSetter(method, out definedField)) { //Override if there is any previous definition of this field FieldDefUseStore fdus = new FieldDefUseStore(definedField, this.GetCurrentMethod(), this.currOffset); this.lastFieldDefsDic[definedField.GlobalIndex] = fdus; } } else if (shortname.StartsWith("get_")) { int foffset; Field usedField; if (DeclEntityCollector.TryGetFieldOfGetter(method, out usedField, out foffset)) { FieldDefUseStore llfs; this.UpdateDUCoverTable(usedField, out llfs); this.lastLoadedFields.Add(usedField); } } } }
public void AddToDefList(Method md, int defoffset) { FieldDefUseStore fdus = new FieldDefUseStore(this.fd, md, defoffset); this.defDic[fdus] = 0; }
public void ComputeDUCoverage(out int totalDUPairs, out int coveredDUPairs, out int totalDefs, out int coveredDefs, out int totalUses, out int coveredUses) { totalDUPairs = this.duCoverageTable.Count; coveredDUPairs = coveredDefs = coveredUses = 0; totalDefs = this.defDic.Count; totalUses = this.useDic.Count; //Computing def-uses foreach (var dcse in this.duCoverageTable.Keys) { var value = this.duCoverageTable[dcse]; if (value > 0) { coveredDUPairs++; var defpart = new FieldDefUseStore(dcse.Field, dcse.DefMethod, dcse.DefOffset); var existingDefValue = 0; if (this.defDic.TryGetValue(defpart, out existingDefValue)) this.defDic[defpart] = existingDefValue + 1; var usepart = new FieldDefUseStore(dcse.Field, dcse.UseMethod, dcse.UseOffset); var existingUseValue = 0; if (this.useDic.TryGetValue(usepart, out existingUseValue)) this.useDic[usepart] = existingUseValue + 1; } } //Computing defs. A def is considered as covered if it is exercised by one use foreach (var defvalue in this.defDic.Values) { if (defvalue > 0) coveredDefs++; } //Computing uses. A use is considered as covered if all its pairs with defs are covered foreach (var usevalue in this.useDic.Values) { if (usevalue >= totalDefs) coveredUses++; } this.TotalDUPairs = totalDUPairs; this.CoveredDUPairs = coveredDUPairs; this.TotalDefs = totalDefs; this.CoveredDefs = coveredDefs; this.TotalUses = totalUses; this.CoveredUses = coveredUses; }