Question

J'ai été déconner avec le compilateur Free Digital Mars au travail (je sais méchant), et créé un code pour inspecter les fonctions compilées et regarder le code d'octets à des fins d'apprentissage, voir si je peux apprendre quelque chose de précieux de la façon dont le compilateur construit ses fonctions. Cependant, en recréant la même méthode dans MSVC ++ a lamentablement échoué et les résultats que je reçois sont assez confus. J'ai une fonction comme ceci:

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 C-style, mais c'est d'ailleurs le point ... J'ai aussi essayé d'utiliser la référence et test, mais qui 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 regarde même pas comme un code valide, et a même un point d'arrêt de débogage coincé là-dedans ... ç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 octets 0xBC loin, il ressemble à ceci:

0xcc, 0xcc, 0xcc ...

i.e.. mémoire initialisés à l'opcode de débogage comme point d'arrêt 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 au moins une partie de la saveur mov suivie d'une ret (0xC2, 0xC3, 0xCA ou 0xCB) un peu plus loin vers le bas

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

Je suis aussi de la difficulté à aller dans l'autre sens (exécution d'octets), mais je soupçonne que la cause sous-jacente est la même.

Toute aide ou des conseils seraient grandement appréciés.

Était-ce utile?

La solution

Je ne peux que deviner, mais je suis sûr que vous inspectez une version de débogage. En mode débogage MSVC ++ compilateur remplace tous les appels par les appels à sauter des talons. 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 les instructions des points d'arrêt, afin de tirer un débogueur éventuellement attaché au cas où vous l'exécution de code où vous ne devriez pas.
Essayez la même chose avec une version release. Cela devrait fonctionner comme prévu.

Edit: Ceci est en fait affectée par le réglage de linker / incrémentales. La raison pour laquelle l'effet que vous décrivez ne se présente pas dans la version construit est que ces talons de saut sont simplement optimisés immédiatement si un type d'optimisation est activée (ce qui est évidemment généralement le cas pour la libération construit).

Autres conseils

Pour votre casting que vous voulez:

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

Commutateur Format de l'information de débogage de 'base de données de programme pour modifier et continuer (/ zi)' à 'base de données du programme (/ Zi)' dans le projet -> Propriétés -> C / C ++ -> Général. Je crois qu'il est ce paramètre qui provoque le compilateur d'insérer du code de saut de sorte que le débogueur peut reconstruire une fonction et un patch chaud dans tout le programme est en cours. Probablement désactiver l'option 'Activer Minimal Rebuild' aussi.

Une façon beaucoup plus simple d'inspecter le code dans MSVC est simplement définir un point de rupture et d'inspecter le démontage (clic droit sur la ligne et sélectionnez « Aller à démonter » dans le menu contextuel. Il annote le démontage à la source le code de sorte que vous pouvez voir ce que chaque ligne est compilé.

Si vous voulez regarder le montage et le code de la machine pour une fonction compilée donnée, il sera plus facile de fournir l'option de ligne de commande / FACS au compilateur et regardez le fichier .asm qui a suivi.

Je ne suis pas sûr de ce que le comportement défini est pour la coulée d'un pointeur de fonction à un flux d'octets - il peut même pas fonctionner correctement - mais une source possible de confusion supplémentaire est que les fonctions x86 sont toutes tailles variables et peu -endian aussi.

Si cela est avec la liaison incrémentielle activée, alors ce que vous voyez est un jmp [destination]. Vous pouvez exécuter le débogueur et voir ce que le démontage est de vérifier aussi bien.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top