does anybody know how to get a FUNCTION pointer to nonstatic C++ method ( in C style) and then be able to call it..
i know that C++ methods have a secret 1st parameter reference to the class instance..
i also know how to get a method pointer (which is typed to that particular class)
what i want to do (in ASM and/or C) is get a pointer to the nonstatic method
and then be able to call it myself, maybe with a typedef where i pass in the instance as the first parameter..
i know many different compilers implmenet the virtual method table and offset and method pointer details differently, if so i'm just interested in MSVC++
i know that C++ methods have a secret 1st parameter reference to the class instance..
i also know how to get a method pointer (which is typed to that particular class)
what i want to do (in ASM and/or C) is get a pointer to the nonstatic method
and then be able to call it myself, maybe with a typedef where i pass in the instance as the first parameter..
i know many different compilers implmenet the virtual method table and offset and method pointer details differently, if so i'm just interested in MSVC++
if i understand your problem correctly i think that some directx win32asm snippets accomplish the same task by calling dx COM functions, don't they?
i'm not talking about calling methods of COM objects, but rather if i have a C++ method pointer, calling the method (or casting it as a function).
http://www.asmcommunity.net/board/index.php?topic=17987
I use this to successfully control C++ objects with my asm code.
I use this to successfully control C++ objects with my asm code.
hmm those look really interesting..
but i am not using masm
but rather just inline assembler inside msvc++7
i basically just want to be able to get a C style function pointer from a method pointer and
then call it.
i don't need such an elebrate system of being able to derive from C++ classes in assembler and such.
but i am not using masm
but rather just inline assembler inside msvc++7
i basically just want to be able to get a C style function pointer from a method pointer and
then call it.
i don't need such an elebrate system of being able to derive from C++ classes in assembler and such.
class Test{
virtual ~Test();
virtual long DoIt(long x);
virtual long DoIt2();
long z;
};
//Test* obj1 = new Test;
obj1->DoIt(10);
obj1->DoIt2();
delete obj1
~Test() is at offset 0 of the vt
DoIt(x) is at offset 4 of the vt
DoIt2() is at offset 8 of the vt
when deleting, the destructor has 1 hidden parameter - usually you need to "push 1".
If the object has at least 1 virtual function (including the destructor), then it has a vt (virtual table), and the first 4 bytes of the class instance point to it. Each such C++ object of same class has exactly the same 4 first bytes - can be used to identify what type the class is.
virtual ~Test();
virtual long DoIt(long x);
virtual long DoIt2();
long z;
};
//Test* obj1 = new Test;
obj1->DoIt(10);
obj1->DoIt2();
delete obj1
mov ecx,obj1
push 10
push ecx
mov eax,[ecx]
mov eax,[eax+4]
call eax
mov ecx,obj1
push ecx
mov eax,[ecx]
mov eax,[eax+8]
call eax
mov ecx,obj1
push 1
push ecx
mov eax,[ecx]
mov eax,[eax]
call eax
~Test() is at offset 0 of the vt
DoIt(x) is at offset 4 of the vt
DoIt2() is at offset 8 of the vt
when deleting, the destructor has 1 hidden parameter - usually you need to "push 1".
If the object has at least 1 virtual function (including the destructor), then it has a vt (virtual table), and the first 4 bytes of the class instance point to it. Each such C++ object of same class has exactly the same 4 first bytes - can be used to identify what type the class is.
very imformative stuff. from your leads i've come up with this (messy) test code..
using inline assembler i test calling a function from assembler, and also convert a method pointer to a function pointer.. however C++ methods use thiscall calling convention, and there is no thiscall keyword to get the C function to work right.. with no parameters it 'pretends' to work right, however the this isn't passed in ECX as it should... anyway here is the test code..its just some simple stuff using MFC for quick ease of making a test app with messagebox
test class definition.
class Test{
public:
virtual ~Test();
virtual long DoIt(long x);
virtual long DoIt2();
virtual long BigTest(int a,int b,int c, int d, int e,CString ratdog);
long DoIt3();
long z;
};
Test::~Test()
{
};
long Test::DoIt(long x)
{
CString tmpstr;
tmpstr.Format("do it with one parameter %d",x);
MessageBox(0,tmpstr,"",0);
return 1;
};
long Test::DoIt2()
{
MessageBox(0,"hello2","",0);
return 2;
};
long Test::DoIt3()
{
MessageBox(0,"hello3","",0);
return 3;
};
long Test::BigTest(int a,int b,int c, int d, int e,CString ratdog)
{
CString tmpstr;
tmpstr.Format("%d %d %d %d %d YEAH %s ",a,b,c,d,e,ratdog);
MessageBox(0,tmpstr,"",0);
return 5;
//tmpstr
}
..and the test code
long (Test::*pfn)(); //method pointer
long (Test::*pfn2)(long x); //method pointer
long (Test::*pfnBigTest)(int a,int b,int c, int d, int e,CString ratdog);
typedef long cfuncptr(Test * tstptr); //typedef of equiv function pointer
typedef long cfuncptr2(Test * tstptr,long x); //typedef of equiv function pointer
typedef long cfuncptrBigTest(Test * tstptr,int a,int b,int c, int d, int e,CString ratdog);
//_thiscall
cfuncptr * funcptr;
cfuncptr2 * funcptr2;
cfuncptrBigTest * BigTestptr;
PVOID myvoid;
Test* obj1 = new Test;
pfn = &Test::DoIt2;
(obj1->*pfn)();
pfn = &Test::DoIt3;
pfnBigTest = &Test::BigTest;
pfn2 = &Test::DoIt;
(obj1->*pfn2)(4);
(obj1->*pfnBigTest) (1,2,3,4,5,"first bigtest");
(obj1->*pfn)();
obj1->DoIt(10);
obj1->DoIt2();
obj1->DoIt3();
obj1->BigTest(10,2,40,5,5,"work please");
MessageBox("before manual");
//call the method pointer from assembler.
_asm {
mov esi,esp
mov ecx,DWORD PTR obj1;
call DWORD PTR pfn;
}
//use assembler to cast the method pointer to PVOID - since C++ compiler won't let you do this
_asm {
mov eax,DWORD PTR pfn;
mov myvoid,eax
}
//cast PVOID to our equiv C function pointer that passes in the instance of the class as the first parameter
funcptr = (cfuncptr *) myvoid;
MessageBox("before C call");
//run method through function pointer
//this one pretends to work.. except inside the call it wouldn't have a valid reference
//to the class (if the method had tried to access properties etc)
long ab = funcptr(obj1);
CString tmpstr2;
tmpstr2.Format("return value %d",ab);
//verify it is returning the return value correctly
MessageBox(tmpstr2);
_asm {
mov eax,DWORD PTR pfn2;
mov myvoid,eax
}
//cast PVOID to our equiv C function pointer that passes in the instance of the class as the first parameter
funcptr2 = (cfuncptr2 *) myvoid;
MessageBox("before 2nd C call");
//run method through function pointer
//this one gives access violation because difference in calliung conventions
long ab2 = funcptr2(obj1,5);
CString tmpstr3;
tmpstr3.Format("2nd return value %d",ab2);
//verify it is returning the return value correctly
MessageBox(tmpstr3);
..
the question is how can i emulate thiscall..
current ideas is use naked functions and use inline assembler to do the same as thiscall, making a C wrapper for each function..
or alternatively, just make a dummy class with the same method parameters,
and inside it cast the 'this' pointer as Test.
anybody else have any ideas?
at least now i can get the pointer to the actual function.
using inline assembler i test calling a function from assembler, and also convert a method pointer to a function pointer.. however C++ methods use thiscall calling convention, and there is no thiscall keyword to get the C function to work right.. with no parameters it 'pretends' to work right, however the this isn't passed in ECX as it should... anyway here is the test code..its just some simple stuff using MFC for quick ease of making a test app with messagebox
test class definition.
class Test{
public:
virtual ~Test();
virtual long DoIt(long x);
virtual long DoIt2();
virtual long BigTest(int a,int b,int c, int d, int e,CString ratdog);
long DoIt3();
long z;
};
Test::~Test()
{
};
long Test::DoIt(long x)
{
CString tmpstr;
tmpstr.Format("do it with one parameter %d",x);
MessageBox(0,tmpstr,"",0);
return 1;
};
long Test::DoIt2()
{
MessageBox(0,"hello2","",0);
return 2;
};
long Test::DoIt3()
{
MessageBox(0,"hello3","",0);
return 3;
};
long Test::BigTest(int a,int b,int c, int d, int e,CString ratdog)
{
CString tmpstr;
tmpstr.Format("%d %d %d %d %d YEAH %s ",a,b,c,d,e,ratdog);
MessageBox(0,tmpstr,"",0);
return 5;
//tmpstr
}
..and the test code
long (Test::*pfn)(); //method pointer
long (Test::*pfn2)(long x); //method pointer
long (Test::*pfnBigTest)(int a,int b,int c, int d, int e,CString ratdog);
typedef long cfuncptr(Test * tstptr); //typedef of equiv function pointer
typedef long cfuncptr2(Test * tstptr,long x); //typedef of equiv function pointer
typedef long cfuncptrBigTest(Test * tstptr,int a,int b,int c, int d, int e,CString ratdog);
//_thiscall
cfuncptr * funcptr;
cfuncptr2 * funcptr2;
cfuncptrBigTest * BigTestptr;
PVOID myvoid;
Test* obj1 = new Test;
pfn = &Test::DoIt2;
(obj1->*pfn)();
pfn = &Test::DoIt3;
pfnBigTest = &Test::BigTest;
pfn2 = &Test::DoIt;
(obj1->*pfn2)(4);
(obj1->*pfnBigTest) (1,2,3,4,5,"first bigtest");
(obj1->*pfn)();
obj1->DoIt(10);
obj1->DoIt2();
obj1->DoIt3();
obj1->BigTest(10,2,40,5,5,"work please");
MessageBox("before manual");
//call the method pointer from assembler.
_asm {
mov esi,esp
mov ecx,DWORD PTR obj1;
call DWORD PTR pfn;
}
//use assembler to cast the method pointer to PVOID - since C++ compiler won't let you do this
_asm {
mov eax,DWORD PTR pfn;
mov myvoid,eax
}
//cast PVOID to our equiv C function pointer that passes in the instance of the class as the first parameter
funcptr = (cfuncptr *) myvoid;
MessageBox("before C call");
//run method through function pointer
//this one pretends to work.. except inside the call it wouldn't have a valid reference
//to the class (if the method had tried to access properties etc)
long ab = funcptr(obj1);
CString tmpstr2;
tmpstr2.Format("return value %d",ab);
//verify it is returning the return value correctly
MessageBox(tmpstr2);
_asm {
mov eax,DWORD PTR pfn2;
mov myvoid,eax
}
//cast PVOID to our equiv C function pointer that passes in the instance of the class as the first parameter
funcptr2 = (cfuncptr2 *) myvoid;
MessageBox("before 2nd C call");
//run method through function pointer
//this one gives access violation because difference in calliung conventions
long ab2 = funcptr2(obj1,5);
CString tmpstr3;
tmpstr3.Format("2nd return value %d",ab2);
//verify it is returning the return value correctly
MessageBox(tmpstr3);
..
the question is how can i emulate thiscall..
current ideas is use naked functions and use inline assembler to do the same as thiscall, making a C wrapper for each function..
or alternatively, just make a dummy class with the same method parameters,
and inside it cast the 'this' pointer as Test.
anybody else have any ideas?
at least now i can get the pointer to the actual function.
MSVC++ passes the this pointer in ECX, usually.
But I'm not sure that you can rely on this behavior.
But I'm not sure that you can rely on this behavior.
i only care about MSVC++ anyhow.. and it seems its THISCALL convention is consistent enough ..
i tried this (changing my function pointers to NOT have the "this" as the first param so
typedef long _stdcall cfuncptr3(long x); //typedef of equiv function pointer
typedef long _stdcall cfuncptrBigTest(int a,int b,int c, int d, int e,CString ratdog);
and calling like this
_asm {
mov eax,DWORD PTR pfn2;
mov myvoid,eax
}
funcptr3 = (cfuncptr3 *) myvoid;
_asm {
mov ecx,obj1;
}
long ab = funcptr3(10);
which worked PERFECT in most scenarios..
but what you can't gaurantee is that the line of code calling the function pointer isn't going to mess up ECX
like in this example
CString ratstring = "hello";
_asm {
mov ecx,obj1;
}
BigTestptr(1,2,3,4,5,ratstring);
ratstring CString ratstring = "hello";
_asm {
mov ecx,obj1;
}
BigTestptr(1,2,3,4,5,ratstring);
functions to prepare ratstring for passing are called which mess up the ecx
(here is the assembler output from MSVC++)
; 266 : _asm {
; 267 : mov ecx,obj1;
mov ecx, DWORD PTR _obj1$
; 268 : }
; 269 : //BigTestptr(1,2,3,4,5,"hello");
push ecx
mov ecx, esp
mov DWORD PTR $T83158, esp
mov esi, esp
lea eax, DWORD PTR _ratstring$
push eax
call DWORD PTR __imp_??0?$CStringT@DV?$StrTraitMFC_DLL@DV?$ChTraitsCRT@D@ATL@@@@@ATL@@QAE@ABV01@@Z
cmp esi, esp
call __RTC_CheckEsp
mov DWORD PTR tv205, eax
push 5
push 4
push 3
push 2
push 1
call DWORD PTR _BigTestptr$
so i think the only reliable method would be to have the complete dispatching code in assembler..
thinking of different ways to make a flexible framework (with inline assembler, and probably "naked" functions to do this..
any ideas?
i tried this (changing my function pointers to NOT have the "this" as the first param so
typedef long _stdcall cfuncptr3(long x); //typedef of equiv function pointer
typedef long _stdcall cfuncptrBigTest(int a,int b,int c, int d, int e,CString ratdog);
and calling like this
_asm {
mov eax,DWORD PTR pfn2;
mov myvoid,eax
}
funcptr3 = (cfuncptr3 *) myvoid;
_asm {
mov ecx,obj1;
}
long ab = funcptr3(10);
which worked PERFECT in most scenarios..
but what you can't gaurantee is that the line of code calling the function pointer isn't going to mess up ECX
like in this example
CString ratstring = "hello";
_asm {
mov ecx,obj1;
}
BigTestptr(1,2,3,4,5,ratstring);
ratstring CString ratstring = "hello";
_asm {
mov ecx,obj1;
}
BigTestptr(1,2,3,4,5,ratstring);
functions to prepare ratstring for passing are called which mess up the ecx
(here is the assembler output from MSVC++)
; 266 : _asm {
; 267 : mov ecx,obj1;
mov ecx, DWORD PTR _obj1$
; 268 : }
; 269 : //BigTestptr(1,2,3,4,5,"hello");
push ecx
mov ecx, esp
mov DWORD PTR $T83158, esp
mov esi, esp
lea eax, DWORD PTR _ratstring$
push eax
call DWORD PTR __imp_??0?$CStringT@DV?$StrTraitMFC_DLL@DV?$ChTraitsCRT@D@ATL@@@@@ATL@@QAE@ABV01@@Z
cmp esi, esp
call __RTC_CheckEsp
mov DWORD PTR tv205, eax
push 5
push 4
push 3
push 2
push 1
call DWORD PTR _BigTestptr$
so i think the only reliable method would be to have the complete dispatching code in assembler..
thinking of different ways to make a flexible framework (with inline assembler, and probably "naked" functions to do this..
any ideas?
I don't mean to crush your dreams here, but realize that MSVC++ was named as such because it's a C++ compiler. And it's for that very reason why it is not called MSASMVC++. Yes it may support 'inline assembly' but it is far from being an assembler. I think you might benefit from ceasing your attempts to turn it into one.
The inline assembler's interaction with the class system is shaky and this was intentional, as a lot of things are going on behind the scenes that could be compromised with the interference of rogue assembly code. If you can get it to work well, you might land a minimal performance boost, but the disadvantages far outweight the benefits, as what you're left with is confusing and unmanageable C++/ASM hybrid code.
However, I can understand if you're doing this just to play around and learn. That's fine. Keep on experimenting.
But if you're trying to come up with a serious application framework then this kind of thing is hackish and just plain bad programming. (I'm not trying to say that you're a bad programmer, don't worry.) It's okay, you're not the first to attempt this sort of thing, and I'm sure you won't be the last. At the very least you will walk away with more intimate knowledge of the internal workings of MS's VC++ compiler. So it won't all be in vain.
If you're looking for an OOP framework using assembly then look around on these forums, as people like NaN have worked diligently to bring this kind of thing to the community.
Oh and for future reference the "{CODE} {/CODE}" VBulletin tags (replace the curly braces with brackets) will make your source a lot easier for others to read.
Have a good one. ;)
The inline assembler's interaction with the class system is shaky and this was intentional, as a lot of things are going on behind the scenes that could be compromised with the interference of rogue assembly code. If you can get it to work well, you might land a minimal performance boost, but the disadvantages far outweight the benefits, as what you're left with is confusing and unmanageable C++/ASM hybrid code.
However, I can understand if you're doing this just to play around and learn. That's fine. Keep on experimenting.
But if you're trying to come up with a serious application framework then this kind of thing is hackish and just plain bad programming. (I'm not trying to say that you're a bad programmer, don't worry.) It's okay, you're not the first to attempt this sort of thing, and I'm sure you won't be the last. At the very least you will walk away with more intimate knowledge of the internal workings of MS's VC++ compiler. So it won't all be in vain.
If you're looking for an OOP framework using assembly then look around on these forums, as people like NaN have worked diligently to bring this kind of thing to the community.
Oh and for future reference the "{CODE} {/CODE}" VBulletin tags (replace the curly braces with brackets) will make your source a lot easier for others to read.
Have a good one. ;)
I don't mean to crush your dreams here, but realize that MSVC++ was named as such because it's a C++ compiler. And it's for that very reason why it is not called MSASMVC++. Yes it may support 'inline assembly' but it is far from being an assembler. I think you might benefit from ceasing your attempts to turn it into one.
maybe i should have explained my context. i do write alot of inline assembler for inner loops MMX/SSE, but this is a bit different. i am not trying turn C++ into an assembler, or planing to write ALOT of code in assembler. actually for this i wish i didn't have to use assembler, but pure C++, but it seems to be impossible.. all i am trying to do is get into the internals of how thiscall calling convection works (which annoyingly doesn't have a keyword), and come to grips with interfacing to virtual call tables at a low level, the same way as i have done previously and successfully with delphi. in my research what i wish to do has been said to be impossible to do. however a little bit of research shows that others have doen similiar things to what i want (Though slightly different)
here are a few articles that got me on my way
http://www.google.co.nz/search?q=cache:X9dOYg50emgJ:www.gdconf.com/archives/2001/bilas.doc+naked+thiscall&hl=en
http://weblogs.asp.net/oldnewthing/archive/2004/02/09/70002.aspx
two things i am trying to do
1)make a dynamic dispatching of nonstatic method calls , where a pointer to a method (which i have to get from assembler) is passed in, as well as an array of parameters.. i often use LUA as a script language, and are totally annoyed at only being able to link callback functions to nonstatic methods or C functions. also i have alot of uses for such dynamic dispatching techniques
2)hooking methods, (and i finally sucessfully got to do this yesterday).. i wish to hook any method (a specific one rather than the whole virtual chain (i no my terminology of such thing does isn't the same as the official terminoloy)
so at execution time when say the non static Test::doIt is called, it actually gets redirected to HookClass::doItReplacement which will have the same parameters etc
and hookclass::doitReplacement with do
Test * testptr = (Test *) this; to get typecast this as Test so it can treat it as such.. (working nice)
then after hookclass::DoItReplacement does its stuff, its most likely to want to call the original method, and it will use the 'dynamic dispatching of nonstatic method in point 1 to do so.
as for bad programming techniques, there are so many situations that we've tried to do things the right way, but have had to come up with a hack to achieve something due to the limitation of an API, language etc, that wasn't designed to do what we want, or need to do with it. However i wouldn't blame you if you thought i was a bad programmer based on the experimental hack i posted earlier, but it was a quick experimental hack :)
ok here is all i have to do now to implement the hooking system
PVOID doitptr;
PVOID hookdoitptr;
PVOID NextHook;
...
//declaration of method function that will be hooked
long Test::DoIt(long x)
{
...
}
//code to get pointers needed for hooking
_asm {
mov eax,DWORD PTR Test::DoIt;
mov doitptr,eax
}
_asm {
mov eax,DWORD PTR TestHook::HookDoIt;
mov hookdoitptr,eax
}
//install the hook
if (!HookCode(doitptr, hookdoitptr, (PVOID*) &NextHook))
MessageBox("did not hook right");
//until it is unhooked whenever Test::Doit is called, TestHook::HookDoIt will be called
instead.
..
//and actually what does TestHook::HookDoIt contains?
long TestHook::HookDoIt(long x)
{
long retvalue;
Test * testptr = (Test *) this;
//now do whatever we want here
CString tmpstr;
tmpstr.Format("inside the hook x: %d this.z : %d",x,testptr->z);
MessageBox(0,tmpstr,"",0);
//now we are done, call the original simulating thiscall calling technique
_asm {
push x
mov ecx,this
call NextHook;
mov retvalue,eax
}
return retvalue;
};
...
//and we might want to uninstall the hook sometime
UnhookCode((PVOID*) &NextHook);
does my madness make any more sense yet?
Karl
I only looked _very_ briefly at your last post, but perhaps a C++ "pointer to member function/method" thingy would work? If not, sorry for my ignorance.
http://www.parashift.com/c++-faq-lite/pointers-to-members.html
http://www.parashift.com/c++-faq-lite/pointers-to-members.html
earlier (as can be seen in the first post ) i had been using pointer to methods, however pointer to methods are linked ot the specific class, and also they aren't a pointer as such, but rather an offset , and can contain a whole bunch of information depending on the base classes etc.. the reason i need to use the assembly is you can't get a pointer to function, to a nonstatic method in C++, a method pointer isn't a 4 byte 32 bit address.. but rather can be 8 or even 12 bytes because of what it contains.. i'm using inline assembler to get the actual 32 bit pointer to the actual method's code
and you can't call a nonstatic method from C, outside of the normal objects method dispatch.
http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.7
but my solution above is working quite nice now. i can hook any function of any class whether static, non static, or virtual..
i haven't yet experimental how the hooking works with decentant classes, base classes, multiple inheritence yet though.
hmm i didn't realise we had posted to the same site until after i had posted :)
and you can't call a nonstatic method from C, outside of the normal objects method dispatch.
http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.7
but my solution above is working quite nice now. i can hook any function of any class whether static, non static, or virtual..
i haven't yet experimental how the hooking works with decentant classes, base classes, multiple inheritence yet though.
hmm i didn't realise we had posted to the same site until after i had posted :)