194 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#include <stddef.h>10 11#ifndef __has_feature12# define __has_feature(x) 013#endif14 15#if __has_feature(ptrauth_init_fini)16#include <ptrauth.h>17#endif18 19__attribute__((visibility("hidden"))) void *__dso_handle = &__dso_handle;20 21#ifdef EH_USE_FRAME_REGISTRY22__extension__ static void *const __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#endif28 29#ifndef CRT_HAS_INITFINI_ARRAY30typedef void (*fp)(void);31 32static fp __CTOR_LIST__[]33 __attribute__((section(".ctors"), aligned(sizeof(fp)))) = {(fp)-1};34extern fp __CTOR_LIST_END__[];35#endif36 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_REGISTRY46 static struct { void *p[8]; } __object;47 if (__register_frame_info)48 __register_frame_info(__EH_FRAME_LIST__, &__object);49#endif50#ifndef CRT_HAS_INITFINI_ARRAY51 const size_t n = __CTOR_LIST_END__ - __CTOR_LIST__ - 1;52 for (size_t i = n; i >= 1; i--) __CTOR_LIST__[i]();53#endif54}55 56#ifdef CRT_HAS_INITFINI_ARRAY57# if __has_feature(ptrauth_init_fini)58// TODO: use __ptrauth-qualified pointers when they are supported on clang side59# 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# else65__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# endif69# elif __has_feature(ptrauth_calls)70# ifdef __aarch64__71// If ptrauth_init_fini feature is not present, compiler emits raw unsigned72// pointers in .init_array. Use inline assembly to avoid implicit signing of73// __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# else78# error "ptrauth_calls is only supported for AArch64"79# endif80# else81__attribute__((section(".init_array"),82 used)) static void (*__init)(void) = __do_init;83# endif84#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#else110#error "crtbegin without .init_fini array unimplemented for this architecture"111#endif // CRT_HAS_INITFINI_ARRAY112 113#ifndef CRT_HAS_INITFINI_ARRAY114static fp __DTOR_LIST__[]115 __attribute__((section(".dtors"), aligned(sizeof(fp)))) = {(fp)-1};116extern fp __DTOR_LIST_END__[];117#endif118 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_ARRAY129 const size_t n = __DTOR_LIST_END__ - __DTOR_LIST__ - 1;130 for (size_t i = 1; i <= n; i++) __DTOR_LIST__[i]();131#endif132#ifdef EH_USE_FRAME_REGISTRY133 if (__deregister_frame_info)134 __deregister_frame_info(__EH_FRAME_LIST__);135#endif136}137 138#ifdef CRT_HAS_INITFINI_ARRAY139# if __has_feature(ptrauth_init_fini)140// TODO: use __ptrauth-qualified pointers when they are supported on clang side141# 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# else147__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# endif151# elif __has_feature(ptrauth_calls)152# ifdef __aarch64__153// If ptrauth_init_fini feature is not present, compiler emits raw unsigned154// pointers in .fini_array. Use inline assembly to avoid implicit signing of155// __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# else160# error "ptrauth_calls is only supported for AArch64"161# endif162# else163__attribute__((section(".fini_array"),164 used)) static void (*__fini)(void) = __do_fini;165# endif166#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#else192#error "crtbegin without .init_fini array unimplemented for this architecture"193#endif // CRT_HAS_INIT_FINI_ARRAY194