Utilisation de v-table thunks pour enchaîner les appels de procédure
Question
Je lisais quelques articles sur le net concernant les thunks de Vtable et j'ai lu quelque part que les thunks peuvent être utilisés pour accrocher/chaîner des appels de procédures.
Est-ce réalisable ?
Est-ce que quelqu'un sait comment cela fonctionne, et je ne parviens pas non plus à trouver de bonnes ressources pour expliquer, merci.Des suggestions à ce sujet ?
La solution
Implémenter un thunk brut dans le style des thunks de table en V est un dernier recours.Tout ce que vous devez accomplir peut très probablement être réalisé avec une fonction wrapper, et ce sera beaucoup moins douloureux.
En général, une réflexion fait ce qui suit :
- Corrigez les paramètres d'entrée (par exemple, convertissez-les dans un format différent)
- Appelez la véritable implémentation
- Nettoyer l'étape 1 / corriger les paramètres de sortie
Pour voir un exemple de la façon dont cela fonctionne, tournons-nous vers notre bon ami Raymond Chen et sa discussion sur les réflexions des experts en sinistres :
http://blogs.msdn.com/oldnewthing/archive/2004/02/06/68695.aspx
La pensée qu'il a utilisée était la suivante :
[thunk]:CSample::QueryInterface`adjustor{4}':
sub DWORD PTR [esp+4], 4 ; this -= sizeof(lpVtbl)
jmp CSample::QueryInterface
Comme il le décrit, vous disposez d'une classe qui implémente les mêmes méthodes via plusieurs interfaces, elle dispose donc de plusieurs tables virtuelles.(Si vous ne connaissez pas COM, tout ce que vous devez savoir c'est qu'il fonctionne directement avec les v-tables, donc un pointeur vers une interface spécifique doit contenir des pointeurs de fonction vers toutes les méthodes de cette interface. en ordre.)
Si vous implémentez deux interfaces avec des méthodes différentes dans un emplacement particulier, vous avez besoin de plusieurs tables virtuelles.Mais vous n'écrivez qu'une seule fois les méthodes qui se chevauchent, cette méthode doit donc pouvoir fonctionner avec les deux pointeurs "this".Pour ce faire, le compilateur génère une méthode qui effectue les corrections nécessaires et appelle l'implémentation d'origine.
Ainsi, cette réflexion effectue les étapes suivantes :
- Corrigez les paramètres d'entrée, à savoir le pointeur "this" caché, dans la première ligne.
- Appelez la véritable implémentation sur la deuxième ligne.
- Nettoyer:aucun requis (voir ci-dessous)
C'est là que le jmp
l'instruction arrive.Normalement, si vous appelez la fonction en utilisant call
, cela te reviendrait, et tu devrais ret
retour à votre appelant.Puisqu'il n'y a pas de nettoyage à faire, le compilateur effectue une optimisation où il déplace l'exécution directement vers l'implémentation réelle et laisse l'instruction return de l'implémentation réelle revenir à ton votre interlocuteur.Il ne s'agit que d'une optimisation, pas d'un élément fondamental de la réflexion.Par exemple, thunks 16/32 bits convertira les paramètres d'entrée/sortie entre 16 et 32 bits si nécessaire, il ne pourra donc pas sauter l'étape de nettoyage ;il faut call
, pas jmp
.
La morale de l'histoire est la suivante :si vous devez faire quelque chose, comme jmp
optimisation, que vous ne pouvez pas écrire directement en C++ ou dans votre autre langage de haut niveau de votre choix, allez-y et écrivez un langage assembleur.Sinon, écrivez simplement un wrapper et finissez-en.
Honnêtement, il semble que vous demandiez une optimisation des performances, et la plupart du temps (1) le compilateur est meilleur en optimisation que nous le pensons et (2) cela ne vous apportera pas une amélioration aussi importante que vous le pensez.
Autres conseils
Eh bien, vous avez bien lu thunks sont une solution, et maintenant vous êtes à la recherche d'un problème à résoudre?
Thunks, en général, sont des fonctions à court "expédition" qui fournissent des mineurs - habituellement - codées en dur. Ajustements
morceaux VTable sont très bien expliquées dans wikipedia au moment. Ils utilisent le schéma commun: générer une petite fonction pour éviter le calcul / travail supplémentaire au moment de l'exécution
.D'autres endroits que j'ai vu / utilisé thunks:
Associer une poignée de fenêtre avec un objet fenêtre:. Pour chaque fenêtre à sous-classé, une petite thunk est générée à la volée qui appelle la procédure de fenêtre avec la référence d'objet, le thunk est ensuite utilisé comme procédure de fenêtre
Retard DLLs Chargement: thunk fait que la DLL est chargée la première fois que la fonction est appelée
.Piégeage appelle l'interface COM: les thunks fournissent un point d'injection pour le diagnostic, et passer à la méthode actuelle.