如何在对驻留在不同程序集中的方法执行JMP指令时获得正确的方法引用

本文关键字:方法 指令 执行 JMP 引用 集中 程序集 程序 | 更新日期: 2023-09-27 18:01:41

我有下面的代码,基本上创建了一个有两个类型的DynamicAssembly,每个类型有一个公共方法。

        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()。

这就像一个魔咒,两种类型驻留在同一个程序集中。

现在,如果我想重定向到另一个程序集中的类型,我如何才能获得正确的程序集/模块引用,以便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字节指令来做这个

如何在对驻留在不同程序集中的方法执行JMP指令时获得正确的方法引用

元数据令牌不是全局唯一的。它们在调用方法的模块的上下文中被解析。您需要在模块上使用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);