diff options
author | Roland McGrath <roland@gnu.org> | 1995-05-31 13:23:14 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 1995-05-31 13:23:14 +0000 |
commit | a1a9d215963c548aef245cacd8efa944de69503b (patch) | |
tree | ff96263310f3c2e3c1f90d4ec8b332b7af028d84 /sysdeps | |
parent | 4174072112e4e2b43cc65a5093a433b4270aed49 (diff) | |
download | glibc-a1a9d215963c548aef245cacd8efa944de69503b.zip glibc-a1a9d215963c548aef245cacd8efa944de69503b.tar.gz glibc-a1a9d215963c548aef245cacd8efa944de69503b.tar.bz2 |
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.
Diffstat (limited to 'sysdeps')
-rw-r--r-- | sysdeps/i386/dl-machine.h | 43 | ||||
-rw-r--r-- | sysdeps/i386/dl-runtime.c | 15 | ||||
-rw-r--r-- | sysdeps/mach/hurd/dl-sysdep.c | 15 | ||||
-rw-r--r-- | sysdeps/mach/hurd/i386/init-first.c | 71 |
4 files changed, 111 insertions, 33 deletions
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h index 1797ae5..f387a88 100644 --- a/sysdeps/i386/dl-machine.h +++ b/sysdeps/i386/dl-machine.h @@ -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\ "); diff --git a/sysdeps/i386/dl-runtime.c b/sysdeps/i386/dl-runtime.c index 1bc5697..8e218e2 100644 --- a/sysdeps/i386/dl-runtime.c +++ b/sysdeps/i386/dl-runtime.c @@ -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; diff --git a/sysdeps/mach/hurd/dl-sysdep.c b/sysdeps/mach/hurd/dl-sysdep.c index 1dca319..d484521 100644 --- a/sysdeps/mach/hurd/dl-sysdep.c +++ b/sysdeps/mach/hurd/dl-sysdep.c @@ -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. */ diff --git a/sysdeps/mach/hurd/i386/init-first.c b/sysdeps/mach/hurd/i386/init-first.c index d747e75..74b15c8 100644 --- a/sysdeps/mach/hurd/i386/init-first.c +++ b/sysdeps/mach/hurd/i386/init-first.c @@ -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. */ |