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