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