This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 3/5][v3][BZ #15022] Correct global-scope dlopen issues in static executables


On Fri, 21 Jun 2013, Roland McGrath wrote:

> > +  /* Try to map a module into the global scope.  */
> > +  handle = dlopen ("modstatic3.so", RTLD_LAZY | RTLD_GLOBAL);
> 
> I guess this is testing just that having RTLD_GLOBAL there doesn't make it
> crash?  There is nothing in the test that actually makes using RTLD_GLOBAL
> worthwhile, so the comment should say clearly why it's using the flag.

 Good point, I've updated comments accordingly and added a BZ # reference.

> > +/* Global-scope DSO tests with a static executable.
> 
> This is the same comment as the first test.  Is there something concise you
> can say here that distinguishes why there are two tests?  If it's just sort
> of a basic test and an exhaustive test, I guess just adding ", more cases"
> or something would be fine.

 The main scopes of the two tests are different -- tststatic3 verifies DSO 
mapping into the global scope while tststatic4 checks access to the global 
object.  Of course the latter requires an auxiliary DSO too or otherwise 
there would be little here to test, so it ends up overlapping with the 
former.  I have updated comments accordingly and added a BZ # reference 
here as well.

> > +  /* Try to map itself into the global scope.  */
> > +  initial_handle = dlopen (NULL, RTLD_LAZY | RTLD_GLOBAL);
> 
> RTLD_GLOBAL isn't really meaningful here, is it?
> The main program pseudo-object is the basis of the global scope.

 Well, either of RTLD_GLOBAL or RTLD_LOCAL should work here and one has to 
be specified.  I use RTLD_LOCAL later on, so I think RTLD_GLOBAL makes 
sense here for diversity.

 While looking into it I've noticed we don't actually have any RTLD_GLOBAL 
vs RTLD_LOCAL semantics tests.  I think with little tweaking tststatic4 
can be adjusted to serve as such a test, for regular dynamic access (i.e. 
from a dynamic executable).  I'll try to cook up something based on that, 
sometime (unless you or someone else beats me to it, that is).

> > +      printf ("*foop [initial]: got 0x%x, expected 0x%x\n", foo, MAGIC0);
> 
> Always use %#x in preference to 0x%x.

 Fixed.

> > +    .l_libname = &(struct libname_list) { .name = "", .dont_free = 1 },
> 
> I didn't realize &compound_literal was kosher.  Nice!

 Indeed.  Useful to avoid namespace pollution.

> > +#if NO_TLS_OFFSET != 0
> > +    .l_tls_offset = NO_TLS_OFFSET,
> > +#endif
> 
> Drop the #if.  An explicit initializer to zero has no cost.

 Fixed.

> Aside from that one nit, the implementation itself looks great.  I'll trust
> you to do appropriate commenting and clean-up on the tests without another
> round of review.

 Thanks.  I've decided to post the new version after all as I found 
another place, in dl-load.c, where I think a piece of !SHARED code can be 
removed.  With the addition of .l_origin initialisation to 
_dl_non_dynamic_init I believe there is not going to be a case where this 
member is null at the time _dl_dst_substitute is called.  Please confirm 
my understanding.  I saw no regressions in MIPS testing with this update.

2013-06-27  Maciej W. Rozycki  <macro@codesourcery.com>

	[BZ #15022]
	* elf/dl-support.c (_dl_main_map): New variable.
	(_dl_ns): Use it to initialize [LM_ID_BASE] element.
	(_dl_nns, _dl_load_adds): Set to 1.
	(_dl_initial_searchlist): Refer to _dl_main_map.
	(_dl_non_dynamic_init): Initialize _dl_main_map.l_origin.
	* elf/dl-load.c (_dl_dst_substitute) [!SHARED]: Remove fallback
	call to _dl_get_origin.
	* elf/dl-open.c (dl_open_worker): Remove !SHARED special casing
	around call_map.
	(_dl_open) [!SHARED]: Remove code to initialize GL(dl_nns).
	* dlfcn/modstatic3.c: New file.
	* dlfcn/tststatic3.c: New file.
	* dlfcn/tststatic4.c: New file.
	* dlfcn/Makefile (tests): Add tststatic3 and tststatic4.
	(tests-static): Likewise.
	(modules-names): Add modstatic3.
	(tststatic3-ENV, tststatic4-ENV): New variables.
	($(objpfx)tststatic3, $(objpfx)tststatic3.out): New dependencies.
	($(objpfx)tststatic4, $(objpfx)tststatic4.out): Likewise.

  Maciej

glibc-static-dlopen.diff
Index: glibc-fsf-trunk-quilt/dlfcn/Makefile
===================================================================
--- glibc-fsf-trunk-quilt.orig/dlfcn/Makefile	2013-06-27 13:16:36.000000000 +0100
+++ glibc-fsf-trunk-quilt/dlfcn/Makefile	2013-06-27 13:42:23.682810206 +0100
@@ -47,11 +47,13 @@ glreflib2.so-no-z-defs = yes
 errmsg1mod.so-no-z-defs = yes
 
 ifeq (yes,$(build-shared))
-tests += tststatic tststatic2
-tests-static += tststatic tststatic2
-modules-names += modstatic modstatic2
+tests += tststatic tststatic2 tststatic3 tststatic4
+tests-static += tststatic tststatic2 tststatic3 tststatic4
+modules-names += modstatic modstatic2 modstatic3
 tststatic-ENV = LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)elf
 tststatic2-ENV = $(tststatic-ENV)
+tststatic3-ENV = $(tststatic-ENV)
+tststatic4-ENV = $(tststatic-ENV)
 endif
 
 extra-test-objs += $(modules-names:=.os)
@@ -104,6 +106,12 @@ $(objpfx)tststatic2.out: $(objpfx)tststa
 
 $(objpfx)modstatic2.so: $(libdl)
 
+$(objpfx)tststatic3: $(objpfx)libdl.a
+$(objpfx)tststatic3.out: $(objpfx)tststatic3 $(objpfx)modstatic3.so
+
+$(objpfx)tststatic4: $(objpfx)libdl.a
+$(objpfx)tststatic4.out: $(objpfx)tststatic4 $(objpfx)modstatic3.so
+
 $(objpfx)bug-dlopen1: $(libdl)
 
 $(objpfx)bug-dlsym1: $(libdl) $(objpfx)bug-dlsym1-lib2.so
Index: glibc-fsf-trunk-quilt/dlfcn/modstatic3.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ glibc-fsf-trunk-quilt/dlfcn/modstatic3.c	2013-06-27 13:42:23.682810206 +0100
@@ -0,0 +1,31 @@
+/* DSO used for dlopen testing with a static executable.
+   Copyright (C) 2013 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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+unsigned int foo;
+
+unsigned int
+getfoo (void)
+{
+  return foo;
+}
+
+void
+setfoo (unsigned int f)
+{
+  foo = f;
+}
Index: glibc-fsf-trunk-quilt/dlfcn/tststatic3.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ glibc-fsf-trunk-quilt/dlfcn/tststatic3.c	2013-06-27 13:42:23.682810206 +0100
@@ -0,0 +1,128 @@
+/* Global-scope DSO mapping test with a static executable (BZ #15022).
+   Copyright (C) 2013 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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <dlfcn.h>
+#include <stddef.h>
+#include <stdio.h>
+
+#define MAGIC0 0
+#define MAGIC1 0x5500ffaa
+#define MAGIC2 0xaaff0055
+
+/* Mapping a DSO into the global scope used to crash in static
+   executables.  Check that it succeeds and then that symbols from
+   the DSO can be accessed and operate as expected.  */
+static int
+do_test (void)
+{
+  unsigned int (*getfoo) (void);
+  void (*setfoo) (unsigned int);
+  unsigned int *foop;
+  unsigned int foo;
+  void *handle;
+
+  /* Try to map a module into the global scope.  */
+  handle = dlopen ("modstatic3.so", RTLD_LAZY | RTLD_GLOBAL);
+  if (handle == NULL)
+    {
+      printf ("dlopen (modstatic3.so): %s\n", dlerror ());
+      return 1;
+    }
+
+  /* Get at its symbols.  */
+  foop = dlsym (handle, "foo");
+  if (foop == NULL)
+    {
+      printf ("dlsym (foo): %s\n", dlerror ());
+      return 1;
+    }
+
+  getfoo = dlsym (handle, "getfoo");
+  if (getfoo == NULL)
+    {
+      printf ("dlsym (getfoo): %s\n", dlerror ());
+      return 1;
+    }
+
+  setfoo = dlsym (handle, "setfoo");
+  if (setfoo == NULL)
+    {
+      printf ("dlsym (setfoo): %s\n", dlerror ());
+      return 1;
+    }
+
+  /* Make sure the view of the initial state is consistent.  */
+  foo = *foop;
+  if (foo != MAGIC0)
+    {
+      printf ("*foop: got %#x, expected %#x\n", foo, MAGIC0);
+      return 1;
+    }
+
+  foo = getfoo ();
+  if (foo != MAGIC0)
+    {
+      printf ("getfoo: got %#x, expected %#x\n", foo, MAGIC0);
+      return 1;
+    }
+
+  /* Likewise with one change to its state.  */
+  setfoo (MAGIC1);
+
+  foo = *foop;
+  if (foo != MAGIC1)
+    {
+      printf ("*foop: got %#x, expected %#x\n", foo, MAGIC1);
+      return 1;
+    }
+
+  foo = getfoo ();
+  if (foo != MAGIC1)
+    {
+      printf ("getfoo: got %#x, expected %#x\n", foo, MAGIC1);
+      return 1;
+    }
+
+  /* And with another.  */
+  setfoo (MAGIC2);
+
+  foo = *foop;
+  if (foo != MAGIC2)
+    {
+      printf ("*foop: got %#x, expected %#x\n", foo, MAGIC2);
+      return 1;
+    }
+
+  foo = getfoo ();
+  if (foo != MAGIC2)
+    {
+      printf ("getfoo: got %#x, expected %#x\n", foo, MAGIC2);
+      return 1;
+    }
+
+  /* All done, clean up.  */
+  getfoo = NULL;
+  setfoo = NULL;
+  foop = NULL;
+  dlclose (handle);
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
Index: glibc-fsf-trunk-quilt/dlfcn/tststatic4.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ glibc-fsf-trunk-quilt/dlfcn/tststatic4.c	2013-06-27 17:13:39.952489145 +0100
@@ -0,0 +1,363 @@
+/* Global object symbol access tests with a static executable (BZ #15022).
+   Copyright (C) 2013 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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <dlfcn.h>
+#include <stddef.h>
+#include <stdio.h>
+
+#define MAGIC0 0
+#define MAGIC1 0x5500ffaa
+#define MAGIC2 0xaaff0055
+#define MAGIC3 0xff55aa00
+
+/* Check the ability to access the global symbol object and then
+   global-scope symbol access consistency via different mappings
+   requested from a static executable.  */
+static int
+do_test (void)
+{
+  unsigned int (*initial_getfoo) (void);
+  void (*initial_setfoo) (unsigned int);
+  unsigned int (*global_getfoo) (void);
+  void (*global_setfoo) (unsigned int);
+  unsigned int (*local_getfoo) (void);
+  void (*local_setfoo) (unsigned int);
+  unsigned int *initial_foop;
+  unsigned int *global_foop;
+  unsigned int *local_foop;
+  void *initial_handle;
+  void *global_handle;
+  void *local_handle;
+  unsigned int foo;
+
+  /* Try to map self.  */
+  initial_handle = dlopen (NULL, RTLD_LAZY | RTLD_GLOBAL);
+  if (initial_handle == NULL)
+    {
+      printf ("dlopen [initial] (NULL): %s\n", dlerror ());
+      return 1;
+    }
+
+  /* Make sure symbol lookups fail gracefully.  */
+  initial_foop = dlsym (initial_handle, "foo");
+  if (initial_foop != NULL)
+    {
+      printf ("dlsym [initial] (foo): got %p, expected NULL\n", initial_foop);
+      return 1;
+    }
+
+  initial_getfoo = dlsym (initial_handle, "getfoo");
+  if (initial_getfoo != NULL)
+    {
+      printf ("dlsym [initial] (getfoo): got %p, expected NULL\n",
+	      initial_getfoo);
+      return 1;
+    }
+
+  initial_setfoo = dlsym (initial_handle, "setfoo");
+  if (initial_setfoo != NULL)
+    {
+      printf ("dlsym [initial] (setfoo): got %p, expected NULL\n",
+	      initial_setfoo);
+      return 1;
+    }
+
+  /* Try to map a module into the global scope.  */
+  global_handle = dlopen ("modstatic3.so", RTLD_LAZY | RTLD_GLOBAL);
+  if (global_handle == NULL)
+    {
+      printf ("dlopen [global] (modstatic3.so): %s\n", dlerror ());
+      return 1;
+    }
+
+  /* Get at its symbols.  */
+  global_foop = dlsym (global_handle, "foo");
+  if (global_foop == NULL)
+    {
+      printf ("dlsym [global] (foo): %s\n", dlerror ());
+      return 1;
+    }
+
+  global_getfoo = dlsym (global_handle, "getfoo");
+  if (global_getfoo == NULL)
+    {
+      printf ("dlsym [global] (getfoo): %s\n", dlerror ());
+      return 1;
+    }
+
+  global_setfoo = dlsym (global_handle, "setfoo");
+  if (global_setfoo == NULL)
+    {
+      printf ("dlsym [global] (setfoo): %s\n", dlerror ());
+      return 1;
+    }
+
+  /* Try to map self again now.  */
+  local_handle = dlopen (NULL, RTLD_LAZY | RTLD_LOCAL);
+  if (local_handle == NULL)
+    {
+      printf ("dlopen [local] (NULL): %s\n", dlerror ());
+      return 1;
+    }
+
+  /* Make sure we can get at the previously loaded module's symbols
+     via this handle too.  */
+  local_foop = dlsym (local_handle, "foo");
+  if (local_foop == NULL)
+    {
+      printf ("dlsym [local] (foo): %s\n", dlerror ());
+      return 1;
+    }
+
+  local_getfoo = dlsym (local_handle, "getfoo");
+  if (local_getfoo == NULL)
+    {
+      printf ("dlsym [local] (getfoo): %s\n", dlerror ());
+      return 1;
+    }
+
+  local_setfoo = dlsym (local_handle, "setfoo");
+  if (local_setfoo == NULL)
+    {
+      printf ("dlsym [local] (setfoo): %s\n", dlerror ());
+      return 1;
+    }
+
+  /* Make sure we can get at the previously loaded module's symbols
+     via a handle that was obtained before the module was loaded too.  */
+  initial_foop = dlsym (initial_handle, "foo");
+  if (initial_foop == NULL)
+    {
+      printf ("dlsym [initial] (foo): %s\n", dlerror ());
+      return 1;
+    }
+
+  initial_getfoo = dlsym (initial_handle, "getfoo");
+  if (initial_getfoo == NULL)
+    {
+      printf ("dlsym [initial] (getfoo): %s\n", dlerror ());
+      return 1;
+    }
+
+  initial_setfoo = dlsym (initial_handle, "setfoo");
+  if (initial_setfoo == NULL)
+    {
+      printf ("dlsym [initial] (setfoo): %s\n", dlerror ());
+      return 1;
+    }
+
+  /* Make sure the view of the initial state is consistent.  */
+  foo = *initial_foop;
+  if (foo != MAGIC0)
+    {
+      printf ("*foop [initial]: got %#x, expected %#x\n", foo, MAGIC0);
+      return 1;
+    }
+
+  foo = *global_foop;
+  if (foo != MAGIC0)
+    {
+      printf ("*foop [global]: got %#x, expected %#x\n", foo, MAGIC0);
+      return 1;
+    }
+
+  foo = *local_foop;
+  if (foo != MAGIC0)
+    {
+      printf ("*foop [local]: got %#x, expected %#x\n", foo, MAGIC0);
+      return 1;
+    }
+
+  foo = initial_getfoo ();
+  if (foo != MAGIC0)
+    {
+      printf ("getfoo [initial]: got %#x, expected %#x\n", foo, MAGIC0);
+      return 1;
+    }
+
+  foo = global_getfoo ();
+  if (foo != MAGIC0)
+    {
+      printf ("getfoo [global]: got %#x, expected %#x\n", foo, MAGIC0);
+      return 1;
+    }
+
+  foo = local_getfoo ();
+  if (foo != MAGIC0)
+    {
+      printf ("getfoo [local]: got %#x, expected %#x\n", foo, MAGIC0);
+      return 1;
+    }
+
+  /* Likewise with a change to its state made through the first handle.  */
+  initial_setfoo (MAGIC1);
+
+  foo = *initial_foop;
+  if (foo != MAGIC1)
+    {
+      printf ("*foop [initial]: got %#x, expected %#x\n", foo, MAGIC1);
+      return 1;
+    }
+
+  foo = *global_foop;
+  if (foo != MAGIC1)
+    {
+      printf ("*foop [global]: got %#x, expected %#x\n", foo, MAGIC1);
+      return 1;
+    }
+
+  foo = *local_foop;
+  if (foo != MAGIC1)
+    {
+      printf ("*foop [local]: got %#x, expected %#x\n", foo, MAGIC1);
+      return 1;
+    }
+
+  foo = initial_getfoo ();
+  if (foo != MAGIC1)
+    {
+      printf ("getfoo [initial]: got %#x, expected %#x\n", foo, MAGIC1);
+      return 1;
+    }
+
+  foo = global_getfoo ();
+  if (foo != MAGIC1)
+    {
+      printf ("getfoo [global]: got %#x, expected %#x\n", foo, MAGIC1);
+      return 1;
+    }
+
+  foo = local_getfoo ();
+  if (foo != MAGIC1)
+    {
+      printf ("getfoo [local]: got %#x, expected %#x\n", foo, MAGIC1);
+      return 1;
+    }
+
+  /* Likewise with a change to its state made through the second handle.  */
+  global_setfoo (MAGIC2);
+
+  foo = *initial_foop;
+  if (foo != MAGIC2)
+    {
+      printf ("*foop [initial]: got %#x, expected %#x\n", foo, MAGIC2);
+      return 1;
+    }
+
+  foo = *global_foop;
+  if (foo != MAGIC2)
+    {
+      printf ("*foop [global]: got %#x, expected %#x\n", foo, MAGIC2);
+      return 1;
+    }
+
+  foo = *local_foop;
+  if (foo != MAGIC2)
+    {
+      printf ("*foop [local]: got %#x, expected %#x\n", foo, MAGIC2);
+      return 1;
+    }
+
+  foo = initial_getfoo ();
+  if (foo != MAGIC2)
+    {
+      printf ("getfoo [initial]: got %#x, expected %#x\n", foo, MAGIC2);
+      return 1;
+    }
+
+  foo = global_getfoo ();
+  if (foo != MAGIC2)
+    {
+      printf ("getfoo [global]: got %#x, expected %#x\n", foo, MAGIC2);
+      return 1;
+    }
+
+  foo = local_getfoo ();
+  if (foo != MAGIC2)
+    {
+      printf ("getfoo [local]: got %#x, expected %#x\n", foo, MAGIC2);
+      return 1;
+    }
+
+  /* Likewise with a change to its state made through the third handle.  */
+  local_setfoo (MAGIC3);
+
+  foo = *initial_foop;
+  if (foo != MAGIC3)
+    {
+      printf ("*foop [initial]: got %#x, expected %#x\n", foo, MAGIC3);
+      return 1;
+    }
+
+  foo = *global_foop;
+  if (foo != MAGIC3)
+    {
+      printf ("*foop [global]: got %#x, expected %#x\n", foo, MAGIC3);
+      return 1;
+    }
+
+  foo = *local_foop;
+  if (foo != MAGIC3)
+    {
+      printf ("*foop [local]: got %#x, expected %#x\n", foo, MAGIC3);
+      return 1;
+    }
+
+  foo = initial_getfoo ();
+  if (foo != MAGIC3)
+    {
+      printf ("getfoo [initial]: got %#x, expected %#x\n", foo, MAGIC3);
+      return 1;
+    }
+
+  foo = global_getfoo ();
+  if (foo != MAGIC3)
+    {
+      printf ("getfoo [global]: got %#x, expected %#x\n", foo, MAGIC3);
+      return 1;
+    }
+
+  foo = local_getfoo ();
+  if (foo != MAGIC3)
+    {
+      printf ("getfoo [local]: got %#x, expected %#x\n", foo, MAGIC3);
+      return 1;
+    }
+
+  /* All done, clean up.  */
+  initial_getfoo = NULL;
+  initial_setfoo = NULL;
+  initial_foop = NULL;
+
+  local_getfoo = NULL;
+  local_setfoo = NULL;
+  local_foop = NULL;
+  dlclose (local_handle);
+
+  global_getfoo = NULL;
+  global_setfoo = NULL;
+  global_foop = NULL;
+  dlclose (global_handle);
+
+  dlclose (initial_handle);
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
Index: glibc-fsf-trunk-quilt/elf/dl-load.c
===================================================================
--- glibc-fsf-trunk-quilt.orig/elf/dl-load.c	2013-06-27 13:16:36.000000000 +0100
+++ glibc-fsf-trunk-quilt/elf/dl-load.c	2013-06-27 13:42:23.682810206 +0100
@@ -342,13 +342,7 @@ _dl_dst_substitute (struct link_map *l, 
 	  if ((len = is_dst (start, name, "ORIGIN", is_path,
 			     INTUSE(__libc_enable_secure))) != 0)
 	    {
-#ifndef SHARED
-	      if (l == NULL)
-		repl = _dl_get_origin ();
-	      else
-#endif
-		repl = l->l_origin;
-
+	      repl = l->l_origin;
 	      check_for_trusted = (INTUSE(__libc_enable_secure)
 				   && l->l_type == lt_executable);
 	    }
Index: glibc-fsf-trunk-quilt/elf/dl-open.c
===================================================================
--- glibc-fsf-trunk-quilt.orig/elf/dl-open.c	2013-06-27 13:16:36.000000000 +0100
+++ glibc-fsf-trunk-quilt/elf/dl-open.c	2013-06-27 13:42:23.682810206 +0100
@@ -204,11 +204,9 @@ dl_open_worker (void *a)
     {
       const void *caller_dlopen = args->caller_dlopen;
 
-#ifdef SHARED
       /* We have to find out from which object the caller is calling.
 	 By default we assume this is the main application.  */
       call_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
-#endif
 
       struct link_map *l = _dl_find_dso_for_object ((ElfW(Addr)) caller_dlopen);
 
@@ -216,15 +214,7 @@ dl_open_worker (void *a)
         call_map = l;
 
       if (args->nsid == __LM_ID_CALLER)
-	{
-#ifndef SHARED
-	  /* In statically linked apps there might be no loaded object.  */
-	  if (call_map == NULL)
-	    args->nsid = LM_ID_BASE;
-	  else
-#endif
-	    args->nsid = call_map->l_ns;
-	}
+	args->nsid = call_map->l_ns;
     }
 
   assert (_dl_debug_initialize (0, args->nsid)->r_state == RT_CONSISTENT);
@@ -642,12 +632,6 @@ no more namespaces available for dlmopen
 	       || GL(dl_ns)[nsid]._ns_loaded->l_auditing))
     _dl_signal_error (EINVAL, file, NULL,
 		      N_("invalid target namespace in dlmopen()"));
-#ifndef SHARED
-  else if ((nsid == LM_ID_BASE || nsid == __LM_ID_CALLER)
-	   && GL(dl_ns)[LM_ID_BASE]._ns_loaded == NULL
-	   && GL(dl_nns) == 0)
-    GL(dl_nns) = 1;
-#endif
 
   struct dl_open_args args;
   args.file = file;
Index: glibc-fsf-trunk-quilt/elf/dl-support.c
===================================================================
--- glibc-fsf-trunk-quilt.orig/elf/dl-support.c	2013-06-27 13:16:36.000000000 +0100
+++ glibc-fsf-trunk-quilt/elf/dl-support.c	2013-06-27 13:42:23.682810206 +0100
@@ -70,17 +70,52 @@ const char *_dl_origin_path;
 /* Nonzero if runtime lookup should not update the .got/.plt.  */
 int _dl_bind_not;
 
+/* A dummy link map for the executable, used by dlopen to access the global
+   scope.  We don't export any symbols ourselves, so this can be minimal.  */
+static struct link_map _dl_main_map =
+  {
+    .l_name = (char *) "",
+    .l_real = &_dl_main_map,
+    .l_ns = LM_ID_BASE,
+    .l_libname = &(struct libname_list) { .name = "", .dont_free = 1 },
+    .l_searchlist =
+      {
+	.r_list = &(struct link_map *) { &_dl_main_map },
+	.r_nlist = 1,
+      },
+    .l_symbolic_searchlist = { .r_list = &(struct link_map *) { NULL } },
+    .l_type = lt_executable,
+    .l_scope_mem = { &_dl_main_map.l_searchlist },
+    .l_scope_max = (sizeof (_dl_main_map.l_scope_mem)
+		    / sizeof (_dl_main_map.l_scope_mem[0])),
+    .l_scope = _dl_main_map.l_scope_mem,
+    .l_local_scope = { &_dl_main_map.l_searchlist },
+    .l_used = 1,
+    .l_tls_offset = NO_TLS_OFFSET,
+    .l_serial = 1,
+  };
+
 /* Namespace information.  */
-struct link_namespaces _dl_ns[DL_NNS];
-size_t _dl_nns;
+struct link_namespaces _dl_ns[DL_NNS] =
+  {
+    [LM_ID_BASE] =
+      {
+	._ns_loaded = &_dl_main_map,
+	._ns_nloaded = 1,
+	._ns_main_searchlist = &_dl_main_map.l_searchlist,
+      }
+  };
+size_t _dl_nns = 1;
 
 /* Incremented whenever something may have been added to dl_loaded. */
-unsigned long long _dl_load_adds;
+unsigned long long _dl_load_adds = 1;
 
-/* Fake scope.  In dynamically linked binaries this is the scope of the
-   main application but here we don't have something like this.  So
-   create a fake scope containing nothing.  */
-struct r_scope_elem _dl_initial_searchlist;
+/* Fake scope of the main application.  */
+struct r_scope_elem _dl_initial_searchlist =
+  {
+    .r_list = &(struct link_map *) { &_dl_main_map },
+    .r_nlist = 1,
+  };
 
 #ifndef HAVE_INLINED_SYSCALLS
 /* Nonzero during startup.  */
@@ -265,6 +300,8 @@ void
 internal_function
 _dl_non_dynamic_init (void)
 {
+  _dl_main_map.l_origin = _dl_get_origin ();
+
   if (HP_TIMING_AVAIL)
     HP_TIMING_NOW (_dl_cpuclock_offset);
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]