summaryrefslogtreecommitdiff
path: root/sysdeps
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1995-09-30 21:18:30 +0000
committerRoland McGrath <roland@gnu.org>1995-09-30 21:18:30 +0000
commit879bf2e65a9ddaea34fe0428ab0f71caca4b4d00 (patch)
tree7bfc6325a784f1f65f7cd527f1b1be6f2ff1a456 /sysdeps
parent41cfadd63c6d28400f263460e3f2b15e74893b63 (diff)
* sysdeps/mach/hurd/dl-sysdep.c (_dl_sysdep_start): If started by
kernel with args on stack, point _dl_hurd_data at 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. * elf/link.h (struct link_map): New member `l_entry'. (_dl_map_object, _dl_map_object_from_fd): Remove last arg ENTRY_POINT. * elf/dl-load.c (_dl_map_object, _dl_map_object_from_fd): Remove last arg ENTRY_POINT. Store the entry point location in the `l_entry' member of the new map. * elf/rtld.c (dl_main): Don't pass USER_ENTRY arg to _dl_map_object. When run as program, set *USER_ENTRY to L->l_entry. * elf/dl-init.c (_dl_init_next): Don't pass ENTRY_POINT arg to _dl_map_object.
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/mach/hurd/dl-sysdep.c73
1 files changed, 70 insertions, 3 deletions
diff --git a/sysdeps/mach/hurd/dl-sysdep.c b/sysdeps/mach/hurd/dl-sysdep.c
index e55a615287..2daf74957c 100644
--- a/sysdeps/mach/hurd/dl-sysdep.c
+++ b/sysdeps/mach/hurd/dl-sysdep.c
@@ -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