de4dot-cex/AssemblyData/methodsrewriter/Resolver.cs

217 lines
6.2 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 05:44:54 +08:00
public static MType getType(ITypeDefOrRef typeRef) {
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-01 05:44:54 +08:00
public static MMethod getMethod(IMethod methodReference) {
if (methodReference == null)
return null;
2011-09-28 04:06:43 +08:00
var module = getModule(methodReference.DeclaringType.Scope);
if (module != null)
return module.getMethod(methodReference);
return null;
}
2012-11-01 05:44:54 +08:00
public static MField getField(IField fieldReference) {
if (fieldReference == null)
return null;
2011-09-28 04:06:43 +08:00
var module = getModule(fieldReference.DeclaringType.Scope);
if (module != null)
return module.getField(fieldReference);
return null;
}
2012-11-01 05:44:54 +08:00
public static object getRtObject(ITokenOperand memberRef) {
if (memberRef == null)
return null;
2012-11-01 05:44:54 +08:00
else if (memberRef is ITypeDefOrRef)
return getRtType((ITypeDefOrRef)memberRef);
else if (memberRef is IField)
return getRtField((IField)memberRef);
else if (memberRef is IMethod)
return getRtMethod((IMethod)memberRef);
2011-09-28 04:06:43 +08:00
2012-11-01 05:44:54 +08:00
throw new ApplicationException(string.Format("Unknown MemberReference: {0}", memberRef));
2011-09-28 04:06:43 +08:00
}
2012-11-01 05:44:54 +08:00
public static Type getRtType(ITypeDefOrRef typeRef) {
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 05:44:54 +08:00
var elemType = typeRef.GetElementType();
2011-11-17 05:56:36 +08:00
var resolver = getAssemblyResolver(elemType);
2011-09-27 07:48:47 +08:00
var resolvedType = resolver.resolve(elemType);
if (resolvedType != null)
2012-11-01 05:44:54 +08:00
return fixType(typeRef, resolvedType);
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 05:44:54 +08:00
static Type fixType(ITypeDefOrRef typeRef, Type type) {
var ts = typeRef as TypeSpec;
if (ts == null)
return type;
var sig = ts.TypeSig;
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;
}
}
}