public PexMeFactoryGuesser(IPexComponent host) : base(host) { this.host = host; this.pmd = host.GetService <IPexMeDynamicDatabase>() as PexMeDynamicDatabase; this.psd = host.GetService <IPexMeStaticDatabase>() as PexMeStaticDatabase; }
/// <summary> /// If type is an interface, returns all concrete implementing classes /// else if type is an abstract class, returns all concrete extending classes /// </summary> /// <param name="psd"></param> /// <param name="type"></param> /// <param name="extendingClasses"></param> /// <returns></returns> public static bool TryGetExtendingClasses(PexMeStaticDatabase psd, TypeEx type, out IIndexable <TypeDefinition> extendingClasses) { //load inheritance hierarchies if not already done psd.LoadInheritanceHierarchies(); extendingClasses = null; TypeStore ts; if (!psd.TypeDictionary.TryGetValue(type.Definition, out ts)) { return(false); } SafeSet <TypeDefinition> extendingClassesSet = new SafeSet <TypeDefinition>(); CollectAllExtendingClasses(ts, extendingClassesSet); if (extendingClassesSet.Count == 0) { return(false); } var extendingClassesList = new SafeList <TypeDefinition>(); foreach (var tdef in extendingClassesSet) { extendingClassesList.Add(tdef); } extendingClasses = extendingClassesList; return(true); }
/// <summary> /// Gets predefined types. Here tdef can be null. In that scenario, if a dictionary exists for the generic /// name, than the first element in the dictionary is returned /// </summary> /// <param name="host"></param> /// <param name="genericname"></param> /// <param name="tdef"></param> /// <param name="genericType"></param> /// <returns></returns> public static bool TryGetInstantiatedClass(IPexComponent host, string genericname, TypeDefinition tdef, out TypeEx genericType) { genericType = null; if (!bClassLoaded) { if (host != null) { string assemblyName = null; PexMeDynamicDatabase pmd = host.GetService <IPexMeDynamicDatabase>() as PexMeDynamicDatabase; if (pmd != null) { assemblyName = pmd.AssemblyName; } else { PexMeStaticDatabase psd = host.GetService <IPexMeStaticDatabase>() as PexMeStaticDatabase; if (psd != null) { assemblyName = psd.AssemblyName; } } //One of PMD or PSD should be available by this time. If not nothing can be done if (assemblyName == null) { host.Log.LogWarning(WikiTopics.MissingWikiTopic, "Hardcoded", "Could not load predefined generic classes data"); return(false); } bClassLoaded = true; LoadPredefinedGenericClasses(host, assemblyName); } } PreDefinedGenericClassesStore pdgc; if (predefinedClasses.TryGetValue(genericname, out pdgc)) { if (tdef != null) { if (pdgc.TryGetTypeExForTypename(tdef.FullName, out genericType)) { return(true); } } //tdef can be null in the case of instantiating methods and fields having generic arguments if (pdgc.TryGetSomeTypeEx(out genericType)) { return(true); } } return(false); }
protected override void Initialize() { base.Initialize(); this.pmd = this.GetService <IPexMeDynamicDatabase>() as PexMeDynamicDatabase; this.psd = this.GetService <IPexMeStaticDatabase>() as PexMeStaticDatabase; this.tba = new TargetBranchAnalyzer(this.pmd, this.Services, this); this.ExplorationServices.ExplorableManager.AddExplorableInsufficienyObserver(this); this.Log.LogMessage("hint provider", "Registered the hint provider"); this.thp = new TypeHintProvider(this.pmd, this.psd); this.ExplorationServices.DomainManager.AddTypeHintProvider(thp); }
public FieldAccessCollector(IFieldAccessPathObserver pathObserver, IFieldAccessExplorationObserver explorationObserver, IPexMeDynamicDatabase pmd, PexMeStaticDatabase psd, int level) { this.pathObserver = pathObserver; this.explorationObserver = explorationObserver; this.pmd = pmd as PexMeDynamicDatabase; this.psd = psd; this.trackedFrameId = -1; this.level = level; this.depth = -1; }
public PexMePostProcessor(IPexComponent host) : base(host) { this.host = host; this.pmd = host.GetService <IPexMeDynamicDatabase>() as PexMeDynamicDatabase; this.psd = host.GetService <IPexMeStaticDatabase>() as PexMeStaticDatabase; this.pdw = new PexMeDumpWriter(host); this.currAssembly = this.pmd.Services.CurrentAssembly.Assembly.Assembly; var nestingdepth = System.Environment.GetEnvironmentVariable("PEXME_NESTED_DEPTH"); if (nestingdepth != null) { ndepth = Convert.ToInt32(nestingdepth, 10); } }
public DUCoverEngine() : base(new Container(new TypeEx[] { Microsoft.ExtendedReflection.Metadata.Metadata <IEngineOptions> .Type }), new IComponent[] { }) { EngineOptions options = new EngineOptions(); this.AddComponent("options", options); this.AddComponents(); var pmd = new PexMeDynamicDatabase(); pmd.AssemblyName = System.Environment.GetEnvironmentVariable(DUCoverConstants.DUCoverAssemblyVar); this.AddComponent("pmd", pmd); var psd = new PexMeStaticDatabase(); psd.AssemblyName = System.Environment.GetEnvironmentVariable(DUCoverConstants.DUCoverAssemblyVar); this.AddComponent("psd", psd); }
public TypeHintProvider(PexMeDynamicDatabase pmd, PexMeStaticDatabase psd) { this.pmd = pmd; this.psd = psd; }
/// <summary> /// Tries to load static database /// </summary> /// <param name="host"></param> /// <param name="psd"></param> /// <returns></returns> public static bool TryLoadStaticDatabase(PexMeStaticDatabase psd) { var fieldstore = Path.Combine(PexMeConstants.PexMeStorageDirectory, PexMeConstants.PexMeStaticFieldStore); if (!File.Exists(fieldstore)) { psd.FieldDictionary = new SafeDictionary <Field, FieldStore>(); } else { try { Stream streamRead = File.OpenRead(fieldstore); if (streamRead.Length <= PexMeConstants.MAX_ALLOWED_STATIC_STORAGE) { BinaryFormatter binaryRead = new BinaryFormatter(); System.Collections.Generic.Dictionary <string, PersistentFieldStore> pfs = binaryRead.Deserialize(streamRead) as System.Collections.Generic.Dictionary <string, PersistentFieldStore>; psd.FieldDictionary = GetFieldDictionary(psd, pfs); } else { psd.FieldDictionary = new SafeDictionary <Field, FieldStore>(); } streamRead.Close(); } catch (Exception) { //host.Log.LogErrorFromException(ex, WikiTopics.MissingWikiTopic, "dumpreader", // "Failed to read the dynamic field store"); psd.FieldDictionary = new SafeDictionary <Field, FieldStore>(); } } var methodstore = Path.Combine(PexMeConstants.PexMeStorageDirectory, PexMeConstants.PexMeStaticMethodStore); if (!File.Exists(methodstore)) { psd.MethodDictionary = new SafeDictionary <Method, MethodStore>(); } else { try { Stream streamRead = File.OpenRead(methodstore); if (streamRead.Length <= PexMeConstants.MAX_ALLOWED_STATIC_STORAGE) { BinaryFormatter binaryRead = new BinaryFormatter(); System.Collections.Generic.Dictionary <string, PersistentMethodStore> pfs = binaryRead.Deserialize(streamRead) as System.Collections.Generic.Dictionary <string, PersistentMethodStore>; psd.MethodDictionary = GetMethodDictionary(psd, pfs); } else { psd.FieldDictionary = new SafeDictionary <Field, FieldStore>(); } streamRead.Close(); } catch (Exception) { //host.Log.LogErrorFromException(ex, WikiTopics.MissingWikiTopic, "dumpreader", // "Failed to read the dynamic field store"); psd.MethodDictionary = new SafeDictionary <Method, MethodStore>(); } } return(true); }
/// <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); } } }
/// <summary> /// Collects defs and uses within a method /// </summary> /// <param name="td"></param> /// <param name="ade"></param> /// <param name="constructor"></param> private static void CollectDefsAndUsesInMethod(PexMeStaticDatabase psd, TypeDefinition td, DeclClassEntity ade, Method method, SafeSet <Method> visitedMethods, SideEffectStore ses) { try { if (visitedMethods == null) { visitedMethods = new SafeSet <Method>(); } if (visitedMethods.Contains(method)) { return; } visitedMethods.Add(method); MethodBodyEx body; if (!method.TryGetBody(out body) || !body.HasInstructions) { return; } int offset = 0; Instruction instruction; OpCode prevOpcode = OpCodes.Nop; //Stack for load instructions Field lastAccessedArrayField = null; SafeList <Field> lastAccessedFieldList = new SafeList <Field>(); while (body.TryGetInstruction(offset, out instruction)) { SafeDebug.AssumeNotNull(instruction, "instruction"); OpCode opCode = instruction.OpCode; if (MethodOrFieldAnalyzer.LdcOpCodes.Contains(opCode)) { //topIsConstant = true; } else if (MethodOrFieldAnalyzer.ConvOpCodes.Contains(opCode)) { // do not change topIsConstant } else { if (opCode == OpCodes.Stfld) { SafeDebug.Assume(opCode.OperandType == OperandType.InlineField, "opCode.OperandType == OperandType.InlineField"); Field field = instruction.Field; DeclFieldEntity dfe; if (ade.FieldEntities.TryGetValue(field.FullName, out dfe)) { //Found a definition of the field. register the definition dfe.AddToDefList(method, offset); } } else if (opCode == OpCodes.Ldfld || opCode == OpCodes.Ldflda) { SafeDebug.Assume(opCode.OperandType == OperandType.InlineField, "opCode.OperandType == OperandType.InlineField"); Field accessedField = instruction.Field; if (PexMeFilter.IsPrimitiveType(accessedField.Type)) { DeclFieldEntity dfe; if (ade.FieldEntities.TryGetValue(accessedField.FullName, out dfe)) { //Found an accessor. register the usage dfe.AddToUseList(method, offset); } lastAccessedArrayField = null; } else { if (accessedField.Type.Spec == TypeSpec.SzArray) { lastAccessedArrayField = accessedField; } else { //Any access needs to be registered as use lastAccessedFieldList.Add(accessedField); } } } else if (MethodOrFieldAnalyzer.StElemOpCodes.Contains(opCode)) { if (lastAccessedArrayField != null) { DeclFieldEntity dfe; if (ade.FieldEntities.TryGetValue(lastAccessedArrayField.FullName, out dfe)) { //Found a definition of the field. register the definition dfe.AddToDefList(method, offset); } lastAccessedArrayField = null; } } else if (MethodOrFieldAnalyzer.BranchOpCodes.Contains(opCode)) { if (lastAccessedFieldList.Count > 0) { //A field is loaded and used in conditional statement. We use the offset of conditional statement as the usage point foreach (var field in lastAccessedFieldList) { DeclFieldEntity dfe; if (ade.FieldEntities.TryGetValue(field.FullName, out dfe)) { //Found a definition of the field. register the definition dfe.AddToUseList(method, offset); } } lastAccessedFieldList.Clear(); } if (lastAccessedArrayField != null) { DeclFieldEntity dfe; if (ade.FieldEntities.TryGetValue(lastAccessedArrayField.FullName, out dfe)) { //Found a definition of the field. register the definition dfe.AddToUseList(method, offset); } lastAccessedArrayField = null; } } else if (opCode == OpCodes.Ret) { //A field is accessed and is returned from here if (lastAccessedFieldList.Count > 0) { foreach (var field in lastAccessedFieldList) { DeclFieldEntity dfe; if (ade.FieldEntities.TryGetValue(field.FullName, out dfe)) { //Found a use of the field. register the definition dfe.AddToUseList(method, offset); } } lastAccessedFieldList.Clear(); } } else if (opCode == OpCodes.Call || opCode == OpCodes.Callvirt) { SafeDebug.Assume(opCode.OperandType == OperandType.InlineMethod, "opCode.OperandType == OperandType.InlineMethod"); Method methodinner = instruction.Method; SafeDebug.AssumeNotNull(method, "method"); //If this condition is not satisfied, it could be a local method call, which is dealt separately if (lastAccessedFieldList.Count != 0) { HandleMethodCall(psd, ade, method, offset, lastAccessedFieldList, methodinner, ses); lastAccessedFieldList.Clear(); } else { var shortname = methodinner.ShortName; if (shortname.StartsWith("set_")) { HandleSetterMethod(ade, method, offset, methodinner); } else if (shortname.StartsWith("get_")) { HandleGetterMethod(ade, method, offset, methodinner, lastAccessedFieldList); } } } } prevOpcode = opCode; offset = instruction.NextOffset; } } catch (Exception ex) { logger.ErrorException("Exception thrown with static analysis " + ex.StackTrace, ex); } }
/// <summary> /// Dumps static database /// </summary> public void DumpStaticDatabase(PexMeStaticDatabase psd) { SafeDebug.AssumeNotNull(psd, "psd"); if (!Directory.Exists(PexMeConstants.PexMeStorageDirectory)) { Directory.CreateDirectory(PexMeConstants.PexMeStorageDirectory); } //Dump the dynamic field store that includes information of which method modify which fields try { var filename = Path.Combine(PexMeConstants.PexMeStorageDirectory, PexMeConstants.PexMeStaticFieldStore); Stream streamWrite = File.Create(filename); BinaryFormatter binaryWrite = new BinaryFormatter(); var persistentFieldDic = this.GetPersistentFieldDictionary(psd.FieldDictionary); binaryWrite.Serialize(streamWrite, persistentFieldDic); streamWrite.Close(); } catch (Exception ex) { psd.Log.LogErrorFromException(ex, WikiTopics.MissingWikiTopic, "dumpwriter", "Failed to dump field store of static database"); } //Dump the dynamic method store that includes information of which method calls other methods and field they modify try { var filename = Path.Combine(PexMeConstants.PexMeStorageDirectory, PexMeConstants.PexMeStaticMethodStore); Stream streamWrite = File.Create(filename); BinaryFormatter binaryWrite = new BinaryFormatter(); var persistentMethodDic = this.GetPersistentMethodDictionary(psd.MethodDictionary); binaryWrite.Serialize(streamWrite, persistentMethodDic); streamWrite.Close(); } catch (Exception ex) { psd.Log.LogErrorFromException(ex, WikiTopics.MissingWikiTopic, "dumpwriter", "Failed to dump method store of static database"); } /******************** DEBUGGING INFO *************************/ //Writing method information var methodDic = psd.MethodDictionary; var methodAccessFileName = Path.Combine(PexMeConstants.PexMeStorageDirectory, psd.AssemblyName + ".static.methodAccess.txt"); using (StreamWriter sw = new StreamWriter(methodAccessFileName)) { foreach (var methodEntry in methodDic.Values) { //Printing write fields sw.WriteLine("Methodname: " + methodEntry.methodName); if (methodEntry.WriteFields.Count > 0) { sw.WriteLine("Write fields: "); foreach (var writeField in methodEntry.WriteFields) { sw.WriteLine("\tField: " + writeField); } } if (methodEntry.CalledMethods.Count > 0) { sw.WriteLine("Called Methods: "); foreach (var calledMethod in methodEntry.CalledMethods) { sw.WriteLine("\t" + calledMethod); } } if (methodEntry.CallingMethods.Count > 0) { sw.WriteLine("Calling Methods: "); foreach (var callingMethod in methodEntry.CallingMethods) { sw.WriteLine("\t" + callingMethod); } } //TODO: Print read fields } } //Writing field information var fieldDic = psd.FieldDictionary; var fieldAccessFileName = Path.Combine(PexMeConstants.PexMeStorageDirectory, psd.AssemblyName + ".static.fieldAccess.txt"); using (StreamWriter sw = new StreamWriter(fieldAccessFileName)) { foreach (var fieldEntry in fieldDic.Values) { //Printing write methods sw.WriteLine("Fieldname: " + fieldEntry.FieldName); sw.WriteLine("Write methods: "); foreach (var writeMethodSet in fieldEntry.WriteMethods.Values) { foreach (var writeMethod in writeMethodSet) { sw.WriteLine("\tMethod: " + writeMethod + ", ModificationType: " + FieldStore.GetModificationType(fieldEntry, writeMethod)); } } sw.WriteLine("Field values: "); foreach (var fieldValue in fieldEntry.FieldValues) { sw.WriteLine("\tValue: " + fieldValue); } //TODO: Print read methods } } /******************** DEBUGGING INFO *************************/ }
public void Analyze() { //this.Log.LogMessage(PexMeLogCategories.MethodBegin, "Begin of FieldAccessPathObserver.Analyze() method"); if (this.explorationObserver == null) { this.explorationObserver = this.GetService <IFieldAccessExplorationObserver>(); } if (this.pmd == null) { this.pmd = this.GetService <IPexMeDynamicDatabase>() as PexMeDynamicDatabase; } if (this.psd == null) { this.psd = this.GetService <IPexMeStaticDatabase>() as PexMeStaticDatabase; } int framesCount = 0; int framesHandled = 0; int maxLevelCount = 16; //TODO: Why 16? pmd.LastExecutedFactoryMethodCallSequence = null; for (int level = 0; level < maxLevelCount; level++) { FieldAccessCollector controller = new FieldAccessCollector(this, this.explorationObserver, this.pmd, this.psd, level); this.pmd.DefectDetectingSequence = false; try { using (IEngine trackingEngine = this.PathServices.TrackingEngineFactory.CreateTrackingEngine(controller)) { IPexTrackingDriver driver = trackingEngine.GetService <IPexTrackingDriver>(); if (!driver.Run()) { break; } } } catch (Exception ex) { this.pmd.DefectDetectingSequence = true; } pmd.LastExecutedFactoryMethodCallSequence = controller.FactoryMethodCallSequence; pmd.LastExecutedCUTMethodCallSequence = controller.CUTMethodCallSequence; //StringBuilder sb = new StringBuilder(); //foreach(Method m in pmd.LastExecutedMethodCallSequence) //{ // sb.Append(m.ToString() + "\n"); //} //this.pmd.Log.LogMessage("debug", "Executed method call sequence " + sb.ToString()); framesCount = SafeMath.Max(framesCount, controller.FramesCount); framesHandled += controller.FramesHandled; if (framesHandled > framesCount) { framesHandled = framesCount; } //this.Log.LogMessage( // "FieldAccessObserver", // "collecting data, {0:P} of all frames up to level {1} / {2}", // ((double)framesHandled / framesCount), level, maxLevelCount); if (controller.FramesHandled == 0 || // did we make any progress? framesHandled >= framesCount) // or have we processed all frames there are? { break; } } //Gather the information of last visited term here to use it later in //InsufficientObjectFactoryObserver.LogExplorableInsufficiency //this.Log.LogMessage(PexMeLogCategories.MethodEnd, "End of FieldAccessPathObserver.Analyze() method"); }