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 * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. 15 */ 16 17 /* 18 * That of the CRT startup routine which itself may be implemented in C. 19 */ 20 21 #include <sys/feature_tests.h> 22 #include <sys/types.h> 23 24 #include <stdlib.h> 25 #include <synch.h> 26 #include <unistd.h> 27 28 #pragma weak _DYNAMIC 29 extern uintptr_t _DYNAMIC; 30 31 #pragma weak environ = _environ 32 char **_environ = NULL; 33 char **___Argv = NULL; 34 35 extern int main(int argc, char **argv, char **envp); 36 extern void _init(void); 37 extern void _fini(void); 38 39 #pragma weak __start_crt_compiler 40 extern int __start_crt_compiler(int argc, char **argv); 41 42 #if defined(__x86) 43 int __longdouble_used = 0; 44 extern void __fpstart(void); 45 #endif 46 47 #if defined(__i386) /* Not amd64 */ 48 #pragma weak __fsr_init_value 49 extern long __fsr_init_value; 50 extern void __fsr(uintptr_t); 51 #endif 52 53 54 /* 55 * Defined here for ABI reasons, must match the definition in libc. 56 * If it cannot, a new symbol must be created. 57 */ 58 mutex_t __environ_lock = DEFAULTMUTEX; 59 60 void 61 _start_crt(int argc, char **argv, void (*exit_handler)(void)) 62 { 63 int ret = 0; 64 65 /* 66 * On x86, we check whether we're a dynamic executable to see whether 67 * we'll receive an exit_handler. 68 * 69 * On SPARC, we just need to check whether the handler was NULL. 70 */ 71 #if defined(__x86) 72 if (&_DYNAMIC != NULL) 73 (void) atexit(exit_handler); 74 #elif defined(__sparc) 75 if (exit_handler != NULL) 76 (void) atexit(exit_handler); 77 #endif 78 79 (void) atexit(_fini); 80 81 _environ = argv + (argc + 1); 82 ___Argv = argv; 83 84 /* 85 * __start_crt_compiler() provides a hook for compilers to perform 86 * extra initialisation before main() is called. For example, gcc uses 87 * this to initialise profiling code for objects built with its -pg 88 * option by linking in an extra object that provides this function. 89 * 90 * This mechanism replaces the earlier separate gcrt1.o. 91 * 92 * If __start_crt_compiler() returns a non-zero value, then the 93 * process will exit with that value, without main() being called. 94 */ 95 if (&__start_crt_compiler != NULL) 96 ret = __start_crt_compiler(argc, argv); 97 98 if (ret == 0) { 99 #if defined(__x86) 100 __fpstart(); 101 #endif 102 #if defined(__i386) /* Not amd64 */ 103 /* 104 * Note that Studio cc(1) sets the _value of the symbol_, that 105 * is, its address. Not the value _at_ that address. 106 */ 107 __fsr((uintptr_t)&__fsr_init_value); 108 #endif 109 _init(); 110 ret = main(argc, argv, _environ); 111 } 112 exit(ret); 113 _exit(ret); 114 } 115