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
25extern void __register_frame_info(const void *, void *) __attribute__((weak));
26extern void *__deregister_frame_info(const void *) __attribute__((weak));
27#endif
28
29#ifndef CRT_HAS_INITFINI_ARRAY
30typedef void (*fp)(void);
31
32static fp __CTOR_LIST__[]
33 __attribute__((section(".ctors"), aligned(sizeof(fp)))) = {(fp)-1};
34extern fp __CTOR_LIST_END__[];
35#endif
36
37extern void __cxa_finalize(void *) __attribute__((weak));
38
39static 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# elif __has_feature(ptrauth_calls)
70# ifdef __aarch64__
71// If ptrauth_init_fini feature is not present, compiler emits raw unsigned
72// pointers in .init_array. Use inline assembly to avoid implicit signing of
73// __do_init function pointer with ptrauth_calls enabled.
74__asm__(".pushsection .init_array,\"aw\",@init_array\n\t"
75 ".xword __do_init\n\t"
76 ".popsection");
77# else
78# error "ptrauth_calls is only supported for AArch64"
79# endif
80# else
81__attribute__((section(".init_array"),
82 used)) static void (*__init)(void) = __do_init;
83# endif
84#elif defined(__i386__) || defined(__x86_64__)
85__asm__(".pushsection .init,\"ax\",@progbits\n\t"
86 "call __do_init\n\t"
87 ".popsection");
88#elif defined(__riscv)
89__asm__(".pushsection .init,\"ax\",%progbits\n\t"
90 "call __do_init\n\t"
91 ".popsection");
92#elif defined(__arm__) || defined(__aarch64__)
93__asm__(".pushsection .init,\"ax\",%progbits\n\t"
94 "bl __do_init\n\t"
95 ".popsection");
96#elif defined(__mips__)
97__asm__(".pushsection .init,\"ax\",@progbits\n\t"
98 "jal __do_init\n\t"
99 ".popsection");
100#elif defined(__powerpc__) || defined(__powerpc64__)
101__asm__(".pushsection .init,\"ax\",@progbits\n\t"
102 "bl __do_init\n\t"
103 "nop\n\t"
104 ".popsection");
105#elif defined(__sparc__)
106__asm__(".pushsection .init,\"ax\",@progbits\n\t"
107 "call __do_init\n\t"
108 ".popsection");
109#else
110#error "crtbegin without .init_fini array unimplemented for this architecture"
111#endif // CRT_HAS_INITFINI_ARRAY
112
113#ifndef CRT_HAS_INITFINI_ARRAY
114static fp __DTOR_LIST__[]
115 __attribute__((section(".dtors"), aligned(sizeof(fp)))) = {(fp)-1};
116extern fp __DTOR_LIST_END__[];
117#endif
118
119static void __attribute__((used)) __do_fini(void) {
120 static _Bool __finalized;
121 if (__builtin_expect(__finalized, 0))
122 return;
123 __finalized = 1;
124
125 if (__cxa_finalize)
126 __cxa_finalize(__dso_handle);
127
128#ifndef CRT_HAS_INITFINI_ARRAY
129 const size_t n = __DTOR_LIST_END__ - __DTOR_LIST__ - 1;
130 for (size_t i = 1; i <= n; i++) __DTOR_LIST__[i]();
131#endif
132#ifdef EH_USE_FRAME_REGISTRY
133 if (__deregister_frame_info)
134 __deregister_frame_info(__EH_FRAME_LIST__);
135#endif
136}
137
138#ifdef CRT_HAS_INITFINI_ARRAY
139# if __has_feature(ptrauth_init_fini)
140// TODO: use __ptrauth-qualified pointers when they are supported on clang side
141# if __has_feature(ptrauth_init_fini_address_discrimination)
142__attribute__((section(".fini_array"), used)) static void *__fini =
143 ptrauth_sign_constant(&__do_fini, ptrauth_key_init_fini_pointer,
144 ptrauth_blend_discriminator(
145 &__fini, __ptrauth_init_fini_discriminator));
146# else
147__attribute__((section(".fini_array"), used)) static void *__fini =
148 ptrauth_sign_constant(&__do_fini, ptrauth_key_init_fini_pointer,
149 __ptrauth_init_fini_discriminator);
150# endif
151# elif __has_feature(ptrauth_calls)
152# ifdef __aarch64__
153// If ptrauth_init_fini feature is not present, compiler emits raw unsigned
154// pointers in .fini_array. Use inline assembly to avoid implicit signing of
155// __do_fini function pointer with ptrauth_calls enabled.
156__asm__(".pushsection .fini_array,\"aw\",@fini_array\n\t"
157 ".xword __do_fini\n\t"
158 ".popsection");
159# else
160# error "ptrauth_calls is only supported for AArch64"
161# endif
162# else
163__attribute__((section(".fini_array"),
164 used)) static void (*__fini)(void) = __do_fini;
165# endif
166#elif defined(__i386__) || defined(__x86_64__)
167__asm__(".pushsection .fini,\"ax\",@progbits\n\t"
168 "call __do_fini\n\t"
169 ".popsection");
170#elif defined(__arm__) || defined(__aarch64__)
171__asm__(".pushsection .fini,\"ax\",%progbits\n\t"
172 "bl __do_fini\n\t"
173 ".popsection");
174#elif defined(__mips__)
175__asm__(".pushsection .fini,\"ax\",@progbits\n\t"
176 "jal __do_fini\n\t"
177 ".popsection");
178#elif defined(__powerpc__) || defined(__powerpc64__)
179__asm__(".pushsection .fini,\"ax\",@progbits\n\t"
180 "bl __do_fini\n\t"
181 "nop\n\t"
182 ".popsection");
183#elif defined(__riscv)
184__asm__(".pushsection .fini,\"ax\",@progbits\n\t"
185 "call __do_fini\n\t"
186 ".popsection");
187#elif defined(__sparc__)
188__asm__(".pushsection .fini,\"ax\",@progbits\n\t"
189 "call __do_fini\n\t"
190 ".popsection");
191#else
192#error "crtbegin without .init_fini array unimplemented for this architecture"
193#endif // CRT_HAS_INIT_FINI_ARRAY
194

source code of compiler-rt/lib/builtins/crtbegin.c