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