de4dot-cex/AssemblyData/methodsrewriter/Resolver.cs

222 lines
6.3 KiB
C#
Raw Permalink Normal View History

2011-09-27 07:48:47 +08:00
/*
2015-10-30 05:45:26 +08:00
Copyright (C) 2011-2015 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;
using dnlib.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>();
2013-01-19 20:03:57 +08:00
public static MModule LoadAssembly(Module module) {
2011-09-28 04:06:43 +08:00
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;
}
2013-01-19 20:03:57 +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;
}
2013-01-19 20:03:57 +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;
}
2013-01-19 20:03:57 +08:00
public static MModule GetModule(IScope scope) {
2012-11-01 05:44:54 +08:00
if (scope.ScopeType == ScopeType.ModuleDef)
2013-01-19 20:03:57 +08:00
return GetModule((ModuleDef)scope);
2012-11-01 05:44:54 +08:00
else if (scope.ScopeType == ScopeType.AssemblyRef)
2013-01-19 20:03:57 +08:00
return GetModule((AssemblyRef)scope);
2011-09-28 04:06:43 +08:00
return null;
}
2013-01-19 20:03:57 +08:00
public static MType GetType(IType typeRef) {
2012-11-01 05:44:54 +08:00
if (typeRef == null)
return null;
2013-01-19 20:03:57 +08:00
var module = GetModule(typeRef.Scope);
2011-09-28 04:06:43 +08:00
if (module != null)
2013-01-19 20:03:57 +08:00
return module.GetType(typeRef);
2011-09-28 04:06:43 +08:00
return null;
}
2013-01-19 20:03:57 +08:00
public static MMethod GetMethod(IMethod methodRef) {
2012-11-22 16:14:51 +08:00
if (methodRef == null)
return null;
2013-01-19 20:03:57 +08:00
var module = GetModule(methodRef.DeclaringType.Scope);
2011-09-28 04:06:43 +08:00
if (module != null)
2013-01-19 20:03:57 +08:00
return module.GetMethod(methodRef);
2011-09-28 04:06:43 +08:00
return null;
}
2013-01-19 20:03:57 +08:00
public static MField GetField(IField fieldRef) {
2012-11-22 16:14:51 +08:00
if (fieldRef == null)
return null;
2013-01-19 20:03:57 +08:00
var module = GetModule(fieldRef.DeclaringType.Scope);
2011-09-28 04:06:43 +08:00
if (module != null)
2013-01-19 20:03:57 +08:00
return module.GetField(fieldRef);
2011-09-28 04:06:43 +08:00
return null;
}
2013-01-19 20:03:57 +08:00
public static object GetRtObject(ITokenOperand memberRef) {
2012-11-01 05:44:54 +08:00
if (memberRef == null)
return null;
2012-11-06 02:21:33 +08:00
var tdr = memberRef as ITypeDefOrRef;
if (tdr != null)
2013-01-19 20:03:57 +08:00
return GetRtType(tdr);
2012-11-06 02:21:33 +08:00
var field = memberRef as IField;
if (field != null && field.FieldSig != null)
2013-01-19 20:03:57 +08:00
return GetRtField(field);
2012-11-06 02:21:33 +08:00
var method = memberRef as IMethod;
if (method != null && method.MethodSig != null)
2013-01-19 20:03:57 +08:00
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
}
2013-01-19 20:03:57 +08:00
public static Type GetRtType(IType typeRef) {
var mtype = GetType(typeRef);
2011-09-28 04:06:43 +08:00
if (mtype != null)
return mtype.type;
2013-01-19 20:03:57 +08:00
return Resolver.Resolve(typeRef);
2011-09-28 04:06:43 +08:00
}
2013-01-19 20:03:57 +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;
2013-01-19 20:03:57 +08:00
return Resolver.Resolve(fieldRef);
2011-09-28 04:06:43 +08:00
}
2013-01-19 20:03:57 +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;
2013-01-19 20:03:57 +08:00
return Resolver.Resolve(methodRef);
2011-09-28 04:06:43 +08:00
}
2011-09-27 07:48:47 +08:00
2013-01-19 20:03:57 +08:00
static AssemblyResolver GetAssemblyResolver(ITypeDefOrRef type) {
2012-11-01 05:44:54 +08:00
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;
}
2013-01-19 20:03:57 +08:00
static Type Resolve(IType typeRef) {
2012-11-01 05:44:54 +08:00
if (typeRef == null)
return null;
2012-11-01 14:34:40 +08:00
var scopeType = typeRef.ScopeType;
2013-01-19 20:03:57 +08:00
var resolver = GetAssemblyResolver(scopeType);
var resolvedType = resolver.Resolve(scopeType);
2011-09-27 07:48:47 +08:00
if (resolvedType != null)
2013-01-19 20:03:57 +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
}
2013-01-19 20:03:57 +08:00
static FieldInfo Resolve(IField fieldRef) {
2012-11-01 05:44:54 +08:00
if (fieldRef == null)
return null;
2013-01-19 20:03:57 +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
}
2013-01-19 20:03:57 +08:00
static MethodBase Resolve(IMethod methodRef) {
2012-11-01 05:44:54 +08:00
if (methodRef == null)
return null;
2013-01-19 20:03:57 +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
}
2013-01-19 20:03:57 +08:00
static Type FixType(IType typeRef, Type type) {
2012-11-01 14:34:40 +08:00
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;
2013-01-19 20:03:57 +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;
}
}
}