【问题标题】:Accessing the compiled code of a virtual member function访问虚拟成员函数的编译代码
【发布时间】:2013-07-02 10:31:10
【问题描述】:

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

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

在我的实际代码中,我根本无法从“main”函数访问 MyImplementation 声明,如果你明白我的意思的话。

【问题讨论】:

  • 使用编译器上的-S选项生成汇编输出,并在生成的汇编文件中定位相关函数?
  • 啊,对不起,没看到你实际上没有源代码。您必须找到 vtable 并在 vtable 中找到相关地址。不幸的是,这意味着知道该特定函数在 vtable 中具有什么“索引”。另一方面,使用objdumpdumpbin 反汇编包含该函数的目标文件(或dll)可能会更幸运。
  • 感谢您的建议。我确实有源文件,但我需要以编程方式查找代码。我正在编写的代码必须检查虚方法中的代码是否符合预期(例如CRC检查)。
  • 检查所有代码不是更有意义吗?当然,如果你只检查虚方法,你会在检查后容易受到替代方法的攻击吗?
  • 这取决于为什么要检查代码。上面的代码被设置为只提供一个合理的场景。实际的代码是不同的。我仍然需要从其他代码中访问虚拟方法代码。

标签: c++ pointers virtual member


【解决方案1】:

这是我破解的一小段代码,它(在 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;
}

【讨论】:

  • 我已经发现这是不可能的(至少不是以标准 C++ 方式,而且我没有使用标准编译器)。所以我决定重新设计。不过感谢您的努力!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-12-17
  • 2012-01-27
  • 1970-01-01
  • 1970-01-01
  • 2013-05-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多