diff options
Diffstat (limited to 'REORG.TODO/hurd/hurdstartup.c')
-rw-r--r-- | REORG.TODO/hurd/hurdstartup.c | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/REORG.TODO/hurd/hurdstartup.c b/REORG.TODO/hurd/hurdstartup.c new file mode 100644 index 0000000000..d057ce1b18 --- /dev/null +++ b/REORG.TODO/hurd/hurdstartup.c @@ -0,0 +1,194 @@ +/* Initial program startup for running under the GNU Hurd. + Copyright (C) 1991-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + 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 <errno.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <hurd.h> +#include <hurd/exec_startup.h> +#include <sysdep.h> +#include <hurd/threadvar.h> +#include <unistd.h> +#include <elf.h> +#include <set-hooks.h> +#include "hurdstartup.h" +#include <argz.h> + +mach_port_t *_hurd_init_dtable; +mach_msg_type_number_t _hurd_init_dtablesize; + +extern void __mach_init (void); + +/* Entry point. This is the first thing in the text segment. + + The exec server started the initial thread in our task with this spot the + PC, and a stack that is presumably big enough. We do basic Mach + initialization so mig-generated stubs work, and then do an exec_startup + RPC on our bootstrap port, to which the exec server responds with the + information passed in the exec call, as well as our original bootstrap + port, and the base address and size of the preallocated stack. + + If using cthreads, we are given a new stack by cthreads initialization and + deallocate the stack set up by the exec server. On the new stack we call + `start1' (above) to do the rest of the startup work. Since the stack may + disappear out from under us in a machine-dependent way, we use a pile of + static variables to communicate the information from exec_startup to start1. + This is unfortunate but preferable to machine-dependent frobnication to copy + the state from the old stack to the new one. */ + + +void +_hurd_startup (void **argptr, void (*main) (intptr_t *data)) +{ + error_t err; + mach_port_t in_bootstrap; + char *args, *env; + mach_msg_type_number_t argslen, envlen; + struct hurd_startup_data data; + char **argv, **envp; + int argc, envc; + intptr_t *argcptr; + vm_address_t addr; + + /* Attempt to map page zero redzoned before we receive any RPC + data that might get allocated there. We can ignore errors. */ + addr = 0; + __vm_map (__mach_task_self (), + &addr, __vm_page_size, 0, 0, MACH_PORT_NULL, 0, 1, + VM_PROT_NONE, VM_PROT_NONE, VM_INHERIT_COPY); + + if (err = __task_get_special_port (__mach_task_self (), TASK_BOOTSTRAP_PORT, + &in_bootstrap)) + LOSE; + + if (in_bootstrap != MACH_PORT_NULL) + { + /* Call the exec server on our bootstrap port and + get all our standard information from it. */ + + argslen = envlen = 0; + data.dtablesize = data.portarraysize = data.intarraysize = 0; + + err = __exec_startup_get_info (in_bootstrap, + &data.user_entry, + &data.phdr, &data.phdrsz, + &data.stack_base, &data.stack_size, + &data.flags, + &args, &argslen, + &env, &envlen, + &data.dtable, &data.dtablesize, + &data.portarray, &data.portarraysize, + &data.intarray, &data.intarraysize); + __mach_port_deallocate (__mach_task_self (), in_bootstrap); + } + + if (err || in_bootstrap == MACH_PORT_NULL || (data.flags & EXEC_STACK_ARGS)) + { + /* Either we have no bootstrap port, or the RPC to the exec server + failed, or whoever started us up passed the flag saying args are + on the stack. Try to snarf the args in the canonical Mach way. + Hopefully either they will be on the stack as expected, or the + stack will be zeros so we don't crash. */ + + argcptr = (intptr_t *) argptr; + argc = argcptr[0]; + argv = (char **) &argcptr[1]; + envp = &argv[argc + 1]; + envc = 0; + while (envp[envc]) + ++envc; + } + else + { + /* Turn the block of null-separated strings we were passed for the + arguments and environment into vectors of pointers to strings. */ + + /* Count up the arguments so we can allocate ARGV. */ + argc = __argz_count (args, argslen); + /* Count up the environment variables so we can allocate ENVP. */ + envc = __argz_count (env, envlen); + + /* There were some arguments. Allocate space for the vectors of + pointers and fill them in. We allocate the space for the + environment pointers immediately after the argv pointers because + the ELF ABI will expect it. */ + argcptr = __alloca (sizeof (intptr_t) + + (argc + 1 + envc + 1) * sizeof (char *) + + sizeof (struct hurd_startup_data)); + *argcptr = argc; + argv = (void *) (argcptr + 1); + __argz_extract (args, argslen, argv); + + /* There was some environment. */ + envp = &argv[argc + 1]; + __argz_extract (env, envlen, envp); + } + + if (err || in_bootstrap == MACH_PORT_NULL) + { + /* Either we have no bootstrap port, or the RPC to the exec server + failed. Set all our other variables to have empty information. */ + + data.flags = 0; + args = env = NULL; + argslen = envlen = 0; + data.dtable = NULL; + data.dtablesize = 0; + data.portarray = NULL; + data.portarraysize = 0; + data.intarray = NULL; + data.intarraysize = 0; + } + else if ((void *) &envp[envc + 1] == argv[0]) + { + /* The arguments arrived on the stack from the kernel, but our + protocol requires some space after them for a `struct + hurd_startup_data'. Move them. */ + struct + { + intptr_t count; + char *argv[argc + 1]; + char *envp[envc + 1]; + struct hurd_startup_data data; + } *args = alloca (sizeof *args); + if ((void *) &args[1] == (void *) argcptr) + args = alloca (-((char *) &args->data - (char *) args)); + memmove (args, argcptr, (char *) &args->data - (char *) args); + argcptr = (void *) args; + argv = args->argv; + envp = args->envp; + } + + { + struct hurd_startup_data *d = (void *) &envp[envc + 1]; + + if ((void *) d != argv[0]) + { + *d = data; + _hurd_init_dtable = d->dtable; + _hurd_init_dtablesize = d->dtablesize; + } + + (*main) (argcptr); + } + + /* Should never get here. */ + LOSE; + abort (); +} |