/// <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; } }
public Translator getTranslator(Sink sink, IDictionary<IUnit, IContractProvider> contractProviders, IDictionary<IUnit, PdbReader> pdbReaders) { TraverserFactory factory; if (isWholeProgram) factory= new WholeProgram(); else factory= new CLRSemantics(); // Translator translator= factory.MakeMetadataTraverser(sink, contractProviders, pdbReaders); Translator translator= factory.getTranslator(sink, contractProviders, pdbReaders); return translator; }
static int Main(string[] args) { // populate options with command line args var options = Program.ParseOptions(args); if (options == null) { return(-1); } stopwatch.Start(); using (var host = GetHostFromOptions(options)) { ISet <IAssembly> rootAssemblies = GetRootAssembliesFromOptions(options, host); WholeProgram wholeProgram = new WholeProgram(rootAssemblies, host); string reportPath = "ILGarbageCollectReport"; if (!String.IsNullOrWhiteSpace(options.report)) { reportPath = options.report + @"\" + reportPath; } bool performMark = (options.mode == RunMode.Mark || options.mode == RunMode.MarkAndSweep); bool performSweep = (options.mode == RunMode.Sweep || options.mode == RunMode.MarkAndSweep); if (performMark) { IEnumerable <IMethodReference> entryPoints = GetEntryPointsFromOptions(options, wholeProgram); IEnumerable <IMethodSummarizer> reflectionSummarizers = GetReflectionSummarizersFromOptions(options, wholeProgram); RunRTA(wholeProgram, reflectionSummarizers, entryPoints, reportPath, options.profile); } if (performSweep) { string transformPath = options.transform; TransformProgram(wholeProgram, transformPath, reportPath, options.removal, options.profile); } } Console.WriteLine("Elapsed time: {0}", stopwatch.Elapsed); return(0); }
public ReachabilitySummary SummarizeMethod(IMethodDefinition methodDefinition, WholeProgram wholeProgram) { // if there is an implementation available (e.g. we can get to opcodes) if (methodDefinition.IsExternal == false && methodDefinition.IsAbstract == false) { BytecodeVisitor visitor = new BytecodeVisitor(); // foreach MSIL instruction in the method foreach (var op in methodDefinition.ResolvedMethod.Body.Operations) { visitor.Visit(op); // handle the opcode } return visitor.GetSummary(); } else { return null; } }
public Translator getTranslator(Sink sink, IDictionary <IUnit, IContractProvider> contractProviders, IDictionary <IUnit, PdbReader> pdbReaders) { TraverserFactory factory; if (isWholeProgram) { factory = new WholeProgram(); } else { factory = new CLRSemantics(); } // Translator translator= factory.MakeMetadataTraverser(sink, contractProviders, pdbReaders); Translator translator = factory.getTranslator(sink, contractProviders, pdbReaders); return(translator); }
public RapidTypeAnalysis(WholeProgram wholeProgram, TargetProfile profile) { Contract.Ensures(!this.FinishedAnalysis); this.types = new HashSet <ITypeDefinition>(new TypeDefinitionEqualityComparer()); this.methods = new HashSet <IMethodDefinition>(new MethodDefinitionEqualityComparer()); this.virtualCallsInDemand = new VirtualDispatchDemand(); this.nonvirtualDispatches = new HashSet <IMethodDefinition>(new MethodDefinitionEqualityComparer()); this.fields = new HashSet <IFieldDefinition>(new FieldDefinitionEqualityComparer()); this.constructed = new HashSet <ITypeDefinition>(new TypeDefinitionEqualityComparer()); this.constructedGenericParameters = new HashSet <IGenericParameter>(new TypeDefinitionEqualityComparer()); // Note: we use the interned key as the hashcode, so this set should be deterministic this.worklist = new HashSet <IMethodDefinition>(new MethodDefinitionEqualityComparer()); this.wholeProgram = wholeProgram; this.reflectionSummarizers = new HashSet <IMethodSummarizer>(); this.simpleBytecodeSummarizer = new SimpleBytecodeMethodSummarizer(); this.reachabilityFlowBytecodeSummarizer = new ReachabilityBasedLocalFlowMethodSummarizer(); //systemObjectType = wholeProgram.Host().PlatformType.SystemObject.ResolvedType; // Weak heuristic -- should provide custom host? IAssembly coreAssembly = wholeProgram.HeuristicFindCoreAssemblyForProfile(profile); Contract.Assert(coreAssembly != null); systemObjectType = GarbageCollectHelper.CreateTypeReference(wholeProgram.Host(), coreAssembly, "System.Object").ResolvedType; Contract.Assert(!(systemObjectType is Dummy)); systemObjectFinalizeMethod = TypeHelper.GetMethod(systemObjectType, wholeProgram.Host().NameTable.GetNameFor("Finalize")); Contract.Assert(!(systemObjectFinalizeMethod is Dummy)); methodsRequiringReflectionSummary = new HashSet <IMethodDefinition>(new MethodDefinitionEqualityComparer()); unresolvedReferences = new HashSet <IReference>(new ReferenceEqualityComparer()); unspecializedTypesPassedAsTypeVariables = new HashSet <ITypeDefinition>(new TypeDefinitionEqualityComparer()); }
public RapidTypeAnalysis(WholeProgram wholeProgram, TargetProfile profile) { Contract.Ensures(!this.FinishedAnalysis); this.types = new HashSet<ITypeDefinition>(new TypeDefinitionEqualityComparer()); this.methods = new HashSet<IMethodDefinition>(new MethodDefinitionEqualityComparer()); this.virtualCallsInDemand = new VirtualDispatchDemand(); this.nonvirtualDispatches = new HashSet<IMethodDefinition>(new MethodDefinitionEqualityComparer()); this.fields = new HashSet<IFieldDefinition>(new FieldDefinitionEqualityComparer()); this.constructed = new HashSet<ITypeDefinition>(new TypeDefinitionEqualityComparer()); this.constructedGenericParameters = new HashSet<IGenericParameter>(new TypeDefinitionEqualityComparer()); // Note: we use the interned key as the hashcode, so this set should be deterministic this.worklist = new HashSet<IMethodDefinition>(new MethodDefinitionEqualityComparer()); this.wholeProgram = wholeProgram; this.reflectionSummarizers = new HashSet<IMethodSummarizer>(); this.simpleBytecodeSummarizer = new SimpleBytecodeMethodSummarizer(); this.reachabilityFlowBytecodeSummarizer = new ReachabilityBasedLocalFlowMethodSummarizer(); //systemObjectType = wholeProgram.Host().PlatformType.SystemObject.ResolvedType; // Weak heuristic -- should provide custom host? IAssembly coreAssembly = wholeProgram.HeuristicFindCoreAssemblyForProfile(profile); Contract.Assert(coreAssembly != null); systemObjectType = GarbageCollectHelper.CreateTypeReference(wholeProgram.Host(), coreAssembly, "System.Object").ResolvedType; Contract.Assert(!(systemObjectType is Dummy)); systemObjectFinalizeMethod = TypeHelper.GetMethod(systemObjectType, wholeProgram.Host().NameTable.GetNameFor("Finalize")); Contract.Assert(!(systemObjectFinalizeMethod is Dummy)); methodsRequiringReflectionSummary = new HashSet<IMethodDefinition>(new MethodDefinitionEqualityComparer()); unresolvedReferences = new HashSet<IReference>(new ReferenceEqualityComparer()); unspecializedTypesPassedAsTypeVariables = new HashSet<ITypeDefinition>(new TypeDefinitionEqualityComparer()); }
private static IFieldDefinition LookupFieldWithIdentifier(string identifier, WholeProgram wholeProgram) { WholeProgramSearchQuery query = CreateQueryForIdentifier(identifier); ISet <IFieldDefinition> fields = wholeProgram.FindFieldsMatchingWholeProgramQuery(query); if (fields.Count() == 1) { return(fields.First()); } else if (fields.Count() > 1) { throw new Exception("Couldn't find unique field with identifier " + identifier + " (found " + fields.Count() + ")"); } else { throw new Exception("Couldn't find fields with identifier: " + identifier); } }
private static void TransformProgram(WholeProgram wholeProgram, string transformedBinariesPath, string reportsPath, MethodRemoval methodRemoval, TargetProfile profile) { System.IO.Directory.CreateDirectory(transformedBinariesPath); StubMethodBodyEmitter stubEmitter = GetStubMethodBodyEmitterForProfile(profile, wholeProgram); foreach (IAssembly assembly in wholeProgram.AllAssemblies()) { if (AssemblyShouldBeRewritten(assembly)) { if (assembly.PublicKeyToken.Count() > 0) { Console.WriteLine("Warning: rewriting assembly with a public key token. {0}", assembly); } string outputBinary = transformedBinariesPath + @"\" + Path.GetFileName(assembly.Location); var copy = new MetadataDeepCopier(wholeProgram.Host()).Copy(assembly); DocumentationCommentDefinitionIdStringMap idMap = new DocumentationCommentDefinitionIdStringMap(new IAssembly[] { copy }); AssemblyReport assemblyReport = AssemblyReport.CreateAssemblyReportFromPath(copy, reportsPath, idMap); stopwatch.Start(); RewriteBinary(copy, assemblyReport, wholeProgram.Host(), outputBinary, methodRemoval, stubEmitter); stopwatch.Start(); } else { //Console.WriteLine("Skipping rewrite of of assembly {0}", assembly.Name.Value); } } }
private static RapidTypeAnalysis RunRTA(WholeProgram wholeProgram, IEnumerable <ILGarbageCollect.Summaries.IMethodSummarizer> reflectionSummarizers, IEnumerable <IMethodReference> entryPoints, string reportPath, TargetProfile profile) { var rta = new RapidTypeAnalysis(wholeProgram, profile); rta.ReflectionSummarizers = reflectionSummarizers; Console.WriteLine("Running Rapid Type Analysis with {0} entry points", entryPoints.Count()); rta.Run(entryPoints); stopwatch.Stop(); OutputRTAStatistics(rta, reportPath); return(rta); }
private static StubMethodBodyEmitter GetStubMethodBodyEmitterForProfile(TargetProfile profile, WholeProgram wholeProgram) { StubMethodBodyEmitter emitter; switch (profile) { case TargetProfile.Desktop: emitter = new DotNetDesktopStubMethodBodyEmitter(wholeProgram.Host()); break; case TargetProfile.Phone: emitter = new WindowsPhoneStubMethodBodyEmitter(wholeProgram.Host()); break; default: emitter = new DotNetDesktopStubMethodBodyEmitter(wholeProgram.Host()); break; } return(emitter); }
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); }
private static ISet <ITypeDefinition> LookupTypesMatchingQuery(WholeProgramSearchQuery query, WholeProgram wholeProgram) { ISet <ITypeDefinition> types = wholeProgram.FindTypesMatchingWholeProgramQuery(query); if (types.Count() > 0) { return(types); } else { // Really should have function that turns query into a human readable string throw new Exception("Couldn't find any types matching query: " + query.AssemblySpecifier + "!" + query.DefinitionSpecifier); } }
private static ITypeDefinition LookupExactTypeWithIdentifier(string identifier, WholeProgram wholeProgram) { WholeProgramSearchQuery query = CreateQueryForIdentifier(identifier); ISet <ITypeDefinition> types = LookupTypesMatchingQuery(query, wholeProgram); if (types.Count() == 1) { return(types.First()); } else { throw new Exception("Couldn't find unique type with identifier: " + identifier + " (found " + types.Count() + ")"); } }
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."); } }
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."); } }
abstract public ReachabilitySummary SummarizeMethod(IMethodDefinition methodDefinition, WholeProgram wholeProgram);
private static IEnumerable<IMethodSummarizer> GetReflectionSummarizersFromOptions(ILGarbageCollectorOptions options, WholeProgram wholeProgram) { ISet<IMethodSummarizer> summarizers = DefaultReflectionSummarizers(); string textSummariesPath = options.summaries; if (textSummariesPath != null) { TextFileMethodSummarizer textFileSummarizer = TextFileMethodSummarizer.CreateSummarizerFromPath(textSummariesPath, wholeProgram); summarizers.Add(textFileSummarizer); } return summarizers; }
private static IEnumerable<IMethodReference> GetEntryPointsFromOptions(ILGarbageCollectorOptions options, WholeProgram wholeProgram) { ISet<IEntryPointDetector> entryPointDetectors = new HashSet<IEntryPointDetector>(); bool ignoreMainEntryPoints = false; if (options.entrypoints != null) { entryPointDetectors.Add(new DocCommentFileEntryPointDetector(options.entrypoints)); ignoreMainEntryPoints = true; } if (options.entryattributes != null) { entryPointDetectors.Add(new AttributeFileEntryPointDetector(options.entryattributes)); } // If no entrypoints were directly specified are used, we'll just get the entry points // from the main assemblies. if (!ignoreMainEntryPoints) { entryPointDetectors.Add(new RootAssembliesEntryPointDetector()); } ISet<IMethodReference> entryPoints = new HashSet<IMethodReference>(); foreach (IEntryPointDetector entryPointDetector in entryPointDetectors) { entryPoints.UnionWith(entryPointDetector.GetEntryPoints(wholeProgram)); } if (entryPoints.Count() == 0) { Console.WriteLine("Error: Could not find any entry points."); System.Environment.Exit(-1); } return entryPoints; }
static int Main(string[] args) { // populate options with command line args var options = Program.ParseOptions(args); if (options == null) return -1; stopwatch.Start(); using (var host = GetHostFromOptions(options)) { ISet<IAssembly> rootAssemblies = GetRootAssembliesFromOptions(options, host); WholeProgram wholeProgram = new WholeProgram(rootAssemblies, host); string reportPath = options.report + @"\" + "ILGarbageCollectReport"; bool performMark = (options.mode == RunMode.Mark || options.mode == RunMode.MarkAndSweep); bool performSweep = (options.mode == RunMode.Sweep || options.mode == RunMode.MarkAndSweep); if (performMark) { IEnumerable<IMethodReference> entryPoints = GetEntryPointsFromOptions(options, wholeProgram); IEnumerable<IMethodSummarizer> reflectionSummarizers = GetReflectionSummarizersFromOptions(options, wholeProgram); RunRTA(wholeProgram, reflectionSummarizers, entryPoints, reportPath, options.profile); } if (performSweep) { string transformPath = options.transform; TransformProgram(wholeProgram, transformPath, reportPath, options.removal, options.profile); } } Console.WriteLine("Elapsed time: {0}", stopwatch.Elapsed); return 0; }
private static IEnumerable <IMethodReference> GetEntryPointsFromOptions(ILGarbageCollectorOptions options, WholeProgram wholeProgram) { ISet <IEntryPointDetector> entryPointDetectors = new HashSet <IEntryPointDetector>(); bool ignoreMainEntryPoints = false; if (options.entrypoints != null) { entryPointDetectors.Add(new DocCommentFileEntryPointDetector(options.entrypoints)); ignoreMainEntryPoints = true; } if (options.entryattributes != null) { entryPointDetectors.Add(new AttributeFileEntryPointDetector(options.entryattributes)); } // If no entrypoints were directly specified are used, we'll just get the entry points // from the main assemblies. if (!ignoreMainEntryPoints) { entryPointDetectors.Add(new RootAssembliesEntryPointDetector()); } ISet <IMethodReference> entryPoints = new HashSet <IMethodReference>(); foreach (IEntryPointDetector entryPointDetector in entryPointDetectors) { entryPoints.UnionWith(entryPointDetector.GetEntryPoints(wholeProgram)); } if (entryPoints.Count() == 0) { Console.WriteLine("Error: Could not find any entry points."); System.Environment.Exit(-1); } return(entryPoints); }
private static IEnumerable <IMethodSummarizer> GetReflectionSummarizersFromOptions(ILGarbageCollectorOptions options, WholeProgram wholeProgram) { ISet <IMethodSummarizer> summarizers = DefaultReflectionSummarizers(); string textSummariesPath = options.summaries; if (textSummariesPath != null) { TextFileMethodSummarizer textFileSummarizer = TextFileMethodSummarizer.CreateSummarizerFromPath(textSummariesPath, wholeProgram); summarizers.Add(textFileSummarizer); } return(summarizers); }
public override ReachabilitySummary SummarizeMethod(IMethodDefinition methodDefinition, WholeProgram wholeProgram) { // Console.WriteLine("Running ReachabilityBasedLocalFlowMethodSummarizer on {0}", methodDefinition); ReachabilityStateAbstraction stateAbstraction = new ReachabilityStateAbstraction(); ReachabilityStateInterpreter stateInterpreter = new ReachabilityStateInterpreter(stateAbstraction); var algorithm = new WorkListAlgorithm <ReachabilityStateInterpreter, ReachabilityStateAbstraction, bool>(stateInterpreter); algorithm.RunOnMethod(methodDefinition, wholeProgram.Host()); SimpleBytecodeMethodSummarizer.BytecodeVisitor visitor = new SimpleBytecodeMethodSummarizer.BytecodeVisitor(); foreach (BasicBlock <Instruction> block in algorithm.ControlFlowGraph.AllBlocks) { bool blockIsReachable = algorithm.GetBlockPostState(block); if (blockIsReachable) { foreach (Instruction instruction in block.Instructions) { visitor.Visit(instruction.Operation); } } } return(visitor.GetSummary()); }
public override ReachabilitySummary SummarizeMethod(IMethodDefinition methodDefinition, WholeProgram wholeProgram) { //Console.WriteLine("Running AlwaysTopLocalFlowMethodSummarizer on {0}", methodDefinition); // hack to analyze on Foo<T> rather than Foo // since we need this for data flow // Unfortunately, this makes the CFG barf. Need to revisit later. /* * ITypeReference fullyInstantiatedSpecializedTypeReference; * * if (TypeHelper.TryGetFullyInstantiatedSpecializedTypeReference(methodDefinition.ContainingTypeDefinition, out fullyInstantiatedSpecializedTypeReference)) { * foreach (IMethodDefinition instantiatedMethod in fullyInstantiatedSpecializedTypeReference.ResolvedType.Methods) { * if (GarbageCollectHelper.UnspecializeAndResolveMethodReference(instantiatedMethod).InternedKey == methodDefinition.InternedKey) { * methodDefinition = instantiatedMethod; * break; * } * } * } */ var valueAbstraction = new TypesValueAbstraction(wholeProgram.Host()); var stateInterpreter = new VirtualCallRecordingStateInterpreter <TypesValueAbstraction, ITypeDefinition>(valueAbstraction); var algorithm = new WorkListAlgorithm <VirtualCallRecordingStateInterpreter <TypesValueAbstraction, ITypeDefinition>, LocalsAndOperandsStateAbstraction <TypesValueAbstraction, ITypeDefinition>, LocalsAndOperands <ITypeDefinition> >(stateInterpreter); try { algorithm.RunOnMethod(methodDefinition, wholeProgram.Host()); } catch (Exception e) { if (e.GetType().FullName.Contains("ContractException")) { // Very hokey, but it is what it is. // Sometimes we fail because building the CFG fails, and occasionally // we fail because of something in the analysis. In either event, // we pick ourselves up and fall back on the regular summarization // Need to record statistics on how often this happens. Console.WriteLine("Got contract exception running local flow for " + methodDefinition); return(new SimpleBytecodeMethodSummarizer().SummarizeMethod(methodDefinition, wholeProgram)); } else { throw; } } LocalFlowEnhancedBytecodeVisitor bytecodeVisitor = new LocalFlowEnhancedBytecodeVisitor(); foreach (BasicBlock <Instruction> block in algorithm.ControlFlowGraph.AllBlocks) { foreach (Instruction instruction in block.Instructions) { if (instruction.Operation.OperationCode == OperationCode.Callvirt) { ITypeDefinition valueAtReceiver = algorithm.StateInterpreter.ReceiverValueForVirtualCallInstruction(instruction.Operation); Contract.Assert(valueAtReceiver != null); //t-devinc: handle not resolving method gracefully. IMethodDefinition compileTimeTargetMethod = (instruction.Operation.Value as IMethodReference).ResolvedMethod; // The only way we allow the analysis to return a type that is a supertype of the type being dispatched upon is // if we've gone to top (System.Object). // // This is really just a sanity check. ITypeDefinition compileTimeType = compileTimeTargetMethod.ContainingTypeDefinition; Contract.Assert(valueAtReceiver == wholeProgram.Host().PlatformType.SystemObject.ResolvedType || TypeHelper.Type1DerivesFromOrIsTheSameAsType2(valueAtReceiver, compileTimeType) || (compileTimeType.IsInterface && TypeHelper.Type1ImplementsType2(valueAtReceiver, compileTimeType)) || (valueAtReceiver.IsInterface && compileTimeType == wholeProgram.Host().PlatformType.SystemObject.ResolvedType) ); bytecodeVisitor.NoteReceiverTypeForCallVirtual(valueAtReceiver, instruction.Operation); } } } foreach (IOperation operation in methodDefinition.Body.Operations) { bytecodeVisitor.Visit(operation); } return(bytecodeVisitor.GetSummary()); }
private static RapidTypeAnalysis RunRTA(WholeProgram wholeProgram, IEnumerable<ILGarbageCollect.Summaries.IMethodSummarizer> reflectionSummarizers, IEnumerable<IMethodReference> entryPoints, string reportPath, TargetProfile profile) { var rta = new RapidTypeAnalysis(wholeProgram, profile); rta.ReflectionSummarizers = reflectionSummarizers; Console.WriteLine("Running Rapid Type Analysis with {0} entry points", entryPoints.Count()); rta.Run(entryPoints); stopwatch.Stop(); OutputRTAStatistics(rta, reportPath); return rta; }
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."); } }
private static StubMethodBodyEmitter GetStubMethodBodyEmitterForProfile(TargetProfile profile, WholeProgram wholeProgram) { StubMethodBodyEmitter emitter; switch (profile) { case TargetProfile.Desktop: emitter = new DotNetDesktopStubMethodBodyEmitter(wholeProgram.Host()); break; case TargetProfile.Phone: emitter = new WindowsPhoneStubMethodBodyEmitter(wholeProgram.Host()); break; default: emitter = new DotNetDesktopStubMethodBodyEmitter(wholeProgram.Host()); break; } return emitter; }
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."); } }
public ReachabilitySummary SummarizeMethod(IMethodDefinition methodDefinition, WholeProgram wholeProgram) { ReachabilitySummary summary = null; summariesByMethod.TryGetValue(methodDefinition, out summary); return(summary); }
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."); } }
public TestCompilerResults(IAssembly mainAssembly, IAssembly[] libraryAssemblies, PeReader.DefaultHost host) { this.MainAssembly = mainAssembly; this.Host = host; this.WholeProgram = new WholeProgram(new IAssembly[] { mainAssembly }, host); }
private static ISet <ITypeDefinition> LookupTypesMatchingRegexpIdentifier(string identifier, WholeProgram wholeProgram) { WholeProgramSearchQuery query = CreateQueryForIdentifier(identifier); query.PerformRegexpMatch = true; return(LookupTypesMatchingQuery(query, wholeProgram)); }
static void ConstructWholeProgramForSources(string[] sources, WholeProgramResultDelegate resultDelegate) { // Each source is assumed to refer to all the sources before it CompileSourcesAndRun(sources, ".dll", compilerResult => { WholeProgram wholeProgram = new WholeProgram(new IAssembly[] { compilerResult.MainAssembly }, compilerResult.Host); resultDelegate(compilerResult, wholeProgram); }); }
private static ISet <ITypeDefinition> LookupTypesWithIdentifier(string identifier, WholeProgram wholeProgram) { WholeProgramSearchQuery query = CreateQueryForIdentifier(identifier); ISet <ITypeDefinition> types = wholeProgram.FindTypesMatchingWholeProgramQuery(query); if (types.Count() > 0) { return(types); } else { throw new Exception("Couldn't find type with identifier: " + identifier); } }
private ISet <ReachabilitySummary> RunReflectionSummarizers(IMethodDefinition method, WholeProgram wholeProgram) { ISet <ReachabilitySummary> summaries = new HashSet <ReachabilitySummary>(); foreach (IMethodSummarizer reflectionSummarizer in reflectionSummarizers) { ReachabilitySummary summary = reflectionSummarizer.SummarizeMethod(method, wholeProgram); if (summary != null) { summaries.Add(summary); } } return(summaries); }
/// <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 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); }
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); } }
static void ConstructClassHierarchyForSources(string[] sources, ClassHierarchyResultDelegate resultDelegate) { // Each source is assumed to refer to all the sources before it CompileSourcesAndRun(sources, ".dll", compilerResult => { WholeProgram wholeProgram = new WholeProgram(new IAssembly[] { compilerResult.MainAssembly }, compilerResult.Host); ClassHierarchy classHierarchy = new ClassHierarchy(wholeProgram.AllDefinedTypes(), compilerResult.Host); resultDelegate(compilerResult, classHierarchy); }); }
public ReachabilitySummary SummarizeMethod(IMethodDefinition methodDefinition, WholeProgram wholeProgram) { // if there is an implementation available (e.g. we can get to opcodes) if (methodDefinition.IsExternal == false && methodDefinition.IsAbstract == false) { BytecodeVisitor visitor = new BytecodeVisitor(); // foreach MSIL instruction in the method foreach (var op in methodDefinition.ResolvedMethod.Body.Operations) { visitor.Visit(op); // handle the opcode } return(visitor.GetSummary()); } else { return(null); } }
static void RunRTAOnSources(string[] sources, RTAResultDelegate runDelegate) { //The last source in the array must have the Main entrypoint CompileSourcesAndRun(sources, ".exe", compilerResult => { var mainAssembly = compilerResult.MainAssembly; WholeProgram wholeProgram = new WholeProgram(new IAssembly[] { compilerResult.MainAssembly }, compilerResult.Host); var rta = new RapidTypeAnalysis(wholeProgram, TargetProfile.Desktop); rta.Run(new IMethodDefinition[1] { mainAssembly.EntryPoint.ResolvedMethod }); runDelegate(compilerResult, rta); }); }
private ISet<ReachabilitySummary> RunReflectionSummarizers(IMethodDefinition method, WholeProgram wholeProgram) { ISet<ReachabilitySummary> summaries = new HashSet<ReachabilitySummary>(); foreach (IMethodSummarizer reflectionSummarizer in reflectionSummarizers) { ReachabilitySummary summary = reflectionSummarizer.SummarizeMethod(method, wholeProgram); if (summary != null) { summaries.Add(summary); } } return summaries; }