Beispiel #1
0
        public void find()
        {
            var additionalTypes = new string[] {
                "System.IntPtr",
//				"System.Reflection.Assembly",		//TODO: Not in unknown DNR version with jitter support
            };
            var checkedMethods = new Dictionary <MethodReferenceAndDeclaringTypeKey, bool>();
            var callCounter    = new CallCounter();
            int typesLeft      = 30;

            foreach (var type in module.GetTypes())
            {
                var cctor = DotNetUtils.getMethod(type, ".cctor");
                if (cctor == null || cctor.Body == null)
                {
                    continue;
                }
                if (typesLeft-- <= 0)
                {
                    break;
                }

                foreach (var method in DotNetUtils.getCalledMethods(module, cctor))
                {
                    var key = new MethodReferenceAndDeclaringTypeKey(method);
                    if (!checkedMethods.ContainsKey(key))
                    {
                        checkedMethods[key] = false;
                        if (method.DeclaringType.BaseType == null || method.DeclaringType.BaseType.FullName != "System.Object")
                        {
                            continue;
                        }
                        if (!DotNetUtils.isMethod(method, "System.Void", "()"))
                        {
                            continue;
                        }
                        if (!encryptedResource.couldBeResourceDecrypter(method, additionalTypes))
                        {
                            continue;
                        }
                        checkedMethods[key] = true;
                    }
                    else if (!checkedMethods[key])
                    {
                        continue;
                    }
                    callCounter.add(method);
                }
            }

            encryptedResource.Method = (MethodDefinition)callCounter.most();
        }
Beispiel #2
0
        void initializeInterfaceMethods(MethodNameGroups groups)
        {
            initializeAllInterfaces();

            if (TypeDefinition.IsInterface)
            {
                return;
            }

            //--- Partition II 12.2 Implementing virtual methods on interfaces:
            //--- The VES shall use the following algorithm to determine the appropriate
            //--- implementation of an interface's virtual abstract methods:
            //---
            //--- * If the base class implements the interface, start with the same virtual methods
            //---	that it provides; otherwise, create an interface that has empty slots for all
            //---	virtual functions.
            // Done. See initializeAllInterfaces().

            var methodsDict = new Dictionary <MethodReferenceKey, MethodDef>();

            //--- * If this class explicitly specifies that it implements the interface (i.e., the
            //---	interfaces that appear in this class‘ InterfaceImpl table, §22.23)
            //---	* If the class defines any public virtual newslot methods whose name and
            //---	  signature match a virtual method on the interface, then use these new virtual
            //---	  methods to implement the corresponding interface method.
            if (interfaces.Count > 0)
            {
                methodsDict.Clear();
                foreach (var method in methods.getValues())
                {
                    if (!method.isPublic() || !method.isVirtual() || !method.isNewSlot())
                    {
                        continue;
                    }
                    methodsDict[new MethodReferenceKey(method.MethodDefinition)] = method;
                }

                foreach (var ifaceInfo in interfaces)
                {
                    foreach (var methodsList in ifaceInfo.typeDef.virtualMethodInstances.getMethods())
                    {
                        if (methodsList.Count != 1)                             // Never happens
                        {
                            throw new ApplicationException("Interface with more than one method in the list");
                        }
                        var methodInst  = methodsList[0];
                        var ifaceMethod = methodInst.origMethodDef;
                        if (!ifaceMethod.isVirtual())
                        {
                            continue;
                        }
                        var       ifaceMethodReference = MethodReferenceInstance.make(methodInst.methodReference, ifaceInfo.typeReference as GenericInstanceType);
                        MethodDef classMethod;
                        var       key = new MethodReferenceKey(ifaceMethodReference);
                        if (!methodsDict.TryGetValue(key, out classMethod))
                        {
                            continue;
                        }
                        interfaceMethodInfos.addMethod(ifaceInfo, ifaceMethod, classMethod);
                    }
                }
            }

            //--- * If there are any virtual methods in the interface that still have empty slots,
            //---	see if there are any public virtual methods, but not public virtual newslot
            //---	methods, available on this class (directly or inherited) having the same name
            //---	and signature, then use these to implement the corresponding methods on the
            //---	interface.
            methodsDict.Clear();
            foreach (var methodInstList in virtualMethodInstances.getMethods())
            {
                // This class' method is at the end
                for (int i = methodInstList.Count - 1; i >= 0; i--)
                {
                    var classMethod = methodInstList[i];
                    // These methods are guaranteed to be virtual.
                    // We should allow newslot methods, despite what the official doc says.
                    if (!classMethod.origMethodDef.isPublic())
                    {
                        continue;
                    }
                    methodsDict[new MethodReferenceKey(classMethod.methodReference)] = classMethod.origMethodDef;
                    break;
                }
            }
            foreach (var ifaceInfo in allImplementedInterfaces.Keys)
            {
                foreach (var methodsList in ifaceInfo.typeDef.virtualMethodInstances.getMethods())
                {
                    if (methodsList.Count != 1)                         // Never happens
                    {
                        throw new ApplicationException("Interface with more than one method in the list");
                    }
                    var ifaceMethod = methodsList[0].origMethodDef;
                    if (!ifaceMethod.isVirtual())
                    {
                        continue;
                    }
                    var       ifaceMethodRef = MethodReferenceInstance.make(ifaceMethod.MethodDefinition, ifaceInfo.typeReference as GenericInstanceType);
                    MethodDef classMethod;
                    var       key = new MethodReferenceKey(ifaceMethodRef);
                    if (!methodsDict.TryGetValue(key, out classMethod))
                    {
                        continue;
                    }
                    interfaceMethodInfos.addMethodIfEmpty(ifaceInfo, ifaceMethod, classMethod);
                }
            }

            //--- * Apply all MethodImpls that are specified for this class, thereby placing
            //---	explicitly specified virtual methods into the interface in preference to those
            //---	inherited or chosen by name matching.
            methodsDict.Clear();
            var ifaceMethodsDict = new Dictionary <MethodReferenceAndDeclaringTypeKey, MethodDef>();

            foreach (var ifaceInfo in allImplementedInterfaces.Keys)
            {
                var git = ifaceInfo.typeReference as GenericInstanceType;
                foreach (var ifaceMethod in ifaceInfo.typeDef.methods.getValues())
                {
                    MethodReference ifaceMethodReference = ifaceMethod.MethodDefinition;
                    if (git != null)
                    {
                        ifaceMethodReference = simpleClone(ifaceMethod.MethodDefinition, git);
                    }
                    ifaceMethodsDict[new MethodReferenceAndDeclaringTypeKey(ifaceMethodReference)] = ifaceMethod;
                }
            }
            foreach (var classMethod in methods.getValues())
            {
                if (!classMethod.isVirtual())
                {
                    continue;
                }
                foreach (var overrideMethod in classMethod.MethodDefinition.Overrides)
                {
                    MethodDef ifaceMethod;
                    var       key = new MethodReferenceAndDeclaringTypeKey(overrideMethod);
                    if (!ifaceMethodsDict.TryGetValue(key, out ifaceMethod))
                    {
                        // We couldn't find the interface method (eg. interface not resolved) or
                        // it overrides a base class method, and not an interface method.
                        continue;
                    }

                    interfaceMethodInfos.addMethod(overrideMethod.DeclaringType, ifaceMethod, classMethod);
                }
            }

            //--- * If the current class is not abstract and there are any interface methods that
            //---	still have empty slots, then the program is invalid.
            // Check it anyway. C# requires a method, even if it's abstract. I don't think anyone
            // writes pure CIL assemblies.
            foreach (var info in interfaceMethodInfos.AllInfos)
            {
                foreach (var pair in info.IfaceMethodToClassMethod)
                {
                    if (pair.Value != null)
                    {
                        continue;
                    }
                    if (!resolvedAllInterfaces() || !resolvedBaseClasses())
                    {
                        continue;
                    }
                    // Ignore if COM class
                    if (!TypeDefinition.IsImport &&
                        !hasAttribute("System.Runtime.InteropServices.ComImportAttribute") &&
                        !hasAttribute("System.Runtime.InteropServices.TypeLibTypeAttribute"))
                    {
                        Log.w("Could not find interface method {0} ({1:X8}). Type: {2} ({3:X8})",
                              Utils.removeNewlines(pair.Key.methodDef.MethodDefinition),
                              pair.Key.methodDef.MethodDefinition.MetadataToken.ToInt32(),
                              Utils.removeNewlines(TypeDefinition),
                              TypeDefinition.MetadataToken.ToInt32());
                    }
                }
            }

            foreach (var info in interfaceMethodInfos.AllInfos)
            {
                foreach (var pair in info.IfaceMethodToClassMethod)
                {
                    if (pair.Value == null)
                    {
                        continue;
                    }
                    if (pair.Key.methodDef.MethodDefinition.Name != pair.Value.MethodDefinition.Name)
                    {
                        continue;
                    }
                    groups.same(pair.Key.methodDef, pair.Value);
                }
            }
        }