C++ instance method addresses
November 16th, 2007 by Joe RanieriSorry if this looks like a repeat; it is a rewrite of a post on our old blog. It may differ from the original content.
C++ doesn’t let you get the address of an instance method. Even if you were to get the address, you couldn’t call it because the convention requires that ‘this’ be in the ecx register. However, with a little creativity we can work around this requirement.
(Please do not stare directly at the following code block until we manage to come up with a new color scheme for GeSHi!)
#include <stdarg.h> void* GetInstanceMethodAddr(char x, ...) { va_list argp; void *addr; va_start(argp, x); addr = va_arg(argp, void *); va_end(argp); return addr; } // For example, void *func = GetInstanceMethodAddr(42, &std::string::size);
The first parameter is arbitrary, and is only used because it’s required by varargs. You can change it as necessary.
November 16th, 2007 at 12:31 pm
Nifty trick, using the va_arg technique!
November 17th, 2007 at 12:14 am
Or… instead of all that hackery, you could just get the typecasts correct…
class Test
{
public:
Test();
void SomeInstanceMethod( void );
};
Test::Test()
{
void (__thiscall Test::*fp)( void ) = &Test::SomeInstanceMethod;
}
void Test::SomeInstanceMethod( void )
{
}
That compiles fine for me, and does get me the expected address of the instance method. Or did I miss something entirely?
Btw, ecx isn’t a requirement unless you’re using the thiscall calling convention. While thiscall is certainly the norm for C++, I am pretty sure it’s not a strict requirement. Nothing says you can’t push it to the stack like a normal parameter and mark it as stdcall in place of thiscall (not certain why you’d want to do that though — but then again, I’m not certain why you’d want the address of an instance method either).
November 17th, 2007 at 7:50 am
That doesn’t get the address in a way you can manipulate it though - I was poking at this for generating thunks and patching functions. As for thiscall, Visual Studio puts ‘this’ in ecx but gcc puts it on the stack like cdecl.
November 17th, 2007 at 1:05 pm
Weird… and basically useless. But each to their own.