1*3e76f9d6SRichard Lowe /* 2*3e76f9d6SRichard Lowe * This file and its contents are supplied under the terms of the 3*3e76f9d6SRichard Lowe * Common Development and Distribution License ("CDDL"), version 1.0. 4*3e76f9d6SRichard Lowe * You may only use this file in accordance with the terms of version 5*3e76f9d6SRichard Lowe * 1.0 of the CDDL. 6*3e76f9d6SRichard Lowe * 7*3e76f9d6SRichard Lowe * A full copy of the text of the CDDL should have accompanied this 8*3e76f9d6SRichard Lowe * source. A copy of the CDDL is also available via the Internet at 9*3e76f9d6SRichard Lowe * http://www.illumos.org/license/CDDL. 10*3e76f9d6SRichard Lowe */ 11*3e76f9d6SRichard Lowe 12*3e76f9d6SRichard Lowe /* 13*3e76f9d6SRichard Lowe * Copyright 2016, Richard Lowe. 14*3e76f9d6SRichard Lowe */ 15*3e76f9d6SRichard Lowe 16*3e76f9d6SRichard Lowe /* 17*3e76f9d6SRichard Lowe * That of the CRT startup routine which itself may be implemented in C. 18*3e76f9d6SRichard Lowe */ 19*3e76f9d6SRichard Lowe 20*3e76f9d6SRichard Lowe #include <sys/feature_tests.h> 21*3e76f9d6SRichard Lowe #include <sys/types.h> 22*3e76f9d6SRichard Lowe 23*3e76f9d6SRichard Lowe #include <stdlib.h> 24*3e76f9d6SRichard Lowe #include <synch.h> 25*3e76f9d6SRichard Lowe #include <unistd.h> 26*3e76f9d6SRichard Lowe 27*3e76f9d6SRichard Lowe #pragma weak _DYNAMIC 28*3e76f9d6SRichard Lowe extern uintptr_t _DYNAMIC; 29*3e76f9d6SRichard Lowe 30*3e76f9d6SRichard Lowe #pragma weak environ = _environ 31*3e76f9d6SRichard Lowe char **_environ = NULL; 32*3e76f9d6SRichard Lowe char **___Argv = NULL; 33*3e76f9d6SRichard Lowe 34*3e76f9d6SRichard Lowe extern int main(int argc, char **argv, char **envp); 35*3e76f9d6SRichard Lowe extern void _init(void); 36*3e76f9d6SRichard Lowe extern void _fini(void); 37*3e76f9d6SRichard Lowe 38*3e76f9d6SRichard Lowe #pragma weak _start_crt_compiler 39*3e76f9d6SRichard Lowe extern void _start_crt_compiler(int argc, char **argv); 40*3e76f9d6SRichard Lowe 41*3e76f9d6SRichard Lowe #if defined(__x86) 42*3e76f9d6SRichard Lowe int __longdouble_used = 0; 43*3e76f9d6SRichard Lowe extern void __fpstart(void); 44*3e76f9d6SRichard Lowe #endif 45*3e76f9d6SRichard Lowe 46*3e76f9d6SRichard Lowe #if defined(__i386) /* Not amd64 */ 47*3e76f9d6SRichard Lowe #pragma weak __fsr_init_value 48*3e76f9d6SRichard Lowe extern long __fsr_init_value; 49*3e76f9d6SRichard Lowe extern void __fsr(uintptr_t); 50*3e76f9d6SRichard Lowe #endif 51*3e76f9d6SRichard Lowe 52*3e76f9d6SRichard Lowe 53*3e76f9d6SRichard Lowe /* 54*3e76f9d6SRichard Lowe * Defined here for ABI reasons, must match the definition in libc. 55*3e76f9d6SRichard Lowe * If it cannot, a new symbol must be created. 56*3e76f9d6SRichard Lowe */ 57*3e76f9d6SRichard Lowe mutex_t __environ_lock = DEFAULTMUTEX; 58*3e76f9d6SRichard Lowe 59*3e76f9d6SRichard Lowe void 60*3e76f9d6SRichard Lowe _start_crt(int argc, char **argv, void (*exit_handler)(void)) 61*3e76f9d6SRichard Lowe { 62*3e76f9d6SRichard Lowe int ret = 0; 63*3e76f9d6SRichard Lowe 64*3e76f9d6SRichard Lowe /* 65*3e76f9d6SRichard Lowe * On x86, we check whether we're a dynamic executable to see whether 66*3e76f9d6SRichard Lowe * we'll receive an exit_handler. 67*3e76f9d6SRichard Lowe * 68*3e76f9d6SRichard Lowe * On SPARC, we just need to check whether the handler was NULL. 69*3e76f9d6SRichard Lowe */ 70*3e76f9d6SRichard Lowe #if defined(__x86) 71*3e76f9d6SRichard Lowe if (&_DYNAMIC != NULL) 72*3e76f9d6SRichard Lowe (void) atexit(exit_handler); 73*3e76f9d6SRichard Lowe #elif defined(__sparc) 74*3e76f9d6SRichard Lowe if (exit_handler != NULL) 75*3e76f9d6SRichard Lowe (void) atexit(exit_handler); 76*3e76f9d6SRichard Lowe #endif 77*3e76f9d6SRichard Lowe 78*3e76f9d6SRichard Lowe (void) atexit(_fini); 79*3e76f9d6SRichard Lowe 80*3e76f9d6SRichard Lowe _environ = argv + (argc + 1); 81*3e76f9d6SRichard Lowe ___Argv = argv; 82*3e76f9d6SRichard Lowe 83*3e76f9d6SRichard Lowe if (&_start_crt_compiler != NULL) 84*3e76f9d6SRichard Lowe _start_crt_compiler(argc, argv); 85*3e76f9d6SRichard Lowe 86*3e76f9d6SRichard Lowe #if defined(__x86) 87*3e76f9d6SRichard Lowe __fpstart(); 88*3e76f9d6SRichard Lowe #endif 89*3e76f9d6SRichard Lowe #if defined(__i386) /* Not amd64 */ 90*3e76f9d6SRichard Lowe /* 91*3e76f9d6SRichard Lowe * Note that Studio cc(1) sets the _value of the symbol_, that is, its 92*3e76f9d6SRichard Lowe * address. Not the value _at_ that address. 93*3e76f9d6SRichard Lowe */ 94*3e76f9d6SRichard Lowe __fsr((uintptr_t)&__fsr_init_value); 95*3e76f9d6SRichard Lowe #endif 96*3e76f9d6SRichard Lowe _init(); 97*3e76f9d6SRichard Lowe ret = main(argc, argv, _environ); 98*3e76f9d6SRichard Lowe exit(ret); 99*3e76f9d6SRichard Lowe _exit(ret); 100*3e76f9d6SRichard Lowe } 101