1 /** 2 * This file has no copyright assigned and is placed in the Public Domain. 3 * This file is part of the mingw-w64 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 <stdio.h> 21 #include <memory.h> 22 #include <malloc.h> 23 #ifndef __REACTOS__ 24 #include <corecrt_startup.h> 25 #else 26 #include <internal.h> 27 #endif 28 29 extern WINBOOL __mingw_TLScallback (HANDLE hDllHandle, DWORD reason, LPVOID reserved); 30 31 #define FUNCS_PER_NODE 30 32 33 typedef struct TlsDtorNode { 34 int count; 35 struct TlsDtorNode *next; 36 _PVFV funcs[FUNCS_PER_NODE]; 37 } TlsDtorNode; 38 39 ULONG _tls_index = 0; 40 41 /* TLS raw template data start and end. 42 We use here pointer-types for start/end so that tls-data remains 43 aligned on pointer-size-width. This seems to be required for 44 pe-loader. */ 45 _CRTALLOC(".tls") char *_tls_start = NULL; 46 _CRTALLOC(".tls$ZZZ") char *_tls_end = NULL; 47 48 _CRTALLOC(".CRT$XLA") PIMAGE_TLS_CALLBACK __xl_a = 0; 49 _CRTALLOC(".CRT$XLZ") PIMAGE_TLS_CALLBACK __xl_z = 0; 50 51 const IMAGE_TLS_DIRECTORY _tls_used = { 52 (ULONG_PTR) &_tls_start, (ULONG_PTR) &_tls_end, 53 (ULONG_PTR) &_tls_index, (ULONG_PTR) (&__xl_a+1), 54 (ULONG) 0, (ULONG) 0 55 }; 56 57 #ifndef __CRT_THREAD 58 #ifdef HAVE_ATTRIBUTE_THREAD 59 #define __CRT_THREAD __declspec(thread) 60 #else 61 #define __CRT_THREAD __thread 62 #endif 63 #endif 64 65 #define DISABLE_MS_TLS 1 66 67 static _CRTALLOC(".CRT$XDA") _PVFV __xd_a = 0; 68 static _CRTALLOC(".CRT$XDZ") _PVFV __xd_z = 0; 69 70 #if !defined (DISABLE_MS_TLS) 71 static __CRT_THREAD TlsDtorNode *dtor_list; 72 static __CRT_THREAD TlsDtorNode dtor_list_head; 73 #endif 74 75 extern int _CRT_MT; 76 77 BOOL WINAPI __dyn_tls_init (HANDLE, DWORD, LPVOID); 78 79 BOOL WINAPI 80 __dyn_tls_init (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved) 81 { 82 _PVFV *pfunc; 83 uintptr_t ps; 84 85 /* We don't let us trick here. */ 86 if (_CRT_MT != 2) 87 _CRT_MT = 2; 88 89 if (dwReason != DLL_THREAD_ATTACH) 90 { 91 if (dwReason == DLL_PROCESS_ATTACH) 92 __mingw_TLScallback (hDllHandle, dwReason, lpreserved); 93 return TRUE; 94 } 95 96 ps = (uintptr_t) &__xd_a; 97 ps += sizeof (uintptr_t); 98 for ( ; ps != (uintptr_t) &__xd_z; ps += sizeof (uintptr_t)) 99 { 100 pfunc = (_PVFV *) ps; 101 if (*pfunc != NULL) 102 (*pfunc)(); 103 } 104 return TRUE; 105 } 106 107 const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback = (const PIMAGE_TLS_CALLBACK) __dyn_tls_init; 108 _CRTALLOC(".CRT$XLC") PIMAGE_TLS_CALLBACK __xl_c = (PIMAGE_TLS_CALLBACK) __dyn_tls_init; 109 110 int __cdecl __tlregdtor (_PVFV); 111 112 int __cdecl 113 __tlregdtor (_PVFV func) 114 { 115 if (!func) 116 return 0; 117 #if !defined (DISABLE_MS_TLS) 118 if (dtor_list == NULL) 119 { 120 dtor_list = &dtor_list_head; 121 dtor_list_head.count = 0; 122 } 123 else if (dtor_list->count == FUNCS_PER_NODE) 124 { 125 TlsDtorNode *pnode = (TlsDtorNode *) malloc (sizeof (TlsDtorNode)); 126 if (pnode == NULL) 127 return -1; 128 pnode->count = 0; 129 pnode->next = dtor_list; 130 dtor_list = pnode; 131 132 dtor_list->count = 0; 133 } 134 dtor_list->funcs[dtor_list->count++] = func; 135 #endif 136 return 0; 137 } 138 139 static BOOL WINAPI 140 __dyn_tls_dtor (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved) 141 { 142 #if !defined (DISABLE_MS_TLS) 143 TlsDtorNode *pnode, *pnext; 144 int i; 145 #endif 146 147 if (dwReason != DLL_THREAD_DETACH && dwReason != DLL_PROCESS_DETACH) 148 return TRUE; 149 /* As TLS variables are detroyed already by DLL_THREAD_DETACH 150 call, we have to avoid access on the possible DLL_PROCESS_DETACH 151 call the already destroyed TLS vars. 152 TODO: The used local thread based variables have to be handled 153 manually, so that we can control their lifetime here. */ 154 #if !defined (DISABLE_MS_TLS) 155 if (dwReason != DLL_PROCESS_DETACH) 156 { 157 for (pnode = dtor_list; pnode != NULL; pnode = pnext) 158 { 159 for (i = pnode->count - 1; i >= 0; --i) 160 { 161 if (pnode->funcs[i] != NULL) 162 (*pnode->funcs[i])(); 163 } 164 pnext = pnode->next; 165 if (pnext != NULL) 166 free ((void *) pnode); 167 } 168 } 169 #endif 170 __mingw_TLScallback (hDllHandle, dwReason, lpreserved); 171 return TRUE; 172 } 173 174 _CRTALLOC(".CRT$XLD") PIMAGE_TLS_CALLBACK __xl_d = (PIMAGE_TLS_CALLBACK) __dyn_tls_dtor; 175 176 177 int mingw_initltsdrot_force = 0; 178 int mingw_initltsdyn_force = 0; 179 int mingw_initltssuo_force = 0; 180