C# 从动态方法解析IL中找到的令牌
感谢Hans Passant在这里回答我的问题: 我能站起来跑步了。我现在正在尝试解析在发出的IL中找到的元数据标记,以查看调用了哪些方法,或者没有调用哪些方法。我能够确定方法体中的下一个标记是调用。我正在使用Mono.Reflection的MethodBodyReader中的一些代码C# 从动态方法解析IL中找到的令牌,c#,dynamicmethod,C#,Dynamicmethod,感谢Hans Passant在这里回答我的问题: 我能站起来跑步了。我现在正在尝试解析在发出的IL中找到的元数据标记,以查看调用了哪些方法,或者没有调用哪些方法。我能够确定方法体中的下一个标记是调用。我正在使用Mono.Reflection的MethodBodyReader中的一些代码 static byte[] GetILByteArray(Delegate @delegate){ // does stuff mentioned in other thread } ... Expres
static byte[] GetILByteArray(Delegate @delegate){
// does stuff mentioned in other thread
}
...
Expression<Action> foo = () => Console.WriteLine(0);
var compiled = foo.Compile();
var bytes = GetILByteArray(compiled);
int index =Array.FindIndex(bytes,b=>GetOpCode(b).OperandType == OperandType.InlineMethod);
var token = BitConverter.ToInt32(bytes,index+1);
compiled.Method.Module.ResolveMember(token);
static byte[]GetILByteArray(Delegate@Delegate){
//其他线程中提到的东西
}
...
表达式foo=()=>Console.WriteLine(0);
var compiled=foo.Compile();
var bytes=GetILByteArray(已编译);
int index=Array.FindIndex(字节,b=>GetOpCode(b).operantype==operantype.InlineMethod);
var token=BitConverter.ToInt32(字节,索引+1);
compiled.Method.Module.ResolveMember(令牌);
引发一个异常,说明令牌在该域中不可解析。有人有把戏吗?我应该尝试传递委托的通用参数,还是它们完全没有用
我目前正在考虑为表达式树的委托编写一个反编译器,我真的希望能够使用我自己编译的表达式树作为测试用例,因为我可以随时返回原始版本并进行比较。答案是必须使用来解析动态方法的标记,而不是使用
模块
。这是有意义的,因为DynamicMethod.m\u resolver.m\u code
是
这是很困难的,因为DynamicResolver.ResolveToken
返回IntPtr
输出,并将其转换回RuntimeTypeHandle
和RuntimeMethodHandle
等需要大量的反射。此解决方案不太可能在.NET4.x运行时中断,但要注意任何主要的版本更改
没有简明扼要的说法
定义并使用此接口而不是模块
来解析令牌:
public interface ITokenResolver
{
MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments);
Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments);
FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments);
MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments);
byte[] ResolveSignature(int metadataToken);
string ResolveString(int metadataToken);
}
对于非动态方法:
public sealed class ModuleTokenResolver : ITokenResolver
{
private readonly Module module;
public ModuleTokenResolver(Module module)
{
this.module = module;
}
public MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) =>
module.ResolveMember(metadataToken, genericTypeArguments, genericMethodArguments);
public Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) =>
module.ResolveType(metadataToken, genericTypeArguments, genericMethodArguments);
public FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) =>
module.ResolveField(metadataToken, genericTypeArguments, genericMethodArguments);
public MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) =>
module.ResolveMethod(metadataToken, genericTypeArguments, genericMethodArguments);
public byte[] ResolveSignature(int metadataToken) =>
module.ResolveSignature(metadataToken);
public string ResolveString(int metadataToken) =>
module.ResolveString(metadataToken);
}
public sealed class DynamicMethodTokenResolver : ITokenResolver
{
private delegate void TokenResolver(int token, out IntPtr typeHandle, out IntPtr methodHandle, out IntPtr fieldHandle);
private delegate string StringResolver(int token);
private delegate byte[] SignatureResolver(int token, int fromMethod);
private delegate Type GetTypeFromHandleUnsafe(IntPtr handle);
private readonly TokenResolver tokenResolver;
private readonly StringResolver stringResolver;
private readonly SignatureResolver signatureResolver;
private readonly GetTypeFromHandleUnsafe getTypeFromHandleUnsafe;
private readonly MethodInfo getMethodBase;
private readonly ConstructorInfo runtimeMethodHandleInternalCtor;
private readonly ConstructorInfo runtimeFieldHandleStubCtor;
private readonly MethodInfo getFieldInfo;
public DynamicMethodTokenResolver(DynamicMethod dynamicMethod)
{
var resolver = typeof(DynamicMethod).GetField("m_resolver", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(dynamicMethod);
if (resolver == null) throw new ArgumentException("The dynamic method's IL has not been finalized.");
tokenResolver = (TokenResolver)resolver.GetType().GetMethod("ResolveToken", BindingFlags.Instance | BindingFlags.NonPublic).CreateDelegate(typeof(TokenResolver), resolver);
stringResolver = (StringResolver)resolver.GetType().GetMethod("GetStringLiteral", BindingFlags.Instance | BindingFlags.NonPublic).CreateDelegate(typeof(StringResolver), resolver);
signatureResolver = (SignatureResolver)resolver.GetType().GetMethod("ResolveSignature", BindingFlags.Instance | BindingFlags.NonPublic).CreateDelegate(typeof(SignatureResolver), resolver);
getTypeFromHandleUnsafe = (GetTypeFromHandleUnsafe)typeof(Type).GetMethod("GetTypeFromHandleUnsafe", BindingFlags.Static | BindingFlags.NonPublic, null, new[] { typeof(IntPtr) }, null).CreateDelegate(typeof(GetTypeFromHandleUnsafe), null);
var runtimeType = typeof(RuntimeTypeHandle).Assembly.GetType("System.RuntimeType");
var runtimeMethodHandleInternal = typeof(RuntimeTypeHandle).Assembly.GetType("System.RuntimeMethodHandleInternal");
getMethodBase = runtimeType.GetMethod("GetMethodBase", BindingFlags.Static | BindingFlags.NonPublic, null, new[] { runtimeType, runtimeMethodHandleInternal }, null);
runtimeMethodHandleInternalCtor = runtimeMethodHandleInternal.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(IntPtr) }, null);
var runtimeFieldInfoStub = typeof(RuntimeTypeHandle).Assembly.GetType("System.RuntimeFieldInfoStub");
runtimeFieldHandleStubCtor = runtimeFieldInfoStub.GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, new[] { typeof(IntPtr), typeof(object) }, null);
getFieldInfo = runtimeType.GetMethod("GetFieldInfo", BindingFlags.Static | BindingFlags.NonPublic, null, new[] { runtimeType, typeof(RuntimeTypeHandle).Assembly.GetType("System.IRuntimeFieldInfo") }, null);
}
public Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
{
IntPtr typeHandle, methodHandle, fieldHandle;
tokenResolver.Invoke(metadataToken, out typeHandle, out methodHandle, out fieldHandle);
return getTypeFromHandleUnsafe.Invoke(typeHandle);
}
public MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
{
IntPtr typeHandle, methodHandle, fieldHandle;
tokenResolver.Invoke(metadataToken, out typeHandle, out methodHandle, out fieldHandle);
return (MethodBase)getMethodBase.Invoke(null, new[]
{
typeHandle == IntPtr.Zero ? null : getTypeFromHandleUnsafe.Invoke(typeHandle),
runtimeMethodHandleInternalCtor.Invoke(new object[] { methodHandle })
});
}
public FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
{
IntPtr typeHandle, methodHandle, fieldHandle;
tokenResolver.Invoke(metadataToken, out typeHandle, out methodHandle, out fieldHandle);
return (FieldInfo)getFieldInfo.Invoke(null, new[]
{
typeHandle == IntPtr.Zero ? null : getTypeFromHandleUnsafe.Invoke(typeHandle),
runtimeFieldHandleStubCtor.Invoke(new object[] { fieldHandle, null })
});
}
public MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
{
IntPtr typeHandle, methodHandle, fieldHandle;
tokenResolver.Invoke(metadataToken, out typeHandle, out methodHandle, out fieldHandle);
if (methodHandle != IntPtr.Zero)
{
return (MethodBase)getMethodBase.Invoke(null, new[]
{
typeHandle == IntPtr.Zero ? null : getTypeFromHandleUnsafe.Invoke(typeHandle),
runtimeMethodHandleInternalCtor.Invoke(new object[] { methodHandle })
});
}
if (fieldHandle != IntPtr.Zero)
{
return (FieldInfo)getFieldInfo.Invoke(null, new[]
{
typeHandle == IntPtr.Zero ? null : getTypeFromHandleUnsafe.Invoke(typeHandle),
runtimeFieldHandleStubCtor.Invoke(new object[] { fieldHandle, null })
});
}
if (typeHandle != IntPtr.Zero)
{
return getTypeFromHandleUnsafe.Invoke(typeHandle);
}
throw new NotImplementedException("DynamicMethods are not able to reference members by token other than types, methods and fields.");
}
public byte[] ResolveSignature(int metadataToken)
{
return signatureResolver.Invoke(metadataToken, 0);
}
public string ResolveString(int metadataToken)
{
return stringResolver.Invoke(metadataToken);
}
}
对于动态方法:
public sealed class ModuleTokenResolver : ITokenResolver
{
private readonly Module module;
public ModuleTokenResolver(Module module)
{
this.module = module;
}
public MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) =>
module.ResolveMember(metadataToken, genericTypeArguments, genericMethodArguments);
public Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) =>
module.ResolveType(metadataToken, genericTypeArguments, genericMethodArguments);
public FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) =>
module.ResolveField(metadataToken, genericTypeArguments, genericMethodArguments);
public MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) =>
module.ResolveMethod(metadataToken, genericTypeArguments, genericMethodArguments);
public byte[] ResolveSignature(int metadataToken) =>
module.ResolveSignature(metadataToken);
public string ResolveString(int metadataToken) =>
module.ResolveString(metadataToken);
}
public sealed class DynamicMethodTokenResolver : ITokenResolver
{
private delegate void TokenResolver(int token, out IntPtr typeHandle, out IntPtr methodHandle, out IntPtr fieldHandle);
private delegate string StringResolver(int token);
private delegate byte[] SignatureResolver(int token, int fromMethod);
private delegate Type GetTypeFromHandleUnsafe(IntPtr handle);
private readonly TokenResolver tokenResolver;
private readonly StringResolver stringResolver;
private readonly SignatureResolver signatureResolver;
private readonly GetTypeFromHandleUnsafe getTypeFromHandleUnsafe;
private readonly MethodInfo getMethodBase;
private readonly ConstructorInfo runtimeMethodHandleInternalCtor;
private readonly ConstructorInfo runtimeFieldHandleStubCtor;
private readonly MethodInfo getFieldInfo;
public DynamicMethodTokenResolver(DynamicMethod dynamicMethod)
{
var resolver = typeof(DynamicMethod).GetField("m_resolver", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(dynamicMethod);
if (resolver == null) throw new ArgumentException("The dynamic method's IL has not been finalized.");
tokenResolver = (TokenResolver)resolver.GetType().GetMethod("ResolveToken", BindingFlags.Instance | BindingFlags.NonPublic).CreateDelegate(typeof(TokenResolver), resolver);
stringResolver = (StringResolver)resolver.GetType().GetMethod("GetStringLiteral", BindingFlags.Instance | BindingFlags.NonPublic).CreateDelegate(typeof(StringResolver), resolver);
signatureResolver = (SignatureResolver)resolver.GetType().GetMethod("ResolveSignature", BindingFlags.Instance | BindingFlags.NonPublic).CreateDelegate(typeof(SignatureResolver), resolver);
getTypeFromHandleUnsafe = (GetTypeFromHandleUnsafe)typeof(Type).GetMethod("GetTypeFromHandleUnsafe", BindingFlags.Static | BindingFlags.NonPublic, null, new[] { typeof(IntPtr) }, null).CreateDelegate(typeof(GetTypeFromHandleUnsafe), null);
var runtimeType = typeof(RuntimeTypeHandle).Assembly.GetType("System.RuntimeType");
var runtimeMethodHandleInternal = typeof(RuntimeTypeHandle).Assembly.GetType("System.RuntimeMethodHandleInternal");
getMethodBase = runtimeType.GetMethod("GetMethodBase", BindingFlags.Static | BindingFlags.NonPublic, null, new[] { runtimeType, runtimeMethodHandleInternal }, null);
runtimeMethodHandleInternalCtor = runtimeMethodHandleInternal.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(IntPtr) }, null);
var runtimeFieldInfoStub = typeof(RuntimeTypeHandle).Assembly.GetType("System.RuntimeFieldInfoStub");
runtimeFieldHandleStubCtor = runtimeFieldInfoStub.GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, new[] { typeof(IntPtr), typeof(object) }, null);
getFieldInfo = runtimeType.GetMethod("GetFieldInfo", BindingFlags.Static | BindingFlags.NonPublic, null, new[] { runtimeType, typeof(RuntimeTypeHandle).Assembly.GetType("System.IRuntimeFieldInfo") }, null);
}
public Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
{
IntPtr typeHandle, methodHandle, fieldHandle;
tokenResolver.Invoke(metadataToken, out typeHandle, out methodHandle, out fieldHandle);
return getTypeFromHandleUnsafe.Invoke(typeHandle);
}
public MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
{
IntPtr typeHandle, methodHandle, fieldHandle;
tokenResolver.Invoke(metadataToken, out typeHandle, out methodHandle, out fieldHandle);
return (MethodBase)getMethodBase.Invoke(null, new[]
{
typeHandle == IntPtr.Zero ? null : getTypeFromHandleUnsafe.Invoke(typeHandle),
runtimeMethodHandleInternalCtor.Invoke(new object[] { methodHandle })
});
}
public FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
{
IntPtr typeHandle, methodHandle, fieldHandle;
tokenResolver.Invoke(metadataToken, out typeHandle, out methodHandle, out fieldHandle);
return (FieldInfo)getFieldInfo.Invoke(null, new[]
{
typeHandle == IntPtr.Zero ? null : getTypeFromHandleUnsafe.Invoke(typeHandle),
runtimeFieldHandleStubCtor.Invoke(new object[] { fieldHandle, null })
});
}
public MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
{
IntPtr typeHandle, methodHandle, fieldHandle;
tokenResolver.Invoke(metadataToken, out typeHandle, out methodHandle, out fieldHandle);
if (methodHandle != IntPtr.Zero)
{
return (MethodBase)getMethodBase.Invoke(null, new[]
{
typeHandle == IntPtr.Zero ? null : getTypeFromHandleUnsafe.Invoke(typeHandle),
runtimeMethodHandleInternalCtor.Invoke(new object[] { methodHandle })
});
}
if (fieldHandle != IntPtr.Zero)
{
return (FieldInfo)getFieldInfo.Invoke(null, new[]
{
typeHandle == IntPtr.Zero ? null : getTypeFromHandleUnsafe.Invoke(typeHandle),
runtimeFieldHandleStubCtor.Invoke(new object[] { fieldHandle, null })
});
}
if (typeHandle != IntPtr.Zero)
{
return getTypeFromHandleUnsafe.Invoke(typeHandle);
}
throw new NotImplementedException("DynamicMethods are not able to reference members by token other than types, methods and fields.");
}
public byte[] ResolveSignature(int metadataToken)
{
return signatureResolver.Invoke(metadataToken, 0);
}
public string ResolveString(int metadataToken)
{
return stringResolver.Invoke(metadataToken);
}
}
以下是如何检测动态方法和一些辅助方法:
public static class ReflectionExtensions
{
public static bool IsLightweightMethod(this MethodBase method)
{
return method is DynamicMethod || typeof(DynamicMethod).GetNestedType("RTDynamicMethod", BindingFlags.NonPublic).IsInstanceOfType(method);
}
public static ITokenResolver GetTokenResolver(this MethodBase method)
{
var dynamicMethod = TryGetDynamicMethod(method as MethodInfo) ?? method as DynamicMethod;
return dynamicMethod != null
? new DynamicMethodTokenResolver(dynamicMethod)
: (ITokenResolver)new ModuleTokenResolver(method.Module);
}
public static byte[] GetILBytes(this MethodBase method)
{
var dynamicMethod = TryGetDynamicMethod(method as MethodInfo) ?? method as DynamicMethod;
return dynamicMethod != null
? GetILBytes(dynamicMethod)
: method.GetMethodBody()?.GetILAsByteArray();
}
public static byte[] GetILBytes(DynamicMethod dynamicMethod)
{
var resolver = typeof(DynamicMethod).GetField("m_resolver", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(dynamicMethod);
if (resolver == null) throw new ArgumentException("The dynamic method's IL has not been finalized.");
return (byte[])resolver.GetType().GetField("m_code", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(resolver);
}
public static DynamicMethod TryGetDynamicMethod(MethodInfo rtDynamicMethod)
{
var typeRTDynamicMethod = typeof(DynamicMethod).GetNestedType("RTDynamicMethod", BindingFlags.NonPublic);
return typeRTDynamicMethod.IsInstanceOfType(rtDynamicMethod)
? (DynamicMethod)typeRTDynamicMethod.GetField("m_owner", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(rtDynamicMethod)
: null;
}
}
这样的项目对你有帮助吗:它似乎是按照同样的思路工作的,所以它的源代码可能包含你需要的东西。那么你正在使用它?我肯定不记得有没有得到答案。帮我回到工作岗位,我会帮你的,希望这有意义。修改你的答案。基本上是正确的,我会把你标记为答案,但我认为烘焙版才是需要的。你有没有想过?我也遇到了这个问题。我有一个解决办法,但它太乱了,让我想哭。您必须从
IntPtr
s构建RuntimeTypeHandle
和RuntimeMethodHandle
等。参考资料表明,这是解决这一问题的唯一真正方法。快发帖了。