home *** CD-ROM | disk | FTP | other *** search
- /* Specialized bits of code needed to support construction and
- destruction of file-scope objects in C++ code.
-
- Written by Ron Guilmette (rfg@netcom.com) with help from Richard Stallman.
-
- Copyright (C) 1991, 1994 Free Software Foundation, Inc.
-
- This file is part of GNU CC.
-
- GNU CC is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- GNU CC is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNU CC; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- /* As a special exception, if you link this library with files
- compiled with GCC to produce an executable, this does not cause
- the resulting executable to be covered by the GNU General Public License.
- This exception does not however invalidate any other reasons why
- the executable file might be covered by the GNU General Public License. */
-
- /* This file is a bit like libgcc1.c/libgcc2.c in that it is compiled
- multiple times and yields multiple .o files.
-
- This file is useful on target machines where the object file format
- supports multiple "user-defined" sections (e.g. COFF, ELF, ROSE). On
- such systems, this file allows us to avoid running collect (or any
- other such slow and painful kludge). Additionally, if the target
- system supports a .init section, this file allows us to support the
- linking of C++ code with a non-C++ main program.
-
- Note that if INIT_SECTION_ASM_OP is defined in the tm.h file, then
- this file *will* make use of the .init section. If that symbol is
- not defined however, then the .init section will not be used.
-
- Currently, only ELF and COFF are supported. It is likely however that
- ROSE could also be supported, if someone was willing to do the work to
- make whatever (small?) adaptations are needed. (Some work may be
- needed on the ROSE assembler and linker also.)
-
- This file must be compiled with gcc. */
-
- /* It is incorrect to include config.h here, because this file is being
- compiled for the target, and hence definitions concerning only the host
- do not apply. */
-
- #include "tm.h"
-
- #ifndef GENERATE_SHARED_ELF_CXX_CODE
- #define GENERATE_SHARED_ELF_CXX_CODE 0
- #endif
-
- #if GENERATE_SHARED_ELF_CXX_CODE==1
-
- /* Provide default definitions for the pseudo-ops used to switch to the
- .ctors and .dtors sections.
-
- Note that we want to give these sections the SHF_WRITE attribute
- because these sections will actually contain data (i.e. tables of
- addresses of functions in the current root executable or shared library
- file) and, in the case of a shared library, the relocatable addresses
- will have to be properly resolved/relocated (and then written into) by
- the dynamic linker when it actually attaches the given shared library
- to the executing process. (Note that on SVR4, you may wish to use the
- `-z text' option to the ELF linker, when building a shared library, as
- an additional check that you are doing everything right. But if you do
- use the `-z text' option when building a shared library, you will get
- errors unless the .ctors and .dtors sections are marked as writable
- via the SHF_WRITE attribute.) */
-
- #ifndef CTORS_SECTION_ASM_OP
- #define CTORS_SECTION_ASM_OP ".section\t.ctors,\"aw\",@progbits"
- #endif
- #ifndef DTORS_SECTION_ASM_OP
- #define DTORS_SECTION_ASM_OP ".section\t.dtors,\"aw\",@progbits"
- #endif
-
- /* Declare a pointer to void function type. */
-
- typedef void (*func_ptr) (void);
-
- /* The following code will be used twice (below) and it must be identical
- in both places, so we define it as a macro. */
-
- #define DO_GLOBAL_CTORS_BODY \
- do { \
- func_ptr *p; \
- for (p = __CTOR_END__; *p != (func_ptr) -1; p--) \
- continue; \
- for (p = p + 1; *p; ) \
- (*p++) (); \
- } while (0)
-
- #ifdef CRT_BEGIN
-
- /* Force cc1 to switch to .data section. */
- static func_ptr force_to_data[0] = { };
-
- /* NOTE: In order to be able to support SVR4 shared libraries, we arrange
- to have one set of symbols { __CTOR_LIST__, __DTOR_LIST__, __CTOR_END__,
- __DTOR_END__ } per root executable and also one set of these symbols
- per shared library. So in any given whole process image, we may have
- multiple definitions of each of these symbols. In order to prevent
- these definitions from conflicting with one another, and in order to
- insure that the proper lists are used for the initialization/finalization
- of each individual shared library (respectively), we give these symbols
- only internal (i.e. `static') linkage, and we also make it a point to
- refer to only the __CTOR_END__ and __DTOR_END__ symbols. (Note that those
- symbols are known only within the crtend.o file, and so all references to
- them are likewise confined to crtend.o.)
-
- Anyway, the following code makes it look like we are providing definitions
- of `__CTOR_END__' and also `__do_global_dtors' within crtbegin.o, but in
- fact, those definitions are only dummy definitions to keep the compiler
- and linker happy. We only need them because we want to have the exact
- same executable code appear within the body of the functions `_init'
- (in crtbegin.o) and `_actual_init_body_and_epilogue' (in crtend.o)
- and that code referens to these two names, so we have to have at least
- some definitions of these in both crtbegin.o and crtend.o. But we only
- really use the definitions in crtend.o. */
-
- /* The -1 is a flag to __do_global_[cd]tors
- indicating that this table does not start with a count of elements. */
- #ifdef CTOR_LIST_BEGIN
- CTOR_LIST_BEGIN;
- #else
- asm (CTORS_SECTION_ASM_OP); /* cc1 doesn't know that we are switching! */
- static func_ptr __CTOR_LIST__[1] = { (func_ptr) (-1) };
- #endif
-
- #ifdef DTOR_LIST_BEGIN
- DTOR_LIST_BEGIN;
- #else
- asm (DTORS_SECTION_ASM_OP); /* cc1 doesn't know that we are switching! */
- static func_ptr __DTOR_LIST__[1] = { (func_ptr) (-1) };
- #endif
-
- #ifdef INIT_SECTION_ASM_OP
-
- /* Dummy definitions just to make the compiler and linker happy. */
-
- static func_ptr __CTOR_END__[1] = { 0 };
- static void __do_global_dtors () { }
-
- asm (INIT_SECTION_ASM_OP); /* cc1 doesn't know that we are switching! */
-
- /* On some svr4 systems, the .init section preamble code provided in
- crti.o may do some evil things which we have to undo before we reach
- the function prologue code for _init (directly below).
- For such systems, define the macro INIT_SECTION_PREAMBLE to
- expand into the code needed to undo the actions of the crti.o file. */
-
- #ifdef INIT_SECTION_PREAMBLE
- INIT_SECTION_PREAMBLE;
- #endif
-
- /* Stick a (weak) label `_init' followed by a normal sort of function
- prologue at the very beginning of the .init section for this entire
- root executable file or for this entire shared library file.
-
- Note that the name `_init' is special to the SVR4 linker. When the
- SVR4 linker sees the _init label (with .globl linkage) in one of the
- input files (while it is creating a shared library output file) it
- creates a special DT_INIT record in the .dynamic section of the output
- shared library file. This record will contain the address of the `_init'
- label, and the dynamic run-time linker will know (from the presence of
- the DT_INIT record in the .dynamic section) that it should transfer
- control to the given address when the relevant shared library is first
- attached to the running process.
-
- Note that we use some tricks here to get *just* the _init label and just
- a function prologue (but no function body or epilogue) into the .init
- section of the crtbegin.o file. Sepcifically, we switch to the .init
- section, start to define a function, and then we switch out to the .text
- section again just before the body and funcyion epilogue are compiled.
-
- Later on, we'll put the corresponding function body and epilogue into
- the .init section of the crtend.o file (which will be linked in last). */
-
- static void
- _init () /* prologue goes in .init section */
- {
- /* NOTE: Our `_init' *must* be declared as `weak', because otherwise, when-
- ever we try to link a root executable, we will get fatal conflicts between
- our definition of this symbol, and the one normally found in the crti.o
- file. (Note that when we link a shared library, we don't include any
- crt*.o files, so in those cases we get no conflicts, and our definition
- of this symbol becomes THE definition which is actually used.) */
-
- #pragma weak _init
-
- #ifdef FORCE_INIT_SECTION_ALIGN
- FORCE_INIT_SECTION_ALIGN; /* Explicit align before switch to .text */
- #endif
- asm (TEXT_SECTION_ASM_OP); /* don't put epilogue and body in .init */
- DO_GLOBAL_CTORS_BODY; /* Never really used, but MUST be here to
- insure that the function prologue generated
- just above matches perfectly with the
- corresponding function epilogue which we
- will later put into the crtend.o file. */
- }
-
- /* The function _init is compiled twice (once in crtbegin.o
- and once in crtend.o). It must be declared static to avoid a link
- error. Here, we define __do_global_ctors as an externally callable
- function. It is externally callable so that __main can invoke it when
- INVOKE__main is defined. */
-
- void
- __do_global_ctors ()
- {
- #ifdef INVOKE__main /* If __main won't actually call __do_global_ctors
- then it doesn't matter what's inside the function.
- The inside of _init is called
- automatically in that case.
- And the Alliant fx2800 linker crashes
- on this reference. So prevent the crash. */
- _init ();
- #endif
- }
-
- #endif /* defined(INIT_SECTION_ASM_OP) */
-
- #endif /* defined(CRT_BEGIN) */
-
- #ifdef CRT_END
-
- /* Force cc1 to switch to .data section. */
- static func_ptr force_to_data[0] = { };
-
- /* Put a word containing zero at the end of each of our two lists of function
- addresses. Note that the words defined here go into the .ctors and .dtors
- sections of the crtend.o file, and since that file is always linked in
- last, these words naturally end up at the very ends of the two lists
- contained in these two sections. */
-
- #ifdef CTOR_LIST_END
- CTOR_LIST_END;
- #else
- asm (CTORS_SECTION_ASM_OP); /* cc1 doesn't know that we are switching! */
- static func_ptr __CTOR_END__[1] = { (func_ptr) 0 };
- #endif
-
- #ifdef DTOR_LIST_END
- DTOR_LIST_END;
- #else
- asm (DTORS_SECTION_ASM_OP); /* cc1 doesn't know that we are switching! */
- static func_ptr __DTOR_END__[1] = { (func_ptr) 0 };
- #endif
-
- #ifdef INIT_SECTION_ASM_OP
-
- /* Run all the global destructors on exit from the program. */
-
- /* Some systems place the number of pointers in the first word of the table.
- On SVR4 however, that word is -1. In all cases, the table is null-
- terminated. On SVR4, we start from the end of the list and invoke each
- per-compilation-unit destructor routine in reverse order until we find
- the -1 value at the start of the list. We write a zero into each list
- element as we go as a way to avoid trying to destroy anything more than
- once while exiting (which could otherwise happen if some destructor
- itself tries to call `exit').
-
- Note that this function MUST be static, and it also must reside in the
- same translation unit with the code that refers to it (in the body of
- the `_actual_init_body_and_epilogue' function below). There will be
- one of these functions in each root executable and one in each shared
- library, but although they all have the same code, each one is unique
- in that it refers to one particular associated `__DTOR_END__' which
- belongs to the same particular root executable or shared library file. */
-
- static void __do_global_ctors () { }
-
- /* It puts __do_global_dtors () in the .fini section. The dynamic
- linker has to able to do the right thing, especially when
- dlopen/dlclose are used on the shared C++ library. Currently only
- the Linux dynamic linker is known good. FYI, crtn.o wil not
- be reached with crtend.o. */
-
- asm (FINI_SECTION_ASM_OP);
-
- #pragma weak _fini = __do_global_dtors
-
- static void
- __do_global_dtors ()
- {
- register func_ptr *p;
-
- for (p = &__DTOR_END__[-1]; *p != (func_ptr) -1; p--)
- if (*p != (func_ptr) 0)
- {
- register func_ptr q;
-
- q = *p;
- *p = (func_ptr) 0; /* Avoid doing this one again. */
- q ();
- }
- }
-
- /* Stick the real initialization code, followed by a normal sort of
- function epilogue at the very end of the .init section for this
- entire root executable file or for this entire shared library file.
-
- Note that we use some tricks here to get *just* the body and just
- a function epilogue (but no function prologue) into the .init
- section of the crtend.o file. Sepcifically, we switch to the .text
- section, start to define a function, and then we switch to the .init
- section just before the body code.
-
- Earlier on, we put the corresponding function prologue into the .init
- section of the crtbegin.o file (which will be linked in first).
-
- Note that we want to invoke all constructors for C++ file-scope static-
- storage objects AFTER any other possible initialization actions which
- may be performed by the code in the .init section contributions made by
- other libraries, etc. That's because those other initializations may
- include setup operations for very primitive things (e.g. initializing
- the state of the floating-point coprocessor, etc.) which should be done
- before we start to execute any of the user's code. */
-
- asm (TEXT_SECTION_ASM_OP); /* don't put epilogue and body in .init */
- static void
- _actual_init_body_and_epilogue () /* prologue goes in .text section */
- {
- asm (INIT_SECTION_ASM_OP);
- DO_GLOBAL_CTORS_BODY;
- } /* epilogue and body go in .init section */
-
- #endif /* defined(INIT_SECTION_ASM_OP) */
-
- #endif /* defined(CRT_END) */
-
- #else /* GENERATE_SHARED_ELF_CXX_CODE */
-
- #include "tm.h"
-
- #ifndef CTORS_SECTION_ASM_OP
- #define CTORS_SECTION_ASM_OP ".section\t.ctors,\"a\",@progbits"
- #endif
- #ifndef DTORS_SECTION_ASM_OP
- #define DTORS_SECTION_ASM_OP ".section\t.dtors,\"a\",@progbits"
- #endif
-
- #include "gbl-ctors.h"
-
- #ifndef ON_EXIT
- #define ON_EXIT(a, b)
- #endif
-
- #ifdef CRT_BEGIN
-
- #ifdef INIT_SECTION_ASM_OP
-
- /* The function __do_global_ctors_aux is compiled twice (once in crtbegin.o
- and once in crtend.o). It must be declared static to avoid a link
- error. Here, we define __do_global_ctors as an externally callable
- function. It is externally callable so that __main can invoke it when
- INVOKE__main is defined. This has the additional effect of forcing cc1
- to switch to the .text section. */
- static void __do_global_ctors_aux ();
- void __do_global_ctors ()
- {
- #ifdef INVOKE__main /* If __main won't actually call __do_global_ctors
- then it doesn't matter what's inside the function.
- The inside of __do_global_ctors_aux is called
- automatically in that case.
- And the Alliant fx2800 linker crashes
- on this reference. So prevent the crash. */
- __do_global_ctors_aux ();
- #endif
- }
-
- asm (INIT_SECTION_ASM_OP); /* cc1 doesn't know that we are switching! */
-
- /* On some svr4 systems, the .init section preamble code provided in
- crti.o may do some evil things which we have to undo before we reach
- the function prologue code for __do_global_ctors (directly below).
- For such systems, define the macro INIT_SECTION_PREAMBLE to
- expand into the code needed to undo the actions of the crti.o file. */
-
- #ifdef INIT_SECTION_PREAMBLE
- INIT_SECTION_PREAMBLE;
- #endif
-
- /* A routine to invoke all of the global constructors upon entry to the
- program. We put this into the .init section (for systems that have
- such a thing) so that we can properly perform the construction of
- file-scope static-storage C++ objects within shared libraries. */
-
- static void
- __do_global_ctors_aux () /* prologue goes in .init section */
- {
- #ifdef FORCE_INIT_SECTION_ALIGN
- FORCE_INIT_SECTION_ALIGN; /* Explicit align before switch to .text */
- #endif
- asm (TEXT_SECTION_ASM_OP); /* don't put epilogue and body in .init */
- DO_GLOBAL_CTORS_BODY;
- ON_EXIT (__do_global_dtors, 0);
- }
-
- #endif /* defined(INIT_SECTION_ASM_OP) */
-
- /* Force cc1 to switch to .data section. */
- static func_ptr force_to_data[0] = { };
-
- /* The -1 is a flag to __do_global_[cd]tors
- indicating that this table does not start with a count of elements. */
- #ifdef CTOR_LIST_BEGIN
- CTOR_LIST_BEGIN;
- #else
- asm (CTORS_SECTION_ASM_OP); /* cc1 doesn't know that we are switching! */
- func_ptr __CTOR_LIST__[1] = { (func_ptr) (-1) };
- #endif
-
- #ifdef DTOR_LIST_BEGIN
- DTOR_LIST_BEGIN;
- #else
- asm (DTORS_SECTION_ASM_OP); /* cc1 doesn't know that we are switching! */
- func_ptr __DTOR_LIST__[1] = { (func_ptr) (-1) };
- #endif
-
- #endif /* defined(CRT_BEGIN) */
-
- #ifdef CRT_END
-
- #ifdef INIT_SECTION_ASM_OP
-
- /* A routine to invoke all of the global constructors upon entry to the
- program. We put this into the .init section (for systems that have
- such a thing) so that we can properly perform the construction of
- file-scope static-storage C++ objects within shared libraries.
-
- This must be virtually identical to the one above so that we can
- insure that the function prologue from the one above works correctly
- with the epilogue from this one. (They will both go into the .init
- section as the first and last things (respectively) that the linker
- will put in that section.)
- */
-
- static void
- __do_global_ctors_aux () /* prologue goes in .text section */
- {
- asm (INIT_SECTION_ASM_OP);
- DO_GLOBAL_CTORS_BODY;
- ON_EXIT (__do_global_dtors, 0);
- } /* epilogue and body go in .init section */
-
- #endif /* defined(INIT_SECTION_ASM_OP) */
-
- /* Force cc1 to switch to .data section. */
- static func_ptr force_to_data[0] = { };
-
- #ifdef CTOR_LIST_END
- CTOR_LIST_END;
- #else
- asm (CTORS_SECTION_ASM_OP); /* cc1 doesn't know that we are switching! */
- func_ptr __CTOR_END__[1] = { (func_ptr) 0 };
- #endif
-
- #ifdef DTOR_LIST_END
- DTOR_LIST_END;
- #else
- asm (DTORS_SECTION_ASM_OP); /* cc1 doesn't know that we are switching! */
- func_ptr __DTOR_END__[1] = { (func_ptr) 0 };
- #endif
-
- #endif /* defined(CRT_END) */
-
- #endif /* GENERATE_SHARED_ELF_CXX_CODE */
-