Search code examples
c++pointersvirtualmember

Accessing the compiled code of a virtual member function


I need to verify the code of a virtual member function in my other code. So how do I get a pointer that points to the correct code?

class MyInterface {
    public:
        virtual void VirtualMethod() = 0;
};

class MyImplementation : public MyInterface {
    private:
        int m_value;
    public:
        MyImplementation() : m_value(0) { }
        virtual void VirtualMethod() {
            m_value = 1;
        }
};

void main(int argc, char* argv[])
{
    MyInterface* pInterface = new MyImplementation();
    // In my real code on the following line, we do not have access to the declaration of MyImplementation
    unsigned int* pFunctionPointer = (unsigned int*)pInterface->VirtualMethod;
    // Now we want to access the compiled code of MyImplementation::VirtualMethod.
    printf("0x%08x\n", *pFunctionPointer);
}

In my actual code, I do not have access to MyImplementation declaration at all from the "main" function, if you get my drift.


Solution

  • Here's a little bit of code that I hacked up, which (in g++ 4.6.3) appears to give the expected results.

    However, before I get downvotes simply because I'm trying to solve an unsolvable probel, this is absolutely relying on "undefined behaviour". Since the standard doesn't even go into how virtual methods are supposed to be implemented with regards to vptr, vtable, etc, there is no way that you can actually implement this without knowing what the compiler does - and of course, a new version, even in a minor revision, or using different compile options of compiler may change this (e.g. debug mode vs release mode could be different - but that would make it hard to mix debug and release or mix code compiled with old and new compilers)

    #include <iostream>
    
    using namespace std;
    
    class A
    {
    public:
        virtual void f();
    };
    
    class A2
    {
    public:
        virtual void g();
    };
    
    
    class B: public A, public A2
    {
    public:
        virtual void f();
        virtual void g();
    };
    
    
    void print_my_addr(const char *name)
    {
        cout << "Address of " << name << "=" <<
        __builtin_return_address (0) << endl;
    }
    
    void A::f()
    {
        print_my_addr(__FUNCTION__);
    }
    
    void A2::g()
    {
        print_my_addr(__FUNCTION__);
    }
    
    void B::f()
    {
        print_my_addr(__FUNCTION__);
    }
    
    void B::g()
    {
        print_my_addr(__FUNCTION__);
    }
    
    
    // p:           pointer to a class object to inspect.
    // base_number: which base-class to inspect. 0 = first baseclass
    // func_no:     function number within the baseclass.
    // returns the address as a intptr_t
    intptr_t findvirt(A *p, int base_number, int func_no)
    {
        intptr_t **vptr = reinterpret_cast<intptr_t**>(p);
    
        intptr_t *vtable = vptr[base_number];
    
        return vtable[func_no];
    }
    
    
    int main()
    {
        A a;
        B b;
        cout << hex << "Address of A::f()" << findvirt(&a, 0, 0) << endl;
        a.f();
        cout << hex << "Address of B::f()" << findvirt(&b, 0, 0) << endl;
        b.f();
        cout << hex << "Address of B::g()" << findvirt(&b, 1, 0) << endl;
    }