summaryrefslogtreecommitdiffstats
path: root/lib/csu
diff options
context:
space:
mode:
authorjdp <jdp@FreeBSD.org>1997-04-09 19:14:31 +0000
committerjdp <jdp@FreeBSD.org>1997-04-09 19:14:31 +0000
commit72875e2a08e9f207eb05ed25d49c1b9a00efc4d8 (patch)
treeddb52407f59f21040a25e367a53af1f7cf00071a /lib/csu
parent9bbed0ec574d078dfdf988be1539aee18c8c7ac6 (diff)
downloadFreeBSD-src-72875e2a08e9f207eb05ed25d49c1b9a00efc4d8.zip
FreeBSD-src-72875e2a08e9f207eb05ed25d49c1b9a00efc4d8.tar.gz
Declare the constructor/destructor linker sets as extern rather than
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.
Diffstat (limited to 'lib/csu')
-rw-r--r--lib/csu/i386/c++rt0.c27
1 files changed, 24 insertions, 3 deletions
diff --git a/lib/csu/i386/c++rt0.c b/lib/csu/i386/c++rt0.c
index 94fa5c5..413524f 100644
--- a/lib/csu/i386/c++rt0.c
+++ b/lib/csu/i386/c++rt0.c
@@ -27,7 +27,7 @@
* (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$
+ * $Id: c++rt0.c,v 1.7 1997/02/22 14:57:42 peter Exp $
*/
/*
@@ -38,8 +38,8 @@
* number of pointers in each.
* The tables are also null-terminated.
*/
-void (*__CTOR_LIST__[2])(void);
-void (*__DTOR_LIST__[2])(void);
+extern void (*__CTOR_LIST__[])(void);
+extern void (*__DTOR_LIST__[])(void);
static void
__dtors(void)
@@ -84,3 +84,24 @@ __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);
OpenPOWER on IntegriCloud