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