L’appel de la fonction de liaison statique se bloque à chaque fois sur Windows 8/10 mais pas 7

Le problème :

J’ai compilé le projet https://github.com/reorg/pg_repack dont ils génèrent un binary. Ce fichier binary est lié à postgres 9.6 redissortingbutable (j’utilise ceux fournis par EntrepriseDb). Tout fonctionne bien sur Windows 7. Je n’ai aucun problème pendant la construction ou pendant l’exécution. Mais sur Windows 8 ou 10, l’application se bloque toujours avec les séquences suivantes. Le binary est généré à partir de sources C avec visual studio 2013, sur Windows 7 (j’ai essayé avec une version générée sur Windows 10 mais cela ne change rien), sur un système x64, pour une application x64 et l’optimisation est désactivée et il utilise une base dynamic. Pour être sûr d’utiliser les bons binarys, j’ai copié tous les fichiers binarys redissortingbuables dans le dossier de mon application.

Détails d’assemblage sur Windows 7 (cas de travail):

Peu de lignes après la principale, l’application appelle la fonction set_pglocale_pgservice

set_pglocale_pgservice(argv[0], "pgscripts"); 00007FF6E4B39C85 mov eax,8 00007FF6E4B39C8A imul rax,rax,0 00007FF6E4B39C8E lea rdx,[default_options+120h (07FF6E4B43B10h)] 00007FF6E4B39C95 mov rcx,qword ptr [argv] 00007FF6E4B39C9A mov rcx,qword ptr [rcx+rax] 00007FF6E4B39C9E call qword ptr [__imp_set_pglocale_pgservice (07FF6E4B40520h)] 

Mémoire à 07FF6E4B40520h

 0x00007FF6E4B40520 00000001403e1da0 .>@.... 0x00007FF6E4B40528 0000000000000000 ........ 0x00007FF6E4B40530 0000000000000000 ........ 0x00007FF6E4B40538 00007ff6e4b35348 HS.äö... 

(note: de 0x7FF6E4B40000 à 0x00007FF6E4B40560, la mémoire contient des adresses de fonctions et mapfile indique: 0002: 00000520 __imp_set_pglocale_pgservice postgres: postgres.exe [postgres redissortingbuable, lié de manière dynamic])

Puis après l’appel qword ptr [__imp_set_pglocale_pgservice (07FF6E4B40520h)]

 00000001403E1DA0 mov qword ptr [rsp+18h],rbx 00000001403E1DA5 push rdi 00000001403E1DA6 sub rsp,0C40h 00000001403E1DAD mov rax,qword ptr [1405F8C60h] 00000001403E1DB4 xor rax,rsp 00000001403E1DB7 mov qword ptr [rsp+0C30h],rax 00000001403E1DBF mov rbx,rdx 00000001403E1DC2 mov rdi,rcx 00000001403E1DC5 lea rdx,[140430540h] 00000001403E1DCC mov rcx,rbx 00000001403E1DCF call 00000001403F67FA 

Puis après l’appel 00000001403F67FA

 00000001403F67FA jmp qword ptr [1403F8998h] 

Mémoire à 1403F8998h

 0x00000001403F8998 00007ffe87a5cc60 `Ì¥.þ... 0x00000001403F89A0 00007ffe87a47060 `p¤.þ... 0x00000001403F89A8 00007ffe87a5f8a4 ¤ø¥.þ... 

(note: de 0x00000001403F8000 à 0x00000001403F8F08, la mémoire contient l’adresse des fonctions, et mapfile indique: 0002: 00000998 ?? _ C @ _04FHBLDJDJ @? 1bin? $ AA @ libpgport: path.obj [postgres redissortingbuable, lié de manière statique])

Puis après le saut à 00007ffe87a5cc60

 00007FFE87A5CC60 sub rdx,rcx 00007FFE87A5CC63 test cl,7 00007FFE87A5CC66 je 00007FFE87A5CC7C 

… et tout fonctionne bien

Détails d’assemblage sur Windows 10 (pas cas de travail):

Peu de lignes après la principale, l’application appelle la fonction set_pglocale_pgservice

 set_pglocale_pgservice(argv[0], "pgscripts"); 00007FF7E9879C85 mov eax,8 00007FF7E9879C8A imul rax,rax,0 00007FF7E9879C8E lea rdx,[default_options+120h (07FF7E9883B10h)] 00007FF7E9879C95 mov rcx,qword ptr [argv] 00007FF7E9879C9A mov rcx,qword ptr [rcx+rax] 00007FF7E9879C9E call qword ptr [__imp_set_pglocale_pgservice (07FF7E9880520h)] 

Mémoire à 07FF7E9880520h

 0x00007FF7E9880520 00000001403e1da0 .>@.... 0x00007FF7E9880528 0000000000000000 ........ 0x00007FF7E9880530 0000000000000000 ........ 0x00007FF7E9880538 00007ff7e9875348 HS.é÷... 

(note: de 0x00007FF7E9880000 à 0x00007FF7E9880560, la mémoire contient des adresses de fonctions et mapfile indique: 0002: 00000520 __imp_set_pglocale_pgservice postgres: postgres.exe [postgres redissortingbuable, lié de manière dynamic])

Puis après l’appel qword ptr [__imp_set_pglocale_pgservice (07FF7E9880520h)]

 00000001403E1DA0 mov qword ptr [rsp+18h],rbx 00000001403E1DA5 push rdi 00000001403E1DA6 sub rsp,0C40h 00000001403E1DAD mov rax,qword ptr [1405F8C60h] 00000001403E1DB4 xor rax,rsp 00000001403E1DB7 mov qword ptr [rsp+0C30h],rax 00000001403E1DBF mov rbx,rdx 00000001403E1DC2 mov rdi,rcx 00000001403E1DC5 lea rdx,[140430540h] 00000001403E1DCC mov rcx,rbx 00000001403E1DCF call 00000001403F67FA 

Puis après l’appel 00000001403F67FA

 00000001403F67FA jmp qword ptr [1403F8998h] (should call C@_04FHBLDJDJ@?1bin?$AA@ libpgport:path.obj [postgres redissortingbutable, which is linked statically])) 

Mémoire à 1403F8998h (ici, l’application diffère de Windows 7)

 0x00000001403F8998 000000000059e6a2 ¢æY..... 0x00000001403F89A0 000000000059e6ac ¬æY..... 0x00000001403F89A8 000000000059e6b6 ¶æY..... 

(note: 0x00000001403F8998 est l’adresse du code op au milieu de la fonction, pas l’adresse d’une fonction)

 00000001403F8998 mov byte ptr [AC000000000059E6h],al 00000001403F89A1 out 59h,al 00000001403F89A3 add byte ptr [rax],al ... 

Mémoire à 000000000059e6a2h

 000000000059E69F ?? ?? 000000000059E6A0 ?? ?? 000000000059E6A1 ?? ?? 

Puis après le saut à 000000000059e6a2 => crash

Traiter les détails du moniteur sur Windows 7 pour le chargement des bibliothèques (ici libpq.dll):

 [...] "16:48:40,2946466","pg_repack.exe","7216","Load Image","C:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Image Base: 0x180000000, Image Size: 0x30000" [...] 

Traiter les détails du moniteur sur Windows 10 (ici libpq.dll) (tout est très similaire à Windows 7, à l’exception du chargement des bibliothèques)

 [...] "11:52:20,6264717","pg_repack.exe","12464","QueryOpen","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","CreationTime: 21/08/2017 11:38:04, LastAccessTime: 21/08/2017 12:06:56, LastWriteTime: 09/05/2017 06:45:07, ChangeTime: 21/08/2017 18:04:09, AllocationSize: 184 320, EndOfFile: 183 296, FileAtsortingbutes: A" "11:52:20,6265789","pg_repack.exe","12464","CreateFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Desired Access: Read Data/List Directory, Execute/Traverse, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Atsortingbutes: n/a, ShareMode: Read, Delete, AllocationSize: n/a, OpenResult: Opened" "11:52:20,6266332","pg_repack.exe","12464","QuerySecurityFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Information: 0x20" "11:52:20,6266513","pg_repack.exe","12464","CreateFileMapping","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","FILE LOCKED WITH ONLY READERS","SyncType: SyncTypeCreateSection, PageProtection: PAGE_EXECUTE" "11:52:20,6266921","pg_repack.exe","12464","CreateFileMapping","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","SyncType: SyncTypeOther" "11:52:20,6267619","pg_repack.exe","12464","Load Image","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Image Base: 0x180000000, Image Size: 0x30000" "11:52:20,6274889","pg_repack.exe","12464","CreateFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Desired Access: Generic Read, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Atsortingbutes: n/a, ShareMode: Read, Delete, AllocationSize: n/a, OpenResult: Opened" "11:52:20,6275293","pg_repack.exe","12464","QuerySecurityFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Information: 0x20" "11:52:20,6275471","pg_repack.exe","12464","QueryBasicInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","CreationTime: 21/08/2017 11:38:04, LastAccessTime: 21/08/2017 12:06:56, LastWriteTime: 09/05/2017 06:45:07, ChangeTime: 21/08/2017 18:04:09, FileAtsortingbutes: A" "11:52:20,6276255","pg_repack.exe","12464","CloseFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","" "11:52:20,6291170","pg_repack.exe","12464","CloseFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","" [...] "11:52:20,6539022","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","BUFFER OVERFLOW","Name: \testF" "11:52:20,6539202","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","BUFFER OVERFLOW","Name: \testF" "11:52:20,6539363","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","BUFFER OVERFLOW","Name: \testF" "11:52:20,6539512","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","BUFFER OVERFLOW","Name: \testF" "11:52:20,6539664","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","BUFFER OVERFLOW","Name: \testF" "11:52:20,6603867","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Name: \testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll" "11:52:20,6604319","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Name: \testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll" "11:52:20,6604778","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Name: \testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll" "11:52:20,6605211","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Name: \testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll" "11:52:20,6605635","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Name: \testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll" [...] 

Note: Je m’attendais à quelque chose de similaire à Windows 7 ou du moins à quelque chose comme:

 "11:52:20,6539022","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","BUFFER OVERFLOW","Length: 63". 

Donc, je ne sais pas pourquoi cette application a un comportement si strange sur Windows 8 ou 10. Je serais ravi si quelqu’un avait des explications ou des idées pour corriger des plantages. N’hésitez pas à demander des détails si nécessaire.

Je regarde votre paquet binary et affiche que vous pg_repack.exe qui importe statiquement de postgres.exe . et racine du problème – est importation du fichier exe. plus exactement à partir du fichier PE qui n’a pas de drapeau IMAGE_FILE_DLL dans IMAGE_FILE_HEADER .Characteristics , car l’extension formelle ( exe , dll , etc. ne joue pas le rôle). en bref, je vais dans prochain sous exe signifie fichier PE sans IMAGE_FILE_DLL dans les Characteristics , mais pas l’extension de fichier formel

au premier chargement exe car dll est incorrect – quand exe chargé de cette façon – le point d’entrée non appelé. et ne peut pas être appelé, car il n’est pas conçu pour être appelé en tant que rappel, recevant DLL_PROCESS_* notification DLL_PROCESS_* , et appelez ExitProcess à la fin. lorsque le point d’entrée du module n’est pas appelé – en général, il n’est pas initialisé. supposons que vous appeliez une fonction exscope depuis exe , mais que se passe-t-il si cette fonction exscope utilise des données qui normalement sont initialisées au point d’entrée exe ? donc conclusion – nous pouvons appeler les fonctions exscopes à partir d’ exe uniquement à partir de la DLL chargée dans ce processus exe . et dans chaque processus doit être qu’un seul exe (en tant que code exécutable).

à la deuxième postgres.exe spécifique n’a pas de relocalisation (indicateur IMAGE_FILE_RELOCS_STRIPPED dans IMAGE_FILE_HEADER.Characteristics ) – en conséquence, ce PE peut être chargé uniquement à l’adresse codée en dur. Ce n’est pas un problème pour exe , qui a toujours mappé en premier pour traiter, quand presque tout l’espace d’adressage est libre. mais en général, cela pose problème lorsque le PE est chargé en tant que DLL – pas en premier dans le processus – la firebase database du code dur peut être déjà occupée. donc conclusion – vous ne pouvez pas utiliser n’importe quel exe sans relogement en tant que DLL

Cependant, la racine de crash sur Windows 10 – parce que Windows 10 ne résout pas l’importation PE (“exe”) si ce pe n’a pas de drapeau IMAGE_FILE_DLL . en d’autres termes, il traite ce PE comme LoadLibraryEx avec l’indicateur DONT_RESOLVE_DLL_REFERENCES – ne charge pas les modules exécutables supplémentaires référencés par le module spécifié et ne résout pas les importations. par conséquent, ce PE n’est pas initialisé et se bloque au premier appel de la fonction d’importation (dans votre cas, il s’agit de strcmp ).

et cela ne se produit que sur win10. sur win 8.1 (build 9600) et l’importation de win 7 pour les fichiers exe (chargés comme dll ) résolus. ( vous dites que lors de votre victoire 8.1, il est tombé en panne – peut-être utilisez-vous plus de nouvelle version ou une mise à jour? )

le test le plus simple pour cet appel de comportement à partir de test exe MatchToken , fonction, qui a exporté à partir de Netsh.exe . le code peut être suivant:

 #include  #pragma comment(linker, "/defaultlib:Netsh.lib") MatchToken(L"*", L"*");// crash here on win 10 

Crash sur Win10 car MatchToken essaie en interne d’appeler _wcsnicmp partir de msvcrt.dll , mais dans win10 cette importation n’est pas résolue. mais sur win8.1, win7, gagnez xp – ce code fonctionne bien.

exemple un peu plus complexe:

 if (HMODULE hmod = LoadLibraryW(L"wshelper.dll")) { DWORD (WINAPI * InitHelperDll)(_In_ DWORD dwNetshVersion, PVOID pReserved); if (*(void**)&InitHelperDll = GetProcAddress(hmod, "InitHelperDll")) { InitHelperDll(1, 0);// crash here on win10 only } FreeLibrary(hmod); } 

Ici, nous chargeons Windows NetShell helper dll standard – “wshelper.dll” et appelons la fonction de rappel InitHelperDll . en interne, InitHelperDll appelle la fonction RegisterHelper partir de Netsh.exe . mais encore une fois, parce que Netsh.exe n’est pas initialisé (importation non résolue) quand il se charge en tant que DLL dans la victoire 10 – il est tombé en panne dans RegisterHelper