Get memory address of member function?

2019-01-13 13:43发布

问题:

How do I get the absolute address of a member function in C++? (I need this for thunking.)

Member function pointers don't work because I can't convert them to absolute addresses (void *) -- I need to know the address of the actual function in memory, not simply the address relative to the type.

回答1:

There exists a syntax to get the address of the member function in MSVC (starting from MSVC 2005 IMHO). But it's pretty tricky. Moreover, the obtained pointer is impossible to cast to other pointer type by conventional means. Though there exists a way to do this nevertheless.

Here's the example:

// class declaration
class MyClass
{
public:
    void Func();
    void Func(int a, int b);
};

// get the pointer to the member function
void (__thiscall MyClass::* pFunc)(int, int) = &MyClass::Func;

// naive pointer cast
void* pPtr = (void*) pFunc; // oops! this doesn't compile!

// another try
void* pPtr = reinterpret_cast<void*>(pFunc); // Damn! Still doesn't compile (why?!)

// tricky cast
void* pPtr = (void*&) pFunc; // this works

The fact that conventional cast doesn't work, even with reinterpret_cast probably means that MS doesn't recommend this casting very strongly.

Nevertheless you may do this. Of course this is all implementation-dependent, you must know the appropriate calling convention to do the thunking + have appropriate assembler skills.



回答2:

try this. should let you cast anything to anything :)

template<typename OUT, typename IN>
OUT ForceCast( IN in )
{
    union
    {
        IN  in;
        OUT out;
    }
    u = { in };

    return u.out;
};

then

void* member_address = ForceCast<void*>(&SomeClass::SomeMethod);


回答3:

By default, C++ member functions use the __thiscall calling convention. In order to Detour a member function, both the trampoline and the detour must have exactly the same calling convention as the target function. Unfortunately, the VC compiler does not support a __thiscall, so the only way to create legal detour and trampoline functions is by making them class members of a "detour" class.

In addition, C++ does not support converting a pointer to a member function to an arbitrary pointer. To get a raw pointer, the address of the member function must be moved into a temporrary member-function pointer, then passed by taking it's address, then de-referencing it. Fortunately, the compiler will optimize the code to remove the extra pointer operations.

from Microsoft Detour library. They deal with code injection and discuss getting address of non-virual member functions. Of course it is compiler implementation specific stuff.

you can find the library here http://research.microsoft.com/en-us/downloads/d36340fb-4d3c-4ddd-bf5b-1db25d03713d/default.aspx