f3112eb32a
common. Add one do-nothing element to each set. This ensures that the linker realizes that they are linker sets rather than simple commons, and makes it possible to link c++rt0.o into every shared library regardless of whether it is a C++ library or not. Without this change, the constructors and destructors in the main program could be executed multiple times. This change is going to make it possible to get rid of the CPLUSPLUSLIB makefile variable once and for all. It is a piece of the solution to PR gnu/3505 (gcc -shared). Finally, it fixes a heretofore unreported bug: If CPLUSPLUSLIB was set in a makefile for a C++ shared library that had no static constructors or destructors in it, then the main program's constructors and destructors would be executed multiple times.
108 lines
3.2 KiB
C
108 lines
3.2 KiB
C
/*
|
|
* Copyright (c) 1993 Paul Kranenburg
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
* must display the following acknowledgement:
|
|
* This product includes software developed by Paul Kranenburg.
|
|
* 4. The name of the author may not be used to endorse or promote products
|
|
* derived from this software without specific prior written permission
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
* $Id: c++rt0.c,v 1.7 1997/02/22 14:57:42 peter Exp $
|
|
*/
|
|
|
|
/*
|
|
* Run-time module for GNU C++ compiled shared libraries.
|
|
*
|
|
* The linker constructs the following arrays of pointers to global
|
|
* constructors and destructors. The first element contains the
|
|
* number of pointers in each.
|
|
* The tables are also null-terminated.
|
|
*/
|
|
extern void (*__CTOR_LIST__[])(void);
|
|
extern void (*__DTOR_LIST__[])(void);
|
|
|
|
static void
|
|
__dtors(void)
|
|
{
|
|
unsigned long i = (unsigned long) __DTOR_LIST__[0];
|
|
void (**p)(void) = __DTOR_LIST__ + i;
|
|
|
|
while (i--)
|
|
(**p--)();
|
|
}
|
|
|
|
static void
|
|
__ctors(void)
|
|
{
|
|
void (**p)(void) = __CTOR_LIST__ + 1;
|
|
|
|
while (*p)
|
|
(**p++)();
|
|
}
|
|
|
|
extern void __init() asm(".init");
|
|
extern void __fini() asm(".fini");
|
|
|
|
void
|
|
__init(void)
|
|
{
|
|
static int initialized = 0;
|
|
|
|
/*
|
|
* Call global constructors.
|
|
* Arrange to call global destructors at exit.
|
|
*/
|
|
if (!initialized) {
|
|
initialized = 1;
|
|
__ctors();
|
|
}
|
|
|
|
}
|
|
|
|
void
|
|
__fini(void)
|
|
{
|
|
__dtors();
|
|
}
|
|
|
|
/*
|
|
* Make sure there is at least one constructor and one destructor in the
|
|
* shared library. Otherwise, the linker does not realize that the
|
|
* constructor and destructor lists are linker sets. It treats them as
|
|
* commons and resolves them to the lists from the main program. That
|
|
* causes multiple invocations of the main program's static constructors
|
|
* and destructors, which is very bad.
|
|
*/
|
|
|
|
static void
|
|
do_nothing(void)
|
|
{
|
|
}
|
|
|
|
/* Linker magic to add an element to a constructor or destructor list. */
|
|
#define TEXT_SET(set, sym) \
|
|
asm(".stabs \"_" #set "\", 23, 0, 0, _" #sym)
|
|
|
|
TEXT_SET(__CTOR_LIST__, do_nothing);
|
|
TEXT_SET(__DTOR_LIST__, do_nothing);
|