xref: /illumos-gate/usr/src/lib/crt/common/common-crt.c (revision e153cda9f9660e385e8f468253f80e59f5d454d7)
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 }
101