Finalize arg, env, aux migration (2/3) (CXX) (BB)
authorKevin Klues <klueska@cs.berkeley.edu>
Mon, 13 Jul 2015 06:31:12 +0000 (23:31 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 14 Jul 2015 14:33:16 +0000 (10:33 -0400)
In this commit I remove a few sysdep files that we no longer need to
specialize anymore. However, because Akaros needs to have the ability to
reenter the _start function mutliple times, it is impossible to do away
with all sysdeps on these low level interfaces.

The true system dependent stuff has now been isolated in a file called
init.c in sysdeps/akaros (this name is required in order to get it to
link in with crt1.o).  It now introduces a new function called
__libc_vcore_entry(), which handles all the code necessary to deal with
our reentrant _start() function.  Our system dependant _start() function
simply calls out to __libc_vcore_entry() and then jumps to the
_real_start(), as defined by the current architecture (currently only
x86_64).

By becoming compliant with the SYSV ABI all of the code dealing with
unpacking our args, env, and auxv data from procinfo is now unnecessary.

tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/Makefile
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/dl-machine.h [deleted file]
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/dl-sysdep.c [deleted file]
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/init.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/start.c [deleted file]
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/x86_64/start.S [new file with mode: 0644]

index 19ada0c..8d6fc91 100644 (file)
@@ -40,3 +40,9 @@ sysdep_headers += fcall.h
 ifeq ($(subdir),stdlib)
 sysdep_routines += serialize
 endif
+
+# Vcore initialization functions. We want this in ctr1.o so we have to build
+# them in the csu subdir and place them in a spcial file called 'init'. */
+ifeq ($(subdir),csu)
+sysdep_routines += init
+endif
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/dl-machine.h b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/dl-machine.h
deleted file mode 100644 (file)
index 101356c..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/* Machine-dependent ELF dynamic relocation inline functions.  x86-64 version.
-   Copyright (C) 2001-2014 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Andreas Jaeger <aj@suse.de>.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include_next "dl-machine.h"
-
-#undef RTLD_START
-
-/* Initial entry point code for the dynamic linker.
- *    The C function `_dl_start' is the real entry point;
- *        its return value is the user program's entry point.  */
-#define RTLD_START \
-static ElfW(Addr) __attribute_used__ internal_function _dl_start (void *arg);\
-extern char **_environ attribute_hidden;\
-void __attribute__((noreturn)) _start(void)\
-{\
-       /* Pass our stack pointer to _dl_start. */\
-       /* Retreive our user entry point. */\
-       void *rsp, *user_entry;\
-       asm volatile("movq %%rsp, %0" : "=r" (rsp));\
-       user_entry = (void*)_dl_start(rsp);\
-       \
-       /* Clear %rbp to mark outermost frame even for initializers. */\
-       asm volatile("xorq %rbp, %rbp");\
-       \
-       /* Call _dl_init to run the initializers. */\
-       _dl_init(GL(dl_ns[0]._ns_loaded), _dl_argc, INTUSE(_dl_argv), _environ);\
-       \
-       /* Pass our finalizer function to the user in %rdx, as per ELF ABI. */\
-       /* And jump to the user! */\
-       asm volatile(\
-               "movq %0, %%rdx;"\
-               "jmp *%1;"\
-               : : "r" (_dl_fini), "r" (user_entry) : "rdx"\
-       );\
-       __builtin_unreachable();\
-}
-
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/dl-sysdep.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/dl-sysdep.c
deleted file mode 100644 (file)
index 4f012a9..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#include <ros/procinfo.h>
-
-#define DL_FIND_ARG_COMPONENTS(cookie, argc, argv, envp, auxp) \
-  do {                                                                       \
-    void **_tmp;                                                             \
-    (argc) = 0;                                                                      \
-    while (__procinfo.argp[(argc)])                                          \
-      (argc)++;                                                                      \
-    (argv) = (char **) __procinfo.argp;                                              \
-    (envp) = (argv) + (argc) + 1;                                            \
-    for (_tmp = (void **) (envp); *_tmp; ++_tmp)                             \
-      continue;                                                                      \
-    (auxp) = (void *) ++_tmp;                                                \
-  } while (0)
-
-#include <elf/dl-sysdep.c>
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/init.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/init.c
new file mode 100644 (file)
index 0000000..fe064a0
--- /dev/null
@@ -0,0 +1,75 @@
+#include <abort-instr.h>
+#include <string.h>
+#include <parlib/vcore.h>
+#include <stdio.h>
+#include <ros/syscall.h>
+#include <ros/procinfo.h>
+#include <unistd.h>
+#include <vcore-tls.c>
+#include <ctype.h>
+
+__thread int __vcoreid = 0;
+__thread bool __vcore_context = FALSE;
+
+#define failmsg(str) write(2,str"\n",sizeof(str"\n")-1)
+
+void __attribute__((noreturn)) __uthread_vcore_entry(void)
+{
+       fputs("Define a uthread_vcore_entry() or a vcore_entry(), foo!\n", stderr);
+       abort();
+       __builtin_unreachable();
+}
+weak_alias(__uthread_vcore_entry, uthread_vcore_entry)
+
+void __attribute__((noreturn)) __vcore_entry(void)
+{
+       uthread_vcore_entry();
+       fputs("vcore_entry() should never return!\n", stderr);
+       abort();
+       __builtin_unreachable();
+}
+weak_alias(__vcore_entry, vcore_entry)
+
+void __libc_vcore_entry(int id)
+{
+       static int init = 0;
+       /* For dynamically-linked programs, the first time through,
+        * __vcore_self_on_entry could be clobbered (on x86), because the linker
+        * will have overwritten eax.  Happily, the first time through, we know we
+        * are vcore 0.  Subsequent entries into this routine do not have this
+        * problem. */
+       if (init == 0)
+               id = 0;
+
+       /* vcore0 when it comes up again, and all threads besides thread 0 must
+        * acquire a TCB. */
+       if (init || (id != 0)) {
+               /* The kernel sets the TLS desc for us, based on whatever is in VCPD.
+                *
+                * x86 32-bit TLS is pretty jacked up, so the kernel doesn't set the TLS
+                * desc for us.  it's a little more expensive to do it here, esp for
+                * amd64.  Can remove this when/if we overhaul 32 bit TLS.
+                *
+                * AFAIK, riscv's TLS changes are really cheap, and they don't do it in
+                * the kernel (yet/ever), so they can set their TLS here too. */
+               #ifndef __x86_64__
+               set_tls_desc((void*)__procdata.vcore_preempt_data[id].vcore_tls_desc,
+                            id);
+               #endif
+               /* These TLS setters actually only need to happen once, at init time */
+               __vcoreid = id;
+               __vcore_context = TRUE;
+               __ctype_init(); /* set locale info for ctype functions */
+               vcore_entry();
+               failmsg("why did vcore_entry() return?");
+               abort();
+               #ifdef ABORT_INSTRUCTION
+               ABORT_INSTRUCTION;
+               #endif
+
+               while(1);
+               __builtin_unreachable();
+       }
+       init = 1;
+}
+
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/start.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/start.c
deleted file mode 100644 (file)
index 0e4dfba..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-#include <abort-instr.h>
-#include <string.h>
-#include <parlib/vcore.h>
-#include <stdio.h>
-#include <ros/syscall.h>
-#include <ros/procinfo.h>
-#include <unistd.h>
-#include <vcore-tls.c>
-
-__thread int __vcoreid = 0;
-__thread bool __vcore_context = FALSE;
-
-extern int main(int,char**,char**);
-extern void __libc_csu_init(int,char**,char**);
-extern void __libc_csu_fini(void);
-extern void __libc_start_main(typeof(&main),int,char**,
-              typeof(&__libc_csu_init),
-              typeof(&__libc_csu_fini),
-              void*,void*);
-
-void __uthread_vcore_entry(void)
-{
-       fputs("Define a uthread_vcore_entry() or a vcore_entry(), foo!\n", stderr);
-       abort();
-}
-weak_alias(__uthread_vcore_entry, uthread_vcore_entry)
-
-void __vcore_entry(void)
-{
-       uthread_vcore_entry();
-}
-weak_alias(__vcore_entry, vcore_entry)
-
-#define failmsg(str) write(2,str"\n",sizeof(str"\n")-1)
-
-void
-_start(void)
-{
-       // WARNING: __vcore_self_on_entry must be read before
-       // anything is register-allocated!
-       int id = __vcore_id_on_entry;
-       static int init = 0;
-       // For dynamically-linked programs, the first time through,
-       // __vcore_self_on_entry could be clobbered (on x86), because
-       // the linker will have overwritten eax.  Happily, the first
-       // time through, we know we are vcore 0.  Subsequent entries
-       // into this routine do not have this problem.
-       if(init == 0)
-               id = 0;
-       
-       // vcore0 when it comes up again, and all threads besides thread 0 must
-       // acquire a TCB.
-       if(init || (id != 0))
-       {
-               /* The kernel sets the TLS desc for us, based on whatever is in VCPD.
-                *
-                * x86 32-bit TLS is pretty jacked up, so the kernel doesn't set the TLS
-                * desc for us.  it's a little more expensive to do it here, esp for
-                * amd64.  Can remove this when/if we overhaul 32 bit TLS.
-                *
-                * AFAIK, riscv's TLS changes are really cheap, and they don't do it in
-                * the kernel (yet/ever), so they can set their TLS here too. */
-               #ifndef __x86_64__
-               set_tls_desc((void*)__procdata.vcore_preempt_data[id].vcore_tls_desc,
-                            id);
-               #endif
-               /* These TLS setters actually only need to happen once, at init time */
-               __vcoreid = id;
-               __vcore_context = TRUE;
-               __ctype_init(); /* set locale info for ctype functions */
-               vcore_entry();
-               failmsg("why did vcore_entry() return?");
-               goto diediedie;
-       }
-
-       init = 1;
-
-       char** argv = (char**)alloca(sizeof(__procinfo.argp));
-       memcpy(argv,__procinfo.argp,sizeof(__procinfo.argp));
-
-       char* argbuf = (char*)alloca(sizeof(__procinfo.argbuf));
-       memcpy(argbuf,__procinfo.argbuf,sizeof(__procinfo.argbuf));
-
-       // touch up pointers, but don't mess up auxp!
-       for(int i = 0, zeros = 0; i < PROCINFO_MAX_ARGP; i++)
-       {
-               if(argv[i])
-                       argv[i] += argbuf - __procinfo.argbuf;
-               else if(++zeros == 2)
-                       break;
-       }
-
-       int argc = 0;
-       while(argv[argc])
-               argc++;
-
-       extern char** _environ;
-       _environ = argv+argc+1;
-
-       __libc_start_main(&main, argc, argv, &__libc_csu_init, &__libc_csu_fini,
-                         0, 0);
-
-       failmsg("why did main() return?");
-
-diediedie:
-       abort();
-       #ifdef ABORT_INSTRUCTION
-       ABORT_INSTRUCTION;
-       #endif
-       while(1);
-}
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/x86_64/start.S b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/x86_64/start.S
new file mode 100644 (file)
index 0000000..5da2563
--- /dev/null
@@ -0,0 +1,31 @@
+/* Copyright (c) 2015 Google Inc., All Rights Reserved.
+ * Kevin Klues <klueska@google.com>
+ * See LICENSE for details. */
+
+#define _start _real_start
+#include <sysdeps/x86_64/start.S>
+#undef _start
+
+       .text
+       .globl _start
+       .type _start,@function
+_start:
+       cfi_startproc
+       /* Save rdx on the stack. The SYSV ABI uses rdx as the only register to
+        * pass information to a process (everything else is on the stack). Save
+        * it here since we interpose with a call to __libc_vcore_entry(). */
+       pushq %rdx
+
+       /* Pass vcoreid to __libc_vcore_entry. Akaros passes it to us in the rbx
+        * register. On all but the first time through this function we will
+        * never return. */
+       movq %rbx, %rdi
+       call __libc_vcore_entry
+
+       /* Restore rdx and call out to the real start function. This function is
+        * Only called once even though we may enter on this start function
+        * multiple times. */
+       popq %rdx
+       jmp _real_start
+       cfi_endproc
+