2010-06-17 19 views
4

Y at-il un plugin ou un outil qui peut lire un fichier .h (ou simplement modifier Intellisense lui-même) et cracher toutes les fonctions et son index de table de fonction virtuelle? Il y a un modèle que je n'ai pas encore compris avec le polymorphisme, et il devient 5 fois plus difficile quand vous commencez à avoir 5 classes ou plus dérivant les unes des autres. Quoi qu'il en soit, le compilateur MSVC++ crache toujours l'index de la table de fonction virtuelle correcte lorsqu'il compile l'appel de fonction virtuelle de C++ vers Assembly. Il doit y avoir un meilleur moyen d'obtenir cet index sans charger, casser, pointer, et réécrire le code, non?Comment obtenir chaque indice de fonction virtuelle comme le fait le compilateur?

Merci!

Répondre

7

Utilisez l'option de compilateur Microsoft C/C++ masquée "/ d1 reportAllClassLayout". Cela imprimera la disposition de la mémoire et vtables de toutes vos classes.

+0

Passons à mon autre commentaire si vous l'avez lu, c'est exactement ce que je cherche! – Gbps

0

Vous pouvez essayer d'écrire un hack qui le détermine pour vous - c'est une implémentation définie, mais vous pouvez généralement trouver un pointeur vers la table de fonction virtuelle au début de la mémoire de classe. Si vous suivez cette table il y aura une liste de pointeurs de fonction dans la mémoire (mais vous ne saurez pas combien). Cependant, en recherchant les fonctions que vous connaissez dans la table des pointeurs de fonction, vous pouvez identifier son index.

+0

Le problème est que ce n'est pas automatisé, et est exactement ce que je faisais auparavant: S – Gbps

0

Dans MSVC, vous ne pouvez pas parcourir la vtable au moment de l'exécution et comparer l'égalité avec un pointeur de fonction membre donné, car ils ne sont pas identiques. L'un est le vrai pointeur, l'autre est un pointeur qui s'oriente vers le vrai. Cependant, avec ce compilateur, vous pouvez le faire à l'exécution avec un autre hack que j'ai découvert.

Créez une classe (nommée IndexFinder par exemple) dans laquelle vous déclarez autant de méthodes d'instance que les méthodes virtuelles max que vous pouvez avoir dans une classe. Chacune de ces méthodes doit retourner une valeur entière unique allant de 0 à votre maximum.

Créez une fausse table de méthode virtuelle et stockez vos pointeurs de méthode afin que l'entier qu'ils renvoient corresponde à l'index dans lequel vous les stockez (la méthode qui renvoie 0 sera la première dans votre vtable fictive). Lorsque vous souhaitez trouver l'index de n'importe quelle méthode virtuelle, vous devez effectuer une distribution incorrecte du pointeur de membre de méthode vers un pointeur de méthode IndexFinder.

Le principe est simple: pour les méthodes virtuelles, le compilateur générera du code qui s'origine vers la méthode réelle en utilisant vtable avec le bon index. Comme vous avez remplacé le compilateur généré vtable avec un faux, il va sauter à la vôtre et pas à la supposée. Comme votre méthode retourne l'index dans lequel elle est stockée, il vous suffit d'obtenir le retour et vous avez votre index.

Voici un code qui est plus explicite (je répète que c'est un bidouillage dépendant du compilateur, ceux qui n'aiment pas ça, ne le lisent pas ^^). Mais j'ai essayé, ça marche parfaitement car c'est juste un hack de redirection (je cherche un truc avec GCC, mais je ne l'ai pas encore trouvé).

Il est possible que cela dépende de la convention d'appel, je ne l'ai pas essayé dans tous les cas pour l'instant. Un avantage de cette astuce est que vous n'avez pas besoin de construire une instance de votre classe pour trouver l'index de l'une de ses méthodes virtuelles.

// In the header .h 
class IndexFinder 
{ 
    typedef int (IndexFinder::*method_pointer)(); 
public: 
    template<typename _MethodPtr> 
    int getIndexOf(_MethodPtr ptr) { 
     return (reinterpret_cast<IndexFinder*>(&fake_vtable_ptr)->**((IndexFinder::method_pointer*)(&ptr)))() 
    } 
protected: 
    int method0() { return 0; } 
    int method1() { return 1; }   
    int method2() { return 2; } 
    int method3() { return 3; } 
protected: 
typedef method_pointer fake_vtable_t [4]; 
    static fake_vtable_t fake_vtable; 
    void*     fake_vtable_ptr; 
}; 

// In the cpp file 
IndexFinder::fake_vtable_t IndexFinder::fake_vtable = { 
    &IndexFinder::method0 , 
    &IndexFinder::method1 , 
    &IndexFinder::method2 , 
    &IndexFinder::method3 
}; 
void* IndexFinder::fake_vtable_ptr = &IndexFinder::fake_vtable; 

// to use it : 
int index = IndexFinder::getIndexOf(&YourClass::yourVirtualMethod);