aboutsummaryrefslogtreecommitdiff
path: root/lib/csu/common/crtbegin.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/csu/common/crtbegin.c')
-rw-r--r--lib/csu/common/crtbegin.c27
1 files changed, 24 insertions, 3 deletions
diff --git a/lib/csu/common/crtbegin.c b/lib/csu/common/crtbegin.c
index 35231fa904f9..859582c37305 100644
--- a/lib/csu/common/crtbegin.c
+++ b/lib/csu/common/crtbegin.c
@@ -32,10 +32,27 @@ typedef void (*crt_func)(void);
extern void *__dso_handle __hidden;
-#ifdef SHARED
-void *__dso_handle = &__dso_handle;
-#else
+#ifndef SHARED
void *__dso_handle = 0;
+#else
+void *__dso_handle = &__dso_handle;
+void __cxa_finalize(void *) __weak_symbol;
+
+/*
+ * Call __cxa_finalize with the dso handle in shared objects.
+ * When we have ctors/dtors call from the dtor handler before calling
+ * any dtors, otherwise use a destructor.
+ */
+#ifndef HAVE_CTORS
+__attribute__((destructor))
+#endif
+static void
+run_cxa_finalize(void)
+{
+
+ if (__cxa_finalize != NULL)
+ __cxa_finalize(__dso_handle);
+}
#endif
/*
@@ -58,6 +75,10 @@ __do_global_dtors_aux(void)
crt_func fn;
int n;
+#ifdef SHARED
+ run_cxa_finalize();
+#endif
+
for (n = 1;; n++) {
fn = __DTOR_LIST__[n];
if (fn == (crt_func)0 || fn == (crt_func)-1)