de4dot-cex/de4dot.code/renamer/asmmodules/Module.cs

259 lines
8.3 KiB
C#
Raw Normal View History

2011-11-15 21:26:51 +08:00
/*
2012-01-10 06:02:47 +08:00
Copyright (C) 2011-2012 de4dot@gmail.com
2011-11-15 21:26:51 +08:00
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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using dot10.DotNet;
2012-11-03 03:10:34 +08:00
using dot10.DotNet.MD;
2011-11-15 21:26:51 +08:00
using de4dot.blocks;
namespace de4dot.code.renamer.asmmodules {
2011-11-15 21:26:51 +08:00
class Module : IResolver {
IObfuscatedFile obfuscatedFile;
TypeDefDict types = new TypeDefDict();
MemberRefFinder memberRefFinder;
2012-11-03 03:10:34 +08:00
IList<RefToDef<TypeRef, TypeDef>> typeRefsToRename = new List<RefToDef<TypeRef, TypeDef>>();
IList<RefToDef<MemberRef, MethodDef>> methodRefsToRename = new List<RefToDef<MemberRef, MethodDef>>();
IList<RefToDef<MemberRef, FieldDef>> fieldRefsToRename = new List<RefToDef<MemberRef, FieldDef>>();
List<CustomAttributeReference> customAttributeFieldReferences = new List<CustomAttributeReference>();
List<CustomAttributeReference> customAttributePropertyReferences = new List<CustomAttributeReference>();
List<MethodDef> allMethods;
2011-11-15 21:26:51 +08:00
public class CustomAttributeReference {
public CustomAttribute cattr;
public int index;
2012-11-03 03:10:34 +08:00
public IMemberRef reference;
public CustomAttributeReference(CustomAttribute cattr, int index, IMemberRef reference) {
this.cattr = cattr;
this.index = index;
this.reference = reference;
}
}
2012-11-03 03:10:34 +08:00
public class RefToDef<R, D> where R : ICodedToken where D : ICodedToken {
2011-11-15 21:26:51 +08:00
public R reference;
public D definition;
public RefToDef(R reference, D definition) {
this.reference = reference;
this.definition = definition;
}
}
2012-11-03 03:10:34 +08:00
public IEnumerable<RefToDef<TypeRef, TypeDef>> TypeRefsToRename {
2011-11-18 23:55:54 +08:00
get { return typeRefsToRename; }
}
2012-11-03 03:10:34 +08:00
public IEnumerable<RefToDef<MemberRef, MethodDef>> MethodRefsToRename {
2011-11-18 23:55:54 +08:00
get { return methodRefsToRename; }
}
2012-11-03 03:10:34 +08:00
public IEnumerable<RefToDef<MemberRef, FieldDef>> FieldRefsToRename {
2011-11-18 23:55:54 +08:00
get { return fieldRefsToRename; }
}
public IEnumerable<CustomAttributeReference> CustomAttributeFieldReferences {
get { return customAttributeFieldReferences; }
}
public IEnumerable<CustomAttributeReference> CustomAttributePropertyReferences {
get { return customAttributePropertyReferences; }
}
2011-11-17 11:17:03 +08:00
public IObfuscatedFile ObfuscatedFile {
get { return obfuscatedFile; }
}
2011-11-15 21:26:51 +08:00
public string Filename {
get { return obfuscatedFile.Filename; }
}
public ModuleDefMD ModuleDefMD {
get { return obfuscatedFile.ModuleDefMD; }
2011-11-15 21:26:51 +08:00
}
public Module(IObfuscatedFile obfuscatedFile) {
this.obfuscatedFile = obfuscatedFile;
}
public IEnumerable<MTypeDef> getAllTypes() {
2012-01-01 19:09:16 +08:00
return types.getValues();
2011-11-15 21:26:51 +08:00
}
public IEnumerable<MethodDef> getAllMethods() {
2011-11-21 17:36:23 +08:00
return allMethods;
}
2011-11-15 21:26:51 +08:00
public void findAllMemberReferences(ref int typeIndex) {
memberRefFinder = new MemberRefFinder();
2012-11-03 03:10:34 +08:00
memberRefFinder.findAll(ModuleDefMD);
allMethods = new List<MethodDef>(memberRefFinder.methodDefs.Keys);
2011-11-15 21:26:51 +08:00
var allTypesList = new List<MTypeDef>();
2012-11-03 03:10:34 +08:00
foreach (var type in memberRefFinder.typeDefs.Keys) {
var typeDef = new MTypeDef(type, this, typeIndex++);
2011-11-15 21:26:51 +08:00
types.add(typeDef);
allTypesList.Add(typeDef);
typeDef.addMembers();
}
var allTypesCopy = new List<MTypeDef>(allTypesList);
var typeToIndex = new Dictionary<TypeDef, int>();
2011-11-15 21:26:51 +08:00
for (int i = 0; i < allTypesList.Count; i++)
typeToIndex[allTypesList[i].TypeDef] = i;
2011-11-15 21:26:51 +08:00
foreach (var typeDef in allTypesList) {
if (typeDef.TypeDef.NestedTypes == null)
2011-11-15 21:26:51 +08:00
continue;
foreach (var nestedTypeDefinition in typeDef.TypeDef.NestedTypes) {
2011-11-15 21:26:51 +08:00
int index = typeToIndex[nestedTypeDefinition];
var nestedTypeDef = allTypesCopy[index];
allTypesCopy[index] = null;
if (nestedTypeDef == null) // Impossible
throw new ApplicationException("Nested type belongs to two or more types");
typeDef.add(nestedTypeDef);
nestedTypeDef.NestingType = typeDef;
}
}
}
public void resolveAllRefs(IResolver resolver) {
2012-11-03 03:10:34 +08:00
foreach (var typeRef in memberRefFinder.typeRefs.Keys) {
var typeDef = resolver.resolveType(typeRef);
2011-11-15 21:26:51 +08:00
if (typeDef != null)
2012-11-03 03:10:34 +08:00
typeRefsToRename.Add(new RefToDef<TypeRef, TypeDef>(typeRef, typeDef.TypeDef));
2011-11-15 21:26:51 +08:00
}
2012-11-03 03:10:34 +08:00
foreach (var memberRef in memberRefFinder.memberRefs.Keys) {
if (memberRef.IsMethodRef) {
var methodDef = resolver.resolveMethod(memberRef);
if (methodDef != null)
methodRefsToRename.Add(new RefToDef<MemberRef, MethodDef>(memberRef, methodDef.MethodDef));
}
else if (memberRef.IsFieldRef) {
var fieldDef = resolver.resolveField(memberRef);
if (fieldDef != null)
fieldRefsToRename.Add(new RefToDef<MemberRef, FieldDef>(memberRef, fieldDef.FieldDef));
}
2011-11-15 21:26:51 +08:00
}
foreach (var cattr in memberRefFinder.customAttributes.Keys) {
2012-11-03 03:10:34 +08:00
var typeDef = resolver.resolveType(cattr.AttributeType);
if (typeDef == null)
continue;
2012-11-03 03:10:34 +08:00
for (int i = 0; i < cattr.NamedArguments.Count; i++) {
var namedArg = cattr.NamedArguments[i];
if (namedArg.IsField) {
var fieldDef = findField(typeDef, namedArg.Name, namedArg.Type);
if (fieldDef == null) {
Log.w("Could not find field {0} in attribute {1} ({2:X8})",
2012-11-03 03:10:34 +08:00
Utils.toCsharpString(namedArg.Name),
Utils.toCsharpString(typeDef.TypeDef.Name),
typeDef.TypeDef.MDToken.ToInt32());
continue;
}
customAttributeFieldReferences.Add(new CustomAttributeReference(cattr, i, fieldDef.FieldDef));
}
2012-11-03 03:10:34 +08:00
else {
var propDef = findProperty(typeDef, namedArg.Name, namedArg.Type);
if (propDef == null) {
Log.w("Could not find property {0} in attribute {1} ({2:X8})",
2012-11-03 03:10:34 +08:00
Utils.toCsharpString(namedArg.Name),
Utils.toCsharpString(typeDef.TypeDef.Name),
typeDef.TypeDef.MDToken.ToInt32());
continue;
}
customAttributePropertyReferences.Add(new CustomAttributeReference(cattr, i, propDef.PropertyDef));
}
}
}
}
2012-11-03 03:10:34 +08:00
static MFieldDef findField(MTypeDef typeDef, UTF8String name, TypeSig fieldType) {
2012-03-04 01:23:53 +08:00
while (typeDef != null) {
foreach (var fieldDef in typeDef.AllFields) {
2012-11-03 03:10:34 +08:00
if (fieldDef.FieldDef.Name != name)
continue;
if (new SigComparer().Equals(fieldDef.FieldDef.FieldSig.Type, fieldType))
2012-03-04 01:23:53 +08:00
return fieldDef;
}
if (typeDef.baseType == null)
break;
typeDef = typeDef.baseType.typeDef;
}
return null;
}
2012-11-03 03:10:34 +08:00
static MPropertyDef findProperty(MTypeDef typeDef, UTF8String name, TypeSig propType) {
2012-03-04 01:23:53 +08:00
while (typeDef != null) {
foreach (var propDef in typeDef.AllProperties) {
2012-11-03 03:10:34 +08:00
if (propDef.PropertyDef.Name != name)
continue;
if (new SigComparer().Equals(propDef.PropertyDef.PropertySig.RetType, propType))
2012-03-04 01:23:53 +08:00
return propDef;
}
if (typeDef.baseType == null)
break;
typeDef = typeDef.baseType.typeDef;
}
return null;
2011-11-15 21:26:51 +08:00
}
2011-11-18 23:55:54 +08:00
public void onTypesRenamed() {
var newTypes = new TypeDefDict();
2012-01-01 19:09:16 +08:00
foreach (var typeDef in types.getValues()) {
2011-11-18 23:55:54 +08:00
typeDef.onTypesRenamed();
newTypes.add(typeDef);
}
types = newTypes;
}
2012-11-03 03:10:34 +08:00
static ITypeDefOrRef getNonGenericTypeReference(ITypeDefOrRef typeRef) {
var ts = typeRef as TypeSpec;
if (ts == null)
return typeRef;
var gis = ts.TypeSig.RemovePinnedAndModifiers() as GenericInstSig;
if (gis == null || gis.GenericType == null)
return typeRef;
return gis.GenericType.TypeDefOrRef;
2011-11-15 21:26:51 +08:00
}
2012-11-03 03:10:34 +08:00
public MTypeDef resolveType(ITypeDefOrRef typeReference) {
2011-11-15 21:26:51 +08:00
return this.types.find(getNonGenericTypeReference(typeReference));
}
2012-11-04 07:50:24 +08:00
public MMethodDef resolveMethod(IMethodDefOrRef methodRef) {
2012-11-03 03:10:34 +08:00
var typeDef = this.types.find(getNonGenericTypeReference(methodRef.DeclaringType));
2011-11-15 21:26:51 +08:00
if (typeDef == null)
return null;
2012-11-03 03:10:34 +08:00
return typeDef.findMethod(methodRef);
2011-11-15 21:26:51 +08:00
}
2012-11-03 03:10:34 +08:00
public MFieldDef resolveField(MemberRef fieldRef) {
var typeDef = this.types.find(getNonGenericTypeReference(fieldRef.DeclaringType));
2011-11-15 21:26:51 +08:00
if (typeDef == null)
return null;
2012-11-03 03:10:34 +08:00
return typeDef.findField(fieldRef);
2011-11-15 21:26:51 +08:00
}
}
}