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>
25 extern wchar_t ***_imp____winitenv
;
26 #define __winitenv (*_imp____winitenv)
30 extern char ***_imp____initenv
;
31 #define __initenv (*_imp____initenv)
34 /* Hack, for bug in ld. Will be removed soon. */
35 #define __ImageBase _image_base__
36 /* This symbol is defined by ld. */
37 extern IMAGE_DOS_HEADER __ImageBase
;
39 extern void _fpreset (void);
40 #define SPACECHAR _T(' ')
41 #define DQUOTECHAR _T('\"')
43 __declspec(dllimport
) void __setusermatherr(int (__cdecl
*)(struct _exception
*));
45 extern int *_imp___fmode
;
46 extern int *_imp___commode
;
50 extern int *_imp___commode
;
51 #define _commode (*_imp___commode)
52 extern int _dowildcard
;
54 int _MINGW_INSTALL_DEBUG_MATHERR
__attribute__((weak
)) = 0;
55 extern int __defaultmatherr
;
56 extern _CRTIMP
void __cdecl
_initterm(_PVFV
*, _PVFV
*);
58 static int __cdecl
check_managed_app (void);
60 extern _CRTALLOC(".CRT$XIA") _PIFV __xi_a
[];
61 extern _CRTALLOC(".CRT$XIZ") _PIFV __xi_z
[];
62 extern _CRTALLOC(".CRT$XCA") _PVFV __xc_a
[];
63 extern _CRTALLOC(".CRT$XCZ") _PVFV __xc_z
[];
65 extern const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback
;
67 extern _PVFV
*__onexitbegin
;
68 extern _PVFV
*__onexitend
;
70 extern int mingw_app_type
;
74 extern void __main(void);
75 static wchar_t **argv
;
76 static wchar_t **envp
;
84 static int managedapp
;
85 static int has_cctor
= 0;
86 static _startupinfo startinfo
;
88 extern void _pei386_runtime_relocator (void);
89 static CALLBACK
long _gnu_exception_handler (EXCEPTION_POINTERS
* exception_data
);
90 static LONG
__mingw_vex(EXCEPTION_POINTERS
* exception_data
);
92 static void duplicate_ppstrings (int ac
, wchar_t ***av
);
94 static void duplicate_ppstrings (int ac
, char ***av
);
97 static int __cdecl
pre_c_init (void);
98 static void __cdecl
pre_cpp_init (void);
100 _CRTALLOC(".CRT$XIAA") _PIFV mingw_pcinit
= pre_c_init
;
101 _CRTALLOC(".CRT$XCAA") _PVFV mingw_pcppinit
= pre_cpp_init
;
106 managedapp
= check_managed_app ();
108 __set_app_type(_GUI_APP
);
110 __set_app_type (_CONSOLE_APP
);
111 __onexitbegin
= __onexitend
= (_PVFV
*) _encode_pointer ((_PVFV
*)(-1));
113 *_imp___fmode
= _fmode
;
114 *_imp___commode
= _commode
;
121 if (_MINGW_INSTALL_DEBUG_MATHERR
)
123 if (! __defaultmatherr
)
125 __setusermatherr (_matherr
);
126 __defaultmatherr
= 1;
130 if (__globallocalestatus
== -1)
139 startinfo
.newmode
= _newmode
;
142 argret
= __wgetmainargs(&argc
,&argv
,&envp
,_dowildcard
,&startinfo
);
144 argret
= __getmainargs(&argc
,&argv
,&envp
,_dowildcard
,&startinfo
);
148 static int __tmainCRTStartup (void);
150 int WinMainCRTStartup (void)
153 __security_init_cookie ();
154 return __tmainCRTStartup ();
157 int mainCRTStartup (void)
160 __security_init_cookie ();
161 return __tmainCRTStartup ();
165 __declspec(noinline
) int
166 __tmainCRTStartup (void)
168 _TCHAR
*lpszCommandLine
= NULL
;
169 STARTUPINFO StartupInfo
;
170 BOOL inDoubleQuote
= FALSE
;
171 memset (&StartupInfo
, 0, sizeof (STARTUPINFO
));
174 GetStartupInfo (&StartupInfo
);
176 void *lock_free
= NULL
;
177 void *fiberid
= ((PNT_TIB
)NtCurrentTeb())->StackBase
;
179 while((lock_free
= InterlockedCompareExchangePointer ((volatile PVOID
*) &__native_startup_lock
,
182 if (lock_free
== fiberid
)
189 if (__native_startup_state
== __initializing
)
193 else if (__native_startup_state
== __uninitialized
)
195 __native_startup_state
= __initializing
;
196 _initterm ((_PVFV
*)(void *)__xi_a
, (_PVFV
*)(void *) __xi_z
);
201 if (__native_startup_state
== __initializing
)
203 _initterm (__xc_a
, __xc_z
);
204 __native_startup_state
= __initialized
;
206 _ASSERTE(__native_startup_state
== __initialized
);
208 (VOID
)InterlockedExchangePointer ((volatile PVOID
*) &__native_startup_lock
, 0);
210 if (__dyn_tls_init_callback
!= NULL
&& _IsNonwritableInCurrentImage ((PBYTE
) &__dyn_tls_init_callback
))
211 __dyn_tls_init_callback (NULL
, DLL_THREAD_ATTACH
, NULL
);
213 _pei386_runtime_relocator ();
216 __asm__
__volatile__ (
219 "movq %rax,%gs:0" "\n");
221 __asm__
__volatile__ (
224 "movl %eax,%fs:0" "\n");
226 AddVectoredExceptionHandler (0, (PVECTORED_EXCEPTION_HANDLER
)__mingw_vex
);
227 SetUnhandledExceptionFilter (_gnu_exception_handler
);
234 lpszCommandLine
= (_TCHAR
*) _wcmdln
;
236 lpszCommandLine
= (char *) _acmdln
;
238 while (*lpszCommandLine
> SPACECHAR
|| (*lpszCommandLine
&&inDoubleQuote
))
240 if (*lpszCommandLine
== DQUOTECHAR
)
241 inDoubleQuote
= !inDoubleQuote
;
243 if (_ismbblead (*lpszCommandLine
))
251 while (*lpszCommandLine
&& (*lpszCommandLine
<= SPACECHAR
))
255 /* C++ initialization.
256 gcc inserts this call automatically for a function called main, but not for wmain. */
259 (int) (StartupInfo
.dwFlags
& STARTF_USESHOWWINDOW
? StartupInfo
.wShowWindow
: SW_SHOWDEFAULT
),
260 (wchar_t **) lpszCommandLine
, (wchar_t **) (HINSTANCE
) &__ImageBase
);
263 (int) (StartupInfo
.dwFlags
& STARTF_USESHOWWINDOW
? StartupInfo
.wShowWindow
: SW_SHOWDEFAULT
),
264 (char **) lpszCommandLine
, (char **) (HINSTANCE
) &__ImageBase
);
269 duplicate_ppstrings (argc
, &argv
);
272 /* C++ initialization.
273 gcc inserts this call automatically for a function called main, but not for wmain. */
275 mainret
= wmain (argc
, argv
, envp
);
278 mainret
= main (argc
, argv
, envp
);
290 extern int mingw_initltsdrot_force
;
291 extern int mingw_initltsdyn_force
;
292 extern int mingw_initltssuo_force
;
293 extern int mingw_initcharmax
;
296 check_managed_app (void)
298 PIMAGE_DOS_HEADER pDOSHeader
;
299 PIMAGE_NT_HEADERS pPEHeader
;
300 PIMAGE_OPTIONAL_HEADER32 pNTHeader32
;
301 PIMAGE_OPTIONAL_HEADER64 pNTHeader64
;
303 /* Force to be linked. */
304 mingw_initltsdrot_force
=1;
305 mingw_initltsdyn_force
=1;
306 mingw_initltssuo_force
=1;
309 pDOSHeader
= (PIMAGE_DOS_HEADER
) &__ImageBase
;
310 if (pDOSHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
)
313 pPEHeader
= (PIMAGE_NT_HEADERS
)((char *)pDOSHeader
+ pDOSHeader
->e_lfanew
);
314 if (pPEHeader
->Signature
!= IMAGE_NT_SIGNATURE
)
317 pNTHeader32
= (PIMAGE_OPTIONAL_HEADER32
) &pPEHeader
->OptionalHeader
;
318 switch (pNTHeader32
->Magic
)
320 case IMAGE_NT_OPTIONAL_HDR32_MAGIC
:
321 if (pNTHeader32
->NumberOfRvaAndSizes
<= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
)
323 return !! pNTHeader32
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
;
324 case IMAGE_NT_OPTIONAL_HDR64_MAGIC
:
325 pNTHeader64
= (PIMAGE_OPTIONAL_HEADER64
)pNTHeader32
;
326 if (pNTHeader64
->NumberOfRvaAndSizes
<= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
)
328 return !! pNTHeader64
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
;
334 _gnu_exception_handler (EXCEPTION_POINTERS
* exception_data
)
336 void (*old_handler
) (int);
337 long action
= EXCEPTION_CONTINUE_SEARCH
;
340 switch (exception_data
->ExceptionRecord
->ExceptionCode
)
342 case EXCEPTION_ACCESS_VIOLATION
:
343 /* test if the user has set SIGSEGV */
344 old_handler
= signal (SIGSEGV
, SIG_DFL
);
345 if (old_handler
== SIG_IGN
)
347 /* this is undefined if the signal was raised by anything other
349 signal (SIGSEGV
, SIG_IGN
);
350 action
= EXCEPTION_CONTINUE_EXECUTION
;
352 else if (old_handler
!= SIG_DFL
)
354 /* This means 'old' is a user defined function. Call it */
355 (*old_handler
) (SIGSEGV
);
356 action
= EXCEPTION_CONTINUE_EXECUTION
;
360 case EXCEPTION_ILLEGAL_INSTRUCTION
:
361 case EXCEPTION_PRIV_INSTRUCTION
:
362 /* test if the user has set SIGILL */
363 old_handler
= signal (SIGILL
, SIG_DFL
);
364 if (old_handler
== SIG_IGN
)
366 /* this is undefined if the signal was raised by anything other
368 signal (SIGILL
, SIG_IGN
);
369 action
= EXCEPTION_CONTINUE_EXECUTION
;
371 else if (old_handler
!= SIG_DFL
)
373 /* This means 'old' is a user defined function. Call it */
374 (*old_handler
) (SIGILL
);
375 action
= EXCEPTION_CONTINUE_EXECUTION
;
379 case EXCEPTION_FLT_INVALID_OPERATION
:
380 case EXCEPTION_FLT_DIVIDE_BY_ZERO
:
381 case EXCEPTION_FLT_DENORMAL_OPERAND
:
382 case EXCEPTION_FLT_OVERFLOW
:
383 case EXCEPTION_FLT_UNDERFLOW
:
384 case EXCEPTION_FLT_INEXACT_RESULT
:
388 case EXCEPTION_INT_DIVIDE_BY_ZERO
:
389 /* test if the user has set SIGFPE */
390 old_handler
= signal (SIGFPE
, SIG_DFL
);
391 if (old_handler
== SIG_IGN
)
393 signal (SIGFPE
, SIG_IGN
);
396 action
= EXCEPTION_CONTINUE_EXECUTION
;
398 else if (old_handler
!= SIG_DFL
)
400 /* This means 'old' is a user defined function. Call it */
401 (*old_handler
) (SIGFPE
);
402 action
= EXCEPTION_CONTINUE_EXECUTION
;
412 static LONG
__mingw_vex(EXCEPTION_POINTERS
* exception_data
)
414 /* TODO this is not chainablem, therefore need rewrite. Disabled the ill code. */
417 __asm__
__volatile__ (
418 "movq %gs:0,%rax" "\n\t"
425 __asm__
__volatile__ (
426 "movl %fs:0,%eax" "\n\t"
434 return _gnu_exception_handler(exception_data
);
439 static size_t wbytelen(const wchar_t *p
)
447 static void duplicate_ppstrings (int ac
, wchar_t ***av
)
451 wchar_t **n
= (wchar_t **) malloc (sizeof (wchar_t *) * (ac
+ 1));
454 for (i
=0; i
< ac
; i
++)
456 int l
= wbytelen (avl
[i
]);
457 n
[i
] = (wchar_t *) malloc (l
);
458 memcpy (n
[i
], avl
[i
], l
);
464 static void duplicate_ppstrings (int ac
, char ***av
)
468 char **n
= (char **) malloc (sizeof (char *) * (ac
+ 1));
471 for (i
=0; i
< ac
; i
++)
473 int l
= strlen (avl
[i
]) + 1;
474 n
[i
] = (char *) malloc (l
);
475 memcpy (n
[i
], avl
[i
], l
);