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