diff --git a/AssemblyData/methodsrewriter/Resolver.cs b/AssemblyData/methodsrewriter/Resolver.cs index 18be64d1..0bf868d1 100644 --- a/AssemblyData/methodsrewriter/Resolver.cs +++ b/AssemblyData/methodsrewriter/Resolver.cs @@ -128,8 +128,8 @@ namespace AssemblyData.methodsrewriter { return Resolver.resolve(methodReference); } - static AssemblyResolver getAssemblyResolver(IMetadataScope scope) { - var asmName = DotNetUtils.getFullAssemblyName(scope); + static AssemblyResolver getAssemblyResolver(TypeReference type) { + var asmName = DotNetUtils.getFullAssemblyName(type); AssemblyResolver resolver; if (!assemblyResolvers.TryGetValue(asmName, out resolver)) assemblyResolvers[asmName] = resolver = new AssemblyResolver(asmName); @@ -140,7 +140,7 @@ namespace AssemblyData.methodsrewriter { if (typeReference == null) return null; var elemType = typeReference.GetElementType(); - var resolver = getAssemblyResolver(elemType.Scope); + var resolver = getAssemblyResolver(elemType); var resolvedType = resolver.resolve(elemType); if (resolvedType != null) return fixType(typeReference, resolvedType); @@ -150,7 +150,7 @@ namespace AssemblyData.methodsrewriter { static FieldInfo resolve(FieldReference fieldReference) { if (fieldReference == null) return null; - var resolver = getAssemblyResolver(fieldReference.DeclaringType.Scope); + var resolver = getAssemblyResolver(fieldReference.DeclaringType); var fieldInfo = resolver.resolve(fieldReference); if (fieldInfo != null) return fieldInfo; @@ -160,7 +160,7 @@ namespace AssemblyData.methodsrewriter { static MethodBase resolve(MethodReference methodReference) { if (methodReference == null) return null; - var resolver = getAssemblyResolver(methodReference.DeclaringType.Scope); + var resolver = getAssemblyResolver(methodReference.DeclaringType); var methodBase = resolver.resolve(methodReference); if (methodBase != null) return methodBase; diff --git a/AssemblyData/methodsrewriter/ResolverUtils.cs b/AssemblyData/methodsrewriter/ResolverUtils.cs index 9aca1f71..9536a267 100644 --- a/AssemblyData/methodsrewriter/ResolverUtils.cs +++ b/AssemblyData/methodsrewriter/ResolverUtils.cs @@ -144,7 +144,7 @@ namespace AssemblyData.methodsrewriter { if ((a.Namespace ?? "") != b.Namespace) return false; - var asmRef = DotNetUtils.getAssemblyNameReference(b.Scope); + var asmRef = DotNetUtils.getAssemblyNameReference(b); var asmName = a.Assembly.GetName(); if (asmRef.Name != asmName.Name) return false; diff --git a/AssemblyData/methodsrewriter/TypeInstanceResolver.cs b/AssemblyData/methodsrewriter/TypeInstanceResolver.cs index d3f485e6..c6593bfb 100644 --- a/AssemblyData/methodsrewriter/TypeInstanceResolver.cs +++ b/AssemblyData/methodsrewriter/TypeInstanceResolver.cs @@ -42,7 +42,7 @@ namespace AssemblyData.methodsrewriter { var git = fieldReference.DeclaringType as GenericInstanceType; if (git != null) - fieldReference = new FieldReferenceExpander(fieldReference, git).expand(); + fieldReference = FieldReferenceInstance.make(fieldReference, git); foreach (var field in list) { if (ResolverUtils.compareFields(field, fieldReference)) @@ -75,7 +75,7 @@ namespace AssemblyData.methodsrewriter { var git = methodReference.DeclaringType as GenericInstanceType; if (git != null) - methodReference = new MethodReferenceExpander(methodReference, git).expand(); + methodReference = MethodReferenceInstance.make(methodReference, git); foreach (var method in list) { if (ResolverUtils.compareMethods(method, methodReference)) diff --git a/blocks/DotNetUtils.cs b/blocks/DotNetUtils.cs index cc2b9174..764c1f45 100644 --- a/blocks/DotNetUtils.cs +++ b/blocks/DotNetUtils.cs @@ -58,8 +58,10 @@ namespace de4dot.blocks { } // Call this to invalidate all modules - public void invalidateAll() { + public List invalidateAll() { + var list = new List(typeCaches.Keys); typeCaches.Clear(); + return list; } public TypeDefinition lookup(ModuleDefinition module, TypeReference typeReference) { @@ -671,20 +673,28 @@ namespace de4dot.blocks { } } - public static AssemblyNameReference getAssemblyNameReference(IMetadataScope scope) { + public static AssemblyNameReference getAssemblyNameReference(TypeReference type) { + var scope = type.Scope; if (scope is ModuleDefinition) { var moduleDefinition = (ModuleDefinition)scope; return moduleDefinition.Assembly.Name; } - else if (scope is AssemblyNameReference) + + if (scope is AssemblyNameReference) return (AssemblyNameReference)scope; + if (scope is ModuleReference && type.Module.Assembly != null) { + foreach (var module in type.Module.Assembly.Modules) { + if (scope.Name == module.Name) + return type.Module.Assembly.Name; + } + } + throw new ApplicationException(string.Format("Unknown IMetadataScope type: {0}", scope.GetType())); } - public static string getFullAssemblyName(IMetadataScope scope) { - //TODO: Returning scope.Name is probably best since the method could fail. - var asmRef = getAssemblyNameReference(scope); + public static string getFullAssemblyName(TypeReference type) { + var asmRef = getAssemblyNameReference(type); return asmRef.FullName; } @@ -789,6 +799,7 @@ namespace de4dot.blocks { // Doesn't fix everything (eg. T[] aren't replaced with eg. int[], but T -> int will be fixed) public static IList replaceGenericParameters(GenericInstanceType typeOwner, GenericInstanceMethod methodOwner, IList types) { + //TODO: You should use MemberRefInstance.cs for (int i = 0; i < types.Count; i++) types[i] = getGenericArgument(typeOwner, methodOwner, types[i]); return types; diff --git a/blocks/MemberRefInstance.cs b/blocks/MemberRefInstance.cs new file mode 100644 index 00000000..b929001c --- /dev/null +++ b/blocks/MemberRefInstance.cs @@ -0,0 +1,278 @@ +/* + Copyright (C) 2011 de4dot@gmail.com + + This file is part of de4dot. + + de4dot is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + de4dot is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with de4dot. If not, see . +*/ + +// Create a new type, method, etc, where all generic parameters have been replaced with the +// corresponding generic argument. + +using System; +using Mono.Cecil; +using de4dot.blocks; + +namespace de4dot.blocks { + public abstract class RefInstance { + protected bool modified = false; + + protected void checkModified(object a, object b) { + if (!ReferenceEquals(a, b)) + modified = true; + } + } + + public class TypeReferenceInstance : RefInstance { + TypeReference typeReference; + GenericInstanceType git; + + public static TypeReference make(TypeReference typeReference, GenericInstanceType git) { + if (git == null) + return typeReference; + return new TypeReferenceInstance(typeReference, git).makeInstance(); + } + + TypeReferenceInstance(TypeReference typeReference, GenericInstanceType git) { + this.typeReference = typeReference; + this.git = git; + } + + // Returns same one if nothing was modified + TypeReference makeInstance() { + var rv = makeInstance(typeReference); + return modified ? rv : typeReference; + } + + TypeReference makeInstance(TypeReference a) { + if (a == null) + return null; + + var type = MemberReferenceHelper.getMemberReferenceType(a); + switch (type) { + case CecilType.ArrayType: + return makeInstanceArrayType((ArrayType)a); + case CecilType.ByReferenceType: + return makeInstanceByReferenceType((ByReferenceType)a); + case CecilType.FunctionPointerType: + return makeInstanceFunctionPointerType((FunctionPointerType)a); + case CecilType.GenericInstanceType: + return makeInstanceGenericInstanceType((GenericInstanceType)a); + case CecilType.GenericParameter: + return makeInstanceGenericParameter((GenericParameter)a); + case CecilType.OptionalModifierType: + return makeInstanceOptionalModifierType((OptionalModifierType)a); + case CecilType.PinnedType: + return makeInstancePinnedType((PinnedType)a); + case CecilType.PointerType: + return makeInstancePointerType((PointerType)a); + case CecilType.RequiredModifierType: + return makeInstanceRequiredModifierType((RequiredModifierType)a); + case CecilType.SentinelType: + return makeInstanceSentinelType((SentinelType)a); + case CecilType.TypeDefinition: + return makeInstanceTypeDefinition((TypeDefinition)a); + case CecilType.TypeReference: + return makeInstanceTypeReference((TypeReference)a); + default: + throw new ApplicationException(string.Format("Unknown cecil type {0}", type)); + } + } + + ArrayType makeInstanceArrayType(ArrayType a) { + var rv = new ArrayType(makeInstance(a.ElementType)); + if (!a.IsVector) { + foreach (var dim in a.Dimensions) + rv.Dimensions.Add(dim); + } + return rv; + } + + ByReferenceType makeInstanceByReferenceType(ByReferenceType a) { + return new ByReferenceType(makeInstance(a.ElementType)); + } + + FunctionPointerType makeInstanceFunctionPointerType(FunctionPointerType a) { + var rv = new FunctionPointerType(); + rv.function = MethodReferenceInstance.make(a.function, git); + checkModified(a.function, rv.function); + return rv; + } + + GenericInstanceType makeInstanceGenericInstanceType(GenericInstanceType a) { + var rv = new GenericInstanceType(makeInstance(a.ElementType)); + foreach (var arg in a.GenericArguments) + rv.GenericArguments.Add(makeInstance(arg)); + return rv; + } + + TypeReference makeInstanceGenericParameter(GenericParameter a) { + if (!MemberReferenceHelper.compareTypes(a.Owner as TypeReference, git.ElementType)) + return a; + modified = true; + return makeInstance(git.GenericArguments[a.Position]); + } + + OptionalModifierType makeInstanceOptionalModifierType(OptionalModifierType a) { + return new OptionalModifierType(makeInstance(a.ModifierType), makeInstance(a.ElementType)); + } + + PinnedType makeInstancePinnedType(PinnedType a) { + return new PinnedType(makeInstance(a.ElementType)); + } + + PointerType makeInstancePointerType(PointerType a) { + return new PointerType(makeInstance(a.ElementType)); + } + + RequiredModifierType makeInstanceRequiredModifierType(RequiredModifierType a) { + return new RequiredModifierType(makeInstance(a.ModifierType), makeInstance(a.ElementType)); + } + + SentinelType makeInstanceSentinelType(SentinelType a) { + return new SentinelType(makeInstance(a.ElementType)); + } + + TypeReference makeInstanceTypeDefinition(TypeDefinition a) { + return makeInstanceTypeReference(a); + } + + TypeReference makeInstanceTypeReference(TypeReference a) { + return a; + } + } + + public abstract class MultiTypeRefInstance : RefInstance { + GenericInstanceType git; + + public MultiTypeRefInstance(GenericInstanceType git) { + this.git = git; + } + + protected TypeReference makeInstance(TypeReference tr) { + var type = TypeReferenceInstance.make(tr, git); + checkModified(type, tr); + return type; + } + + protected T getResult(T orig, T newOne) { + return modified ? newOne : orig; + } + } + + public class MethodReferenceInstance : MultiTypeRefInstance { + MethodReference methodReference; + + public static MethodReference make(MethodReference methodReference, GenericInstanceType git) { + if (git == null) + return methodReference; + return new MethodReferenceInstance(methodReference, git).makeInstance(); + } + + MethodReferenceInstance(MethodReference methodReference, GenericInstanceType git) + : base(git) { + this.methodReference = methodReference; + } + + MethodReference makeInstance() { + var mr = new MethodReference(methodReference.Name, makeInstance(methodReference.MethodReturnType.ReturnType), methodReference.DeclaringType); + mr.HasThis = methodReference.HasThis; + mr.ExplicitThis = methodReference.ExplicitThis; + mr.CallingConvention = methodReference.CallingConvention; + + if (methodReference.HasParameters) { + foreach (var param in methodReference.Parameters) { + var newParam = new ParameterDefinition(param.Name, param.Attributes, makeInstance(param.ParameterType)); + mr.Parameters.Add(newParam); + } + } + + if (methodReference.HasGenericParameters) { + foreach (var param in methodReference.GenericParameters) { + var newParam = new GenericParameter(param.Name, mr); + mr.GenericParameters.Add(newParam); + } + } + + return getResult(methodReference, mr); + } + } + + public class FieldReferenceInstance : MultiTypeRefInstance { + FieldReference fieldReference; + + public static FieldReference make(FieldReference fieldReference, GenericInstanceType git) { + if (git == null) + return fieldReference; + return new FieldReferenceInstance(fieldReference, git).makeInstance(); + } + + FieldReferenceInstance(FieldReference fieldReference, GenericInstanceType git) + : base(git) { + this.fieldReference = fieldReference; + } + + FieldReference makeInstance() { + var fr = new FieldReference(fieldReference.Name, makeInstance(fieldReference.FieldType)); + return getResult(fieldReference, fr); + } + } + + public class EventReferenceInstance : MultiTypeRefInstance { + EventReference eventReference; + + public static EventReference make(EventReference eventReference, GenericInstanceType git) { + if (git == null) + return eventReference; + return new EventReferenceInstance(eventReference, git).makeInstance(); + } + + EventReferenceInstance(EventReference eventReference, GenericInstanceType git) + : base(git) { + this.eventReference = eventReference; + } + + EventReference makeInstance() { + var er = new EventDefinition(eventReference.Name, (EventAttributes)0, makeInstance(eventReference.EventType)); + return getResult(eventReference, er); + } + } + + public class PropertyReferenceInstance : MultiTypeRefInstance { + PropertyReference propertyReference; + + public static PropertyReference make(PropertyReference propertyReference, GenericInstanceType git) { + if (git == null) + return propertyReference; + return new PropertyReferenceInstance(propertyReference, git).makeInstance(); + } + + PropertyReferenceInstance(PropertyReference propertyReference, GenericInstanceType git) + : base(git) { + this.propertyReference = propertyReference; + } + + PropertyReference makeInstance() { + var pr = new PropertyDefinition(propertyReference.Name, (PropertyAttributes)0, makeInstance(propertyReference.PropertyType)); + if (propertyReference.Parameters != null) { + foreach (var param in propertyReference.Parameters) { + var newParam = new ParameterDefinition(param.Name, param.Attributes, makeInstance(param.ParameterType)); + pr.Parameters.Add(newParam); + } + } + + return getResult(propertyReference, pr); + } + } +} diff --git a/blocks/MemberReferenceExpander.cs b/blocks/MemberReferenceExpander.cs deleted file mode 100644 index 7503cd93..00000000 --- a/blocks/MemberReferenceExpander.cs +++ /dev/null @@ -1,244 +0,0 @@ -/* - Copyright (C) 2011 de4dot@gmail.com - - This file is part of de4dot. - - de4dot is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - de4dot is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with de4dot. If not, see . -*/ - -using System; -using Mono.Cecil; - -namespace de4dot.blocks { - public abstract class Expander { - protected bool modified = false; - - protected void checkModified(object a, object b) { - if (!ReferenceEquals(a, b)) - modified = true; - } - } - - public class TypeReferenceExpander : Expander { - TypeReference typeReference; - GenericInstanceType git; - - public TypeReferenceExpander(TypeReference typeReference, GenericInstanceType git) { - this.typeReference = typeReference; - this.git = git; - } - - // Returns same one if nothing was expanded - public TypeReference expand() { - var rv = expandType(typeReference); - return modified ? rv : typeReference; - } - - TypeReference expandType(TypeReference a) { - if (a == null) - return null; - - var type = MemberReferenceHelper.getMemberReferenceType(a); - switch (type) { - case CecilType.ArrayType: - return expandArrayType((ArrayType)a); - case CecilType.ByReferenceType: - return expandByReferenceType((ByReferenceType)a); - case CecilType.FunctionPointerType: - return expandFunctionPointerType((FunctionPointerType)a); - case CecilType.GenericInstanceType: - return expandGenericInstanceType((GenericInstanceType)a); - case CecilType.GenericParameter: - return expandGenericParameter((GenericParameter)a); - case CecilType.OptionalModifierType: - return expandOptionalModifierType((OptionalModifierType)a); - case CecilType.PinnedType: - return expandPinnedType((PinnedType)a); - case CecilType.PointerType: - return expandPointerType((PointerType)a); - case CecilType.RequiredModifierType: - return expandRequiredModifierType((RequiredModifierType)a); - case CecilType.SentinelType: - return expandSentinelType((SentinelType)a); - case CecilType.TypeDefinition: - return expandTypeDefinition((TypeDefinition)a); - case CecilType.TypeReference: - return expandTypeReference((TypeReference)a); - default: - throw new ApplicationException(string.Format("Unknown cecil type {0}", type)); - } - } - - ArrayType expandArrayType(ArrayType a) { - var rv = new ArrayType(expandType(a.ElementType)); - if (!a.IsVector) { - foreach (var dim in a.Dimensions) - rv.Dimensions.Add(dim); - } - return rv; - } - - ByReferenceType expandByReferenceType(ByReferenceType a) { - return new ByReferenceType(expandType(a.ElementType)); - } - - FunctionPointerType expandFunctionPointerType(FunctionPointerType a) { - var rv = new FunctionPointerType(); - rv.function = new MethodReferenceExpander(a.function, git).expand(); - checkModified(a.function, rv.function); - return rv; - } - - GenericInstanceType expandGenericInstanceType(GenericInstanceType a) { - var rv = new GenericInstanceType(expandType(a.ElementType)); - foreach (var arg in a.GenericArguments) - rv.GenericArguments.Add(expandType(arg)); - return rv; - } - - TypeReference expandGenericParameter(GenericParameter a) { - if (!MemberReferenceHelper.compareTypes(a.Owner as TypeReference, git.ElementType)) - return a; - modified = true; - return expandType(git.GenericArguments[a.Position]); - } - - OptionalModifierType expandOptionalModifierType(OptionalModifierType a) { - return new OptionalModifierType(expandType(a.ModifierType), expandType(a.ElementType)); - } - - PinnedType expandPinnedType(PinnedType a) { - return new PinnedType(expandType(a.ElementType)); - } - - PointerType expandPointerType(PointerType a) { - return new PointerType(expandType(a.ElementType)); - } - - RequiredModifierType expandRequiredModifierType(RequiredModifierType a) { - return new RequiredModifierType(expandType(a.ModifierType), expandType(a.ElementType)); - } - - SentinelType expandSentinelType(SentinelType a) { - return new SentinelType(expandType(a.ElementType)); - } - - TypeReference expandTypeDefinition(TypeDefinition a) { - return expandTypeReference(a); - } - - TypeReference expandTypeReference(TypeReference a) { - return a; - } - } - - public abstract class MultiTypeExpander : Expander { - GenericInstanceType git; - - public MultiTypeExpander(GenericInstanceType git) { - this.git = git; - } - - protected TypeReference expandType(TypeReference tr) { - var type = new TypeReferenceExpander(tr, git).expand(); - checkModified(type, tr); - return type; - } - - protected T getResult(T orig, T expanded) { - return modified ? expanded : orig; - } - } - - public class MethodReferenceExpander : MultiTypeExpander { - MethodReference methodReference; - - public MethodReferenceExpander(MethodReference methodReference, GenericInstanceType git) - : base(git) { - this.methodReference = methodReference; - } - - public MethodReference expand() { - var mr = new MethodReference(methodReference.Name, expandType(methodReference.MethodReturnType.ReturnType), methodReference.DeclaringType); - mr.HasThis = methodReference.HasThis; - mr.ExplicitThis = methodReference.ExplicitThis; - mr.CallingConvention = methodReference.CallingConvention; - - if (methodReference.HasParameters) { - foreach (var param in methodReference.Parameters) { - var newParam = new ParameterDefinition(param.Name, param.Attributes, expandType(param.ParameterType)); - mr.Parameters.Add(newParam); - } - } - - if (methodReference.HasGenericParameters) { - foreach (var param in methodReference.GenericParameters) { - var newParam = new GenericParameter(param.Name, mr); - mr.GenericParameters.Add(newParam); - } - } - - return getResult(methodReference, mr); - } - } - - public class FieldReferenceExpander : MultiTypeExpander { - FieldReference fieldReference; - - public FieldReferenceExpander(FieldReference fieldReference, GenericInstanceType git) - : base(git) { - this.fieldReference = fieldReference; - } - - public FieldReference expand() { - var fr = new FieldReference(fieldReference.Name, expandType(fieldReference.FieldType)); - return getResult(fieldReference, fr); - } - } - - public class EventReferenceExpander : MultiTypeExpander { - EventReference eventReference; - - public EventReferenceExpander(EventReference eventReference, GenericInstanceType git) - : base(git) { - this.eventReference = eventReference; - } - - public EventReference expand() { - var er = new EventDefinition(eventReference.Name, (EventAttributes)0, expandType(eventReference.EventType)); - return getResult(eventReference, er); - } - } - - public class PropertyReferenceExpander : MultiTypeExpander { - PropertyReference propertyReference; - - public PropertyReferenceExpander(PropertyReference propertyReference, GenericInstanceType git) - : base(git) { - this.propertyReference = propertyReference; - } - - public PropertyReference expand() { - var pr = new PropertyDefinition(propertyReference.Name, (PropertyAttributes)0, expandType(propertyReference.PropertyType)); - if (propertyReference.Parameters != null) { - foreach (var param in propertyReference.Parameters) { - var newParam = new ParameterDefinition(param.Name, param.Attributes, expandType(param.ParameterType)); - pr.Parameters.Add(newParam); - } - } - - return getResult(propertyReference, pr); - } - } -} diff --git a/blocks/blocks.csproj b/blocks/blocks.csproj index 2e4cd484..63da0cbe 100644 --- a/blocks/blocks.csproj +++ b/blocks/blocks.csproj @@ -59,7 +59,7 @@ - + diff --git a/de4dot.code/old_renamer/ExternalAssemblies.cs b/de4dot.code/old_renamer/ExternalAssemblies.cs index 8204cda8..9f0b8c34 100644 --- a/de4dot.code/old_renamer/ExternalAssemblies.cs +++ b/de4dot.code/old_renamer/ExternalAssemblies.cs @@ -50,7 +50,7 @@ namespace de4dot.old_renamer { Dictionary assemblies = new Dictionary(); ExternalAssembly load(TypeReference type) { - var asmFullName = DotNetUtils.getFullAssemblyName(type.Scope); + var asmFullName = DotNetUtils.getFullAssemblyName(type); ExternalAssembly asm; if (assemblies.TryGetValue(asmFullName, out asm)) return asm; diff --git a/de4dot.code/old_renamer/RefExpander.cs b/de4dot.code/old_renamer/RefExpander.cs index 1abe3300..d9ccd408 100644 --- a/de4dot.code/old_renamer/RefExpander.cs +++ b/de4dot.code/old_renamer/RefExpander.cs @@ -35,19 +35,19 @@ namespace de4dot.old_renamer { } protected MethodReference expandMethodReference(MethodReference methodReference) { - var mr = new MethodReferenceExpander(methodReference, git).expand(); + var mr = MethodReferenceInstance.make(methodReference, git); checkModified(methodReference, mr); return mr; } protected EventReference expandEventReference(EventReference eventReference) { - var er = new EventReferenceExpander(eventReference, git).expand(); + var er = EventReferenceInstance.make(eventReference, git); checkModified(eventReference, er); return er; } protected PropertyReference expandPropertyReference(PropertyReference propertyReference) { - var pr = new PropertyReferenceExpander(propertyReference, git).expand(); + var pr = PropertyReferenceInstance.make(propertyReference, git); checkModified(propertyReference, pr); return pr; }