飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 604|回复: 8

[C/C++] .NET笔记:挂钩JIT获取编译的方法句柄、本机代码地址和部分方法名称

  [复制链接]

该用户从未签到

发表于 2024-12-30 21:32:28 | 显示全部楼层 |阅读模式
本帖最后由 鲲鹏 于 2024-12-30 21:32 编辑

流程如下。

1. 挂钩JIT,获取`methodInfo`结构体中的`ftn`成员,该成员有关方法句柄原始数据。获取`entryAddress`参数,该参数有关本机代码地址。
2. 将方法句柄原始数据转为`RuntimeMethodHandle`。需要注意的是,仅符合条件的部分方法可以完成转换。如泛型等会引发异常。
3. 根据`RuntimeMethodHandle`得到`MethodBase`。此时已经可以通过`Name`属性获取方法名称。
4. (可选)使用`dnlib`获取更为详细的方法名称。

不妨使用C++/CLI和C#混合编程。首先使用C++/CLI编写挂钩JIT。我们选取`compileMethod`位置进行挂钩,定位该位置可通过符号文件或`getJit`虚表等多种方式实现,这里不再赘述。目标方法为非托管。
[C++] 纯文本查看 复制代码
#pragma managed(push, off)
int __stdcall Hook_compileMethod(void *self, void *compHnd, void *methodInfo, unsigned int flags,
                                 unsigned char **entryAddress, unsigned long *nativeSizeOfCode)
{
    thread_local int recursionFlag = 0;

    int retval = Orig_compileMethod(self, compHnd, methodInfo, flags, entryAddress, nativeSizeOfCode);

    if (recursionFlag)
        return retval;

    if (retval == 0)
    {
        // 获取`methodInfo`结构体中的`ftn`成员,该成员有关方法句柄原始数据。
        void *methodInfo_ftn = *(void **)methodInfo;

        // 获取`entryAddress`参数,该参数有关本机代码地址。
        printf("%p\n", *entryAddress);

        recursionFlag++;
        FuncInternal(methodInfo_ftn);
        recursionFlag--;
    }
    return retval;
}
#pragma managed(pop)

其中,`FuncInternal`完成方法名称输出工作。该方法为托管。为了演示C++/CLI和C#混合编程的便捷性,我们调用了C#编写的`Func`方法。
[C++] 纯文本查看 复制代码
#pragma managed(push, on)
void FuncInternal(void *ptr)
{
    IntPtr methodHandleValue = IntPtr(ptr);
    ClassLibrary1::Class1::Func(methodHandleValue);
}
#pragma managed(pop)

C#代码如下。`GetRuntimeMethodHandle`将方法句柄原始数据转为`RuntimeMethodHandle`。`Func`输出方法名称。
[C#] 纯文本查看 复制代码
namespace ClassLibrary1
{
    public class Class1
    {
        public static RuntimeMethodHandle GetRuntimeMethodHandle(IntPtr methodHandleValue)
        {
            var asm = typeof(RuntimeMethodHandle).Assembly;
            var method = asm.CreateInstance("System.RuntimeMethodInfoStub",
                                            false,
                                            BindingFlags.Instance | BindingFlags.Public,
                                            null,
                                            new object[] { methodHandleValue, null },
                                            null,
                                            null);
            var handle = (RuntimeMethodHandle)asm.CreateInstance("System.RuntimeMethodHandle",
                                                                 false,
                                                                 BindingFlags.Instance | BindingFlags.NonPublic,
                                                                 null,
                                                                 new object[] { method },
                                                                 null,
                                                                 null);
            return handle;
        }

        public static void Func(IntPtr methodHandleValue)
        {
            try
            {
                // 将方法句柄原始数据转为`RuntimeMethodHandle`。
                var handle = GetRuntimeMethodHandle(methodHandleValue);
                var mb = MethodBase.GetMethodFromHandle(handle);
                // 通过`Name`属性获取方法名称。
                Console.WriteLine(mb.Name);

                // (可选)使用`dnlib`获取更为详细的方法名称。
                ModuleDefMD moduleDefMD = ModuleDefMD.Load(mb.Module);
                MethodDef methodDef = (MethodDef)moduleDefMD.ResolveToken(mb.MetadataToken);
                Console.WriteLine(methodDef.FullName);
            }
            catch
            {
                // 需要注意的是,仅符合条件的部分方法可以完成转换。如泛型等会引发异常。
            }
        }
    }
}



评分

参与人数 2威望 +3 飘云币 +3 收起 理由
wtujoxk + 1 + 1 感谢发布原创作品,PYG有你更精彩!
不破不立 + 2 + 2 感谢发布原创作品,PYG有你更精彩!

查看全部评分

PYG19周年生日快乐!
  • TA的每日心情
    开心
    昨天 08:31
  • 签到天数: 2449 天

    [LV.Master]伴坛终老

    发表于 2024-12-31 08:40:41 | 显示全部楼层
    感谢分享思路
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    昨天 11:08
  • 签到天数: 410 天

    [LV.9]以坛为家II

    发表于 2024-12-31 16:25:47 | 显示全部楼层
    每个字都认识,连起来一起读就闷逼了
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    昨天 08:29
  • 签到天数: 1584 天

    [LV.Master]伴坛终老

    发表于 2025-1-1 09:54:43 | 显示全部楼层
    楼主厉害,向你学习
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    昨天 15:34
  • 签到天数: 200 天

    [LV.7]常住居民III

    发表于 2025-1-2 17:09:34 | 显示全部楼层

    感谢发布原创作品,PYG有你更精彩!
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    昨天 07:47
  • 签到天数: 1855 天

    [LV.Master]伴坛终老

    发表于 2025-1-4 00:01:32 | 显示全部楼层
    学习了,感谢提供分享!
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    昨天 08:33
  • 签到天数: 1145 天

    [LV.10]以坛为家III

    发表于 2025-1-7 08:36:12 | 显示全部楼层
            PYG有你更精彩!
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

    快速回复 返回顶部 返回列表