de4dot-cex/AssemblyData/methodsrewriter/Resolver.cs

222 lines
6.3 KiB
C#
Raw Normal View History

2011-09-27 07:48:47 +08:00
/*
2012-01-10 06:02:47 +08:00
Copyright (C) 2011-2012 de4dot@gmail.com
2011-09-27 07:48:47 +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 System.Reflection;
2012-11-01 05:44:54 +08:00
using dot10.DotNet;
2011-09-27 07:48:47 +08:00
using de4dot.blocks;
namespace AssemblyData.methodsrewriter {
2011-09-28 04:06:43 +08:00
static class Resolver {
2011-09-27 07:48:47 +08:00
static Dictionary<string, AssemblyResolver> assemblyResolvers = new Dictionary<string, AssemblyResolver>(StringComparer.Ordinal);
2011-09-28 04:06:43 +08:00
static Dictionary<Module, MModule> modules = new Dictionary<Module, MModule>();
public static MModule loadAssembly(Module module) {
MModule info;
if (modules.TryGetValue(module, out info))
return info;
2012-11-01 05:44:54 +08:00
info = new MModule(module, ModuleDefMD.Load(module.FullyQualifiedName));
2011-09-28 04:06:43 +08:00
modules[module] = info;
return info;
}
2012-11-01 05:44:54 +08:00
static MModule getModule(ModuleDef moduleDef) {
2011-09-28 04:06:43 +08:00
foreach (var mm in modules.Values) {
2012-11-01 05:44:54 +08:00
if (mm.moduleDef == moduleDef)
2011-09-28 04:06:43 +08:00
return mm;
}
return null;
}
2012-11-01 05:44:54 +08:00
static MModule getModule(AssemblyRef asmRef) {
2011-09-28 04:06:43 +08:00
foreach (var mm in modules.Values) {
2012-11-01 05:44:54 +08:00
var asm = mm.moduleDef.Assembly;
if (asm != null && asm.FullName == asmRef.FullName)
2011-09-28 04:06:43 +08:00
return mm;
}
return null;
}
2012-11-01 05:44:54 +08:00
public static MModule getModule(IScope scope) {
if (scope.ScopeType == ScopeType.ModuleDef)
return getModule((ModuleDef)scope);
else if (scope.ScopeType == ScopeType.AssemblyRef)
return getModule((AssemblyRef)scope);
2011-09-28 04:06:43 +08:00
return null;
}
2012-11-01 14:34:40 +08:00
public static MType getType(IType typeRef) {
2012-11-01 05:44:54 +08:00
if (typeRef == null)
return null;
2012-11-01 05:44:54 +08:00
var module = getModule(typeRef.Scope);
2011-09-28 04:06:43 +08:00
if (module != null)
2012-11-01 05:44:54 +08:00
return module.getType(typeRef);
2011-09-28 04:06:43 +08:00
return null;
}
2012-11-22 16:14:51 +08:00
public static MMethod getMethod(IMethod methodRef) {
if (methodRef == null)
return null;
2012-11-22 16:14:51 +08:00
var module = getModule(methodRef.DeclaringType.Scope);
2011-09-28 04:06:43 +08:00
if (module != null)
2012-11-22 16:14:51 +08:00
return module.getMethod(methodRef);
2011-09-28 04:06:43 +08:00
return null;
}
2012-11-22 16:14:51 +08:00
public static MField getField(IField fieldRef) {
if (fieldRef == null)
return null;
2012-11-22 16:14:51 +08:00
var module = getModule(fieldRef.DeclaringType.Scope);
2011-09-28 04:06:43 +08:00
if (module != null)
2012-11-22 16:14:51 +08:00
return module.getField(fieldRef);
2011-09-28 04:06:43 +08:00
return null;
}
2012-11-01 05:44:54 +08:00
public static object getRtObject(ITokenOperand memberRef) {
if (memberRef == null)
return null;
2012-11-06 02:21:33 +08:00
var tdr = memberRef as ITypeDefOrRef;
if (tdr != null)
return getRtType(tdr);
var field = memberRef as IField;
if (field != null && field.FieldSig != null)
return getRtField(field);
var method = memberRef as IMethod;
if (method != null && method.MethodSig != null)
return getRtMethod(method);
2011-09-28 04:06:43 +08:00
2012-11-22 16:14:51 +08:00
throw new ApplicationException(string.Format("Unknown MemberRef: {0}", memberRef));
2011-09-28 04:06:43 +08:00
}
2012-11-01 14:34:40 +08:00
public static Type getRtType(IType typeRef) {
2012-11-01 05:44:54 +08:00
var mtype = getType(typeRef);
2011-09-28 04:06:43 +08:00
if (mtype != null)
return mtype.type;
2012-11-01 05:44:54 +08:00
return Resolver.resolve(typeRef);
2011-09-28 04:06:43 +08:00
}
2012-11-01 05:44:54 +08:00
public static FieldInfo getRtField(IField fieldRef) {
var mfield = getField(fieldRef);
2011-09-28 04:06:43 +08:00
if (mfield != null)
return mfield.fieldInfo;
2012-11-01 05:44:54 +08:00
return Resolver.resolve(fieldRef);
2011-09-28 04:06:43 +08:00
}
2012-11-01 05:44:54 +08:00
public static MethodBase getRtMethod(IMethod methodRef) {
var mmethod = getMethod(methodRef);
2011-09-28 04:06:43 +08:00
if (mmethod != null)
return mmethod.methodBase;
2012-11-01 05:44:54 +08:00
return Resolver.resolve(methodRef);
2011-09-28 04:06:43 +08:00
}
2011-09-27 07:48:47 +08:00
2012-11-01 05:44:54 +08:00
static AssemblyResolver getAssemblyResolver(ITypeDefOrRef type) {
var asmName = type.DefinitionAssembly.FullName;
2011-09-27 07:48:47 +08:00
AssemblyResolver resolver;
if (!assemblyResolvers.TryGetValue(asmName, out resolver))
assemblyResolvers[asmName] = resolver = new AssemblyResolver(asmName);
return resolver;
}
2012-11-01 05:44:54 +08:00
static Type resolve(IType typeRef) {
if (typeRef == null)
return null;
2012-11-01 14:34:40 +08:00
var scopeType = typeRef.ScopeType;
var resolver = getAssemblyResolver(scopeType);
var resolvedType = resolver.resolve(scopeType);
2011-09-27 07:48:47 +08:00
if (resolvedType != null)
2012-11-01 05:44:54 +08:00
return fixType(typeRef, resolvedType);
2012-11-06 02:21:33 +08:00
throw new ApplicationException(string.Format("Could not resolve type {0} ({1:X8}) in assembly {2}", typeRef, typeRef.MDToken.Raw, resolver));
2011-09-27 07:48:47 +08:00
}
2012-11-01 05:44:54 +08:00
static FieldInfo resolve(IField fieldRef) {
if (fieldRef == null)
return null;
2012-11-01 05:44:54 +08:00
var resolver = getAssemblyResolver(fieldRef.DeclaringType);
var fieldInfo = resolver.resolve(fieldRef);
2011-09-27 07:48:47 +08:00
if (fieldInfo != null)
return fieldInfo;
2012-11-01 05:44:54 +08:00
throw new ApplicationException(string.Format("Could not resolve field {0} ({1:X8}) in assembly {2}", fieldRef, fieldRef.MDToken.Raw, resolver));
2011-09-27 07:48:47 +08:00
}
2012-11-01 05:44:54 +08:00
static MethodBase resolve(IMethod methodRef) {
if (methodRef == null)
return null;
2012-11-01 05:44:54 +08:00
var resolver = getAssemblyResolver(methodRef.DeclaringType);
var methodBase = resolver.resolve(methodRef);
2011-09-27 07:48:47 +08:00
if (methodBase != null)
return methodBase;
2012-11-01 05:44:54 +08:00
throw new ApplicationException(string.Format("Could not resolve method {0} ({1:X8}) in assembly {2}", methodRef, methodRef.MDToken.Raw, resolver));
2011-09-27 07:48:47 +08:00
}
2012-11-01 14:34:40 +08:00
static Type fixType(IType typeRef, Type type) {
var sig = typeRef as TypeSig;
2012-11-06 02:21:33 +08:00
if (sig == null) {
2012-11-01 14:34:40 +08:00
var ts = typeRef as TypeSpec;
if (ts != null)
sig = ts.TypeSig;
}
2012-11-01 05:44:54 +08:00
while (sig != null) {
switch (sig.ElementType) {
case ElementType.SZArray:
type = type.MakeArrayType();
break;
2011-09-27 07:48:47 +08:00
2012-11-01 05:44:54 +08:00
case ElementType.Array:
type = type.MakeArrayType((int)((ArraySig)sig).Rank);
break;
case ElementType.ByRef:
2011-09-27 07:48:47 +08:00
type = type.MakeByRefType();
2012-11-01 05:44:54 +08:00
break;
case ElementType.Ptr:
2011-09-27 07:48:47 +08:00
type = type.MakePointerType();
2012-11-01 05:44:54 +08:00
break;
case ElementType.GenericInst:
var git = (GenericInstSig)sig;
2011-09-27 07:48:47 +08:00
var args = new Type[git.GenericArguments.Count];
bool isGenericTypeDef = true;
for (int i = 0; i < args.Length; i++) {
2012-11-01 05:44:54 +08:00
var arg = git.GenericArguments[i];
if (!(arg is GenericSig))
2011-09-27 07:48:47 +08:00
isGenericTypeDef = false;
2012-11-01 05:44:54 +08:00
args[i] = Resolver.resolve(arg);
2011-09-27 07:48:47 +08:00
}
if (!isGenericTypeDef)
type = type.MakeGenericType(args);
2012-11-01 05:44:54 +08:00
break;
default:
break;
2011-09-27 07:48:47 +08:00
}
2012-11-01 05:44:54 +08:00
sig = sig.Next;
2011-09-27 07:48:47 +08:00
}
return type;
}
}
}