web-dev-qa-db-fra.com

Obtenir l'adresse mémoire de la fonction membre?

Comment obtenir l'adresse absolue d'une fonction membre en C++? (J'en ai besoin pour le thunking.)

Les pointeurs de fonction membre ne fonctionnent pas car je ne peux pas les convertir en adresses absolues (void *) - J'ai besoin de connaître l'adresse de la fonction réelle en mémoire, pas simplement l'adresse relative au type.

31
user541686

Il existe une syntaxe pour obtenir l'adresse de la fonction membre dans MSVC (à partir de MSVC 2005 IMHO). Mais c'est assez délicat. De plus, le pointeur obtenu est impossible à convertir en un autre type de pointeur par des moyens conventionnels. Bien qu'il existe néanmoins un moyen de le faire.

Voici l'exemple:

// class declaration
class MyClass
{
public:
    void Func();
    void Func(int a, int b);
};

// get the pointer to the member function
void (__thiscall MyClass::* pFunc)(int, int) = &MyClass::Func;

// naive pointer cast
void* pPtr = (void*) pFunc; // oops! this doesn't compile!

// another try
void* pPtr = reinterpret_cast<void*>(pFunc); // Damn! Still doesn't compile (why?!)

// tricky cast
void* pPtr = (void*&) pFunc; // this works

Le fait que la fonte conventionnelle ne fonctionne pas, même avec reinterpret_cast signifie probablement que MS ne recommande pas cette distribution très fortement.

Vous pouvez néanmoins le faire. Bien sûr, tout dépend de l'implémentation, vous devez connaître la convention d'appel appropriée pour effectuer le thunking + et avoir les compétences d'assembleur appropriées.

26
valdo

essaye ça. devrait vous permettre de lancer n'importe quoi sur n'importe quoi :)

template<typename OUT, typename IN>
OUT ForceCast( IN in )
{
    union
    {
        IN  in;
        OUT out;
    }
    u = { in };

    return u.out;
};

puis

void* member_address = ForceCast<void*>(&SomeClass::SomeMethod);
4
HaPpY

Par défaut, les fonctions membres C++ utilisent la convention d'appel __thiscall. Pour détourner une fonction membre, le trampoline et le détour doivent avoir exactement la même convention d'appel que la fonction cible. Malheureusement, le compilateur VC ne prend pas en charge un __thiscall, donc la seule façon de créer des fonctions de détour et de trampoline légales est de les faire membres d'une classe de "détour".

En outre, C++ ne prend pas en charge la conversion d'un pointeur vers une fonction membre en un pointeur arbitraire. Pour obtenir un pointeur brut, l'adresse de la fonction membre doit être déplacée dans un pointeur fonction membre temporaire, puis transmise en prenant son adresse, puis en la dé-référençant. Heureusement, le compilateur optimisera le code pour supprimer les opérations de pointeur supplémentaires.

à partir de la bibliothèque Microsoft Detour. Ils traitent de l'injection de code et discutent de l'obtention de l'adresse des fonctions des membres non viraux. Bien sûr, il s'agit de choses spécifiques à l'implémentation du compilateur.

vous pouvez trouver la bibliothèque ici http://research.Microsoft.com/en-us/downloads/d36340fb-4d3c-4ddd-bf5b-1db25d03713d/default.aspx

2
kreuzerkrieg