1 | //===-- crtbegin.c - Start of constructors and destructors ----------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include <stddef.h> |
10 | |
11 | #ifndef __has_feature |
12 | # define __has_feature(x) 0 |
13 | #endif |
14 | |
15 | #if __has_feature(ptrauth_init_fini) |
16 | #include <ptrauth.h> |
17 | #endif |
18 | |
19 | __attribute__((visibility("hidden" ))) void *__dso_handle = &__dso_handle; |
20 | |
21 | #ifdef EH_USE_FRAME_REGISTRY |
22 | __extension__ static void *__EH_FRAME_LIST__[] |
23 | __attribute__((section(".eh_frame" ), aligned(sizeof(void *)))) = {}; |
24 | |
25 | extern void __register_frame_info(const void *, void *) __attribute__((weak)); |
26 | extern void *__deregister_frame_info(const void *) __attribute__((weak)); |
27 | #endif |
28 | |
29 | #ifndef CRT_HAS_INITFINI_ARRAY |
30 | typedef void (*fp)(void); |
31 | |
32 | static fp __CTOR_LIST__[] |
33 | __attribute__((section(".ctors" ), aligned(sizeof(fp)))) = {(fp)-1}; |
34 | extern fp __CTOR_LIST_END__[]; |
35 | #endif |
36 | |
37 | extern void __cxa_finalize(void *) __attribute__((weak)); |
38 | |
39 | static void __attribute__((used)) __do_init(void) { |
40 | static _Bool __initialized; |
41 | if (__builtin_expect(__initialized, 0)) |
42 | return; |
43 | __initialized = 1; |
44 | |
45 | #ifdef EH_USE_FRAME_REGISTRY |
46 | static struct { void *p[8]; } __object; |
47 | if (__register_frame_info) |
48 | __register_frame_info(__EH_FRAME_LIST__, &__object); |
49 | #endif |
50 | #ifndef CRT_HAS_INITFINI_ARRAY |
51 | const size_t n = __CTOR_LIST_END__ - __CTOR_LIST__ - 1; |
52 | for (size_t i = n; i >= 1; i--) __CTOR_LIST__[i](); |
53 | #endif |
54 | } |
55 | |
56 | #ifdef CRT_HAS_INITFINI_ARRAY |
57 | #if __has_feature(ptrauth_init_fini) |
58 | // TODO: use __ptrauth-qualified pointers when they are supported on clang side |
59 | #if __has_feature(ptrauth_init_fini_address_discrimination) |
60 | __attribute__((section(".init_array" ), used)) static void *__init = |
61 | ptrauth_sign_constant(&__do_init, ptrauth_key_init_fini_pointer, |
62 | ptrauth_blend_discriminator( |
63 | &__init, __ptrauth_init_fini_discriminator)); |
64 | #else |
65 | __attribute__((section(".init_array" ), used)) static void *__init = |
66 | ptrauth_sign_constant(&__do_init, ptrauth_key_init_fini_pointer, |
67 | __ptrauth_init_fini_discriminator); |
68 | #endif |
69 | #else |
70 | __attribute__((section(".init_array" ), |
71 | used)) static void (*__init)(void) = __do_init; |
72 | #endif |
73 | #elif defined(__i386__) || defined(__x86_64__) |
74 | __asm__(".pushsection .init,\"ax\",@progbits\n\t" |
75 | "call __do_init\n\t" |
76 | ".popsection" ); |
77 | #elif defined(__riscv) |
78 | __asm__(".pushsection .init,\"ax\",%progbits\n\t" |
79 | "call __do_init\n\t" |
80 | ".popsection" ); |
81 | #elif defined(__arm__) || defined(__aarch64__) |
82 | __asm__(".pushsection .init,\"ax\",%progbits\n\t" |
83 | "bl __do_init\n\t" |
84 | ".popsection" ); |
85 | #elif defined(__mips__) |
86 | __asm__(".pushsection .init,\"ax\",@progbits\n\t" |
87 | "jal __do_init\n\t" |
88 | ".popsection" ); |
89 | #elif defined(__powerpc__) || defined(__powerpc64__) |
90 | __asm__(".pushsection .init,\"ax\",@progbits\n\t" |
91 | "bl __do_init\n\t" |
92 | "nop\n\t" |
93 | ".popsection" ); |
94 | #elif defined(__sparc__) |
95 | __asm__(".pushsection .init,\"ax\",@progbits\n\t" |
96 | "call __do_init\n\t" |
97 | ".popsection" ); |
98 | #else |
99 | #error "crtbegin without .init_fini array unimplemented for this architecture" |
100 | #endif // CRT_HAS_INITFINI_ARRAY |
101 | |
102 | #ifndef CRT_HAS_INITFINI_ARRAY |
103 | static fp __DTOR_LIST__[] |
104 | __attribute__((section(".dtors" ), aligned(sizeof(fp)))) = {(fp)-1}; |
105 | extern fp __DTOR_LIST_END__[]; |
106 | #endif |
107 | |
108 | static void __attribute__((used)) __do_fini(void) { |
109 | static _Bool __finalized; |
110 | if (__builtin_expect(__finalized, 0)) |
111 | return; |
112 | __finalized = 1; |
113 | |
114 | if (__cxa_finalize) |
115 | __cxa_finalize(__dso_handle); |
116 | |
117 | #ifndef CRT_HAS_INITFINI_ARRAY |
118 | const size_t n = __DTOR_LIST_END__ - __DTOR_LIST__ - 1; |
119 | for (size_t i = 1; i <= n; i++) __DTOR_LIST__[i](); |
120 | #endif |
121 | #ifdef EH_USE_FRAME_REGISTRY |
122 | if (__deregister_frame_info) |
123 | __deregister_frame_info(__EH_FRAME_LIST__); |
124 | #endif |
125 | } |
126 | |
127 | #ifdef CRT_HAS_INITFINI_ARRAY |
128 | #if __has_feature(ptrauth_init_fini) |
129 | // TODO: use __ptrauth-qualified pointers when they are supported on clang side |
130 | #if __has_feature(ptrauth_init_fini_address_discrimination) |
131 | __attribute__((section(".fini_array" ), used)) static void *__fini = |
132 | ptrauth_sign_constant(&__do_fini, ptrauth_key_init_fini_pointer, |
133 | ptrauth_blend_discriminator( |
134 | &__fini, __ptrauth_init_fini_discriminator)); |
135 | #else |
136 | __attribute__((section(".fini_array" ), used)) static void *__fini = |
137 | ptrauth_sign_constant(&__do_fini, ptrauth_key_init_fini_pointer, |
138 | __ptrauth_init_fini_discriminator); |
139 | #endif |
140 | #else |
141 | __attribute__((section(".fini_array" ), |
142 | used)) static void (*__fini)(void) = __do_fini; |
143 | #endif |
144 | #elif defined(__i386__) || defined(__x86_64__) |
145 | __asm__(".pushsection .fini,\"ax\",@progbits\n\t" |
146 | "call __do_fini\n\t" |
147 | ".popsection" ); |
148 | #elif defined(__arm__) || defined(__aarch64__) |
149 | __asm__(".pushsection .fini,\"ax\",%progbits\n\t" |
150 | "bl __do_fini\n\t" |
151 | ".popsection" ); |
152 | #elif defined(__mips__) |
153 | __asm__(".pushsection .fini,\"ax\",@progbits\n\t" |
154 | "jal __do_fini\n\t" |
155 | ".popsection" ); |
156 | #elif defined(__powerpc__) || defined(__powerpc64__) |
157 | __asm__(".pushsection .fini,\"ax\",@progbits\n\t" |
158 | "bl __do_fini\n\t" |
159 | "nop\n\t" |
160 | ".popsection" ); |
161 | #elif defined(__riscv) |
162 | __asm__(".pushsection .fini,\"ax\",@progbits\n\t" |
163 | "call __do_fini\n\t" |
164 | ".popsection" ); |
165 | #elif defined(__sparc__) |
166 | __asm__(".pushsection .fini,\"ax\",@progbits\n\t" |
167 | "call __do_fini\n\t" |
168 | ".popsection" ); |
169 | #else |
170 | #error "crtbegin without .init_fini array unimplemented for this architecture" |
171 | #endif // CRT_HAS_INIT_FINI_ARRAY |
172 | |