fix ordering of shared library ctors with respect to libc init
authorRich Felker <dalias@aerifal.cx>
Fri, 30 Nov 2012 22:56:23 +0000 (17:56 -0500)
committerRich Felker <dalias@aerifal.cx>
Fri, 30 Nov 2012 22:56:23 +0000 (17:56 -0500)
previously, shared library constructors were being called before
important internal things like the environment (extern char **environ)
and hwcap flags (needed for sjlj to work right with float on arm) were
initialized in __libc_start_main. rather than trying to have to
dynamic linker make sure this stuff all gets initialized right, I've
opted to just defer calling shared library constructors until after
the main program's entry point is reached. this also fixes the order
of ctors to be the exact reverse of dtors, which is a desirable
property and possibly even mandated by some languages.

the main practical effect of this change is that shared libraries
calling getenv from ctors will no longer fail.

src/env/__libc_start_main.c
src/ldso/dynlink.c

index ee10b0ded6753686c08c2ff72a4fe1b1cd714435..04a454e8bf9c9031f87ac4a230627532050195b4 100644 (file)
@@ -3,6 +3,7 @@
 
 void __init_tls(size_t *);
 void __init_security(size_t *);
+void __init_ldso_ctors(void);
 
 #define AUX_CNT 38
 
@@ -37,6 +38,10 @@ int __libc_start_main(
        /* Execute constructors (static) linked into the application */
        if (init) init(argc, argv, envp);
 
+#ifdef SHARED
+       __init_ldso_ctors();
+#endif
+
        /* Pass control to to application */
        exit(main(argc, argv, envp));
        return 0;
index c436b88fadf6771aa53d76e9b3cae67315d63422..d564b8f2aa207d8b8744c48b32301e211db5a515 100644 (file)
@@ -999,13 +999,16 @@ void *__dynlink(int argc, char **argv)
 
        if (ssp_used) __init_ssp((void *)aux[AT_RANDOM]);
 
-       atexit(do_fini);
-       do_init_fini(tail);
-
        errno = 0;
        return (void *)aux[AT_ENTRY];
 }
 
+void __init_ldso_ctors(void)
+{
+       atexit(do_fini);
+       do_init_fini(tail);
+}
+
 void *dlopen(const char *file, int mode)
 {
        struct dso *volatile p, *orig_tail, *next;