/// <summary>
        /// Function that retrieves associated method store 
        /// </summary>
        /// <param name="pms"></param>
        /// <param name="ms"></param>
        /// <returns></returns>
        public static bool TryGetFieldStore(IPexComponent host, PersistentFieldStore pfs, out FieldStore fs)
        {
            fs = new FieldStore();

            bool bresult = MethodOrFieldAnalyzer.TryGetFieldFromPersistentStringForm(host, pfs.FieldName, out fs.FieldName);
            SafeDebug.Assume(bresult, "Failed to get field from the persistent store");

            fs.FieldValues.AddRange(pfs.FieldValues);

            //TODO: Performance can be improved via caching over here
            foreach (var mname in pfs.ReadMethods)
            {
                Method m;
                bresult = MethodOrFieldAnalyzer.TryGetMethodFromPersistentStringForm(host, mname, out m);
                SafeDebug.Assume(bresult, "Failed to get method from persistent string form ");
                fs.ReadMethods.Add(m);
            }

            foreach (var typeex in pfs.WriteMethods.Keys)
            {
                SafeSet<Method> wmethods = new SafeSet<Method>();
                TypeEx typeEx;
                bresult = MethodOrFieldAnalyzer.TryGetTypeExFromPersistentStringForm(host, typeex, out typeEx);
                SafeDebug.Assume(bresult, "Failed to get type from persistent string form " + typeex);

                fs.WriteMethods.Add(typeEx, wmethods);

                HashSet<string> methods;
                bresult = pfs.WriteMethods.TryGetValue(typeex, out methods);
                SafeDebug.Assume(bresult, "Failed to get associated set of methods for a type " + typeex);

                foreach (var m in methods)
                {
                    Method method;
                    bresult = MethodOrFieldAnalyzer.TryGetMethodFromPersistentStringForm(host, m, out method);
                    SafeDebug.Assume(bresult, "Failed to get method from string form " + m);
                    wmethods.Add(method);
                }
            }

            foreach (var m in pfs.ModificationTypeDictionary.Keys)
            {
                var value = pfs.ModificationTypeDictionary[m];
                Method method;
                bresult = MethodOrFieldAnalyzer.TryGetMethodFromPersistentStringForm(host, m, out method);
                SafeDebug.Assume(bresult, "Failed to get method from string form " + m);
                fs.ModificationTypeDictionary.Add(method, value);
            }

            foreach (var m in pfs.PreciseModificationTypeDictionary.Keys)
            {
                var value = pfs.PreciseModificationTypeDictionary[m];
                Method method;
                bresult = MethodOrFieldAnalyzer.TryGetMethodFromPersistentStringForm(host, m, out method);
                SafeDebug.Assume(bresult, "Failed to get method from string form " + m);
                fs.PreciseModificationTypeDictionary.Add(method, value);
            }

            return true;
        }
Example #2
0
        /// <summary>
        /// Gets textual form of modification type
        /// </summary>
        /// <param name="method"></param>
        /// <returns></returns>
        public static string GetModificationType(FieldStore fs, Method method)
        {
            if (!fs.ModificationTypeDictionary.ContainsKey(method))
                return "UNKNOWN";

            FieldModificationType fmt = fs.ModificationTypeDictionary[method];
            return GetModificationTypeStr(fmt);
        }
Example #3
0
        /// <summary>
        /// Gets textual form of modification type
        /// </summary>
        /// <param name="method"></param>
        /// <returns></returns>
        public static string GetPreciseModificationType(FieldStore fs, Method method)
        {
            if (!fs.PreciseModificationTypeDictionary.ContainsKey(method))
            {
                return("UNKNOWN");
            }

            FieldModificationType fmt = fs.PreciseModificationTypeDictionary[method];

            return(GetModificationTypeStr(fmt));
        }
        /// <summary>
        /// Gets the set of write methods associated with a field in the given type
        /// </summary>
        /// <param name="field"></param>
        /// <returns></returns>
        public bool TryGetWriteMethods(Field field, TypeEx declaringType, out SafeSet<Method> writeMethods)
        {
            SafeDebug.AssumeNotNull(field, "field");
            SafeDebug.AssumeNotNull(declaringType, "declaringType");

            //Declaring type should include defintinion
            if (declaringType == null || declaringType.Definition == null)
            {
                this.Log.LogWarning(WikiTopics.MissingWikiTopic, "WriteMethods",
                    "Missing definition for the declaring type " + declaringType.FullName);
                writeMethods = null;
                return false;
            }

            FieldStore fs;
            if (this.FieldDictionary.TryGetValue(field, out fs))
            {
                if (fs.WriteMethods.TryGetValue(declaringType, out writeMethods))
                    return true;
                else
                {
                    writeMethods = new SafeSet<Method>();
                    fs.WriteMethods[declaringType] = writeMethods;
                }
            }
            else
            {
                fs = new FieldStore();
                fs.FieldName = field;
                writeMethods = new SafeSet<Method>();
                fs.WriteMethods[declaringType] = writeMethods;
                this.FieldDictionary[field] = fs;
            }

            foreach (MethodDefinition instanceMethod in declaringType.Definition.DeclaredInstanceMethods)
            {
                //Ignore abstract methods
                if (instanceMethod.IsAbstract)
                    continue;

                //If the DISABLE_CALLING_METHODS_WITHIN_CLASS is set to true, then private methods need not be considered
                //since they will be filtered out.
                if (PexMeConstants.DISABLE_CALLING_METHODS_WITHIN_CLASS && instanceMethod.DeclaredVisibility == Visibility.Private)
                    continue;

                Method method = instanceMethod.Instantiate(declaringType.GenericTypeArguments, MethodOrFieldAnalyzer.GetGenericMethodParameters(this, instanceMethod));
                MethodEffects me;

                if (!MethodOrFieldAnalyzer.TryComputeMethodEffects(this, declaringType, method, null, out me))
                {
                    this.Log.LogWarning(WikiTopics.MissingWikiTopic, "methodeffects",
                        "Failed to get the method effects for method " + method);
                    continue;
                }

                if (me.WrittenInstanceFields.Contains(field.ShortName))
                {
                    writeMethods.Add(method);
                }

                FieldModificationType fmt;
                if (me.ModificationTypeDictionary.TryGetValue(field.ShortName, out fmt))
                {
                    fs.ModificationTypeDictionary[method] = fmt;
                }
            }

            //Check whether there are any private methods in calling methods.
            //If yes, replace them with their callers.
            if (!PexMeConstants.DISABLE_CALLING_METHODS_WITHIN_CLASS)
            {
                var newWriteMethods = new SafeSet<Method>();
                GetCallingMethods(field, declaringType, writeMethods, newWriteMethods);

                writeMethods.Clear();
                writeMethods.AddRange(newWriteMethods);
            }

            TypeEx baseType = declaringType.BaseType;
            if (baseType != null && baseType.FullName != "System.Object")
            {
                SafeSet<Method> innerWriteMethods;
                this.TryGetWriteMethods(field, baseType, out innerWriteMethods);
                if (innerWriteMethods != null)
                    writeMethods.AddRange(innerWriteMethods);
            }

            return true;
        }
        /// <summary>
        /// Function the retrieves associated Persistent store for each MethodStore
        /// </summary>
        /// <param name="ms"></param>
        /// <param name="pms"></param>
        /// <returns></returns>
        public static bool TryGetPersistentFieldStore(IPexComponent host, FieldStore fs, out PersistentFieldStore pfs)
        {
            pfs = new PersistentFieldStore();

            pfs.FieldName = MethodOrFieldAnalyzer.GetPersistentStringFormOfField(fs.FieldName);
            //foreach(var value in fs.FieldValues)
            //    pfs.FieldValues.Add(value);

            //TODO: Performance can be improved via caching over here
            foreach (var m in fs.ReadMethods)
                pfs.ReadMethods.Add(MethodOrFieldAnalyzer.GetPersistentStringFormOfMethod(m));

            foreach (var typeex in fs.WriteMethods.Keys)
            {
                HashSet<string> wmethods = new HashSet<string>();
                pfs.WriteMethods.Add(MethodOrFieldAnalyzer.GetPersistentStringFormOfTypeEx(typeex), wmethods);

                SafeSet<Method> methods;
                bool bresult = fs.WriteMethods.TryGetValue(typeex, out methods);
                SafeDebug.Assume(bresult, "Failed to get associated set of methods for a type");

                var assemblyname = typeex.Definition.Module.Assembly.Location;
                var typename = typeex.FullName;

                foreach (var m in methods)
                {
                    wmethods.Add(assemblyname + PexMeConstants.PexMePersistenceFormSeparator
                        + typename + PexMeConstants.PexMePersistenceFormSeparator + MethodOrFieldAnalyzer.GetMethodSignature(m));
                }
            }

            foreach (var m in fs.ModificationTypeDictionary.Keys)
            {
                var value = fs.ModificationTypeDictionary[m];
                pfs.ModificationTypeDictionary.Add(MethodOrFieldAnalyzer.GetPersistentStringFormOfMethod(m), value);
            }

            foreach (var m in fs.PreciseModificationTypeDictionary.Keys)
            {
                var value = fs.PreciseModificationTypeDictionary[m];
                pfs.PreciseModificationTypeDictionary.Add(MethodOrFieldAnalyzer.GetPersistentStringFormOfMethod(m), value);
            }

            return true;
        }
        private bool IsEligibleForLooping(MethodSignatureSequence seq, Field field, 
            Dictionary<string, Method> writeMethods, FieldStore fs, out string loop_method)
        {
            string prevMethod = "";
            int numTimes = 1;
            foreach (var method in seq.Sequence)
            {
                if (method == prevMethod)
                    numTimes++;
                else
                    numTimes = 1;

                if (numTimes >= PexMeConstants.LOOP_THRESHOLD)
                {
                    //Check whether this loop_method modifies the culprit field
                    //exactly by ONE (We current handle only INCREMENT_BY_ONE CASE)
                    if (!writeMethods.ContainsKey(method))
                        continue;

                    var wm = writeMethods[method];
                    FieldModificationType fmt;
                    if (!fs.PreciseModificationTypeDictionary.TryGetValue(wm, out fmt))
                        continue;

                    if (fmt != FieldModificationType.INCREMENT_ONE)
                        continue;
                    loop_method = method;
                    return true;
                }

                prevMethod = method;
            }

            loop_method = "";
            return false;
        }
Example #7
0
        /// <summary>
        /// Adds a monitored field to the database. Updates two kinds of hashmaps
        /// a. Field to Method mapper, which gives what the methods modifying a given field
        /// b. Method to Field mapper, which gives what fields are modified by each method (later used to identify a minimized set of methods)
        /// </summary>
        /// <param name="tm"></param>
        /// <param name="method"></param>
        /// <param name="f"></param>
        /// <param name="indices"></param>
        /// <param name="fieldValue"></param>
        public void AddMonitoredField(TermManager tm, Method method, Field f, Term[] indices, Term fieldValue, Term initialValue)
        {
            string arrayIndex = "";

            using (PexMeTermRewriter pexmeRewriter = new PexMeTermRewriter(tm))
            {
                fieldValue = pexmeRewriter.VisitTerm(default(TVoid), fieldValue); //update the field value to accomodate array-type field
                //if (indices.Length == 0) //not an array-type field
                if (indices.Length == 1)                                          //is an array-type field
                {
                    arrayIndex = " at index of " + indices[0].UniqueIndex.ToString();
                }

                if (initialValue != null)
                {
                    initialValue = pexmeRewriter.VisitTerm(default(TVoid), initialValue);
                }
            }

            //Updating the method store
            MethodStore ms;

            if (!methodDic.TryGetValue(method, out ms))
            {
                ms                = new MethodStore();
                ms.methodName     = method;
                methodDic[method] = ms;
            }

            ms.WriteFields.Add(f);
            //TODO: Gather information of read fields

            //Updating the field store
            FieldStore fs;

            if (!fieldDic.TryGetValue(f, out fs))
            {
                fs           = new FieldStore();
                fs.FieldName = f;
                fieldDic[f]  = fs;
            }

            TypeEx declaringType;

            if (!method.TryGetDeclaringType(out declaringType))
            {
                this.Log.LogError(WikiTopics.MissingWikiTopic, "monitorfield",
                                  "Failed to get the declaring type for the method " + method.FullName);
                return;
            }

            SafeSet <Method> writeMethods;

            if (!fs.WriteMethods.TryGetValue(declaringType, out writeMethods))
            {
                writeMethods = new SafeSet <Method>();
                fs.WriteMethods[declaringType] = writeMethods;
            }
            writeMethods.Add(method);

            var sb      = new SafeStringBuilder();
            var swriter = new TermSExpWriter(tm, new SafeStringWriter(sb), true, false);

            swriter.Write(fieldValue);
            sb.Append(arrayIndex);

            int value;

            if (tm.TryGetI4Constant(fieldValue, out value))
            {
                int initialval;
                if (initialValue != null)
                {
                    tm.TryGetI4Constant(initialValue, out initialval);
                }
                else
                {
                    initialval = 0;
                }

                sb.Append("  constant value: " + value);

                if (f.Type.ToString() != "System.Boolean")
                {
                    if (value < initialval)
                    {
                        fs.ModificationTypeDictionary[method] = FieldModificationType.DECREMENT;
                    }
                    else if (value > initialval)
                    {
                        fs.ModificationTypeDictionary[method] = FieldModificationType.INCREMENT;

                        if (value == initialval + 1)
                        {
                            fs.PreciseModificationTypeDictionary[method] = FieldModificationType.INCREMENT_ONE;
                        }
                    }
                    else
                    {
                        fs.ModificationTypeDictionary[method] = FieldModificationType.UNKNOWN;
                    }
                }
                else
                {
                    if (value == 0)
                    {
                        fs.ModificationTypeDictionary[method] = FieldModificationType.FALSE_SET;
                    }
                    else
                    {
                        fs.ModificationTypeDictionary[method] = FieldModificationType.TRUE_SET;
                    }
                }
            }
            else if (tm.IsDefaultValue(fieldValue))
            {
                if (initialValue != null && !tm.IsDefaultValue(initialValue))
                {
                    fs.ModificationTypeDictionary[method] = FieldModificationType.NULL_SET;
                }
                else
                {
                    fs.ModificationTypeDictionary[method] = FieldModificationType.UNKNOWN;
                }

                sb.Append("  null reference ");
            }
            else
            {
                if (initialValue == null)
                {
                    fs.ModificationTypeDictionary[method] = FieldModificationType.NON_NULL_SET;
                }
                else
                {
                    fs.ModificationTypeDictionary[method] = FieldModificationType.UNKNOWN;
                }

                sb.Append("  not-null reference ");
            }

            fs.FieldValues.Add(sb.ToString());
        }
        /// <summary>
        /// Adds a monitored field to the database. Updates two kinds of hashmaps
        /// a. Field to Method mapper, which gives what the methods modifying a given field
        /// b. Method to Field mapper, which gives what fields are modified by each method (later used to identify a minimized set of methods)
        /// </summary>
        /// <param name="tm"></param>
        /// <param name="method"></param>
        /// <param name="f"></param>
        /// <param name="indices"></param>
        /// <param name="fieldValue"></param>
        public void AddMonitoredField(TermManager tm, Method method, Field f, Term[] indices, Term fieldValue, Term initialValue)
        {
            string arrayIndex = "";
            using (PexMeTermRewriter pexmeRewriter = new PexMeTermRewriter(tm))
            {
                fieldValue = pexmeRewriter.VisitTerm(default(TVoid), fieldValue); //update the field value to accomodate array-type field
                //if (indices.Length == 0) //not an array-type field
                if (indices.Length == 1) //is an array-type field
                {
                    arrayIndex = " at index of " + indices[0].UniqueIndex.ToString();
                }

                if(initialValue != null)
                    initialValue = pexmeRewriter.VisitTerm(default(TVoid), initialValue);
            }

            //Updating the method store
            MethodStore ms;
            if(!methodDic.TryGetValue(method, out ms))
            {
                ms = new MethodStore();
                ms.methodName = method;
                methodDic[method] = ms;
            }

            ms.WriteFields.Add(f);
            //TODO: Gather information of read fields

            //Updating the field store
            FieldStore fs;
            if (!fieldDic.TryGetValue(f, out fs))
            {
                fs = new FieldStore();
                fs.FieldName = f;
                fieldDic[f] = fs;
            }

            TypeEx declaringType;
            if (!method.TryGetDeclaringType(out declaringType))
            {
                this.Log.LogError(WikiTopics.MissingWikiTopic, "monitorfield",
                    "Failed to get the declaring type for the method " + method.FullName);
                return;
            }

            SafeSet<Method> writeMethods;
            if (!fs.WriteMethods.TryGetValue(declaringType, out writeMethods))
            {
                writeMethods = new SafeSet<Method>();
                fs.WriteMethods[declaringType] = writeMethods;
            }
            writeMethods.Add(method);

            var sb = new SafeStringBuilder();
            var swriter = new TermSExpWriter(tm, new SafeStringWriter(sb), true, false);
            swriter.Write(fieldValue);
            sb.Append(arrayIndex);

            int value;
            if (tm.TryGetI4Constant(fieldValue, out value))
            {
                int initialval;
                if (initialValue != null)
                    tm.TryGetI4Constant(initialValue, out initialval);
                else
                    initialval = 0;

                sb.Append("  constant value: " + value);

                if (f.Type.ToString() != "System.Boolean")
                {
                    if (value < initialval)
                        fs.ModificationTypeDictionary[method] = FieldModificationType.DECREMENT;
                    else if (value > initialval)
                    {
                        fs.ModificationTypeDictionary[method] = FieldModificationType.INCREMENT;

                        if (value == initialval + 1)
                            fs.PreciseModificationTypeDictionary[method] = FieldModificationType.INCREMENT_ONE;
                    }
                    else
                        fs.ModificationTypeDictionary[method] = FieldModificationType.UNKNOWN;
                }
                else
                {
                    if (value == 0)
                        fs.ModificationTypeDictionary[method] = FieldModificationType.FALSE_SET;
                    else
                        fs.ModificationTypeDictionary[method] = FieldModificationType.TRUE_SET;
                }
            }
            else if (tm.IsDefaultValue(fieldValue))
            {
                if (initialValue != null && !tm.IsDefaultValue(initialValue))
                    fs.ModificationTypeDictionary[method] = FieldModificationType.NULL_SET;
                else
                    fs.ModificationTypeDictionary[method] = FieldModificationType.UNKNOWN;

                sb.Append("  null reference ");
            }
            else
            {
                if (initialValue == null)
                    fs.ModificationTypeDictionary[method] = FieldModificationType.NON_NULL_SET;
                else
                    fs.ModificationTypeDictionary[method] = FieldModificationType.UNKNOWN;

                sb.Append("  not-null reference ");
            }

            fs.FieldValues.Add(sb.ToString());
        }
        /// <summary>
        /// Gets the set of write methods associated with a field in the given type
        /// </summary>
        /// <param name="field"></param>
        /// <returns></returns>
        public bool TryGetWriteMethods(Field field, TypeEx declaringType, out SafeSet <Method> writeMethods)
        {
            SafeDebug.AssumeNotNull(field, "field");
            SafeDebug.AssumeNotNull(declaringType, "declaringType");

            //Declaring type should include defintinion
            if (declaringType == null || declaringType.Definition == null)
            {
                this.Log.LogWarning(WikiTopics.MissingWikiTopic, "WriteMethods",
                                    "Missing definition for the declaring type " + declaringType.FullName);
                writeMethods = null;
                return(false);
            }

            FieldStore fs;

            if (this.FieldDictionary.TryGetValue(field, out fs))
            {
                if (fs.WriteMethods.TryGetValue(declaringType, out writeMethods))
                {
                    return(true);
                }
                else
                {
                    writeMethods = new SafeSet <Method>();
                    fs.WriteMethods[declaringType] = writeMethods;
                }
            }
            else
            {
                fs           = new FieldStore();
                fs.FieldName = field;
                writeMethods = new SafeSet <Method>();
                fs.WriteMethods[declaringType] = writeMethods;
                this.FieldDictionary[field]    = fs;
            }

            foreach (MethodDefinition instanceMethod in declaringType.Definition.DeclaredInstanceMethods)
            {
                //Ignore abstract methods
                if (instanceMethod.IsAbstract)
                {
                    continue;
                }

                //If the DISABLE_CALLING_METHODS_WITHIN_CLASS is set to true, then private methods need not be considered
                //since they will be filtered out.
                if (PexMeConstants.DISABLE_CALLING_METHODS_WITHIN_CLASS && instanceMethod.DeclaredVisibility == Visibility.Private)
                {
                    continue;
                }

                Method        method = instanceMethod.Instantiate(declaringType.GenericTypeArguments, MethodOrFieldAnalyzer.GetGenericMethodParameters(this, instanceMethod));
                MethodEffects me;

                if (!MethodOrFieldAnalyzer.TryComputeMethodEffects(this, declaringType, method, null, out me))
                {
                    this.Log.LogWarning(WikiTopics.MissingWikiTopic, "methodeffects",
                                        "Failed to get the method effects for method " + method);
                    continue;
                }

                if (me.WrittenInstanceFields.Contains(field.ShortName))
                {
                    writeMethods.Add(method);
                }

                FieldModificationType fmt;
                if (me.ModificationTypeDictionary.TryGetValue(field.ShortName, out fmt))
                {
                    fs.ModificationTypeDictionary[method] = fmt;
                }
            }

            //Check whether there are any private methods in calling methods.
            //If yes, replace them with their callers.
            if (!PexMeConstants.DISABLE_CALLING_METHODS_WITHIN_CLASS)
            {
                var newWriteMethods = new SafeSet <Method>();
                GetCallingMethods(field, declaringType, writeMethods, newWriteMethods);

                writeMethods.Clear();
                writeMethods.AddRange(newWriteMethods);
            }

            TypeEx baseType = declaringType.BaseType;

            if (baseType != null && baseType.FullName != "System.Object")
            {
                SafeSet <Method> innerWriteMethods;
                this.TryGetWriteMethods(field, baseType, out innerWriteMethods);
                if (innerWriteMethods != null)
                {
                    writeMethods.AddRange(innerWriteMethods);
                }
            }

            return(true);
        }