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 within this package.
12 #define SPECIAL_CRTEXE
21 #include <sect_attribs.h>
26 extern wchar_t ***_imp____winitenv
;
27 #define __winitenv (*_imp____winitenv)
31 extern char ***_imp____initenv
;
32 #define __initenv (*_imp____initenv)
35 /* Hack, for bug in ld. Will be removed soon. */
36 #define __ImageBase _image_base__
37 /* This symbol is defined by ld. */
38 extern IMAGE_DOS_HEADER __ImageBase
;
40 extern void _fpreset (void);
41 #define SPACECHAR _T(' ')
42 #define DQUOTECHAR _T('\"')
44 __declspec(dllimport
) void __setusermatherr(int (__cdecl
*)(struct _exception
*));
46 extern int *_imp___fmode
;
47 extern int *_imp___commode
;
51 extern int *_imp___commode
;
52 #define _commode (*_imp___commode)
53 extern int _dowildcard
;
55 int _MINGW_INSTALL_DEBUG_MATHERR
__attribute__((weak
)) = 0;
56 extern int __defaultmatherr
;
57 extern _CRTIMP
void __cdecl
_initterm(_PVFV
*, _PVFV
*);
59 static int __cdecl
check_managed_app (void);
61 extern _CRTALLOC(".CRT$XIA") _PIFV __xi_a
[];
62 extern _CRTALLOC(".CRT$XIZ") _PIFV __xi_z
[];
63 extern _CRTALLOC(".CRT$XCA") _PVFV __xc_a
[];
64 extern _CRTALLOC(".CRT$XCZ") _PVFV __xc_z
[];
66 extern const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback
;
68 extern _PVFV
*__onexitbegin
;
69 extern _PVFV
*__onexitend
;
71 extern int mingw_app_type
;
75 extern void __main(void);
76 static wchar_t **argv
;
77 static wchar_t **envp
;
85 static int managedapp
;
86 static int has_cctor
= 0;
87 static _startupinfo startinfo
;
89 extern void _pei386_runtime_relocator (void);
90 static long CALLBACK
_gnu_exception_handler (EXCEPTION_POINTERS
* exception_data
);
91 //static LONG __mingw_vex(EXCEPTION_POINTERS * exception_data);
93 static void duplicate_ppstrings (int ac
, wchar_t ***av
);
95 static void duplicate_ppstrings (int ac
, char ***av
);
98 static int __cdecl
pre_c_init (void);
99 static void __cdecl
pre_cpp_init (void);
101 _CRTALLOC(".CRT$XIAA") _PIFV mingw_pcinit
= pre_c_init
;
102 _CRTALLOC(".CRT$XCAA") _PVFV mingw_pcppinit
= pre_cpp_init
;
107 managedapp
= check_managed_app ();
109 __set_app_type(_GUI_APP
);
111 __set_app_type (_CONSOLE_APP
);
112 __onexitbegin
= __onexitend
= (_PVFV
*) _encode_pointer ((_PVFV
*)(-1));
114 *_imp___fmode
= _fmode
;
115 *_imp___commode
= _commode
;
122 if (_MINGW_INSTALL_DEBUG_MATHERR
)
124 if (! __defaultmatherr
)
126 __setusermatherr (_matherr
);
127 __defaultmatherr
= 1;
131 if (__globallocalestatus
== -1)
140 startinfo
.newmode
= _newmode
;
143 argret
= __wgetmainargs(&argc
,&argv
,&envp
,_dowildcard
,&startinfo
);
145 argret
= __getmainargs(&argc
,&argv
,&envp
,_dowildcard
,&startinfo
);
149 static int __tmainCRTStartup (void);
151 int WinMainCRTStartup (void)
154 __security_init_cookie ();
155 return __tmainCRTStartup ();
158 int mainCRTStartup (void)
161 __security_init_cookie ();
162 return __tmainCRTStartup ();
166 __declspec(noinline
) int
167 __tmainCRTStartup (void)
169 _TCHAR
*lpszCommandLine
= NULL
;
170 STARTUPINFO StartupInfo
;
171 BOOL inDoubleQuote
= FALSE
;
172 memset (&StartupInfo
, 0, sizeof (STARTUPINFO
));
175 GetStartupInfo (&StartupInfo
);
177 void *lock_free
= NULL
;
178 void *fiberid
= ((PNT_TIB
)NtCurrentTeb())->StackBase
;
180 while((lock_free
= InterlockedCompareExchangePointer ((volatile PVOID
*) &__native_startup_lock
,
183 if (lock_free
== fiberid
)
190 if (__native_startup_state
== __initializing
)
194 else if (__native_startup_state
== __uninitialized
)
196 __native_startup_state
= __initializing
;
197 _initterm ((_PVFV
*)(void *)__xi_a
, (_PVFV
*)(void *) __xi_z
);
202 if (__native_startup_state
== __initializing
)
204 _initterm (__xc_a
, __xc_z
);
205 __native_startup_state
= __initialized
;
207 _ASSERTE(__native_startup_state
== __initialized
);
209 (VOID
)InterlockedExchangePointer ((volatile PVOID
*) &__native_startup_lock
, 0);
211 if (__dyn_tls_init_callback
!= NULL
&& _IsNonwritableInCurrentImage ((PBYTE
) &__dyn_tls_init_callback
))
212 __dyn_tls_init_callback (NULL
, DLL_THREAD_ATTACH
, NULL
);
214 _pei386_runtime_relocator ();
216 #if defined(__i386__) || defined(_M_IX86)
217 __writefsdword(0, 0xffffffff);
219 //AddVectoredExceptionHandler (0, (PVECTORED_EXCEPTION_HANDLER)__mingw_vex);
220 SetUnhandledExceptionFilter (_gnu_exception_handler
);
227 lpszCommandLine
= (_TCHAR
*) _wcmdln
;
229 lpszCommandLine
= (char *) _acmdln
;
231 while (*lpszCommandLine
> SPACECHAR
|| (*lpszCommandLine
&&inDoubleQuote
))
233 if (*lpszCommandLine
== DQUOTECHAR
)
234 inDoubleQuote
= !inDoubleQuote
;
236 if (_ismbblead (*lpszCommandLine
))
244 while (*lpszCommandLine
&& (*lpszCommandLine
<= SPACECHAR
))
248 /* C++ initialization.
249 gcc inserts this call automatically for a function called main, but not for wmain. */
252 (int) (StartupInfo
.dwFlags
& STARTF_USESHOWWINDOW
? StartupInfo
.wShowWindow
: SW_SHOWDEFAULT
),
253 (wchar_t **) lpszCommandLine
, (wchar_t **) (HINSTANCE
) &__ImageBase
);
256 (int) (StartupInfo
.dwFlags
& STARTF_USESHOWWINDOW
? StartupInfo
.wShowWindow
: SW_SHOWDEFAULT
),
257 (char **) lpszCommandLine
, (char **) (HINSTANCE
) &__ImageBase
);
262 duplicate_ppstrings (argc
, &argv
);
265 /* C++ initialization.
266 gcc inserts this call automatically for a function called main, but not for wmain. */
268 mainret
= wmain (argc
, argv
, envp
);
271 mainret
= main (argc
, argv
, envp
);
283 extern int mingw_initltsdrot_force
;
284 extern int mingw_initltsdyn_force
;
285 extern int mingw_initltssuo_force
;
286 extern int mingw_initcharmax
;
289 check_managed_app (void)
291 PIMAGE_DOS_HEADER pDOSHeader
;
292 PIMAGE_NT_HEADERS pPEHeader
;
293 PIMAGE_OPTIONAL_HEADER32 pNTHeader32
;
294 PIMAGE_OPTIONAL_HEADER64 pNTHeader64
;
296 /* Force to be linked. */
297 mingw_initltsdrot_force
=1;
298 mingw_initltsdyn_force
=1;
299 mingw_initltssuo_force
=1;
302 pDOSHeader
= (PIMAGE_DOS_HEADER
) &__ImageBase
;
303 if (pDOSHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
)
306 pPEHeader
= (PIMAGE_NT_HEADERS
)((char *)pDOSHeader
+ pDOSHeader
->e_lfanew
);
307 if (pPEHeader
->Signature
!= IMAGE_NT_SIGNATURE
)
310 pNTHeader32
= (PIMAGE_OPTIONAL_HEADER32
) &pPEHeader
->OptionalHeader
;
311 switch (pNTHeader32
->Magic
)
313 case IMAGE_NT_OPTIONAL_HDR32_MAGIC
:
314 if (pNTHeader32
->NumberOfRvaAndSizes
<= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
)
316 return !! pNTHeader32
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
;
317 case IMAGE_NT_OPTIONAL_HDR64_MAGIC
:
318 pNTHeader64
= (PIMAGE_OPTIONAL_HEADER64
)pNTHeader32
;
319 if (pNTHeader64
->NumberOfRvaAndSizes
<= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
)
321 return !! pNTHeader64
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
;
327 _gnu_exception_handler (EXCEPTION_POINTERS
* exception_data
)
329 void (*old_handler
) (int);
330 long action
= EXCEPTION_CONTINUE_SEARCH
;
333 switch (exception_data
->ExceptionRecord
->ExceptionCode
)
335 case EXCEPTION_ACCESS_VIOLATION
:
336 /* test if the user has set SIGSEGV */
337 old_handler
= signal (SIGSEGV
, SIG_DFL
);
338 if (old_handler
== SIG_IGN
)
340 /* this is undefined if the signal was raised by anything other
342 signal (SIGSEGV
, SIG_IGN
);
343 action
= EXCEPTION_CONTINUE_EXECUTION
;
345 else if (old_handler
!= SIG_DFL
)
347 /* This means 'old' is a user defined function. Call it */
348 (*old_handler
) (SIGSEGV
);
349 action
= EXCEPTION_CONTINUE_EXECUTION
;
353 case EXCEPTION_ILLEGAL_INSTRUCTION
:
354 case EXCEPTION_PRIV_INSTRUCTION
:
355 /* test if the user has set SIGILL */
356 old_handler
= signal (SIGILL
, SIG_DFL
);
357 if (old_handler
== SIG_IGN
)
359 /* this is undefined if the signal was raised by anything other
361 signal (SIGILL
, SIG_IGN
);
362 action
= EXCEPTION_CONTINUE_EXECUTION
;
364 else if (old_handler
!= SIG_DFL
)
366 /* This means 'old' is a user defined function. Call it */
367 (*old_handler
) (SIGILL
);
368 action
= EXCEPTION_CONTINUE_EXECUTION
;
372 case EXCEPTION_FLT_INVALID_OPERATION
:
373 case EXCEPTION_FLT_DIVIDE_BY_ZERO
:
374 case EXCEPTION_FLT_DENORMAL_OPERAND
:
375 case EXCEPTION_FLT_OVERFLOW
:
376 case EXCEPTION_FLT_UNDERFLOW
:
377 case EXCEPTION_FLT_INEXACT_RESULT
:
381 case EXCEPTION_INT_DIVIDE_BY_ZERO
:
382 /* test if the user has set SIGFPE */
383 old_handler
= signal (SIGFPE
, SIG_DFL
);
384 if (old_handler
== SIG_IGN
)
386 signal (SIGFPE
, SIG_IGN
);
389 action
= EXCEPTION_CONTINUE_EXECUTION
;
391 else if (old_handler
!= SIG_DFL
)
393 /* This means 'old' is a user defined function. Call it */
394 (*old_handler
) (SIGFPE
);
395 action
= EXCEPTION_CONTINUE_EXECUTION
;
406 static LONG
__mingw_vex(EXCEPTION_POINTERS
* exception_data
)
408 /* TODO this is not chainablem, therefore need rewrite. Disabled the ill code. */
411 __asm__
__volatile__ (
412 "movq %gs:0,%rax" "\n\t"
419 __asm__
__volatile__ (
420 "movl %fs:0,%eax" "\n\t"
428 return _gnu_exception_handler(exception_data
);
434 static size_t wbytelen(const wchar_t *p
)
442 static void duplicate_ppstrings (int ac
, wchar_t ***av
)
446 wchar_t **n
= (wchar_t **) malloc (sizeof (wchar_t *) * (ac
+ 1));
449 for (i
=0; i
< ac
; i
++)
451 int l
= wbytelen (avl
[i
]);
452 n
[i
] = (wchar_t *) malloc (l
);
453 memcpy (n
[i
], avl
[i
], l
);
459 static void duplicate_ppstrings (int ac
, char ***av
)
463 char **n
= (char **) malloc (sizeof (char *) * (ac
+ 1));
466 for (i
=0; i
< ac
; i
++)
468 int l
= strlen (avl
[i
]) + 1;
469 n
[i
] = (char *) malloc (l
);
470 memcpy (n
[i
], avl
[i
], l
);