master
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#include <oscalls.h>
8#include <internal.h>
9#include <process.h>
10#include <signal.h>
11#include <math.h>
12#include <stdlib.h>
13#include <tchar.h>
14#include <sect_attribs.h>
15#include <locale.h>
16#include <corecrt_startup.h>
17
18#if defined(__SEH__) && (!defined(__clang__) || __clang_major__ >= 7)
19#define SEH_INLINE_ASM
20#endif
21
22extern IMAGE_DOS_HEADER __ImageBase;
23
24extern void _fpreset (void);
25
26int *__cdecl __p__commode(void);
27
28#undef _fmode
29extern int _fmode;
30#undef _commode
31extern int _commode;
32extern int _dowildcard;
33
34extern _CRTIMP void __cdecl _initterm(_PVFV *, _PVFV *);
35
36static int __cdecl check_managed_app (void);
37
38extern _PIFV __xi_a[];
39extern _PIFV __xi_z[];
40extern _PVFV __xc_a[];
41extern _PVFV __xc_z[];
42
43
44/* TLS initialization hook. */
45extern const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback;
46
47extern int __mingw_app_type;
48
49static int argc;
50extern void __main(void);
51static _TCHAR **argv;
52static _TCHAR **envp;
53
54static int mainret=0;
55static int managedapp;
56static int has_cctor = 0;
57extern LPTOP_LEVEL_EXCEPTION_FILTER __mingw_oldexcpt_handler;
58
59extern void _pei386_runtime_relocator (void);
60long CALLBACK _gnu_exception_handler (EXCEPTION_POINTERS * exception_data);
61static void duplicate_ppstrings (int ac, _TCHAR ***av);
62
63static int __cdecl pre_c_init (void);
64static void __cdecl pre_cpp_init (void);
65_CRTALLOC(".CRT$XIAA") _PIFV __mingw_pcinit = pre_c_init;
66_CRTALLOC(".CRT$XCAA") _PVFV __mingw_pcppinit = pre_cpp_init;
67
68extern int _MINGW_INSTALL_DEBUG_MATHERR;
69
70#ifdef __MINGW_SHOW_INVALID_PARAMETER_EXCEPTION
71#define __UNUSED_PARAM_1(x) x
72#else
73#define __UNUSED_PARAM_1 __UNUSED_PARAM
74#endif
75static void
76__mingw_invalidParameterHandler (const wchar_t * __UNUSED_PARAM_1(expression),
77 const wchar_t * __UNUSED_PARAM_1(function),
78 const wchar_t * __UNUSED_PARAM_1(file),
79 unsigned int __UNUSED_PARAM_1(line),
80 uintptr_t __UNUSED_PARAM(pReserved))
81{
82#ifdef __MINGW_SHOW_INVALID_PARAMETER_EXCEPTION
83 wprintf(L"Invalid parameter detected in function %s. File: %s Line: %d\n", function, file, line);
84 wprintf(L"Expression: %s\n", expression);
85#endif
86}
87
88static int __cdecl
89pre_c_init (void)
90{
91 int ret;
92 managedapp = check_managed_app ();
93 if (__mingw_app_type)
94 __set_app_type(_GUI_APP);
95 else
96 __set_app_type (_CONSOLE_APP);
97
98 * __p__fmode() = _fmode;
99 * __p__commode() = _commode;
100
101#ifdef _UNICODE
102 ret = _wsetargv();
103#else
104 ret = _setargv();
105#endif
106 if (ret < 0)
107 _amsg_exit(8); /* _RT_SPACEARG */
108 if (_MINGW_INSTALL_DEBUG_MATHERR == 1)
109 {
110 __setusermatherr (_matherr);
111 }
112
113 if (__globallocalestatus == -1)
114 {
115 }
116 return 0;
117}
118
119static void __cdecl
120pre_cpp_init (void)
121{
122 _startupinfo startinfo;
123 int argret;
124
125 startinfo.newmode = _newmode;
126
127#ifdef _UNICODE
128 argret = __wgetmainargs(&argc,&argv,&envp,_dowildcard,&startinfo);
129#else
130 argret = __getmainargs(&argc,&argv,&envp,_dowildcard,&startinfo);
131#endif
132 if (argret < 0)
133 _amsg_exit(8); /* _RT_SPACEARG */
134}
135
136static int __tmainCRTStartup (void);
137
138int WinMainCRTStartup (void);
139
140__attribute__((used)) /* required due to GNU LD bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30300 */
141int WinMainCRTStartup (void)
142{
143 int ret = 255;
144#ifdef SEH_INLINE_ASM
145 asm ("\t.l_startw:\n");
146#endif
147 __mingw_app_type = 1;
148 ret = __tmainCRTStartup ();
149#ifdef SEH_INLINE_ASM
150 asm ("\tnop\n"
151 "\t.l_endw: nop\n"
152#ifdef __arm__
153 "\t.seh_handler __C_specific_handler, %except\n"
154#else
155 "\t.seh_handler __C_specific_handler, @except\n"
156#endif
157 "\t.seh_handlerdata\n"
158 "\t.long 1\n"
159 "\t.rva .l_startw, .l_endw, _gnu_exception_handler ,.l_endw\n"
160 "\t.text");
161#endif
162 return ret;
163}
164
165int mainCRTStartup (void);
166
167#if defined(__x86_64__) && !defined(__SEH__)
168int __mingw_init_ehandler (void);
169#endif
170
171__attribute__((used)) /* required due to GNU LD bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30300 */
172int mainCRTStartup (void)
173{
174 int ret = 255;
175#ifdef SEH_INLINE_ASM
176 asm ("\t.l_start:\n");
177#endif
178 __mingw_app_type = 0;
179 ret = __tmainCRTStartup ();
180#ifdef SEH_INLINE_ASM
181 asm ("\tnop\n"
182 "\t.l_end: nop\n"
183#ifdef __arm__
184 "\t.seh_handler __C_specific_handler, %except\n"
185#else
186 "\t.seh_handler __C_specific_handler, @except\n"
187#endif
188 "\t.seh_handlerdata\n"
189 "\t.long 1\n"
190 "\t.rva .l_start, .l_end, _gnu_exception_handler ,.l_end\n"
191 "\t.text");
192#endif
193 return ret;
194}
195
196static
197#if defined(__i386__) || defined(_X86_)
198/* We need to make sure that we align the stack to 16 bytes for the sake of SSE
199 opts in main or in functions called from main. */
200__attribute__((force_align_arg_pointer))
201#endif
202__declspec(noinline) int
203__tmainCRTStartup (void)
204{
205 void *lock_free = NULL;
206 void *fiberid = ((PNT_TIB)NtCurrentTeb())->StackBase;
207 BOOL nested = FALSE;
208 while((lock_free = InterlockedCompareExchangePointer (&__native_startup_lock,
209 fiberid, NULL)) != 0)
210 {
211 if (lock_free == fiberid)
212 {
213 nested = TRUE;
214 break;
215 }
216 Sleep(1000);
217 }
218 if (__native_startup_state == __initializing)
219 {
220 _amsg_exit (31);
221 }
222 else if (__native_startup_state == __uninitialized)
223 {
224 __native_startup_state = __initializing;
225 if (_initterm_e (__xi_a, __xi_z) != 0)
226 return 255;
227 }
228 else
229 has_cctor = 1;
230
231 if (__native_startup_state == __initializing)
232 {
233 _initterm (__xc_a, __xc_z);
234 __native_startup_state = __initialized;
235 }
236 _ASSERTE(__native_startup_state == __initialized);
237 if (! nested)
238 (VOID)InterlockedExchangePointer (&__native_startup_lock, NULL);
239
240 if (__dyn_tls_init_callback != NULL)
241 __dyn_tls_init_callback (NULL, DLL_THREAD_ATTACH, NULL);
242
243 _pei386_runtime_relocator ();
244 __mingw_oldexcpt_handler = SetUnhandledExceptionFilter (_gnu_exception_handler);
245#if defined(__x86_64__) && !defined(__SEH__)
246 __mingw_init_ehandler ();
247#endif
248 _set_invalid_parameter_handler (__mingw_invalidParameterHandler);
249
250 _fpreset ();
251
252 duplicate_ppstrings (argc, &argv);
253 __main (); /* C++ initialization. */
254#ifdef _UNICODE
255 __winitenv = envp;
256#else
257 __initenv = envp;
258#endif
259 mainret = _tmain (argc, argv, envp);
260 if (!managedapp)
261 exit (mainret);
262
263 if (has_cctor == 0)
264 _cexit ();
265
266 return mainret;
267}
268
269extern int __mingw_initltsdrot_force;
270extern int __mingw_initltsdyn_force;
271extern int __mingw_initltssuo_force;
272
273static int __cdecl
274check_managed_app (void)
275{
276 PIMAGE_DOS_HEADER pDOSHeader;
277 PIMAGE_NT_HEADERS pPEHeader;
278 PIMAGE_OPTIONAL_HEADER32 pNTHeader32;
279 PIMAGE_OPTIONAL_HEADER64 pNTHeader64;
280
281 /* Force to be linked. */
282 __mingw_initltsdrot_force=1;
283 __mingw_initltsdyn_force=1;
284 __mingw_initltssuo_force=1;
285
286 pDOSHeader = (PIMAGE_DOS_HEADER) &__ImageBase;
287 if (pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE)
288 return 0;
289
290 pPEHeader = (PIMAGE_NT_HEADERS)((char *)pDOSHeader + pDOSHeader->e_lfanew);
291 if (pPEHeader->Signature != IMAGE_NT_SIGNATURE)
292 return 0;
293
294 pNTHeader32 = (PIMAGE_OPTIONAL_HEADER32) &pPEHeader->OptionalHeader;
295 switch (pNTHeader32->Magic)
296 {
297 case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
298 if (pNTHeader32->NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)
299 return 0;
300 return !! pNTHeader32->DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress;
301 case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
302 pNTHeader64 = (PIMAGE_OPTIONAL_HEADER64)pNTHeader32;
303 if (pNTHeader64->NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)
304 return 0;
305 return !! pNTHeader64->DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress;
306 }
307 return 0;
308}
309
310static void duplicate_ppstrings (int ac, _TCHAR ***av)
311{
312 _TCHAR **avl;
313 int i;
314 _TCHAR **n = (_TCHAR **) malloc (sizeof (_TCHAR *) * (ac + 1));
315
316 avl=*av;
317 for (i=0; i < ac; i++)
318 {
319 size_t l = sizeof (_TCHAR) * (_tcslen (avl[i]) + 1);
320 n[i] = (_TCHAR *) malloc (l);
321 memcpy (n[i], avl[i], l);
322 }
323 n[i] = NULL;
324 *av = n;
325}
326
327int __cdecl atexit (_PVFV func)
328{
329 /*
330 * msvcrt def file renames the real atexit() function to _crt_atexit().
331 * UCRT provides atexit() function only under name _crt_atexit().
332 * So redirect call to _crt_atexit() function.
333 */
334 return _crt_atexit(func);
335}
336
337char __mingw_module_is_dll = 0;