Допустим, у вас есть класс C ++, например:
class Foo {
public:
virtual ~Foo() {}
virtual DoSomething() = 0;
};
Компилятор C ++ переводит вызов в поиск vtable:
Foo* foo;
// Translated by C++ to:
// foo->vtable->DoSomething(foo);
foo->DoSomething();
Предположим, я писал JIT компилятор, и я хотел получить адрес функции DoSomething () для конкретного экземпляра класса Foo, чтобы я мог сгенерировать код, который переходит к нему напрямую, вместо того, чтобы выполнять поиск в таблице и косвенную ветвь.
Мои вопросы:
Есть ли какой-нибудь стандартный способ C ++ сделать это (я почти уверен, что ответ отрицательный, но хотел бы спросить для полноты картины).
Есть ли какой-либо дистанционно независимый от компилятора способ сделать это, например, реализованная кем-то библиотека, которая предоставляет API для доступа к vtable?
Я полностью открыт для взломов, если они будут работать. Например, если бы я создал свой собственный производный класс и мог определить адрес его метода DoSomething, я мог бы предположить, что vtable является первым (скрытым) членом Foo, и искать в его vtable, пока не найду свое значение указателя. Однако я не знаю, как получить этот адрес: если я напишу & DerivedFoo :: DoSomething
, я получу указатель на член, а это нечто совершенно иное.
Может быть, я мог бы превратить указатель на член в смещение vtable.Когда я компилирую следующее:
class Foo {
public:
virtual ~Foo() {}
virtual void DoSomething() = 0;
};
void foo(Foo *f, void (Foo::*member)()) {
(f->*member)();
}
На GCC / x86-64 я получаю следующий результат сборки:
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.