about summary refs log tree commit diff
path: root/sysdeps
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1995-05-31 13:23:14 +0000
committerRoland McGrath <roland@gnu.org>1995-05-31 13:23:14 +0000
commita1a9d215963c548aef245cacd8efa944de69503b (patch)
treeff96263310f3c2e3c1f90d4ec8b332b7af028d84 /sysdeps
parent4174072112e4e2b43cc65a5093a433b4270aed49 (diff)
downloadglibc-a1a9d215963c548aef245cacd8efa944de69503b.tar.gz
glibc-a1a9d215963c548aef245cacd8efa944de69503b.tar.xz
glibc-a1a9d215963c548aef245cacd8efa944de69503b.zip
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.h43
-rw-r--r--sysdeps/i386/dl-runtime.c15
-rw-r--r--sysdeps/mach/hurd/dl-sysdep.c15
-rw-r--r--sysdeps/mach/hurd/i386/init-first.c71
4 files changed, 111 insertions, 33 deletions
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h
index 1797ae5b87..f387a887c1 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 1bc569760c..8e218e2a62 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 1dca319433..d4845213f4 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 d747e75c7d..74b15c8f2f 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.  */