4 * Source code for the startup procedures used by all programs. This
5 * code is compiled to crt1.o, which is located in the library path.
9 * Written by Colin Peters <colin@bird.fu.is.saga-u.ac.jp>
10 * Copyright (C) 1997, 1999, 2002-2007, 2009, 2010, 2014, 2016,
11 * 2017, MinGW.org Project.
14 * Permission is hereby granted, free of charge, to any person obtaining a
15 * copy of this software and associated documentation files (the "Software"),
16 * to deal in the Software without restriction, including without limitation
17 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 * and/or sell copies of the Software, and to permit persons to whom the
19 * Software is furnished to do so, subject to the following conditions:
21 * The above copyright notice, this permission notice, and the following
22 * disclaimer shall be included in all copies or substantial portions of
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
26 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
28 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
30 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER
31 * DEALINGS IN THE SOFTWARE.
34 #define __IN_MINGW_RUNTIME
35 /* Hide the declaration of _fmode(), with its dllimport attribute in
36 * <stdlib.h>, to avoid problems with older GCC.
44 #define WIN32_LEAN_AND_MEAN
48 #include "cpu_features.h"
50 extern void __main ();
51 extern void _pei386_runtime_relocator (void);
53 /* Main program entry point, and argument initialization hook.
55 extern int main (int, char **, char **);
56 extern void _setargv (void);
61 /* NOTE: Thanks to Pedro A. Aranda Gutiirrez <paag@tid.es> for pointing
62 * this out: the GetMainArgs() function, (provided by CRTDLL.DDL, as an
63 * argument initialization hook), takes a fourth argument (an int), which
64 * controls the globbing of the command line; if it is non-zero the command
65 * line will be globbed (e.g. *.* will be expanded to a list, separated by
66 * spaces, of all files in the startup directory).
68 * We determine how globbing should be performed, by inspection of the two
69 * least significant bits of the global int variable _CRT_glob, (defined in
70 * the mingw32 library, with a default value of 2). If this pair of bits
71 * represent a value of 2 or more, the new MinGW globbing algorithm, (as
72 * implemented by function _setargv() in setargv.c), will be applied; for
73 * values of one or zero, _setargv() will delegate the globbing function to
74 * the _mingw32_init_mainargs() callback function implemented below, and so
75 * invoking the Microsoft GetMainArgs() algorithm, with its fourth argument
76 * set to one or zero, to match the least significant bit of _CRT_glob.
78 * The mingw32 library default value of 2 for _CRT_glob enables command line
79 * globbing using the MinGW algorithm. If you prefer to adopt the Microsoft
80 * algorithm, you should define _CRT_glob as a global variable, by including
81 * a line in one of your own source code files, like this:
85 * Alternatively, if you prefer to disable globbing, and do all command line
86 * processing yourself, (and so evade possible bogons in the Microsoft or in
87 * the MinGW globbing code), include a similar line in one of your own source
88 * code files, defining _CRT_glob with a value of zero, like this:
95 /* In MSVCRT.DLL, Microsoft's initialization hook is called __getmainargs(),
96 * and it expects a further structure argument, (which we don't use, but pass
97 * it as a dummy, with a declared size of zero in its first and only field).
99 typedef struct { int newmode; } _startupinfo;
100 extern void __getmainargs( int *, char ***, char ***, int, _startupinfo * );
103 /* In CRTDLL.DLL, the initialization hook is called __GetMainArgs().
105 extern void __GetMainArgs( int *, char ***, char ***, int );
108 void _mingw32_init_mainargs()
109 { /* This is the old start-up mechanism, in which we use a start-up
110 * hook provided by Microsoft's runtime library to initialize the
111 * argument and environment vectors.
113 * Note that the preferred method for accessing the environment
114 * vector is via a direct pointer retrieved from the runtime DLL,
115 * using a system call declared in stdlib.h; thus, we don't need
116 * to preserve the pointer returned by the start-up hook, so we
117 * may simply capture it locally, and subsequently discard it.
121 # define _CRT_GLOB_OPT _CRT_glob & __CRT_GLOB_USE_MSVCRT__
123 /* The MSVCRT.DLL start-up hook requires this invocation
126 _startupinfo start_info = { 0 };
127 __getmainargs( &_argc, &_argv, &dummy_envp, _CRT_GLOB_OPT, &start_info );
130 /* ...while a somewhat simpler protocol is applicable, in
131 * the case of the CRTDLL.DLL version.
133 __GetMainArgs( &_argc, &_argv, &dummy_envp, _CRT_GLOB_OPT );
137 /* TLS initialization hook.
139 extern const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback;
141 /* Must have the correct app type for MSVCRT.
144 # define __UNKNOWN_APP 0
145 # define __CONSOLE_APP 1
148 __MINGW_IMPORT void __set_app_type(int);
150 #endif /* __MSVCRT__ */
152 /* Global _fmode for this .exe, (not the one in msvcrt.dll).
154 * The default is set in txtmode.o in libmingw32.a
155 * Override the dllimport'd declarations in stdlib.h
160 extern int* __p__fmode(void); /* To access the dll _fmode */
163 /* Setup the default file handles to have the _CRT_fmode mode,
164 * as well as any new files created by the user.
166 extern int _CRT_fmode;
169 _mingw32_init_fmode (void)
170 { /* Don't set the std file mode if the user hasn't set any
177 /* This overrides the default file mode settings for stdin,
178 * stdout and stderr. At first I thought you would have to
179 * test with isatty, but it seems that the DOS console at
180 * least is smart enough to handle _O_BINARY stdout and
181 * still display correctly.
183 if (stdin) _setmode (_fileno (stdin), _CRT_fmode);
184 if (stdout) _setmode (_fileno (stdout), _CRT_fmode);
185 if (stderr) _setmode (_fileno (stderr), _CRT_fmode);
188 /* Now sync the dll _fmode to the one for this .exe.
191 *__p__fmode() = _fmode;
193 *_imp___fmode_dll = _fmode;
197 /* This function will be called when a trap occurs. Thanks to
198 * Jacob Navia for this contribution.
201 _gnu_exception_handler (EXCEPTION_POINTERS * exception_data)
203 void (*old_handler) (int);
204 long action = EXCEPTION_CONTINUE_SEARCH;
207 switch (exception_data->ExceptionRecord->ExceptionCode)
209 case EXCEPTION_ACCESS_VIOLATION:
210 /* Test if the user has set SIGSEGV
212 old_handler = signal (SIGSEGV, SIG_DFL);
213 if (old_handler == SIG_IGN)
214 { /* This is undefined if the signal was raised by
215 * anything other than raise()
217 signal (SIGSEGV, SIG_IGN);
218 action = EXCEPTION_CONTINUE_EXECUTION;
220 else if (old_handler != SIG_DFL)
221 { /* This means 'old_handler' is a user defined
224 (*old_handler) (SIGSEGV);
225 action = EXCEPTION_CONTINUE_EXECUTION;
229 case EXCEPTION_ILLEGAL_INSTRUCTION:
230 case EXCEPTION_PRIV_INSTRUCTION:
231 /* Test if the user has set SIGILL
233 old_handler = signal (SIGILL, SIG_DFL);
234 if (old_handler == SIG_IGN)
235 { /* This is undefined if the signal was raised by
236 * anything other than raise()
238 signal (SIGILL, SIG_IGN);
239 action = EXCEPTION_CONTINUE_EXECUTION;
241 else if (old_handler != SIG_DFL)
242 { /* This means 'old_handler' is a user defined
245 (*old_handler) (SIGILL);
246 action = EXCEPTION_CONTINUE_EXECUTION;
250 case EXCEPTION_FLT_INVALID_OPERATION:
251 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
252 case EXCEPTION_FLT_DENORMAL_OPERAND:
253 case EXCEPTION_FLT_OVERFLOW:
254 case EXCEPTION_FLT_UNDERFLOW:
255 case EXCEPTION_FLT_INEXACT_RESULT:
259 case EXCEPTION_INT_DIVIDE_BY_ZERO:
260 /* Test if the user has set SIGFPE
262 old_handler = signal (SIGFPE, SIG_DFL);
263 if (old_handler == SIG_IGN)
265 signal (SIGFPE, SIG_IGN);
267 fesetenv (FE_DFL_ENV);
268 action = EXCEPTION_CONTINUE_EXECUTION;
270 else if (old_handler != SIG_DFL)
271 { /* This means 'old_handler' is a user defined
274 (*old_handler) (SIGFPE);
275 action = EXCEPTION_CONTINUE_EXECUTION;
281 /* During application start-up, we establish the default configuration
282 * for the FPU. MSVCRT.DLL provides the _fpreset() function to perform
283 * the appropriate initialization, but it sets the default operation to
284 * be in IEEE-754 8-byte mode, whereas we prefer IEEE-754 10-byte mode,
285 * to better support GCC's 10-byte long doubles; nevertheless, we offer
286 * the option, via the _CRT_fenv global variable, to establish either
287 * one of these modes as initial default, it should be set to either
288 * FE_PD64_ENV, (defined in <fenv.h>, reflecting the 64-bit precision
289 * of the 10-byte mode, and established as default for _CRT_fenv within
290 * the runtime library), or overridden by a setting of FE_PD53_ENV, in
291 * user code, like this:
294 * const fenv_t *_CRT_fenv = FE_PD53_ENV;
296 * (or by linking with CRT_fp8.o), to select the 53-bit precision of
299 * Whichever of these assignments, i.e. FE_PD64_ENV or FE_PD53_ENV, is
300 * in effect when the following __mingw_CRTStartup() function is invoked,
301 * will cause FE_DFL_ENV to be mapped to one or other of the predefined
302 * environments, FE_PC64_ENV or FE_PC53_ENV, respectively.
304 extern const fenv_t *_CRT_fenv;
306 /* The function mainCRTStartup(), (defined below), is the entry point
307 * for all console programs, it is, primarily, a wrapper around the
308 * following __mingw_CRTStartup() helper function.
310 static __MINGW_ATTRIB_NORETURN void __mingw_CRTStartup (void)
314 /* Initialize TLS callback.
316 if (__dyn_tls_init_callback != NULL)
317 __dyn_tls_init_callback (NULL, DLL_THREAD_ATTACH, NULL);
319 /* Set up the top-level exception handler so that signal handling
320 * works as expected. The mapping between ANSI/POSIX signals and
321 * Win32 SE is not 1-to-1, so caveat emptor.
324 SetUnhandledExceptionFilter (_gnu_exception_handler);
326 /* Initialize the floating point unit.
328 __cpu_features_init (); /* Do we have SSE, etc. */
329 fesetenv (_CRT_fenv); /* Supplied by the runtime library. */
331 /* Set up __argc, __argv and _environ.
335 /* Set the default file mode. If _CRT_fmode is set, also set mode
336 * for stdin, stdout and stderr, as well. NOTE: DLLs don't do this
337 * because that would be rude!
339 _mingw32_init_fmode ();
341 /* Adust references to dllimported data that have non-zero offsets.
343 _pei386_runtime_relocator ();
345 /* Align the stack to 16 bytes for the sake of SSE ops in main
346 * or in functions inlined into main.
348 asm __volatile__ ("andl $-16, %%esp" : : : "%esp");
350 /* From libgcc.a, __main() calls global class constructors via
351 * __do_global_ctors(); this in turn registers __do_global_dtors()
352 * as the first entry of the application's atexit() table. We do
353 * this explicitly at application startup rather than rely on GCC
354 * to generate the call in main()'s prologue, since main() may be
355 * imported from a DLL which has its own __do_global_ctors()
359 /* Call the main() function. If the user does not supply one
360 * the one in the 'libmingw32.a' library will be linked in, and
361 * that one calls WinMain(). See main.c in the 'lib' directory
364 nRet = main (_argc, _argv, environ);
366 /* Perform exit processing for the C library. This means flushing
367 * output and calling atexit() registered functions.
374 /* The function mainCRTStartup() is the entry point for all console
378 mainCRTStartup (void)
381 __set_app_type (__CONSOLE_APP);
383 __mingw_CRTStartup ();
386 /* For now the GUI startup function is the same as the console one.
387 * This simply gets rid of the annoying warning about not being able
388 * to find WinMainCRTStartup when linking GUI applications.
391 WinMainCRTStartup (void)
394 __set_app_type (__GUI_APP);
396 __mingw_CRTStartup ();
399 /* We force use of library version of atexit(), which is only
400 * visible in import lib as _imp__atexit
402 extern int (*_imp__atexit)(void (*)(void));
403 int atexit (void (* pfn )(void)){ return (*_imp__atexit)(pfn); }
405 /* Likewise for non-ANSI _onexit()
407 extern _onexit_t (*_imp___onexit)(_onexit_t);
408 _onexit_t _onexit (_onexit_t pfn){ return (*_imp___onexit)(pfn); }
410 /* $RCSfile$: end of file */