1 /** 2 * This file has no copyright assigned and is placed in the Public Domain. 3 * This file is part of the w64 mingw-runtime package. 4 * No warranty is given; refer to the file DISCLAIMER.PD within this package. 5 * 6 * Written by Kai Tietz <kai.tietz@onevision.com> 7 */ 8 9 #ifdef CRTDLL 10 #undef CRTDLL 11 #endif 12 13 #include <sect_attribs.h> 14 15 /*#ifndef WIN32_LEAN_AND_MEAN 16 #define WIN32_LEAN_AND_MEAN 17 #endif 18 #include <windows.h>*/ 19 20 #include <stdarg.h> 21 #include <windef.h> 22 #include <winbase.h> 23 24 #include <stdio.h> 25 #include <memory.h> 26 #include <malloc.h> 27 #ifndef _WIN64 28 #include <stdlib.h> /* for _winmajor */ 29 #endif 30 31 #ifndef __INTERNAL_FUNC_DEFINED 32 #define __INTERNAL_FUNC_DEFINED 33 typedef void (__cdecl *_PVFV)(void); 34 typedef int (__cdecl *_PIFV)(void); 35 typedef void (__cdecl *_PVFI)(int); 36 #endif 37 38 extern WINBOOL __mingw_TLScallback (HANDLE hDllHandle, DWORD reason, LPVOID reserved); 39 40 #define FUNCS_PER_NODE 30 41 42 typedef struct TlsDtorNode { 43 int count; 44 struct TlsDtorNode *next; 45 _PVFV funcs[FUNCS_PER_NODE]; 46 } TlsDtorNode; 47 48 ULONG _tls_index = 0; 49 50 /* TLS raw template data start and end. */ 51 _CRTALLOC(".tls") char _tls_start = 0; 52 _CRTALLOC(".tls$ZZZ") char _tls_end = 0; 53 54 _CRTALLOC(".CRT$XLA") PIMAGE_TLS_CALLBACK __xl_a = 0; 55 _CRTALLOC(".CRT$XLZ") PIMAGE_TLS_CALLBACK __xl_z = 0; 56 57 _CRTALLOC(".rdata$T") const IMAGE_TLS_DIRECTORY _tls_used = { 58 (ULONG_PTR) &_tls_start+1, (ULONG_PTR) &_tls_end, 59 (ULONG_PTR) &_tls_index, (ULONG_PTR) (&__xl_a+1), 60 (ULONG) 0, (ULONG) 0 61 }; 62 63 #ifndef __CRT_THREAD 64 #ifdef HAVE_ATTRIBUTE_THREAD 65 #define __CRT_THREAD __declspec(thread) 66 #else 67 #define __CRT_THREAD __thread 68 #endif 69 #endif 70 71 #define DISABLE_MS_TLS 1 72 73 static _CRTALLOC(".CRT$XDA") _PVFV __xd_a = 0; 74 static _CRTALLOC(".CRT$XDZ") _PVFV __xd_z = 0; 75 76 #if !defined (DISABLE_MS_TLS) 77 static __CRT_THREAD TlsDtorNode *dtor_list; 78 static __CRT_THREAD TlsDtorNode dtor_list_head; 79 #endif 80 81 extern int _CRT_MT; 82 83 #ifndef _WIN64 84 #define MINGWM10_DLL "mingwm10.dll" 85 typedef int (*fMTRemoveKeyDtor)(DWORD key); 86 typedef int (*fMTKeyDtor)(DWORD key, void (*dtor)(void *)); 87 fMTRemoveKeyDtor __mingw_gMTRemoveKeyDtor; 88 fMTKeyDtor __mingw_gMTKeyDtor; 89 int __mingw_usemthread_dll; 90 static HANDLE __mingw_mthread_hdll; 91 #endif 92 93 BOOL WINAPI __dyn_tls_init (HANDLE, DWORD, LPVOID); 94 95 BOOL WINAPI 96 __dyn_tls_init (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved) 97 { 98 _PVFV *pfunc; 99 uintptr_t ps; 100 101 #ifndef _WIN64 102 if (_winmajor < 4) 103 { 104 __mingw_usemthread_dll = 1; 105 __mingw_mthread_hdll = LoadLibrary (MINGWM10_DLL); 106 if (__mingw_mthread_hdll != NULL) 107 { 108 __mingw_gMTRemoveKeyDtor = (fMTRemoveKeyDtor) GetProcAddress (__mingw_mthread_hdll, "__mingwthr_remove_key_dtor"); 109 __mingw_gMTKeyDtor = (fMTKeyDtor) GetProcAddress (__mingw_mthread_hdll, "__mingwthr_key_dtor"); 110 } 111 if (__mingw_mthread_hdll == NULL || !__mingw_gMTRemoveKeyDtor || !__mingw_gMTKeyDtor) 112 { 113 __mingw_gMTKeyDtor = NULL; 114 __mingw_gMTRemoveKeyDtor = NULL; 115 if (__mingw_mthread_hdll) 116 FreeLibrary (__mingw_mthread_hdll); 117 __mingw_mthread_hdll = NULL; 118 _CRT_MT = 0; 119 return TRUE; 120 } 121 _CRT_MT = 1; 122 return TRUE; 123 } 124 #endif 125 /* We don't let us trick here. */ 126 if (_CRT_MT != 2) 127 _CRT_MT = 2; 128 129 if (dwReason != DLL_THREAD_ATTACH) 130 { 131 if (dwReason == DLL_PROCESS_ATTACH) 132 __mingw_TLScallback (hDllHandle, dwReason, lpreserved); 133 return TRUE; 134 } 135 136 ps = (uintptr_t) &__xd_a; 137 ps += sizeof (uintptr_t); 138 for ( ; ps != (uintptr_t) &__xd_z; ps += sizeof (uintptr_t)) 139 { 140 pfunc = (_PVFV *) ps; 141 if (*pfunc != NULL) 142 (*pfunc)(); 143 } 144 return TRUE; 145 } 146 147 const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback = (const PIMAGE_TLS_CALLBACK) __dyn_tls_init; 148 _CRTALLOC(".CRT$XLC") PIMAGE_TLS_CALLBACK __xl_c = (PIMAGE_TLS_CALLBACK) __dyn_tls_init; 149 150 int __cdecl __tlregdtor (_PVFV); 151 152 int __cdecl 153 __tlregdtor (_PVFV func) 154 { 155 if (!func) 156 return 0; 157 #if !defined (DISABLE_MS_TLS) 158 if (dtor_list == NULL) 159 { 160 dtor_list = &dtor_list_head; 161 dtor_list_head.count = 0; 162 } 163 else if (dtor_list->count == FUNCS_PER_NODE) 164 { 165 TlsDtorNode *pnode = (TlsDtorNode *) malloc (sizeof (TlsDtorNode)); 166 if (pnode == NULL) 167 return -1; 168 pnode->count = 0; 169 pnode->next = dtor_list; 170 dtor_list = pnode; 171 172 dtor_list->count = 0; 173 } 174 dtor_list->funcs[dtor_list->count++] = func; 175 #endif 176 return 0; 177 } 178 179 static BOOL WINAPI 180 __dyn_tls_dtor (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved) 181 { 182 #if !defined (DISABLE_MS_TLS) 183 TlsDtorNode *pnode, *pnext; 184 int i; 185 #endif 186 187 if (dwReason != DLL_THREAD_DETACH && dwReason != DLL_PROCESS_DETACH) 188 return TRUE; 189 /* As TLS variables are detroyed already by DLL_THREAD_DETACH 190 call, we have to avoid access on the possible DLL_PROCESS_DETACH 191 call the already destroyed TLS vars. 192 TODO: The used local thread based variables have to be handled 193 manually, so that we can control their lifetime here. */ 194 #if !defined (DISABLE_MS_TLS) 195 if (dwReason != DLL_PROCESS_DETACH) 196 { 197 for (pnode = dtor_list; pnode != NULL; pnode = pnext) 198 { 199 for (i = pnode->count - 1; i >= 0; --i) 200 { 201 if (pnode->funcs[i] != NULL) 202 (*pnode->funcs[i])(); 203 } 204 pnext = pnode->next; 205 if (pnext != NULL) 206 free ((void *) pnode); 207 } 208 } 209 #endif 210 __mingw_TLScallback (hDllHandle, dwReason, lpreserved); 211 return TRUE; 212 } 213 214 _CRTALLOC(".CRT$XLD") PIMAGE_TLS_CALLBACK __xl_d = (PIMAGE_TLS_CALLBACK) __dyn_tls_dtor; 215 216 217 int mingw_initltsdrot_force = 0; 218 int mingw_initltsdyn_force = 0; 219 int mingw_initltssuo_force = 0; 220