| Commit | Line | Data |
|---|---|---|
| e4b17023 JM |
1 | /* Specialized bits of code needed to support construction and |
| 2 | destruction of file-scope objects in C++ code. | |
| 3 | Copyright (C) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 | |
| 4 | 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011 | |
| 5 | Free Software Foundation, Inc. | |
| 6 | Contributed by Ron Guilmette (rfg@monkeys.com). | |
| 7 | ||
| 8 | This file is part of GCC. | |
| 9 | ||
| 10 | GCC is free software; you can redistribute it and/or modify it under | |
| 11 | the terms of the GNU General Public License as published by the Free | |
| 12 | Software Foundation; either version 3, or (at your option) any later | |
| 13 | version. | |
| 14 | ||
| 15 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
| 16 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 17 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 18 | for more details. | |
| 19 | ||
| 20 | Under Section 7 of GPL version 3, you are granted additional | |
| 21 | permissions described in the GCC Runtime Library Exception, version | |
| 22 | 3.1, as published by the Free Software Foundation. | |
| 23 | ||
| 24 | You should have received a copy of the GNU General Public License and | |
| 25 | a copy of the GCC Runtime Library Exception along with this program; | |
| 26 | see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
| 27 | <http://www.gnu.org/licenses/>. */ | |
| 28 | ||
| 29 | /* This file is a bit like libgcc2.c in that it is compiled | |
| 30 | multiple times and yields multiple .o files. | |
| 31 | ||
| 32 | This file is useful on target machines where the object file format | |
| 33 | supports multiple "user-defined" sections (e.g. COFF, ELF, ROSE). On | |
| 34 | such systems, this file allows us to avoid running collect (or any | |
| 35 | other such slow and painful kludge). Additionally, if the target | |
| 36 | system supports a .init section, this file allows us to support the | |
| 37 | linking of C++ code with a non-C++ main program. | |
| 38 | ||
| 39 | Note that if INIT_SECTION_ASM_OP is defined in the tm.h file, then | |
| 40 | this file *will* make use of the .init section. If that symbol is | |
| 41 | not defined however, then the .init section will not be used. | |
| 42 | ||
| 43 | Currently, only ELF and COFF are supported. It is likely however that | |
| 44 | ROSE could also be supported, if someone was willing to do the work to | |
| 45 | make whatever (small?) adaptations are needed. (Some work may be | |
| 46 | needed on the ROSE assembler and linker also.) | |
| 47 | ||
| 48 | This file must be compiled with gcc. */ | |
| 49 | ||
| 50 | /* Target machine header files require this define. */ | |
| 51 | #define IN_LIBGCC2 | |
| 52 | ||
| 53 | /* FIXME: Including auto-host is incorrect, but until we have | |
| 54 | identified the set of defines that need to go into auto-target.h, | |
| 55 | this will have to do. */ | |
| 56 | #include "auto-host.h" | |
| 57 | #undef pid_t | |
| 58 | #undef rlim_t | |
| 59 | #undef ssize_t | |
| 60 | #undef vfork | |
| 61 | #include "tconfig.h" | |
| 62 | #include "tsystem.h" | |
| 63 | #include "coretypes.h" | |
| 64 | #include "tm.h" | |
| 65 | #include "libgcc_tm.h" | |
| 66 | #include "unwind-dw2-fde.h" | |
| 67 | ||
| 68 | #ifndef FORCE_CODE_SECTION_ALIGN | |
| 69 | # define FORCE_CODE_SECTION_ALIGN | |
| 70 | #endif | |
| 71 | ||
| 72 | #ifndef CRT_CALL_STATIC_FUNCTION | |
| 73 | # define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \ | |
| 74 | static void __attribute__((__used__)) \ | |
| 75 | call_ ## FUNC (void) \ | |
| 76 | { \ | |
| 77 | asm (SECTION_OP); \ | |
| 78 | FUNC (); \ | |
| 79 | FORCE_CODE_SECTION_ALIGN \ | |
| 80 | asm (TEXT_SECTION_ASM_OP); \ | |
| 81 | } | |
| 82 | #endif | |
| 83 | ||
| fdc4107c JM |
84 | #if defined(TARGET_DL_ITERATE_PHDR) && \ |
| 85 | ( defined(__FreeBSD__) \ | |
| 86 | || defined(__OpenBSD__) \ | |
| 87 | || defined(__NetBSD__) \ | |
| 88 | || defined(__DragonFly__)) | |
| 89 | #define BSD_DL_ITERATE_PHDR_AVAILABLE | |
| 90 | #endif | |
| 91 | ||
| e4b17023 JM |
92 | #if defined(OBJECT_FORMAT_ELF) \ |
| 93 | && !defined(OBJECT_FORMAT_FLAT) \ | |
| 94 | && defined(HAVE_LD_EH_FRAME_HDR) \ | |
| 95 | && !defined(inhibit_libc) && !defined(CRTSTUFFT_O) \ | |
| fdc4107c | 96 | && defined(BSD_DL_ITERATE_PHDR_AVAILABLE) |
| e4b17023 JM |
97 | #include <link.h> |
| 98 | # define USE_PT_GNU_EH_FRAME | |
| 99 | #endif | |
| 100 | ||
| 101 | #if defined(OBJECT_FORMAT_ELF) \ | |
| 102 | && !defined(OBJECT_FORMAT_FLAT) \ | |
| 103 | && defined(HAVE_LD_EH_FRAME_HDR) && defined(TARGET_DL_ITERATE_PHDR) \ | |
| 104 | && !defined(inhibit_libc) && !defined(CRTSTUFFT_O) \ | |
| 105 | && defined(__sun__) && defined(__svr4__) | |
| 106 | #include <link.h> | |
| 107 | # define USE_PT_GNU_EH_FRAME | |
| 108 | #endif | |
| 109 | ||
| 110 | #if defined(OBJECT_FORMAT_ELF) \ | |
| 111 | && !defined(OBJECT_FORMAT_FLAT) \ | |
| 112 | && defined(HAVE_LD_EH_FRAME_HDR) \ | |
| 113 | && !defined(inhibit_libc) && !defined(CRTSTUFFT_O) \ | |
| 114 | && defined(__GLIBC__) && __GLIBC__ >= 2 | |
| 115 | #include <link.h> | |
| 116 | /* uClibc pretends to be glibc 2.2 and DT_CONFIG is defined in its link.h. | |
| 117 | But it doesn't use PT_GNU_EH_FRAME ELF segment currently. */ | |
| 118 | # if !defined(__UCLIBC__) \ | |
| 119 | && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) \ | |
| 120 | || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && defined(DT_CONFIG))) | |
| 121 | # define USE_PT_GNU_EH_FRAME | |
| 122 | # endif | |
| 123 | #endif | |
| 124 | #if defined(EH_FRAME_SECTION_NAME) && !defined(USE_PT_GNU_EH_FRAME) | |
| 125 | # define USE_EH_FRAME_REGISTRY | |
| 126 | #endif | |
| 127 | #if defined(EH_FRAME_SECTION_NAME) && EH_TABLES_CAN_BE_READ_ONLY | |
| 128 | # define EH_FRAME_SECTION_CONST const | |
| 129 | #else | |
| 130 | # define EH_FRAME_SECTION_CONST | |
| 131 | #endif | |
| 132 | ||
| 133 | #if !defined(DTOR_LIST_END) && defined(OBJECT_FORMAT_ELF) \ | |
| 134 | && defined(HAVE_GAS_HIDDEN) && !defined(FINI_ARRAY_SECTION_ASM_OP) | |
| 135 | # define HIDDEN_DTOR_LIST_END | |
| 136 | #endif | |
| 137 | ||
| 138 | #if !defined(USE_TM_CLONE_REGISTRY) && defined(OBJECT_FORMAT_ELF) | |
| 139 | # define USE_TM_CLONE_REGISTRY 1 | |
| 140 | #endif | |
| 141 | ||
| 142 | /* We do not want to add the weak attribute to the declarations of these | |
| 143 | routines in unwind-dw2-fde.h because that will cause the definition of | |
| 144 | these symbols to be weak as well. | |
| 145 | ||
| 146 | This exposes a core issue, how to handle creating weak references vs | |
| 147 | how to create weak definitions. Either we have to have the definition | |
| 148 | of TARGET_WEAK_ATTRIBUTE be conditional in the shared header files or | |
| 149 | have a second declaration if we want a function's references to be weak, | |
| 150 | but not its definition. | |
| 151 | ||
| 152 | Making TARGET_WEAK_ATTRIBUTE conditional seems like a good solution until | |
| 153 | one thinks about scaling to larger problems -- i.e., the condition under | |
| 154 | which TARGET_WEAK_ATTRIBUTE is active will eventually get far too | |
| 155 | complicated. | |
| 156 | ||
| 157 | So, we take an approach similar to #pragma weak -- we have a second | |
| 158 | declaration for functions that we want to have weak references. | |
| 159 | ||
| 160 | Neither way is particularly good. */ | |
| 161 | ||
| 162 | /* References to __register_frame_info and __deregister_frame_info should | |
| 163 | be weak in this file if at all possible. */ | |
| 164 | extern void __register_frame_info (const void *, struct object *) | |
| 165 | TARGET_ATTRIBUTE_WEAK; | |
| 166 | extern void __register_frame_info_bases (const void *, struct object *, | |
| 167 | void *, void *) | |
| 168 | TARGET_ATTRIBUTE_WEAK; | |
| 169 | extern void *__deregister_frame_info (const void *) | |
| 170 | TARGET_ATTRIBUTE_WEAK; | |
| 171 | extern void *__deregister_frame_info_bases (const void *) | |
| 172 | TARGET_ATTRIBUTE_WEAK; | |
| 173 | extern void __do_global_ctors_1 (void); | |
| 174 | ||
| 175 | /* Likewise for _Jv_RegisterClasses. */ | |
| 176 | extern void _Jv_RegisterClasses (void *) TARGET_ATTRIBUTE_WEAK; | |
| 177 | ||
| 178 | /* Likewise for transactional memory clone tables. */ | |
| 179 | extern void _ITM_registerTMCloneTable (void *, size_t) TARGET_ATTRIBUTE_WEAK; | |
| 180 | extern void _ITM_deregisterTMCloneTable (void *) TARGET_ATTRIBUTE_WEAK; | |
| 181 | ||
| 182 | #ifdef OBJECT_FORMAT_ELF | |
| 183 | ||
| 184 | /* Declare a pointer to void function type. */ | |
| 185 | typedef void (*func_ptr) (void); | |
| 186 | #define STATIC static | |
| 187 | ||
| 188 | #else /* OBJECT_FORMAT_ELF */ | |
| 189 | ||
| 190 | #include "gbl-ctors.h" | |
| 191 | ||
| 192 | #define STATIC | |
| 193 | ||
| 194 | #endif /* OBJECT_FORMAT_ELF */ | |
| 195 | ||
| 196 | #ifdef CRT_BEGIN | |
| 197 | ||
| 198 | /* NOTE: In order to be able to support SVR4 shared libraries, we arrange | |
| 199 | to have one set of symbols { __CTOR_LIST__, __DTOR_LIST__, __CTOR_END__, | |
| 200 | __DTOR_END__ } per root executable and also one set of these symbols | |
| 201 | per shared library. So in any given whole process image, we may have | |
| 202 | multiple definitions of each of these symbols. In order to prevent | |
| 203 | these definitions from conflicting with one another, and in order to | |
| 204 | ensure that the proper lists are used for the initialization/finalization | |
| 205 | of each individual shared library (respectively), we give these symbols | |
| 206 | only internal (i.e. `static') linkage, and we also make it a point to | |
| 207 | refer to only the __CTOR_END__ symbol in crtend.o and the __DTOR_LIST__ | |
| 208 | symbol in crtbegin.o, where they are defined. */ | |
| 209 | ||
| 210 | /* No need for .ctors/.dtors section if linker can place them in | |
| 211 | .init_array/.fini_array section. */ | |
| 212 | #ifndef USE_INITFINI_ARRAY | |
| 213 | /* The -1 is a flag to __do_global_[cd]tors indicating that this table | |
| 214 | does not start with a count of elements. */ | |
| 215 | #ifdef CTOR_LIST_BEGIN | |
| 216 | CTOR_LIST_BEGIN; | |
| 217 | #elif defined(CTORS_SECTION_ASM_OP) | |
| 218 | /* Hack: force cc1 to switch to .data section early, so that assembling | |
| 219 | __CTOR_LIST__ does not undo our behind-the-back change to .ctors. */ | |
| 220 | static func_ptr force_to_data[1] __attribute__ ((__used__)) = { }; | |
| 221 | asm (CTORS_SECTION_ASM_OP); | |
| 222 | STATIC func_ptr __CTOR_LIST__[1] | |
| 223 | __attribute__ ((__used__, aligned(sizeof(func_ptr)))) | |
| 224 | = { (func_ptr) (-1) }; | |
| 225 | #else | |
| 226 | STATIC func_ptr __CTOR_LIST__[1] | |
| 227 | __attribute__ ((__used__, section(".ctors"), aligned(sizeof(func_ptr)))) | |
| 228 | = { (func_ptr) (-1) }; | |
| 229 | #endif /* __CTOR_LIST__ alternatives */ | |
| 230 | ||
| 231 | #ifdef DTOR_LIST_BEGIN | |
| 232 | DTOR_LIST_BEGIN; | |
| 233 | #elif defined(DTORS_SECTION_ASM_OP) | |
| 234 | asm (DTORS_SECTION_ASM_OP); | |
| 235 | STATIC func_ptr __DTOR_LIST__[1] | |
| 236 | __attribute__ ((aligned(sizeof(func_ptr)))) | |
| 237 | = { (func_ptr) (-1) }; | |
| 238 | #else | |
| 239 | STATIC func_ptr __DTOR_LIST__[1] | |
| 240 | __attribute__((section(".dtors"), aligned(sizeof(func_ptr)))) | |
| 241 | = { (func_ptr) (-1) }; | |
| 242 | #endif /* __DTOR_LIST__ alternatives */ | |
| 243 | #endif /* USE_INITFINI_ARRAY */ | |
| 244 | ||
| 245 | #ifdef USE_EH_FRAME_REGISTRY | |
| 246 | /* Stick a label at the beginning of the frame unwind info so we can register | |
| 247 | and deregister it with the exception handling library code. */ | |
| 248 | STATIC EH_FRAME_SECTION_CONST char __EH_FRAME_BEGIN__[] | |
| 249 | __attribute__((section(EH_FRAME_SECTION_NAME), aligned(4))) | |
| 250 | = { }; | |
| 251 | #endif /* USE_EH_FRAME_REGISTRY */ | |
| 252 | ||
| 253 | #ifdef JCR_SECTION_NAME | |
| 254 | /* Stick a label at the beginning of the java class registration info | |
| 255 | so we can register them properly. */ | |
| 256 | STATIC void *__JCR_LIST__[] | |
| 257 | __attribute__ ((used, section(JCR_SECTION_NAME), aligned(sizeof(void*)))) | |
| 258 | = { }; | |
| 259 | #endif /* JCR_SECTION_NAME */ | |
| 260 | ||
| 261 | #if USE_TM_CLONE_REGISTRY | |
| 262 | STATIC func_ptr __TMC_LIST__[] | |
| 263 | __attribute__((used, section(".tm_clone_table"), aligned(sizeof(void*)))) | |
| 264 | = { }; | |
| 265 | # ifdef HAVE_GAS_HIDDEN | |
| 266 | extern func_ptr __TMC_END__[] __attribute__((__visibility__ ("hidden"))); | |
| 267 | # endif | |
| 268 | ||
| 269 | static inline void | |
| 270 | deregister_tm_clones (void) | |
| 271 | { | |
| 272 | void (*fn) (void *); | |
| 273 | ||
| 274 | #ifdef HAVE_GAS_HIDDEN | |
| 275 | if (__TMC_END__ - __TMC_LIST__ == 0) | |
| 276 | return; | |
| 277 | #else | |
| 278 | if (__TMC_LIST__[0] == NULL) | |
| 279 | return; | |
| 280 | #endif | |
| 281 | ||
| 282 | fn = _ITM_deregisterTMCloneTable; | |
| 283 | __asm ("" : "+r" (fn)); | |
| 284 | if (fn) | |
| 285 | fn (__TMC_LIST__); | |
| 286 | } | |
| 287 | ||
| 288 | static inline void | |
| 289 | register_tm_clones (void) | |
| 290 | { | |
| 291 | void (*fn) (void *, size_t); | |
| 292 | size_t size; | |
| 293 | ||
| 294 | #ifdef HAVE_GAS_HIDDEN | |
| 295 | size = (__TMC_END__ - __TMC_LIST__) / 2; | |
| 296 | #else | |
| 297 | for (size = 0; __TMC_LIST__[size * 2] != NULL; size++) | |
| 298 | continue; | |
| 299 | #endif | |
| 300 | if (size == 0) | |
| 301 | return; | |
| 302 | ||
| 303 | fn = _ITM_registerTMCloneTable; | |
| 304 | __asm ("" : "+r" (fn)); | |
| 305 | if (fn) | |
| 306 | fn (__TMC_LIST__, size); | |
| 307 | } | |
| 308 | #endif /* USE_TM_CLONE_REGISTRY */ | |
| 309 | ||
| 310 | #if defined(INIT_SECTION_ASM_OP) || defined(INIT_ARRAY_SECTION_ASM_OP) | |
| 311 | ||
| 312 | #ifdef OBJECT_FORMAT_ELF | |
| 313 | ||
| 314 | /* Declare the __dso_handle variable. It should have a unique value | |
| 315 | in every shared-object; in a main program its value is zero. The | |
| 316 | object should in any case be protected. This means the instance | |
| 317 | in one DSO or the main program is not used in another object. The | |
| 318 | dynamic linker takes care of this. */ | |
| 319 | ||
| 320 | #ifdef TARGET_LIBGCC_SDATA_SECTION | |
| 321 | extern void *__dso_handle __attribute__ ((__section__ (TARGET_LIBGCC_SDATA_SECTION))); | |
| 322 | #endif | |
| 323 | #ifdef HAVE_GAS_HIDDEN | |
| 324 | extern void *__dso_handle __attribute__ ((__visibility__ ("hidden"))); | |
| 325 | #endif | |
| 326 | #ifdef CRTSTUFFS_O | |
| 327 | void *__dso_handle = &__dso_handle; | |
| 328 | #else | |
| 329 | void *__dso_handle = 0; | |
| 330 | #endif | |
| 331 | ||
| 332 | /* The __cxa_finalize function may not be available so we use only a | |
| 333 | weak declaration. */ | |
| 334 | extern void __cxa_finalize (void *) TARGET_ATTRIBUTE_WEAK; | |
| 335 | ||
| 336 | /* Run all the global destructors on exit from the program. */ | |
| 337 | ||
| 338 | /* Some systems place the number of pointers in the first word of the | |
| 339 | table. On SVR4 however, that word is -1. In all cases, the table is | |
| 340 | null-terminated. On SVR4, we start from the beginning of the list and | |
| 341 | invoke each per-compilation-unit destructor routine in order | |
| 342 | until we find that null. | |
| 343 | ||
| 344 | Note that this function MUST be static. There will be one of these | |
| 345 | functions in each root executable and one in each shared library, but | |
| 346 | although they all have the same code, each one is unique in that it | |
| 347 | refers to one particular associated `__DTOR_LIST__' which belongs to the | |
| 348 | same particular root executable or shared library file. | |
| 349 | ||
| 350 | On some systems, this routine is run more than once from the .fini, | |
| 351 | when exit is called recursively, so we arrange to remember where in | |
| 352 | the list we left off processing, and we resume at that point, | |
| 353 | should we be re-invoked. */ | |
| 354 | ||
| 355 | static void __attribute__((used)) | |
| 356 | __do_global_dtors_aux (void) | |
| 357 | { | |
| 358 | static _Bool completed; | |
| 359 | ||
| 360 | if (__builtin_expect (completed, 0)) | |
| 361 | return; | |
| 362 | ||
| 363 | #ifdef CRTSTUFFS_O | |
| 364 | if (__cxa_finalize) | |
| 365 | __cxa_finalize (__dso_handle); | |
| 366 | #endif | |
| 367 | ||
| 368 | #ifdef FINI_ARRAY_SECTION_ASM_OP | |
| 369 | /* If we are using .fini_array then destructors will be run via that | |
| 370 | mechanism. */ | |
| 371 | #elif defined(HIDDEN_DTOR_LIST_END) | |
| 372 | { | |
| 373 | /* Safer version that makes sure only .dtors function pointers are | |
| 374 | called even if the static variable is maliciously changed. */ | |
| 375 | extern func_ptr __DTOR_END__[] __attribute__((visibility ("hidden"))); | |
| 376 | static size_t dtor_idx; | |
| 377 | const size_t max_idx = __DTOR_END__ - __DTOR_LIST__ - 1; | |
| 378 | func_ptr f; | |
| 379 | ||
| 380 | while (dtor_idx < max_idx) | |
| 381 | { | |
| 382 | f = __DTOR_LIST__[++dtor_idx]; | |
| 383 | f (); | |
| 384 | } | |
| 385 | } | |
| 386 | #else /* !defined (FINI_ARRAY_SECTION_ASM_OP) */ | |
| 387 | { | |
| 388 | static func_ptr *p = __DTOR_LIST__ + 1; | |
| 389 | func_ptr f; | |
| 390 | ||
| 391 | while ((f = *p)) | |
| 392 | { | |
| 393 | p++; | |
| 394 | f (); | |
| 395 | } | |
| 396 | } | |
| 397 | #endif /* !defined(FINI_ARRAY_SECTION_ASM_OP) */ | |
| 398 | ||
| 399 | #if USE_TM_CLONE_REGISTRY | |
| 400 | deregister_tm_clones (); | |
| 401 | #endif /* USE_TM_CLONE_REGISTRY */ | |
| 402 | ||
| 403 | #ifdef USE_EH_FRAME_REGISTRY | |
| 404 | #ifdef CRT_GET_RFIB_DATA | |
| 405 | /* If we used the new __register_frame_info_bases interface, | |
| 406 | make sure that we deregister from the same place. */ | |
| 407 | if (__deregister_frame_info_bases) | |
| 408 | __deregister_frame_info_bases (__EH_FRAME_BEGIN__); | |
| 409 | #else | |
| 410 | if (__deregister_frame_info) | |
| 411 | __deregister_frame_info (__EH_FRAME_BEGIN__); | |
| 412 | #endif | |
| 413 | #endif | |
| 414 | ||
| 415 | completed = 1; | |
| 416 | } | |
| 417 | ||
| 418 | /* Stick a call to __do_global_dtors_aux into the .fini section. */ | |
| 419 | #ifdef FINI_SECTION_ASM_OP | |
| 420 | CRT_CALL_STATIC_FUNCTION (FINI_SECTION_ASM_OP, __do_global_dtors_aux) | |
| 421 | #elif defined (FINI_ARRAY_SECTION_ASM_OP) | |
| 422 | static func_ptr __do_global_dtors_aux_fini_array_entry[] | |
| 423 | __attribute__ ((__used__, section(".fini_array"), aligned(sizeof(func_ptr)))) | |
| 424 | = { __do_global_dtors_aux }; | |
| 425 | #else /* !FINI_SECTION_ASM_OP && !FINI_ARRAY_SECTION_ASM_OP */ | |
| 426 | static void __attribute__((used)) | |
| 427 | __do_global_dtors_aux_1 (void) | |
| 428 | { | |
| 429 | atexit (__do_global_dtors_aux); | |
| 430 | } | |
| 431 | CRT_CALL_STATIC_FUNCTION (INIT_SECTION_ASM_OP, __do_global_dtors_aux_1) | |
| 432 | #endif | |
| 433 | ||
| 434 | #if defined(USE_EH_FRAME_REGISTRY) \ | |
| 435 | || defined(JCR_SECTION_NAME) \ | |
| 436 | || defined(USE_TM_CLONE_REGISTRY) | |
| 437 | /* Stick a call to __register_frame_info into the .init section. For some | |
| 438 | reason calls with no arguments work more reliably in .init, so stick the | |
| 439 | call in another function. */ | |
| 440 | ||
| 441 | static void __attribute__((used)) | |
| 442 | frame_dummy (void) | |
| 443 | { | |
| 444 | #ifdef USE_EH_FRAME_REGISTRY | |
| 445 | static struct object object; | |
| 446 | #ifdef CRT_GET_RFIB_DATA | |
| 447 | void *tbase, *dbase; | |
| 448 | tbase = 0; | |
| 449 | CRT_GET_RFIB_DATA (dbase); | |
| 450 | if (__register_frame_info_bases) | |
| 451 | __register_frame_info_bases (__EH_FRAME_BEGIN__, &object, tbase, dbase); | |
| 452 | #else | |
| 453 | if (__register_frame_info) | |
| 454 | __register_frame_info (__EH_FRAME_BEGIN__, &object); | |
| 455 | #endif /* CRT_GET_RFIB_DATA */ | |
| 456 | #endif /* USE_EH_FRAME_REGISTRY */ | |
| 457 | ||
| 458 | #ifdef JCR_SECTION_NAME | |
| 459 | if (__JCR_LIST__[0]) | |
| 460 | { | |
| 461 | void (*register_classes) (void *) = _Jv_RegisterClasses; | |
| 462 | __asm ("" : "+r" (register_classes)); | |
| 463 | if (register_classes) | |
| 464 | register_classes (__JCR_LIST__); | |
| 465 | } | |
| 466 | #endif /* JCR_SECTION_NAME */ | |
| 467 | ||
| 468 | #if USE_TM_CLONE_REGISTRY | |
| 469 | register_tm_clones (); | |
| 470 | #endif /* USE_TM_CLONE_REGISTRY */ | |
| 471 | } | |
| 472 | ||
| 473 | #ifdef INIT_SECTION_ASM_OP | |
| 474 | CRT_CALL_STATIC_FUNCTION (INIT_SECTION_ASM_OP, frame_dummy) | |
| 475 | #else /* defined(INIT_SECTION_ASM_OP) */ | |
| 476 | static func_ptr __frame_dummy_init_array_entry[] | |
| 477 | __attribute__ ((__used__, section(".init_array"), aligned(sizeof(func_ptr)))) | |
| 478 | = { frame_dummy }; | |
| 479 | #endif /* !defined(INIT_SECTION_ASM_OP) */ | |
| 480 | #endif /* USE_EH_FRAME_REGISTRY || JCR_SECTION_NAME || USE_TM_CLONE_REGISTRY */ | |
| 481 | ||
| 482 | #else /* OBJECT_FORMAT_ELF */ | |
| 483 | ||
| 484 | /* The function __do_global_ctors_aux is compiled twice (once in crtbegin.o | |
| 485 | and once in crtend.o). It must be declared static to avoid a link | |
| 486 | error. Here, we define __do_global_ctors as an externally callable | |
| 487 | function. It is externally callable so that __main can invoke it when | |
| 488 | INVOKE__main is defined. This has the additional effect of forcing cc1 | |
| 489 | to switch to the .text section. */ | |
| 490 | ||
| 491 | static void __do_global_ctors_aux (void); | |
| 492 | void | |
| 493 | __do_global_ctors (void) | |
| 494 | { | |
| 495 | #ifdef INVOKE__main | |
| 496 | /* If __main won't actually call __do_global_ctors then it doesn't matter | |
| 497 | what's inside the function. The inside of __do_global_ctors_aux is | |
| 498 | called automatically in that case. And the Alliant fx2800 linker | |
| 499 | crashes on this reference. So prevent the crash. */ | |
| 500 | __do_global_ctors_aux (); | |
| 501 | #endif | |
| 502 | } | |
| 503 | ||
| 504 | asm (INIT_SECTION_ASM_OP); /* cc1 doesn't know that we are switching! */ | |
| 505 | ||
| 506 | /* A routine to invoke all of the global constructors upon entry to the | |
| 507 | program. We put this into the .init section (for systems that have | |
| 508 | such a thing) so that we can properly perform the construction of | |
| 509 | file-scope static-storage C++ objects within shared libraries. */ | |
| 510 | ||
| 511 | static void __attribute__((used)) | |
| 512 | __do_global_ctors_aux (void) /* prologue goes in .init section */ | |
| 513 | { | |
| 514 | FORCE_CODE_SECTION_ALIGN /* explicit align before switch to .text */ | |
| 515 | asm (TEXT_SECTION_ASM_OP); /* don't put epilogue and body in .init */ | |
| 516 | DO_GLOBAL_CTORS_BODY; | |
| 517 | atexit (__do_global_dtors); | |
| 518 | } | |
| 519 | ||
| 520 | #endif /* OBJECT_FORMAT_ELF */ | |
| 521 | ||
| 522 | #elif defined(HAS_INIT_SECTION) /* ! INIT_SECTION_ASM_OP */ | |
| 523 | ||
| 524 | extern void __do_global_dtors (void); | |
| 525 | ||
| 526 | /* This case is used by the Irix 6 port, which supports named sections but | |
| 527 | not an SVR4-style .fini section. __do_global_dtors can be non-static | |
| 528 | in this case because we protect it with -hidden_symbol. */ | |
| 529 | ||
| 530 | void | |
| 531 | __do_global_dtors (void) | |
| 532 | { | |
| 533 | func_ptr *p, f; | |
| 534 | for (p = __DTOR_LIST__ + 1; (f = *p); p++) | |
| 535 | f (); | |
| 536 | ||
| 537 | #if USE_TM_CLONE_REGISTRY | |
| 538 | deregister_tm_clones (); | |
| 539 | #endif /* USE_TM_CLONE_REGISTRY */ | |
| 540 | ||
| 541 | #ifdef USE_EH_FRAME_REGISTRY | |
| 542 | if (__deregister_frame_info) | |
| 543 | __deregister_frame_info (__EH_FRAME_BEGIN__); | |
| 544 | #endif | |
| 545 | } | |
| 546 | ||
| 547 | #if defined(USE_EH_FRAME_REGISTRY) \ | |
| 548 | || defined(JCR_SECTION_NAME) \ | |
| 549 | || defined(USE_TM_CLONE_REGISTRY) | |
| 550 | /* A helper function for __do_global_ctors, which is in crtend.o. Here | |
| 551 | in crtbegin.o, we can reference a couple of symbols not visible there. | |
| 552 | Plus, since we're before libgcc.a, we have no problems referencing | |
| 553 | functions from there. */ | |
| 554 | void | |
| 555 | __do_global_ctors_1(void) | |
| 556 | { | |
| 557 | #ifdef USE_EH_FRAME_REGISTRY | |
| 558 | static struct object object; | |
| 559 | if (__register_frame_info) | |
| 560 | __register_frame_info (__EH_FRAME_BEGIN__, &object); | |
| 561 | #endif | |
| 562 | ||
| 563 | #ifdef JCR_SECTION_NAME | |
| 564 | if (__JCR_LIST__[0]) | |
| 565 | { | |
| 566 | void (*register_classes) (void *) = _Jv_RegisterClasses; | |
| 567 | __asm ("" : "+r" (register_classes)); | |
| 568 | if (register_classes) | |
| 569 | register_classes (__JCR_LIST__); | |
| 570 | } | |
| 571 | #endif | |
| 572 | ||
| 573 | #if USE_TM_CLONE_REGISTRY | |
| 574 | register_tm_clones (); | |
| 575 | #endif /* USE_TM_CLONE_REGISTRY */ | |
| 576 | } | |
| 577 | #endif /* USE_EH_FRAME_REGISTRY || JCR_SECTION_NAME || USE_TM_CLONE_REGISTRY */ | |
| 578 | ||
| 579 | #else /* ! INIT_SECTION_ASM_OP && ! HAS_INIT_SECTION */ | |
| 580 | #error "What are you doing with crtstuff.c, then?" | |
| 581 | #endif | |
| 582 | ||
| 583 | #elif defined(CRT_END) /* ! CRT_BEGIN */ | |
| 584 | ||
| 585 | /* No need for .ctors/.dtors section if linker can place them in | |
| 586 | .init_array/.fini_array section. */ | |
| 587 | #ifndef USE_INITFINI_ARRAY | |
| 588 | /* Put a word containing zero at the end of each of our two lists of function | |
| 589 | addresses. Note that the words defined here go into the .ctors and .dtors | |
| 590 | sections of the crtend.o file, and since that file is always linked in | |
| 591 | last, these words naturally end up at the very ends of the two lists | |
| 592 | contained in these two sections. */ | |
| 593 | ||
| 594 | #ifdef CTOR_LIST_END | |
| 595 | CTOR_LIST_END; | |
| 596 | #elif defined(CTORS_SECTION_ASM_OP) | |
| 597 | /* Hack: force cc1 to switch to .data section early, so that assembling | |
| 598 | __CTOR_LIST__ does not undo our behind-the-back change to .ctors. */ | |
| 599 | static func_ptr force_to_data[1] __attribute__ ((__used__)) = { }; | |
| 600 | asm (CTORS_SECTION_ASM_OP); | |
| 601 | STATIC func_ptr __CTOR_END__[1] | |
| 602 | __attribute__((aligned(sizeof(func_ptr)))) | |
| 603 | = { (func_ptr) 0 }; | |
| 604 | #else | |
| 605 | STATIC func_ptr __CTOR_END__[1] | |
| 606 | __attribute__((section(".ctors"), aligned(sizeof(func_ptr)))) | |
| 607 | = { (func_ptr) 0 }; | |
| 608 | #endif | |
| 609 | ||
| 610 | #ifdef DTOR_LIST_END | |
| 611 | DTOR_LIST_END; | |
| 612 | #elif defined(HIDDEN_DTOR_LIST_END) | |
| 613 | #ifdef DTORS_SECTION_ASM_OP | |
| 614 | asm (DTORS_SECTION_ASM_OP); | |
| 615 | #endif | |
| 616 | func_ptr __DTOR_END__[1] | |
| 617 | __attribute__ ((used, | |
| 618 | #ifndef DTORS_SECTION_ASM_OP | |
| 619 | section(".dtors"), | |
| 620 | #endif | |
| 621 | aligned(sizeof(func_ptr)), visibility ("hidden"))) | |
| 622 | = { (func_ptr) 0 }; | |
| 623 | #elif defined(DTORS_SECTION_ASM_OP) | |
| 624 | asm (DTORS_SECTION_ASM_OP); | |
| 625 | STATIC func_ptr __DTOR_END__[1] | |
| 626 | __attribute__ ((used, aligned(sizeof(func_ptr)))) | |
| 627 | = { (func_ptr) 0 }; | |
| 628 | #else | |
| 629 | STATIC func_ptr __DTOR_END__[1] | |
| 630 | __attribute__((used, section(".dtors"), aligned(sizeof(func_ptr)))) | |
| 631 | = { (func_ptr) 0 }; | |
| 632 | #endif | |
| 633 | #endif /* USE_INITFINI_ARRAY */ | |
| 634 | ||
| 635 | #ifdef EH_FRAME_SECTION_NAME | |
| 636 | /* Terminate the frame unwind info section with a 4byte 0 as a sentinel; | |
| 637 | this would be the 'length' field in a real FDE. */ | |
| 638 | # if __INT_MAX__ == 2147483647 | |
| 639 | typedef int int32; | |
| 640 | # elif __LONG_MAX__ == 2147483647 | |
| 641 | typedef long int32; | |
| 642 | # elif __SHRT_MAX__ == 2147483647 | |
| 643 | typedef short int32; | |
| 644 | # else | |
| 645 | # error "Missing a 4 byte integer" | |
| 646 | # endif | |
| 647 | STATIC EH_FRAME_SECTION_CONST int32 __FRAME_END__[] | |
| 648 | __attribute__ ((used, section(EH_FRAME_SECTION_NAME), | |
| 649 | aligned(sizeof(int32)))) | |
| 650 | = { 0 }; | |
| 651 | #endif /* EH_FRAME_SECTION_NAME */ | |
| 652 | ||
| 653 | #ifdef JCR_SECTION_NAME | |
| 654 | /* Null terminate the .jcr section array. */ | |
| 655 | STATIC void *__JCR_END__[1] | |
| 656 | __attribute__ ((used, section(JCR_SECTION_NAME), | |
| 657 | aligned(sizeof(void *)))) | |
| 658 | = { 0 }; | |
| 659 | #endif /* JCR_SECTION_NAME */ | |
| 660 | ||
| 661 | #if USE_TM_CLONE_REGISTRY | |
| 662 | # ifndef HAVE_GAS_HIDDEN | |
| 663 | static | |
| 664 | # endif | |
| 665 | func_ptr __TMC_END__[] | |
| 666 | __attribute__((used, section(".tm_clone_table"), aligned(sizeof(void *)))) | |
| 667 | # ifdef HAVE_GAS_HIDDEN | |
| 668 | __attribute__((__visibility__ ("hidden"))) = { }; | |
| 669 | # else | |
| 670 | = { 0, 0 }; | |
| 671 | # endif | |
| 672 | #endif /* USE_TM_CLONE_REGISTRY */ | |
| 673 | ||
| 674 | #ifdef INIT_ARRAY_SECTION_ASM_OP | |
| 675 | ||
| 676 | /* If we are using .init_array, there is nothing to do. */ | |
| 677 | ||
| 678 | #elif defined(INIT_SECTION_ASM_OP) | |
| 679 | ||
| 680 | #ifdef OBJECT_FORMAT_ELF | |
| 681 | static void __attribute__((used)) | |
| 682 | __do_global_ctors_aux (void) | |
| 683 | { | |
| 684 | func_ptr *p; | |
| 685 | for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--) | |
| 686 | (*p) (); | |
| 687 | } | |
| 688 | ||
| 689 | /* Stick a call to __do_global_ctors_aux into the .init section. */ | |
| 690 | CRT_CALL_STATIC_FUNCTION (INIT_SECTION_ASM_OP, __do_global_ctors_aux) | |
| 691 | #else /* OBJECT_FORMAT_ELF */ | |
| 692 | ||
| 693 | /* Stick the real initialization code, followed by a normal sort of | |
| 694 | function epilogue at the very end of the .init section for this | |
| 695 | entire root executable file or for this entire shared library file. | |
| 696 | ||
| 697 | Note that we use some tricks here to get *just* the body and just | |
| 698 | a function epilogue (but no function prologue) into the .init | |
| 699 | section of the crtend.o file. Specifically, we switch to the .text | |
| 700 | section, start to define a function, and then we switch to the .init | |
| 701 | section just before the body code. | |
| 702 | ||
| 703 | Earlier on, we put the corresponding function prologue into the .init | |
| 704 | section of the crtbegin.o file (which will be linked in first). | |
| 705 | ||
| 706 | Note that we want to invoke all constructors for C++ file-scope static- | |
| 707 | storage objects AFTER any other possible initialization actions which | |
| 708 | may be performed by the code in the .init section contributions made by | |
| 709 | other libraries, etc. That's because those other initializations may | |
| 710 | include setup operations for very primitive things (e.g. initializing | |
| 711 | the state of the floating-point coprocessor, etc.) which should be done | |
| 712 | before we start to execute any of the user's code. */ | |
| 713 | ||
| 714 | static void | |
| 715 | __do_global_ctors_aux (void) /* prologue goes in .text section */ | |
| 716 | { | |
| 717 | asm (INIT_SECTION_ASM_OP); | |
| 718 | DO_GLOBAL_CTORS_BODY; | |
| 719 | atexit (__do_global_dtors); | |
| 720 | } /* epilogue and body go in .init section */ | |
| 721 | ||
| 722 | FORCE_CODE_SECTION_ALIGN | |
| 723 | asm (TEXT_SECTION_ASM_OP); | |
| 724 | ||
| 725 | #endif /* OBJECT_FORMAT_ELF */ | |
| 726 | ||
| 727 | #elif defined(HAS_INIT_SECTION) /* ! INIT_SECTION_ASM_OP */ | |
| 728 | ||
| 729 | extern void __do_global_ctors (void); | |
| 730 | ||
| 731 | /* This case is used by the Irix 6 port, which supports named sections but | |
| 732 | not an SVR4-style .init section. __do_global_ctors can be non-static | |
| 733 | in this case because we protect it with -hidden_symbol. */ | |
| 734 | void | |
| 735 | __do_global_ctors (void) | |
| 736 | { | |
| 737 | func_ptr *p; | |
| 738 | #if defined(USE_EH_FRAME_REGISTRY) \ | |
| 739 | || defined(JCR_SECTION_NAME) \ | |
| 740 | || defined(USE_TM_CLONE_REGISTRY) | |
| 741 | __do_global_ctors_1(); | |
| 742 | #endif | |
| 743 | for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--) | |
| 744 | (*p) (); | |
| 745 | } | |
| 746 | ||
| 747 | #else /* ! INIT_SECTION_ASM_OP && ! HAS_INIT_SECTION */ | |
| 748 | #error "What are you doing with crtstuff.c, then?" | |
| 749 | #endif | |
| 750 | ||
| 751 | #else /* ! CRT_BEGIN && ! CRT_END */ | |
| 752 | #error "One of CRT_BEGIN or CRT_END must be defined." | |
| 753 | #endif |