public PexMeFactoryGuesser(IPexComponent host)
     : base(host)
 {
     this.host = host;
     this.pmd  = host.GetService <IPexMeDynamicDatabase>() as PexMeDynamicDatabase;
     this.psd  = host.GetService <IPexMeStaticDatabase>() as PexMeStaticDatabase;
 }
示例#2
0
        /// <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);
        }
示例#3
0
        /// <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);
        }
示例#4
0
        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);
        }
示例#5
0
 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;
 }
示例#6
0
        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);
            }
        }
示例#7
0
        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);
        }
示例#10
0
        /// <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);
                }
            }
        }
示例#11
0
        /// <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);
            }
        }
示例#12
0
        /// <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 *************************/
        }
示例#13
0
        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");
        }