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