예제 #1
0
        void instantiateVirtualMembers(MethodNameScopes scopes)
        {
            if (!TypeDefinition.IsInterface) {
                if (baseType != null)
                    virtualMethodInstances.initializeFrom(baseType.typeDef.virtualMethodInstances, baseType.typeReference as GenericInstanceType);

                // Figure out which methods we override in the base class
                foreach (var methodDef in methods.getValues()) {
                    if (!methodDef.isVirtual() || methodDef.isNewSlot())
                        continue;
                    var methodInstList = virtualMethodInstances.lookup(methodDef.MethodDefinition);
                    if (methodInstList == null)
                        continue;
                    foreach (var methodInst in methodInstList)
                        scopes.same(methodDef, methodInst.origMethodDef);
                }
            }

            foreach (var methodDef in methods.getValues()) {
                if (!methodDef.isVirtual())
                    continue;
                virtualMethodInstances.add(new MethodInst(methodDef, methodDef.MethodDefinition));
            }
        }
예제 #2
0
        public void initializeVirtualMembers(MethodNameScopes scopes, IResolver resolver)
        {
            if (initializeVirtualMembersCalled)
                return;
            initializeVirtualMembersCalled = true;

            foreach (var iface in interfaces)
                iface.typeDef.initializeVirtualMembers(scopes, resolver);
            if (baseType != null)
                baseType.typeDef.initializeVirtualMembers(scopes, resolver);

            foreach (var methodDef in methods.getValues()) {
                if (methodDef.isVirtual())
                    scopes.add(methodDef);
            }

            instantiateVirtualMembers(scopes);
            initializeInterfaceMethods(scopes);
        }
예제 #3
0
        void initializeInterfaceMethods(MethodNameScopes scopes)
        {
            if (baseType != null)
                overrideMethods = new Dictionary<MethodDef, bool>(baseType.typeDef.overrideMethods);
            else
                overrideMethods = new Dictionary<MethodDef, bool>();

            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;
                    }

                    var oldMethod = interfaceMethodInfos.addMethod(overrideMethod.DeclaringType, ifaceMethod, classMethod);
                    if (oldMethod != classMethod)
                        overrideMethods[classMethod] = true;
                }
            }

            //--- * 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.MethodDefinition),
                                pair.Key.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 (overrideMethods.ContainsKey(pair.Value))
                        continue;
                    scopes.same(pair.Key, pair.Value);
                }
            }
        }
예제 #4
0
        void prepareRenameMemberDefinitions(MethodNameScopes scopes)
        {
            Log.v("Renaming member definitions #1");

            prepareRenameEntryPoints();

            var virtualMethods = new ScopeHelper(memberInfos, modules.AllTypes);
            var ifaceMethods = new ScopeHelper(memberInfos, modules.AllTypes);
            var propMethods = new ScopeHelper(memberInfos, modules.AllTypes);
            var eventMethods = new ScopeHelper(memberInfos, modules.AllTypes);
            foreach (var scope in getSorted(scopes)) {
                if (scope.hasNonRenamableMethod())
                    continue;
                else if (scope.hasGetterOrSetterPropertyMethod() && getPropertyMethodType(scope.Methods[0]) != PropertyMethodType.Other)
                    propMethods.add(scope);
                else if (scope.hasAddRemoveOrRaiseEventMethod())
                    eventMethods.add(scope);
                else if (scope.hasInterfaceMethod())
                    ifaceMethods.add(scope);
                else
                    virtualMethods.add(scope);
            }

            var prepareHelper = new PrepareHelper(memberInfos, modules.AllTypes);
            prepareHelper.prepare((info) => info.prepareRenameMembers());

            prepareHelper.prepare((info) => info.prepareRenamePropsAndEvents());
            propMethods.visitAll((scope) => prepareRenameProperty(scope, false));
            eventMethods.visitAll((scope) => prepareRenameEvent(scope, false));
            propMethods.visitAll((scope) => prepareRenameProperty(scope, true));
            eventMethods.visitAll((scope) => prepareRenameEvent(scope, true));

            foreach (var typeDef in modules.AllTypes)
                memberInfos.type(typeDef).initializeEventHandlerNames();

            prepareHelper.prepare((info) => info.prepareRenameMethods());
            ifaceMethods.visitAll((scope) => prepareRenameVirtualMethods(scope, "imethod_", false));
            virtualMethods.visitAll((scope) => prepareRenameVirtualMethods(scope, "vmethod_", false));
            ifaceMethods.visitAll((scope) => prepareRenameVirtualMethods(scope, "imethod_", true));
            virtualMethods.visitAll((scope) => prepareRenameVirtualMethods(scope, "vmethod_", true));

            restoreMethodArgs(scopes);

            foreach (var typeDef in modules.AllTypes)
                memberInfos.type(typeDef).prepareRenameMethods2();
        }
예제 #5
0
 static List<MethodNameScope> getSorted(MethodNameScopes scopes)
 {
     var allScopes = new List<MethodNameScope>(scopes.getAllScopes());
     allScopes.Sort((a, b) => Utils.compareInt32(b.Count, a.Count));
     return allScopes;
 }
예제 #6
0
 void restorePropertiesAndEvents(MethodNameScopes scopes)
 {
     var allScopes = scopes.getAllScopes();
     restoreVirtualProperties(allScopes);
     restorePropertiesFromNames(allScopes);
     restoreVirtualEvents(allScopes);
     restoreEventsFromNames(allScopes);
 }
예제 #7
0
        void restoreMethodArgs(MethodNameScopes scopes)
        {
            foreach (var scope in scopes.getAllScopes()) {
                if (scope.Methods[0].ParamDefs.Count == 0)
                    continue;

                var argNames = getValidArgNames(scope);

                foreach (var method in scope.Methods) {
                    if (!method.Owner.HasModule)
                        continue;
                    var nameChecker = method.Owner.Module.ObfuscatedFile.NameChecker;

                    for (int i = 0; i < argNames.Length; i++) {
                        var argName = argNames[i];
                        if (argName == null || !nameChecker.isValidMethodArgName(argName))
                            continue;
                        var info = memberInfos.param(method.ParamDefs[i]);
                        if (nameChecker.isValidMethodArgName(info.oldName))
                            continue;
                        info.newName = argName;
                    }
                }
            }
        }
예제 #8
0
 void removeUselessOverrides(MethodNameScopes scopes)
 {
     foreach (var scope in scopes.getAllScopes()) {
         foreach (var method in scope.Methods) {
             if (!method.Owner.HasModule)
                 continue;
             if (!method.isPublic())
                 continue;
             var overrides = method.MethodDefinition.Overrides;
             for (int i = 0; i < overrides.Count; i++) {
                 var overrideMethod = overrides[i];
                 if (method.MethodDefinition.Name != overrideMethod.Name)
                     continue;
                 Log.v("Removed useless override from method {0} ({1:X8}), override: {2:X8}",
                             Utils.removeNewlines(method.MethodDefinition),
                             method.MethodDefinition.MetadataToken.ToInt32(),
                             overrideMethod.MetadataToken.ToInt32());
                 overrides.RemoveAt(i);
                 i--;
             }
         }
     }
 }