|
|
1.1 root 1: /* Specialized bits of code needed to support construction and
2: destruction of file-scope objects in C++ code.
3:
1.1.1.5 root 4: Written by Ron Guilmette ([email protected]) with help from Richard Stallman.
1.1 root 5:
1.1.1.6 ! root 6: Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc.
1.1 root 7:
8: This file is part of GNU CC.
9:
10: GNU CC is free software; you can redistribute it and/or modify
11: it under the terms of the GNU General Public License as published by
12: the Free Software Foundation; either version 2, or (at your option)
13: any later version.
14:
15: GNU CC is distributed in the hope that it will be useful,
16: but WITHOUT ANY WARRANTY; without even the implied warranty of
17: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18: GNU General Public License for more details.
19:
20: You should have received a copy of the GNU General Public License
21: along with GNU CC; see the file COPYING. If not, write to
1.1.1.6 ! root 22: the Free Software Foundation, 59 Temple Place - Suite 330,
! 23: Boston, MA 02111-1307, USA. */
1.1 root 24:
25: /* As a special exception, if you link this library with files
26: compiled with GCC to produce an executable, this does not cause
27: the resulting executable to be covered by the GNU General Public License.
28: This exception does not however invalidate any other reasons why
29: the executable file might be covered by the GNU General Public License. */
30:
31: /* This file is a bit like libgcc1.c/libgcc2.c in that it is compiled
32: multiple times and yields multiple .o files.
33:
34: This file is useful on target machines where the object file format
35: supports multiple "user-defined" sections (e.g. COFF, ELF, ROSE). On
36: such systems, this file allows us to avoid running collect (or any
37: other such slow and painful kludge). Additionally, if the target
38: system supports a .init section, this file allows us to support the
39: linking of C++ code with a non-C++ main program.
40:
41: Note that if INIT_SECTION_ASM_OP is defined in the tm.h file, then
42: this file *will* make use of the .init section. If that symbol is
43: not defined however, then the .init section will not be used.
44:
1.1.1.3 root 45: Currently, only ELF and COFF are supported. It is likely however that
46: ROSE could also be supported, if someone was willing to do the work to
47: make whatever (small?) adaptations are needed. (Some work may be
48: needed on the ROSE assembler and linker also.)
1.1 root 49:
50: This file must be compiled with gcc. */
51:
52: /* It is incorrect to include config.h here, because this file is being
53: compiled for the target, and hence definitions concerning only the host
54: do not apply. */
55:
56: #include "tm.h"
57:
1.1.1.6 ! root 58: /* Provide default definitions for the pseudo-ops used to switch to the
! 59: .ctors and .dtors sections.
! 60:
! 61: Note that we want to give these sections the SHF_WRITE attribute
! 62: because these sections will actually contain data (i.e. tables of
! 63: addresses of functions in the current root executable or shared library
! 64: file) and, in the case of a shared library, the relocatable addresses
! 65: will have to be properly resolved/relocated (and then written into) by
! 66: the dynamic linker when it actually attaches the given shared library
! 67: to the executing process. (Note that on SVR4, you may wish to use the
! 68: `-z text' option to the ELF linker, when building a shared library, as
! 69: an additional check that you are doing everything right. But if you do
! 70: use the `-z text' option when building a shared library, you will get
! 71: errors unless the .ctors and .dtors sections are marked as writable
! 72: via the SHF_WRITE attribute.) */
! 73:
1.1 root 74: #ifndef CTORS_SECTION_ASM_OP
1.1.1.6 ! root 75: #define CTORS_SECTION_ASM_OP ".section\t.ctors,\"aw\""
1.1 root 76: #endif
77: #ifndef DTORS_SECTION_ASM_OP
1.1.1.6 ! root 78: #define DTORS_SECTION_ASM_OP ".section\t.dtors,\"aw\""
1.1 root 79: #endif
80:
1.1.1.6 ! root 81: #ifdef OBJECT_FORMAT_ELF
! 82:
! 83: /* Declare a pointer to void function type. */
! 84: typedef void (*func_ptr) (void);
! 85: #define STATIC static
! 86:
! 87: #else /* OBJECT_FORMAT_ELF */
! 88:
1.1 root 89: #include "gbl-ctors.h"
90:
1.1.1.2 root 91: #ifndef ON_EXIT
1.1 root 92: #define ON_EXIT(a, b)
93: #endif
1.1.1.6 ! root 94: #define STATIC
! 95:
! 96: #endif /* OBJECT_FORMAT_ELF */
1.1 root 97:
98: #ifdef CRT_BEGIN
99:
100: #ifdef INIT_SECTION_ASM_OP
101:
1.1.1.6 ! root 102: #ifdef OBJECT_FORMAT_ELF
! 103:
! 104: /* Run all the global destructors on exit from the program. */
! 105:
! 106: /* Some systems place the number of pointers in the first word of the
! 107: table. On SVR4 however, that word is -1. In all cases, the table is
! 108: null-terminated. On SVR4, we start from the beginning of the list and
! 109: invoke each per-compilation-unit destructor routine in order
! 110: until we find that null.
! 111:
! 112: Note that this function MUST be static. There will be one of these
! 113: functions in each root executable and one in each shared library, but
! 114: although they all have the same code, each one is unique in that it
! 115: refers to one particular associated `__DTOR_LIST__' which belongs to the
! 116: same particular root executable or shared library file. */
! 117:
! 118: static func_ptr __DTOR_LIST__[];
! 119: static void
! 120: __do_global_dtors_aux ()
! 121: {
! 122: func_ptr *p;
! 123: for (p = __DTOR_LIST__ + 1; *p; p++)
! 124: (*p) ();
! 125: }
! 126:
! 127: /* Stick a call to __do_global_dtors_aux into the .fini section. */
! 128: static void
! 129: fini_dummy ()
! 130: {
! 131: asm (FINI_SECTION_ASM_OP);
! 132: __do_global_dtors_aux ();
! 133: #ifdef FORCE_FINI_SECTION_ALIGN
! 134: FORCE_FINI_SECTION_ALIGN;
! 135: #endif
! 136: asm (TEXT_SECTION_ASM_OP);
! 137: }
! 138:
! 139: #else /* OBJECT_FORMAT_ELF */
! 140:
1.1.1.2 root 141: /* The function __do_global_ctors_aux is compiled twice (once in crtbegin.o
1.1.1.3 root 142: and once in crtend.o). It must be declared static to avoid a link
1.1.1.2 root 143: error. Here, we define __do_global_ctors as an externally callable
144: function. It is externally callable so that __main can invoke it when
145: INVOKE__main is defined. This has the additional effect of forcing cc1
146: to switch to the .text section. */
147: static void __do_global_ctors_aux ();
1.1.1.3 root 148: void __do_global_ctors ()
149: {
150: #ifdef INVOKE__main /* If __main won't actually call __do_global_ctors
151: then it doesn't matter what's inside the function.
152: The inside of __do_global_ctors_aux is called
153: automatically in that case.
154: And the Alliant fx2800 linker crashes
155: on this reference. So prevent the crash. */
156: __do_global_ctors_aux ();
157: #endif
158: }
1.1 root 159:
160: asm (INIT_SECTION_ASM_OP); /* cc1 doesn't know that we are switching! */
161:
1.1.1.6 ! root 162: /* On some svr4 systems, the initial .init section preamble code provided in
! 163: crti.o may do something, such as bump the stack, which we have to
! 164: undo before we reach the function prologue code for __do_global_ctors
! 165: (directly below). For such systems, define the macro INIT_SECTION_PREAMBLE
! 166: to expand into the code needed to undo the actions of the crti.o file. */
! 167:
1.1.1.2 root 168: #ifdef INIT_SECTION_PREAMBLE
169: INIT_SECTION_PREAMBLE;
170: #endif
171:
1.1 root 172: /* A routine to invoke all of the global constructors upon entry to the
173: program. We put this into the .init section (for systems that have
174: such a thing) so that we can properly perform the construction of
175: file-scope static-storage C++ objects within shared libraries. */
176:
177: static void
1.1.1.2 root 178: __do_global_ctors_aux () /* prologue goes in .init section */
1.1 root 179: {
1.1.1.4 root 180: #ifdef FORCE_INIT_SECTION_ALIGN
181: FORCE_INIT_SECTION_ALIGN; /* Explicit align before switch to .text */
182: #endif
1.1 root 183: asm (TEXT_SECTION_ASM_OP); /* don't put epilogue and body in .init */
184: DO_GLOBAL_CTORS_BODY;
1.1.1.2 root 185: ON_EXIT (__do_global_dtors, 0);
1.1 root 186: }
187:
1.1.1.6 ! root 188: #endif /* OBJECT_FORMAT_ELF */
1.1 root 189: #endif /* defined(INIT_SECTION_ASM_OP) */
190:
191: /* Force cc1 to switch to .data section. */
192: static func_ptr force_to_data[0] = { };
193:
1.1.1.6 ! root 194: /* NOTE: In order to be able to support SVR4 shared libraries, we arrange
! 195: to have one set of symbols { __CTOR_LIST__, __DTOR_LIST__, __CTOR_END__,
! 196: __DTOR_END__ } per root executable and also one set of these symbols
! 197: per shared library. So in any given whole process image, we may have
! 198: multiple definitions of each of these symbols. In order to prevent
! 199: these definitions from conflicting with one another, and in order to
! 200: ensure that the proper lists are used for the initialization/finalization
! 201: of each individual shared library (respectively), we give these symbols
! 202: only internal (i.e. `static') linkage, and we also make it a point to
! 203: refer to only the __CTOR_END__ symbol in crtend.o and the __DTOR_LIST__
! 204: symbol in crtbegin.o, where they are defined. */
! 205:
1.1 root 206: /* The -1 is a flag to __do_global_[cd]tors
207: indicating that this table does not start with a count of elements. */
1.1.1.2 root 208: #ifdef CTOR_LIST_BEGIN
209: CTOR_LIST_BEGIN;
210: #else
1.1 root 211: asm (CTORS_SECTION_ASM_OP); /* cc1 doesn't know that we are switching! */
1.1.1.6 ! root 212: STATIC func_ptr __CTOR_LIST__[1] = { (func_ptr) (-1) };
1.1.1.2 root 213: #endif
1.1 root 214:
1.1.1.2 root 215: #ifdef DTOR_LIST_BEGIN
216: DTOR_LIST_BEGIN;
217: #else
1.1 root 218: asm (DTORS_SECTION_ASM_OP); /* cc1 doesn't know that we are switching! */
1.1.1.6 ! root 219: STATIC func_ptr __DTOR_LIST__[1] = { (func_ptr) (-1) };
1.1.1.2 root 220: #endif
1.1 root 221:
222: #endif /* defined(CRT_BEGIN) */
223:
224: #ifdef CRT_END
225:
226: #ifdef INIT_SECTION_ASM_OP
227:
1.1.1.6 ! root 228: #ifdef OBJECT_FORMAT_ELF
1.1 root 229:
1.1.1.6 ! root 230: static func_ptr __CTOR_END__[];
! 231: static void
! 232: __do_global_ctors_aux ()
! 233: {
! 234: func_ptr *p;
! 235: for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--)
! 236: (*p) ();
! 237: }
! 238:
! 239: /* Stick a call to __do_global_ctors_aux into the .init section. */
! 240: static void
! 241: init_dummy ()
! 242: {
! 243: asm (INIT_SECTION_ASM_OP);
! 244: __do_global_ctors_aux ();
! 245: #ifdef FORCE_INIT_SECTION_ALIGN
! 246: FORCE_INIT_SECTION_ALIGN;
! 247: #endif
! 248: asm (TEXT_SECTION_ASM_OP);
! 249:
! 250: /* This is a kludge. The Linux dynamic linker needs ___brk_addr, __environ
! 251: and atexit (). We have to make sure they are in the .dynsym section. We
! 252: accomplish it by making a dummy call here. This
! 253: code is never reached. */
! 254:
! 255: #if defined(__linux__) && defined(__PIC__)
! 256: {
! 257: extern void *___brk_addr;
! 258: extern char **__environ;
! 259:
! 260: ___brk_addr = __environ;
! 261: atexit ();
! 262: }
! 263: #endif
! 264: }
! 265:
! 266: #else /* OBJECT_FORMAT_ELF */
! 267:
! 268: /* Stick the real initialization code, followed by a normal sort of
! 269: function epilogue at the very end of the .init section for this
! 270: entire root executable file or for this entire shared library file.
! 271:
! 272: Note that we use some tricks here to get *just* the body and just
! 273: a function epilogue (but no function prologue) into the .init
! 274: section of the crtend.o file. Specifically, we switch to the .text
! 275: section, start to define a function, and then we switch to the .init
! 276: section just before the body code.
! 277:
! 278: Earlier on, we put the corresponding function prologue into the .init
! 279: section of the crtbegin.o file (which will be linked in first).
! 280:
! 281: Note that we want to invoke all constructors for C++ file-scope static-
! 282: storage objects AFTER any other possible initialization actions which
! 283: may be performed by the code in the .init section contributions made by
! 284: other libraries, etc. That's because those other initializations may
! 285: include setup operations for very primitive things (e.g. initializing
! 286: the state of the floating-point coprocessor, etc.) which should be done
! 287: before we start to execute any of the user's code. */
1.1 root 288:
289: static void
1.1.1.2 root 290: __do_global_ctors_aux () /* prologue goes in .text section */
1.1 root 291: {
292: asm (INIT_SECTION_ASM_OP);
293: DO_GLOBAL_CTORS_BODY;
1.1.1.2 root 294: ON_EXIT (__do_global_dtors, 0);
1.1 root 295: } /* epilogue and body go in .init section */
296:
1.1.1.6 ! root 297: #endif /* OBJECT_FORMAT_ELF */
! 298:
1.1 root 299: #endif /* defined(INIT_SECTION_ASM_OP) */
300:
301: /* Force cc1 to switch to .data section. */
302: static func_ptr force_to_data[0] = { };
303:
1.1.1.6 ! root 304: /* Put a word containing zero at the end of each of our two lists of function
! 305: addresses. Note that the words defined here go into the .ctors and .dtors
! 306: sections of the crtend.o file, and since that file is always linked in
! 307: last, these words naturally end up at the very ends of the two lists
! 308: contained in these two sections. */
! 309:
1.1.1.2 root 310: #ifdef CTOR_LIST_END
311: CTOR_LIST_END;
312: #else
1.1 root 313: asm (CTORS_SECTION_ASM_OP); /* cc1 doesn't know that we are switching! */
1.1.1.6 ! root 314: STATIC func_ptr __CTOR_END__[1] = { (func_ptr) 0 };
1.1.1.2 root 315: #endif
1.1 root 316:
1.1.1.2 root 317: #ifdef DTOR_LIST_END
318: DTOR_LIST_END;
319: #else
1.1 root 320: asm (DTORS_SECTION_ASM_OP); /* cc1 doesn't know that we are switching! */
1.1.1.6 ! root 321: STATIC func_ptr __DTOR_END__[1] = { (func_ptr) 0 };
1.1.1.2 root 322: #endif
1.1 root 323:
324: #endif /* defined(CRT_END) */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.