public override LocalsAndOperands <V> EntryPreState(IMethodDefinition method) { // entry pre-state is empty operand stack // with locals initialized // LocalsAndOperands <V> state = new LocalsAndOperands <V>(); // If method has a this, parameter, it is the first argument if (!method.IsStatic && !method.HasExplicitThisParameter) { ITypeDefinition instantiatedThis = GarbageCollectHelper.InstantiatedTypeIfPossible(method.ContainingTypeDefinition); state.Arguments.Add(ValueAbstraction.GetAbstractValueForType(instantiatedThis)); } foreach (IParameterDefinition parameter in method.Parameters) { state.Arguments.Add(ValueAbstraction.GetAbstractValueForType(parameter.Type.ResolvedType)); } foreach (ILocalDefinition localVariable in method.Body.LocalVariables) { ITypeDefinition typeOfLocal = localVariable.Type.ResolvedType; state.Locals.Add(ValueAbstraction.GetAbstractValueForType(typeOfLocal)); } return(state); }
public ISet <IMethodReference> GetEntryPoints(WholeProgram wholeProgram) { ISet <string> entryPointAttributeIDs = new HashSet <string>(System.IO.File.ReadAllLines(pathToFile)); ISet <IMethodReference> foundEntryPoints = new HashSet <IMethodReference>(); ISet <string> foundEntryPointIDs = new HashSet <string>(); foreach (IMethodDefinition methodDefinition in wholeProgram.AllDefinedMethods()) { foreach (ICustomAttribute attribute in methodDefinition.Attributes) { string attributeDefinitionID = GarbageCollectHelper.GetIDStringForReference(attribute.Type); if (entryPointAttributeIDs.Contains(attributeDefinitionID)) { foundEntryPoints.Add(methodDefinition); foundEntryPointIDs.Add(attributeDefinitionID); } } } // A poor attempt at slightly more humane error-reporting foreach (string desiredEntryPointID in entryPointAttributeIDs) { if (!foundEntryPointIDs.Contains(desiredEntryPointID)) { Console.WriteLine("Couldn't find any entry points with attribute {0}", desiredEntryPointID); Environment.Exit(-1); } } return(foundEntryPoints); }
public DotNetDesktopStubMethodBodyEmitter(IMetadataHost host) : base(host) { this.consoleWriteLine = new Microsoft.Cci.MethodReference(host, GarbageCollectHelper.CreateTypeReference(host, coreAssemblyReference, "System.Console"), CallingConvention.Default, host.PlatformType.SystemVoid, host.NameTable.GetNameFor("WriteLine"), 0, host.PlatformType.SystemString); this.environmentGetStackTrace = new Microsoft.Cci.MethodReference(host, GarbageCollectHelper.CreateTypeReference(host, coreAssemblyReference, "System.Environment"), CallingConvention.Default, host.PlatformType.SystemString, host.NameTable.GetNameFor("get_StackTrace"), 0); this.environmentExit = new Microsoft.Cci.MethodReference(host, GarbageCollectHelper.CreateTypeReference(host, coreAssemblyReference, "System.Environment"), CallingConvention.Default, host.PlatformType.SystemVoid, host.NameTable.GetNameFor("Exit"), 0, host.PlatformType.SystemInt32); }
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."); } }
public WindowsPhoneStubMethodBodyEmitter(IMetadataHost host) : base(host) { this.consoleWriteLine = new Microsoft.Cci.MethodReference(host, GarbageCollectHelper.CreateTypeReference(host, coreAssemblyReference, "System.Console"), CallingConvention.Default, host.PlatformType.SystemVoid, host.NameTable.GetNameFor("WriteLine"), 0, host.PlatformType.SystemString); this.stackTraceConstructor = new Microsoft.Cci.MethodReference(host, GarbageCollectHelper.CreateTypeReference(host, coreAssemblyReference, "System.Diagnostics.StackTrace"), CallingConvention.HasThis, host.PlatformType.SystemVoid, host.NameTable.GetNameFor(".ctor"), 0); this.toString = new Microsoft.Cci.MethodReference(host, host.PlatformType.SystemObject, CallingConvention.HasThis, host.PlatformType.SystemString, host.NameTable.GetNameFor("ToString"), 0); }
public WholeProgram(IEnumerable <IAssembly> rootAssemblies, MetadataReaderHost host) { this.rootAssemblies = new HashSet <IAssembly>(rootAssemblies); this.allAssemblies = GarbageCollectHelper.CloseAndResolveOverReferencedAssemblies(rootAssemblies); this.host = host; }
private void WriteDefinitionIdentifiersToFile(IEnumerable <IDefinition> definitions, string path) { using (StreamWriter outfile = new StreamWriter(path)) { foreach (var definition in definitions) { string definitionID = GarbageCollectHelper.GetIDStringForReference(definition); outfile.WriteLine(definitionID); } } }
public IMethodDefinition FindMethodWithIdentifierInAssembly(string docCommentMethodIdentifier, IAssembly assembly) { // We could be more efficient here, but for now we go with simplicity foreach (IMethodDefinition method in GetAllMethodsInAssembly(assembly)) { if (GarbageCollectHelper.GetIDStringForReference(method) == docCommentMethodIdentifier) { return(method); } } return(null); }
private ITypeDefinition FixupTypeForFlow(ITypeDefinition type) { // If the type is generic but we're not instantiated, we try to instantiate it. // This is required because the CFG is over the completely unspecialized uninstantiated // bytecode while but some instruction *types* (e.g. calls) require instantiate types. // This has got to be slow. // Another alternative would have been to constrcut the CFG over the instantiated type // but this appears to be buggy at the moment. return(GarbageCollectHelper.InstantiatedTypeIfPossible(type)); }
internal override void Visit(IOperation op) { if (op.OperationCode == OperationCode.Callvirt) { IMethodDefinition compileTimeTargetMethod = ResolveMethodReference(op.Value as IMethodReference); if (compileTimeTargetMethod != null && compileTimeTargetMethod.IsVirtual) { // we have a callvirt to a virtual method // so lets use the local flow information //summary.VirtuallyCalledMethods.Add(target); ITypeDefinition tightenedReceiverType; if (receiverTypesByCallvirtOperation.TryGetValue(op, out tightenedReceiverType)) { if (!tightenedReceiverType.IsInterface && TypeHelper.Type1DerivesFromOrIsTheSameAsType2(tightenedReceiverType, compileTimeTargetMethod.ContainingType)) { //Console.WriteLine("Value at receiver is {0}", valueAtReceiver); //Console.WriteLine("Will look up {0} in {1}", compileTimeTargetMethod, tightenedReceiverType); IMethodDefinition tightenedMethod = GarbageCollectHelper.ImplementsInstantiated(tightenedReceiverType, compileTimeTargetMethod); if (tightenedMethod != null) { if (tightenedMethod != compileTimeTargetMethod) { //Console.WriteLine("Tightened method is {0} (from {1})", tightenedMethod, compileTimeTargetMethod); } // Yay, all the flow analysis paid off! GetSummary().VirtuallyCalledMethods.Add(tightenedMethod); //GetSummary().VirtuallyCalledMethods.Add(compileTimeTargetMethod); return; } } } } } // If we've gotten here, we fall back to normal handling base.Visit(op); }
protected void AppendEmitExceptionThrow(ILGenerator generator) { var systemExceptionTypeReference = GarbageCollectHelper.CreateTypeReference(host, coreAssemblyReference, "System.Exception"); IMethodReference exceptionConstructor = new Microsoft.Cci.MethodReference( host, systemExceptionTypeReference, CallingConvention.HasThis, host.PlatformType.SystemVoid, host.NameTable.Ctor, 0); generator.Emit(OperationCode.Newobj, exceptionConstructor); generator.Emit(OperationCode.Throw); }
public ISet <IDefinition> FindDefinitionsMatchingRegularExpressionInAssembly(Regex regex, IAssembly assembly) { // Maybe figure out how to factor out commons parts of this with FindDefinitionWithIdentifierInAssembly? ISet <IDefinition> results = new HashSet <IDefinition>(new DefinitionEqualityComparer()); string regexPattern = regex.ToString(); // We could be more efficient here, but for now we go with simplicity if (regexPattern.StartsWith("M:")) { foreach (IMethodDefinition method in GetAllMethodsInAssembly(assembly)) { if (regex.IsMatch(GarbageCollectHelper.GetIDStringForReference(method))) { results.Add(method); } } } else if (regexPattern.StartsWith("T:")) { foreach (ITypeDefinition type in assembly.GetAllTypes()) { if (regex.IsMatch(GarbageCollectHelper.GetIDStringForReference(type))) { results.Add(type); } } } else if (regexPattern.StartsWith("F:")) { foreach (IFieldDefinition field in GetAllFieldsInAssembly(assembly)) { if (regex.IsMatch(GarbageCollectHelper.GetIDStringForReference(field))) { results.Add(field); } } } else { throw new Exception("Un recognized doc comment definition identifier prefix in: " + regexPattern + " (expected T:, M:, or F:)"); } return(results); }
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."); } }
public IDefinition FindDefinitionWithIdentifierInAssembly(string docCommentIdentifier, IAssembly assembly) { // We could be more efficient here, but for now we go with simplicity if (docCommentIdentifier.StartsWith("M:")) { foreach (IMethodDefinition method in GetAllMethodsInAssembly(assembly)) { if (GarbageCollectHelper.GetIDStringForReference(method) == docCommentIdentifier) { return(method); } } } else if (docCommentIdentifier.StartsWith("T:")) { foreach (ITypeDefinition type in assembly.GetAllTypes()) { if (GarbageCollectHelper.GetIDStringForReference(type) == docCommentIdentifier) { return(type); } } } else if (docCommentIdentifier.StartsWith("F:")) { foreach (IFieldDefinition field in GetAllFieldsInAssembly(assembly)) { if (GarbageCollectHelper.GetIDStringForReference(field) == docCommentIdentifier) { return(field); } } } else { throw new Exception("Un recognized doc comment definition identifier prefix in: " + docCommentIdentifier + " (expected T:, M:, or F:)"); } return(null); }
internal DocumentationCommentDefinitionIdStringMap(IEnumerable <IAssembly> assemblies) { foreach (IAssembly assembly in assemblies) { foreach (ITypeDefinition typeDefinition in assembly.GetAllTypes()) { AddIdStringForDefinition(GarbageCollectHelper.GetIDStringForReference(typeDefinition), typeDefinition); foreach (IMethodDefinition methodDefinition in typeDefinition.Methods) { AddIdStringForDefinition(GarbageCollectHelper.GetIDStringForReference(methodDefinition), methodDefinition); } foreach (IFieldDefinition fieldDefinition in typeDefinition.Fields) { AddIdStringForDefinition(GarbageCollectHelper.GetIDStringForReference(fieldDefinition), fieldDefinition); } } } }
private static bool MethodIsCustomAttributeConstructor(IMethodDefinition methodDefinition) { if (methodDefinition.IsConstructor) { foreach (ITypeDefinition superClass in GarbageCollectHelper.AllSuperClasses(methodDefinition.ContainingTypeDefinition)) { if (superClass is INamedTypeDefinition) { // t-devinc: Could be more principled here, for sure string typeName = superClass.ToString(); if (typeName.Equals("System.Attribute")) { return(true); } } } } return(false); }
internal ClassHierarchy(IEnumerable <ITypeDefinition> allTypes, IMetadataReaderHost host) { this.host = host; foreach (ITypeDefinition typeDefinition in allTypes) { Contract.Assert(GarbageCollectHelper.TypeDefinitionIsUnspecialized(typeDefinition)); foreach (ITypeDefinition superType in GarbageCollectHelper.BaseClasses(typeDefinition)) { NoteClassIsSubClassOfClass(typeDefinition, GarbageCollectHelper.UnspecializeAndResolveTypeReference(superType)); } // We treat every interface type as a subtype of System.Object if (typeDefinition.IsInterface) { //NoteClassIsSubClassOfClass(instantiatedSubType, host.PlatformType.SystemObject.ResolvedType); NoteClassIsSubClassOfClass(typeDefinition, host.PlatformType.SystemObject.ResolvedType); } } }
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."); } }
internal virtual void Visit(IOperation op) { IMethodDefinition target; switch (op.OperationCode) { case OperationCode.Newobj: target = ResolveMethodReference(op.Value as IMethodReference); if (target != null) { Contract.Assert(!(target is Dummy)); if (target.ContainingType is INamedTypeReference) { //Console.WriteLine("Got newobj to {0}", ((INamedTypeReference)target.ContainingType).Name); } ITypeDefinition constructedType = target.ContainingType.ResolvedType; Contract.Assert(GarbageCollectHelper.TypeIsConstructable(constructedType)); summary.ReachableTypes.Add(constructedType); summary.ConstructedTypes.Add(constructedType); summary.NonvirtuallyCalledMethods.Add(target); } break; case OperationCode.Box: // Boxing a struct means a callvirt could possibly // dispatch to one of its methods. ITypeDefinition boxedType = ResolveTypeReference(op.Value as ITypeReference); if (boxedType != null) { // Guard for structs here because box to a reference type is a no-op but allowed and // the Code Contracts instrumentation does this. if (boxedType.IsStruct) { Contract.Assert(GarbageCollectHelper.TypeIsConstructable(boxedType)); summary.ConstructedTypes.Add(boxedType); } } break; case OperationCode.Ldtoken: if (op.Value is IFieldReference) { IFieldDefinition field = ResolveFieldReference(op.Value as IFieldReference); if (field != null) { summary.ReachableFields.Add(field); } } // t-devinc: Need to handle: method and type tokens, as well as generics. // Fully supporting generics here may be very tricky -- this is a place // where operating over specialized bytecode could perhaps help. break; /* Notes on call/callvirt: * * We can get a call on a virtual method when that method is called via 'base' * We can also get a callvirt on a non-virtual method whenever the compiler * feels like it? This seems a little wonky. */ case OperationCode.Ldftn: case OperationCode.Call: target = ResolveMethodReference(op.Value as IMethodReference); if (target != null) { if (target.ContainingType is INamedTypeReference) { //Console.WriteLine("Got call to {0}", target); } summary.NonvirtuallyCalledMethods.Add(target); if (target.Name.Value == "CreateInstance") { // t-devinc: gross, clean this up INamespaceTypeDefinition containingTypeDefinition = target.ContainingTypeDefinition as INamespaceTypeDefinition; if (containingTypeDefinition != null && containingTypeDefinition.Name.Value == "Activator") { if (containingTypeDefinition.ContainingNamespace.Name.Value == "System") { IGenericMethodInstance targetAsGenericMethodInstance = target as IGenericMethodInstance; if (targetAsGenericMethodInstance != null) { // We have a call to 'new T()'; ITypeDefinition definitionForT = targetAsGenericMethodInstance.GenericArguments.First().ResolvedType; summary.ConstructedTypeParameters.Add((IGenericParameter)definitionForT); } } } } } break; case OperationCode.Ldvirtftn: case OperationCode.Callvirt: target = ResolveMethodReference(op.Value as IMethodReference); if (target != null) { if (target.ContainingType is INamedTypeReference) { //Console.WriteLine("Got callvirt to {0}", target); } if (target.IsVirtual) { summary.VirtuallyCalledMethods.Add(target); } else { // In its infinite wisdom, sometimes the compiler gives us a callvirt on a non-virtual method summary.NonvirtuallyCalledMethods.Add(target); } } break; case OperationCode.Ldfld: case OperationCode.Ldflda: case OperationCode.Ldsfld: case OperationCode.Ldsflda: /* For now we treat loads and stores as the same -- we'll want to be smarter about this in the future */ case OperationCode.Stfld: case OperationCode.Stsfld: IFieldDefinition fieldDefinition = ResolveFieldReference(op.Value as IFieldReference); if (fieldDefinition != null) { summary.ReachableTypes.Add(fieldDefinition.ContainingTypeDefinition); summary.ReachableFields.Add(fieldDefinition); } break; default: break; } }
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); } }