mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-25 06:20:06 +00:00
Wed May 10 21:00:47 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
* sysdeps/mach/i386/sysdep.h (RETURN_TO): New macro. * Makerules (install-lib.so): Add %.so for each %_pic.a. * sysdeps/mach/hurd/i386/init-first.c: New file.
This commit is contained in:
parent
87220b3563
commit
99b306dc44
@ -1,5 +1,11 @@
|
||||
Wed May 10 21:00:47 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
|
||||
|
||||
* sysdeps/mach/i386/sysdep.h (RETURN_TO): New macro.
|
||||
|
||||
Tue May 9 01:26:52 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
|
||||
|
||||
* Makerules (install-lib.so): Add %.so for each %_pic.a.
|
||||
|
||||
* sysdeps/i386/elf/start.S (__data_start): Define this symbol as
|
||||
the first thing in .data.
|
||||
|
||||
@ -108,6 +114,7 @@ Tue May 2 01:52:58 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
|
||||
* sysdeps/i386/elf/start.S: New file.
|
||||
* sysdeps/generic/dl-sysdep.c: New file.
|
||||
* sysdeps/mach/hurd/dl-sysdep.c: New file.
|
||||
* sysdeps/mach/hurd/i386/init-first.c: New file.
|
||||
* sysdeps/i386/init-first.c: New file.
|
||||
* sysdeps/stub/init-first.c: New file.
|
||||
|
||||
|
@ -26,8 +26,10 @@ Cambridge, MA 02139, USA. */
|
||||
#include <sysdep.h>
|
||||
#include <hurd/threadvar.h>
|
||||
#include <unistd.h>
|
||||
#include <elf.h>
|
||||
#include "set-hooks.h"
|
||||
#include "hurdmalloc.h" /* XXX */
|
||||
#include "hurdstartup.h"
|
||||
|
||||
mach_port_t *_hurd_init_dtable;
|
||||
mach_msg_type_number_t _hurd_init_dtablesize;
|
||||
@ -41,39 +43,10 @@ unsigned long int __hurd_sigthread_stack_base;
|
||||
unsigned long int __hurd_sigthread_stack_end;
|
||||
unsigned long int *__hurd_sigthread_variables;
|
||||
|
||||
vm_address_t _hurd_stack_base;
|
||||
vm_size_t _hurd_stack_size;
|
||||
|
||||
/* Things that want to be run before _hurd_init or much anything else.
|
||||
Importantly, these are called before anything tries to use malloc. */
|
||||
DEFINE_HOOK (_hurd_preinit_hook, (void));
|
||||
|
||||
extern void __mach_init (void);
|
||||
extern void __libc_init (int argc, char **argv, char **envp);
|
||||
|
||||
void *(*_cthread_init_routine) (void); /* Returns new SP to use. */
|
||||
void (*_cthread_exit_routine) (int status) __attribute__ ((__noreturn__));
|
||||
|
||||
int _hurd_split_args (char *, size_t, char **);
|
||||
|
||||
/* These communicate values from _hurd_startup to start1,
|
||||
where we cannot use the stack for anything. */
|
||||
struct info
|
||||
{
|
||||
char *args, *env;
|
||||
mach_port_t *portarray;
|
||||
int *intarray;
|
||||
mach_msg_type_number_t argslen, envlen, portarraysize, intarraysize;
|
||||
int flags;
|
||||
char **argv, **envp;
|
||||
int argc;
|
||||
void (*hurd_main) (int, char **, char **,
|
||||
mach_port_t *, mach_msg_type_number_t,
|
||||
int *, mach_msg_type_number_t);
|
||||
};
|
||||
|
||||
static void start1 (struct info *) __attribute__ ((__noreturn__));
|
||||
|
||||
|
||||
/* Entry point. This is the first thing in the text segment.
|
||||
|
||||
@ -92,25 +65,22 @@ static void start1 (struct info *) __attribute__ ((__noreturn__));
|
||||
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) (int, char **, char **,
|
||||
mach_port_t *, mach_msg_type_number_t,
|
||||
int *, mach_msg_type_number_t))
|
||||
_hurd_startup (void **argptr, void (*main) (int *data))
|
||||
{
|
||||
error_t err;
|
||||
mach_port_t in_bootstrap;
|
||||
struct info i;
|
||||
char *args, *env;
|
||||
mach_msg_type_number_t argslen, envlen;
|
||||
struct hurd_startup_data data;
|
||||
char **argv, **envp;
|
||||
int argc, envc;
|
||||
int *argcptr;
|
||||
|
||||
/* Basic Mach initialization, must be done before RPCs can be done. */
|
||||
__mach_init ();
|
||||
|
||||
/* Run things that want to do initialization as soon as possible. We do
|
||||
this before exec_startup so that no out of line data arrives and
|
||||
clutters up the address space before brk initialization. */
|
||||
|
||||
RUN_HOOK (_hurd_preinit_hook, ());
|
||||
|
||||
if (err = __task_get_special_port (__mach_task_self (), TASK_BOOTSTRAP_PORT,
|
||||
&in_bootstrap))
|
||||
LOSE;
|
||||
@ -120,153 +90,113 @@ _hurd_startup (void **argptr,
|
||||
/* Call the exec server on our bootstrap port and
|
||||
get all our standard information from it. */
|
||||
|
||||
i.argslen = i.envlen = 0;
|
||||
_hurd_init_dtablesize = i.portarraysize = i.intarraysize = 0;
|
||||
argslen = envlen = 0;
|
||||
data.dtablesize = data.portarraysize = data.intarraysize = 0;
|
||||
|
||||
err = __exec_startup (in_bootstrap,
|
||||
&_hurd_stack_base, &_hurd_stack_size,
|
||||
&i.flags,
|
||||
&i.args, &i.argslen, &i.env, &i.envlen,
|
||||
&_hurd_init_dtable, &_hurd_init_dtablesize,
|
||||
&i.portarray, &i.portarraysize,
|
||||
&i.intarray, &i.intarraysize);
|
||||
&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)
|
||||
{
|
||||
#if 0
|
||||
/* Either we have no bootstrap port, or the RPC to the exec server
|
||||
failed. 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. Set all our other
|
||||
variables to have empty information. */
|
||||
|
||||
ENTRY_SP (argptr);
|
||||
/* SNARF_ARGS (ARGPTR, ARGC, ARGV, ENVP) snarfs the arguments and
|
||||
environment from the stack, assuming they were put there by the
|
||||
microkernel. */
|
||||
SNARF_ARGS (argptr, i.argc, i.argv, i.envp);
|
||||
XXX XXX XXX
|
||||
|
||||
SNARF_ARGS (argptr, argc, argv, envp);
|
||||
#endif
|
||||
|
||||
i.flags = 0;
|
||||
i.args = i.env = NULL;
|
||||
i.argslen = i.envlen = 0;
|
||||
_hurd_init_dtable = NULL;
|
||||
_hurd_init_dtablesize = 0;
|
||||
i.portarray = NULL;
|
||||
i.portarraysize = 0;
|
||||
i.intarray = NULL;
|
||||
i.intarraysize = 0;
|
||||
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
|
||||
i.argv = i.envp = NULL;
|
||||
|
||||
i.hurd_main = main;
|
||||
|
||||
/* The user might have defined a value for this, to get more variables.
|
||||
Otherwise it will be zero on startup. We must make sure it is set
|
||||
properly before before cthreads initialization, so cthreads can know
|
||||
how much space to leave for thread variables. */
|
||||
if (__hurd_threadvar_max < _HURD_THREADVAR_MAX)
|
||||
__hurd_threadvar_max = _HURD_THREADVAR_MAX;
|
||||
|
||||
/* Do cthreads initialization and switch to the cthread stack. */
|
||||
|
||||
if (_cthread_init_routine != NULL)
|
||||
CALL_WITH_SP (start1, i, (*_cthread_init_routine) ());
|
||||
else
|
||||
start1 (&i);
|
||||
|
||||
/* Should never get here. */
|
||||
LOSE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
start1 (struct info *info)
|
||||
{
|
||||
register int envc = 0;
|
||||
|
||||
{
|
||||
/* Check if the stack we are now on is different from
|
||||
the one described by _hurd_stack_{base,size}. */
|
||||
|
||||
char dummy;
|
||||
const vm_address_t newsp = (vm_address_t) &dummy;
|
||||
|
||||
if (_hurd_stack_size != 0 && (newsp < _hurd_stack_base ||
|
||||
newsp - _hurd_stack_base > _hurd_stack_size))
|
||||
/* The new stack pointer does not intersect with the
|
||||
stack the exec server set up for us, so free that stack. */
|
||||
__vm_deallocate (__mach_task_self (),
|
||||
_hurd_stack_base, _hurd_stack_size);
|
||||
}
|
||||
|
||||
if (__hurd_threadvar_stack_mask == 0)
|
||||
{
|
||||
/* We are not using cthreads, so we will have just a single allocated
|
||||
area for the per-thread variables of the main user thread. */
|
||||
unsigned long int i;
|
||||
__hurd_threadvar_stack_offset
|
||||
= (unsigned long int) malloc (__hurd_threadvar_max *
|
||||
sizeof (unsigned long int));
|
||||
if (__hurd_threadvar_stack_offset == 0)
|
||||
__libc_fatal ("Can't allocate single-threaded per-thread variables.");
|
||||
for (i = 0; i < __hurd_threadvar_max; ++i)
|
||||
((unsigned long int *) __hurd_threadvar_stack_offset)[i] = 0;
|
||||
}
|
||||
argv = envp = NULL;
|
||||
|
||||
|
||||
/* Turn the block of null-separated strings we were passed for the
|
||||
arguments and environment into vectors of pointers to strings. */
|
||||
|
||||
if (! info->argv)
|
||||
{
|
||||
if (info->args)
|
||||
/* Count up the arguments so we can allocate ARGV. */
|
||||
info->argc = _hurd_split_args (args, argslen, NULL);
|
||||
if (! info->args || info->argc == 0)
|
||||
{
|
||||
/* No arguments passed; set argv to { NULL }. */
|
||||
info->argc = 0;
|
||||
info->args = NULL;
|
||||
info->argv = (char **) &info->args;
|
||||
}
|
||||
}
|
||||
|
||||
if (! info->envp)
|
||||
{
|
||||
if (info->env)
|
||||
/* Count up the environment variables so we can allocate ENVP. */
|
||||
envc = _hurd_split_args (info->env, info->envlen, NULL);
|
||||
if (! info->env || envc == 0)
|
||||
{
|
||||
/* No environment passed; set __environ to { NULL }. */
|
||||
info->env = NULL;
|
||||
info->envp = (char **) &env;
|
||||
}
|
||||
}
|
||||
|
||||
if (! info->argv)
|
||||
{
|
||||
/* There were some arguments.
|
||||
Allocate space for the vectors of pointers and fill them in. */
|
||||
info->argv = __alloca ((info->argc + 1) * sizeof (char *));
|
||||
_hurd_split_args (info->args, info->argslen, info->argv);
|
||||
}
|
||||
|
||||
if (! info->envp)
|
||||
if (! argv)
|
||||
{
|
||||
/* There was some environment.
|
||||
Allocate space for the vectors of pointers and fill them in. */
|
||||
info->envp = __alloca ((envc + 1) * sizeof (char *));
|
||||
_hurd_split_args (info->env, info->envlen, info->envp);
|
||||
/* Count up the arguments so we can allocate ARGV. */
|
||||
argc = _hurd_split_args (args, argslen, NULL);
|
||||
/* Count up the environment variables so we can allocate ENVP. */
|
||||
envc = _hurd_split_args (env, envlen, NULL);
|
||||
|
||||
/* 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 (int) +
|
||||
(argc + 1 + envc + 1) * sizeof (char *) +
|
||||
sizeof (struct hurd_startup_data));
|
||||
*argcptr = argc;
|
||||
argv = (void *) (argcptr + 1);
|
||||
_hurd_split_args (args, argslen, argv);
|
||||
|
||||
/* There was some environment. */
|
||||
envp = &argv[argc + 1];
|
||||
_hurd_split_args (env, envlen, envp);
|
||||
}
|
||||
|
||||
(*info->hurd_main) (info->argc, info->argv, info->envp,
|
||||
info->portarray, info->portarraysize,
|
||||
info->intarray, info->intarraysize);
|
||||
{
|
||||
struct hurd_startup_data *d = (void *) &envp[envc + 1];
|
||||
|
||||
/* XXX hardcoded until exec_startup changes */
|
||||
#ifdef PIC
|
||||
#if 0
|
||||
const Elf32_Ehdr *ehdr = (const void *) 0x08000000;
|
||||
vm_address_t phdr = 0x08000000 + ehdr->e_phoff;
|
||||
vm_size_t phdrsz = ehdr->e_phnum * ehdr->e_phentsize;
|
||||
vm_address_t user_entry = ehdr->e_entry;
|
||||
#else
|
||||
vm_address_t phdr = 0;
|
||||
vm_size_t phdrsz = 0;
|
||||
extern void _start();
|
||||
vm_address_t user_entry = (vm_address_t) &_start;
|
||||
#endif
|
||||
#else
|
||||
vm_address_t phdr = 0;
|
||||
vm_size_t phdrsz = 0;
|
||||
vm_address_t user_entry = 0;
|
||||
#endif
|
||||
|
||||
*d = data;
|
||||
_hurd_init_dtable = d->dtable;
|
||||
_hurd_init_dtablesize = d->dtablesize;
|
||||
d->phdr = phdr;
|
||||
d->phdrsz = phdrsz;
|
||||
d->user_entry = user_entry;
|
||||
|
||||
(*main) (argcptr);
|
||||
}
|
||||
|
||||
/* Should never get here. */
|
||||
LOSE;
|
||||
abort ();
|
||||
}
|
||||
|
||||
/* Split ARGSLEN bytes at ARGS into words, breaking at NUL characters. If
|
||||
|
494
sysdeps/mach/hurd/dl-sysdep.c
Normal file
494
sysdeps/mach/hurd/dl-sysdep.c
Normal file
@ -0,0 +1,494 @@
|
||||
/* Operating system support for run-time dynamic linker. Hurd version.
|
||||
Copyright (C) 1995 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 Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If
|
||||
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
||||
Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <hurd.h>
|
||||
#include <link.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/wait.h>
|
||||
#include <assert.h>
|
||||
#include <sysdep.h>
|
||||
#include <mach/mig_support.h>
|
||||
#include "hurdstartup.h"
|
||||
#include <mach/host_info.h>
|
||||
#include "../stdio/_itoa.h"
|
||||
#include <hurd/auth.h>
|
||||
#include <hurd/term.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "dl-machine.h"
|
||||
|
||||
extern int _dl_argc;
|
||||
extern char **_dl_argv;
|
||||
extern char **_environ;
|
||||
|
||||
struct hurd_startup_data *_dl_hurd_data;
|
||||
|
||||
Elf32_Addr
|
||||
_dl_sysdep_start (void **start_argptr,
|
||||
void (*dl_main) (const Elf32_Phdr *phdr, Elf32_Word phent,
|
||||
Elf32_Addr *user_entry))
|
||||
{
|
||||
void go (int *argdata)
|
||||
{
|
||||
char **p;
|
||||
|
||||
/* Cache the information in various global variables. */
|
||||
_dl_argc = *argdata++;
|
||||
_dl_argv = (void *) argdata;
|
||||
_environ = &_dl_argv[_dl_argc + 1];
|
||||
for (p = _environ; *p; ++p);
|
||||
_dl_hurd_data = (void *) ++p;
|
||||
|
||||
_dl_secure = _dl_hurd_data->flags & EXEC_SECURE;
|
||||
|
||||
/* Call elf/rtld.c's main program. It will set everything
|
||||
up and leave us to transfer control to USER_ENTRY. */
|
||||
(*dl_main) ((const Elf32_Phdr *) _dl_hurd_data->phdr,
|
||||
_dl_hurd_data->phdrsz / sizeof (Elf32_Phdr),
|
||||
&_dl_hurd_data->user_entry);
|
||||
|
||||
{
|
||||
extern void _dl_start_user (void);
|
||||
/* Unwind the stack to ARGDATA and simulate a return from _dl_start
|
||||
to the RTLD_START code which will run the user's entry point. */
|
||||
RETURN_TO (argdata, &_dl_start_user, _dl_hurd_data->user_entry);
|
||||
}
|
||||
}
|
||||
|
||||
/* See hurd/hurdstartup.c; this deals with getting information
|
||||
from the exec server and slicing up the arguments.
|
||||
Then it will call `go', above. */
|
||||
_hurd_startup (start_argptr, &go);
|
||||
|
||||
LOSE;
|
||||
}
|
||||
|
||||
/* This is called when all other dynamic linking is finished, before the
|
||||
dynamic linker re-relocates itself when ld.so itself appears in a
|
||||
DT_NEEDED entry. It is called whether of not ld.so is being linked in.
|
||||
|
||||
We take this opportunity to deallocate the reply port and task-self send
|
||||
right user reference we have acquired, since they will not be used again
|
||||
before the library and user code runs. The C library will acquire its
|
||||
own ports in its initialization. */
|
||||
|
||||
void
|
||||
_dl_sysdep_prepare_for_ld_reloc (void)
|
||||
{
|
||||
__mig_dealloc_reply_port (__mig_get_reply_port ());
|
||||
__mach_port_deallocate (__mach_task_self (), __mach_task_self ());
|
||||
}
|
||||
|
||||
int
|
||||
_dl_sysdep_open_zero_fill (void)
|
||||
{
|
||||
return (int) MACH_PORT_NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_dl_sysdep_fatal (const char *msg, ...)
|
||||
{
|
||||
extern __typeof (__io_write) __hurd_intr_rpc_io_write;
|
||||
va_list ap;
|
||||
|
||||
va_start (ap, msg);
|
||||
do
|
||||
{
|
||||
size_t len = strlen (msg);
|
||||
mach_msg_type_number_t nwrote;
|
||||
do
|
||||
{
|
||||
if (__hurd_intr_rpc_io_write (_hurd_init_dtable[2],
|
||||
msg, len, -1, &nwrote))
|
||||
break;
|
||||
len -= nwrote;
|
||||
msg += nwrote;
|
||||
} while (nwrote > 0);
|
||||
msg = va_arg (ap, const char *);
|
||||
} while (msg);
|
||||
va_end (ap);
|
||||
|
||||
_exit (127);
|
||||
}
|
||||
|
||||
|
||||
/* Minimal open/close/mmap implementation sufficient for initial loading of
|
||||
shared libraries. These are weak definitions so that when the
|
||||
dynamic linker re-relocates itself to be user-visible (for -ldl),
|
||||
it will get the user's definition (i.e. usually libc's). */
|
||||
|
||||
int
|
||||
open (const char *file_name, int mode, ...)
|
||||
{
|
||||
extern __typeof (__dir_lookup) __hurd_intr_rpc_dir_lookup;
|
||||
extern __typeof (__io_reauthenticate) __hurd_intr_rpc_io_reauthenticate;
|
||||
enum retry_type doretry;
|
||||
char retryname[1024]; /* XXX string_t LOSES! */
|
||||
file_t startdir, newpt, fileport;
|
||||
int dealloc_dir;
|
||||
int nloops;
|
||||
|
||||
|
||||
assert (mode == O_RDONLY);
|
||||
|
||||
|
||||
startdir = _dl_hurd_data->portarray[file_name[0] == '/' ?
|
||||
INIT_PORT_CRDIR : INIT_PORT_CWDIR];
|
||||
|
||||
while (file_name[0] == '/')
|
||||
file_name++;
|
||||
|
||||
if (errno = __hurd_intr_rpc_dir_lookup (startdir, file_name, mode, 0,
|
||||
&doretry, retryname, &fileport))
|
||||
return -1;
|
||||
|
||||
dealloc_dir = 0;
|
||||
nloops = 0;
|
||||
errno = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (dealloc_dir)
|
||||
__mach_port_deallocate (__mach_task_self (), startdir);
|
||||
if (errno)
|
||||
return -1;
|
||||
|
||||
switch (doretry)
|
||||
{
|
||||
case FS_RETRY_REAUTH:
|
||||
{
|
||||
mach_port_t ref = __mach_reply_port ();
|
||||
errno = __hurd_intr_rpc_io_reauthenticate
|
||||
(fileport, ref, MACH_MSG_TYPE_MAKE_SEND);
|
||||
if (! errno)
|
||||
errno = __auth_user_authenticate
|
||||
(_dl_hurd_data->portarray[INIT_PORT_AUTH],
|
||||
fileport,
|
||||
ref, MACH_MSG_TYPE_MAKE_SEND,
|
||||
&newpt);
|
||||
__mach_port_destroy (__mach_task_self (), ref);
|
||||
}
|
||||
__mach_port_deallocate (__mach_task_self (), fileport);
|
||||
if (errno)
|
||||
return -1;
|
||||
fileport = newpt;
|
||||
/* Fall through. */
|
||||
|
||||
case FS_RETRY_NORMAL:
|
||||
#ifdef SYMLOOP_MAX
|
||||
if (nloops++ >= SYMLOOP_MAX)
|
||||
{
|
||||
errno = ELOOP;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* An empty RETRYNAME indicates we have the final port. */
|
||||
if (retryname[0] == '\0')
|
||||
{
|
||||
mach_port_t memobj_rd, memobj_wr;
|
||||
extern __typeof (__io_map) __hurd_intr_rpc_io_map;
|
||||
|
||||
dealloc_dir = 1;
|
||||
|
||||
opened:
|
||||
/* We have the file open. Now map it. */
|
||||
errno = __hurd_intr_rpc_io_map (fileport,
|
||||
&memobj_rd, &memobj_wr);
|
||||
if (dealloc_dir)
|
||||
__mach_port_deallocate (__mach_task_self (), fileport);
|
||||
if (errno)
|
||||
return -1;
|
||||
if (memobj_wr != MACH_PORT_NULL)
|
||||
__mach_port_deallocate (__mach_task_self (), memobj_wr);
|
||||
|
||||
return (int) memobj_rd;
|
||||
}
|
||||
|
||||
startdir = fileport;
|
||||
dealloc_dir = 1;
|
||||
file_name = retryname;
|
||||
break;
|
||||
|
||||
case FS_RETRY_MAGICAL:
|
||||
switch (retryname[0])
|
||||
{
|
||||
case '/':
|
||||
startdir = _dl_hurd_data->portarray[INIT_PORT_CRDIR];
|
||||
dealloc_dir = 0;
|
||||
if (fileport != MACH_PORT_NULL)
|
||||
__mach_port_deallocate (__mach_task_self (), fileport);
|
||||
file_name = &retryname[1];
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
if (retryname[1] == 'd' && retryname[2] == '/')
|
||||
{
|
||||
int fd;
|
||||
char *end;
|
||||
errno = 0;
|
||||
fd = (int) strtol (retryname, &end, 10);
|
||||
if (end == NULL || errno || /* Malformed number. */
|
||||
/* Check for excess text after the number. A slash
|
||||
is valid; it ends the component. Anything else
|
||||
does not name a numeric file descriptor. */
|
||||
(*end != '/' && *end != '\0'))
|
||||
{
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
if (fd < 0 || fd >= _dl_hurd_data->dtablesize ||
|
||||
_dl_hurd_data->dtable[fd] == MACH_PORT_NULL)
|
||||
{
|
||||
/* If the name was a proper number, but the file
|
||||
descriptor does not exist, we return EBADF instead
|
||||
of ENOENT. */
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
fileport = _dl_hurd_data->dtable[fd];
|
||||
if (*end == '\0')
|
||||
{
|
||||
/* This descriptor is the file port we want. */
|
||||
dealloc_dir = 0;
|
||||
goto opened;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Do a normal retry on the remaining components. */
|
||||
startdir = fileport;
|
||||
dealloc_dir = 1;
|
||||
file_name = end + 1; /* Skip the slash. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
goto bad_magic;
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
if (retryname[1] == 'a' && retryname[2] == 'c' &&
|
||||
retryname[3] == 'h' && retryname[4] == 't' &&
|
||||
retryname[5] == 'y' && retryname[6] == 'p' &&
|
||||
retryname[7] == 'e')
|
||||
{
|
||||
error_t err;
|
||||
struct host_basic_info hostinfo;
|
||||
mach_msg_type_number_t hostinfocnt = HOST_BASIC_INFO_COUNT;
|
||||
char *p;
|
||||
if (err = __host_info (__mach_host_self (), HOST_BASIC_INFO,
|
||||
(natural_t *) &hostinfo,
|
||||
&hostinfocnt))
|
||||
return err;
|
||||
if (hostinfocnt != HOST_BASIC_INFO_COUNT)
|
||||
return EGRATUITOUS;
|
||||
p = _itoa (hostinfo.cpu_subtype, &retryname[8], 10, 0);
|
||||
*--p = '/';
|
||||
p = _itoa (hostinfo.cpu_type, &retryname[8], 10, 0);
|
||||
if (p < retryname)
|
||||
abort (); /* XXX write this right if this ever happens */
|
||||
if (p > retryname)
|
||||
strcpy (retryname, p);
|
||||
startdir = fileport;
|
||||
dealloc_dir = 1;
|
||||
}
|
||||
else
|
||||
goto bad_magic;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
if (retryname[1] == 't' && retryname[2] == 'y')
|
||||
switch (retryname[3])
|
||||
{
|
||||
error_t opentty (file_t *result)
|
||||
{
|
||||
error_t err;
|
||||
file_t unauth;
|
||||
err = __termctty_open_terminal
|
||||
(_dl_hurd_data->portarray[INIT_PORT_CTTYID],
|
||||
mode, &unauth);
|
||||
if (! err)
|
||||
{
|
||||
mach_port_t ref = __mach_reply_port ();
|
||||
err = __hurd_intr_rpc_io_reauthenticate
|
||||
(unauth, ref, MACH_MSG_TYPE_MAKE_SEND);
|
||||
if (! err)
|
||||
err = __auth_user_authenticate
|
||||
(_dl_hurd_data->portarray[INIT_PORT_AUTH],
|
||||
unauth,
|
||||
ref, MACH_MSG_TYPE_MAKE_SEND,
|
||||
result);
|
||||
__mach_port_deallocate (__mach_task_self (),
|
||||
unauth);
|
||||
__mach_port_destroy (__mach_task_self (), ref);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
case '\0':
|
||||
if (errno = opentty (&fileport))
|
||||
return -1;
|
||||
dealloc_dir = 1;
|
||||
goto opened;
|
||||
case '/':
|
||||
if (errno = opentty (&startdir))
|
||||
return -1;
|
||||
dealloc_dir = 1;
|
||||
strcpy (retryname, &retryname[4]);
|
||||
break;
|
||||
default:
|
||||
goto bad_magic;
|
||||
}
|
||||
else
|
||||
goto bad_magic;
|
||||
break;
|
||||
|
||||
default:
|
||||
bad_magic:
|
||||
errno = EGRATUITOUS;
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
errno = EGRATUITOUS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
errno = __hurd_intr_rpc_dir_lookup (startdir, file_name, mode, 0,
|
||||
&doretry, retryname, &fileport);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
close (int fd)
|
||||
{
|
||||
if (fd != (int) MACH_PORT_NULL)
|
||||
__mach_port_deallocate (__mach_task_self (), (mach_port_t) fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
caddr_t
|
||||
mmap (caddr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
|
||||
{
|
||||
vm_prot_t vmprot;
|
||||
vm_address_t mapaddr;
|
||||
|
||||
vmprot = VM_PROT_NONE;
|
||||
if (prot & PROT_READ)
|
||||
vmprot |= VM_PROT_READ;
|
||||
if (prot & PROT_WRITE)
|
||||
vmprot |= VM_PROT_WRITE;
|
||||
if (prot & PROT_EXEC)
|
||||
vmprot |= VM_PROT_EXECUTE;
|
||||
|
||||
mapaddr = (vm_address_t) addr;
|
||||
errno = __vm_map (__mach_task_self (),
|
||||
&mapaddr, (vm_size_t) len, (vm_address_t) 0,
|
||||
!(flags & MAP_FIXED),
|
||||
(mach_port_t) fd, (vm_offset_t) offset,
|
||||
flags & (MAP_COPY|MAP_PRIVATE),
|
||||
vmprot, VM_PROT_ALL,
|
||||
(flags & MAP_INHERIT) ? VM_INHERIT_COPY : VM_INHERIT_NONE);
|
||||
return errno ? (caddr_t) -1 : (caddr_t) mapaddr;
|
||||
}
|
||||
|
||||
void
|
||||
_exit (int status)
|
||||
{
|
||||
extern __typeof (__proc_mark_exit) __hurd_intr_rpc_proc_mark_exit;
|
||||
__hurd_intr_rpc_proc_mark_exit (_dl_hurd_data->portarray[INIT_PORT_PROC],
|
||||
W_EXITCODE (status, 0));
|
||||
while (__task_terminate (__mach_task_self ()))
|
||||
__mach_task_self_ = (__mach_task_self) ();
|
||||
}
|
||||
|
||||
weak_symbol (_exit)
|
||||
weak_symbol (open)
|
||||
weak_symbol (close)
|
||||
weak_symbol (mmap)
|
||||
|
||||
/* Minimal `malloc' allocator for use while loading shared libraries.
|
||||
Only small blocks are allocated, and none are ever freed. */
|
||||
|
||||
void *
|
||||
malloc (size_t n)
|
||||
{
|
||||
static vm_address_t ptr, end;
|
||||
void *block;
|
||||
|
||||
if (end == 0)
|
||||
{
|
||||
/* Consume any unused space in the last page of our data segment. */
|
||||
extern char _end;
|
||||
ptr = (vm_address_t) &_end;
|
||||
end = round_page (ptr);
|
||||
}
|
||||
|
||||
/* Make sure the allocation pointer is ideally aligned. */
|
||||
ptr += sizeof (double) - 1;
|
||||
ptr &= ~(sizeof (double) - 1);
|
||||
|
||||
if (ptr + n >= end)
|
||||
{
|
||||
/* Insufficient space left; allocate another page. */
|
||||
vm_address_t page;
|
||||
assert (n <= __vm_page_size);
|
||||
__vm_allocate (__mach_task_self (), &page, __vm_page_size, 1);
|
||||
if (page != end)
|
||||
ptr = page;
|
||||
end = page + __vm_page_size;
|
||||
}
|
||||
|
||||
block = (void *) ptr;
|
||||
ptr += n;
|
||||
return block;
|
||||
}
|
||||
|
||||
weak_symbol (malloc)
|
||||
|
||||
/* These should never be called. */
|
||||
void *realloc (void *ptr, size_t n) { ptr += n; abort (); }
|
||||
void free (void *ptr) { ptr = ptr; abort (); }
|
||||
weak_symbol (realloc)
|
||||
weak_symbol (free)
|
||||
|
||||
/* Avoid signal frobnication in setjmp/longjmp. */
|
||||
|
||||
int __sigjmp_save (sigjmp_buf env, int savemask)
|
||||
{ env[0].__mask_was_saved = savemask; return 0; }
|
||||
weak_symbol (__sigjmp_save)
|
||||
|
||||
void
|
||||
longjmp (jmp_buf env, int val) { __longjmp (env[0].__jmpbuf, val); }
|
||||
weak_symbol (longjmp)
|
||||
|
||||
|
||||
/* Stub out this function that is called by interruptible RPC stubs. It
|
||||
should never get called during initial dynamic linking, because we use
|
||||
only the raw MiG stub functions __hurd_intr_rpc_*. Since this defn is
|
||||
weak, the real defn in libc.so will override it if we are linked into
|
||||
the user program (-ldl). */
|
||||
struct hurd_sigstate *
|
||||
_hurd_thread_sigstate (thread_t thread) { thread = thread; abort (); }
|
||||
weak_symbol (_hurd_thread_sigstate)
|
172
sysdeps/mach/hurd/i386/init-first.c
Normal file
172
sysdeps/mach/hurd/i386/init-first.c
Normal file
@ -0,0 +1,172 @@
|
||||
/* Initialization code run first thing by the ELF startup code. For i386/Hurd.
|
||||
Copyright (C) 1995 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 Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If
|
||||
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
||||
Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <hurd.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include "hurdstartup.h"
|
||||
#include "set-hooks.h"
|
||||
#include "hurdmalloc.h" /* XXX */
|
||||
|
||||
extern void __mach_init (void);
|
||||
extern void __libc_init (int, char **, char **);
|
||||
|
||||
void *(*_cthread_init_routine) (void); /* Returns new SP to use. */
|
||||
void (*_cthread_exit_routine) (int status) __attribute__ ((__noreturn__));
|
||||
|
||||
|
||||
/* Things that want to be run before _hurd_init or much anything else.
|
||||
Importantly, these are called before anything tries to use malloc. */
|
||||
DEFINE_HOOK (_hurd_preinit_hook, (void));
|
||||
|
||||
|
||||
static void
|
||||
init1 (int argc, char *arg0, ...)
|
||||
{
|
||||
char **argv = &arg0;
|
||||
char **envp = &argv[argc + 1];
|
||||
struct hurd_startup_data *d;
|
||||
|
||||
__environ = envp;
|
||||
while (*envp)
|
||||
++envp;
|
||||
d = (void *) ++envp;
|
||||
|
||||
/* If we are the bootstrap task started by the kernel,
|
||||
then after the environment pointers there is no Hurd
|
||||
data block; the argument strings start there. */
|
||||
if ((void *) d != argv[0])
|
||||
{
|
||||
_hurd_init_dtable = d->dtable;
|
||||
_hurd_init_dtablesize = d->dtablesize;
|
||||
|
||||
{
|
||||
/* Check if the stack we are now on is different from
|
||||
the one described by _hurd_stack_{base,size}. */
|
||||
|
||||
char dummy;
|
||||
const vm_address_t newsp = (vm_address_t) &dummy;
|
||||
|
||||
if (d->stack_size != 0 && (newsp < d->stack_base ||
|
||||
newsp - d->stack_base > d->stack_size))
|
||||
/* The new stack pointer does not intersect with the
|
||||
stack the exec server set up for us, so free that stack. */
|
||||
__vm_deallocate (__mach_task_self (), d->stack_base, d->stack_size);
|
||||
}
|
||||
}
|
||||
|
||||
if (__hurd_threadvar_stack_mask == 0)
|
||||
{
|
||||
/* We are not using cthreads, so we will have just a single allocated
|
||||
area for the per-thread variables of the main user thread. */
|
||||
unsigned long int i;
|
||||
__hurd_threadvar_stack_offset
|
||||
= (unsigned long int) malloc (__hurd_threadvar_max *
|
||||
sizeof (unsigned long int));
|
||||
if (__hurd_threadvar_stack_offset == 0)
|
||||
__libc_fatal ("Can't allocate single-threaded per-thread variables.");
|
||||
for (i = 0; i < __hurd_threadvar_max; ++i)
|
||||
((unsigned long int *) __hurd_threadvar_stack_offset)[i] = 0;
|
||||
}
|
||||
|
||||
if ((void *) d != argv[0] && (d->portarray || d->intarray))
|
||||
/* Initialize library data structures, start signal processing, etc. */
|
||||
_hurd_init (d->flags, argv,
|
||||
d->portarray, d->portarraysize,
|
||||
d->intarray, d->intarraysize);
|
||||
|
||||
__libc_init (argc, argv, __environ);
|
||||
}
|
||||
|
||||
static void
|
||||
init (int *data, int retaddr)
|
||||
{
|
||||
int argc = *data;
|
||||
char **argv = (void *) (data + 1);
|
||||
char **envp = &argv[argc + 1];
|
||||
struct hurd_startup_data *d;
|
||||
|
||||
__environ = envp;
|
||||
while (*envp)
|
||||
++envp;
|
||||
d = (void *) ++envp;
|
||||
|
||||
/* The user might have defined a value for this, to get more variables.
|
||||
Otherwise it will be zero on startup. We must make sure it is set
|
||||
properly before before cthreads initialization, so cthreads can know
|
||||
how much space to leave for thread variables. */
|
||||
if (__hurd_threadvar_max < _HURD_THREADVAR_MAX)
|
||||
__hurd_threadvar_max = _HURD_THREADVAR_MAX;
|
||||
|
||||
if (_cthread_init_routine)
|
||||
{
|
||||
/* Initialize cthreads, which will allocate us a new stack to run on. */
|
||||
void *newsp = (*_cthread_init_routine) ();
|
||||
/* Copy the argdata from the old stack to the new one. */
|
||||
newsp = memcpy (newsp - ((char *) &d[1] - (char *) data), data,
|
||||
(char *) &d[1] - (char *) data);
|
||||
data = newsp;
|
||||
}
|
||||
|
||||
/* Call `init1' (above) with the user code as the return address,
|
||||
and the argument data immediately above that on the stack. */
|
||||
*--data = retaddr;
|
||||
asm volatile ("movl %0, %%esp; jmp %*%1" : : "g" (data), "r" (&init1));
|
||||
}
|
||||
|
||||
|
||||
#ifdef PIC
|
||||
/* This function is called to initialize the shared C library.
|
||||
It is called just before the user _start code from i386/elf/start.S,
|
||||
with the stack set up as that code gets it. */
|
||||
|
||||
static void soinit (int argc, ...) __attribute__ ((unused, section (".init")));
|
||||
|
||||
static void
|
||||
soinit (int argc, ...)
|
||||
{
|
||||
/* Initialize data structures so we can do RPCs. */
|
||||
__mach_init ();
|
||||
|
||||
RUN_HOOK (_hurd_preinit_hook, ());
|
||||
|
||||
init (&argc, (&argc)[-1]);
|
||||
|
||||
(void) &soinit; /* Avoid gcc optimizing this fn out. */
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void
|
||||
__libc_init_first (int argc, ...)
|
||||
{
|
||||
#ifndef PIC
|
||||
void doinit (int *data)
|
||||
{
|
||||
init (data, (&argc)[-1]);
|
||||
}
|
||||
|
||||
/* Initialize data structures so we can do RPCs. */
|
||||
__mach_init ();
|
||||
|
||||
RUN_HOOK (_hurd_preinit_hook, ());
|
||||
|
||||
_hurd_startup ((void **) &argc, &doinit);
|
||||
#endif
|
||||
}
|
@ -44,6 +44,11 @@ Cambridge, MA 02139, USA. */
|
||||
"g" (ptr), "m" (*(long int *) (fn)) : "%esp"); \
|
||||
} while (0)
|
||||
|
||||
#define RETURN_TO(sp, pc, retval) \
|
||||
asm volatile ("movl %0, %%esp; jmp %*%1 # %2" \
|
||||
: : "g" (sp), "r" (pc), "a" (retval))
|
||||
|
||||
|
||||
#define STACK_GROWTH_DOWN
|
||||
|
||||
#include_next <sysdep.h>
|
||||
|
Loading…
Reference in New Issue
Block a user