[Visual C++ x64] Konstruktor via Funktionszeiger aufrufen

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

[Visual C++ x64] Konstruktor via Funktionszeiger aufrufen

Beitrag von Krishty »

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?
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Artificial Mind
Establishment
Beiträge: 802
Registriert: 17.12.2007, 17:51
Wohnort: Aachen

Re: [Visual C++ x64] Konstruktor via Funktionszeiger aufrufe

Beitrag von Artificial Mind »

Krishty hat geschrieben: Aber Inline Assembly gibt es unter Visual C++ x64 nicht.
Kannst du dann nicht einfach eine eigene Datei für die Assembler-Teile anlegen und daraus aufrufen?
Also nicht Inline Assembler, sondern ganz normale Assembler-Module.
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [Visual C++ x64] Konstruktor via Funktionszeiger aufrufe

Beitrag von Krishty »

Ich habe ehrlich gesagt Angst vor Prolog, Epilog, und Frame Unwinding. Da die Funktion kein Leaf ist, müsste das ja dann von Hand gemacht werden …

… ich suche gerade, ob ich einen Sprung zu einem Funktionszeiger nicht auch mit Intrinsics hinbekomme. Ich begreife auch nicht, wo der Fehler liegt, weil die Maschinenbefehle des normalen typedef-Aufrufs sehr ähnlich aussehen:

    mov    rdx,qword ptr [pSource]
    mov    rcx,qword ptr [pDestination]
    call   qword ptr [myCopyCtor]


Nachtrag: Das Problem ist, dass der K’tor RCX überschreibt. Hmm.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [Visual C++ x64] Konstruktor via Funktionszeiger aufrufe

Beitrag von dot »

Ich komm leider nicht umhin zu fragen: Wofür genau brauchst du das? xD
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [Visual C++ x64] Konstruktor via Funktionszeiger aufrufe

Beitrag von Krishty »

http://zfx.info/viewtopic.php?f=9&t=307&p=36840#p36840

Wird eine User-Type-Ausnahme geworfen und by-value gefangen, muss das Objekt kopiert werden. Dafür gibt mir der Compiler einen Zeiger auf den Kopierk'tor und ein paar Zusatzinformationen wie die Größe des Objekts.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [Visual C++ x64] Konstruktor via Funktionszeiger aufrufe

Beitrag von dot »

Notlösung: Bytecode in Array packen, nach void (*)() casten und aufrufen :>
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [Visual C++ x64] Konstruktor via Funktionszeiger aufrufe

Beitrag von Krishty »

Sieht so aus, als ob ich irgendwo zwischen der 4. und 6. Indirektion einen Zeiger vertauscht hätte. Jedenfalls kann ich auch alles krachen lassen, wenn ich den K'tor nicht aufrufe, sondern einfach memset() auf meinen Zielbereich. Yeah. Ich melde mich zurück, sobald es was Neues gibt.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Antworten