2010-01-12 5 views
3

J'exporte une fonction [using _declspec (dllexport)] à partir d'un exe C++. La fonction fonctionne bien lorsqu'elle est invoquée par l'exe lui-même. Je charge cet exe (appelons cet exe1) d'un autre exe [l'exe du projet de test - je l'appelle exe2] en utilisant la liaison statique ie j'utilise le fichier .lib d'exe1 pendant la compilation exe2 et exe2 le charge en mémoire au démarrage comme n'importe quelle DLL. Cela provoque l'échec de la fonction lors de l'exécution.Chargement d'un exe à partir d'un exe

Le problème exact est révélé dans le désassemblage pour une déclaration de cas de commutation dans la fonction.

Code de l'Assemblée lorsque exe1 invoque la fonction

switch (dwType) 
0040FF84 mov   eax,dword ptr [dwType] 
0040FF87 mov   dword ptr [ebp-4],eax 
0040FF8A cmp   dword ptr [ebp-4],0Bh 
0040FF8E ja   $LN2+7 (40FFD2h) 
0040FF90 mov   ecx,dword ptr [ebp-4] 
0040FF93 jmp   dword ptr (40FFE0h)[ecx*4] 

Tenir compte des deux dernières instructions. Le mov déplace l'argument passé en ecx. À 40EFF0h nous avons des adresses pour les différentes instructions pour les déclarations de cas respectifs. Ainsi, la JMP nous emmènerait aux instructions de cas pertinentes

Code Assemblée lorsque exe2 appelle la fonction

switch (dwType) 
0037FF84 mov   eax,dword ptr [dwType] 
0037FF87 mov   dword ptr [ebp-4],eax 
0037FF8A cmp   dword ptr [ebp-4],0Bh 
0037FF8E ja   $LN2+7 (37FFD2h) 
0037FF90 mov   ecx,dword ptr [ebp-4] 
0037FF93 jmp   dword ptr [ecx*4+40FFE0h] 

spot ce qui se passe mal? Les adresses d'instruction. Le code a maintenant été chargé dans un endroit différent en mémoire. Quand exe1 a été compilé, le compilateur a supposé que nous le lancerions toujours et donc il serait toujours chargé à 0x0040000 [comme c'est le cas avec toutes les fenêtres exes]. Donc, il a codé en dur quelques valeurs comme 40FFE0h dans les instructions. Seulement dans le second cas 40FFE0 est aussi bon que la mémoire indésirable puisque la table d'adresse d'instruction que nous recherchons ne se trouve pas là.

Comment puis-je résoudre ce problème sans convertir exe1 en dll?

Répondre

1

ne le faites pas. Cela ne vaut pas la peine.

J'ai essayé de faire ce que vous essayez il y a un moment. Vous pouvez éventuellement résoudre le problème exe non-relocatable en changeant l'option dans la fenêtre des propriétés sous "Linker-> Advenced-> Adresse de base fixe" mais vous aurez d'autres problèmes.
La chose qui m'a finalement fait réaliser que c'est une perte de temps se rend compte que l'EXE n'a pas de fonction DllMain(). Cela signifie que la bibliothèque CRT n'est pas initialisée et que toutes sortes de choses ne fonctionnent pas comme prévu.

Here's the question I posted about this a while back

+0

Essayé de faire la même chose, et atteint la même conclusion. – Chad

1

Avez-vous envisagé une autre façon de le faire? Tels que faire le 2ème .exe dans un .dll et l'invoquer avec rundll32 quand vous voulez l'utiliser comme un exécutable?

Sinon: L'assemblage généré est correct. Le problème est que les exécutables portables Win32 ont une adresse de base (0x0040000 dans ce cas) et une section qui contient des détails sur les emplacements des adresses afin qu'ils puissent être rebasés si nécessaire.

Donc, une chose se passe pour deux choses: - Le compilateur n'inclut pas les enregistrements IMAGE_BASE_RELOCATION lors de la génération du fichier .exe. - Ou le moteur d'exécution ne remplit pas les relocalisations de base lors du chargement dynamiclaly le .exe - (peut-être les deux)

Si le fichier .exe contient les enregistrements de réinstallation, vous pouvez les lire et d'effectuer le déplacement de base vous-même. Vous devrez sauter à travers des cerceaux comme vous assurer que vous avez un accès en écriture à la mémoire (VirtualAlloc etc.) mais c'est conceptuellement assez simple.Si le .exe ne contient pas les enregistrements de relocalisation, vous êtes bourré - soit trouvez une option de compilateur pour forcer leur inclusion, soit trouvez une autre façon de faire ce que vous faites. Editer: Comme le souligne Shoosh, vous pouvez rencontrer d'autres problèmes une fois que vous avez résolu celui-ci.

Questions connexes