Tue May 30 15:52:32 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>

* mach/Makefile (server-interfaces): Removed notify and
 	device_reply.  For shlibs with eager binding, libmachuser.so must
 	not refer to any functions not defined in libc.
This commit is contained in:
Roland McGrath 1995-05-31 13:23:14 +00:00
parent 4174072112
commit a1a9d21596
14 changed files with 193 additions and 87 deletions

View File

@ -1,3 +1,9 @@
Tue May 30 15:52:32 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
* mach/Makefile (server-interfaces): Removed notify and
device_reply. For shlibs with eager binding, libmachuser.so must
not refer to any functions not defined in libc.
Sat May 27 16:23:22 1995 Jim Meyering (meyering@comco.com) Sat May 27 16:23:22 1995 Jim Meyering (meyering@comco.com)
* sysdeps/generic/memchr.c: Cast RHS to const unsigned char * * sysdeps/generic/memchr.c: Cast RHS to const unsigned char *

View File

@ -43,8 +43,14 @@ _dl_catch_error (const char **errstring,
signalled_errstring = signalled_objname = NULL; signalled_errstring = signalled_objname = NULL;
errcode = setjmp (catch_env); errcode = setjmp (catch_env);
if (errcode == 0)
{
(*operate) (); (*operate) ();
return 0;
}
/* We get here only if we longjmp'd out of OPERATE. */
*errstring = signalled_errstring; *errstring = signalled_errstring;
*objname = signalled_objname; *objname = signalled_objname;
return *errstring ? errcode : 0; return errcode == -1 ? 0 : errcode;
} }

View File

@ -26,5 +26,5 @@ _dl_fini (void)
for (l = _dl_loaded; l; l = l->l_next) for (l = _dl_loaded; l; l = l->l_next)
if (l->l_init_called && l->l_info[DT_FINI]) if (l->l_init_called && l->l_info[DT_FINI])
(*(void (*) (void)) l->l_info[DT_FINI]->d_un.d_ptr) (); (*(void (*) (void)) (l->l_addr + l->l_info[DT_FINI]->d_un.d_ptr)) ();
} }

View File

@ -46,15 +46,17 @@ _dl_init_next (void)
{ {
/* Find each dependency in order, and see if it /* Find each dependency in order, and see if it
needs to run an initializer. */ needs to run an initializer. */
const char *strtab
= ((void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
const Elf32_Dyn *d; const Elf32_Dyn *d;
for (d = l->l_ld; d->d_tag != DT_NULL; ++d) for (d = l->l_ld; d->d_tag != DT_NULL; ++d)
if (d->d_tag == DT_NEEDED) if (d->d_tag == DT_NEEDED)
{ {
struct link_map *needed = _dl_map_object struct link_map *needed
(l, (const char *) (l->l_addr + d->d_un.d_ptr), NULL); = _dl_map_object (l, strtab + d->d_un.d_val, NULL);
Elf32_Addr init; Elf32_Addr init;
--needed->l_opencount; --needed->l_opencount;
init = next_init (l); /* Recurse on this dependency. */ init = next_init (needed); /* Recurse on this dependency. */
if (init != 0) if (init != 0)
return init; return init;
} }
@ -74,7 +76,7 @@ _dl_init_next (void)
} }
/* Look for the first initializer not yet called. */ /* Look for the first initializer not yet called. */
l = _dl_loaded; l = _dl_loaded->l_next; /* Skip the executable itself. */
do do
{ {
init = next_init (l); init = next_init (l);

View File

@ -158,11 +158,12 @@ _dl_map_object (struct link_map *loader, const char *name,
size_t namelen = strlen (name) + 1; size_t namelen = strlen (name) + 1;
void trypath (const char *dirpath) inline void trypath (const char *dirpath)
{ {
fd = open_path (name, namelen, dirpath, &realname); fd = open_path (name, namelen, dirpath, &realname);
} }
fd = -1;
if (loader && loader->l_info[DT_RPATH]) if (loader && loader->l_info[DT_RPATH])
trypath ((const char *) (loader->l_addr + trypath ((const char *) (loader->l_addr +
loader->l_info[DT_RPATH]->d_un.d_ptr)); loader->l_info[DT_RPATH]->d_un.d_ptr));
@ -317,13 +318,13 @@ _dl_map_object (struct link_map *loader, const char *name,
if (ph->p_memsz > ph->p_filesz) if (ph->p_memsz > ph->p_filesz)
{ {
/* Extra zero pages should appear at the end of this segment, /* Extra zero pages should appear at the end of this segment,
after the data mapped from the file. Adjust MAPEND to map after the data mapped from the file. */
only the data from the file. We will later allocate zero caddr_t zero, zeroend, zeropage;
pages following the data mapping. */
caddr_t zero = mapat - mapstart + ph->p_filesz; mapat += ph->p_vaddr - mapstart;
caddr_t zeroend = mapat - mapstart + ph->p_memsz; zero = mapat + ph->p_filesz;
caddr_t zeropage zeroend = mapat + ph->p_memsz;
= (caddr_t) ((Elf32_Addr) (zero + pagesize - 1) zeropage = (caddr_t) ((Elf32_Addr) (zero + pagesize - 1)
& ~(pagesize - 1)); & ~(pagesize - 1));
if (zeroend < zeropage) if (zeroend < zeropage)
@ -342,7 +343,7 @@ _dl_map_object (struct link_map *loader, const char *name,
prot|PROT_WRITE) < 0) prot|PROT_WRITE) < 0)
lose (errno, "cannot change memory protections"); lose (errno, "cannot change memory protections");
} }
memset (zero, 0, zeroend - zero); memset (zero, 0, zeropage - zero);
if ((prot & PROT_WRITE) == 0) if ((prot & PROT_WRITE) == 0)
mprotect ((caddr_t) ((Elf32_Addr) zero mprotect ((caddr_t) ((Elf32_Addr) zero
& ~(pagesize - 1)), & ~(pagesize - 1)),

View File

@ -20,6 +20,7 @@ Cambridge, MA 02139, USA. */
#include <stddef.h> #include <stddef.h>
#include <libelf.h> #include <libelf.h>
#include <link.h> #include <link.h>
#include <assert.h>
/* Search loaded objects' symbol tables for a definition of /* Search loaded objects' symbol tables for a definition of
the symbol UNDEF_NAME. Don't use a PLT defn in UNDEF_MAP, since the symbol UNDEF_NAME. Don't use a PLT defn in UNDEF_MAP, since
@ -70,13 +71,13 @@ _dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref,
continue; continue;
} }
if (sym == *ref) if (sym->st_shndx == SHN_UNDEF)
/* This is the same symbol we are looking for the value for. /* This is the same symbol we are looking for the value for.
If it is a PLT entry, it will have a value of its own; If it is a PLT entry, it will have a value of its own;
but that is not what we are looking for. */ but that is not what we are looking for. */
continue; continue;
if (strcmp (strtab + sym->st_name, undef_name)) if (sym != *ref && strcmp (strtab + sym->st_name, undef_name))
/* Not the symbol we are looking for. */ /* Not the symbol we are looking for. */
continue; continue;
@ -106,8 +107,8 @@ _dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref,
const char msg[] = "undefined symbol: "; const char msg[] = "undefined symbol: ";
char buf[sizeof msg + strlen (undef_name)]; char buf[sizeof msg + strlen (undef_name)];
memcpy (buf, msg, sizeof msg - 1); memcpy (buf, msg, sizeof msg - 1);
memcpy (&buf[sizeof msg - 1], undef_name, sizeof buf - sizeof msg); memcpy (&buf[sizeof msg - 1], undef_name, sizeof buf - sizeof msg + 1);
_dl_signal_error (0, reference_name, msg); _dl_signal_error (0, reference_name, buf);
} }
*ref = weak_value.s; *ref = weak_value.s;

View File

@ -83,7 +83,7 @@ _dl_relocate_object (struct link_map *l, int lazy)
l->l_prev->l_next = l; l->l_prev->l_next = l;
} }
if (l->l_info[DT_JMPREL] && ! lazy) if (l->l_info[DT_JMPREL] && lazy)
/* Set up the PLT so its unrelocated entries will /* Set up the PLT so its unrelocated entries will
jump to _dl_runtime_resolve, which will relocate them. */ jump to _dl_runtime_resolve, which will relocate them. */
elf_machine_runtime_setup (l); elf_machine_runtime_setup (l);

View File

@ -30,18 +30,27 @@ Cambridge, MA 02139, USA. */
/* Perform the relocations in MAP on the running program image as specified /* Perform the relocations in MAP on the running program image as specified
by RELTAG, SZTAG. *RESOLVE is called to resolve symbol values; it by RELTAG, SZTAG. *RESOLVE is called to resolve symbol values; it
modifies its argument pointer to point to the defining symbol, and modifies its argument pointer to point to the defining symbol, and
returns the base load address of the defining object. */ returns the base load address of the defining object. If LAZY is
nonzero, this is the first pass on PLT relocations; they should be set
up to call _dl_runtime_resolve, rather than fully resolved now. */
static inline void static inline void
elf_dynamic_do_rel (struct link_map *map, elf_dynamic_do_rel (struct link_map *map,
int reltag, int sztag, int reltag, int sztag,
Elf32_Addr (*resolve) (const Elf32_Sym **)) Elf32_Addr (*resolve) (const Elf32_Sym **),
int lazy)
{ {
const Elf32_Sym *const symtab const Elf32_Sym *const symtab
= (const Elf32_Sym *) map->l_info[DT_SYMTAB]->d_un.d_ptr; = (const Elf32_Sym *) (map->l_addr + map->l_info[DT_SYMTAB]->d_un.d_ptr);
const Elf32_Rel *r = (const Elf32_Rel *) map->l_info[reltag]->d_un.d_ptr; const Elf32_Rel *r
= (const Elf32_Rel *) (map->l_addr + map->l_info[reltag]->d_un.d_ptr);
const Elf32_Rel *end = &r[map->l_info[sztag]->d_un.d_val / sizeof *r]; const Elf32_Rel *end = &r[map->l_info[sztag]->d_un.d_val / sizeof *r];
if (lazy)
/* Doing lazy PLT relocations; they need very little info. */
for (; r < end; ++r)
elf_machine_lazy_rel (map, r);
else
for (; r < end; ++r) for (; r < end; ++r)
{ {
const Elf32_Sym *definer = &symtab[ELF32_R_SYM (r->r_info)]; const Elf32_Sym *definer = &symtab[ELF32_R_SYM (r->r_info)];

View File

@ -56,9 +56,9 @@ elf_get_dynamic_info (Elf32_Dyn *dyn, Elf32_Dyn *info[DT_NUM])
#include "do-rel.h" #include "do-rel.h"
#define ELF_DYNAMIC_DO_REL(map, lazy, resolve) \ #define ELF_DYNAMIC_DO_REL(map, lazy, resolve) \
if ((map)->l_info[DT_REL]) \ if ((map)->l_info[DT_REL]) \
elf_dynamic_do_rel ((map), DT_REL, DT_RELSZ, (resolve)); \ elf_dynamic_do_rel ((map), DT_REL, DT_RELSZ, (resolve), 0); \
if (!(lazy) && (map)->l_info[DT_PLTREL]->d_un.d_val == DT_REL) \ if ((map)->l_info[DT_PLTREL]->d_un.d_val == DT_REL) \
elf_dynamic_do_rel ((map), DT_JMPREL, DT_PLTRELSZ, (resolve)); elf_dynamic_do_rel ((map), DT_JMPREL, DT_PLTRELSZ, (resolve), (lazy));
#else #else
#define ELF_DYNAMIC_DO_RELA(map, lazy, resolve) /* Nothing to do. */ #define ELF_DYNAMIC_DO_RELA(map, lazy, resolve) /* Nothing to do. */
#endif #endif
@ -68,9 +68,9 @@ elf_get_dynamic_info (Elf32_Dyn *dyn, Elf32_Dyn *info[DT_NUM])
#include "do-rel.h" #include "do-rel.h"
#define ELF_DYNAMIC_DO_RELA(map, lazy, resolve) \ #define ELF_DYNAMIC_DO_RELA(map, lazy, resolve) \
if ((map)->l_info[DT_RELA]) \ if ((map)->l_info[DT_RELA]) \
elf_dynamic_do_rela ((map), DT_RELA, DT_RELASZ, (resolve)); \ elf_dynamic_do_rela ((map), DT_RELA, DT_RELASZ, (resolve), 0); \
if (!(lazy) && (map)->l_info[DT_PLTREL]->d_un.d_val == DT_RELA) \ if ((map)->l_info[DT_PLTREL]->d_un.d_val == DT_RELA) \
elf_dynamic_do_rela ((map), DT_JMPREL, DT_PLTRELSZ, (resolve); elf_dynamic_do_rela ((map), DT_JMPREL, DT_PLTRELSZ, (resolve), (lazy));
#else #else
#define ELF_DYNAMIC_DO_RELA(map, lazy, resolve) /* Nothing to do. */ #define ELF_DYNAMIC_DO_RELA(map, lazy, resolve) /* Nothing to do. */
#endif #endif

View File

@ -93,6 +93,8 @@ _dl_start (void *arg)
void _start (void); void _start (void);
static int rtld_command; /* Nonzero if we were run directly. */
static void static void
dl_main (const Elf32_Phdr *phdr, dl_main (const Elf32_Phdr *phdr,
Elf32_Word phent, Elf32_Word phent,
@ -138,6 +140,7 @@ file you run. This is mostly of use for maintainers to test new versions\n\
of this helper program; chances are you did not intend to run this program.\n" of this helper program; chances are you did not intend to run this program.\n"
); );
rtld_command = 1;
interpreter_name = _dl_argv[0]; interpreter_name = _dl_argv[0];
--_dl_argc; --_dl_argc;
++_dl_argv; ++_dl_argv;
@ -164,7 +167,7 @@ of this helper program; chances are you did not intend to run this program.\n"
case PT_DYNAMIC: case PT_DYNAMIC:
/* This tells us where to find the dynamic section, /* This tells us where to find the dynamic section,
which tells us everything we need to do. */ which tells us everything we need to do. */
l->l_ld = (void *) ph->p_vaddr; l->l_ld = (void *) l->l_addr + ph->p_vaddr;
break; break;
case PT_INTERP: case PT_INTERP:
/* This "interpreter segment" was used by the program loader to /* This "interpreter segment" was used by the program loader to
@ -173,7 +176,7 @@ of this helper program; chances are you did not intend to run this program.\n"
dlopen call or DT_NEEDED entry, for something that wants to link dlopen call or DT_NEEDED entry, for something that wants to link
against the dynamic linker as a shared library, will know that against the dynamic linker as a shared library, will know that
the shared object is already loaded. */ the shared object is already loaded. */
interpreter_name = (void *) ph->p_vaddr; interpreter_name = (void *) l->l_addr + ph->p_vaddr;
break; break;
} }
assert (interpreter_name); /* How else did we get here? */ assert (interpreter_name); /* How else did we get here? */
@ -220,7 +223,7 @@ of this helper program; chances are you did not intend to run this program.\n"
l->l_next->l_prev = l->l_prev; l->l_next->l_prev = l->l_prev;
} }
lazy = _dl_secure || *(getenv ("LD_BIND_NOW") ?: ""); lazy = !_dl_secure && *(getenv ("LD_BIND_NOW") ?: "") == '\0';
/* Now we have all the objects loaded. Relocate them all. /* Now we have all the objects loaded. Relocate them all.
We do this in reverse order so that copy relocs of earlier We do this in reverse order so that copy relocs of earlier

View File

@ -75,7 +75,7 @@ elf_machine_rel (struct link_map *map,
const Elf32_Rel *reloc, const Elf32_Rel *reloc,
Elf32_Addr sym_loadaddr, const Elf32_Sym *sym) Elf32_Addr sym_loadaddr, const Elf32_Sym *sym)
{ {
Elf32_Addr *const reloc_addr = (Elf32_Addr *) reloc->r_offset; Elf32_Addr *const reloc_addr = (void *) (map->l_addr + reloc->r_offset);
const Elf32_Addr sym_value = sym_loadaddr + sym->st_value; const Elf32_Addr sym_value = sym_loadaddr + sym->st_value;
switch (ELF32_R_TYPE (reloc->r_info)) switch (ELF32_R_TYPE (reloc->r_info))
@ -102,6 +102,20 @@ elf_machine_rel (struct link_map *map,
} }
} }
static inline void
elf_machine_lazy_rel (struct link_map *map, const Elf32_Rel *reloc)
{
Elf32_Addr *const reloc_addr = (void *) (map->l_addr + reloc->r_offset);
switch (ELF32_R_TYPE (reloc->r_info))
{
case R_386_JMP_SLOT:
*reloc_addr += map->l_addr;
break;
default:
assert (! "unexpected PLT reloc type");
break;
}
}
/* The i386 never uses Elf32_Rela relocations. */ /* The i386 never uses Elf32_Rela relocations. */
#define ELF_MACHINE_NO_RELA 1 #define ELF_MACHINE_NO_RELA 1
@ -113,12 +127,14 @@ elf_machine_rel (struct link_map *map,
static inline void static inline void
elf_machine_runtime_setup (struct link_map *l) elf_machine_runtime_setup (struct link_map *l)
{ {
Elf32_Addr *got;
extern void _dl_runtime_resolve (Elf32_Word); extern void _dl_runtime_resolve (Elf32_Word);
/* The GOT entries for functions in the PLT have not yet been filled /* The GOT entries for functions in the PLT have not yet been filled
in. Their initial contents will arrange when called to push an in. Their initial contents will arrange when called to push an
offset into the .rel.plt section, push _GLOBAL_OFFSET_TABLE_[1], offset into the .rel.plt section, push _GLOBAL_OFFSET_TABLE_[1],
and then jump to _GLOBAL_OFFSET_TABLE[2]. */ and then jump to _GLOBAL_OFFSET_TABLE[2]. */
Elf32_Addr *got = (Elf32_Addr *) l->l_info[DT_PLTGOT]->d_un.d_ptr; got = (Elf32_Addr *) (l->l_addr + l->l_info[DT_PLTGOT]->d_un.d_ptr);
got[1] = (Elf32_Addr) l; /* Identify this shared object. */ got[1] = (Elf32_Addr) l; /* Identify this shared object. */
/* This function will get called to fix up the GOT entry indicated by /* This function will get called to fix up the GOT entry indicated by
the offset on the stack, and then jump to the resolved address. */ the offset on the stack, and then jump to the resolved address. */
@ -140,9 +156,20 @@ _dl_start_user:\n\
# Save the user entry point address in %edi.\n\ # Save the user entry point address in %edi.\n\
movl %eax, %edi\n\ movl %eax, %edi\n\
# Point %ebx at the GOT. # Point %ebx at the GOT.
1: call 2f\n\ call 0f\n\
2: popl %ebx\n\ 0: popl %ebx\n\
addl $_GLOBAL_OFFSET_TABLE_+[.-2b], %ebx\n\ addl $_GLOBAL_OFFSET_TABLE_+[.-0b], %ebx\n\
# See if we were run as a command with the executable file\n\
# name as an extra leading argument.\n\
movl rtld_command@GOT(%ebx), %eax\n\
movl (%eax),%eax\n\
testl %eax,%eax\n\
jz 0f\n\
# Pop the original argument count, decrement it, and replace\n\
# the original first argument pointer with the new count.\n\
popl %eax\n\
decl %eax\n\
movl %eax,(%esp)\n\
# Call _dl_init_next to return the address of an initializer\n\ # Call _dl_init_next to return the address of an initializer\n\
# function to run.\n\ # function to run.\n\
0: call _dl_init_next@PLT\n\ 0: call _dl_init_next@PLT\n\
@ -150,7 +177,7 @@ _dl_start_user:\n\
testl %eax,%eax\n\ testl %eax,%eax\n\
jz 1f\n\ jz 1f\n\
# Call the shared object initializer function.\n\ # Call the shared object initializer function.\n\
# NOTE: We depend only on the registers (%ebx)\n\ # NOTE: We depend only on the registers (%ebx and %edi)\n\
# and the return address pushed by this call;\n\ # and the return address pushed by this call;\n\
# the initializer is called with the stack just\n\ # the initializer is called with the stack just\n\
# as it appears on entry, and it is free to move\n\ # as it appears on entry, and it is free to move\n\
@ -159,8 +186,8 @@ _dl_start_user:\n\
call *%eax\n\ call *%eax\n\
# Loop to call _dl_init_next for the next initializer.\n\ # Loop to call _dl_init_next for the next initializer.\n\
jmp 0b\n\ jmp 0b\n\
# Pass our finalizer function to the user in %edx, as per ELF ABI.\n\ 1: # Pass our finalizer function to the user in %edx, as per ELF ABI.\n\
leal _dl_fini@GOT(%ebx), %edx\n\ movl _dl_fini@GOT(%ebx), %edx\n\
# Jump to the user's entry point.\n\ # Jump to the user's entry point.\n\
jmp *%edi\n\ jmp *%edi\n\
"); ");

View File

@ -34,15 +34,16 @@ void
_dl_runtime_resolve (Elf32_Word reloc_offset) _dl_runtime_resolve (Elf32_Word reloc_offset)
{ {
__label__ return_insn; __label__ return_insn;
struct link_map *l = (void *) &(&reloc_offset)[-1]; struct link_map *l = (void *) (&reloc_offset)[-1];
const Elf32_Sym *const symtab const Elf32_Sym *const symtab
= (const Elf32_Sym *) l->l_info[DT_SYMTAB]->d_un.d_ptr; = (const Elf32_Sym *) (l->l_addr + l->l_info[DT_SYMTAB]->d_un.d_ptr);
const char *strtab const char *strtab =
= ((void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr); (const char *) (l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
const Elf32_Rel *const reloc = (void *) (l->l_info[DT_JMPREL]->d_un.d_ptr const Elf32_Rel *const reloc
+ reloc_offset); = (const void *) (l->l_addr + l->l_info[DT_JMPREL]->d_un.d_ptr +
reloc_offset);
const Elf32_Sym *definer; const Elf32_Sym *definer;
Elf32_Addr loadbase; Elf32_Addr loadbase;
@ -83,7 +84,7 @@ _dl_runtime_resolve (Elf32_Word reloc_offset)
referred to by this PLT entry; once "ret" pops this address, the referred to by this PLT entry; once "ret" pops this address, the
function in the shared object will run with the stack arranged just as function in the shared object will run with the stack arranged just as
when the user entered the PLT. */ when the user entered the PLT. */
(&reloc_offset)[0] = *(Elf32_Word *) reloc->r_offset; (&reloc_offset)[0] = *(Elf32_Word *) (l->l_addr + reloc->r_offset);
return; return;

View File

@ -36,6 +36,8 @@ Cambridge, MA 02139, USA. */
#include "dl-machine.h" #include "dl-machine.h"
extern void __mach_init (void);
extern int _dl_argc; extern int _dl_argc;
extern char **_dl_argv; extern char **_dl_argv;
extern char **_environ; extern char **_environ;
@ -52,8 +54,8 @@ _dl_sysdep_start (void **start_argptr,
char **p; char **p;
/* Cache the information in various global variables. */ /* Cache the information in various global variables. */
_dl_argc = *argdata++; _dl_argc = *argdata;
_dl_argv = (void *) argdata; _dl_argv = (void *) &argdata[1];
_environ = &_dl_argv[_dl_argc + 1]; _environ = &_dl_argv[_dl_argc + 1];
for (p = _environ; *p; ++p); for (p = _environ; *p; ++p);
_dl_hurd_data = (void *) ++p; _dl_hurd_data = (void *) ++p;
@ -66,6 +68,12 @@ _dl_sysdep_start (void **start_argptr,
_dl_hurd_data->phdrsz / sizeof (Elf32_Phdr), _dl_hurd_data->phdrsz / sizeof (Elf32_Phdr),
&_dl_hurd_data->user_entry); &_dl_hurd_data->user_entry);
/* Deallocate the reply port and task port rights acquired by
__mach_init. We are done with them now, and the user will
reacquire them for himself when he wants them. */
__mig_dealloc_reply_port (MACH_PORT_NULL);
__mach_port_deallocate (__mach_task_self (), __mach_task_self_);
{ {
extern void _dl_start_user (void); extern void _dl_start_user (void);
/* Unwind the stack to ARGDATA and simulate a return from _dl_start /* Unwind the stack to ARGDATA and simulate a return from _dl_start
@ -74,6 +82,9 @@ _dl_sysdep_start (void **start_argptr,
} }
} }
/* Set up so we can do RPCs. */
__mach_init ();
/* See hurd/hurdstartup.c; this deals with getting information /* See hurd/hurdstartup.c; this deals with getting information
from the exec server and slicing up the arguments. from the exec server and slicing up the arguments.
Then it will call `go', above. */ Then it will call `go', above. */

View File

@ -96,7 +96,7 @@ init1 (int argc, char *arg0, ...)
} }
static void static void
init (int *data, int retaddr) init (int *data, void *usercode, void **retaddrloc)
{ {
int argc = *data; int argc = *data;
char **argv = (void *) (data + 1); char **argv = (void *) (data + 1);
@ -115,6 +115,11 @@ init (int *data, int retaddr)
if (__hurd_threadvar_max < _HURD_THREADVAR_MAX) if (__hurd_threadvar_max < _HURD_THREADVAR_MAX)
__hurd_threadvar_max = _HURD_THREADVAR_MAX; __hurd_threadvar_max = _HURD_THREADVAR_MAX;
/* After possibly switching stacks, call `init1' (above) with the user
code as the return address, and the argument data immediately above
that on the stack. */
if (_cthread_init_routine) if (_cthread_init_routine)
{ {
/* Initialize cthreads, which will allocate us a new stack to run on. */ /* Initialize cthreads, which will allocate us a new stack to run on. */
@ -136,13 +141,45 @@ init (int *data, int retaddr)
/* Copy the Hurd startup data block to the new stack. */ /* Copy the Hurd startup data block to the new stack. */
*od = *d; *od = *d;
data = newsp; /* Push the user code address on the top of the new stack. It will
be the return address for `init1'; we will jump there with NEWSP
as the stack pointer. */
*--(void **) newsp = usercode;
/* Mutate our own return address to run the code below. */
*retaddrloc = &&switch_stacks;
/* Force NEWSP into %ecx and &init1 into %eax, which are not restored
by function return. */
asm volatile ("# a %0 c %1" : : "a" (&init1), "c" (newsp));
return;
switch_stacks:
/* Our return address was redirected to here, so at this point our
stack is unwound and callers' registers restored. Only %ecx and
%eax are call-clobbered and thus still have the values we set just
above. Fetch from there the new stack pointer we will run on, and
jmp to the run-time address of `init1'; when it returns, it will
run the user code with the argument data at the top of the stack. */
asm volatile ("movl %ecx, %esp; jmp *%eax");
/* NOTREACHED */
}
else
{
/* We are not switching stacks, but we must play some games with
the one we've got, similar to the stack-switching code above. */
*retaddrloc = &&call_init1;
/* Force the user code address into %ecx and the run-time address of
`init1' into %eax, for use below. */
asm volatile ("# a %0 c %1" : : "a" (&init1), "c" (usercode));
return;
call_init1:
/* As in the stack-switching case, at this point our stack is unwound
and callers' registers restored, and only %ecx and %eax
communicate values from the lines above. In this case we have
stashed in %ecx the user code return address. Push it on the top
of the stack so it acts as init1's return address, and then jump
there. */
asm volatile ("pushl %ecx; jmp *%eax");
/* NOTREACHED */
} }
/* 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));
} }
@ -151,30 +188,32 @@ init (int *data, int retaddr)
It is called just before the user _start code from i386/elf/start.S, It is called just before the user _start code from i386/elf/start.S,
with the stack set up as that code gets it. */ with the stack set up as that code gets it. */
static void soinit (int argc, ...) __attribute__ ((unused, section (".init"))); /* NOTE! The linker notices the magical name `_init' and sets the DT_INIT
pointer in the dynamic section based solely on that. It is convention
for this function to be in the `.init' section, but the symbol name is
the only thing that really matters!! */
/*void _init (int argc, ...) __attribute__ ((unused, section (".init")));*/
static void void
soinit (int argc, ...) _init (int argc, ...)
{ {
/* Initialize data structures so we can do RPCs. */ /* Initialize data structures so we can do RPCs. */
__mach_init (); __mach_init ();
RUN_HOOK (_hurd_preinit_hook, ()); RUN_HOOK (_hurd_preinit_hook, ());
init (&argc, (&argc)[-1]); init (&argc, ((void **) &argc)[-1], &((void **) &argc)[-1]);
(void) &soinit; /* Avoid gcc optimizing this fn out. */
} }
#endif #endif
void void
__libc_init_first (int argc, ...) __libc_init_first (int argc __attribute__ ((unused)), ...)
{ {
#ifndef PIC #ifndef PIC
void doinit (int *data) void doinit (int *data)
{ {
init (data, (&argc)[-1]); init (data, ((void **) &argc)[-1], &((void **) &data)[-1]);
} }
/* Initialize data structures so we can do RPCs. */ /* Initialize data structures so we can do RPCs. */