/// <summary> /// Collects all definitions and uses among each class in the assembly under analysis /// </summary> /// <param name="ade"></param> private static void CollectAllDefsAndUsesInTypeDef(TypeDefinition td, DeclClassEntity ade) { var host = DUCoverStore.GetInstance().Host; SideEffectStore ses = SideEffectStore.GetInstance(); var psd = host.GetService <PexMeStaticDatabase>() as PexMeStaticDatabase; foreach (var constructor in td.DeclaredInstanceConstructors) { var method = constructor.Instantiate(MethodOrFieldAnalyzer.GetGenericTypeParameters(host, td), MethodOrFieldAnalyzer.GetGenericMethodParameters(host, constructor)); CollectDefsAndUsesInMethod(psd, td, ade, method, null, ses); } foreach (var mdef in td.DeclaredInstanceMethods) { try { var method = mdef.Instantiate(MethodOrFieldAnalyzer.GetGenericTypeParameters(host, td), MethodOrFieldAnalyzer.GetGenericMethodParameters(host, mdef)); CollectDefsAndUsesInMethod(psd, td, ade, method, null, ses); } catch (Exception ex) { logger.ErrorException("Failed to instantiate method " + mdef.FullName, ex); } } foreach (var prop in td.DeclaredProperties) { var getter = prop.Getter; if (getter != null) { Field usedField; int foffset; var method = getter.Instantiate(MethodOrFieldAnalyzer.GetGenericTypeParameters(host, td), MethodOrFieldAnalyzer.GetGenericMethodParameters(host, getter)); if (TryGetFieldOfGetter(method, out usedField, out foffset)) { DeclFieldEntity dfe; if (ade.FieldEntities.TryGetValue(usedField.FullName, out dfe)) { //Found an accessor. register the usage dfe.AddToUseList(method, foffset); } } } var setter = prop.Setter; if (setter != null) { var method = setter.Instantiate(MethodOrFieldAnalyzer.GetGenericTypeParameters(host, td), MethodOrFieldAnalyzer.GetGenericMethodParameters(host, setter)); CollectDefsAndUsesInMethod(psd, td, ade, method, null, ses); } } }
/// <summary> /// Analyzes the given assembly statically and gathers all declared entities /// such as member variables and local variables /// </summary> /// <param name="assembly"></param> public static void CollectAllDeclEntitiesInAssembly(AssemblyEx assembly) { SafeDebug.AssumeNotNull(assembly, "assembly"); logger.Debug("Beginning of static analysis"); if (ade == null) { ade = DUCoverStore.GetInstance(); } foreach (TypeDefinition td in assembly.TypeDefinitions) { CollectAllDeclEntitiesInTypeDef(td); } }
public static void DumpAllDeclEntity(DUCoverStore ade, int totalDUPairs, int coveredDUPairs, int totalDefs, int coveredDefs, int totalUses, int coveredUses) { //Dump the dynamic field store that includes information of which method modify which fields try { var filename = DUCoverConstants.DeclEntityFile; using (StreamWriter sw = new StreamWriter(filename)) { sw.WriteLine("Total number of DUPairs: " + totalDUPairs); sw.WriteLine("\tCovered DUPairs: " + coveredDUPairs); sw.WriteLine("\tDef-Use Coverage: " + ((double)coveredDUPairs / (double)totalDUPairs)); sw.WriteLine("Total number of Defs: " + totalDefs); sw.WriteLine("\tCovered Defs: " + coveredDefs); sw.WriteLine("\tAll-Defs Coverage: " + ((double)coveredDefs / (double)totalDefs)); sw.WriteLine("Total number of Uses: " + totalUses); sw.WriteLine("\tCovered Uses: " + coveredUses); sw.WriteLine("\tAll-Uses Coverage: " + ((double)coveredUses / (double)totalUses)); foreach (var de in ade.DeclEntityDic.Values) { sw.WriteLine("ClassName: " + de.ToString()); sw.WriteLine("Total DU pairs: " + de.TotalDUPairs); sw.WriteLine("Covered DU pairs: " + de.CoveredDUPairs); sw.WriteLine("Total defs: " + de.TotalDefs); sw.WriteLine("Covered defs: " + de.CoveredDefs); sw.WriteLine("Total uses: " + de.TotalUses); sw.WriteLine("Covered uses: " + de.CoveredUses); sw.WriteLine(); foreach (var dfe in de.FieldEntities.Values) { sw.WriteLine("\tField: " + dfe.ToString()); sw.WriteLine("\tTotal DU pairs: " + dfe.TotalDUPairs); sw.WriteLine("\tCovered DU pairs: " + dfe.CoveredDUPairs); sw.WriteLine("\tTotal defs: " + dfe.TotalDefs); sw.WriteLine("\tCovered defs: " + dfe.CoveredDefs); sw.WriteLine("\tTotal uses: " + dfe.TotalUses); sw.WriteLine("\tCovered uses: " + dfe.CoveredUses); sw.WriteLine("\tAll Def Entries"); foreach (var defkey in dfe.DefDic.Keys) { sw.WriteLine("\t\t" + defkey.ToString() + " " + dfe.DefDic[defkey]); } sw.WriteLine("\t All Use Entries"); foreach (var usekey in dfe.UseDic.Keys) { sw.WriteLine("\t\t" + usekey.ToString() + " " + dfe.UseDic[usekey]); } sw.WriteLine("\t All DefOrUse (currently unknown) entries"); foreach (var deforusekey in dfe.DefOrUseSet) { sw.WriteLine("\t\t" + deforusekey.ToString()); } sw.WriteLine("\t All Def-Use Entries"); var dudic = dfe.DUCoverageTable; foreach (var defusekey in dudic.Keys) { sw.WriteLine("\t\t" + defusekey + " : " + dudic[defusekey]); } } sw.WriteLine("===================================================="); } } } catch (Exception ex) { logger.ErrorException("Failed to write contents of all declared entities", ex); } }
/// <summary> /// Handles a method call /// </summary> /// <param name="psd"></param> /// <param name="ade"></param> /// <param name="method"></param> /// <param name="offset"></param> /// <param name="lastAccessedFieldList"></param> /// <param name="methodinner"></param> private static void HandleMethodCall(PexMeStaticDatabase psd, DeclClassEntity ade, Method method, int offset, SafeList <Field> lastAccessedFieldList, Method methodinner, SideEffectStore ses) { SafeList <Field> fieldsProcessed = new SafeList <Field>(); Field receiverField = null; //Check whether the current method call is actually on the field previously loaded TypeEx methodDeclType; if (!methodinner.TryGetDeclaringType(out methodDeclType)) { logger.Error("Failed to get the declaring type of the method: " + methodinner.FullName); return; } if (methodDeclType.FullName == "System.String" || methodDeclType.FullName == "System.string") { return; //Do not process string types. } //Check whether the declaring type is in the fields list foreach (var field in lastAccessedFieldList) { var fieldType = field.Type; if (fieldType == methodDeclType || fieldType.IsAssignableTo(methodDeclType) || methodDeclType.IsAssignableTo(fieldType)) { fieldsProcessed.Add(field); receiverField = field; break; } } if (receiverField == null) { //Failed to identify the reciver field of this method return; } //Identify arguments of the current method call foreach (var argtype in methodinner.ParameterTypes) { foreach (var field in lastAccessedFieldList) { if (field == receiverField) { continue; } var fieldType = field.Type; if (fieldType == argtype || fieldType.IsAssignableTo(argtype) || argtype.IsAssignableTo(fieldType)) { fieldsProcessed.Add(field); break; } } } DUCoverStore dcs = DUCoverStore.GetInstance(); //If the method is known, its side-effects are well-known if (methodinner.ShortName.StartsWith("set_")) { foreach (var processedField in fieldsProcessed) { DeclFieldEntity dfe; if (ade.FieldEntities.TryGetValue(processedField.FullName, out dfe)) { dfe.AddToDefList(method, offset); } lastAccessedFieldList.Remove(processedField); } } else if (methodinner.ShortName.StartsWith("get_")) { foreach (var processedField in fieldsProcessed) { DeclFieldEntity dfe; if (ade.FieldEntities.TryGetValue(processedField.FullName, out dfe)) { dfe.AddToUseList(method, offset); } lastAccessedFieldList.Remove(processedField); } } else { //add all fiels to def or use, since we may not aware of their side-effects here foreach (var processedField in fieldsProcessed) { DeclFieldEntity dfe; if (ade.FieldEntities.TryGetValue(processedField.FullName, out dfe)) { bool defined, used; if (ses.TryGetFieldDefOrUseByMethod(method, processedField, offset, out defined, out used)) { if (defined) { dfe.AddToDefList(method, offset); } if (used) { dfe.AddToUseList(method, offset); } } else { dfe.AddToDefOrUseList(method, offset, methodinner); } } lastAccessedFieldList.Remove(processedField); } } }
public PUTGen() { this.dcs = DUCoverStore.GetInstance(); this.host = this.dcs.Host; }