访问虚拟成员函数的已编译代码

Accessing the compiled code of a virtual member function

本文关键字:编译 代码 虚拟成员 函数 访问      更新时间:2023-10-16

我需要在其他代码中验证虚拟成员函数的代码。那么,如何获得指向正确代码的指针呢?

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%08xn", *pFunctionPointer);
}

在我的实际代码中,如果您了解我的漂移,我根本无法从"main"函数访问MyImplementation声明。

下面是我破解的一小段代码,它(在g++4.6.3中)似乎给出了预期的结果。

然而,在我仅仅因为试图解决一个无法解决的问题而被否决之前,这绝对是依赖于"未定义的行为"。由于该标准甚至没有涉及虚拟方法应该如何实现vptr、vtable等,因此在不知道编译器做什么的情况下,你不可能真正实现这一点——当然,还有一个新版本,即使是一个小版本,或者使用编译器的不同编译选项可能会改变这一点(例如,调试模式与发布模式可能不同,但这将使调试和发布混合或使用新旧编译器编译的代码混合变得困难)

#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;
}