mirror of
https://sourceware.org/git/glibc.git
synced 2024-12-22 02:40:08 +00:00
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:
parent
4174072112
commit
a1a9d21596
@ -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)
|
||||
|
||||
* sysdeps/generic/memchr.c: Cast RHS to const unsigned char *
|
||||
|
@ -43,8 +43,14 @@ _dl_catch_error (const char **errstring,
|
||||
|
||||
signalled_errstring = signalled_objname = NULL;
|
||||
errcode = setjmp (catch_env);
|
||||
(*operate) ();
|
||||
if (errcode == 0)
|
||||
{
|
||||
(*operate) ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We get here only if we longjmp'd out of OPERATE. */
|
||||
*errstring = signalled_errstring;
|
||||
*objname = signalled_objname;
|
||||
return *errstring ? errcode : 0;
|
||||
return errcode == -1 ? 0 : errcode;
|
||||
}
|
||||
|
@ -26,5 +26,5 @@ _dl_fini (void)
|
||||
|
||||
for (l = _dl_loaded; l; l = l->l_next)
|
||||
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)) ();
|
||||
}
|
||||
|
@ -46,15 +46,17 @@ _dl_init_next (void)
|
||||
{
|
||||
/* Find each dependency in order, and see if it
|
||||
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;
|
||||
for (d = l->l_ld; d->d_tag != DT_NULL; ++d)
|
||||
if (d->d_tag == DT_NEEDED)
|
||||
{
|
||||
struct link_map *needed = _dl_map_object
|
||||
(l, (const char *) (l->l_addr + d->d_un.d_ptr), NULL);
|
||||
struct link_map *needed
|
||||
= _dl_map_object (l, strtab + d->d_un.d_val, NULL);
|
||||
Elf32_Addr init;
|
||||
--needed->l_opencount;
|
||||
init = next_init (l); /* Recurse on this dependency. */
|
||||
init = next_init (needed); /* Recurse on this dependency. */
|
||||
if (init != 0)
|
||||
return init;
|
||||
}
|
||||
@ -74,7 +76,7 @@ _dl_init_next (void)
|
||||
}
|
||||
|
||||
/* Look for the first initializer not yet called. */
|
||||
l = _dl_loaded;
|
||||
l = _dl_loaded->l_next; /* Skip the executable itself. */
|
||||
do
|
||||
{
|
||||
init = next_init (l);
|
||||
|
@ -158,11 +158,12 @@ _dl_map_object (struct link_map *loader, const char *name,
|
||||
|
||||
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 = -1;
|
||||
if (loader && loader->l_info[DT_RPATH])
|
||||
trypath ((const char *) (loader->l_addr +
|
||||
loader->l_info[DT_RPATH]->d_un.d_ptr));
|
||||
@ -317,14 +318,14 @@ _dl_map_object (struct link_map *loader, const char *name,
|
||||
if (ph->p_memsz > ph->p_filesz)
|
||||
{
|
||||
/* Extra zero pages should appear at the end of this segment,
|
||||
after the data mapped from the file. Adjust MAPEND to map
|
||||
only the data from the file. We will later allocate zero
|
||||
pages following the data mapping. */
|
||||
caddr_t zero = mapat - mapstart + ph->p_filesz;
|
||||
caddr_t zeroend = mapat - mapstart + ph->p_memsz;
|
||||
caddr_t zeropage
|
||||
= (caddr_t) ((Elf32_Addr) (zero + pagesize - 1)
|
||||
& ~(pagesize - 1));
|
||||
after the data mapped from the file. */
|
||||
caddr_t zero, zeroend, zeropage;
|
||||
|
||||
mapat += ph->p_vaddr - mapstart;
|
||||
zero = mapat + ph->p_filesz;
|
||||
zeroend = mapat + ph->p_memsz;
|
||||
zeropage = (caddr_t) ((Elf32_Addr) (zero + pagesize - 1)
|
||||
& ~(pagesize - 1));
|
||||
|
||||
if (zeroend < zeropage)
|
||||
/* All the extra data is in the last page of the segment.
|
||||
@ -342,7 +343,7 @@ _dl_map_object (struct link_map *loader, const char *name,
|
||||
prot|PROT_WRITE) < 0)
|
||||
lose (errno, "cannot change memory protections");
|
||||
}
|
||||
memset (zero, 0, zeroend - zero);
|
||||
memset (zero, 0, zeropage - zero);
|
||||
if ((prot & PROT_WRITE) == 0)
|
||||
mprotect ((caddr_t) ((Elf32_Addr) zero
|
||||
& ~(pagesize - 1)),
|
||||
|
@ -20,6 +20,7 @@ Cambridge, MA 02139, USA. */
|
||||
#include <stddef.h>
|
||||
#include <libelf.h>
|
||||
#include <link.h>
|
||||
#include <assert.h>
|
||||
|
||||
/* Search loaded objects' symbol tables for a definition of
|
||||
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;
|
||||
}
|
||||
|
||||
if (sym == *ref)
|
||||
if (sym->st_shndx == SHN_UNDEF)
|
||||
/* 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;
|
||||
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. */
|
||||
continue;
|
||||
|
||||
@ -106,8 +107,8 @@ _dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref,
|
||||
const char msg[] = "undefined symbol: ";
|
||||
char buf[sizeof msg + strlen (undef_name)];
|
||||
memcpy (buf, msg, sizeof msg - 1);
|
||||
memcpy (&buf[sizeof msg - 1], undef_name, sizeof buf - sizeof msg);
|
||||
_dl_signal_error (0, reference_name, msg);
|
||||
memcpy (&buf[sizeof msg - 1], undef_name, sizeof buf - sizeof msg + 1);
|
||||
_dl_signal_error (0, reference_name, buf);
|
||||
}
|
||||
|
||||
*ref = weak_value.s;
|
||||
|
@ -83,7 +83,7 @@ _dl_relocate_object (struct link_map *l, int lazy)
|
||||
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
|
||||
jump to _dl_runtime_resolve, which will relocate them. */
|
||||
elf_machine_runtime_setup (l);
|
||||
|
53
elf/do-rel.h
53
elf/do-rel.h
@ -30,37 +30,46 @@ Cambridge, MA 02139, USA. */
|
||||
/* Perform the relocations in MAP on the running program image as specified
|
||||
by RELTAG, SZTAG. *RESOLVE is called to resolve symbol values; it
|
||||
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
|
||||
elf_dynamic_do_rel (struct link_map *map,
|
||||
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 *) 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_Sym *) (map->l_addr + map->l_info[DT_SYMTAB]->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];
|
||||
|
||||
for (; r < end; ++r)
|
||||
{
|
||||
const Elf32_Sym *definer = &symtab[ELF32_R_SYM (r->r_info)];
|
||||
Elf32_Addr loadbase;
|
||||
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)
|
||||
{
|
||||
const Elf32_Sym *definer = &symtab[ELF32_R_SYM (r->r_info)];
|
||||
Elf32_Addr loadbase;
|
||||
|
||||
if (ELF32_R_SYM (r->r_info) == STN_UNDEF)
|
||||
loadbase = 0; /* This value will not be consulted. */
|
||||
else
|
||||
{
|
||||
if (resolve)
|
||||
loadbase = (*resolve) (&definer);
|
||||
else
|
||||
{
|
||||
assert (definer->st_shndx != SHN_UNDEF);
|
||||
loadbase = map->l_addr;
|
||||
}
|
||||
}
|
||||
elf_machine_rel (map, r, loadbase, definer);
|
||||
}
|
||||
if (ELF32_R_SYM (r->r_info) == STN_UNDEF)
|
||||
loadbase = 0; /* This value will not be consulted. */
|
||||
else
|
||||
{
|
||||
if (resolve)
|
||||
loadbase = (*resolve) (&definer);
|
||||
else
|
||||
{
|
||||
assert (definer->st_shndx != SHN_UNDEF);
|
||||
loadbase = map->l_addr;
|
||||
}
|
||||
}
|
||||
elf_machine_rel (map, r, loadbase, definer);
|
||||
}
|
||||
}
|
||||
|
||||
#undef elf_dynamic_do_rel
|
||||
|
@ -56,9 +56,9 @@ elf_get_dynamic_info (Elf32_Dyn *dyn, Elf32_Dyn *info[DT_NUM])
|
||||
#include "do-rel.h"
|
||||
#define ELF_DYNAMIC_DO_REL(map, lazy, resolve) \
|
||||
if ((map)->l_info[DT_REL]) \
|
||||
elf_dynamic_do_rel ((map), DT_REL, DT_RELSZ, (resolve)); \
|
||||
if (!(lazy) && (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_REL, DT_RELSZ, (resolve), 0); \
|
||||
if ((map)->l_info[DT_PLTREL]->d_un.d_val == DT_REL) \
|
||||
elf_dynamic_do_rel ((map), DT_JMPREL, DT_PLTRELSZ, (resolve), (lazy));
|
||||
#else
|
||||
#define ELF_DYNAMIC_DO_RELA(map, lazy, resolve) /* Nothing to do. */
|
||||
#endif
|
||||
@ -68,9 +68,9 @@ elf_get_dynamic_info (Elf32_Dyn *dyn, Elf32_Dyn *info[DT_NUM])
|
||||
#include "do-rel.h"
|
||||
#define ELF_DYNAMIC_DO_RELA(map, lazy, resolve) \
|
||||
if ((map)->l_info[DT_RELA]) \
|
||||
elf_dynamic_do_rela ((map), DT_RELA, DT_RELASZ, (resolve)); \
|
||||
if (!(lazy) && (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_RELA, DT_RELASZ, (resolve), 0); \
|
||||
if ((map)->l_info[DT_PLTREL]->d_un.d_val == DT_RELA) \
|
||||
elf_dynamic_do_rela ((map), DT_JMPREL, DT_PLTRELSZ, (resolve), (lazy));
|
||||
#else
|
||||
#define ELF_DYNAMIC_DO_RELA(map, lazy, resolve) /* Nothing to do. */
|
||||
#endif
|
||||
|
@ -93,6 +93,8 @@ _dl_start (void *arg)
|
||||
|
||||
void _start (void);
|
||||
|
||||
static int rtld_command; /* Nonzero if we were run directly. */
|
||||
|
||||
static void
|
||||
dl_main (const Elf32_Phdr *phdr,
|
||||
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"
|
||||
);
|
||||
|
||||
rtld_command = 1;
|
||||
interpreter_name = _dl_argv[0];
|
||||
--_dl_argc;
|
||||
++_dl_argv;
|
||||
@ -164,7 +167,7 @@ of this helper program; chances are you did not intend to run this program.\n"
|
||||
case PT_DYNAMIC:
|
||||
/* This tells us where to find the dynamic section,
|
||||
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;
|
||||
case PT_INTERP:
|
||||
/* 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
|
||||
against the dynamic linker as a shared library, will know that
|
||||
the shared object is already loaded. */
|
||||
interpreter_name = (void *) ph->p_vaddr;
|
||||
interpreter_name = (void *) l->l_addr + ph->p_vaddr;
|
||||
break;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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.
|
||||
We do this in reverse order so that copy relocs of earlier
|
||||
|
@ -75,7 +75,7 @@ elf_machine_rel (struct link_map *map,
|
||||
const Elf32_Rel *reloc,
|
||||
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;
|
||||
|
||||
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. */
|
||||
#define ELF_MACHINE_NO_RELA 1
|
||||
@ -113,12 +127,14 @@ elf_machine_rel (struct link_map *map,
|
||||
static inline void
|
||||
elf_machine_runtime_setup (struct link_map *l)
|
||||
{
|
||||
Elf32_Addr *got;
|
||||
extern void _dl_runtime_resolve (Elf32_Word);
|
||||
|
||||
/* The GOT entries for functions in the PLT have not yet been filled
|
||||
in. Their initial contents will arrange when called to push an
|
||||
offset into the .rel.plt section, push _GLOBAL_OFFSET_TABLE_[1],
|
||||
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. */
|
||||
/* 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. */
|
||||
@ -140,9 +156,20 @@ _dl_start_user:\n\
|
||||
# Save the user entry point address in %edi.\n\
|
||||
movl %eax, %edi\n\
|
||||
# Point %ebx at the GOT.
|
||||
1: call 2f\n\
|
||||
2: popl %ebx\n\
|
||||
addl $_GLOBAL_OFFSET_TABLE_+[.-2b], %ebx\n\
|
||||
call 0f\n\
|
||||
0: popl %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\
|
||||
# function to run.\n\
|
||||
0: call _dl_init_next@PLT\n\
|
||||
@ -150,7 +177,7 @@ _dl_start_user:\n\
|
||||
testl %eax,%eax\n\
|
||||
jz 1f\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\
|
||||
# the initializer is called with the stack just\n\
|
||||
# as it appears on entry, and it is free to move\n\
|
||||
@ -159,8 +186,8 @@ _dl_start_user:\n\
|
||||
call *%eax\n\
|
||||
# Loop to call _dl_init_next for the next initializer.\n\
|
||||
jmp 0b\n\
|
||||
# Pass our finalizer function to the user in %edx, as per ELF ABI.\n\
|
||||
leal _dl_fini@GOT(%ebx), %edx\n\
|
||||
1: # Pass our finalizer function to the user in %edx, as per ELF ABI.\n\
|
||||
movl _dl_fini@GOT(%ebx), %edx\n\
|
||||
# Jump to the user's entry point.\n\
|
||||
jmp *%edi\n\
|
||||
");
|
||||
|
@ -34,15 +34,16 @@ void
|
||||
_dl_runtime_resolve (Elf32_Word reloc_offset)
|
||||
{
|
||||
__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 *) l->l_info[DT_SYMTAB]->d_un.d_ptr;
|
||||
const char *strtab
|
||||
= ((void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
|
||||
= (const Elf32_Sym *) (l->l_addr + l->l_info[DT_SYMTAB]->d_un.d_ptr);
|
||||
const char *strtab =
|
||||
(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
|
||||
+ reloc_offset);
|
||||
const Elf32_Rel *const reloc
|
||||
= (const void *) (l->l_addr + l->l_info[DT_JMPREL]->d_un.d_ptr +
|
||||
reloc_offset);
|
||||
|
||||
const Elf32_Sym *definer;
|
||||
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
|
||||
function in the shared object will run with the stack arranged just as
|
||||
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;
|
||||
|
||||
|
@ -36,6 +36,8 @@ Cambridge, MA 02139, USA. */
|
||||
|
||||
#include "dl-machine.h"
|
||||
|
||||
extern void __mach_init (void);
|
||||
|
||||
extern int _dl_argc;
|
||||
extern char **_dl_argv;
|
||||
extern char **_environ;
|
||||
@ -52,8 +54,8 @@ _dl_sysdep_start (void **start_argptr,
|
||||
char **p;
|
||||
|
||||
/* Cache the information in various global variables. */
|
||||
_dl_argc = *argdata++;
|
||||
_dl_argv = (void *) argdata;
|
||||
_dl_argc = *argdata;
|
||||
_dl_argv = (void *) &argdata[1];
|
||||
_environ = &_dl_argv[_dl_argc + 1];
|
||||
for (p = _environ; *p; ++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->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);
|
||||
/* 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
|
||||
from the exec server and slicing up the arguments.
|
||||
Then it will call `go', above. */
|
||||
|
@ -95,8 +95,8 @@ init1 (int argc, char *arg0, ...)
|
||||
__libc_init (argc, argv, __environ);
|
||||
}
|
||||
|
||||
static void
|
||||
init (int *data, int retaddr)
|
||||
static void
|
||||
init (int *data, void *usercode, void **retaddrloc)
|
||||
{
|
||||
int argc = *data;
|
||||
char **argv = (void *) (data + 1);
|
||||
@ -115,6 +115,11 @@ init (int *data, int retaddr)
|
||||
if (__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)
|
||||
{
|
||||
/* 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. */
|
||||
*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,
|
||||
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
|
||||
soinit (int argc, ...)
|
||||
void
|
||||
_init (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. */
|
||||
init (&argc, ((void **) &argc)[-1], &((void **) &argc)[-1]);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void
|
||||
__libc_init_first (int argc, ...)
|
||||
__libc_init_first (int argc __attribute__ ((unused)), ...)
|
||||
{
|
||||
#ifndef PIC
|
||||
void doinit (int *data)
|
||||
{
|
||||
init (data, (&argc)[-1]);
|
||||
init (data, ((void **) &argc)[-1], &((void **) &data)[-1]);
|
||||
}
|
||||
|
||||
/* Initialize data structures so we can do RPCs. */
|
||||
|
Loading…
Reference in New Issue
Block a user