Domanda

Stavo leggendo alcuni articoli in rete riguardanti i thunk Vtable e ho letto da qualche parte che i thunk possono essere utilizzati per agganciare/concatenare chiamate di procedure.

È realizzabile?

Qualcuno sa come funziona, inoltre non riesco a trovare buone risorse che spieghino i ringraziamenti.Qualche suggerimento in merito?

È stato utile?

Soluzione

L'implementazione di un thunk non elaborato nello stile dei thunk v-table è l'ultima risorsa.Qualunque cosa tu debba realizzare, molto probabilmente può essere ottenuta con una funzione wrapper e sarà molto meno dolorosa.

In generale, un thunk esegue le seguenti operazioni:

  1. Correggere i parametri di input (ad esempio, convertire in un formato diverso)
  2. Chiama l'implementazione reale
  3. Pulisci il passaggio 1/correggi i parametri di output

Per vedere un esempio di come funziona, rivolgiamoci al nostro buon amico Raymond Chen e alla sua discussione sui periti:

http://blogs.msdn.com/oldnewthing/archive/2004/02/06/68695.aspx

Il thunk che ha utilizzato è stato il seguente:

[thunk]:CSample::QueryInterface`adjustor{4}':
  sub     DWORD PTR [esp+4], 4 ; this -= sizeof(lpVtbl)
  jmp     CSample::QueryInterface

Come descrive, hai una classe che implementa gli stessi metodi attraverso più interfacce, quindi ha più tabelle v.(Se non conosci COM, tutto ciò che devi sapere è che funziona direttamente con v-tables, quindi un puntatore a un'interfaccia specifica deve contenere puntatori a funzione a tutti i metodi di quell'interfaccia al fine.)

Se implementi due interfacce con metodi diversi in uno slot particolare, sono necessarie più tabelle v.Ma scrivi i metodi sovrapposti solo una volta, quindi quel metodo deve essere in grado di funzionare con entrambi i puntatori "questo".Per fare ciò, il compilatore genera un metodo che esegue la correzione necessaria e chiama l'implementazione originale.

Quindi, questo thunk esegue i seguenti passaggi:

  1. Correggi i parametri di input, vale a dire il puntatore nascosto "questo", nella prima riga.
  2. Chiama l'implementazione reale nella seconda riga.
  3. Ripulire:nessuno richiesto (vedi sotto)

Questo è dove il jmp arrivano le istruzioniNormalmente, se dovessi chiamare la funzione utilizzando call, ti ritornerebbe e dovresti farlo ret torna al tuo chiamante.Poiché non c'è alcuna pulizia da fare, il compilatore esegue un'ottimizzazione in cui sposta l'esecuzione direttamente sull'implementazione reale e lascia che l'istruzione return dell'implementazione reale ritorni a tuo chiamante.Questa è solo un'ottimizzazione, non una parte fondamentale del pensiero.Ad esempio, i thunk a 16/32 bit convertiranno i parametri di input/output tra 16 e 32 bit secondo necessità, quindi non è possibile saltare la fase di pulizia;deve call, non jmp.

La morale della favola è:se hai bisogno di fare qualcosa, come ad esempio jmp ottimizzazione, che non puoi scrivere direttamente in C++ o in un altro linguaggio di alto livello preferito, vai avanti e scrivi un thunk in linguaggio assembly.Altrimenti, basta scrivere un wrapper e farla finita.

Onestamente, sembra che tu stia chiedendo l'ottimizzazione delle prestazioni e la maggior parte delle volte (1) il compilatore è più bravo nell'ottimizzazione di quanto pensiamo e (2) non ti darà un miglioramento così grande come pensi.

Altri suggerimenti

Bene, hai letto che i thunk sono una soluzione e ora stai cercando un problema da risolvere?

I thunk, in genere, sono brevi funzioni di "inoltro" che forniscono aggiustamenti minori, solitamente codificati.

I blocchi VTable sono spiegati molto bene Wikipedia al momento.Usano il modello comune:generare una piccola funzione per evitare calcoli/lavoro extra in fase di esecuzione.

Altri posti in cui ho visto/usato thunk:

Associazione di un handle di finestra con un oggetto finestra:per ogni finestra da sottoclassare viene generato al volo un piccolo thunk che chiama la window procedure con il riferimento all'oggetto, il thunk viene poi utilizzato come window procedure.

Ritarda caricamento DLL:il thunk si assicura che la DLL venga caricata la prima volta che viene chiamata una funzione.

Trapping delle chiamate all'interfaccia COM:i thunk forniscono un punto di iniezione per la diagnostica e passano al metodo effettivo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top