3 * This file has no copyright assigned and is placed in the Public Domain.
4 * This file is a part of the mingw-runtime package.
5 * No warranty is given; refer to the file DISCLAIMER within the package.
7 * Source code for the startup proceedures used by all programs. This code
8 * is compiled to make crt1.o, which should be located in the library path.
12 /* Hide the declaration of _fmode with dllimport attribute in stdlib.h to
13 * avoid problems with older GCC.
15 #define __IN_MINGW_RUNTIME
21 #define WIN32_LEAN_AND_MEAN
25 #include "cpu_features.h"
27 extern void __main ();
28 extern void _pei386_runtime_relocator (void);
30 /* Main program entry point, and argument initialization hook.
32 extern int main (int, char **, char **);
33 extern void _setargv (void);
38 /* NOTE: Thanks to Pedro A. Aranda Gutiirrez <paag@tid.es> for pointing
39 * this out: the GetMainArgs() function, (provided by CRTDLL.DDL, as an
40 * argument initialization hook), takes a fourth argument (an int), which
41 * controls the globbing of the command line; if it is non-zero the command
42 * line will be globbed (e.g. *.* will be expanded to a list, separated by
43 * spaces, of all files in the startup directory).
45 * We determine how globbing should be performed, by inspection of the two
46 * least significant bits of the global int variable _CRT_glob, (defined in
47 * the mingw32 library, with a default value of 2). If this pair of bits
48 * represent a value of 2 or more, the new MinGW globbing algorithm, (as
49 * implemented by function _setargv() in setargv.c), will be applied; for
50 * values of one or zero, _setargv() will delegate the globbing function to
51 * the _mingw32_init_mainargs() callback function implemented below, and so
52 * invoking the Microsoft GetMainArgs() algorithm, with its fourth argument
53 * set to one or zero, to match the least significant bit of _CRT_glob.
55 * The mingw32 library default value of 2 for _CRT_glob enables command line
56 * globbing using the MinGW algorithm. If you prefer to adopt the Microsoft
57 * algorithm, you should define _CRT_glob as a global variable, by including
58 * a line in one of your own source code files, like this:
62 * Alternatively, if you prefer to disable globbing, and do all command line
63 * processing yourself, (and so evade possible bogons in the Microsoft or in
64 * the MinGW globbing code), include a similar line in one of your own source
65 * code files, defining _CRT_glob with a value of zero, like this:
72 /* In MSVCRT.DLL, Microsoft's initialization hook is called __getmainargs(),
73 * and it expects a further structure argument, (which we don't use, but pass
74 * it as a dummy, with a declared size of zero in its first and only field).
76 typedef struct { int newmode; } _startupinfo;
77 extern void __getmainargs( int *, char ***, char ***, int, _startupinfo * );
80 /* In CRTDLL.DLL, the initialization hook is called __GetMainArgs().
82 extern void __GetMainArgs( int *, char ***, char ***, int );
85 void _mingw32_init_mainargs()
87 /* This is the old start-up mechanism, in which we use a start-up
88 * hook provided by Microsoft's runtime library to initialize the
89 * argument and environment vectors.
91 * Note that the preferred method for accessing the environment
92 * vector is via a direct pointer retrieved from the runtime DLL,
93 * using a system call declared in stdlib.h; thus, we don't need
94 * to preserve the pointer returned by the start-up hook, so we
95 * may simply capture it locally, and subsequently discard it.
99 # define _CRT_GLOB_OPT _CRT_glob & __CRT_GLOB_USE_MSVCRT__
101 /* The MSVCRT.DLL start-up hook requires this invocation
104 _startupinfo start_info = { 0 };
105 __getmainargs( &_argc, &_argv, &dummy_envp, _CRT_GLOB_OPT, &start_info );
108 /* ...while a somewhat simpler protocol is applicable, in
109 * the case of the CRTDLL.DLL version.
111 __GetMainArgs( &_argc, &_argv, &dummy_envp, _CRT_GLOB_OPT );
115 /* TLS initialization hook.
117 extern const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback;
119 /* Must have the correct app type for MSVCRT.
122 # define __UNKNOWN_APP 0
123 # define __CONSOLE_APP 1
126 __MINGW_IMPORT void __set_app_type(int);
128 #endif /* __MSVCRT__ */
130 /* Global _fmode for this .exe, (not the one in msvcrt.dll).
132 * The default is set in txtmode.o in libmingw32.a
133 * Override the dllimport'd declarations in stdlib.h
138 extern int* __p__fmode(void); /* To access the dll _fmode */
142 * Setup the default file handles to have the _CRT_fmode mode, as well as
143 * any new files created by the user.
145 extern int _CRT_fmode;
148 _mingw32_init_fmode (void)
150 /* Don't set the std file mode if the user hasn't set any value for it.
156 /* This overrides the default file mode settings for stdin,
157 * stdout and stderr. At first I thought you would have to
158 * test with isatty, but it seems that the DOS console at
159 * least is smart enough to handle _O_BINARY stdout and
160 * still display correctly.
162 if (stdin) _setmode (_fileno (stdin), _CRT_fmode);
163 if (stdout) _setmode (_fileno (stdout), _CRT_fmode);
164 if (stderr) _setmode (_fileno (stderr), _CRT_fmode);
167 /* Now sync the dll _fmode to the one for this .exe.
170 *__p__fmode() = _fmode;
172 *_imp___fmode_dll = _fmode;
176 /* This function will be called when a trap occurs. Thanks to
177 * Jacob Navia for this contribution.
180 _gnu_exception_handler (EXCEPTION_POINTERS * exception_data)
182 void (*old_handler) (int);
183 long action = EXCEPTION_CONTINUE_SEARCH;
186 switch (exception_data->ExceptionRecord->ExceptionCode)
188 case EXCEPTION_ACCESS_VIOLATION:
189 /* test if the user has set SIGSEGV */
190 old_handler = signal (SIGSEGV, SIG_DFL);
191 if (old_handler == SIG_IGN)
193 /* this is undefined if the signal was raised by anything other
195 signal (SIGSEGV, SIG_IGN);
196 action = EXCEPTION_CONTINUE_EXECUTION;
198 else if (old_handler != SIG_DFL)
200 /* This means 'old' is a user defined function. Call it */
201 (*old_handler) (SIGSEGV);
202 action = EXCEPTION_CONTINUE_EXECUTION;
206 case EXCEPTION_ILLEGAL_INSTRUCTION:
207 case EXCEPTION_PRIV_INSTRUCTION:
208 /* test if the user has set SIGILL */
209 old_handler = signal (SIGILL, SIG_DFL);
210 if (old_handler == SIG_IGN)
212 /* this is undefined if the signal was raised by anything other
214 signal (SIGILL, SIG_IGN);
215 action = EXCEPTION_CONTINUE_EXECUTION;
217 else if (old_handler != SIG_DFL)
219 /* This means 'old' is a user defined function. Call it */
220 (*old_handler) (SIGILL);
221 action = EXCEPTION_CONTINUE_EXECUTION;
225 case EXCEPTION_FLT_INVALID_OPERATION:
226 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
227 case EXCEPTION_FLT_DENORMAL_OPERAND:
228 case EXCEPTION_FLT_OVERFLOW:
229 case EXCEPTION_FLT_UNDERFLOW:
230 case EXCEPTION_FLT_INEXACT_RESULT:
234 case EXCEPTION_INT_DIVIDE_BY_ZERO:
235 /* test if the user has set SIGFPE */
236 old_handler = signal (SIGFPE, SIG_DFL);
237 if (old_handler == SIG_IGN)
239 signal (SIGFPE, SIG_IGN);
242 action = EXCEPTION_CONTINUE_EXECUTION;
244 else if (old_handler != SIG_DFL)
246 /* This means 'old' is a user defined function. Call it */
247 (*old_handler) (SIGFPE);
248 action = EXCEPTION_CONTINUE_EXECUTION;
258 /* The function mainCRTStartup is the entry point for all console programs.
260 static void __MINGW_ATTRIB_NORETURN
261 __mingw_CRTStartup (void)
265 /* Initialize TLS callback.
267 if (__dyn_tls_init_callback != NULL)
268 __dyn_tls_init_callback (NULL, DLL_THREAD_ATTACH, NULL);
270 /* Set up the top-level exception handler so that signal handling
271 * works as expected. The mapping between ANSI/POSIX signals and
272 * Win32 SE is not 1-to-1, so caveat emptor.
275 SetUnhandledExceptionFilter (_gnu_exception_handler);
277 /* Initialize floating point unit.
279 __cpu_features_init (); /* Do we have SSE, etc.*/
280 _fpreset (); /* Supplied by the runtime library. */
282 /* Set up __argc, __argv and _environ.
286 /* Sets the default file mode.
287 * If _CRT_fmode is set, also set mode for stdin, stdout
288 * and stderr, as well
289 * NOTE: DLLs don't do this because that would be rude!
291 _mingw32_init_fmode ();
293 /* Adust references to dllimported data that have non-zero offsets.
295 _pei386_runtime_relocator ();
297 /* Align the stack to 16 bytes for the sake of SSE ops in main
298 * or in functions inlined into main.
300 asm __volatile__ ("andl $-16, %%esp" : : : "%esp");
302 /* From libgcc.a, __main calls global class constructors via
303 __do_global_ctors, This in turn registers __do_global_dtors
304 as the first entry of the app's atexit table. We do this
305 explicitly at app startup rather than rely on gcc to generate
306 the call in main's prologue, since main may be imported from a dll
307 which has its own __do_global_ctors. */
310 /* Call the main function. If the user does not supply one
311 * the one in the 'libmingw32.a' library will be linked in, and
312 * that one calls WinMain. See main.c in the 'lib' dir
315 nRet = main (_argc, _argv, environ);
317 /* Perform exit processing for the C library. This means
318 * flushing output and calling 'atexit' registered functions.
326 * The function mainCRTStartup is the entry point for all console programs.
329 mainCRTStartup (void)
332 __set_app_type (__CONSOLE_APP);
334 __mingw_CRTStartup ();
338 * For now the GUI startup function is the same as the console one.
339 * This simply gets rid of the annoying warning about not being able
340 * to find WinMainCRTStartup when linking GUI applications.
343 WinMainCRTStartup (void)
346 __set_app_type (__GUI_APP);
348 __mingw_CRTStartup ();
352 * We force use of library version of atexit, which is only
353 * visible in import lib as _imp__atexit
355 extern int (*_imp__atexit)(void (*)(void));
356 int atexit (void (* pfn )(void) )
358 return ( (*_imp__atexit)(pfn));
361 /* Likewise for non-ANSI _onexit */
362 extern _onexit_t (*_imp___onexit)(_onexit_t);
364 _onexit (_onexit_t pfn )
366 return (*_imp___onexit)(pfn);