about summary refs log tree commit diff
path: root/elf
diff options
context:
space:
mode:
Diffstat (limited to 'elf')
-rw-r--r--elf/dl-error.c9
-rw-r--r--elf/dl-open.c8
-rw-r--r--elf/dlerror.c8
-rw-r--r--elf/rtld.c15
4 files changed, 31 insertions, 9 deletions
diff --git a/elf/dl-error.c b/elf/dl-error.c
index 737bba7421..2eaa7e03d1 100644
--- a/elf/dl-error.c
+++ b/elf/dl-error.c
@@ -46,8 +46,13 @@ _dl_signal_error (int errcode,
 
   if (catch)
     {
-      /* We are inside _dl_catch_error.  Return to it.  */
-      catch->errstring = errstring;
+      /* We are inside _dl_catch_error.  Return to it.  We have to
+	 duplicate the error string since it might be allocated on the
+	 stack.  */
+      size_t len = strlen (errstring) + 1;
+      catch->errstring = malloc (len);
+      if (catch->errstring != NULL)
+	memcpy (catch->errstring, errstring, len);
       catch->objname = objname;
       longjmp (catch->env, errcode ?: -1);
     }
diff --git a/elf/dl-open.c b/elf/dl-open.c
index 40b5224725..76f6329762 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -27,6 +27,11 @@ extern void _dl_start (void); weak_extern (_dl_start)
 
 extern int __libc_multiple_libcs;	/* Defined in init-first.c.  */
 
+extern int __libc_argc;
+extern char **__libc_argv;
+extern char **__libc_envp;
+
+
 size_t _dl_global_scope_alloc;
 
 struct link_map *
@@ -136,7 +141,8 @@ _dl_open (const char *file, int mode)
 
   /* Run the initializer functions of new objects.  */
   while (init = _dl_init_next (new))
-    (*(void (*) (void)) init) ();
+    (*(void (*) (int, char **, char **)) init) (__libc_argc, __libc_argv,
+						__libc_envp);
 
   if (dl_start_ptr == NULL)
     /* We must be the static _dl_open in libc.a because ld.so.1 is not
diff --git a/elf/dlerror.c b/elf/dlerror.c
index 4ec5037de4..663207d708 100644
--- a/elf/dlerror.c
+++ b/elf/dlerror.c
@@ -1,5 +1,5 @@
 /* dlerror -- Return error detail for failing <dlfcn.h> functions.
-Copyright (C) 1995 Free Software Foundation, Inc.
+Copyright (C) 1995, 1996 Free Software Foundation, Inc.
 This file is part of the GNU C Library.
 
 The GNU C Library is free software; you can redistribute it and/or
@@ -58,6 +58,7 @@ dlerror (void)
 	   ? NULL : buf);
 
   /* Reset the error indicator.  */
+  free (last_errstring);
   last_errstring = NULL;
   return ret;
 }
@@ -65,6 +66,11 @@ dlerror (void)
 int
 _dlerror_run (void (*operate) (void))
 {
+  if (last_errstring != NULL)
+    /* Free the error string from the last failed command.  This can
+       happen if `dlerror' was not run after an error was found.  */
+    free (last_errstring);
+
   last_errcode = _dl_catch_error (&last_errstring, &last_object_name,
 				  operate);
   return last_errstring != NULL;
diff --git a/elf/rtld.c b/elf/rtld.c
index 9f13124207..be71e88c3c 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -204,12 +204,15 @@ of this helper program; chances are you did not intend to run this program.\n",
 	    {
 	      l = _dl_map_object (NULL, _dl_argv[0], lt_library);
 	    }
-	  const char *err_str = NULL;
+	  char *err_str = NULL;
 	  const char *obj_name __attribute__ ((unused));
 
 	  (void) _dl_catch_error (&err_str, &obj_name, doit);
 	  if (err_str != NULL)
-	    _exit (EXIT_FAILURE);
+	    {
+	      free (err_str);
+	      _exit (EXIT_FAILURE);
+	    }
 	}
       else
 	l = _dl_map_object (NULL, _dl_argv[0], lt_library);
@@ -395,7 +398,8 @@ of this helper program; chances are you did not intend to run this program.\n",
 	    const ElfW(Sym) *ref = NULL;
 	    ElfW(Addr) loadbase = _dl_lookup_symbol (_dl_argv[i], &ref,
 						     &_dl_default_scope[2],
-						     "argument", 0);
+						     "argument",
+						     DL_LOOKUP_NOPLT);
 	    char buf[20], *bp;
 	    buf[sizeof buf - 1] = '\0';
 	    bp = _itoa (ref->st_value, &buf[sizeof buf - 1], 16, 0);
@@ -488,8 +492,9 @@ of this helper program; chances are you did not intend to run this program.\n",
 	 dynamic linker.  There is no additional initialization
 	 required for the ABI-compliant dynamic linker.  */
 
-      (*(void (*) (void)) (_dl_rtld_map.l_addr +
-			   _dl_rtld_map.l_info[DT_INIT]->d_un.d_ptr)) ();
+      (*(void (*) (int, char **, char**))
+       (_dl_rtld_map.l_addr + _dl_rtld_map.l_info[DT_INIT]->d_un.d_ptr))
+	(0, NULL, NULL);
 
       /* Clear the field so a future dlopen won't run it again.  */
       _dl_rtld_map.l_info[DT_INIT] = NULL;