/* 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 */
