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>
|
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
|
* sysdeps/i386/elf/start.S (__data_start): Define this symbol as
|
||||||
the first thing in .data.
|
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/i386/elf/start.S: New file.
|
||||||
* sysdeps/generic/dl-sysdep.c: New file.
|
* sysdeps/generic/dl-sysdep.c: New file.
|
||||||
* sysdeps/mach/hurd/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/i386/init-first.c: New file.
|
||||||
* sysdeps/stub/init-first.c: New file.
|
* sysdeps/stub/init-first.c: New file.
|
||||||
|
|
||||||
|
@ -26,8 +26,10 @@ Cambridge, MA 02139, USA. */
|
|||||||
#include <sysdep.h>
|
#include <sysdep.h>
|
||||||
#include <hurd/threadvar.h>
|
#include <hurd/threadvar.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <elf.h>
|
||||||
#include "set-hooks.h"
|
#include "set-hooks.h"
|
||||||
#include "hurdmalloc.h" /* XXX */
|
#include "hurdmalloc.h" /* XXX */
|
||||||
|
#include "hurdstartup.h"
|
||||||
|
|
||||||
mach_port_t *_hurd_init_dtable;
|
mach_port_t *_hurd_init_dtable;
|
||||||
mach_msg_type_number_t _hurd_init_dtablesize;
|
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_stack_end;
|
||||||
unsigned long int *__hurd_sigthread_variables;
|
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 __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 **);
|
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.
|
/* 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
|
This is unfortunate but preferable to machine-dependent frobnication to copy
|
||||||
the state from the old stack to the new one. */
|
the state from the old stack to the new one. */
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_hurd_startup (void **argptr,
|
_hurd_startup (void **argptr, void (*main) (int *data))
|
||||||
void (*main) (int, char **, char **,
|
|
||||||
mach_port_t *, mach_msg_type_number_t,
|
|
||||||
int *, mach_msg_type_number_t))
|
|
||||||
{
|
{
|
||||||
error_t err;
|
error_t err;
|
||||||
mach_port_t in_bootstrap;
|
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. */
|
/* Basic Mach initialization, must be done before RPCs can be done. */
|
||||||
__mach_init ();
|
__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,
|
if (err = __task_get_special_port (__mach_task_self (), TASK_BOOTSTRAP_PORT,
|
||||||
&in_bootstrap))
|
&in_bootstrap))
|
||||||
LOSE;
|
LOSE;
|
||||||
@ -120,153 +90,113 @@ _hurd_startup (void **argptr,
|
|||||||
/* Call the exec server on our bootstrap port and
|
/* Call the exec server on our bootstrap port and
|
||||||
get all our standard information from it. */
|
get all our standard information from it. */
|
||||||
|
|
||||||
i.argslen = i.envlen = 0;
|
argslen = envlen = 0;
|
||||||
_hurd_init_dtablesize = i.portarraysize = i.intarraysize = 0;
|
data.dtablesize = data.portarraysize = data.intarraysize = 0;
|
||||||
|
|
||||||
err = __exec_startup (in_bootstrap,
|
err = __exec_startup (in_bootstrap,
|
||||||
&_hurd_stack_base, &_hurd_stack_size,
|
&data.stack_base, &data.stack_size,
|
||||||
&i.flags,
|
&data.flags, &args, &argslen, &env, &envlen,
|
||||||
&i.args, &i.argslen, &i.env, &i.envlen,
|
&data.dtable, &data.dtablesize,
|
||||||
&_hurd_init_dtable, &_hurd_init_dtablesize,
|
&data.portarray, &data.portarraysize,
|
||||||
&i.portarray, &i.portarraysize,
|
&data.intarray, &data.intarraysize);
|
||||||
&i.intarray, &i.intarraysize);
|
|
||||||
__mach_port_deallocate (__mach_task_self (), in_bootstrap);
|
__mach_port_deallocate (__mach_task_self (), in_bootstrap);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err || in_bootstrap == MACH_PORT_NULL)
|
if (err || in_bootstrap == MACH_PORT_NULL)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
/* Either we have no bootstrap port, or the RPC to the exec server
|
/* Either we have no bootstrap port, or the RPC to the exec server
|
||||||
failed. Try to snarf the args in the canonical Mach way.
|
failed. Try to snarf the args in the canonical Mach way.
|
||||||
Hopefully either they will be on the stack as expected, or the
|
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
|
stack will be zeros so we don't crash. Set all our other
|
||||||
variables to have empty information. */
|
variables to have empty information. */
|
||||||
|
|
||||||
|
ENTRY_SP (argptr);
|
||||||
/* SNARF_ARGS (ARGPTR, ARGC, ARGV, ENVP) snarfs the arguments and
|
/* SNARF_ARGS (ARGPTR, ARGC, ARGV, ENVP) snarfs the arguments and
|
||||||
environment from the stack, assuming they were put there by the
|
environment from the stack, assuming they were put there by the
|
||||||
microkernel. */
|
microkernel. */
|
||||||
SNARF_ARGS (argptr, i.argc, i.argv, i.envp);
|
XXX XXX XXX
|
||||||
|
|
||||||
|
SNARF_ARGS (argptr, argc, argv, envp);
|
||||||
|
#endif
|
||||||
|
|
||||||
i.flags = 0;
|
data.flags = 0;
|
||||||
i.args = i.env = NULL;
|
args = env = NULL;
|
||||||
i.argslen = i.envlen = 0;
|
argslen = envlen = 0;
|
||||||
_hurd_init_dtable = NULL;
|
data.dtable = NULL;
|
||||||
_hurd_init_dtablesize = 0;
|
data.dtablesize = 0;
|
||||||
i.portarray = NULL;
|
data.portarray = NULL;
|
||||||
i.portarraysize = 0;
|
data.portarraysize = 0;
|
||||||
i.intarray = NULL;
|
data.intarray = NULL;
|
||||||
i.intarraysize = 0;
|
data.intarraysize = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
i.argv = i.envp = NULL;
|
argv = 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Turn the block of null-separated strings we were passed for the
|
/* Turn the block of null-separated strings we were passed for the
|
||||||
arguments and environment into vectors of pointers to strings. */
|
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.
|
/* Count up the arguments so we can allocate ARGV. */
|
||||||
Allocate space for the vectors of pointers and fill them in. */
|
argc = _hurd_split_args (args, argslen, NULL);
|
||||||
info->envp = __alloca ((envc + 1) * sizeof (char *));
|
/* Count up the environment variables so we can allocate ENVP. */
|
||||||
_hurd_split_args (info->env, info->envlen, info->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,
|
struct hurd_startup_data *d = (void *) &envp[envc + 1];
|
||||||
info->intarray, info->intarraysize);
|
|
||||||
|
/* 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. */
|
/* Should never get here. */
|
||||||
LOSE;
|
LOSE;
|
||||||
|
abort ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Split ARGSLEN bytes at ARGS into words, breaking at NUL characters. If
|
/* 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"); \
|
"g" (ptr), "m" (*(long int *) (fn)) : "%esp"); \
|
||||||
} while (0)
|
} 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
|
#define STACK_GROWTH_DOWN
|
||||||
|
|
||||||
#include_next <sysdep.h>
|
#include_next <sysdep.h>
|
||||||
|
Loading…
Reference in New Issue
Block a user