如何在对驻留在不同程序集中的方法执行 JMP 指令时获取正确的方法引用
How to get a correct method reference when performing a JMP instruction to a method that resides in a different assembly
我有以下代码,基本上创建了一个包含 2 种类型的 DynamicAssembly,每种类型有一个 public 方法。
var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly
(new AssemblyName("TestAssembly"), AssemblyBuilderAccess.Run);
var module = assembly.DefineDynamicModule("Main");
var type1 = module.DefineType("type1");
var method1 = type1.DefineMethod
(
"Method1", MethodAttributes.Public, typeof(void), null
);
var gen = method1.GetILGenerator();
gen.Emit(OpCodes.Ret);
var t1 = type1.CreateType();
var createdMethod1 = t1.GetMethod("Method1");
var type2 = module.DefineType("type2");
var method2 = type2.DefineMethod
(
"Method2", MethodAttributes.Public, typeof(void), null
);
byte[] ilCodes = new byte[5];
ilCodes[0] = (byte)OpCodes.Jmp.Value;
ilCodes[1] = (byte)(createdMethod1.MetadataToken & 0xFF);
ilCodes[2] = (byte)(createdMethod1.MetadataToken >> 8 & 0xFF);
ilCodes[3] = (byte)(createdMethod1.MetadataToken >> 16 & 0xFF);
ilCodes[4] = (byte)(createdMethod1.MetadataToken >> 24 & 0xFF);
method2.SetMethodBody(ilCodes, ilCodes.Length, null, null, null);
var obj = Activator.CreateInstance(type2.CreateType());
obj.GetType().GetMethod("Method2").Invoke(obj, null);
每当我调用 type2.method2() 时,我都会有一条 JMP 指令指向 type1.method1()。
这很有魅力,两种类型都位于同一个程序集中。
现在,如果我想重定向到另一个程序集中的类型,我如何才能获得正确的 assembly/module 引用以使 JMP 指令成功。如果我这样做:
byte[] ilCodes = new byte[5];
ilCodes[0] = (byte)OpCodes.Jmp.Value;
ilCodes[1] = (byte)(methodFromOtherAssembly.MetadataToken & 0xFF);
ilCodes[2] = (byte)(methodFromOtherAssembly.MetadataToken >> 8 & 0xFF);
ilCodes[3] = (byte)(methodFromOtherAssembly.MetadataToken >> 16 & 0xFF);
ilCodes[4] = (byte)(methodFromOtherAssembly.MetadataToken >> 24 & 0xFF);
它一直失败并出现 IndexNotFound 异常。
我想用 Raw IL 字节指令执行此操作。
元数据标记不是全局唯一的。它们在调用方法模块的上下文中解析。您需要在模块上使用 GetMetadataToken 以获得正确的令牌。您的第一个示例有效,因为这些方法共享相同的模块。
这将从动态模块中获取正确的令牌:
byte[] ilCodes = new byte[5];
int token = module.GetMetadataToken(methodFromOtherAssembly).Token;
ilCodes[0] = (byte)OpCodes.Jmp.Value;
ilCodes[1] = (byte)(token & 0xFF);
ilCodes[2] = (byte)(token >> 8 & 0xFF);
ilCodes[3] = (byte)(token >> 16 & 0xFF);
ilCodes[4] = (byte)(token >> 24 & 0xFF);
我有以下代码,基本上创建了一个包含 2 种类型的 DynamicAssembly,每种类型有一个 public 方法。
var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly
(new AssemblyName("TestAssembly"), AssemblyBuilderAccess.Run);
var module = assembly.DefineDynamicModule("Main");
var type1 = module.DefineType("type1");
var method1 = type1.DefineMethod
(
"Method1", MethodAttributes.Public, typeof(void), null
);
var gen = method1.GetILGenerator();
gen.Emit(OpCodes.Ret);
var t1 = type1.CreateType();
var createdMethod1 = t1.GetMethod("Method1");
var type2 = module.DefineType("type2");
var method2 = type2.DefineMethod
(
"Method2", MethodAttributes.Public, typeof(void), null
);
byte[] ilCodes = new byte[5];
ilCodes[0] = (byte)OpCodes.Jmp.Value;
ilCodes[1] = (byte)(createdMethod1.MetadataToken & 0xFF);
ilCodes[2] = (byte)(createdMethod1.MetadataToken >> 8 & 0xFF);
ilCodes[3] = (byte)(createdMethod1.MetadataToken >> 16 & 0xFF);
ilCodes[4] = (byte)(createdMethod1.MetadataToken >> 24 & 0xFF);
method2.SetMethodBody(ilCodes, ilCodes.Length, null, null, null);
var obj = Activator.CreateInstance(type2.CreateType());
obj.GetType().GetMethod("Method2").Invoke(obj, null);
每当我调用 type2.method2() 时,我都会有一条 JMP 指令指向 type1.method1()。
这很有魅力,两种类型都位于同一个程序集中。
现在,如果我想重定向到另一个程序集中的类型,我如何才能获得正确的 assembly/module 引用以使 JMP 指令成功。如果我这样做:
byte[] ilCodes = new byte[5];
ilCodes[0] = (byte)OpCodes.Jmp.Value;
ilCodes[1] = (byte)(methodFromOtherAssembly.MetadataToken & 0xFF);
ilCodes[2] = (byte)(methodFromOtherAssembly.MetadataToken >> 8 & 0xFF);
ilCodes[3] = (byte)(methodFromOtherAssembly.MetadataToken >> 16 & 0xFF);
ilCodes[4] = (byte)(methodFromOtherAssembly.MetadataToken >> 24 & 0xFF);
它一直失败并出现 IndexNotFound 异常。
我想用 Raw IL 字节指令执行此操作。
元数据标记不是全局唯一的。它们在调用方法模块的上下文中解析。您需要在模块上使用 GetMetadataToken 以获得正确的令牌。您的第一个示例有效,因为这些方法共享相同的模块。
这将从动态模块中获取正确的令牌:
byte[] ilCodes = new byte[5];
int token = module.GetMetadataToken(methodFromOtherAssembly).Token;
ilCodes[0] = (byte)OpCodes.Jmp.Value;
ilCodes[1] = (byte)(token & 0xFF);
ilCodes[2] = (byte)(token >> 8 & 0xFF);
ilCodes[3] = (byte)(token >> 16 & 0xFF);
ilCodes[4] = (byte)(token >> 24 & 0xFF);