| ... | ... | @@ -0,0 +1,436 @@ |
| 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 | |
| 7 | #undef CRTDLL |
| 8 | #ifndef _DLL |
| 9 | #define _DLL |
| 10 | #endif |
| 11 | |
| 12 | #ifdef HAVE_CONFIG_H |
| 13 | #include "config.h" |
| 14 | #endif |
| 15 | |
| 16 | #define SPECIAL_CRTEXE |
| 17 | |
| 18 | #include <oscalls.h> |
| 19 | #include <internal.h> |
| 20 | #include <process.h> |
| 21 | #include <signal.h> |
| 22 | #include <math.h> |
| 23 | #include <stdlib.h> |
| 24 | #include <tchar.h> |
| 25 | #include <sect_attribs.h> |
| 26 | #include <locale.h> |
| 27 | |
| 28 | #if defined(__SEH__) && (!defined(__clang__) || __clang_major__ >= 7) |
| 29 | #define SEH_INLINE_ASM |
| 30 | #endif |
| 31 | |
| 32 | #ifndef __winitenv |
| 33 | extern wchar_t *** __MINGW_IMP_SYMBOL(__winitenv); |
| 34 | #define __winitenv (* __MINGW_IMP_SYMBOL(__winitenv)) |
| 35 | #endif |
| 36 | |
| 37 | #if !defined(__initenv) && !defined(__arm__) && !defined(__aarch64__) |
| 38 | extern char *** __MINGW_IMP_SYMBOL(__initenv); |
| 39 | #define __initenv (* __MINGW_IMP_SYMBOL(__initenv)) |
| 40 | #endif |
| 41 | |
| 42 | /* Hack, for bug in ld. Will be removed soon. */ |
| 43 | #if defined(__GNUC__) |
| 44 | #define __ImageBase __MINGW_LSYMBOL(_image_base__) |
| 45 | #endif |
| 46 | /* This symbol is defined by ld. */ |
| 47 | extern IMAGE_DOS_HEADER __ImageBase; |
| 48 | |
| 49 | extern void _fpreset (void); |
| 50 | #define SPACECHAR _T(' ') |
| 51 | #define DQUOTECHAR _T('\"') |
| 52 | |
| 53 | int *__cdecl __p__commode(void); |
| 54 | |
| 55 | #undef _fmode |
| 56 | extern int _fmode; |
| 57 | extern int _commode; |
| 58 | extern int _dowildcard; |
| 59 | |
| 60 | extern _CRTIMP void __cdecl _initterm(_PVFV *, _PVFV *); |
| 61 | |
| 62 | static int __cdecl check_managed_app (void); |
| 63 | |
| 64 | extern _CRTALLOC(".CRT$XIA") _PIFV __xi_a[]; |
| 65 | extern _CRTALLOC(".CRT$XIZ") _PIFV __xi_z[]; |
| 66 | extern _CRTALLOC(".CRT$XCA") _PVFV __xc_a[]; |
| 67 | extern _CRTALLOC(".CRT$XCZ") _PVFV __xc_z[]; |
| 68 | |
| 69 | #ifndef HAVE_CTOR_LIST |
| 70 | __attribute__ (( __section__ (".ctors"), __used__ , aligned(sizeof(void *)))) const void * __CTOR_LIST__ = (void *) -1; |
| 71 | __attribute__ (( __section__ (".dtors"), __used__ , aligned(sizeof(void *)))) const void * __DTOR_LIST__ = (void *) -1; |
| 72 | __attribute__ (( __section__ (".ctors.99999"), __used__ , aligned(sizeof(void *)))) const void * __CTOR_END__ = (void *) 0; |
| 73 | __attribute__ (( __section__ (".dtors.99999"), __used__ , aligned(sizeof(void *)))) const void * __DTOR_END__ = (void *) 0; |
| 74 | #endif |
| 75 | |
| 76 | /* TLS initialization hook. */ |
| 77 | extern const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback; |
| 78 | |
| 79 | extern int mingw_app_type; |
| 80 | |
| 81 | HINSTANCE __mingw_winmain_hInstance; |
| 82 | _TCHAR *__mingw_winmain_lpCmdLine; |
| 83 | DWORD __mingw_winmain_nShowCmd = SW_SHOWDEFAULT; |
| 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 | _CRTALLOC(".CRT$XIAA") _PIFV mingw_pcinit = pre_c_init; |
| 113 | _CRTALLOC(".CRT$XCAA") _PVFV mingw_pcppinit = pre_cpp_init; |
| 114 | |
| 115 | extern int _MINGW_INSTALL_DEBUG_MATHERR; |
| 116 | |
| 117 | #ifdef __MINGW_SHOW_INVALID_PARAMETER_EXCEPTION |
| 118 | #define __UNUSED_PARAM_1(x) x |
| 119 | #else |
| 120 | #define __UNUSED_PARAM_1	__UNUSED_PARAM |
| 121 | #endif |
| 122 | static void |
| 123 | __mingw_invalidParameterHandler (const wchar_t * __UNUSED_PARAM_1(expression), |
| 124 | 				 const wchar_t * __UNUSED_PARAM_1(function), |
| 125 | 				 const wchar_t * __UNUSED_PARAM_1(file), |
| 126 | 				 unsigned int __UNUSED_PARAM_1(line), |
| 127 | 				 uintptr_t __UNUSED_PARAM(pReserved)) |
| 128 | { |
| 129 | #ifdef __MINGW_SHOW_INVALID_PARAMETER_EXCEPTION |
| 130 | wprintf(L"Invalid parameter detected in function %s. File: %s Line: %d\n", function, file, line); |
| 131 | wprintf(L"Expression: %s\n", expression); |
| 132 | #endif |
| 133 | } |
| 134 | |
| 135 | static int __cdecl |
| 136 | pre_c_init (void) |
| 137 | { |
| 138 | managedapp = check_managed_app (); |
| 139 | if (mingw_app_type) |
| 140 | __set_app_type(_GUI_APP); |
| 141 | else |
| 142 | __set_app_type (_CONSOLE_APP); |
| 143 | |
| 144 | * __p__fmode() = _fmode; |
| 145 | * __p__commode() = _commode; |
| 146 | |
| 147 | #ifdef WPRFLAG |
| 148 | _wsetargv(); |
| 149 | #else |
| 150 | _setargv(); |
| 151 | #endif |
| 152 | if (_MINGW_INSTALL_DEBUG_MATHERR == 1) |
| 153 | { |
| 154 | __setusermatherr (_matherr); |
| 155 | } |
| 156 | |
| 157 | if (__globallocalestatus == -1) |
| 158 | { |
| 159 | } |
| 160 | return 0; |
| 161 | } |
| 162 | |
| 163 | static void __cdecl |
| 164 | pre_cpp_init (void) |
| 165 | { |
| 166 | startinfo.newmode = _newmode; |
| 167 | |
| 168 | #ifdef WPRFLAG |
| 169 | argret = __wgetmainargs(&argc,&argv,&envp,_dowildcard,&startinfo); |
| 170 | #else |
| 171 | argret = __getmainargs(&argc,&argv,&envp,_dowildcard,&startinfo); |
| 172 | #endif |
| 173 | } |
| 174 | |
| 175 | static int __tmainCRTStartup (void); |
| 176 | |
| 177 | int WinMainCRTStartup (void); |
| 178 | |
| 179 | int WinMainCRTStartup (void) |
| 180 | { |
| 181 | int ret = 255; |
| 182 | #ifdef SEH_INLINE_ASM |
| 183 | asm ("\t.l_startw:\n"); |
| 184 | #endif |
| 185 | mingw_app_type = 1; |
| 186 | ret = __tmainCRTStartup (); |
| 187 | #ifdef SEH_INLINE_ASM |
| 188 | asm ("\tnop\n" |
| 189 | "\t.l_endw: nop\n" |
| 190 | "\t.seh_handler __C_specific_handler, @except\n" |
| 191 | "\t.seh_handlerdata\n" |
| 192 | "\t.long 1\n" |
| 193 | "\t.rva .l_startw, .l_endw, _gnu_exception_handler ,.l_endw\n" |
| 194 | "\t.text"); |
| 195 | #endif |
| 196 | return ret; |
| 197 | } |
| 198 | |
| 199 | int mainCRTStartup (void); |
| 200 | |
| 201 | #if defined(__x86_64__) && !defined(__SEH__) |
| 202 | int __mingw_init_ehandler (void); |
| 203 | #endif |
| 204 | |
| 205 | int mainCRTStartup (void) |
| 206 | { |
| 207 | int ret = 255; |
| 208 | #ifdef SEH_INLINE_ASM |
| 209 | asm ("\t.l_start:\n"); |
| 210 | #endif |
| 211 | mingw_app_type = 0; |
| 212 | ret = __tmainCRTStartup (); |
| 213 | #ifdef SEH_INLINE_ASM |
| 214 | asm ("\tnop\n" |
| 215 | "\t.l_end: nop\n" |
| 216 | "\t.seh_handler __C_specific_handler, @except\n" |
| 217 | "\t.seh_handlerdata\n" |
| 218 | "\t.long 1\n" |
| 219 | "\t.rva .l_start, .l_end, _gnu_exception_handler ,.l_end\n" |
| 220 | "\t.text"); |
| 221 | #endif |
| 222 | return ret; |
| 223 | } |
| 224 | |
| 225 | static |
| 226 | #if defined(__i386__) || defined(_X86_) |
| 227 | /* We need to make sure that we align the stack to 16 bytes for the sake of SSE |
| 228 | opts in main or in functions called main. */ |
| 229 | __attribute__((force_align_arg_pointer)) |
| 230 | #endif |
| 231 | __declspec(noinline) int |
| 232 | __tmainCRTStartup (void) |
| 233 | { |
| 234 | _TCHAR *lpszCommandLine = NULL; |
| 235 | STARTUPINFO StartupInfo; |
| 236 | WINBOOL inDoubleQuote = FALSE; |
| 237 | memset (&StartupInfo, 0, sizeof (STARTUPINFO)); |
| 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 | #if defined(__x86_64__) && !defined(__SEH__) |
| 282 | __mingw_init_ehandler (); |
| 283 | #endif |
| 284 | _set_invalid_parameter_handler (__mingw_invalidParameterHandler); |
| 285 | |
| 286 | _fpreset (); |
| 287 | |
| 288 | __mingw_winmain_hInstance = (HINSTANCE) &__ImageBase; |
| 289 | |
| 290 | #ifdef WPRFLAG |
| 291 | lpszCommandLine = (_TCHAR *) _wcmdln; |
| 292 | #else |
| 293 | lpszCommandLine = (char *) _acmdln; |
| 294 | #endif |
| 295 | |
| 296 | if (lpszCommandLine) |
| 297 | { |
| 298 | 	while (*lpszCommandLine > SPACECHAR || (*lpszCommandLine && inDoubleQuote)) |
| 299 | 	 { |
| 300 | 	 if (*lpszCommandLine == DQUOTECHAR) |
| 301 | 	 inDoubleQuote = !inDoubleQuote; |
| 302 | #ifdef _MBCS |
| 303 | 	 if (_ismbblead (*lpszCommandLine)) |
| 304 | 	 { |
| 305 | 		if (lpszCommandLine[1]) |
| 306 | 		 ++lpszCommandLine; |
| 307 | 	 } |
| 308 | #endif |
| 309 | 	 ++lpszCommandLine; |
| 310 | 	 } |
| 311 | 	while (*lpszCommandLine && (*lpszCommandLine <= SPACECHAR)) |
| 312 | 	 lpszCommandLine++; |
| 313 | |
| 314 | 	__mingw_winmain_lpCmdLine = lpszCommandLine; |
| 315 | } |
| 316 | |
| 317 | if (mingw_app_type) |
| 318 | { |
| 319 | 	__mingw_winmain_nShowCmd = StartupInfo.dwFlags & STARTF_USESHOWWINDOW ? |
| 320 | 				 StartupInfo.wShowWindow : SW_SHOWDEFAULT; |
| 321 | } |
| 322 | duplicate_ppstrings (argc, &argv); |
| 323 | __main (); |
| 324 | #ifdef WPRFLAG |
| 325 | __winitenv = envp; |
| 326 | /* C++ initialization. |
| 327 | gcc inserts this call automatically for a function called main, but not for wmain. */ |
| 328 | mainret = wmain (argc, argv, envp); |
| 329 | #else |
| 330 | #if !defined(__arm__) && !defined(__aarch64__) |
| 331 | __initenv = envp; |
| 332 | #endif |
| 333 | mainret = main (argc, argv, envp); |
| 334 | #endif |
| 335 | if (!managedapp) |
| 336 | exit (mainret); |
| 337 | |
| 338 | if (has_cctor == 0) |
| 339 | _cexit (); |
| 340 | } |
| 341 | return mainret; |
| 342 | } |
| 343 | |
| 344 | extern int mingw_initltsdrot_force; |
| 345 | extern int mingw_initltsdyn_force; |
| 346 | extern int mingw_initltssuo_force; |
| 347 | extern int mingw_initcharmax; |
| 348 | |
| 349 | static int __cdecl |
| 350 | check_managed_app (void) |
| 351 | { |
| 352 | PIMAGE_DOS_HEADER pDOSHeader; |
| 353 | PIMAGE_NT_HEADERS pPEHeader; |
| 354 | PIMAGE_OPTIONAL_HEADER32 pNTHeader32; |
| 355 | PIMAGE_OPTIONAL_HEADER64 pNTHeader64; |
| 356 | |
| 357 | /* Force to be linked. */ |
| 358 | mingw_initltsdrot_force=1; |
| 359 | mingw_initltsdyn_force=1; |
| 360 | mingw_initltssuo_force=1; |
| 361 | mingw_initcharmax=1; |
| 362 | |
| 363 | pDOSHeader = (PIMAGE_DOS_HEADER) &__ImageBase; |
| 364 | if (pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE) |
| 365 | return 0; |
| 366 | |
| 367 | pPEHeader = (PIMAGE_NT_HEADERS)((char *)pDOSHeader + pDOSHeader->e_lfanew); |
| 368 | if (pPEHeader->Signature != IMAGE_NT_SIGNATURE) |
| 369 | return 0; |
| 370 | |
| 371 | pNTHeader32 = (PIMAGE_OPTIONAL_HEADER32) &pPEHeader->OptionalHeader; |
| 372 | switch (pNTHeader32->Magic) |
| 373 | { |
| 374 | case IMAGE_NT_OPTIONAL_HDR32_MAGIC: |
| 375 | if (pNTHeader32->NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR) |
| 376 | 	return 0; |
| 377 | return !! pNTHeader32->DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress; |
| 378 | case IMAGE_NT_OPTIONAL_HDR64_MAGIC: |
| 379 | pNTHeader64 = (PIMAGE_OPTIONAL_HEADER64)pNTHeader32; |
| 380 | if (pNTHeader64->NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR) |
| 381 | 	return 0; |
| 382 | return !! pNTHeader64->DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress; |
| 383 | } |
| 384 | return 0; |
| 385 | } |
| 386 | |
| 387 | #ifdef WPRFLAG |
| 388 | static size_t wbytelen(const wchar_t *p) |
| 389 | { |
| 390 | 	size_t ret = 1; |
| 391 | 	while (*p!=0) { |
| 392 | 		ret++,++p; |
| 393 | 	} |
| 394 | 	return ret*2; |
| 395 | } |
| 396 | static void duplicate_ppstrings (int ac, wchar_t ***av) |
| 397 | { |
| 398 | 	wchar_t **avl; |
| 399 | 	int i; |
| 400 | 	wchar_t **n = (wchar_t **) malloc (sizeof (wchar_t *) * (ac + 1)); |
| 401 | |
| 402 | 	avl=*av; |
| 403 | 	for (i=0; i < ac; i++) |
| 404 | 	 { |
| 405 | 		size_t l = wbytelen (avl[i]); |
| 406 | 		n[i] = (wchar_t *) malloc (l); |
| 407 | 		memcpy (n[i], avl[i], l); |
| 408 | 	 } |
| 409 | 	n[i] = NULL; |
| 410 | 	*av = n; |
| 411 | } |
| 412 | #else |
| 413 | static void duplicate_ppstrings (int ac, char ***av) |
| 414 | { |
| 415 | 	char **avl; |
| 416 | 	int i; |
| 417 | 	char **n = (char **) malloc (sizeof (char *) * (ac + 1)); |
| 418 | 	 |
| 419 | 	avl=*av; |
| 420 | 	for (i=0; i < ac; i++) |
| 421 | 	 { |
| 422 | 		size_t l = strlen (avl[i]) + 1; |
| 423 | 		n[i] = (char *) malloc (l); |
| 424 | 		memcpy (n[i], avl[i], l); |
| 425 | 	 } |
| 426 | 	n[i] = NULL; |
| 427 | 	*av = n; |
| 428 | } |
| 429 | #endif |
| 430 | |
| 431 | int __cdecl atexit (_PVFV func) |
| 432 | { |
| 433 | return _onexit((_onexit_t)func) ? 0 : -1; |
| 434 | } |
| 435 | |
| 436 | char __mingw_module_is_dll = 0; |