clean up and refactor program initialization
authorRich Felker <dalias@aerifal.cx>
Mon, 8 Oct 2012 01:43:46 +0000 (21:43 -0400)
committerRich Felker <dalias@aerifal.cx>
Mon, 8 Oct 2012 01:43:46 +0000 (21:43 -0400)
the code in __libc_start_main is now responsible for parsing auxv,
rather than duplicating the parsing all over the place. this should
shave off a few cycles and some code size. __init_libc is left as an
external-linkage function despite the fact that it could be static, to
prevent it from being inlined and permanently wasting stack space when
main is called.

a few other minor changes are included, like eliminating per-thread
ssp canaries (they were likely broken when combined with certain
dlopen usages, and completely unnecessary) and some other unnecessary
checks. since this code gets linked into every program, it should be
as small and simple as possible.

src/env/__init_security.c
src/env/__init_tls.c
src/env/__libc_start_main.c
src/env/__stack_chk_fail.c
src/ldso/dynlink.c
src/thread/pthread_create.c

index f9de9c62e4620b069e8a9a2a4e68c2969c2e1bb6..91b9b1001ac97949c6c05c0b3294abf33487e2a7 100644 (file)
@@ -6,31 +6,26 @@
 #include "libc.h"
 #include "atomic.h"
 
-#define AUX_CNT 24
-
-static void dummy(size_t *auxv)
+static void dummy(void *ent)
 {
 }
 weak_alias(dummy, __init_ssp);
 
-void __init_security(size_t *auxv)
+void __init_security(size_t *aux)
 {
-       size_t i, aux[AUX_CNT] = { 0 };
        struct pollfd pfd[3] = { {.fd=0}, {.fd=1}, {.fd=2} };
+       int i;
 
 #ifndef SHARED
-       __init_ssp(auxv);
+       __init_ssp((void *)aux[AT_RANDOM]);
 #endif
 
-       for (; auxv[0]; auxv+=2) if (auxv[0]<AUX_CNT) aux[auxv[0]] = auxv[1];
-       __hwcap = aux[AT_HWCAP];
        if (aux[AT_UID]==aux[AT_EUID] && aux[AT_GID]==aux[AT_EGID]
                && !aux[AT_SECURE]) return;
 
        __syscall(SYS_poll, pfd, 3, 0);
-       for (i=0; i<3; i++)
-               if (pfd[i].revents&POLLNVAL)
-                       if (__syscall(SYS_open, "/dev/null", O_RDWR|O_LARGEFILE)<0)
-                               a_crash();
+       for (i=0; i<3; i++) if (pfd[i].revents&POLLNVAL)
+               if (__syscall(SYS_open, "/dev/null", O_RDWR|O_LARGEFILE)<0)
+                       a_crash();
        libc.secure = 1;
 }
index 6b3cd28bb03699d6a71e32a9de276398389779c4..e70025d77a01b25176c2ffd0487cee103cf047a6 100644 (file)
@@ -46,19 +46,14 @@ typedef Elf32_Phdr Phdr;
 typedef Elf64_Phdr Phdr;
 #endif
 
-#define AUX_CNT 6
-
-void __init_tls(size_t *auxv)
+void __init_tls(size_t *aux)
 {
-       size_t i, aux[AUX_CNT] = { 0 };
        unsigned char *p, *mem;
        size_t n, d;
        Phdr *phdr, *tls_phdr=0;
        size_t base = 0;
 
-       for (; auxv[0]; auxv+=2) if (auxv[0]<AUX_CNT) aux[auxv[0]] = auxv[1];
-       p = (void *)aux[AT_PHDR];
-       for (p=(void *)aux[AT_PHDR]; aux[AT_PHNUM]--; p+=aux[AT_PHENT]) {
+       for (p=(void *)aux[AT_PHDR],n=aux[AT_PHNUM]; n; n--,p+=aux[AT_PHENT]) {
                phdr = (void *)p;
                if (phdr->p_type == PT_PHDR)
                        base = aux[AT_PHDR] - phdr->p_vaddr;
@@ -79,8 +74,6 @@ void __init_tls(size_t *auxv)
 
        mem = __mmap(0, libc.tls_size, PROT_READ|PROT_WRITE,
                MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
-       if (mem == MAP_FAILED) a_crash();
-
        if (!__install_initial_tls(__copy_tls(mem))) a_crash();
 }
 #else
index a38569d5d6aa03bad7e8085f5d19455957d69ade..07613a522b01cba6609295b59fe30835d4be17dd 100644 (file)
@@ -1,24 +1,36 @@
+#include <elf.h>
 #include "libc.h"
 
 void __init_tls(size_t *);
 void __init_security(size_t *);
 
+#define AUX_CNT 38
+
+void __init_libc(char **envp)
+{
+       size_t i, *auxv, aux[AUX_CNT];
+       __environ = envp;
+       for (i=0; envp[i]; i++);
+       libc.auxv = auxv = (void *)(envp+i+1);
+       for (i=0; auxv[i]; i+=2) if (auxv[i]<AUX_CNT) aux[auxv[i]] = auxv[i+1];
+       __hwcap = aux[AT_HWCAP];
+
+       __init_tls(aux);
+       __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))
 {
-       char **envp = argv+argc+1, **auxv = envp;
+       char **envp = argv+argc+1;
+
+       __init_libc(envp);
 
-       __environ = envp;
-       do auxv++; while (*auxv);
-       libc.auxv = (void *)++auxv;
        libc.ldso_fini = ldso_fini;
        libc.fini = fini;
 
-       __init_tls((void *)auxv);
-       __init_security((void *)auxv);
-
        /* Execute constructors (static) linked into the application */
        if (init) init(argc, argv, envp);
 
index eac852b7a39572e9b10bfd1df3a2488c0a52ba39..3e2e4b6dfabac5d60194c33eee3c1e4b58371dec 100644 (file)
@@ -6,13 +6,12 @@
 
 uintptr_t __stack_chk_guard;
 
-void __init_ssp(size_t *auxv)
+void __init_ssp(void *entropy)
 {
        size_t i;
        pthread_t self = __pthread_self_init();
        uintptr_t canary;
-       for (i=0; auxv[i] && auxv[i]!=AT_RANDOM; i+=2);
-       if (auxv[i]) memcpy(&canary, (void *)auxv[i+1], sizeof canary);
+       if (entropy) memcpy(&canary, entropy, sizeof canary);
        else canary = (uintptr_t)&canary * 1103515245;
        a_cas_l(&__stack_chk_guard, 0, canary);
        self->canary = __stack_chk_guard;
index 33ef7e55f05b1dc2dbce05d15f071039cde712b7..c3cb6115b50e0177b17606b72fa23bcc670fd7d0 100644 (file)
@@ -105,7 +105,7 @@ static pthread_mutex_t init_fini_lock = { ._m_type = PTHREAD_MUTEX_RECURSIVE };
 
 struct debug *_dl_debug_addr = &debug;
 
-#define AUX_CNT 24
+#define AUX_CNT 38
 #define DYN_CNT 34
 
 static void decode_vec(size_t *v, size_t *a, size_t cnt)
@@ -967,7 +967,7 @@ void *__dynlink(int argc, char **argv)
        debug.state = 0;
        _dl_debug_state();
 
-       if (ssp_used) __init_ssp(auxv);
+       if (ssp_used) __init_ssp((void *)aux[AT_RANDOM]);
 
        atexit(do_fini);
        do_init_fini(tail);
index 92ce9ffb5d6e7852445de7eb1bb0d03571132b6b..6327a9429155e6ae757c31ed340fe152cdf08e6c 100644 (file)
@@ -144,7 +144,7 @@ int pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict attr,
                flags -= 0x200000;
        }
        new->unblock_cancel = self->cancel;
-       new->canary = self->canary ^ (uintptr_t)&new;
+       new->canary = self->canary;
        stack = (void *)new;
 
        a_inc(&libc.threads_minus_1);