/// <summary> /// Finds all the com objects in a given namespace and marks the methods of their subclasses as reachable. /// /// Perhaps too blunt. /// </summary> /// <param name="wholeProgram"></param> /// <param name="namespacePrefix"></param> /// <returns></returns> internal static ReachabilitySummary COMSummary(WholeProgram wholeProgram, String namespacePrefix) { // The ToString() here is probably not the best idea. IEnumerable <ITypeDefinition> comInterfaces = wholeProgram.AllDefinedTypes().Where(type => type.IsComObject && type.IsInterface && type.ToString().StartsWith("Microsoft.Cci")); ReachabilitySummary summary = new ReachabilitySummary(); foreach (ITypeDefinition comInterface in comInterfaces) { summary.ReachableTypes.Add(comInterface); foreach (ITypeDefinition subtype in wholeProgram.ClassHierarchy().AllSubClassesOfClass(comInterface)) { summary.ConstructedTypes.Add(subtype); foreach (IMethodDefinition method in subtype.Methods) { summary.NonvirtuallyCalledMethods.Add(method); } } } return(summary); }
public ReachabilitySummary SummarizeMethod(IMethodDefinition method, WholeProgram wholeProgram) { if (method.IsExternal == false && method.IsAbstract == false) { ReachabilitySummary summary = new ReachabilitySummary(); IMethodDefinition target; // foreach MSIL instruction in the method foreach (var op in method.Body.Operations) { switch (op.OperationCode) { // non virtual method calls: just add static type case OperationCode.Newobj: case OperationCode.Call: case OperationCode.Calli: target = (op.Value as IMethodReference).ResolvedMethod; summary.NonvirtuallyCalledMethods.Add(target); break; case OperationCode.Ldvirtftn: case OperationCode.Callvirt: target = (op.Value as IMethodReference).ResolvedMethod; if (target.IsVirtual == false) { summary.NonvirtuallyCalledMethods.Add(target); } else { ITypeDefinition typeDefiningTarget = target.ContainingTypeDefinition; IMethodDefinition targetUnspecialized = GarbageCollectHelper.UnspecializeAndResolveMethodReference(op.Value as IMethodReference); // find all possible implementations of virtual call foreach (ITypeDefinition subType in new ITypeDefinition[] { typeDefiningTarget }.Concat(wholeProgram.ClassHierarchy().AllSubClassesOfClass(typeDefiningTarget))) { if (GarbageCollectHelper.TypeIsConstructable(subType)) { // walk class hierarchy from subType up to (including) typeDefiningTarget, looking for targetUnspecialized. ICollection<IMethodDefinition> implementationsOfMethodDefinitionForSubType = GarbageCollectHelper.Implements(subType, typeDefiningTarget, targetUnspecialized); // we have to have found at least 1 implementation Contract.Assert(implementationsOfMethodDefinitionForSubType.Count() > 0); // add all of them as virtually called methods foreach (IMethodDefinition implementationOfTarget in implementationsOfMethodDefinitionForSubType) { summary.VirtuallyCalledMethods.Add(implementationOfTarget); } } } } break; default: break; } } return summary; } else { return null; } }
private static ISet <ITypeDefinition> LookupTypesWithSpecifier(TypeSpecifier specifier, WholeProgram wholeProgram) { HashSet <ITypeDefinition> result = new HashSet <ITypeDefinition>(new TypeDefinitionEqualityComparer()); string typeIdentifier = specifier.TypeIdentifier; switch (specifier.Kind) { case TypeSpecifierKind.Exactly: result.Add(LookupExactTypeWithIdentifier(typeIdentifier, wholeProgram)); break; case TypeSpecifierKind.Subtypes: // t-devinc: We really out to change this to include the type itself, not just all of its proper subtypes result.UnionWith(wholeProgram.ClassHierarchy().AllSubClassesOfClass(LookupExactTypeWithIdentifier(typeIdentifier, wholeProgram))); break; case TypeSpecifierKind.Matches: return(LookupTypesMatchingRegexpIdentifier(typeIdentifier, wholeProgram)); } return(result); }
public ReachabilitySummary SummarizeMethod(IMethodDefinition method, WholeProgram wholeProgram) { if (method.IsExternal == false && method.IsAbstract == false) { ReachabilitySummary summary = new ReachabilitySummary(); IMethodDefinition target; // foreach MSIL instruction in the method foreach (var op in method.Body.Operations) { switch (op.OperationCode) { // non virtual method calls: just add static type case OperationCode.Newobj: case OperationCode.Call: case OperationCode.Calli: target = (op.Value as IMethodReference).ResolvedMethod; summary.NonvirtuallyCalledMethods.Add(target); break; case OperationCode.Ldvirtftn: case OperationCode.Callvirt: target = (op.Value as IMethodReference).ResolvedMethod; if (target.IsVirtual == false) { summary.NonvirtuallyCalledMethods.Add(target); } else { ITypeDefinition typeDefiningTarget = target.ContainingTypeDefinition; IMethodDefinition targetUnspecialized = GarbageCollectHelper.UnspecializeAndResolveMethodReference(op.Value as IMethodReference); // find all possible implementations of virtual call foreach (ITypeDefinition subType in new ITypeDefinition[] { typeDefiningTarget }.Concat(wholeProgram.ClassHierarchy().AllSubClassesOfClass(typeDefiningTarget))) { if (GarbageCollectHelper.TypeIsConstructable(subType)) { // walk class hierarchy from subType up to (including) typeDefiningTarget, looking for targetUnspecialized. ICollection <IMethodDefinition> implementationsOfMethodDefinitionForSubType = GarbageCollectHelper.Implements(subType, typeDefiningTarget, targetUnspecialized); // we have to have found at least 1 implementation Contract.Assert(implementationsOfMethodDefinitionForSubType.Count() > 0); // add all of them as virtually called methods foreach (IMethodDefinition implementationOfTarget in implementationsOfMethodDefinitionForSubType) { summary.VirtuallyCalledMethods.Add(implementationOfTarget); } } } } break; default: break; } } return(summary); } else { return(null); } }
private void NoteVirtualDispatch(IMethodDefinition methodDispatchedUpon) { Contract.Requires(methodDispatchedUpon != null); Contract.Requires(!(methodDispatchedUpon is Dummy)); Contract.Requires(GarbageCollectHelper.MethodDefinitionIsUnspecialized(methodDispatchedUpon)); Contract.Requires(methodDispatchedUpon.IsVirtual); Contract.Ensures(VirtualMethodIsInDemand(methodDispatchedUpon)); //Console.WriteLine("VirtCallFound on {0} of type {1}", methodDefinition, methodDefinition.GetType()); bool virtualMethodIsAlreadyKnown = VirtualMethodIsInDemand(methodDispatchedUpon); MarkVirtualMethodAsInDemand(methodDispatchedUpon); if (virtualMethodIsAlreadyKnown) { return; } // The code below this point is called only the first time we learn that // someone has dispatched against this method. //Console.WriteLine("{0} has {1} derived methods", methodDefinition, this.callgraph.GetAllDerivedMethods(methodDefinition).ToArray().Length); ITypeDefinition typeDefiningM = methodDispatchedUpon.ContainingTypeDefinition; this.TypeUseFound(typeDefiningM); // t-devinc: clean this up foreach (ITypeDefinition subType in new ITypeDefinition[] { typeDefiningM }.Concat(wholeProgram.ClassHierarchy().AllSubClassesOfClass(typeDefiningM))) { if (GarbageCollectHelper.TypeIsConstructable(subType) && ((subType.IsStruct || constructed.Contains(subType)))) { ICollection <IMethodDefinition> implementationsOfMethodDefinitionForSubType = GarbageCollectHelper.Implements(subType, typeDefiningM, methodDispatchedUpon); Contract.Assert(implementationsOfMethodDefinitionForSubType.Count() > 0); foreach (IMethodDefinition implementationOfM in implementationsOfMethodDefinitionForSubType) { NoteDispatch(methodDispatchedUpon, GarbageCollectHelper.UnspecializeAndResolveMethodReference(implementationOfM), subType); } } } }
/// <summary> /// Finds all the com objects in a given namespace and marks the methods of their subclasses as reachable. /// /// Perhaps too blunt. /// </summary> /// <param name="wholeProgram"></param> /// <param name="namespacePrefix"></param> /// <returns></returns> internal static ReachabilitySummary COMSummary(WholeProgram wholeProgram, String namespacePrefix) { // The ToString() here is probably not the best idea. IEnumerable<ITypeDefinition> comInterfaces = wholeProgram.AllDefinedTypes().Where(type => type.IsComObject && type.IsInterface && type.ToString().StartsWith("Microsoft.Cci")); ReachabilitySummary summary = new ReachabilitySummary(); foreach (ITypeDefinition comInterface in comInterfaces) { summary.ReachableTypes.Add(comInterface); foreach (ITypeDefinition subtype in wholeProgram.ClassHierarchy().AllSubClassesOfClass(comInterface)) { summary.ConstructedTypes.Add(subtype); foreach (IMethodDefinition method in subtype.Methods) { summary.NonvirtuallyCalledMethods.Add(method); } } } return summary; }