2019-05-01 02:13:22 +08:00
|
|
|
//===-- crtbegin.c - Start of constructors and destructors ----------------===//
|
|
|
|
//
|
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include <stddef.h>
|
|
|
|
|
|
|
|
__attribute__((visibility("hidden"))) void *__dso_handle = &__dso_handle;
|
|
|
|
|
Fix include guard and properly order __deregister_frame_info.
Summary:
This patch fixes two problems with the crtbegin.c as written:
1. In do_init, register_frame_info is not guarded by a #define, but in
do_fini, deregister_frame_info is guarded by #ifndef
CRT_HAS_INITFINI_ARRAY. Thus when CRT_HAS_INITFINI_ARRAY is not
defined, frames are registered but then never deregistered.
The frame registry mechanism builds a linked-list from the .so's
static variable do_init.object, and when the .so is unloaded, this
memory becomes invalid and should be deregistered.
Further, libgcc's crtbegin treats the frame registry as independent
from the initfini array mechanism.
This patch fixes this by adding a new #define,
"EH_USE_FRAME_INFO_REGISTRY", which is set by the cmake option
COMPILER_RT_CRT_USE_EH_FRAME_REGISTRY Currently, do_init calls
register_frame_info, and then calls the binary's constructors. This
allows constructors to safely use libunwind. However, do_fini calls
deregister_frame_info and then calls the binary's destructors. This
prevents destructors from safely using libunwind.
This patch also switches that ordering, so that destructors can safely
use libunwind. As it happens, this is a fairly common scenario for
thread sanitizer.
2019-11-09 07:51:35 +08:00
|
|
|
#ifdef EH_USE_FRAME_REGISTRY
|
2019-05-01 14:25:21 +08:00
|
|
|
__extension__ static void *__EH_FRAME_LIST__[]
|
2019-05-01 02:13:22 +08:00
|
|
|
__attribute__((section(".eh_frame"), aligned(sizeof(void *)))) = {};
|
|
|
|
|
|
|
|
extern void __register_frame_info(const void *, void *) __attribute__((weak));
|
|
|
|
extern void *__deregister_frame_info(const void *) __attribute__((weak));
|
Fix include guard and properly order __deregister_frame_info.
Summary:
This patch fixes two problems with the crtbegin.c as written:
1. In do_init, register_frame_info is not guarded by a #define, but in
do_fini, deregister_frame_info is guarded by #ifndef
CRT_HAS_INITFINI_ARRAY. Thus when CRT_HAS_INITFINI_ARRAY is not
defined, frames are registered but then never deregistered.
The frame registry mechanism builds a linked-list from the .so's
static variable do_init.object, and when the .so is unloaded, this
memory becomes invalid and should be deregistered.
Further, libgcc's crtbegin treats the frame registry as independent
from the initfini array mechanism.
This patch fixes this by adding a new #define,
"EH_USE_FRAME_INFO_REGISTRY", which is set by the cmake option
COMPILER_RT_CRT_USE_EH_FRAME_REGISTRY Currently, do_init calls
register_frame_info, and then calls the binary's constructors. This
allows constructors to safely use libunwind. However, do_fini calls
deregister_frame_info and then calls the binary's destructors. This
prevents destructors from safely using libunwind.
This patch also switches that ordering, so that destructors can safely
use libunwind. As it happens, this is a fairly common scenario for
thread sanitizer.
2019-11-09 07:51:35 +08:00
|
|
|
#endif
|
2019-05-01 02:13:22 +08:00
|
|
|
|
|
|
|
#ifndef CRT_HAS_INITFINI_ARRAY
|
|
|
|
typedef void (*fp)(void);
|
|
|
|
|
|
|
|
static fp __CTOR_LIST__[]
|
|
|
|
__attribute__((section(".ctors"), aligned(sizeof(fp)))) = {(fp)-1};
|
|
|
|
extern fp __CTOR_LIST_END__[];
|
|
|
|
#endif
|
|
|
|
|
|
|
|
extern void __cxa_finalize(void *) __attribute__((weak));
|
|
|
|
|
|
|
|
static void __attribute__((used)) __do_init() {
|
|
|
|
static _Bool __initialized;
|
|
|
|
if (__builtin_expect(__initialized, 0))
|
|
|
|
return;
|
|
|
|
__initialized = 1;
|
|
|
|
|
Fix include guard and properly order __deregister_frame_info.
Summary:
This patch fixes two problems with the crtbegin.c as written:
1. In do_init, register_frame_info is not guarded by a #define, but in
do_fini, deregister_frame_info is guarded by #ifndef
CRT_HAS_INITFINI_ARRAY. Thus when CRT_HAS_INITFINI_ARRAY is not
defined, frames are registered but then never deregistered.
The frame registry mechanism builds a linked-list from the .so's
static variable do_init.object, and when the .so is unloaded, this
memory becomes invalid and should be deregistered.
Further, libgcc's crtbegin treats the frame registry as independent
from the initfini array mechanism.
This patch fixes this by adding a new #define,
"EH_USE_FRAME_INFO_REGISTRY", which is set by the cmake option
COMPILER_RT_CRT_USE_EH_FRAME_REGISTRY Currently, do_init calls
register_frame_info, and then calls the binary's constructors. This
allows constructors to safely use libunwind. However, do_fini calls
deregister_frame_info and then calls the binary's destructors. This
prevents destructors from safely using libunwind.
This patch also switches that ordering, so that destructors can safely
use libunwind. As it happens, this is a fairly common scenario for
thread sanitizer.
2019-11-09 07:51:35 +08:00
|
|
|
#ifdef EH_USE_FRAME_REGISTRY
|
2019-05-01 02:13:22 +08:00
|
|
|
static struct { void *p[8]; } __object;
|
|
|
|
if (__register_frame_info)
|
|
|
|
__register_frame_info(__EH_FRAME_LIST__, &__object);
|
Fix include guard and properly order __deregister_frame_info.
Summary:
This patch fixes two problems with the crtbegin.c as written:
1. In do_init, register_frame_info is not guarded by a #define, but in
do_fini, deregister_frame_info is guarded by #ifndef
CRT_HAS_INITFINI_ARRAY. Thus when CRT_HAS_INITFINI_ARRAY is not
defined, frames are registered but then never deregistered.
The frame registry mechanism builds a linked-list from the .so's
static variable do_init.object, and when the .so is unloaded, this
memory becomes invalid and should be deregistered.
Further, libgcc's crtbegin treats the frame registry as independent
from the initfini array mechanism.
This patch fixes this by adding a new #define,
"EH_USE_FRAME_INFO_REGISTRY", which is set by the cmake option
COMPILER_RT_CRT_USE_EH_FRAME_REGISTRY Currently, do_init calls
register_frame_info, and then calls the binary's constructors. This
allows constructors to safely use libunwind. However, do_fini calls
deregister_frame_info and then calls the binary's destructors. This
prevents destructors from safely using libunwind.
This patch also switches that ordering, so that destructors can safely
use libunwind. As it happens, this is a fairly common scenario for
thread sanitizer.
2019-11-09 07:51:35 +08:00
|
|
|
#endif
|
2019-05-01 02:13:22 +08:00
|
|
|
#ifndef CRT_HAS_INITFINI_ARRAY
|
|
|
|
const size_t n = __CTOR_LIST_END__ - __CTOR_LIST__ - 1;
|
|
|
|
for (size_t i = n; i >= 1; i--) __CTOR_LIST__[i]();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef CRT_HAS_INITFINI_ARRAY
|
|
|
|
__attribute__((section(".init_array"),
|
|
|
|
used)) static void (*__init)(void) = __do_init;
|
2019-12-28 03:52:12 +08:00
|
|
|
#elif defined(__i386__) || defined(__x86_64__)
|
2019-05-11 10:33:33 +08:00
|
|
|
__asm__(".pushsection .init,\"ax\",@progbits\n\t"
|
2019-05-01 02:13:22 +08:00
|
|
|
"call " __USER_LABEL_PREFIX__ "__do_init\n\t"
|
|
|
|
".popsection");
|
|
|
|
#elif defined(__arm__)
|
2019-05-11 10:33:33 +08:00
|
|
|
__asm__(".pushsection .init,\"ax\",%progbits\n\t"
|
2019-05-01 02:13:22 +08:00
|
|
|
"bl " __USER_LABEL_PREFIX__ "__do_init\n\t"
|
|
|
|
".popsection");
|
2019-12-28 03:52:12 +08:00
|
|
|
#elif defined(__powerpc__) || defined(__powerpc64__)
|
|
|
|
__asm__(".pushsection .init,\"ax\",@progbits\n\t"
|
|
|
|
"bl " __USER_LABEL_PREFIX__ "__do_init\n\t"
|
|
|
|
"nop\n\t"
|
|
|
|
".popsection");
|
|
|
|
#elif defined(__sparc__)
|
|
|
|
__asm__(".pushsection .init,\"ax\",@progbits\n\t"
|
|
|
|
"call " __USER_LABEL_PREFIX__ "__do_init\n\t"
|
|
|
|
".popsection");
|
|
|
|
#else
|
|
|
|
#error "crtbegin without .init_fini array unimplemented for this architecture"
|
|
|
|
#endif // CRT_HAS_INITFINI_ARRAY
|
2019-05-01 02:13:22 +08:00
|
|
|
|
|
|
|
#ifndef CRT_HAS_INITFINI_ARRAY
|
|
|
|
static fp __DTOR_LIST__[]
|
|
|
|
__attribute__((section(".dtors"), aligned(sizeof(fp)))) = {(fp)-1};
|
|
|
|
extern fp __DTOR_LIST_END__[];
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static void __attribute__((used)) __do_fini() {
|
|
|
|
static _Bool __finalized;
|
|
|
|
if (__builtin_expect(__finalized, 0))
|
|
|
|
return;
|
|
|
|
__finalized = 1;
|
|
|
|
|
|
|
|
if (__cxa_finalize)
|
|
|
|
__cxa_finalize(__dso_handle);
|
|
|
|
|
|
|
|
#ifndef CRT_HAS_INITFINI_ARRAY
|
|
|
|
const size_t n = __DTOR_LIST_END__ - __DTOR_LIST__ - 1;
|
2019-05-03 08:11:53 +08:00
|
|
|
for (size_t i = 1; i <= n; i++) __DTOR_LIST__[i]();
|
2019-05-01 02:13:22 +08:00
|
|
|
#endif
|
Fix include guard and properly order __deregister_frame_info.
Summary:
This patch fixes two problems with the crtbegin.c as written:
1. In do_init, register_frame_info is not guarded by a #define, but in
do_fini, deregister_frame_info is guarded by #ifndef
CRT_HAS_INITFINI_ARRAY. Thus when CRT_HAS_INITFINI_ARRAY is not
defined, frames are registered but then never deregistered.
The frame registry mechanism builds a linked-list from the .so's
static variable do_init.object, and when the .so is unloaded, this
memory becomes invalid and should be deregistered.
Further, libgcc's crtbegin treats the frame registry as independent
from the initfini array mechanism.
This patch fixes this by adding a new #define,
"EH_USE_FRAME_INFO_REGISTRY", which is set by the cmake option
COMPILER_RT_CRT_USE_EH_FRAME_REGISTRY Currently, do_init calls
register_frame_info, and then calls the binary's constructors. This
allows constructors to safely use libunwind. However, do_fini calls
deregister_frame_info and then calls the binary's destructors. This
prevents destructors from safely using libunwind.
This patch also switches that ordering, so that destructors can safely
use libunwind. As it happens, this is a fairly common scenario for
thread sanitizer.
2019-11-09 07:51:35 +08:00
|
|
|
#ifdef EH_USE_FRAME_REGISTRY
|
|
|
|
if (__deregister_frame_info)
|
|
|
|
__deregister_frame_info(__EH_FRAME_LIST__);
|
|
|
|
#endif
|
2019-05-01 02:13:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef CRT_HAS_INITFINI_ARRAY
|
|
|
|
__attribute__((section(".fini_array"),
|
|
|
|
used)) static void (*__fini)(void) = __do_fini;
|
2019-12-28 03:52:12 +08:00
|
|
|
#elif defined(__i386__) || defined(__x86_64__)
|
2019-05-11 10:33:33 +08:00
|
|
|
__asm__(".pushsection .fini,\"ax\",@progbits\n\t"
|
2019-05-01 02:13:22 +08:00
|
|
|
"call " __USER_LABEL_PREFIX__ "__do_fini\n\t"
|
|
|
|
".popsection");
|
|
|
|
#elif defined(__arm__)
|
2019-05-11 10:33:33 +08:00
|
|
|
__asm__(".pushsection .fini,\"ax\",%progbits\n\t"
|
2019-05-01 02:13:22 +08:00
|
|
|
"bl " __USER_LABEL_PREFIX__ "__do_fini\n\t"
|
|
|
|
".popsection");
|
2019-12-28 03:52:12 +08:00
|
|
|
#elif defined(__powerpc__) || defined(__powerpc64__)
|
|
|
|
__asm__(".pushsection .fini,\"ax\",@progbits\n\t"
|
|
|
|
"bl " __USER_LABEL_PREFIX__ "__do_fini\n\t"
|
|
|
|
"nop\n\t"
|
|
|
|
".popsection");
|
|
|
|
#elif defined(__sparc__)
|
|
|
|
__asm__(".pushsection .fini,\"ax\",@progbits\n\t"
|
|
|
|
"call " __USER_LABEL_PREFIX__ "__do_fini\n\t"
|
|
|
|
".popsection");
|
|
|
|
#else
|
|
|
|
#error "crtbegin without .init_fini array unimplemented for this architecture"
|
2019-05-01 02:13:22 +08:00
|
|
|
#endif // CRT_HAS_INIT_FINI_ARRAY
|