【问题标题】:Get the vtable address in C#?在 C# 中获取 vtable 地址?
【发布时间】:2013-01-05 02:53:31
【问题描述】:

我愿意使用unsafe。如何获取类虚拟表地址并将其转换为 int?

【问题讨论】:

  • 你为什么要这样做?
  • 通过反汇编器查看OpCodes.Callvirtmsdn.microsoft.com/en-us/library/…
  • @ColeJohnson:我真的厌倦了 WHAT_HAVE_YOU_TRIED。在提出问题之前,并非所有事情都可以先尝试。家庭作业问题可以,这个问题不行。
  • @Matthew Opcodes.Callvirt 只是一个字节序列。您需要查看 CLR 标准或 Mono 的源代码。
  • 我不是那个意思。我的意思是:你有任何起始代码吗?因为这个问题可以不用。你有什么可以帮助我们的吗?

标签: c#


【解决方案1】:

(编辑:拍摄 - 忘了你还必须确保它不是内联的 - 请参阅编辑)

您不需要不安全,但您确实需要确保该方法已经过 JIT(.PrepareMethod 确实如此):

警告:我不完全确定(没有更多研究)这些数字在长期内有多准确;我知道他们曾经使用是准确的,因为我曾经用它来运行时交换方法实现...... shh

using System;
using System.Runtime.CompilerServices;
void Main()
{
    long typeHandle = typeof(Foo).TypeHandle.Value.ToInt64();
    Console.WriteLine("addressOf(typeof(Foo)): 0x{0:x}", typeHandle);

    MethodInfo instanceMethod1 = typeof(Foo).GetMethod("InstanceFunc1");
    RuntimeHelpers.PrepareMethod(instanceMethod1.MethodHandle);
    long addressOfInstanceMethod1 = instanceMethod1.MethodHandle.GetFunctionPointer().ToInt64();
    Console.WriteLine("foo.InstanceFunc1:      0x{0:x}", addressOfInstanceMethod1);

    MethodInfo instanceMethod2 = typeof(Foo).GetMethod("InstanceFunc2");
    RuntimeHelpers.PrepareMethod(instanceMethod2.MethodHandle);
    long addressOfInstanceMethod2 = instanceMethod2.MethodHandle.GetFunctionPointer().ToInt64();
    Console.WriteLine("foo.InstanceFunc2:      0x{0:x}", addressOfInstanceMethod2);

    MethodInfo staticMethod = typeof(Foo).GetMethod("StaticFunc");
    RuntimeHelpers.PrepareMethod(staticMethod.MethodHandle);
    long addressOfStaticMethod = staticMethod.MethodHandle.GetFunctionPointer().ToInt64();
    Console.WriteLine("Foo.StaticFunc:         0x{0:x}", addressOfStaticMethod);
}

public class Foo
{
   [MethodImpl(MethodImplOptions.NoInlining)]
   public static int StaticFunc() { return 1; } 
   [MethodImpl(MethodImplOptions.NoInlining)]
   public int InstanceFunc1() { return 1; } 
   [MethodImpl(MethodImplOptions.NoInlining)]
   public int InstanceFunc2() { return 1; }
}

【讨论】:

  • 为什么要在内存中移动函数?它们是对象,所以它们不会只停留在一个常量地址(每次编译都会改变)
  • @ColeJohnson 抱歉,严重误判并且没有校对:我的意思是说对象的布局和其他引用已从 CLR 的版本到版本的不同;最明显的是在 2.0->4.0 之间。我会进行编辑。此外,很好的编辑。 :)
【解决方案2】:

看看这篇文章 - 它适用于 .NET 1.1,但它只是一个开始。由于 JIT 内部没有很好的文档记录,我不确定这适用于当前框架版本的效果如何。

How the CLR Creates Runtime Objects

This SO question may also be useful.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-04-07
    • 2012-03-25
    • 1970-01-01
    • 2013-07-25
    • 2013-02-27
    • 2012-02-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多