xref: /illumos-gate/usr/src/lib/crt/common/common-crt.c (revision 4004e4c5)
13e76f9d6SRichard Lowe /*
23e76f9d6SRichard Lowe  * This file and its contents are supplied under the terms of the
33e76f9d6SRichard Lowe  * Common Development and Distribution License ("CDDL"), version 1.0.
43e76f9d6SRichard Lowe  * You may only use this file in accordance with the terms of version
53e76f9d6SRichard Lowe  * 1.0 of the CDDL.
63e76f9d6SRichard Lowe  *
73e76f9d6SRichard Lowe  * A full copy of the text of the CDDL should have accompanied this
83e76f9d6SRichard Lowe  * source.  A copy of the CDDL is also available via the Internet at
93e76f9d6SRichard Lowe  * http://www.illumos.org/license/CDDL.
103e76f9d6SRichard Lowe  */
113e76f9d6SRichard Lowe 
123e76f9d6SRichard Lowe /*
133e76f9d6SRichard Lowe  * Copyright 2016, Richard Lowe.
14*4004e4c5SAndy Fiddaman  * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
153e76f9d6SRichard Lowe  */
163e76f9d6SRichard Lowe 
173e76f9d6SRichard Lowe /*
183e76f9d6SRichard Lowe  * That of the CRT startup routine which itself may be implemented in C.
193e76f9d6SRichard Lowe  */
203e76f9d6SRichard Lowe 
213e76f9d6SRichard Lowe #include <sys/feature_tests.h>
223e76f9d6SRichard Lowe #include <sys/types.h>
233e76f9d6SRichard Lowe 
243e76f9d6SRichard Lowe #include <stdlib.h>
253e76f9d6SRichard Lowe #include <synch.h>
263e76f9d6SRichard Lowe #include <unistd.h>
273e76f9d6SRichard Lowe 
283e76f9d6SRichard Lowe #pragma weak _DYNAMIC
293e76f9d6SRichard Lowe extern uintptr_t _DYNAMIC;
303e76f9d6SRichard Lowe 
313e76f9d6SRichard Lowe #pragma weak environ = _environ
323e76f9d6SRichard Lowe char **_environ = NULL;
333e76f9d6SRichard Lowe char **___Argv = NULL;
343e76f9d6SRichard Lowe 
353e76f9d6SRichard Lowe extern int main(int argc, char **argv, char **envp);
363e76f9d6SRichard Lowe extern void _init(void);
373e76f9d6SRichard Lowe extern void _fini(void);
383e76f9d6SRichard Lowe 
39*4004e4c5SAndy Fiddaman #pragma weak __start_crt_compiler
40*4004e4c5SAndy Fiddaman extern int __start_crt_compiler(int argc, char **argv);
413e76f9d6SRichard Lowe 
423e76f9d6SRichard Lowe #if defined(__x86)
433e76f9d6SRichard Lowe int __longdouble_used = 0;
443e76f9d6SRichard Lowe extern void __fpstart(void);
453e76f9d6SRichard Lowe #endif
463e76f9d6SRichard Lowe 
473e76f9d6SRichard Lowe #if defined(__i386)		/* Not amd64 */
483e76f9d6SRichard Lowe #pragma weak __fsr_init_value
493e76f9d6SRichard Lowe extern long __fsr_init_value;
503e76f9d6SRichard Lowe extern void __fsr(uintptr_t);
513e76f9d6SRichard Lowe #endif
523e76f9d6SRichard Lowe 
533e76f9d6SRichard Lowe 
543e76f9d6SRichard Lowe /*
553e76f9d6SRichard Lowe  * Defined here for ABI reasons, must match the definition in libc.
563e76f9d6SRichard Lowe  * If it cannot, a new symbol must be created.
573e76f9d6SRichard Lowe  */
583e76f9d6SRichard Lowe mutex_t __environ_lock = DEFAULTMUTEX;
593e76f9d6SRichard Lowe 
603e76f9d6SRichard Lowe void
_start_crt(int argc,char ** argv,void (* exit_handler)(void))613e76f9d6SRichard Lowe _start_crt(int argc, char **argv, void (*exit_handler)(void))
623e76f9d6SRichard Lowe {
633e76f9d6SRichard Lowe 	int ret = 0;
643e76f9d6SRichard Lowe 
653e76f9d6SRichard Lowe 	/*
663e76f9d6SRichard Lowe 	 * On x86, we check whether we're a dynamic executable to see whether
673e76f9d6SRichard Lowe 	 * we'll receive an exit_handler.
683e76f9d6SRichard Lowe 	 *
693e76f9d6SRichard Lowe 	 * On SPARC, we just need to check whether the handler was NULL.
703e76f9d6SRichard Lowe 	 */
713e76f9d6SRichard Lowe #if defined(__x86)
723e76f9d6SRichard Lowe 	if (&_DYNAMIC != NULL)
733e76f9d6SRichard Lowe 		(void) atexit(exit_handler);
743e76f9d6SRichard Lowe #elif defined(__sparc)
753e76f9d6SRichard Lowe 	if (exit_handler != NULL)
763e76f9d6SRichard Lowe 		(void) atexit(exit_handler);
773e76f9d6SRichard Lowe #endif
783e76f9d6SRichard Lowe 
793e76f9d6SRichard Lowe 	(void) atexit(_fini);
803e76f9d6SRichard Lowe 
813e76f9d6SRichard Lowe 	_environ = argv + (argc + 1);
823e76f9d6SRichard Lowe 	___Argv = argv;
833e76f9d6SRichard Lowe 
84*4004e4c5SAndy Fiddaman 	/*
85*4004e4c5SAndy Fiddaman 	 * __start_crt_compiler() provides a hook for compilers to perform
86*4004e4c5SAndy Fiddaman 	 * extra initialisation before main() is called. For example, gcc uses
87*4004e4c5SAndy Fiddaman 	 * this to initialise profiling code for objects built with its -pg
88*4004e4c5SAndy Fiddaman 	 * option by linking in an extra object that provides this function.
89*4004e4c5SAndy Fiddaman 	 *
90*4004e4c5SAndy Fiddaman 	 * This mechanism replaces the earlier separate gcrt1.o.
91*4004e4c5SAndy Fiddaman 	 *
92*4004e4c5SAndy Fiddaman 	 * If __start_crt_compiler() returns a non-zero value, then the
93*4004e4c5SAndy Fiddaman 	 * process will exit with that value, without main() being called.
94*4004e4c5SAndy Fiddaman 	 */
95*4004e4c5SAndy Fiddaman 	if (&__start_crt_compiler != NULL)
96*4004e4c5SAndy Fiddaman 		ret = __start_crt_compiler(argc, argv);
973e76f9d6SRichard Lowe 
98*4004e4c5SAndy Fiddaman 	if (ret == 0) {
993e76f9d6SRichard Lowe #if defined(__x86)
100*4004e4c5SAndy Fiddaman 		__fpstart();
1013e76f9d6SRichard Lowe #endif
102*4004e4c5SAndy Fiddaman #if defined(__i386)		/* Not amd64 */
103*4004e4c5SAndy Fiddaman 		/*
104*4004e4c5SAndy Fiddaman 		 * Note that Studio cc(1) sets the _value of the symbol_, that
105*4004e4c5SAndy Fiddaman 		 * is, its address.  Not the value _at_ that address.
106*4004e4c5SAndy Fiddaman 		 */
107*4004e4c5SAndy Fiddaman 		__fsr((uintptr_t)&__fsr_init_value);
1083e76f9d6SRichard Lowe #endif
109*4004e4c5SAndy Fiddaman 		_init();
110*4004e4c5SAndy Fiddaman 		ret = main(argc, argv, _environ);
111*4004e4c5SAndy Fiddaman 	}
1123e76f9d6SRichard Lowe 	exit(ret);
1133e76f9d6SRichard Lowe 	_exit(ret);
1143e76f9d6SRichard Lowe }