private static void InterpretCallAny(ReachabilitySummary summary, TypeSpecifier typeSpecifier, WholeProgram wholeProgram) { if (summary != null) { foreach (ITypeDefinition type in LookupTypesWithSpecifier(typeSpecifier, wholeProgram)) { // Note, for now this only looks at methods directly defined on that type // not on any methods defined on super types (and inherited). // This is probably not what we really want to expose to the user. foreach (IMethodDefinition method in type.Methods) { if (!method.IsAbstract) { summary.NonvirtuallyCalledMethods.Add(method); // If there is a constructor, we treat the type as constructed if (method.IsConstructor && GarbageCollectHelper.TypeIsConstructable(type)) { summary.ConstructedTypes.Add(type); } } } } } else { throw new Exception("Cannot call any outside of a summarized method."); } }
/// <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 methodDefinition, WholeProgram wholeProgram) { ReachabilitySummary summary = null; summariesByMethod.TryGetValue(methodDefinition, out summary); 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 void MarkNonPrivateConstructorsReachableForType(ReachabilitySummary summary, ITypeDefinition type) { foreach (IMethodDefinition method in type.Methods) { if (method.IsConstructor && (method.Visibility != TypeMemberVisibility.Private)) { summary.NonvirtuallyCalledMethods.Add(method); } } }
private static void InterpretWriteField(ReachabilitySummary summary, string methodIdentifier, WholeProgram wholeProgram) { if (summary != null) { IFieldDefinition field = LookupFieldWithIdentifier(methodIdentifier, wholeProgram); summary.ReachableFields.Add(field); } else { throw new Exception("Cannot use 'write' field outside of a summarized method."); } }
private static void InterpretCallVirtual(ReachabilitySummary summary, string methodIdentifier, WholeProgram wholeProgram) { if (summary != null) { IMethodDefinition method = LookupMethodWithIdentifier(methodIdentifier, wholeProgram); summary.VirtuallyCalledMethods.Add(method); } else { throw new Exception("Cannot call virtual outside of a summarized method."); } }
private static void InterpretConstructAttributes(ReachabilitySummary summary, string fieldIdentifier, WholeProgram wholeProgram) { if (summary != null) { // For now we assume the argument is a field -- we really should support types and methods too IFieldDefinition fieldWithAttributes = LookupFieldWithIdentifier(fieldIdentifier, wholeProgram); foreach (ICustomAttribute customAttribute in fieldWithAttributes.Attributes) { IMethodDefinition constructorDefinition = GarbageCollectHelper.UnspecializeAndResolveMethodReference(customAttribute.Constructor); ITypeDefinition constructorType = constructorDefinition.ContainingTypeDefinition; // Mark attribute constructor reachable summary.NonvirtuallyCalledMethods.Add(constructorDefinition); // Mark named argument property setters reachable foreach (IMetadataNamedArgument namedArgument in customAttribute.NamedArguments) { IName setterName = wholeProgram.Host().NameTable.GetNameFor("set_" + namedArgument.ArgumentName.Value); IMethodDefinition setterMethod = TypeHelper.GetMethod(constructorType, setterName, namedArgument.ArgumentValue.Type); if (setterMethod != Dummy.Method) { // We treat this as a non-virtual call because we know the exact runtime-type of the attribute summary.NonvirtuallyCalledMethods.Add(setterMethod); } else { // Note this won't find a property defined in a super class of the attribute (unsound). // We'll want to fix this if try to generalize this code to handle arbitrary attributes throw new Exception("Couldn't find setter " + setterName + " for type " + namedArgument.ArgumentValue.Type + " in " + constructorType); } } } } else { throw new Exception("Cannot construct subtypes outside of a summarized method."); } }
private static void InterpretConstruct(ReachabilitySummary summary, TypeSpecifier typeSpecifier, WholeProgram wholeProgram) { if (summary != null) { foreach (ITypeDefinition typeToConstruct in LookupTypesWithSpecifier(typeSpecifier, wholeProgram)) { if (GarbageCollectHelper.TypeIsConstructable(typeToConstruct)) { summary.ConstructedTypes.Add(typeToConstruct); // now we mark ALL the non-private constructors as reachable. This is perhaps too imprecise // an alternative would be to allow the user to specify the constructor signature. MarkNonPrivateConstructorsReachableForType(summary, typeToConstruct); } } } else { throw new Exception("Cannot construct type outside of a summarized method."); } }
public static TextFileMethodSummarizer CreateSummarizerFromPath(string path, WholeProgram wholeProgram) { TextFileMethodSummarizer summarizer = new TextFileMethodSummarizer(); ReachabilitySummary summaryForCurrentMethod = null; foreach (string line in System.IO.File.ReadAllLines(path)) { string trimmedLine = line.Trim(); if (trimmedLine == "" || trimmedLine.StartsWith("#")) { continue; } SummarizeCommand command = ParseCommand(trimmedLine); switch (command.Operation) { case SummarizeOperation.Summarize: summaryForCurrentMethod = new ReachabilitySummary(); summarizer.summariesByMethod[LookupMethodWithIdentifier((string)command.Argument, wholeProgram)] = summaryForCurrentMethod; break; case SummarizeOperation.Construct: InterpretConstruct(summaryForCurrentMethod, (TypeSpecifier)command.Argument, wholeProgram); break; case SummarizeOperation.ConstructAttributes: InterpretConstructAttributes(summaryForCurrentMethod, (string)command.Argument, wholeProgram); break; case SummarizeOperation.Call: InterpretCall(summaryForCurrentMethod, (string)command.Argument, wholeProgram); break; case SummarizeOperation.CallVirtual: InterpretCallVirtual(summaryForCurrentMethod, (string)command.Argument, wholeProgram); break; // We should really introduce a notion of a method specifier analogous to TypeSpecifier // that specifies a method, rather than have these separate operations for different ways to // specify methods case SummarizeOperation.CallAnyPublic: InterpretCallAnyPublic(summaryForCurrentMethod, (TypeSpecifier)command.Argument, wholeProgram); break; case SummarizeOperation.CallAny: InterpretCallAny(summaryForCurrentMethod, (TypeSpecifier)command.Argument, wholeProgram); break; case SummarizeOperation.ReadField: InterpretReadField(summaryForCurrentMethod, (string)command.Argument, wholeProgram); break; case SummarizeOperation.WriteField: InterpretWriteField(summaryForCurrentMethod, (string)command.Argument, wholeProgram); break; default: throw new Exception("Unhandled summarize command: " + command.Operation + " " + command.Argument); } } return(summarizer); }
private bool IsReflectionSummaryProbablyNeeded(ReachabilitySummary bytecodeSummary, IMethodDefinition containingMethod) { // Note we only get the compile-time targets for virtually called methods here. // This is not right; but we're really just using it as a heuristic to help debugging. // If a non-system class calls a reflection class, heuristically we probably need a summary // t-devinc: ToString(): gross if (!containingMethod.ContainingType.ToString().Contains("System")) { foreach (IMethodDefinition calledMethod in bytecodeSummary.NonvirtuallyCalledMethods.Concat(bytecodeSummary.VirtuallyCalledMethods)) { if ( calledMethod.ContainingType.ToString().Contains("System.Reflection") || calledMethod.ContainingType.ToString().Contains("System.Activator") || calledMethod.ContainingType.ToString().Contains("System.Xml.Serialization.XmlSerializer")) { //Console.WriteLine("{0} calls reflection method {1}", containingMethod, calledMethod); return true; } } } return false; }
public void ProcessSummary(ReachabilitySummary summary, IMethodDefinition summarizedMethod) { Contract.Requires(GarbageCollectHelper.MethodDefinitionIsUnspecialized(summarizedMethod)); foreach (IMethodDefinition nonvirtuallyCalledMethod in summary.NonvirtuallyCalledMethods) { NoteGenericParameterFlowForMethod(nonvirtuallyCalledMethod); IMethodDefinition unspecializedMethod = GarbageCollectHelper.UnspecializeAndResolveMethodReference(nonvirtuallyCalledMethod); analysisReasons.NoteNonVirtualDispatchReachableForReason(nonvirtuallyCalledMethod, analysisReasons.DispatchReachedBecauseContainingMethodWasReached(summarizedMethod)); if (nonvirtualDispatches.Add(unspecializedMethod)) { MethodReachedReason reason = analysisReasons.MethodReachedByDispatchAgainstNonVirtualMethod(unspecializedMethod); NotePotentialNonVirtualMethodReachedForReason(unspecializedMethod, reason); } } foreach (IMethodDefinition virtuallyCalledMethod in summary.VirtuallyCalledMethods) { NoteGenericParameterFlowForMethod(virtuallyCalledMethod); IMethodDefinition unspecializedMethod = GarbageCollectHelper.UnspecializeAndResolveMethodReference(virtuallyCalledMethod); analysisReasons.NoteVirtualDispatchReachableForReason(unspecializedMethod, analysisReasons.DispatchReachedBecauseContainingMethodWasReached(summarizedMethod)); NoteVirtualDispatch(unspecializedMethod); } foreach (ITypeDefinition reachableType in summary.ReachableTypes) { TypeUseFound(GarbageCollectHelper.UnspecializeAndResolveTypeReference(reachableType)); } foreach (ITypeDefinition constructedType in summary.ConstructedTypes) { ITypeDefinition unspecializedConstructedType = GarbageCollectHelper.UnspecializeAndResolveTypeReference(constructedType); ConstructionFoundWithReason(unspecializedConstructedType, analysisReasons.TypeConstructedBecauseAllocatingMethodReached(summarizedMethod)); } foreach (IFieldDefinition reachableField in summary.ReachableFields) { fields.Add(GarbageCollectHelper.UnspecializeAndResolveFieldReference(reachableField)); } foreach (IGenericParameter genericParameter in summary.ConstructedTypeParameters) { NoteTypeVariableConstructed(genericParameter); } unresolvedReferences.UnionWith(summary.UnresolvedReferences); }
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); } }
internal BytecodeVisitor() { summary = new ReachabilitySummary(); }
/// <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; }