xref: /dragonfly/lib/csu/common/initfini.c (revision 73610d44)
1 /*-
2  * Copyright 2012 Konstantin Belousov <kib@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "notes.h"
27 
28 extern int main(int, char **, char **);
29 
30 extern void (*__preinit_array_start []) (int, char **, char **) __dso_hidden;
31 extern void (*__preinit_array_end   []) (int, char **, char **) __dso_hidden;
32 extern void (*__init_array_start    []) (int, char **, char **) __dso_hidden;
33 extern void (*__init_array_end      []) (int, char **, char **) __dso_hidden;
34 extern void (*__fini_array_start    []) (void) __dso_hidden;
35 extern void (*__fini_array_end      []) (void) __dso_hidden;
36 extern void _fini(void);
37 extern void _init(void);
38 
39 extern int _DYNAMIC;
40 #pragma weak _DYNAMIC
41 
42 char **environ;
43 const char *__progname = "";
44 
45 static void
46 finalizer(void)
47 {
48 	void (*fn)(void);
49 	size_t array_size, n;
50 
51 	array_size = __fini_array_end - __fini_array_start;
52 	for (n = array_size; n > 0; n--) {
53 		fn = __fini_array_start[n - 1];
54 		if ((uintptr_t)fn != 0 && (uintptr_t)fn != 1)
55 			(fn)();
56 	}
57 	_fini();
58 }
59 
60 static inline void
61 handle_static_init(int argc, char **argv, char **env)
62 {
63 	void (*fn)(int, char **, char **);
64 	size_t array_size, n;
65 
66 	if (&_DYNAMIC != NULL)
67 		return;
68 
69 	atexit(finalizer);
70 
71 	array_size = __preinit_array_end - __preinit_array_start;
72 	for (n = 0; n < array_size; n++) {
73 		fn = __preinit_array_start[n];
74 		if ((uintptr_t)fn != 0 && (uintptr_t)fn != 1)
75 			fn(argc, argv, env);
76 	}
77 	_init();
78 	array_size = __init_array_end - __init_array_start;
79 	for (n = 0; n < array_size; n++) {
80 		fn = __init_array_start[n];
81 		if ((uintptr_t)fn != 0 && (uintptr_t)fn != 1)
82 			fn(argc, argv, env);
83 	}
84 }
85 
86 static inline void
87 handle_argv(int argc, char *argv[], char **env)
88 {
89 	const char *s;
90 
91 	if (environ == NULL)
92 		environ = env;
93 	if (argc > 0 && argv[0] != NULL) {
94 		__progname = argv[0];
95 		for (s = __progname; *s != '\0'; s++) {
96 			if (*s == '/')
97 				__progname = s + 1;
98                 }
99 	}
100 }
101 
102 static const struct {
103 	int32_t	namesz;
104 	int32_t	descsz;
105 	int32_t	type;
106 	char	name[sizeof(NOTE_VENDOR)];
107 	uint32_t desc;
108 } crt_noinit_tag __attribute__ ((section (NOTE_SECTION),
109     aligned(4))) __attribute__ ((used)) = {
110 	.namesz = sizeof(NOTE_VENDOR),
111 	.descsz = sizeof(uint32_t),
112 	.type = CRT_NOINIT_NOTETYPE,
113 	.name = NOTE_VENDOR,
114 	.desc = 0
115 };
116