[BZ #15022] Correct global-scope dlopen issues in static executables.
authorMaciej W. Rozycki <macro@codesourcery.com>
Fri, 28 Jun 2013 15:20:26 +0000 (16:20 +0100)
committerMaciej W. Rozycki <macro@codesourcery.com>
Fri, 28 Jun 2013 15:22:20 +0000 (16:22 +0100)
This change creates a link map in static executables to serve as the
global search list for dlopen.  It fixes a problem with the inability
to access the global symbol object and a crash on an attempt to map a
DSO into the global scope.  Some code that has become dead after the
addition of this link map is removed too and test cases are provided.

ChangeLog
NEWS
dlfcn/Makefile
dlfcn/modstatic3.c [new file with mode: 0644]
dlfcn/tststatic3.c [new file with mode: 0644]
dlfcn/tststatic4.c [new file with mode: 0644]
elf/dl-load.c
elf/dl-open.c
elf/dl-support.c

index 1012b2c2dbf8a329bf47f6832a15d047716bf3f9..174b184c37d2bea436c63377454373136d7ba897 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2013-06-28  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.
+
 2013-06-26  Joseph Myers  <joseph@codesourcery.com>
 
        * configure.in (CC): Require GCC version 4.4 or later.
diff --git a/NEWS b/NEWS
index 60fbe73c651b104ee0be396cb004a0aada65a6e5..e7fcf8158b6282c57406ab0a461cea7eaf7eab69 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -14,14 +14,14 @@ Version 2.18
   14176, 14200, 14256, 14280, 14293, 14317, 14327, 14478, 14496, 14582,
   14686, 14812, 14888, 14894, 14907, 14908, 14909, 14920, 14952, 14964,
   14981, 14982, 14985, 14991, 14994, 14996, 15000, 15003, 15006, 15007,
-  15014, 15020, 15023, 15036, 15054, 15055, 15062, 15078, 15084, 15085,
-  15086, 15100, 15160, 15214, 15221, 15232, 15234, 15283, 15285, 15287,
-  15304, 15305, 15307, 15309, 15327, 15330, 15335, 15336, 15337, 15339,
-  15342, 15346, 15359, 15361, 15366, 15380, 15381, 15394, 15395, 15405,
-  15406, 15409, 15416, 15418, 15419, 15423, 15424, 15426, 15429, 15431,
-  15432, 15441, 15442, 15448, 15465, 15480, 15485, 15488, 15490, 15492,
-  15493, 15497, 15506, 15529, 15536, 15553, 15577, 15583, 15618, 15627,
-  15631, 15654, 15655, 15666, 15667, 15674.
+  15014, 15020, 15022, 15023, 15036, 15054, 15055, 15062, 15078, 15084,
+  15085, 15086, 15100, 15160, 15214, 15221, 15232, 15234, 15283, 15285,
+  15287, 15304, 15305, 15307, 15309, 15327, 15330, 15335, 15336, 15337,
+  15339, 15342, 15346, 15359, 15361, 15366, 15380, 15381, 15394, 15395,
+  15405, 15406, 15409, 15416, 15418, 15419, 15423, 15424, 15426, 15429,
+  15431, 15432, 15441, 15442, 15448, 15465, 15480, 15485, 15488, 15490,
+  15492, 15493, 15497, 15506, 15529, 15536, 15553, 15577, 15583, 15618,
+  15627, 15631, 15654, 15655, 15666, 15667, 15674.
 
 * CVE-2013-0242 Buffer overrun in regexp matcher has been fixed (Bugzilla
   #15078).
index 20e6f0294e9206feb82538849306f7a4086e3fa2..fca0951a5a546bc51d5eb988c83700682f99a88b 100644 (file)
@@ -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)tststatic2 $(objpfx)modstatic.so \
 
 $(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
diff --git a/dlfcn/modstatic3.c b/dlfcn/modstatic3.c
new file mode 100644 (file)
index 0000000..cd24986
--- /dev/null
@@ -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;
+}
diff --git a/dlfcn/tststatic3.c b/dlfcn/tststatic3.c
new file mode 100644 (file)
index 0000000..8a3421e
--- /dev/null
@@ -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"
diff --git a/dlfcn/tststatic4.c b/dlfcn/tststatic4.c
new file mode 100644 (file)
index 0000000..f6078e0
--- /dev/null
@@ -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 757b6ec56b3db595740289192efec76840c3db2b..d53ead4db334721d238b519a35bccd020bc7e77c 100644 (file)
@@ -342,13 +342,7 @@ _dl_dst_substitute (struct link_map *l, const char *name, char *result,
          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 15221c8d5753255bc77b52802c6320fe5274736e..7adf66b221fdbb748b909fdfc436be099801b192 100644 (file)
@@ -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 b3ab9560ad75bf367f8368de3511bbe5d1e4b2f9..76752f33f37a73e8b40a131d6cac5a91b3e8183c 100644 (file)
@@ -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);