How to get every virtual function index just as the compiler does?

淺唱寂寞╮ 提交于 2019-12-05 12:46:51

Use the hidden Microsoft C/C++ compiler option "/d1 reportAllClassLayout". This will print out the memory layout and vtables of all your classes.

You could try writing a hack that determines it for you - this is implementation defined, but you can usually find a pointer to the virtual function table at the beginning of class memory. If you follow to this table there'll be a list of function pointers in memory (but you won't know how many). However, by searching for the functions you know about in the table of function pointers, you could identify its index.

In MSVC you can't browse at runtime the vtable and compare equality with a given member function pointer as they are not the same. One is the real pointer, the other is a pointer which indirects to the real one.

However with this compiler you can do it at runtime with another hack I discovered.

Create a class (named IndexFinder for example) inside which you declare as many instance methods as the max virtual methods you can have in a class. Each of these method must return an unique integer value starting from 0 to your max.

Create a fake virtual method table and store your method pointers so that the integer they return match the index in which you store them (the method which returns 0 will be the first in your fake vtable). When you want to find the index of any virtual method you have to do some dirty cast of the method member pointer to a IndexFinder method pointer.

The principle is easy : for virtual methods the compiler will generate code which indirects to the real method using the vtable with the good index. As you replaced the compiler generated vtable with a fake one, it will jump to yours and not to the supposed one. As your method returns the index inside which it's stored, you just have to get the return and you have your index.

Here is a code which is more explicit (I repeat it's a compiler dependant hack, the ones who don't like that, don't read it ^^). But I tried it, it works perfectly as it's just a redirection hack (I'm looking for a trick with GCC, but i haven't find it yet).

It's possible that it depends on the call convention, i haven't tried it in all cases for now. One advantage of this trick is that you don't need to construct an instance of your class to find the index of one of it's virtual methods.

// In the header .h
class IndexFinder
{
    typedef int (IndexFinder::*method_pointer)();
public:
    template<typename _MethodPtr>
    int getIndexOf(_MethodPtr ptr) { 
        return (reinterpret_cast<IndexFinder*>(&fake_vtable_ptr)->**((IndexFinder::method_pointer*)(&ptr)))() 
    }
protected:
    int method0() { return 0; }
    int method1() { return 1; }        
    int method2() { return 2; }
    int method3() { return 3; }
protected:
typedef method_pointer fake_vtable_t [4]; 
    static fake_vtable_t   fake_vtable;
    void*                  fake_vtable_ptr;  
};

// In the cpp file
IndexFinder::fake_vtable_t IndexFinder::fake_vtable = {
    &IndexFinder::method0 ,
    &IndexFinder::method1 ,
    &IndexFinder::method2 ,
    &IndexFinder::method3 
};
void* IndexFinder::fake_vtable_ptr = &IndexFinder::fake_vtable;

// to use it : 
int index = IndexFinder::getIndexOf(&YourClass::yourVirtualMethod);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!