home *** CD-ROM | disk | FTP | other *** search
/ Serving the Web / ServingTheWeb1995.disc1of1.iso / linux / slacksrce / d / libc / libc-4.6 / libc-4 / libc-linux / elf / crt / crtstuff.c.hjl next >
Encoding:
Text File  |  1994-11-05  |  18.0 KB  |  478 lines

  1. /* Specialized bits of code needed to support construction and
  2.    destruction of file-scope objects in C++ code.
  3.  
  4.    Written by Ron Guilmette (rfg@netcom.com) with help from Richard Stallman.
  5.  
  6. Copyright (C) 1991, 1994 Free Software Foundation, Inc.
  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
  22. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  23.  
  24. /* As a special exception, if you link this library with files
  25.    compiled with GCC to produce an executable, this does not cause
  26.    the resulting executable to be covered by the GNU General Public License.
  27.    This exception does not however invalidate any other reasons why
  28.    the executable file might be covered by the GNU General Public License.  */
  29.  
  30. /* This file is a bit like libgcc1.c/libgcc2.c in that it is compiled
  31.    multiple times and yields multiple .o files.
  32.  
  33.    This file is useful on target machines where the object file format
  34.    supports multiple "user-defined" sections (e.g. COFF, ELF, ROSE).  On
  35.    such systems, this file allows us to avoid running collect (or any
  36.    other such slow and painful kludge).  Additionally, if the target
  37.    system supports a .init section, this file allows us to support the
  38.    linking of C++ code with a non-C++ main program.
  39.  
  40.    Note that if INIT_SECTION_ASM_OP is defined in the tm.h file, then
  41.    this file *will* make use of the .init section.  If that symbol is
  42.    not defined however, then the .init section will not be used.
  43.  
  44.    Currently, only ELF and COFF are supported.  It is likely however that
  45.    ROSE could also be supported, if someone was willing to do the work to
  46.    make whatever (small?) adaptations are needed.  (Some work may be
  47.    needed on the ROSE assembler and linker also.)
  48.  
  49.    This file must be compiled with gcc.  */
  50.  
  51. /* It is incorrect to include config.h here, because this file is being
  52.    compiled for the target, and hence definitions concerning only the host
  53.    do not apply.  */
  54.  
  55. #include "tm.h"
  56.  
  57. #ifndef GENERATE_SHARED_ELF_CXX_CODE
  58. #define GENERATE_SHARED_ELF_CXX_CODE 0
  59. #endif
  60.  
  61. #if GENERATE_SHARED_ELF_CXX_CODE==1
  62.  
  63. /* Provide default definitions for the pseudo-ops used to switch to the
  64.    .ctors and .dtors sections.
  65.  
  66.    Note that we want to give these sections the SHF_WRITE attribute
  67.    because these sections will actually contain data (i.e. tables of
  68.    addresses of functions in the current root executable or shared library
  69.    file) and, in the case of a shared library, the relocatable addresses
  70.    will have to be properly resolved/relocated (and then written into) by
  71.    the dynamic linker when it actually attaches the given shared library
  72.    to the executing process.  (Note that on SVR4, you may wish to use the
  73.    `-z text' option to the ELF linker, when building a shared library, as
  74.    an additional check that you are doing everything right.  But if you do
  75.    use the `-z text' option when building a shared library, you will get
  76.    errors unless the .ctors and .dtors sections are marked as writable
  77.    via the SHF_WRITE attribute.)  */
  78.  
  79. #ifndef CTORS_SECTION_ASM_OP
  80. #define CTORS_SECTION_ASM_OP    ".section\t.ctors,\"aw\",@progbits"
  81. #endif
  82. #ifndef DTORS_SECTION_ASM_OP
  83. #define DTORS_SECTION_ASM_OP    ".section\t.dtors,\"aw\",@progbits"
  84. #endif
  85.  
  86. /*  Declare a pointer to void function type.  */
  87.  
  88. typedef void (*func_ptr) (void);
  89.  
  90. /* The following code will be used twice (below) and it must be identical
  91.    in both places, so we define it as a macro.  */
  92.  
  93. #define DO_GLOBAL_CTORS_BODY                        \
  94. do {                                    \
  95.   func_ptr *p;                                \
  96.   for (p = __CTOR_END__; *p != (func_ptr) -1; p--)             \
  97.     continue;                                \
  98.   for (p = p + 1; *p; )                            \
  99.     (*p++) ();                                \
  100. } while (0)
  101.  
  102. #ifdef CRT_BEGIN
  103.  
  104. /* Force cc1 to switch to .data section.  */
  105. static func_ptr force_to_data[0] = { };
  106.  
  107. /* NOTE:  In order to be able to support SVR4 shared libraries, we arrange
  108.    to have one set of symbols { __CTOR_LIST__, __DTOR_LIST__, __CTOR_END__,
  109.    __DTOR_END__ } per root executable and also one set of these symbols
  110.    per shared library.  So in any given whole process image, we may have
  111.    multiple definitions of each of these symbols.  In order to prevent
  112.    these definitions from conflicting with one another, and in order to
  113.    insure that the proper lists are used for the initialization/finalization
  114.    of each individual shared library (respectively), we give these symbols
  115.    only internal (i.e. `static') linkage, and we also make it a point to
  116.    refer to only the __CTOR_END__ and __DTOR_END__ symbols.  (Note that those
  117.    symbols are known only within the crtend.o file, and so all references to
  118.    them are likewise confined to crtend.o.)
  119.  
  120.    Anyway, the following code makes it look like we are providing definitions
  121.    of `__CTOR_END__' and also `__do_global_dtors' within crtbegin.o, but in
  122.    fact, those definitions are only dummy definitions to keep the compiler
  123.    and linker happy.  We only need them because we want to have the exact
  124.    same executable code appear within the body of the functions `_init'
  125.    (in crtbegin.o) and  `_actual_init_body_and_epilogue' (in crtend.o)
  126.    and that code referens to these two names, so we have to have at least
  127.    some definitions of these in both crtbegin.o and crtend.o.  But we only
  128.    really use the definitions in crtend.o.  */
  129.  
  130. /* The -1 is a flag to __do_global_[cd]tors
  131.    indicating that this table does not start with a count of elements.  */
  132. #ifdef CTOR_LIST_BEGIN
  133. CTOR_LIST_BEGIN;
  134. #else
  135. asm (CTORS_SECTION_ASM_OP);    /* cc1 doesn't know that we are switching! */
  136. static func_ptr __CTOR_LIST__[1] = { (func_ptr) (-1) };
  137. #endif
  138.  
  139. #ifdef DTOR_LIST_BEGIN
  140. DTOR_LIST_BEGIN;
  141. #else
  142. asm (DTORS_SECTION_ASM_OP);    /* cc1 doesn't know that we are switching! */
  143. static func_ptr __DTOR_LIST__[1] = { (func_ptr) (-1) };
  144. #endif
  145.  
  146. #ifdef INIT_SECTION_ASM_OP
  147.  
  148. /* Dummy definitions just to make the compiler and linker happy.  */
  149.  
  150. static func_ptr __CTOR_END__[1] = { 0 };
  151. static void __do_global_dtors () { }
  152.  
  153. asm (INIT_SECTION_ASM_OP);    /* cc1 doesn't know that we are switching! */
  154.  
  155. /* On some svr4 systems, the .init section preamble code provided in
  156.    crti.o may do some evil things which we have to undo before we reach
  157.    the function prologue code for _init (directly below).
  158.    For such systems, define the macro INIT_SECTION_PREAMBLE to
  159.    expand into the code needed to undo the actions of the crti.o file.  */
  160.    
  161. #ifdef INIT_SECTION_PREAMBLE
  162.   INIT_SECTION_PREAMBLE;
  163. #endif
  164.  
  165. /* Stick a (weak) label `_init' followed by a normal sort of function
  166.    prologue at the very beginning of the .init section for this entire
  167.    root executable file or for this entire shared library file.
  168.  
  169.    Note that the name `_init' is special to the SVR4 linker.  When the
  170.    SVR4 linker sees the _init label (with .globl linkage) in one of the
  171.    input files (while it is creating a shared library output file) it
  172.    creates a special DT_INIT record in the .dynamic section of the output
  173.    shared library file.  This record will contain the address of the `_init'
  174.    label, and the dynamic run-time linker will know (from the presence of
  175.    the DT_INIT record in the .dynamic section) that it should transfer
  176.    control to the given address when the relevant shared library is first
  177.    attached to the running process.
  178.  
  179.    Note that we use some tricks here to get *just* the _init label and just
  180.    a function prologue (but no function body or epilogue) into the .init
  181.    section of the crtbegin.o file.  Sepcifically, we switch to the .init
  182.    section, start to define a function, and then we switch out to the .text
  183.    section again just before the body and funcyion epilogue are compiled.
  184.  
  185.    Later on, we'll put the corresponding function body and epilogue into
  186.    the .init section of the crtend.o file (which will be linked in last).  */
  187.  
  188. static void
  189. _init ()    /* prologue goes in .init section */
  190. {
  191. /* NOTE:  Our `_init' *must* be declared as `weak', because otherwise, when-
  192.    ever we try to link a root executable, we will get fatal conflicts between
  193.    our definition of this symbol, and the one normally found in the crti.o
  194.    file.  (Note that when we link a shared library, we don't include any
  195.    crt*.o files, so in those cases we get no conflicts, and our definition
  196.    of this symbol becomes THE definition which is actually used.)  */
  197.  
  198.   #pragma weak _init
  199.  
  200. #ifdef FORCE_INIT_SECTION_ALIGN
  201.   FORCE_INIT_SECTION_ALIGN;    /* Explicit align before switch to .text */
  202. #endif
  203.   asm (TEXT_SECTION_ASM_OP);    /* don't put epilogue and body in .init */
  204.   DO_GLOBAL_CTORS_BODY;        /* Never really used, but MUST be here to
  205.                    insure that the function prologue generated
  206.                    just above matches perfectly with the
  207.                    corresponding function epilogue which we
  208.                    will later put into the crtend.o file.  */
  209. }
  210.  
  211. /* The function _init is compiled twice (once in crtbegin.o
  212.    and once in crtend.o).  It must be declared static to avoid a link
  213.    error.  Here, we define __do_global_ctors as an externally callable
  214.    function.  It is externally callable so that __main can invoke it when
  215.    INVOKE__main is defined.  */
  216.  
  217. void
  218. __do_global_ctors ()
  219. {
  220. #ifdef INVOKE__main  /* If __main won't actually call __do_global_ctors
  221.             then it doesn't matter what's inside the function.
  222.             The inside of _init is called
  223.             automatically in that case.
  224.             And the Alliant fx2800 linker crashes
  225.             on this reference.  So prevent the crash.  */
  226.   _init ();
  227. #endif
  228. }
  229.  
  230. #endif /* defined(INIT_SECTION_ASM_OP) */
  231.  
  232. #endif /* defined(CRT_BEGIN) */
  233.  
  234. #ifdef CRT_END
  235.  
  236. /* Force cc1 to switch to .data section.  */
  237. static func_ptr force_to_data[0] = { };
  238.  
  239. /* Put a word containing zero at the end of each of our two lists of function
  240.    addresses.  Note that the words defined here go into the .ctors and .dtors
  241.    sections of the crtend.o file, and since that file is always linked in
  242.    last, these words naturally end up at the very ends of the two lists
  243.    contained in these two sections.  */
  244.  
  245. #ifdef CTOR_LIST_END
  246. CTOR_LIST_END;
  247. #else
  248. asm (CTORS_SECTION_ASM_OP);    /* cc1 doesn't know that we are switching! */
  249. static func_ptr __CTOR_END__[1] = { (func_ptr) 0 };
  250. #endif
  251.  
  252. #ifdef DTOR_LIST_END
  253. DTOR_LIST_END;
  254. #else
  255. asm (DTORS_SECTION_ASM_OP);    /* cc1 doesn't know that we are switching! */
  256. static func_ptr __DTOR_END__[1] = { (func_ptr) 0 };
  257. #endif
  258.  
  259. #ifdef INIT_SECTION_ASM_OP
  260.  
  261. /* Run all the global destructors on exit from the program.  */
  262.  
  263. /* Some systems place the number of pointers in the first word of the table.
  264.    On SVR4 however, that word is -1.  In all cases, the table is null-
  265.    terminated.  On SVR4, we start from the end of the list and invoke each
  266.    per-compilation-unit destructor routine in reverse order until we find
  267.    the -1 value at the start of the list.  We write a zero into each list
  268.    element as we go as a way to avoid trying to destroy anything more than
  269.    once while exiting (which could otherwise happen if some destructor
  270.    itself tries to call `exit').
  271.  
  272.    Note that this function MUST be static, and it also must reside in the
  273.    same translation unit with the code that refers to it (in the body of
  274.    the `_actual_init_body_and_epilogue' function below).  There will be
  275.    one of these functions in each root executable and one in each shared
  276.    library, but although they all have the same code, each one is unique
  277.    in that it refers to one particular associated `__DTOR_END__' which
  278.    belongs to the same particular root executable or shared library file.  */
  279.  
  280. static void __do_global_ctors () { }
  281.  
  282. /* It puts __do_global_dtors () in the .fini section. The dynamic
  283.    linker has to able to do the right thing, especially when
  284.    dlopen/dlclose are used on the shared C++ library. Currently only
  285.    the Linux dynamic linker is known good. FYI, crtn.o wil not
  286.    be reached with crtend.o. */
  287.  
  288. asm (FINI_SECTION_ASM_OP);
  289.  
  290. #pragma weak _fini = __do_global_dtors
  291.  
  292. static void
  293. __do_global_dtors ()
  294. {
  295.   register func_ptr *p;
  296.  
  297.   for (p = &__DTOR_END__[-1]; *p != (func_ptr) -1; p--)
  298.     if (*p != (func_ptr) 0)
  299.       {
  300.     register func_ptr q;
  301.  
  302.     q = *p;
  303.     *p = (func_ptr) 0;    /* Avoid doing this one again.  */
  304.     q ();
  305.       }
  306. }
  307.  
  308. /* Stick the real initialization code, followed by a normal sort of
  309.    function epilogue at the very end of the .init section for this
  310.    entire root executable file or for this entire shared library file.
  311.  
  312.    Note that we use some tricks here to get *just* the body and just
  313.    a function epilogue (but no function prologue) into the .init
  314.    section of the crtend.o file.  Sepcifically, we switch to the .text
  315.    section, start to define a function, and then we switch to the .init
  316.    section just before the body code.
  317.  
  318.    Earlier on, we put the corresponding function prologue into the .init
  319.    section of the crtbegin.o file (which will be linked in first).
  320.  
  321.    Note that we want to invoke all constructors for C++ file-scope static-
  322.    storage objects AFTER any other possible initialization actions which
  323.    may be performed by the code in the .init section contributions made by
  324.    other libraries, etc.  That's because those other initializations may
  325.    include setup operations for very primitive things (e.g. initializing
  326.    the state of the floating-point coprocessor, etc.) which should be done
  327.    before we start to execute any of the user's code. */
  328.  
  329. asm (TEXT_SECTION_ASM_OP);    /* don't put epilogue and body in .init */
  330. static void
  331. _actual_init_body_and_epilogue ()    /* prologue goes in .text section */
  332. {
  333.   asm (INIT_SECTION_ASM_OP);
  334.   DO_GLOBAL_CTORS_BODY;
  335. }                /* epilogue and body go in .init section */
  336.  
  337. #endif /* defined(INIT_SECTION_ASM_OP) */
  338.  
  339. #endif /* defined(CRT_END) */
  340.  
  341. #else  /* GENERATE_SHARED_ELF_CXX_CODE */
  342.  
  343. #include "tm.h"
  344.  
  345. #ifndef CTORS_SECTION_ASM_OP
  346. #define CTORS_SECTION_ASM_OP    ".section\t.ctors,\"a\",@progbits"
  347. #endif
  348. #ifndef DTORS_SECTION_ASM_OP
  349. #define DTORS_SECTION_ASM_OP    ".section\t.dtors,\"a\",@progbits"
  350. #endif
  351.  
  352. #include "gbl-ctors.h"
  353.  
  354. #ifndef ON_EXIT
  355. #define ON_EXIT(a, b)
  356. #endif
  357.  
  358. #ifdef CRT_BEGIN
  359.  
  360. #ifdef INIT_SECTION_ASM_OP
  361.  
  362. /* The function __do_global_ctors_aux is compiled twice (once in crtbegin.o
  363.    and once in crtend.o).  It must be declared static to avoid a link
  364.    error.  Here, we define __do_global_ctors as an externally callable
  365.    function.  It is externally callable so that __main can invoke it when
  366.    INVOKE__main is defined.  This has the additional effect of forcing cc1
  367.    to switch to the .text section.  */
  368. static void __do_global_ctors_aux ();
  369. void __do_global_ctors ()
  370. {
  371. #ifdef INVOKE__main  /* If __main won't actually call __do_global_ctors
  372.             then it doesn't matter what's inside the function.
  373.             The inside of __do_global_ctors_aux is called
  374.             automatically in that case.
  375.             And the Alliant fx2800 linker crashes
  376.             on this reference.  So prevent the crash.  */
  377.   __do_global_ctors_aux ();
  378. #endif
  379. }
  380.  
  381. asm (INIT_SECTION_ASM_OP);    /* cc1 doesn't know that we are switching! */
  382.  
  383. /* On some svr4 systems, the .init section preamble code provided in
  384.    crti.o may do some evil things which we have to undo before we reach
  385.    the function prologue code for __do_global_ctors (directly below).
  386.    For such systems, define the macro INIT_SECTION_PREAMBLE to
  387.    expand into the code needed to undo the actions of the crti.o file.  */
  388.    
  389. #ifdef INIT_SECTION_PREAMBLE
  390.   INIT_SECTION_PREAMBLE;
  391. #endif
  392.  
  393. /* A routine to invoke all of the global constructors upon entry to the
  394.    program.  We put this into the .init section (for systems that have
  395.    such a thing) so that we can properly perform the construction of
  396.    file-scope static-storage C++ objects within shared libraries.   */
  397.  
  398. static void
  399. __do_global_ctors_aux ()    /* prologue goes in .init section */
  400. {
  401. #ifdef FORCE_INIT_SECTION_ALIGN
  402.   FORCE_INIT_SECTION_ALIGN;    /* Explicit align before switch to .text */
  403. #endif
  404.   asm (TEXT_SECTION_ASM_OP);    /* don't put epilogue and body in .init */
  405.   DO_GLOBAL_CTORS_BODY;
  406.   ON_EXIT (__do_global_dtors, 0);
  407. }
  408.  
  409. #endif /* defined(INIT_SECTION_ASM_OP) */
  410.  
  411. /* Force cc1 to switch to .data section.  */
  412. static func_ptr force_to_data[0] = { };
  413.  
  414. /* The -1 is a flag to __do_global_[cd]tors
  415.    indicating that this table does not start with a count of elements.  */
  416. #ifdef CTOR_LIST_BEGIN
  417. CTOR_LIST_BEGIN;
  418. #else
  419. asm (CTORS_SECTION_ASM_OP);    /* cc1 doesn't know that we are switching! */
  420. func_ptr __CTOR_LIST__[1] = { (func_ptr) (-1) };
  421. #endif
  422.  
  423. #ifdef DTOR_LIST_BEGIN
  424. DTOR_LIST_BEGIN;
  425. #else
  426. asm (DTORS_SECTION_ASM_OP);    /* cc1 doesn't know that we are switching! */
  427. func_ptr __DTOR_LIST__[1] = { (func_ptr) (-1) };
  428. #endif
  429.  
  430. #endif /* defined(CRT_BEGIN) */
  431.  
  432. #ifdef CRT_END
  433.  
  434. #ifdef INIT_SECTION_ASM_OP
  435.  
  436. /* A routine to invoke all of the global constructors upon entry to the
  437.    program.  We put this into the .init section (for systems that have
  438.    such a thing) so that we can properly perform the construction of
  439.    file-scope static-storage C++ objects within shared libraries.
  440.  
  441.    This must be virtually identical to the one above so that we can
  442.    insure that the function prologue from the one above works correctly
  443.    with the epilogue from this one.  (They will both go into the .init
  444.    section as the first and last things (respectively) that the linker
  445.    will put in that section.)
  446. */
  447.  
  448. static void
  449. __do_global_ctors_aux ()    /* prologue goes in .text section */
  450. {
  451.   asm (INIT_SECTION_ASM_OP);
  452.   DO_GLOBAL_CTORS_BODY;
  453.   ON_EXIT (__do_global_dtors, 0);
  454. }                /* epilogue and body go in .init section */
  455.  
  456. #endif /* defined(INIT_SECTION_ASM_OP) */
  457.  
  458. /* Force cc1 to switch to .data section.  */
  459. static func_ptr force_to_data[0] = { };
  460.  
  461. #ifdef CTOR_LIST_END
  462. CTOR_LIST_END;
  463. #else
  464. asm (CTORS_SECTION_ASM_OP);    /* cc1 doesn't know that we are switching! */
  465. func_ptr __CTOR_END__[1] = { (func_ptr) 0 };
  466. #endif
  467.  
  468. #ifdef DTOR_LIST_END
  469. DTOR_LIST_END;
  470. #else
  471. asm (DTORS_SECTION_ASM_OP);    /* cc1 doesn't know that we are switching! */
  472. func_ptr __DTOR_END__[1] = { (func_ptr) 0 };
  473. #endif
  474.  
  475. #endif /* defined(CRT_END) */
  476.  
  477. #endif /* GENERATE_SHARED_ELF_CXX_CODE */
  478.