public void InitializeVirtualMembers(MethodNameGroups groups, IResolver resolver) { if (initializeVirtualMembersCalled) { return; } initializeVirtualMembersCalled = true; foreach (var iface in interfaces) { iface.typeDef.InitializeVirtualMembers(groups, resolver); } if (baseType != null) { baseType.typeDef.InitializeVirtualMembers(groups, resolver); } foreach (var methodDef in methods.GetValues()) { if (methodDef.IsVirtual()) { groups.Add(methodDef); } } InstantiateVirtualMembers(groups); InitializeInterfaceMethods(groups); }
public MethodNameGroups InitializeVirtualMembers() { var groups = new MethodNameGroups(); foreach (var typeDef in allTypes) { typeDef.InitializeVirtualMembers(groups, this); } return(groups); }
void instantiateVirtualMembers(MethodNameGroups groups) { 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) { groups.same(methodDef, methodInst.origMethodDef); } } } foreach (var methodDef in methods.getValues()) { if (!methodDef.isVirtual()) { continue; } virtualMethodInstances.add(new MethodInst(methodDef, methodDef.MethodDefinition)); } }
void InstantiateVirtualMembers(MethodNameGroups groups) { if (!TypeDef.IsInterface) { if (baseType != null) { virtualMethodInstances.InitializeFrom(baseType.typeDef.virtualMethodInstances, baseType.typeRef.TryGetGenericInstSig()); } // 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.MethodDef); if (methodInstList == null) { continue; } foreach (var methodInst in methodInstList) { groups.Same(methodDef, methodInst.origMethodDef); } } } foreach (var methodDef in methods.GetValues()) { if (!methodDef.IsVirtual()) { continue; } virtualMethodInstances.Add(new MethodInst(methodDef, methodDef.MethodDef)); } }
void PrepareRenameMemberDefs(MethodNameGroups groups) { if (isVerbose) Logger.v("Renaming member definitions #1"); PrepareRenameEntryPoints(); var virtualMethods = new GroupHelper(memberInfos, modules.AllTypes); var ifaceMethods = new GroupHelper(memberInfos, modules.AllTypes); var propMethods = new GroupHelper(memberInfos, modules.AllTypes); var eventMethods = new GroupHelper(memberInfos, modules.AllTypes); foreach (var group in GetSorted(groups)) { if (group.HasNonRenamableMethod()) continue; else if (group.HasGetterOrSetterPropertyMethod() && GetPropertyMethodType(group.Methods[0]) != PropertyMethodType.Other) propMethods.Add(group); else if (group.HasAddRemoveOrRaiseEventMethod()) eventMethods.Add(group); else if (group.HasInterfaceMethod()) ifaceMethods.Add(group); else virtualMethods.Add(group); } var prepareHelper = new PrepareHelper(memberInfos, modules.AllTypes); prepareHelper.Prepare((info) => info.PrepareRenameMembers()); prepareHelper.Prepare((info) => info.PrepareRenamePropsAndEvents()); propMethods.VisitAll((group) => PrepareRenameProperty(group, false)); eventMethods.VisitAll((group) => PrepareRenameEvent(group, false)); propMethods.VisitAll((group) => PrepareRenameProperty(group, true)); eventMethods.VisitAll((group) => PrepareRenameEvent(group, true)); foreach (var typeDef in modules.AllTypes) memberInfos.Type(typeDef).InitializeEventHandlerNames(); prepareHelper.Prepare((info) => info.PrepareRenameMethods()); ifaceMethods.VisitAll((group) => PrepareRenameVirtualMethods(group, "imethod_", false)); virtualMethods.VisitAll((group) => PrepareRenameVirtualMethods(group, "vmethod_", false)); ifaceMethods.VisitAll((group) => PrepareRenameVirtualMethods(group, "imethod_", true)); virtualMethods.VisitAll((group) => PrepareRenameVirtualMethods(group, "vmethod_", true)); RestoreMethodArgs(groups); foreach (var typeDef in modules.AllTypes) memberInfos.Type(typeDef).PrepareRenameMethods2(); }
void InitializeInterfaceMethods(MethodNameGroups groups) { InitializeAllInterfaces(); if (TypeDef.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 <IMethodDefOrRef, MMethodDef>(MethodEqualityComparer.DontCompareDeclaringTypes); //--- * 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[method.MethodDef] = method; } foreach (var ifaceInfo in interfaces) { foreach (var methodsList in ifaceInfo.typeDef.virtualMethodInstances.GetMethods()) { if (methodsList.Count < 1) { continue; } var methodInst = methodsList[0]; var ifaceMethod = methodInst.origMethodDef; if (!ifaceMethod.IsVirtual()) { continue; } var ifaceMethodRef = GenericArgsSubstitutor.Create(methodInst.methodRef, ifaceInfo.typeRef.TryGetGenericInstSig()); MMethodDef classMethod; if (!methodsDict.TryGetValue(ifaceMethodRef, 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[classMethod.methodRef] = classMethod.origMethodDef; break; } } foreach (var ifaceInfo in allImplementedInterfaces.Keys) { foreach (var methodsList in ifaceInfo.typeDef.virtualMethodInstances.GetMethods()) { if (methodsList.Count < 1) { continue; } var ifaceMethod = methodsList[0].origMethodDef; if (!ifaceMethod.IsVirtual()) { continue; } var ifaceMethodRef = GenericArgsSubstitutor.Create(ifaceMethod.MethodDef, ifaceInfo.typeRef.TryGetGenericInstSig()); MMethodDef classMethod; if (!methodsDict.TryGetValue(ifaceMethodRef, 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 <IMethodDefOrRef, MMethodDef>(MethodEqualityComparer.CompareDeclaringTypes); foreach (var ifaceInfo in allImplementedInterfaces.Keys) { var git = ifaceInfo.typeRef.TryGetGenericInstSig(); foreach (var ifaceMethod in ifaceInfo.typeDef.methods.GetValues()) { IMethodDefOrRef ifaceMethodRef = ifaceMethod.MethodDef; if (git != null) { ifaceMethodRef = SimpleClone(ifaceMethod.MethodDef, ifaceInfo.typeRef); } ifaceMethodsDict[ifaceMethodRef] = ifaceMethod; } } foreach (var classMethod in methods.GetValues()) { if (!classMethod.IsVirtual()) { continue; } foreach (var overrideMethod in classMethod.MethodDef.Overrides) { MMethodDef ifaceMethod; if (!ifaceMethodsDict.TryGetValue(overrideMethod.MethodDeclaration, 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.MethodDeclaration.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 (!TypeDef.IsImport && !HasAttribute("System.Runtime.InteropServices.ComImportAttribute") && !HasAttribute("System.Runtime.InteropServices.TypeLibTypeAttribute")) { Logger.w("Could not find interface method {0} ({1:X8}). Type: {2} ({3:X8})", Utils.RemoveNewlines(pair.Key.methodDef.MethodDef), pair.Key.methodDef.MethodDef.MDToken.ToInt32(), Utils.RemoveNewlines(TypeDef), TypeDef.MDToken.ToInt32()); } } } foreach (var info in interfaceMethodInfos.AllInfos) { foreach (var pair in info.IfaceMethodToClassMethod) { if (pair.Value == null) { continue; } if (pair.Key.methodDef.MethodDef.Name != pair.Value.MethodDef.Name) { continue; } groups.Same(pair.Key.methodDef, pair.Value); } } }
void RestorePropertiesAndEvents(MethodNameGroups groups) { var allGroups = groups.GetAllGroups(); RestoreVirtualProperties(allGroups); RestorePropertiesFromNames2(allGroups); ResetVirtualPropertyNames(allGroups); RestoreVirtualEvents(allGroups); RestoreEventsFromNames2(allGroups); ResetVirtualEventNames(allGroups); }
void restorePropertiesAndEvents(MethodNameGroups groups) { var allGroups = groups.getAllGroups(); restoreVirtualProperties(allGroups); restorePropertiesFromNames(allGroups); restoreVirtualEvents(allGroups); restoreEventsFromNames(allGroups); }
static List<MethodNameGroup> GetSorted(MethodNameGroups groups) { var allGroups = new List<MethodNameGroup>(groups.GetAllGroups()); allGroups.Sort((a, b) => b.Count.CompareTo(a.Count)); return allGroups; }
void RemoveUselessOverrides(MethodNameGroups groups) { foreach (var group in groups.GetAllGroups()) { foreach (var method in group.Methods) { if (!method.Owner.HasModule) continue; if (!method.IsPublic()) continue; var overrides = method.MethodDef.Overrides; for (int i = 0; i < overrides.Count; i++) { var overrideMethod = overrides[i].MethodDeclaration; if (method.MethodDef.Name != overrideMethod.Name) continue; if (isVerbose) Logger.v("Removed useless override from method {0} ({1:X8}), override: {2:X8}", Utils.RemoveNewlines(method.MethodDef), method.MethodDef.MDToken.ToInt32(), overrideMethod.MDToken.ToInt32()); overrides.RemoveAt(i); i--; } } } }
void instantiateVirtualMembers(MethodNameGroups groups) { 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) groups.same(methodDef, methodInst.origMethodDef); } } foreach (var methodDef in methods.getValues()) { if (!methodDef.isVirtual()) continue; virtualMethodInstances.add(new MethodInst(methodDef, methodDef.MethodDefinition)); } }
void RestoreMethodArgs(MethodNameGroups groups) { foreach (var group in groups.GetAllGroups()) { if (group.Methods[0].VisibleParameterCount == 0) continue; var argNames = GetValidArgNames(group); foreach (var method in group.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; } } } }
static List<MethodNameGroup> getSorted(MethodNameGroups groups) { var allGroups = new List<MethodNameGroup>(groups.getAllGroups()); allGroups.Sort((a, b) => Utils.compareInt32(b.Count, a.Count)); return allGroups; }
void removeUselessOverrides(MethodNameGroups groups) { foreach (var group in groups.getAllGroups()) { foreach (var method in group.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--; } } } }
void InstantiateVirtualMembers(MethodNameGroups groups) { if (!TypeDef.IsInterface) { if (baseType != null) virtualMethodInstances.InitializeFrom(baseType.typeDef.virtualMethodInstances, baseType.typeRef.TryGetGenericInstSig()); // 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.MethodDef); if (methodInstList == null) continue; foreach (var methodInst in methodInstList) groups.Same(methodDef, methodInst.origMethodDef); } } foreach (var methodDef in methods.GetValues()) { if (!methodDef.IsVirtual()) continue; virtualMethodInstances.Add(new MethodInst(methodDef, methodDef.MethodDef)); } }
void InitializeInterfaceMethods(MethodNameGroups groups) { InitializeAllInterfaces(); if (TypeDef.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<IMethodDefOrRef, MMethodDef>(MethodEqualityComparer.DontCompareDeclaringTypes); //--- * 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[method.MethodDef] = method; } foreach (var ifaceInfo in interfaces) { foreach (var methodsList in ifaceInfo.typeDef.virtualMethodInstances.GetMethods()) { if (methodsList.Count < 1) continue; var methodInst = methodsList[0]; var ifaceMethod = methodInst.origMethodDef; if (!ifaceMethod.IsVirtual()) continue; var ifaceMethodRef = GenericArgsSubstitutor.Create(methodInst.methodRef, ifaceInfo.typeRef.TryGetGenericInstSig()); MMethodDef classMethod; if (!methodsDict.TryGetValue(ifaceMethodRef, 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[classMethod.methodRef] = classMethod.origMethodDef; break; } } foreach (var ifaceInfo in allImplementedInterfaces.Keys) { foreach (var methodsList in ifaceInfo.typeDef.virtualMethodInstances.GetMethods()) { if (methodsList.Count < 1) continue; var ifaceMethod = methodsList[0].origMethodDef; if (!ifaceMethod.IsVirtual()) continue; var ifaceMethodRef = GenericArgsSubstitutor.Create(ifaceMethod.MethodDef, ifaceInfo.typeRef.TryGetGenericInstSig()); MMethodDef classMethod; if (!methodsDict.TryGetValue(ifaceMethodRef, 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<IMethodDefOrRef, MMethodDef>(MethodEqualityComparer.CompareDeclaringTypes); foreach (var ifaceInfo in allImplementedInterfaces.Keys) { var git = ifaceInfo.typeRef.TryGetGenericInstSig(); foreach (var ifaceMethod in ifaceInfo.typeDef.methods.GetValues()) { IMethodDefOrRef ifaceMethodRef = ifaceMethod.MethodDef; if (git != null) ifaceMethodRef = SimpleClone(ifaceMethod.MethodDef, ifaceInfo.typeRef); ifaceMethodsDict[ifaceMethodRef] = ifaceMethod; } } foreach (var classMethod in methods.GetValues()) { if (!classMethod.IsVirtual()) continue; foreach (var overrideMethod in classMethod.MethodDef.Overrides) { MMethodDef ifaceMethod; if (!ifaceMethodsDict.TryGetValue(overrideMethod.MethodDeclaration, 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.MethodDeclaration.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 (!TypeDef.IsImport && !HasAttribute("System.Runtime.InteropServices.ComImportAttribute") && !HasAttribute("System.Runtime.InteropServices.TypeLibTypeAttribute")) { Logger.w("Could not find interface method {0} ({1:X8}). Type: {2} ({3:X8})", Utils.RemoveNewlines(pair.Key.methodDef.MethodDef), pair.Key.methodDef.MethodDef.MDToken.ToInt32(), Utils.RemoveNewlines(TypeDef), TypeDef.MDToken.ToInt32()); } } } foreach (var info in interfaceMethodInfos.AllInfos) { foreach (var pair in info.IfaceMethodToClassMethod) { if (pair.Value == null) continue; if (pair.Key.methodDef.MethodDef.Name != pair.Value.MethodDef.Name) continue; groups.Same(pair.Key.methodDef, pair.Value); } } }
public void InitializeVirtualMembers(MethodNameGroups groups, IResolver resolver) { if (initializeVirtualMembersCalled) return; initializeVirtualMembersCalled = true; foreach (var iface in interfaces) iface.typeDef.InitializeVirtualMembers(groups, resolver); if (baseType != null) baseType.typeDef.InitializeVirtualMembers(groups, resolver); foreach (var methodDef in methods.GetValues()) { if (methodDef.IsVirtual()) groups.Add(methodDef); } InstantiateVirtualMembers(groups); InitializeInterfaceMethods(groups); }