/// <summary> /// Appends a method store to the current one /// </summary> /// <param name="sem"></param> public void AppendMethodStore(SEMethodStore sem, int offset) { foreach (var defelem in sem.DefinedFieldSet.Values) { SEFieldStore sef; if (!this.defFieldSet.TryGetValue(defelem.FullName, out sef)) { sef = new SEFieldStore(defelem.FullName); sef.OptionalField = defelem.OptionalField; this.defFieldSet[defelem.FullName] = sef; } sef.AllOffsets.Add(offset); } foreach (var useelem in sem.UsedFieldSet.Values) { SEFieldStore sef; if (!this.useFieldSet.TryGetValue(useelem.FullName, out sef)) { sef = new SEFieldStore(useelem.FullName); sef.OptionalField = useelem.OptionalField; this.useFieldSet[useelem.FullName] = sef; } sef.AllOffsets.Add(offset); } }
public override bool Equals(object obj) { SEMethodStore other = obj as SEMethodStore; if (other == null) { return(false); } return(this.methodName == other.methodName); }
/// <summary> /// Adds that method defines the field /// </summary> /// <param name="method"></param> /// <param name="field"></param> public void AddFieldDefinition(Method method, Field field, int offset) { //Prevent adding information not related to current assembly if (this.CurrAssembly == null || method.Definition.Module.Assembly != this.CurrAssembly) { return; } SEMethodStore sem; if (!this.methodStore.TryGetValue(method.FullName, out sem)) { sem = new SEMethodStore(method.FullName); sem.OptionalMethod = method; this.methodStore[method.FullName] = sem; } sem.AddToDefinedList(field, offset); }
/// <summary> /// Appends a method store to the one in the repository /// </summary> /// <param name="sem"></param> public void AppendMethodStore(SEMethodStore sem) { //Prevent adding information not related to current assembly if (this.CurrAssembly == null || sem.OptionalMethod.Definition.Module.Assembly != this.CurrAssembly) { return; } SEMethodStore repositoryStore; if (!this.methodStore.TryGetValue(sem.MethodName, out repositoryStore)) { repositoryStore = new SEMethodStore(sem.MethodName); repositoryStore.OptionalMethod = sem.OptionalMethod; this.methodStore[sem.MethodName] = repositoryStore; } //Append fields that are within our assembly foreach (var deffield in sem.DefinedFieldSet.Values) { if (deffield.OptionalField.Definition.Module.Assembly != this.CurrAssembly) { continue; } repositoryStore.DefinedFieldSet[deffield.FullName] = deffield; } foreach (var usefield in sem.UsedFieldSet.Values) { if (usefield.OptionalField.Definition.Module.Assembly != this.CurrAssembly) { continue; } repositoryStore.UsedFieldSet[usefield.FullName] = usefield; } }
/// <summary> /// Reads from the database /// </summary> /// <returns></returns> public static SideEffectStore ReadFromDatabase() { try { var filename = Path.Combine(DUCoverConstants.DUCoverStoreLocation, DUCoverConstants.SideEffectStoreDebugFile); SideEffectStore ses = new SideEffectStore(); if (!File.Exists(filename)) return ses; using (StreamReader sr = new StreamReader(filename)) { string line; while ((line = sr.ReadLine()) != null) { line.Trim(); string methodname = line; SEMethodStore sem = new SEMethodStore(methodname); ses.MethodStore[methodname] = sem; //Reading defined line = sr.ReadLine().Trim(); string[] parts = line.Split(' '); int numDefined = Convert.ToInt32(parts[1]); for (int count = 0; count < numDefined; count++) { line = sr.ReadLine().Trim(); string[] lineparts = line.Split(' '); SEFieldStore sef = new SEFieldStore(lineparts[0]); sem.DefinedFieldSet[lineparts[0]] = sef; for (int tcount = 1; tcount < lineparts.Length; tcount++) { sef.AllOffsets.Add(Convert.ToInt32(lineparts[tcount])); } } //Reading used line = sr.ReadLine().Trim(); parts = line.Split(' '); int numUsed = Convert.ToInt32(parts[1]); for (int count = 0; count < numUsed; count++) { line = sr.ReadLine().Trim(); string[] lineparts = line.Split(' '); SEFieldStore sef = new SEFieldStore(lineparts[0]); sem.UsedFieldSet[lineparts[0]] = sef; for (int tcount = 1; tcount < lineparts.Length; tcount++) { sef.AllOffsets.Add(Convert.ToInt32(lineparts[tcount])); } } } } Console.WriteLine("Number of entries read: " + ses.MethodStore.Count); return ses; } catch (Exception ex) { Console.WriteLine("Failed to deserialize"); logger.ErrorException("Error occurred while reading from file " + ex.StackTrace, ex); } return new SideEffectStore(); }
/// <summary> /// Appends a method store to the one in the repository /// </summary> /// <param name="sem"></param> public void AppendMethodStore(SEMethodStore sem) { //Prevent adding information not related to current assembly if (this.CurrAssembly == null || sem.OptionalMethod.Definition.Module.Assembly != this.CurrAssembly) return; SEMethodStore repositoryStore; if(!this.methodStore.TryGetValue(sem.MethodName, out repositoryStore)) { repositoryStore = new SEMethodStore(sem.MethodName); repositoryStore.OptionalMethod = sem.OptionalMethod; this.methodStore[sem.MethodName] = repositoryStore; } //Append fields that are within our assembly foreach (var deffield in sem.DefinedFieldSet.Values) { if (deffield.OptionalField.Definition.Module.Assembly != this.CurrAssembly) continue; repositoryStore.DefinedFieldSet[deffield.FullName] = deffield; } foreach (var usefield in sem.UsedFieldSet.Values) { if (usefield.OptionalField.Definition.Module.Assembly != this.CurrAssembly) continue; repositoryStore.UsedFieldSet[usefield.FullName] = usefield; } }
/// <summary> /// Adds that method modifies the field /// </summary> /// <param name="method"></param> /// <param name="field"></param> public void AddFieldUsage(Method method, Field field, int offset) { //Prevent adding information not related to current assembly if (this.CurrAssembly == null || method.Definition.Module.Assembly != this.CurrAssembly) return; SEMethodStore sem; if (!this.methodStore.TryGetValue(method.FullName, out sem)) { sem = new SEMethodStore(method.FullName); sem.OptionalMethod = method; this.methodStore[method.FullName] = sem; } sem.AddToUsedList(field, offset); }
/// <summary> /// Appends a method store to the current one /// </summary> /// <param name="sem"></param> public void AppendMethodStore(SEMethodStore sem, int offset) { foreach (var defelem in sem.DefinedFieldSet.Values) { SEFieldStore sef; if (!this.defFieldSet.TryGetValue(defelem.FullName, out sef)) { sef = new SEFieldStore(defelem.FullName); sef.OptionalField = defelem.OptionalField; this.defFieldSet[defelem.FullName] = sef; } sef.AllOffsets.Add(offset); } foreach (var useelem in sem.UsedFieldSet.Values) { SEFieldStore sef; if (!this.useFieldSet.TryGetValue(useelem.FullName, out sef)) { sef = new SEFieldStore(useelem.FullName); sef.OptionalField = useelem.OptionalField; this.useFieldSet[useelem.FullName] = sef; } sef.AllOffsets.Add(offset); } }
/// <summary> /// Reads from the database /// </summary> /// <returns></returns> public static SideEffectStore ReadFromDatabase() { try { var filename = Path.Combine(DUCoverConstants.DUCoverStoreLocation, DUCoverConstants.SideEffectStoreDebugFile); SideEffectStore ses = new SideEffectStore(); if (!File.Exists(filename)) { return(ses); } using (StreamReader sr = new StreamReader(filename)) { string line; while ((line = sr.ReadLine()) != null) { line.Trim(); string methodname = line; SEMethodStore sem = new SEMethodStore(methodname); ses.MethodStore[methodname] = sem; //Reading defined line = sr.ReadLine().Trim(); string[] parts = line.Split(' '); int numDefined = Convert.ToInt32(parts[1]); for (int count = 0; count < numDefined; count++) { line = sr.ReadLine().Trim(); string[] lineparts = line.Split(' '); SEFieldStore sef = new SEFieldStore(lineparts[0]); sem.DefinedFieldSet[lineparts[0]] = sef; for (int tcount = 1; tcount < lineparts.Length; tcount++) { sef.AllOffsets.Add(Convert.ToInt32(lineparts[tcount])); } } //Reading used line = sr.ReadLine().Trim(); parts = line.Split(' '); int numUsed = Convert.ToInt32(parts[1]); for (int count = 0; count < numUsed; count++) { line = sr.ReadLine().Trim(); string[] lineparts = line.Split(' '); SEFieldStore sef = new SEFieldStore(lineparts[0]); sem.UsedFieldSet[lineparts[0]] = sef; for (int tcount = 1; tcount < lineparts.Length; tcount++) { sef.AllOffsets.Add(Convert.ToInt32(lineparts[tcount])); } } } } Console.WriteLine("Number of entries read: " + ses.MethodStore.Count); return(ses); } catch (Exception ex) { Console.WriteLine("Failed to deserialize"); logger.ErrorException("Error occurred while reading from file " + ex.StackTrace, ex); } return(new SideEffectStore()); }
/// <summary> /// Propagates the changes made by a called method to its caller, based on the lastLoadedFields /// For example, if the called method modifies any fields, then the related parent fields in the caller method /// are marked as updated /// </summary> /// <param name="callerMStore"></param> /// <param name="calledMethodStore"></param> private void PropagateModificationsToCaller(SEMethodStore callerMStore, SEMethodStore calledMethodStore, Method calledMethod) { if (this.lastLoadedFields.Count == 0) return; //Idenitfy relevant fields from the last loadedFields 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 (!calledMethod.TryGetDeclaringType(out methodDeclType)) { logger.Error("Failed to get the declaring type of the method: " + calledMethod.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 this.lastLoadedFields) { 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 calledMethod.ParameterTypes) { foreach (var field in this.lastLoadedFields) { if (field == receiverField) continue; var fieldType = field.Type; if (fieldType == argtype || fieldType.IsAssignableTo(argtype) || argtype.IsAssignableTo(fieldType)) { fieldsProcessed.Add(field); break; } } } if (calledMethodStore.DefinedFieldSet.Count == 0) { //If the called method does not define any field, all current fields are just loaded fields foreach (var field in fieldsProcessed) { callerMStore.AddToUsedList(field, this.currOffset); this.lastLoadedFields.Remove(field); } } else { //process each defined field foreach (var deffield in calledMethodStore.DefinedFieldSet.Values) { TypeEx deffieldType; if (deffield.OptionalField.TryGetDeclaringType(out deffieldType)) { //Identify the related field in the lastLoadedFields Field processedField = null; foreach (var field in fieldsProcessed) { var fieldType = field.Type; if (fieldType == deffieldType || fieldType.IsAssignableTo(deffieldType) || deffieldType.IsAssignableTo(fieldType)) { processedField = field; callerMStore.AddToDefinedList(field, this.currOffset); break; } } if (processedField != null) { fieldsProcessed.Remove(processedField); this.lastLoadedFields.Remove(processedField); } } } //Consider the remaining fields at usedfields and remove them from lastLoadedFields foreach (var field in fieldsProcessed) { callerMStore.AddToUsedList(field, this.currOffset); this.lastLoadedFields.Remove(field); } } }
public override void LeaveMethod() { if (!bStartMonitoring) return; if (this.methodStack.Count == 0) return; var poppedMethod = this.methodStack.Pop(); this.currOffset = this.offsetStack.Pop(); var previousLoadedFields = this.lastLoadedFieldsStack.Pop(); //If the last method call is a getter, add the field just loaded by that getter method //Or any other remaining loaded fields if (poppedMethod.ShortName.StartsWith("get_")) { Field usedField; int foffset; if (DeclEntityCollector.TryGetFieldOfGetter(poppedMethod, out usedField, out foffset)) { previousLoadedFields.AddRange(usedField); } } this.lastLoadedFields.Clear(); this.lastLoadedFields.AddRange(previousLoadedFields); //Updating the defined and used field list if (this.methodStoreStack.Count > 0) { ses.AppendMethodStore(currSEMethodStore); var poppedStore = this.methodStoreStack.Pop(); if (!poppedMethod.ShortName.StartsWith("get_")) { //Do not propogate for getter methods PropagateModificationsToCaller(poppedStore, currSEMethodStore, poppedMethod); } poppedStore.AppendMethodStore(currSEMethodStore, this.currOffset); currSEMethodStore = poppedStore; } if (poppedMethod.ShortName.Equals("Main") || poppedMethod.ShortName.Equals("DUCoverTerminate")) { ses.DumpToDatabase(); bStartMonitoring = false; } }
public override EnterMethodFlags EnterMethod(Method method) { //Console.WriteLine(method.FullName); if (this.methodStack.Count == 0 && !bStartMonitoring) { var assemblyShortname = method.Definition.Module.Assembly.ShortName; if (assemblyShortname == this.currentAssemblyLoc) { //Whereever the main method, it is the assembly under analysis, //since our tool assumes that there is only one assembly var assembly = method.Definition.Module.Assembly; ses.CurrAssembly = assembly; bStartMonitoring = true; } } if (bStartMonitoring) { this.methodStack.Push(method); if (currSEMethodStore != null) this.methodStoreStack.Push(currSEMethodStore); currSEMethodStore = new SEMethodStore(method.FullName); currSEMethodStore.OptionalMethod = method; var tempLastLoadedFields = new SafeList<Field>(); tempLastLoadedFields.AddRange(lastLoadedFields); this.lastLoadedFieldsStack.Push(tempLastLoadedFields); this.lastLoadedFields.Clear(); this.offsetStack.Push(this.currOffset); } return base.EnterMethod(method); // 'true' indicates that we want callbacks for the argument values }