@@ -746,7 +746,96 @@ static void NTAPI mi_win_main(PVOID module, DWORD reason, LPVOID reserved) {
746746}
747747
748748
749- #if defined(MI_SHARED_LIB )
749+ #if 1 /* we use a combination of _pRawDllMain and TLS init/fini for both static and dynamic linkage */
750+ #define MI_PRIM_HAS_PROCESS_ATTACH 1
751+ // nothing to do since `_mi_thread_done` is handled through the DLL_THREAD_DETACH event.
752+ void _mi_prim_thread_init_auto_done (void ) {}
753+ void _mi_prim_thread_done_auto_done (void ) {}
754+ void _mi_prim_thread_associate_default_theap (mi_theap_t * theap ) {
755+ MI_UNUSED (theap );
756+ }
757+
758+ // If linked into a DLL module, this raw entry is called before the CRT attach and
759+ // after the CRT detach through the CRT _pRawDllMain pointer.
760+ static BOOL NTAPI mi_dll_main_raw (PVOID module , DWORD reason , LPVOID reserved ) {
761+ //if (reason == DLL_PROCESS_ATTACH) { mi_debug_out("dll process attach\n"); }
762+ //else if (reason == DLL_PROCESS_DETACH) { mi_debug_out("dll process detach\n"); }
763+ //else if (reason == DLL_THREAD_ATTACH) { mi_debug_out("dll thread attach\n"); }
764+ //else if (reason == DLL_THREAD_DETACH) { mi_debug_out("dll thread detach\n"); }
765+ mi_win_main (module , reason , reserved );
766+ return TRUE;
767+ }
768+
769+ // Set the value of the CRT _pRawDllMain pointer
770+ #if defined(__cplusplus )
771+ extern "C"
772+ #endif
773+ PVOID _pRawDllMain = & mi_dll_main_raw ;
774+
775+ // We also hook into the Windows loader TLS initialization and finalization.
776+ // If we are linked into an EXE module we rely on these as `mi_dll_main_raw`
777+ // is not called (and otherwise we ignore the TLS callbacks by checking if we are in a DLL).
778+ static bool mi_module_is_dll (PVOID mod ) {
779+ if (mod == NULL ) return false;
780+ PIMAGE_DOS_HEADER imageDosHeader = (PIMAGE_DOS_HEADER )mod ;
781+ PIMAGE_NT_HEADERS imageNtHeaders = (PIMAGE_NT_HEADERS )((unsigned char * )imageDosHeader + imageDosHeader -> e_lfanew );
782+ return ((imageNtHeaders -> FileHeader .Characteristics & IMAGE_FILE_DLL ) == IMAGE_FILE_DLL );
783+ }
784+
785+ static void NTAPI mi_tls_attach (PVOID module , DWORD reason , LPVOID reserved ) {
786+ if (reason == DLL_PROCESS_ATTACH || reason == DLL_THREAD_ATTACH ) {
787+ if (!mi_module_is_dll (module )) {
788+ // mi_debug_out(reason==DLL_PROCESS_ATTACH ? "exe process attach\n" : "exe thread attach\n");
789+ mi_win_main (module , reason , reserved );
790+ }
791+ }
792+ }
793+ static void NTAPI mi_tls_detach (PVOID module , DWORD reason , LPVOID reserved ) {
794+ if (reason == DLL_PROCESS_DETACH || reason == DLL_THREAD_DETACH ) {
795+ if (!mi_module_is_dll (module )) {
796+ // mi_debug_out(reason==DLL_PROCESS_DETACH ? "exe process detach\n" : "exe thread detach\n");
797+ mi_win_main (module , reason , reserved );
798+ }
799+ }
800+ }
801+
802+ // Set up TLS callbacks in a statically linked library by using special data sections.
803+ // See <https://stackoverflow.com/questions/14538159/tls-callback-in-windows>
804+ // We use 2 entries to ensure we call attach events before constructors
805+ // are called, and detach events after destructors are called.
806+ #if defined(__cplusplus )
807+ extern "C" {
808+ #endif
809+
810+ #if defined(_WIN64 )
811+ #pragma comment(linker, "/INCLUDE:_tls_used")
812+ #pragma comment(linker, "/INCLUDE:_mi_tls_callback_pre")
813+ #pragma comment(linker, "/INCLUDE:_mi_tls_callback_post")
814+ #pragma const_seg(".CRT$XLB")
815+ extern const PIMAGE_TLS_CALLBACK _mi_tls_callback_pre [];
816+ const PIMAGE_TLS_CALLBACK _mi_tls_callback_pre [] = { & mi_tls_attach };
817+ #pragma const_seg()
818+ #pragma const_seg(".CRT$XLY")
819+ extern const PIMAGE_TLS_CALLBACK _mi_tls_callback_post [];
820+ const PIMAGE_TLS_CALLBACK _mi_tls_callback_post [] = { & mi_tls_detach };
821+ #pragma const_seg()
822+ #else
823+ #pragma comment(linker, "/INCLUDE:__tls_used")
824+ #pragma comment(linker, "/INCLUDE:__mi_tls_callback_pre")
825+ #pragma comment(linker, "/INCLUDE:__mi_tls_callback_post")
826+ #pragma data_seg(".CRT$XLB")
827+ PIMAGE_TLS_CALLBACK _mi_tls_callback_pre [] = { & mi_tls_attach };
828+ #pragma data_seg()
829+ #pragma data_seg(".CRT$XIY")
830+ PIMAGE_TLS_CALLBACK _mi_tls_callback_post [] = { & mi_tls_detach };
831+ #pragma data_seg()
832+ #endif
833+
834+ #if defined(__cplusplus )
835+ }
836+ #endif
837+
838+ #elif defined(MI_SHARED_LIB)
750839 #define MI_PRIM_HAS_PROCESS_ATTACH 1
751840
752841 // Windows DLL: easy to hook into process_init and thread_done
@@ -775,7 +864,7 @@ static void NTAPI mi_win_main(PVOID module, DWORD reason, LPVOID reserved) {
775864 mi_win_main (module , reason , reserved );
776865 }
777866 }
778-
867+
779868 // Set up TLS callbacks in a statically linked library by using special data sections.
780869 // See <https://stackoverflow.com/questions/14538159/tls-callback-in-windows>
781870 // We use 2 entries to ensure we call attach events before constructors
@@ -795,15 +884,15 @@ static void NTAPI mi_win_main(PVOID module, DWORD reason, LPVOID reserved) {
795884 #pragma const_seg(".CRT$XLY")
796885 extern const PIMAGE_TLS_CALLBACK _mi_tls_callback_post [];
797886 const PIMAGE_TLS_CALLBACK _mi_tls_callback_post [] = { & mi_win_main_detach };
798- #pragma const_seg()
887+ #pragma const_seg()
799888 #else
800889 #pragma comment(linker, "/INCLUDE:__tls_used")
801890 #pragma comment(linker, "/INCLUDE:__mi_tls_callback_pre")
802891 #pragma comment(linker, "/INCLUDE:__mi_tls_callback_post")
803892 #pragma data_seg(".CRT$XLB")
804893 PIMAGE_TLS_CALLBACK _mi_tls_callback_pre [] = { & mi_win_main_attach };
805894 #pragma data_seg()
806- #pragma data_seg(".CRT$XLY ")
895+ #pragma data_seg(".CRT$XIY ")
807896 PIMAGE_TLS_CALLBACK _mi_tls_callback_post [] = { & mi_win_main_detach };
808897 #pragma data_seg()
809898 #endif
@@ -903,6 +992,7 @@ static void NTAPI mi_win_main(PVOID module, DWORD reason, LPVOID reserved) {
903992 mi_redirected = false;
904993 }
905994 else if (reason == DLL_THREAD_DETACH ) {
995+ // mi_debug_out("redirect thread detach\n");
906996 _mi_thread_done (NULL );
907997 }
908998 }
0 commit comments