2009-02-06 6 views
2

J'ai joué avec le Digital Mars Compiler gratuit au travail (vilain je sais), et créé du code pour inspecter les fonctions compilées et regarder le code d'octets à des fins d'apprentissage, voir si je peut apprendre quelque chose de précieux de la façon dont le compilateur construit ses fonctions. Cependant, recréer la même méthode dans MSVC++ a échoué lamentablement et les résultats que je reçois sont assez confus. J'ai une fonction comme ceci:Problème lors de l'examen du code d'octet dans MSVC++

unsigned int __stdcall test() 
{ 
    return 42; 
} 

Puis plus tard, je fais:

unsigned char* testCode = (unsigned char*)test; 

Je ne peux pas sembler obtenir le C++ static_cast pour travailler dans ce cas (il renvoie une erreur du compilateur) .. d'où le casting de style C, mais c'est d'ailleurs le point ... J'ai également essayé d'utiliser le test de référence &, mais cela ne aide pas. Maintenant, quand j'examine le contenu de la mémoire pointée par testCode, je suis confus parce que ce que je vois ne ressemble même pas à du code valide, et a même un point d'arrêt de débogage coincé là ... ça ressemble à ça (cible est IA-32):

0xE9, 0xBC, 0x18, 0x00, 0x00, 0xcc ...

Ceci est manifestement erronée, 0xE9 est une instruction de saut relatif, et en regardant 0xBC octets loin, il ressemble à ceci:

0xcc, 0xcc, 0xcc ...

c'est-à-dire la mémoire initialisée à l'opcode debug breakpoint comme prévu pour la mémoire non allouée ou non utilisée.

Où que ce que je pense d'une fonction de retour 42 serait quelque chose comme:

0x8b, 0x2a, 0x00, 0x00, 0x00, 0xC3

ou tout au moins un peu de saveur de mov suivi d'un ret (0xc2, 0xc3, 0xca ou 0xcb) un peu plus bas

Est-ce que MSVC++ prend des mesures pour m'empêcher de faire ce genre de chose pour des raisons de sécurité, ou est-ce que je fais quelque chose de stupide sans m'en rendre compte? Cette méthode semble fonctionner correctement en utilisant DMC comme compilateur ...

J'ai aussi des problèmes pour aller dans l'autre sens (en exécutant des octets), mais je soupçonne que la cause sous-jacente est la même.

Toute aide ou conseil serait grandement appréciée.

+0

reinterpret_cast est destiné à la diffusion de pointeurs, static_cast est utilisé pour lancer des types "connexes" qui ne correspondent pas à dynamic_cast –

Répondre

2

Je ne peux que deviner, mais je suis sûr que vous inspectez une version de débogage. En mode débogage, le compilateur MSVC++ remplace tous les appels par des appels aux jumps.Cela signifie que chaque fonction commence par un saut à la fonction réelle et c'est exactement ce que vous faites face ici.
Les octets 0xCC environnants sont en effet des instructions de point de rupture, afin de déclencher un débogueur éventuellement attaché au cas où vous exécutez du code où vous ne devriez pas.
Essayez la même chose avec une version de construction. Cela devrait fonctionner comme prévu.

Édition: Ceci est réellement affecté par le paramètre de l'éditeur de liens/INCREMENTAL. La raison pour laquelle l'effet que vous décrivez n'apparaît pas dans les versions de versions, c'est que ces dernières sont simplement optimisées si un type d'optimisation est activé (ce qui est généralement le cas pour les versions de versions).

1

Si vous souhaitez examiner l'assembly et le code machine pour une fonction compilée donnée, il sera plus facile de fournir l'option de ligne de commande/FAcs au compilateur et de regarder le fichier .asm qui en découle. Je ne suis pas sûr de ce que le comportement défini est pour couler un pointeur de fonction à un flux d'octets - il peut même ne pas fonctionner correctement - mais une source possible de confusion supplémentaire est que les fonctions x86 sont toutes des tailles variables et petit-boutiste aussi.

1

Si la liaison incrémentielle est activée, ce que vous voyez est jmp [destination]. Vous pouvez exécuter le débogueur et voir ce que le démontage doit également vérifier.

2

Pour votre casting que vous voulez:

unsigned char* testCode = reinterpret_cast<unsigned char*>(test); 

Switch Informations de débogage Format de 'base de données de programme pour modifier & Continuer (/ zi)' à 'Base de données de programme (/ Zi)' dans le projet -> Propriétés -> C/C++ -> Général. Je crois que c'est ce paramètre qui amène le compilateur à insérer du code de saut pour que le débogueur puisse reconstruire une fonction et le correctif pendant que le programme est en cours d'exécution. Éteignez probablement 'Enable Minimal Rebuild' également. Une manière beaucoup plus simple d'inspecter le code dans MSVC est de simplement définir un point de rupture et inspecter le démontage (faites un clic droit sur la ligne et sélectionnez "Goto disassembly" dans le menu contextuel.) Il annote le démontage avec le code source pour que vous puissiez voir à quoi chaque ligne est compilée

+0

Merci pour les informations utiles, cela a résolu le problème avec le casting C++ ... j'ai supposé à tort que réinterpréter était seulement pour travailler autour des questions avec l'héritage je suis conscient du "goto démontage" mais je cherche quelque chose à l'exécution merci beaucoup cependant. bonne réponse. :) – jheriko

Questions connexes