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 }
115