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;