如何从C ++ vtable中获取指针? [英] How to obtain a pointer out of a C++ vtable?

查看:116
本文介绍了如何从C ++ vtable中获取指针?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设您有一个C ++类,例如:

Say you have a C++ class like:

class Foo {
 public:
  virtual ~Foo() {}
  virtual DoSomething() = 0;
};

C ++编译器将调用转换为vtable查找:

The C++ compiler translates a call into a vtable lookup:

Foo* foo;

// Translated by C++ to:
//   foo->vtable->DoSomething(foo);
foo->DoSomething();

假设我正在编写一个JIT编译器,并且我想获得DoSomething一个特殊的类Foo实例,所以我可以生成跳转到它直接代码,而不是一个表查找和间接分支。

Suppose I was writing a JIT compiler and I wanted to obtain the address of the DoSomething() function for a particular instance of class Foo, so I can generate code that jumps to it directly instead of doing a table lookup and an indirect branch.

我的问题是:


  1. 是否有任何标准的C ++方法来做到这一点(我几乎肯定答案是否定的,完整性)。

  1. Is there any standard C++ way to do this (I'm almost sure the answer is no, but wanted to ask for the sake of completeness).

有没有任何远程编译器独立的方式,像一个人实现的库提供访问vtable的API? p>

Is there any remotely compiler-independent way of doing this, like a library someone has implemented that provides an API for accessing a vtable?

我完全打开黑客,如果他们会工作。例如,如果我创建了我自己的派生类,并且可以确定它的DoSomething方法的地址,我可以假设vtable是Foo的第一个(隐藏)成员,并搜索它的vtable,直到找到我的指针值。但是,我不知道如何写这个地址:如果我写& DerivedFoo :: DoSomething 我得到一个指针到成员,这是完全不同的。

I'm open completely to hacks, if they will work. For example, if I created my own derived class and could determine the address of its DoSomething method, I could assume that the vtable is the first (hidden) member of Foo and search through its vtable until I find my pointer value. However, I don't know a way of getting this address: if I write &DerivedFoo::DoSomething I get a pointer-to-member, which is something totally different.

也许我可以将指针指向成员到vtable偏移。当我编译以下:

Maybe I could turn the pointer-to-member into the vtable offset. When I compile the following:

class Foo {
 public:
  virtual ~Foo() {}
  virtual void DoSomething() = 0;
};

void foo(Foo *f, void (Foo::*member)()) {
  (f->*member)();
}

在GCC / x86-64,我得到这个程序集输出:

On GCC/x86-64, I get this assembly output:

Disassembly of section .text:

0000000000000000 <_Z3fooP3FooMS_FvvE>:
   0:   40 f6 c6 01             test   sil,0x1
   4:   48 89 74 24 e8          mov    QWORD PTR [rsp-0x18],rsi
   9:   48 89 54 24 f0          mov    QWORD PTR [rsp-0x10],rdx
   e:   74 10                   je     20 <_Z3fooP3FooMS_FvvE+0x20>
  10:   48 01 d7                add    rdi,rdx
  13:   48 8b 07                mov    rax,QWORD PTR [rdi]
  16:   48 8b 74 30 ff          mov    rsi,QWORD PTR [rax+rsi*1-0x1]
  1b:   ff e6                   jmp    rsi
  1d:   0f 1f 00                nop    DWORD PTR [rax]
  20:   48 01 d7                add    rdi,rdx
  23:   ff e6                   jmp    rsi

我不完全明白这里发生了什么,但如果我可以逆向工程这或者使用ABI规范,我可以为每个单独的平台生成一个片段,作为从vtable获取指针的一种方法。

I don't fully understand what's going on here, but if I could reverse-engineer this or use an ABI spec I could generate a fragment like the above for each separate platform, as a way of obtaining a pointer out of a vtable.

推荐答案

为什么你认为& DerivedFoo :: DoSomething 是不同的?这不是你要的吗?我的想法,任何调用 DerivedFoo :: DoSomething()将调用相同的函数,传递一个不同的this指针。 vtable只区分源自 Foo 的不同类型,而不是实例。

Why do you think &DerivedFoo::DoSomething is different? Isn't this exactly what you're asking for? The way I think about it, any call to DerivedFoo::DoSomething() will call the same function, passing a different this pointer. The vtable merely distinguishes between different types derived from Foo, not instances.

这篇关于如何从C ++ vtable中获取指针?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆