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.");
            }
        }
示例#2
0
        /// <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();
 }
 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;
    }