(_dl_sysdep_start): If started by kernel with args on stack,
authorroland <roland>
Sat, 30 Sep 1995 21:13:08 +0000 (21:13 +0000)
committerroland <roland>
Sat, 30 Sep 1995 21:13:08 +0000 (21:13 +0000)
point _dl_hurd_data and zero data instead of garbage.
When ld.so run as program, grok args -LIB=MEMOBJ and pre-load
shared object files found in memory objects loaded by the boot loader.

sysdeps/mach/hurd/dl-sysdep.c

index e55a615..2daf749 100644 (file)
@@ -80,20 +80,75 @@ _dl_sysdep_start (void **start_argptr,
                  void (*dl_main) (const Elf32_Phdr *phdr, Elf32_Word phent,
                                   Elf32_Addr *user_entry))
 {
+  extern void _start ();
+
   void go (int *argdata)
     {
+      extern unsigned int _dl_skip_args; /* rtld.c */
       char **p;
 
       /* Cache the information in various global variables.  */
       _dl_argc = *argdata;
-      _dl_argv = (void *) &argdata[1];
+      _dl_argv = 1 + (char **) argdata;
       _environ = &_dl_argv[_dl_argc + 1];
-      for (p = _environ; *p; ++p);
-      _dl_hurd_data = (void *) ++p;
+      for (p = _environ; *p++;); /* Skip environ pointers and terminator.  */
+
+      if ((void *) p == _dl_argv[0])
+       {
+         static struct hurd_startup_data nodata;
+         _dl_hurd_data = &nodata;
+         nodata.user_entry = (vm_address_t) &_start;
+       }
+      else
+       _dl_hurd_data = (void *) p;
 
       _dl_secure = _dl_hurd_data->flags & EXEC_SECURE;
 
 unfmh();                       /* XXX */
+
+      if (_dl_hurd_data->user_entry == (vm_address_t) &_start)
+       /* We were invoked as a command, not as the program interpreter.
+          The generic ld.so code supports this: it will parse the args
+          as "ld.so PROGRAM [ARGS...]".  For booting the Hurd, we
+          support an additional special syntax:
+            ld.so [-LIBS...] PROGRAM [ARGS...]
+          Each LIBS word consists of "FILENAME=MEMOBJ";
+          for example "-/lib/libc.so=123" says that the contents of
+          /lib/libc.so are found in a memory object whose port name
+          in our task is 123.  */
+       while (_dl_argc > 2 && _dl_argv[1][0] == '-')
+         {
+           char *lastslash, *memobjname, *p;
+           struct link_map *l;
+           mach_port_t memobj;
+           error_t err;
+
+           ++_dl_skip_args;
+           --_dl_argc;
+           p = _dl_argv++[1] + 1;
+
+           memobjname = strchr (p, '=');
+           if (! memobjname)
+             _dl_sysdep_fatal ("Bogus library spec: ", p, "\n", NULL);
+           *memobjname++ = '\0';
+           memobj = (mach_port_t) atoi (memobjname);
+      
+           /* Add a user reference on the memory object port, so we will
+              still have one after _dl_map_object_from_fd calls our
+              `close'.  */
+           err = __mach_port_mod_refs (__mach_task_self (), memobj,
+                                       MACH_PORT_RIGHT_SEND, +1);
+           assert_perror (err);
+           
+           lastslash = strrchr (p, '/');
+           l = _dl_map_object_from_fd (lastslash ? lastslash + 1 : p,
+                                       memobj, strdup (p));
+
+           /* Squirrel away the memory object port where it
+              can be retrieved by the program later.  */
+           l->l_info[DT_NULL] = (void *) memobj;
+         }
+
       /* 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,
@@ -106,6 +161,18 @@ unfmh();                   /* XXX */
       __mig_dealloc_reply_port (MACH_PORT_NULL);
       __mach_port_deallocate (__mach_task_self (), __mach_task_self_);
 
+      if (_dl_skip_args && _dl_argv[-_dl_skip_args] == (char *) p)
+       {
+         /* We are ignoring the first few arguments, but we have no Hurd
+            startup data.  It is magical convention that ARGV[0] == P in
+            this case.  The startup code in init-first.c will get confused
+            if this is not the case, so we must rearrange things to make
+            it so.  Overwrite the original ARGV[0] at P with
+            ARGV[_dl_skip_args].  */
+         assert ((char *) p < _dl_argv[0]);
+         _dl_argv[0] = strcpy ((char *) p, _dl_argv[0]);
+       }
+
       {
        extern void _dl_start_user (void);
        /* Unwind the stack to ARGDATA and simulate a return from _dl_start