如何从C ++ vtable中获取指针? [英] How to obtain a pointer out of a 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.
我的问题是:
-
是否有任何标准的C ++方法来做到这一点(我几乎肯定答案是否定的,完整性)。
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屋!