From 45cd6bf211df5cbb73ae211f930a1d5e2df16940 Mon Sep 17 00:00:00 2001 From: de4dot Date: Tue, 22 Nov 2011 08:14:34 +0100 Subject: [PATCH] Update the code that renames virtual methods, props, events --- de4dot.code/renamer/ExistingNames.cs | 8 +- de4dot.code/renamer/NameCreators.cs | 82 ++++----- de4dot.code/renamer/Renamer.cs | 161 +++++++++--------- de4dot.code/renamer/TypeInfo.cs | 21 ++- de4dot.code/renamer/TypeNames.cs | 109 ++++++------ de4dot.code/renamer/TypeRenamerState.cs | 4 +- de4dot.code/renamer/VariableNameState.cs | 37 ++-- .../renamer/asmmodules/MethodNameScopes.cs | 15 +- 8 files changed, 203 insertions(+), 234 deletions(-) diff --git a/de4dot.code/renamer/ExistingNames.cs b/de4dot.code/renamer/ExistingNames.cs index 9bd1a933..5dfb473f 100644 --- a/de4dot.code/renamer/ExistingNames.cs +++ b/de4dot.code/renamer/ExistingNames.cs @@ -52,11 +52,9 @@ namespace de4dot.renamer { } } - public ExistingNames clone() { - var cn = new ExistingNames(); - foreach (var key in allNames.Keys) - cn.allNames[key] = true; - return cn; + public void merge(ExistingNames other) { + foreach (var key in other.allNames.Keys) + allNames[key] = true; } } } diff --git a/de4dot.code/renamer/NameCreators.cs b/de4dot.code/renamer/NameCreators.cs index 7ce9df81..ae77a3fe 100644 --- a/de4dot.code/renamer/NameCreators.cs +++ b/de4dot.code/renamer/NameCreators.cs @@ -23,7 +23,6 @@ using de4dot.blocks; namespace de4dot.renamer { interface INameCreator { - INameCreator clone(); string create(); } @@ -34,70 +33,53 @@ namespace de4dot.renamer { this.name = name; } - public INameCreator clone() { - return this; - } - public string create() { return name; } } - class GlobalNameCreator : INameCreator { - INameCreator other; + abstract class NameCreatorCounter : INameCreator { + protected int num; - public GlobalNameCreator(INameCreator other) { - this.other = other; - } + public abstract string create(); - public INameCreator clone() { + public NameCreatorCounter merge(NameCreatorCounter other) { + if (num < other.num) + num = other.num; return this; } - - public string create() { - return other.create(); - } } - class GenericParamNameCreator : INameCreator { + class GenericParamNameCreator : NameCreatorCounter { static string[] names = new string[] { "T", "U", "V", "W", "X", "Y", "Z" }; - int index = 0; - public string create() { - if (index < names.Length) - return names[index++]; - return string.Format("T{0}", index++); - } - - public INameCreator clone() { - var rv = new GenericParamNameCreator(); - rv.index = index; - return rv; + public override string create() { + if (num < names.Length) + return names[num++]; + return string.Format("T{0}", num++); } } - class NameCreator : INameCreator { + class NameCreator : NameCreatorCounter { string prefix; - int num; public NameCreator(string prefix, int num = 0) { this.prefix = prefix; this.num = num; } - public INameCreator clone() { + public NameCreator clone() { return new NameCreator(prefix, num); } - public string create() { + public override string create() { return prefix + num++; } } // Like NameCreator but don't add the counter the first time - class NameCreator2 : INameCreator { + class NameCreator2 : NameCreatorCounter { string prefix; - int num; const string separator = "_"; public NameCreator2(string prefix, int num = 0) { @@ -105,11 +87,7 @@ namespace de4dot.renamer { this.num = num; } - public INameCreator clone() { - return new NameCreator2(prefix, num); - } - - public string create() { + public override string create() { string rv; if (num == 0) rv = prefix; @@ -129,18 +107,18 @@ namespace de4dot.renamer { class NameInfo { public string name; - public INameCreator nameCreator; - public NameInfo(string name, INameCreator nameCreator) { + public NameCreator nameCreator; + public NameInfo(string name, NameCreator nameCreator) { this.name = name; this.nameCreator = nameCreator; } } - public void add(string name, INameCreator nameCreator) { + public void add(string name, NameCreator nameCreator) { nameInfos.Add(new NameInfo(name, nameCreator)); } - public INameCreator find(string typeName) { + public NameCreator find(string typeName) { foreach (var nameInfo in nameInfos) { if (typeName.Contains(nameInfo.name)) return nameInfo.nameCreator; @@ -152,12 +130,12 @@ namespace de4dot.renamer { class TypeNameCreator : ITypeNameCreator { ExistingNames existingNames; - INameCreator createUnknownTypeName; - INameCreator createEnumName; - INameCreator createStructName; - INameCreator createDelegateName; - INameCreator createClassName; - INameCreator createInterfaceName; + NameCreator createUnknownTypeName; + NameCreator createEnumName; + NameCreator createStructName; + NameCreator createDelegateName; + NameCreator createClassName; + NameCreator createInterfaceName; NameInfos nameInfos = new NameInfos(); public TypeNameCreator(ExistingNames existingNames) { @@ -181,7 +159,7 @@ namespace de4dot.renamer { nameInfos.add(name, createNameCreator(name)); } - protected virtual INameCreator createNameCreator(string prefix) { + protected virtual NameCreator createNameCreator(string prefix) { return new NameCreator(prefix); } @@ -190,7 +168,7 @@ namespace de4dot.renamer { return existingNames.getName(typeDefinition.Name, nameCreator); } - INameCreator getNameCreator(TypeDefinition typeDefinition, string newBaseTypeName) { + NameCreator getNameCreator(TypeDefinition typeDefinition, string newBaseTypeName) { var nameCreator = createUnknownTypeName; if (typeDefinition.IsEnum) nameCreator = createEnumName; @@ -222,8 +200,8 @@ namespace de4dot.renamer { : base(existingNames) { } - protected override INameCreator createNameCreator(string prefix) { - return new GlobalNameCreator(base.createNameCreator("G" + prefix)); + protected override NameCreator createNameCreator(string prefix) { + return base.createNameCreator("G" + prefix); } } } diff --git a/de4dot.code/renamer/Renamer.cs b/de4dot.code/renamer/Renamer.cs index 465b7192..0346ab26 100644 --- a/de4dot.code/renamer/Renamer.cs +++ b/de4dot.code/renamer/Renamer.cs @@ -604,9 +604,6 @@ namespace de4dot.renamer { prepareRenameEntryPoints(); - foreach (var typeDef in modules.BaseTypes) - memberInfos.type(typeDef).variableNameState = new VariableNameState(); - foreach (var typeDef in modules.AllTypes) prepareRenameMembers(typeDef); @@ -638,68 +635,92 @@ namespace de4dot.renamer { return allScopes; } + class ScopeHelper { + MemberInfos memberInfos; + Dictionary visited = new Dictionary(); + Dictionary methodToScope; + List scopes = new List(); + IEnumerable allTypes; + Action func; + + public ScopeHelper(MemberInfos memberInfos, IEnumerable allTypes) { + this.memberInfos = memberInfos; + this.allTypes = allTypes; + } + + public void add(MethodNameScope scope) { + scopes.Add(scope); + } + + public void visitAll(Action func) { + this.func = func; + visited.Clear(); + + methodToScope = new Dictionary(); + foreach (var scope in scopes) { + foreach (var method in scope.Methods) + methodToScope[method] = scope; + } + + foreach (var type in allTypes) + visit(type); + } + + void visit(TypeDef type) { + if (visited.ContainsKey(type)) + return; + visited[type] = true; + + foreach (var ifaceInfo in type.interfaces) + visit(ifaceInfo.typeDef); + if (type.baseType != null) + visit(type.baseType.typeDef); + + TypeInfo info; + if (!memberInfos.tryGetType(type, out info)) + return; + info.mergeState(); + + foreach (var method in type.AllMethodsSorted) { + MethodNameScope scope; + if (!methodToScope.TryGetValue(method, out scope)) + continue; + foreach (var m in scope.Methods) + methodToScope.Remove(m); + func(scope); + } + } + } + void prepareRenameVirtualMethods(MethodNameScopes scopes) { var allScopes = getSorted(scopes); - var virtualMethods = new List(); - var ifaceMethods = new List(); - var propMethods = new List(); - var eventMethods = new List(); + 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 allScopes) { if (scope.hasNonRenamableMethod()) continue; else if (scope.hasPropertyMethod() && getPropertyMethodType(scope.Methods[0]) != PropertyMethodType.Other) - propMethods.Add(scope); + propMethods.add(scope); else if (scope.hasEventMethod()) - eventMethods.Add(scope); + eventMethods.add(scope); else if (scope.hasInterfaceMethod()) - ifaceMethods.Add(scope); + ifaceMethods.add(scope); else - virtualMethods.Add(scope); + virtualMethods.add(scope); } - prepareRenameVirtualProperties(propMethods); - prepareRenameVirtualEvents(eventMethods); - prepareRenameVirtualMethods(virtualMethods, "vmethod_", false); - prepareRenameVirtualMethods(ifaceMethods, "imethod_", false); - prepareRenameVirtualMethods(virtualMethods, "vmethod_", true); - prepareRenameVirtualMethods(ifaceMethods, "imethod_", true); - } + propMethods.visitAll((scope) => prepareRenameProperty(scope, false)); + eventMethods.visitAll((scope) => prepareRenameEvent(scope, false)); + virtualMethods.visitAll((scope) => prepareRenameVirtualMethods(scope, "vmethod_", false)); + ifaceMethods.visitAll((scope) => prepareRenameVirtualMethods(scope, "imethod_", false)); - Dictionary numBaseClassesDict = new Dictionary(); - int getNumberOfBaseClasses(TypeDef type) { - int numBaseClasses; - if (numBaseClassesDict.TryGetValue(type, out numBaseClasses)) - return numBaseClasses; - return numBaseClassesDict[type] = getNumberOfBaseClassesInternal(type); - } - - int getNumberOfBaseClassesInternal(TypeDef type) { - if (type.baseType == null) - return 0; - return getNumberOfBaseClasses(type.baseType.typeDef) + 1; - } - - int compareTypes(TypeDef a, TypeDef b) { - int ac = getNumberOfBaseClasses(a); - int bc = getNumberOfBaseClasses(b); - if (ac < bc) return -1; - if (ac > bc) return 1; - return Utils.compareInt32(a.Index, b.Index); - } - - void sortScopes(List scopes) { - var scopeToType = new Dictionary(scopes.Count); - foreach (var scope in scopes) { - TypeDef type = null; - foreach (var method in scope.Methods) { - var owner = method.Owner; - if (type == null || compareTypes(owner, type) < 0) - type = owner; - } - scopeToType[scope] = type; - } - scopes.Sort((a, b) => compareTypes(scopeToType[a], scopeToType[b])); + propMethods.visitAll((scope) => prepareRenameProperty(scope, true)); + eventMethods.visitAll((scope) => prepareRenameEvent(scope, true)); + virtualMethods.visitAll((scope) => prepareRenameVirtualMethods(scope, "vmethod_", true)); + ifaceMethods.visitAll((scope) => prepareRenameVirtualMethods(scope, "imethod_", true)); } static readonly Regex removeGenericsArityRegex = new Regex(@"`[0-9]+"); @@ -719,15 +740,6 @@ namespace de4dot.renamer { return name.Substring(index + 1); } - void prepareRenameVirtualEvents(List scopes) { - sortScopes(scopes); - - foreach (var scope in scopes) - prepareRenameEvent(scope, false); - foreach (var scope in scopes) - prepareRenameEvent(scope, true); - } - void prepareRenameEvent(MethodNameScope scope, bool renameOverrides) { string methodPrefix, overridePrefix; var eventName = prepareRenameEvent(scope, renameOverrides, out overridePrefix, out methodPrefix); @@ -808,15 +820,6 @@ namespace de4dot.renamer { return null; } - void prepareRenameVirtualProperties(List scopes) { - sortScopes(scopes); - - foreach (var scope in scopes) - prepareRenameProperty(scope, false); - foreach (var scope in scopes) - prepareRenameProperty(scope, true); - } - void prepareRenameProperty(MethodNameScope scope, bool renameOverrides) { string overridePrefix; var propName = prepareRenameProperty(scope, renameOverrides, out overridePrefix); @@ -918,16 +921,15 @@ namespace de4dot.renamer { const string defaultVal = "Prop_"; var propType = getPropertyType(scope); - if (propType == null) + if (propType == null || propType is GenericInstanceType) return defaultVal; string name = propType.Name; - int i = name.IndexOf('`'); - if (i >= 0) - name = name.Substring(0, i); - i = name.IndexOf('.'); - if (i >= 0) + int i; + if ((i = name.IndexOf('`')) >= 0) name = name.Substring(0, i); + if ((i = name.LastIndexOf('.')) >= 0) + name = name.Substring(i + 1); if (name == "") return defaultVal; return name + "_"; @@ -968,13 +970,6 @@ namespace de4dot.renamer { return type; } - void prepareRenameVirtualMethods(List scopes, string namePrefix, bool renameOverrides) { - sortScopes(scopes); - - foreach (var scope in scopes) - prepareRenameVirtualMethods(scope, namePrefix, renameOverrides); - } - void prepareRenameVirtualMethods(MethodNameScope scope, string namePrefix, bool renameOverrides) { if (!hasInvalidMethodName(scope)) return; diff --git a/de4dot.code/renamer/TypeInfo.cs b/de4dot.code/renamer/TypeInfo.cs index 5a14f903..fdb3c277 100644 --- a/de4dot.code/renamer/TypeInfo.cs +++ b/de4dot.code/renamer/TypeInfo.cs @@ -29,7 +29,7 @@ namespace de4dot.renamer { class TypeInfo : MemberInfo { public string oldNamespace; public string newNamespace; - public VariableNameState variableNameState; + public VariableNameState variableNameState = new VariableNameState(); public TypeDef type; MemberInfos memberInfos; @@ -111,9 +111,24 @@ namespace de4dot.renamer { prepareRenameGenericParams(type.GenericParams, checker); } + public void mergeState() { + foreach (var ifaceInfo in type.interfaces) + mergeState(ifaceInfo.typeDef); + if (type.baseType != null) + mergeState(type.baseType.typeDef); + } + + void mergeState(TypeDef other) { + if (other == null) + return; + TypeInfo otherInfo; + if (!memberInfos.tryGetType(other, out otherInfo)) + return; + variableNameState.merge(otherInfo.variableNameState); + } + public void prepareRenameMembers() { - if (variableNameState == null) - variableNameState = memberInfos.type(type.baseType.typeDef).variableNameState.clone(); + mergeState(); foreach (var fieldDef in type.AllFields) variableNameState.addFieldName(field(fieldDef).oldName); diff --git a/de4dot.code/renamer/TypeNames.cs b/de4dot.code/renamer/TypeNames.cs index a10ca222..51f30833 100644 --- a/de4dot.code/renamer/TypeNames.cs +++ b/de4dot.code/renamer/TypeNames.cs @@ -23,10 +23,56 @@ using Mono.Cecil; namespace de4dot.renamer { abstract class TypeNames { - protected IDictionary typeNames = new Dictionary(StringComparer.Ordinal); - protected INameCreator genericParamNameCreator = new NameCreator("gparam_"); + protected Dictionary typeNames = new Dictionary(StringComparer.Ordinal); + protected NameCreator genericParamNameCreator = new NameCreator("gparam_"); - public TypeNames() { + public string create(TypeReference typeRef) { + var elementType = typeRef.GetElementType(); + if (elementType is GenericParameter) + return genericParamNameCreator.create(); + + var name = elementType.FullName; + NameCreator nc; + if (typeNames.TryGetValue(name, out nc)) + return nc.create(); + + var parts = name.Replace('/', '.').Split(new char[] { '.' }); + var newName = parts[parts.Length - 1]; + int tickIndex = newName.LastIndexOf('`'); + if (tickIndex > 0) + newName = newName.Substring(0, tickIndex); + + return addTypeName(name, newName).create(); + } + + protected INameCreator addTypeName(string fullName, string newName) { + newName = fixName(newName); + + var name2 = " " + newName; + NameCreator nc; + if (!typeNames.TryGetValue(name2, out nc)) + typeNames[name2] = nc = new NameCreator(newName + "_"); + + typeNames[fullName] = nc; + return nc; + } + + protected abstract string fixName(string name); + + public virtual TypeNames merge(TypeNames other) { + foreach (var pair in other.typeNames) { + if (typeNames.ContainsKey(pair.Key)) + typeNames[pair.Key].merge(pair.Value); + else + typeNames[pair.Key] = pair.Value.clone(); + } + genericParamNameCreator.merge(other.genericParamNameCreator); + return this; + } + } + + class VariableNameCreator : TypeNames { + public VariableNameCreator() { addTypeName("System.Boolean", "bool"); addTypeName("System.Byte", "byte"); addTypeName("System.Char", "char"); @@ -45,49 +91,6 @@ namespace de4dot.renamer { addTypeName("System.Decimal", "decimal"); } - public string create(TypeReference typeRef) { - var elementType = typeRef.GetElementType(); - if (elementType is GenericParameter) - return genericParamNameCreator.create(); - - var name = elementType.FullName; - INameCreator nc; - if (typeNames.TryGetValue(name, out nc)) - return nc.create(); - - var parts = name.Replace('/', '.').Split(new char[] { '.' }); - var newName = parts[parts.Length - 1]; - int tickIndex = newName.LastIndexOf('`'); - if (tickIndex > 0) - newName = newName.Substring(0, tickIndex); - - return addTypeName(name, newName).create(); - } - - INameCreator addTypeName(string fullName, string newName) { - newName = fixName(newName); - - var name2 = " " + newName; - INameCreator nc; - if (!typeNames.TryGetValue(name2, out nc)) - typeNames[name2] = nc = new NameCreator(newName + "_"); - - typeNames[fullName] = nc; - return nc; - } - - protected abstract string fixName(string name); - public abstract TypeNames clone(); - - protected IDictionary cloneDict() { - var rv = new Dictionary(StringComparer.Ordinal); - foreach (var key in typeNames.Keys) - rv[key] = typeNames[key].clone(); - return rv; - } - } - - class VariableNameCreator : TypeNames { protected override string fixName(string name) { // Make all leading upper case chars lower case var s = ""; @@ -99,25 +102,11 @@ namespace de4dot.renamer { } return s; } - - public override TypeNames clone() { - var rv = new VariableNameCreator(); - rv.typeNames = cloneDict(); - rv.genericParamNameCreator = genericParamNameCreator.clone(); - return rv; - } } class PropertyNameCreator : TypeNames { protected override string fixName(string name) { return name.Substring(0, 1).ToUpperInvariant() + name.Substring(1); } - - public override TypeNames clone() { - var rv = new PropertyNameCreator(); - rv.typeNames = cloneDict(); - rv.genericParamNameCreator = genericParamNameCreator.clone(); - return rv; - } } } diff --git a/de4dot.code/renamer/TypeRenamerState.cs b/de4dot.code/renamer/TypeRenamerState.cs index 5d73b43b..31696eae 100644 --- a/de4dot.code/renamer/TypeRenamerState.cs +++ b/de4dot.code/renamer/TypeRenamerState.cs @@ -24,14 +24,14 @@ namespace de4dot.renamer { class TypeRenamerState { ExistingNames existingNames; Dictionary namespaceToNewName; - INameCreator createNamespaceName; + NameCreator createNamespaceName; public ITypeNameCreator globalTypeNameCreator; public ITypeNameCreator internalTypeNameCreator; public TypeRenamerState() { existingNames = new ExistingNames(); namespaceToNewName = new Dictionary(StringComparer.Ordinal); - createNamespaceName = new GlobalNameCreator(new NameCreator("ns")); + createNamespaceName = new NameCreator("ns"); globalTypeNameCreator = new GlobalTypeNameCreator(existingNames); internalTypeNameCreator = new TypeNameCreator(existingNames); } diff --git a/de4dot.code/renamer/VariableNameState.cs b/de4dot.code/renamer/VariableNameState.cs index 86578c80..2f7c40fc 100644 --- a/de4dot.code/renamer/VariableNameState.cs +++ b/de4dot.code/renamer/VariableNameState.cs @@ -27,28 +27,27 @@ namespace de4dot.renamer { ExistingNames existingEventNames = new ExistingNames(); TypeNames variableNameCreator = new VariableNameCreator(); // For fields and method args TypeNames propertyNameCreator = new PropertyNameCreator(); - INameCreator eventNameCreator = new NameCreator("Event_"); - INameCreator genericPropertyNameCreator = new NameCreator("Prop_"); - public INameCreator staticMethodNameCreator = new NameCreator("smethod_"); - public INameCreator instanceMethodNameCreator = new NameCreator("method_"); + NameCreator eventNameCreator = new NameCreator("Event_"); + NameCreator genericPropertyNameCreator = new NameCreator("Prop_"); + public NameCreator staticMethodNameCreator = new NameCreator("smethod_"); + public NameCreator instanceMethodNameCreator = new NameCreator("method_"); - public virtual VariableNameState clone() { - var rv = new VariableNameState(); - cloneInit(rv); - return rv; + public VariableNameState clone() { + return new VariableNameState().merge(this); } - void cloneInit(VariableNameState variableNameState) { - variableNameState.existingVariableNames = existingVariableNames.clone(); - variableNameState.existingMethodNames = existingMethodNames.clone(); - variableNameState.existingPropertyNames = existingPropertyNames.clone(); - variableNameState.existingEventNames = existingEventNames.clone(); - variableNameState.variableNameCreator = variableNameCreator.clone(); - variableNameState.propertyNameCreator = propertyNameCreator.clone(); - variableNameState.eventNameCreator = eventNameCreator.clone(); - variableNameState.genericPropertyNameCreator = genericPropertyNameCreator.clone(); - variableNameState.staticMethodNameCreator = staticMethodNameCreator.clone(); - variableNameState.instanceMethodNameCreator = instanceMethodNameCreator.clone(); + public VariableNameState merge(VariableNameState other) { + existingVariableNames.merge(other.existingVariableNames); + existingMethodNames.merge(other.existingMethodNames); + existingPropertyNames.merge(other.existingPropertyNames); + existingEventNames.merge(other.existingEventNames); + variableNameCreator.merge(other.variableNameCreator); + propertyNameCreator.merge(other.propertyNameCreator); + eventNameCreator.merge(other.eventNameCreator); + genericPropertyNameCreator.merge(other.genericPropertyNameCreator); + staticMethodNameCreator.merge(other.staticMethodNameCreator); + instanceMethodNameCreator.merge(other.instanceMethodNameCreator); + return this; } public string getNewPropertyName(PropertyDefinition propertyDefinition) { diff --git a/de4dot.code/renamer/asmmodules/MethodNameScopes.cs b/de4dot.code/renamer/asmmodules/MethodNameScopes.cs index 96b37d32..b513c66f 100644 --- a/de4dot.code/renamer/asmmodules/MethodNameScopes.cs +++ b/de4dot.code/renamer/asmmodules/MethodNameScopes.cs @@ -68,8 +68,11 @@ namespace de4dot.renamer.asmmodules { public bool hasEventMethod() { foreach (var method in methods) { - if (method.Event != null) - return true; + if (method.Event != null) { + var evt = method.Event; + if (method == evt.AddMethod || method == evt.RemoveMethod || method == evt.RaiseMethod) + return true; + } } return false; } @@ -82,14 +85,6 @@ namespace de4dot.renamer.asmmodules { return false; } - public bool hasEvent() { - foreach (var method in methods) { - if (method.Event != null) - return true; - } - return false; - } - public override string ToString() { return string.Format("{0} -- {1}", methods.Count, methods.Count > 0 ? methods[0].ToString() : ""); }