summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/env/__libc_start_main.c26
-rw-r--r--src/exit/exit.c16
-rw-r--r--src/internal/libc.h3
-rw-r--r--src/ldso/dynlink.c14
4 files changed, 33 insertions, 26 deletions
diff --git a/src/env/__libc_start_main.c b/src/env/__libc_start_main.c
index aef9f9ec..2a8698bb 100644
--- a/src/env/__libc_start_main.c
+++ b/src/env/__libc_start_main.c
@@ -5,6 +5,13 @@ void __init_tls(size_t *);
void __init_security(size_t *);
void __init_ldso_ctors(void);
+#ifndef SHARED
+static void dummy() {}
+weak_alias(dummy, _init);
+extern void (*const __init_array_start)() __attribute__((weak));
+extern void (*const __init_array_end)() __attribute__((weak));
+#endif
+
#define AUX_CNT 38
extern size_t __hwcap, __sysinfo;
@@ -29,23 +36,16 @@ void __init_libc(char **envp, char *pn)
__init_security(aux);
}
-int __libc_start_main(
- int (*main)(int, char **, char **), int argc, char **argv,
- int (*init)(int, char **, char **), void (*fini)(void),
- void (*ldso_fini)(void))
+int __libc_start_main(int (*main)(int,char **,char **), int argc, char **argv)
{
char **envp = argv+argc+1;
+#ifndef SHARED
__init_libc(envp, argv[0]);
-
- libc.ldso_fini = ldso_fini;
- libc.fini = fini;
-
- /* Execute constructors (static) linked into the application */
- if (init) init(argc, argv, envp);
-
-#ifdef SHARED
- __init_ldso_ctors();
+ _init();
+ uintptr_t a = (uintptr_t)&__init_array_start;
+ for (; a<(uintptr_t)&__init_array_end; a+=sizeof(void(*)()))
+ (*(void (**)())a)();
#endif
/* Pass control to to application */
diff --git a/src/exit/exit.c b/src/exit/exit.c
index e4932b5b..f259c982 100644
--- a/src/exit/exit.c
+++ b/src/exit/exit.c
@@ -14,6 +14,12 @@ weak_alias(dummy, __funcs_on_exit);
weak_alias(dummy, __flush_on_exit);
weak_alias(dummy, __seek_on_exit);
+#ifndef SHARED
+weak_alias(dummy, _fini);
+extern void (*const __fini_array_start)() __attribute__((weak));
+extern void (*const __fini_array_end)() __attribute__((weak));
+#endif
+
_Noreturn void exit(int code)
{
static int lock;
@@ -22,8 +28,14 @@ _Noreturn void exit(int code)
while (a_swap(&lock, 1)) __syscall(SYS_pause);
__funcs_on_exit();
- if (libc.fini) libc.fini();
- if (libc.ldso_fini) libc.ldso_fini();
+
+#ifndef SHARED
+ uintptr_t a = (uintptr_t)&__fini_array_end;
+ for (; a>(uintptr_t)&__fini_array_start; a-=sizeof(void(*)()))
+ (*(void (**)())(a-sizeof(void(*)())))();
+ _fini();
+#endif
+
__flush_on_exit();
__seek_on_exit();
diff --git a/src/internal/libc.h b/src/internal/libc.h
index c9416f07..c8fbe3fd 100644
--- a/src/internal/libc.h
+++ b/src/internal/libc.h
@@ -9,9 +9,6 @@ struct __libc {
int threaded;
int secure;
size_t *auxv;
- int (*atexit)(void (*)(void));
- void (*fini)(void);
- void (*ldso_fini)(void);
volatile int threads_minus_1;
int canceldisable;
FILE *ofl_head;
diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c
index 829696ff..3a0bf95d 100644
--- a/src/ldso/dynlink.c
+++ b/src/ldso/dynlink.c
@@ -91,6 +91,7 @@ struct symdef {
void __init_ssp(size_t *);
void *__install_initial_tls(void *);
+void __init_libc(char **, char *);
static struct dso *head, *tail, *ldso, *fini_head;
static char *env_path, *sys_path, *r_path;
@@ -841,6 +842,7 @@ void *__dynlink(int argc, char **argv)
char *env_preload=0;
size_t vdso_base;
size_t *auxv;
+ char **envp = argv+argc+1;
/* Find aux vector just past environ[] */
for (i=argc+1; argv[i]; i++)
@@ -953,7 +955,6 @@ void *__dynlink(int argc, char **argv)
tls_align = MAXP2(tls_align, app->tls_align);
}
app->global = 1;
- app->constructed = 1;
decode_dyn(app);
/* Attach to vdso, if provided by the kernel */
@@ -1038,15 +1039,12 @@ void *__dynlink(int argc, char **argv)
_dl_debug_state();
if (ssp_used) __init_ssp((void *)aux[AT_RANDOM]);
-
- errno = 0;
- return (void *)aux[AT_ENTRY];
-}
-
-void __init_ldso_ctors(void)
-{
+ __init_libc(envp, argv[0]);
atexit(do_fini);
+ errno = 0;
do_init_fini(tail);
+
+ return (void *)aux[AT_ENTRY];
}
void *dlopen(const char *file, int mode)