• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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