xref: /llvm-project/compiler-rt/lib/builtins/crtbegin.c (revision 41b83ca559c402d238e303c0ac233180d60dcd57)
1b47beeccSPetr Hosek //===-- crtbegin.c - Start of constructors and destructors ----------------===//
2b47beeccSPetr Hosek //
3b47beeccSPetr Hosek // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4b47beeccSPetr Hosek // See https://llvm.org/LICENSE.txt for license information.
5b47beeccSPetr Hosek // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b47beeccSPetr Hosek //
7b47beeccSPetr Hosek //===----------------------------------------------------------------------===//
8b47beeccSPetr Hosek 
9b47beeccSPetr Hosek #include <stddef.h>
10b47beeccSPetr Hosek 
11*41b83ca5SKazu Hirata #ifndef __has_feature
12*41b83ca5SKazu Hirata # define __has_feature(x) 0
13*41b83ca5SKazu Hirata #endif
14*41b83ca5SKazu Hirata 
156e45fa95SDaniil Kovalev #if __has_feature(ptrauth_init_fini)
166e45fa95SDaniil Kovalev #include <ptrauth.h>
176e45fa95SDaniil Kovalev #endif
186e45fa95SDaniil Kovalev 
19b47beeccSPetr Hosek __attribute__((visibility("hidden"))) void *__dso_handle = &__dso_handle;
20b47beeccSPetr Hosek 
21b47beeccSPetr Hosek #ifdef EH_USE_FRAME_REGISTRY
22b47beeccSPetr Hosek __extension__ static void *__EH_FRAME_LIST__[]
23b47beeccSPetr Hosek     __attribute__((section(".eh_frame"), aligned(sizeof(void *)))) = {};
24b47beeccSPetr Hosek 
25b47beeccSPetr Hosek extern void __register_frame_info(const void *, void *) __attribute__((weak));
26b47beeccSPetr Hosek extern void *__deregister_frame_info(const void *) __attribute__((weak));
27b47beeccSPetr Hosek #endif
28b47beeccSPetr Hosek 
29b47beeccSPetr Hosek #ifndef CRT_HAS_INITFINI_ARRAY
30b47beeccSPetr Hosek typedef void (*fp)(void);
31b47beeccSPetr Hosek 
32b47beeccSPetr Hosek static fp __CTOR_LIST__[]
33b47beeccSPetr Hosek     __attribute__((section(".ctors"), aligned(sizeof(fp)))) = {(fp)-1};
34b47beeccSPetr Hosek extern fp __CTOR_LIST_END__[];
35b47beeccSPetr Hosek #endif
36b47beeccSPetr Hosek 
37b47beeccSPetr Hosek extern void __cxa_finalize(void *) __attribute__((weak));
38b47beeccSPetr Hosek 
39b47beeccSPetr Hosek static void __attribute__((used)) __do_init(void) {
40b47beeccSPetr Hosek   static _Bool __initialized;
41b47beeccSPetr Hosek   if (__builtin_expect(__initialized, 0))
42b47beeccSPetr Hosek     return;
43b47beeccSPetr Hosek   __initialized = 1;
44b47beeccSPetr Hosek 
45b47beeccSPetr Hosek #ifdef EH_USE_FRAME_REGISTRY
46b47beeccSPetr Hosek   static struct { void *p[8]; } __object;
47b47beeccSPetr Hosek   if (__register_frame_info)
48b47beeccSPetr Hosek     __register_frame_info(__EH_FRAME_LIST__, &__object);
49b47beeccSPetr Hosek #endif
50b47beeccSPetr Hosek #ifndef CRT_HAS_INITFINI_ARRAY
51b47beeccSPetr Hosek   const size_t n = __CTOR_LIST_END__ - __CTOR_LIST__ - 1;
52b47beeccSPetr Hosek   for (size_t i = n; i >= 1; i--) __CTOR_LIST__[i]();
53b47beeccSPetr Hosek #endif
54b47beeccSPetr Hosek }
55b47beeccSPetr Hosek 
56b47beeccSPetr Hosek #ifdef CRT_HAS_INITFINI_ARRAY
576e45fa95SDaniil Kovalev #if __has_feature(ptrauth_init_fini)
586e45fa95SDaniil Kovalev // TODO: use __ptrauth-qualified pointers when they are supported on clang side
596e45fa95SDaniil Kovalev #if __has_feature(ptrauth_init_fini_address_discrimination)
606e45fa95SDaniil Kovalev __attribute__((section(".init_array"), used)) static void *__init =
616e45fa95SDaniil Kovalev     ptrauth_sign_constant(&__do_init, ptrauth_key_init_fini_pointer,
626e45fa95SDaniil Kovalev                           ptrauth_blend_discriminator(
636e45fa95SDaniil Kovalev                               &__init, __ptrauth_init_fini_discriminator));
646e45fa95SDaniil Kovalev #else
656e45fa95SDaniil Kovalev __attribute__((section(".init_array"), used)) static void *__init =
666e45fa95SDaniil Kovalev     ptrauth_sign_constant(&__do_init, ptrauth_key_init_fini_pointer,
676e45fa95SDaniil Kovalev                           __ptrauth_init_fini_discriminator);
686e45fa95SDaniil Kovalev #endif
696e45fa95SDaniil Kovalev #else
70b47beeccSPetr Hosek __attribute__((section(".init_array"),
71b47beeccSPetr Hosek                used)) static void (*__init)(void) = __do_init;
726e45fa95SDaniil Kovalev #endif
73b47beeccSPetr Hosek #elif defined(__i386__) || defined(__x86_64__)
74b47beeccSPetr Hosek __asm__(".pushsection .init,\"ax\",@progbits\n\t"
75b47beeccSPetr Hosek         "call __do_init\n\t"
76b47beeccSPetr Hosek         ".popsection");
77b47beeccSPetr Hosek #elif defined(__riscv)
78b47beeccSPetr Hosek __asm__(".pushsection .init,\"ax\",%progbits\n\t"
79b47beeccSPetr Hosek         "call __do_init\n\t"
80b47beeccSPetr Hosek         ".popsection");
81b47beeccSPetr Hosek #elif defined(__arm__) || defined(__aarch64__)
82b47beeccSPetr Hosek __asm__(".pushsection .init,\"ax\",%progbits\n\t"
83b47beeccSPetr Hosek         "bl __do_init\n\t"
84b47beeccSPetr Hosek         ".popsection");
85b47beeccSPetr Hosek #elif defined(__mips__)
86b47beeccSPetr Hosek __asm__(".pushsection .init,\"ax\",@progbits\n\t"
87b47beeccSPetr Hosek         "jal __do_init\n\t"
88b47beeccSPetr Hosek         ".popsection");
89b47beeccSPetr Hosek #elif defined(__powerpc__) || defined(__powerpc64__)
90b47beeccSPetr Hosek __asm__(".pushsection .init,\"ax\",@progbits\n\t"
91b47beeccSPetr Hosek         "bl __do_init\n\t"
92b47beeccSPetr Hosek         "nop\n\t"
93b47beeccSPetr Hosek         ".popsection");
94b47beeccSPetr Hosek #elif defined(__sparc__)
95b47beeccSPetr Hosek __asm__(".pushsection .init,\"ax\",@progbits\n\t"
96b47beeccSPetr Hosek         "call __do_init\n\t"
97b47beeccSPetr Hosek         ".popsection");
98b47beeccSPetr Hosek #else
99b47beeccSPetr Hosek #error "crtbegin without .init_fini array unimplemented for this architecture"
100b47beeccSPetr Hosek #endif // CRT_HAS_INITFINI_ARRAY
101b47beeccSPetr Hosek 
102b47beeccSPetr Hosek #ifndef CRT_HAS_INITFINI_ARRAY
103b47beeccSPetr Hosek static fp __DTOR_LIST__[]
104b47beeccSPetr Hosek     __attribute__((section(".dtors"), aligned(sizeof(fp)))) = {(fp)-1};
105b47beeccSPetr Hosek extern fp __DTOR_LIST_END__[];
106b47beeccSPetr Hosek #endif
107b47beeccSPetr Hosek 
108b47beeccSPetr Hosek static void __attribute__((used)) __do_fini(void) {
109b47beeccSPetr Hosek   static _Bool __finalized;
110b47beeccSPetr Hosek   if (__builtin_expect(__finalized, 0))
111b47beeccSPetr Hosek     return;
112b47beeccSPetr Hosek   __finalized = 1;
113b47beeccSPetr Hosek 
114b47beeccSPetr Hosek   if (__cxa_finalize)
115b47beeccSPetr Hosek     __cxa_finalize(__dso_handle);
116b47beeccSPetr Hosek 
117b47beeccSPetr Hosek #ifndef CRT_HAS_INITFINI_ARRAY
118b47beeccSPetr Hosek   const size_t n = __DTOR_LIST_END__ - __DTOR_LIST__ - 1;
119b47beeccSPetr Hosek   for (size_t i = 1; i <= n; i++) __DTOR_LIST__[i]();
120b47beeccSPetr Hosek #endif
121b47beeccSPetr Hosek #ifdef EH_USE_FRAME_REGISTRY
122b47beeccSPetr Hosek   if (__deregister_frame_info)
123b47beeccSPetr Hosek     __deregister_frame_info(__EH_FRAME_LIST__);
124b47beeccSPetr Hosek #endif
125b47beeccSPetr Hosek }
126b47beeccSPetr Hosek 
127b47beeccSPetr Hosek #ifdef CRT_HAS_INITFINI_ARRAY
1286e45fa95SDaniil Kovalev #if __has_feature(ptrauth_init_fini)
1296e45fa95SDaniil Kovalev // TODO: use __ptrauth-qualified pointers when they are supported on clang side
1306e45fa95SDaniil Kovalev #if __has_feature(ptrauth_init_fini_address_discrimination)
1316e45fa95SDaniil Kovalev __attribute__((section(".fini_array"), used)) static void *__fini =
1326e45fa95SDaniil Kovalev     ptrauth_sign_constant(&__do_fini, ptrauth_key_init_fini_pointer,
1336e45fa95SDaniil Kovalev                           ptrauth_blend_discriminator(
1346e45fa95SDaniil Kovalev                               &__fini, __ptrauth_init_fini_discriminator));
1356e45fa95SDaniil Kovalev #else
1366e45fa95SDaniil Kovalev __attribute__((section(".fini_array"), used)) static void *__fini =
1376e45fa95SDaniil Kovalev     ptrauth_sign_constant(&__do_fini, ptrauth_key_init_fini_pointer,
1386e45fa95SDaniil Kovalev                           __ptrauth_init_fini_discriminator);
1396e45fa95SDaniil Kovalev #endif
1406e45fa95SDaniil Kovalev #else
141b47beeccSPetr Hosek __attribute__((section(".fini_array"),
142b47beeccSPetr Hosek                used)) static void (*__fini)(void) = __do_fini;
1436e45fa95SDaniil Kovalev #endif
144b47beeccSPetr Hosek #elif defined(__i386__) || defined(__x86_64__)
145b47beeccSPetr Hosek __asm__(".pushsection .fini,\"ax\",@progbits\n\t"
146b47beeccSPetr Hosek         "call __do_fini\n\t"
147b47beeccSPetr Hosek         ".popsection");
148b47beeccSPetr Hosek #elif defined(__arm__) || defined(__aarch64__)
149b47beeccSPetr Hosek __asm__(".pushsection .fini,\"ax\",%progbits\n\t"
150b47beeccSPetr Hosek         "bl __do_fini\n\t"
151b47beeccSPetr Hosek         ".popsection");
152b47beeccSPetr Hosek #elif defined(__mips__)
153b47beeccSPetr Hosek __asm__(".pushsection .fini,\"ax\",@progbits\n\t"
154b47beeccSPetr Hosek         "jal __do_fini\n\t"
155b47beeccSPetr Hosek         ".popsection");
156b47beeccSPetr Hosek #elif defined(__powerpc__) || defined(__powerpc64__)
157b47beeccSPetr Hosek __asm__(".pushsection .fini,\"ax\",@progbits\n\t"
158b47beeccSPetr Hosek         "bl __do_fini\n\t"
159b47beeccSPetr Hosek         "nop\n\t"
160b47beeccSPetr Hosek         ".popsection");
161b47beeccSPetr Hosek #elif defined(__riscv)
162b47beeccSPetr Hosek __asm__(".pushsection .fini,\"ax\",@progbits\n\t"
163b47beeccSPetr Hosek         "call __do_fini\n\t"
164b47beeccSPetr Hosek         ".popsection");
165b47beeccSPetr Hosek #elif defined(__sparc__)
166b47beeccSPetr Hosek __asm__(".pushsection .fini,\"ax\",@progbits\n\t"
167b47beeccSPetr Hosek         "call __do_fini\n\t"
168b47beeccSPetr Hosek         ".popsection");
169b47beeccSPetr Hosek #else
170b47beeccSPetr Hosek #error "crtbegin without .init_fini array unimplemented for this architecture"
171b47beeccSPetr Hosek #endif  // CRT_HAS_INIT_FINI_ARRAY
172