[Visual C++ x64] Konstruktor via Funktionszeiger aufrufen
Verfasst: 17.03.2013, 18:59
Hi,
In Fortsetzung von Artificial Minds alter Frage speziell für Visual Studio 2010/2012 x64:
Ich kenne die Adresse eines Kopierk’tors; habe seinen Parameter; und den Ort, an dem ich eine Kopie erzeugen will. Wie rufe ich den Kopierk'tor auf?
Zunächst einmal ist bei der Signatur zu beachten: this als unsichtbarer erster Parameter; Referenz auf das Original als zweiter Parameter. Unter Visual C++ geben außerdem alle Konstruktoren implizit einen Zeiger auf die neue Instanz als Rückgabewert zurück:
typedef void * (CopyConstructor)(void * pThis, void const * pThat);
(Die Referenz als Zeiger zu übergeben ist legitim, da Referenzen in Visual C++’ ABI als Zeiger realisiert werden.)
Den Kopierk'tor aufzurufen wird allerdings den Stack zerschießen, da der Aufruf keiner bekannten Calling Convention folgt:
myCopyCtor(pDestination, pSource);
// Ab hier ist alles kaputt!
Die x86-CRT bietet Quelltext für einen vernünftigen Aufruf:
__declspec(naked) void __stdcall _CallMemberFunction1(
void *pthis, // Value for 'this' pointer
void *pmfn, // Pointer to the member function
void *pthat // Value of 1st parameter (type assumes copy ctor)
) {
__asm {
pop eax // Save return address
pop ecx // Get 'this'
xchg [esp],eax // Get function address, stash return address
jmp eax // jump to the function (function will return to caller of this func)
}
}
(Die 1 am Namensende steht dafür, dass dieser Kopierk'tor einen Parameter gibt. Es gibt scheinbar auch welche mit zweien.)
Leider ist für die x64-CRT kein entsprechender Quelltext mitgeliefert. Was der Compiler erzeugt, ist:
mov rdx,[pSource]
mov rcx,qword ptr [pDestination]
call qword ptr [myCopyCtor]
jmp (Ende)
Aber Inline Assembly gibt es unter Visual C++ x64 nicht.
Und was mache ich jetzt um aufzurufen?
In Fortsetzung von Artificial Minds alter Frage speziell für Visual Studio 2010/2012 x64:
Ich kenne die Adresse eines Kopierk’tors; habe seinen Parameter; und den Ort, an dem ich eine Kopie erzeugen will. Wie rufe ich den Kopierk'tor auf?
Zunächst einmal ist bei der Signatur zu beachten: this als unsichtbarer erster Parameter; Referenz auf das Original als zweiter Parameter. Unter Visual C++ geben außerdem alle Konstruktoren implizit einen Zeiger auf die neue Instanz als Rückgabewert zurück:
typedef void * (CopyConstructor)(void * pThis, void const * pThat);
(Die Referenz als Zeiger zu übergeben ist legitim, da Referenzen in Visual C++’ ABI als Zeiger realisiert werden.)
Den Kopierk'tor aufzurufen wird allerdings den Stack zerschießen, da der Aufruf keiner bekannten Calling Convention folgt:
myCopyCtor(pDestination, pSource);
// Ab hier ist alles kaputt!
Die x86-CRT bietet Quelltext für einen vernünftigen Aufruf:
__declspec(naked) void __stdcall _CallMemberFunction1(
void *pthis, // Value for 'this' pointer
void *pmfn, // Pointer to the member function
void *pthat // Value of 1st parameter (type assumes copy ctor)
) {
__asm {
pop eax // Save return address
pop ecx // Get 'this'
xchg [esp],eax // Get function address, stash return address
jmp eax // jump to the function (function will return to caller of this func)
}
}
(Die 1 am Namensende steht dafür, dass dieser Kopierk'tor einen Parameter gibt. Es gibt scheinbar auch welche mit zweien.)
Leider ist für die x64-CRT kein entsprechender Quelltext mitgeliefert. Was der Compiler erzeugt, ist:
mov rdx,[pSource]
mov rcx,qword ptr [pDestination]
call qword ptr [myCopyCtor]
jmp (Ende)
Aber Inline Assembly gibt es unter Visual C++ x64 nicht.
Und was mache ich jetzt um aufzurufen?