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 7 #undef CRTDLL 8 #ifndef _DLL 9 #define _DLL 10 #endif 11 12 #define SPECIAL_CRTEXE 13 14 #include <oscalls.h> 15 #include <internal.h> 16 #include <process.h> 17 #include <signal.h> 18 #include <math.h> 19 #include <stdlib.h> 20 #include <tchar.h> 21 #include <sect_attribs.h> 22 #include <locale.h> 23 #ifdef _MBCS 24 #include <mbstring.h> 25 #endif 26 27 #ifndef __winitenv 28 extern wchar_t *** __MINGW_IMP_SYMBOL(__winitenv); 29 #define __winitenv (* __MINGW_IMP_SYMBOL(__winitenv)) 30 #endif 31 32 #ifndef __initenv 33 extern char *** __MINGW_IMP_SYMBOL(__initenv); 34 #define __initenv (* __MINGW_IMP_SYMBOL(__initenv)) 35 #endif 36 37 /* Hack, for bug in ld. Will be removed soon. */ 38 #if defined(__GNUC__) 39 #define __ImageBase __MINGW_LSYMBOL(_image_base__) 40 #endif 41 42 /* This symbol is defined by ld. */ 43 extern IMAGE_DOS_HEADER __ImageBase; 44 45 extern void __cdecl _fpreset (void); 46 #define SPACECHAR _T(' ') 47 #define DQUOTECHAR _T('\"') 48 49 extern int * __MINGW_IMP_SYMBOL(_fmode); 50 extern int * __MINGW_IMP_SYMBOL(_commode); 51 52 #undef _fmode 53 extern int _fmode; 54 extern int * __MINGW_IMP_SYMBOL(_commode); 55 #define _commode (* __MINGW_IMP_SYMBOL(_commode)) 56 extern int _dowildcard; 57 58 extern _CRTIMP void __cdecl _initterm(_PVFV *, _PVFV *); 59 60 static int __cdecl check_managed_app (void); 61 62 extern _CRTALLOC(".CRT$XIA") _PIFV __xi_a[]; 63 extern _CRTALLOC(".CRT$XIZ") _PIFV __xi_z[]; 64 extern _CRTALLOC(".CRT$XCA") _PVFV __xc_a[]; 65 extern _CRTALLOC(".CRT$XCZ") _PVFV __xc_z[]; 66 67 /* TLS initialization hook. */ 68 extern const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback; 69 70 extern _PVFV *__onexitbegin; 71 extern _PVFV *__onexitend; 72 73 extern int mingw_app_type; 74 75 HINSTANCE __mingw_winmain_hInstance; 76 _TCHAR *__mingw_winmain_lpCmdLine; 77 DWORD __mingw_winmain_nShowCmd; 78 79 static int argc; 80 extern void __main(void); 81 #ifdef WPRFLAG 82 static wchar_t **argv; 83 static wchar_t **envp; 84 #else 85 static char **argv; 86 static char **envp; 87 #endif 88 89 static int argret; 90 static int mainret=0; 91 static int managedapp; 92 static int has_cctor = 0; 93 static _startupinfo startinfo; 94 extern LPTOP_LEVEL_EXCEPTION_FILTER __mingw_oldexcpt_handler; 95 96 extern void _pei386_runtime_relocator (void); 97 long CALLBACK _gnu_exception_handler (EXCEPTION_POINTERS * exception_data); 98 #ifdef WPRFLAG 99 static void duplicate_ppstrings (int ac, wchar_t ***av); 100 #else 101 static void duplicate_ppstrings (int ac, char ***av); 102 #endif 103 104 static int __cdecl pre_c_init (void); 105 static void __cdecl pre_cpp_init (void); 106 static void __cdecl __mingw_prepare_except_for_msvcr80_and_higher (void); 107 _CRTALLOC(".CRT$XIAA") _PIFV mingw_pcinit = pre_c_init; 108 _CRTALLOC(".CRT$XCAA") _PVFV mingw_pcppinit = pre_cpp_init; 109 110 extern int _MINGW_INSTALL_DEBUG_MATHERR; 111 112 static int __cdecl 113 pre_c_init (void) 114 { 115 managedapp = check_managed_app (); 116 if (mingw_app_type) 117 __set_app_type(_GUI_APP); 118 else 119 __set_app_type (_CONSOLE_APP); 120 __onexitbegin = __onexitend = (_PVFV *) _encode_pointer ((_PVFV *)(-1)); 121 122 * __MINGW_IMP_SYMBOL(_fmode) = _fmode; 123 * __MINGW_IMP_SYMBOL(_commode) = _commode; 124 125 #ifdef WPRFLAG 126 _wsetargv(); 127 #else 128 _setargv(); 129 #endif 130 if (_MINGW_INSTALL_DEBUG_MATHERR == 1) 131 { 132 __setusermatherr (_matherr); 133 } 134 #ifndef __clang__ /* FIXME: CORE-14042 */ 135 if (__globallocalestatus == -1) 136 { 137 } 138 #endif 139 return 0; 140 } 141 142 static void __cdecl 143 pre_cpp_init (void) 144 { 145 startinfo.newmode = _newmode; 146 147 #ifdef WPRFLAG 148 argret = __wgetmainargs(&argc,&argv,&envp,_dowildcard,&startinfo); 149 #else 150 argret = __getmainargs(&argc,&argv,&envp,_dowildcard,&startinfo); 151 #endif 152 } 153 154 static int __cdecl __tmainCRTStartup (void); 155 156 int __cdecl WinMainCRTStartup (void); 157 158 int __cdecl WinMainCRTStartup (void) 159 { 160 int ret = 255; 161 #ifdef __SEH__ 162 asm ("\t.l_startw:\n" 163 "\t.seh_handler __C_specific_handler, @except\n" 164 "\t.seh_handlerdata\n" 165 "\t.long 1\n" 166 "\t.rva .l_startw, .l_endw, _gnu_exception_handler ,.l_endw\n" 167 "\t.text" 168 ); 169 #endif 170 mingw_app_type = 1; 171 __security_init_cookie (); 172 ret = __tmainCRTStartup (); 173 #ifdef __SEH__ 174 asm ("\tnop\n" 175 "\t.l_endw: nop\n"); 176 #endif 177 return ret; 178 } 179 180 int __cdecl mainCRTStartup (void); 181 182 #ifdef _WIN64 183 int __mingw_init_ehandler (void); 184 #endif 185 186 int __cdecl mainCRTStartup (void) 187 { 188 int ret = 255; 189 #ifdef __SEH__ 190 asm ("\t.l_start:\n" 191 "\t.seh_handler __C_specific_handler, @except\n" 192 "\t.seh_handlerdata\n" 193 "\t.long 1\n" 194 "\t.rva .l_start, .l_end, _gnu_exception_handler ,.l_end\n" 195 "\t.text" 196 ); 197 #endif 198 mingw_app_type = 0; 199 __security_init_cookie (); 200 ret = __tmainCRTStartup (); 201 #ifdef __SEH__ 202 asm ("\tnop\n" 203 "\t.l_end: nop\n"); 204 #endif 205 return ret; 206 } 207 208 static 209 __declspec(noinline) 210 int __cdecl 211 __tmainCRTStartup (void) 212 { 213 _TCHAR *lpszCommandLine = NULL; 214 STARTUPINFO StartupInfo; 215 WINBOOL inDoubleQuote = FALSE; 216 memset (&StartupInfo, 0, sizeof (STARTUPINFO)); 217 218 #ifndef _WIN64 219 /* We need to make sure that this function is build with frame-pointer 220 and that we align the stack to 16 bytes for the sake of SSE ops in main 221 or in functions inlined into main. */ 222 lpszCommandLine = (_TCHAR *) alloca (32); 223 memset (lpszCommandLine, 0xcc, 32); 224 #ifdef __GNUC__ 225 asm __volatile__ ("andl $-16, %%esp" : : : "%esp"); 226 #endif 227 #endif 228 229 if (mingw_app_type) 230 GetStartupInfo (&StartupInfo); 231 { 232 void *lock_free = NULL; 233 void *fiberid = ((PNT_TIB)NtCurrentTeb())->StackBase; 234 int nested = FALSE; 235 while((lock_free = InterlockedCompareExchangePointer ((volatile PVOID *) &__native_startup_lock, 236 fiberid, 0)) != 0) 237 { 238 if (lock_free == fiberid) 239 { 240 nested = TRUE; 241 break; 242 } 243 Sleep(1000); 244 } 245 if (__native_startup_state == __initializing) 246 { 247 _amsg_exit (31); 248 } 249 else if (__native_startup_state == __uninitialized) 250 { 251 __native_startup_state = __initializing; 252 _initterm ((_PVFV *)(void *)__xi_a, (_PVFV *)(void *) __xi_z); 253 } 254 else 255 has_cctor = 1; 256 257 if (__native_startup_state == __initializing) 258 { 259 _initterm (__xc_a, __xc_z); 260 __native_startup_state = __initialized; 261 } 262 _ASSERTE(__native_startup_state == __initialized); 263 if (! nested) 264 (VOID)InterlockedExchangePointer ((volatile PVOID *) &__native_startup_lock, 0); 265 266 if (__dyn_tls_init_callback != NULL) 267 __dyn_tls_init_callback (NULL, DLL_THREAD_ATTACH, NULL); 268 269 _pei386_runtime_relocator (); 270 __mingw_oldexcpt_handler = SetUnhandledExceptionFilter (_gnu_exception_handler); 271 #ifdef _WIN64 272 __mingw_init_ehandler (); 273 #endif 274 __mingw_prepare_except_for_msvcr80_and_higher (); 275 276 _fpreset (); 277 278 if (mingw_app_type) 279 { 280 #ifdef WPRFLAG 281 lpszCommandLine = (_TCHAR *) _wcmdln; 282 #else 283 lpszCommandLine = (char *) _acmdln; 284 #endif 285 while (*lpszCommandLine > SPACECHAR || (*lpszCommandLine && inDoubleQuote)) 286 { 287 if (*lpszCommandLine == DQUOTECHAR) 288 inDoubleQuote = !inDoubleQuote; 289 #ifdef _MBCS 290 if (_ismbblead (*lpszCommandLine)) 291 { 292 if (lpszCommandLine) /* FIXME: Why this check? Should I check for *lpszCommandLine != 0 too? */ 293 lpszCommandLine++; 294 } 295 #endif 296 ++lpszCommandLine; 297 } 298 while (*lpszCommandLine && (*lpszCommandLine <= SPACECHAR)) 299 lpszCommandLine++; 300 301 __mingw_winmain_hInstance = (HINSTANCE) &__ImageBase; 302 __mingw_winmain_lpCmdLine = lpszCommandLine; 303 __mingw_winmain_nShowCmd = StartupInfo.dwFlags & STARTF_USESHOWWINDOW ? 304 StartupInfo.wShowWindow : SW_SHOWDEFAULT; 305 } 306 duplicate_ppstrings (argc, &argv); 307 __main (); 308 #ifdef WPRFLAG 309 __winitenv = envp; 310 /* C++ initialization. 311 gcc inserts this call automatically for a function called main, but not for wmain. */ 312 mainret = wmain (argc, argv, envp); 313 #else 314 __initenv = envp; 315 mainret = main (argc, argv, envp); 316 #endif 317 if (!managedapp) 318 exit (mainret); 319 320 if (has_cctor == 0) 321 _cexit (); 322 } 323 return mainret; 324 } 325 326 extern int mingw_initltsdrot_force; 327 extern int mingw_initltsdyn_force; 328 extern int mingw_initltssuo_force; 329 extern int mingw_initcharmax; 330 331 static int __cdecl 332 check_managed_app (void) 333 { 334 PIMAGE_DOS_HEADER pDOSHeader; 335 PIMAGE_NT_HEADERS pPEHeader; 336 PIMAGE_OPTIONAL_HEADER32 pNTHeader32; 337 PIMAGE_OPTIONAL_HEADER64 pNTHeader64; 338 339 /* Force to be linked. */ 340 mingw_initltsdrot_force=1; 341 mingw_initltsdyn_force=1; 342 mingw_initltssuo_force=1; 343 mingw_initcharmax=1; 344 345 pDOSHeader = (PIMAGE_DOS_HEADER) &__ImageBase; 346 if (pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE) 347 return 0; 348 349 pPEHeader = (PIMAGE_NT_HEADERS)((char *)pDOSHeader + pDOSHeader->e_lfanew); 350 if (pPEHeader->Signature != IMAGE_NT_SIGNATURE) 351 return 0; 352 353 pNTHeader32 = (PIMAGE_OPTIONAL_HEADER32) &pPEHeader->OptionalHeader; 354 switch (pNTHeader32->Magic) 355 { 356 case IMAGE_NT_OPTIONAL_HDR32_MAGIC: 357 if (pNTHeader32->NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR) 358 return 0; 359 return !! pNTHeader32->DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress; 360 case IMAGE_NT_OPTIONAL_HDR64_MAGIC: 361 pNTHeader64 = (PIMAGE_OPTIONAL_HEADER64)pNTHeader32; 362 if (pNTHeader64->NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR) 363 return 0; 364 return !! pNTHeader64->DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress; 365 } 366 return 0; 367 } 368 369 #ifdef WPRFLAG 370 static size_t wbytelen(const wchar_t *p) 371 { 372 size_t ret = 1; 373 while (*p!=0) { 374 ret++,++p; 375 } 376 return ret*2; 377 } 378 static void duplicate_ppstrings (int ac, wchar_t ***av) 379 { 380 wchar_t **avl; 381 int i; 382 wchar_t **n = (wchar_t **) malloc (sizeof (wchar_t *) * (ac + 1)); 383 384 avl=*av; 385 for (i=0; i < ac; i++) 386 { 387 size_t l = wbytelen (avl[i]); 388 n[i] = (wchar_t *) malloc (l); 389 memcpy (n[i], avl[i], l); 390 } 391 n[i] = NULL; 392 *av = n; 393 } 394 #else 395 static void duplicate_ppstrings (int ac, char ***av) 396 { 397 char **avl; 398 int i; 399 char **n = (char **) malloc (sizeof (char *) * (ac + 1)); 400 401 avl=*av; 402 for (i=0; i < ac; i++) 403 { 404 size_t l = strlen (avl[i]) + 1; 405 n[i] = (char *) malloc (l); 406 memcpy (n[i], avl[i], l); 407 } 408 n[i] = NULL; 409 *av = n; 410 } 411 #endif 412 413 #ifdef __MINGW_SHOW_INVALID_PARAMETER_EXCEPTION 414 #define __UNUSED_PARAM_1(x) x 415 #else 416 #define __UNUSED_PARAM_1 __UNUSED_PARAM 417 #endif 418 static void __cdecl 419 __mingw_invalidParameterHandler (const wchar_t * __UNUSED_PARAM_1(expression), 420 const wchar_t * __UNUSED_PARAM_1(function), 421 const wchar_t * __UNUSED_PARAM_1(file), 422 unsigned int __UNUSED_PARAM_1(line), 423 uintptr_t __UNUSED_PARAM(pReserved)) 424 { 425 #ifdef __MINGW_SHOW_INVALID_PARAMETER_EXCEPTION 426 wprintf(L"Invalid parameter detected in function %s. File: %s Line: %u\n", function, file, line); 427 wprintf(L"Expression: %s\n", expression); 428 #endif 429 } 430 431 HANDLE __mingw_get_msvcrt_handle(void); 432 433 static void __cdecl 434 __mingw_prepare_except_for_msvcr80_and_higher (void) 435 { 436 _invalid_parameter_handler (*fIPH)(_invalid_parameter_handler) = NULL; 437 438 fIPH = (void*)GetProcAddress (__mingw_get_msvcrt_handle(), "_set_invalid_parameter_handler"); 439 if (fIPH) 440 (*fIPH)(__mingw_invalidParameterHandler); 441 } 442