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]

Re: [PATCH][BZ #15022] Correct global-scope dlopen issues in staticexecutables


On Wed, 16 Jan 2013, Roland McGrath wrote:

> As Joseph said, you should file two bugs with appropriate minimal test
> cases for the two issues.  Then use [BZ #nnn] in the log entry for the
> change that affects the bug.

 This is really a single bug only, triggering two different symptoms 
depending on how you poke at the bug.  The bug is the lack of global scope 
in static executables.  Now when you attempt to open that scope, as with 
dlopen (NULL, ...), then owing to how its internals work the dynamic 
loader engine tries to open a directory and treat it as a DSO.  When on 
the other hand you attempt to add a DSO to that scope, as with dlopen 
("foo", RTLD_GLOBAL), then the engine crashes.

 I have therefore created one bug report only, #15022.

> I would like to see a fix that does not change user-visible semantics at
> all (aside from not crashing, of course).  If the change to the
> user-visible semantics of dlopen is desireable, then propose it
> separately.  If it's inordinately difficult or ugly to fix the crash
> without the semantic change, then let the semantic change go in and
> settle first.  If it's reasonably doable to fix the problems without the
> semantic change, then send the fixes first and then if the semantic
> change is desireable and goes in later, you can send additional cleanup
> changes to make the code simpler again afterwards.

 Please elaborate on what user-visible semantics you would like 
specifically to preserve.

> Each test case should be minimal and focussed on testing just one thing.
> For dynamic linking tests, that means they should use pure examples that
> only rely on linking behavior use trivial functions in the test itself.
> If it's worthwhile to test something having to do with the value
> returned by getpagesize, add that as separate test for getpagesize or
> whatever it is truly testing, not for linking behavior.

 Well, some code paths can only be tested with more complicated scenarios 
and whenever a test case regresses you probably want to run `git bisect' 
on the tree anyway to find the offending change.  Obviously you can't 
verify that static DSO initialisation works correctly without referring to 
code that relies on that, like the said getpagesize function.

 Anyway I can see a benefit in having more limited cases as well, for 
example to assess a regression quickly without having to look into it in 
detail.  So I have added two extra test cases now, modelled on the 
original ones, that merely manipulate some data passed back and forth 
between a static executable and a DSO, and making sure the changes 
requested are as expected.  I hope the two new tests meet your 
expectations and fulfil your requirements.

 Additionally, I made the error messages more verbose and unique, so that 
any stage causing a failure is clearly identifiable by just looking at the 
relevant test case source, without a need to attach with GDB or suchlike.

 Finally, if you'd rather I split the getpagesize tests off and submitted 
them separately, then I'm fine with that; obviously the tests would have 
to be added after the bug fix itself or otherwise they would regress right 
away.

 I have smoke-tested the updated test cases, by running them on a 
big-endian o32 MIPS target.  If you agree this is the right change, then 
I'll run full testing -- that'll take about a day.  Otherwise I'll 
appreciate your feedback.  Thanks for your review.

2013-01-24  Maciej W. Rozycki  <macro@codesourcery.com>

	ChangeLog:
	[BZ #15022]
	* csu/libc-start.c (LIBC_START_MAIN) [!SHARED]: Prepare a global
	search list.
	* dlfcn/modstatic3.c: New file.
	* dlfcn/modstatic5.c: New file.
	* dlfcn/tststatic3.c: New file.
	* dlfcn/tststatic4.c: New file.
	* dlfcn/tststatic5.c: New file.
	* dlfcn/tststatic6.c: New file.
	* dlfcn/Makefile (tests): Add tststatic3, tststatic4, tststatic5
	and tststatic6.
	(tests-static): Likewise.
	(modules-names): Add modstatic3 and modstatic5.
	(tststatic3-ENV, tststatic4-ENV): New variables.
	($(objpfx)tststatic3, $(objpfx)tststatic3.out): New dependencies.
	($(objpfx)tststatic4, $(objpfx)tststatic4.out): Likewise.
	($(objpfx)tststatic5, $(objpfx)tststatic5.out): Likewise.
	($(objpfx)tststatic6, $(objpfx)tststatic6.out): Likewise.

	ports/ChangeLog.ia64:
	[BZ #15022]
	* sysdeps/unix/sysv/linux/ia64/dl-static.c (_dl_static_init):
	Exit right away if opening self.

	ports/ChangeLog.mips:
	[BZ #15022]
	* sysdeps/unix/sysv/linux/mips/dl-static.c (_dl_static_init):
	Exit right away if opening self.

  Maciej

glibc-static-dlopen.diff
Index: glibc-fsf-trunk-quilt/csu/libc-start.c
===================================================================
--- glibc-fsf-trunk-quilt.orig/csu/libc-start.c	2013-01-23 03:10:20.000000000 +0000
+++ glibc-fsf-trunk-quilt/csu/libc-start.c	2013-01-23 03:12:02.036666536 +0000
@@ -15,6 +15,7 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#include <assert.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <unistd.h>
@@ -177,6 +178,26 @@ LIBC_START_MAIN (int (*main) (int, char 
      we need to setup errno.  */
   __pthread_initialize_minimal ();
 
+  /* Create 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.  */
+  struct link_map **new_global;
+  struct link_map *main_map;
+
+  main_map = _dl_new_object ("", "", lt_executable, NULL, 0, LM_ID_BASE);
+  assert (main_map != NULL);
+
+  _dl_add_to_namespace_list (main_map, LM_ID_BASE);
+  assert (main_map == GL(dl_ns)[LM_ID_BASE]._ns_loaded);
+  GL(dl_nns) = 1;
+
+  new_global = malloc (sizeof (struct link_map **));
+  assert (new_global != NULL);
+  *new_global = main_map;
+  main_map->l_searchlist.r_list = new_global;
+  main_map->l_searchlist.r_nlist = 1;
+  GL(dl_ns)[LM_ID_BASE]._ns_main_searchlist = &main_map->l_searchlist;
+
   /* Set up the stack checker's canary.  */
   uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard (_dl_random);
 # ifdef THREAD_SET_STACK_GUARD
Index: glibc-fsf-trunk-quilt/dlfcn/Makefile
===================================================================
--- glibc-fsf-trunk-quilt.orig/dlfcn/Makefile	2013-01-23 03:10:20.000000000 +0000
+++ glibc-fsf-trunk-quilt/dlfcn/Makefile	2013-01-24 10:10:35.846606720 +0000
@@ -47,11 +47,16 @@ 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 tststatic5 tststatic6
+tests-static += tststatic tststatic2 tststatic3 tststatic4
+tests-static += tststatic5 tststatic6
+modules-names += modstatic modstatic2 modstatic3 modstatic5
 tststatic-ENV = LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)elf
 tststatic2-ENV = LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)elf
+tststatic3-ENV = LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)elf
+tststatic4-ENV = LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)elf
+tststatic5-ENV = LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)elf
+tststatic6-ENV = LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)elf
 endif
 
 extra-test-objs += $(modules-names:=.os)
@@ -104,6 +109,18 @@ $(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)tststatic5: $(objpfx)libdl.a
+$(objpfx)tststatic5.out: $(objpfx)tststatic5 $(objpfx)modstatic5.so
+
+$(objpfx)tststatic6: $(objpfx)libdl.a
+$(objpfx)tststatic6.out: $(objpfx)tststatic6 $(objpfx)modstatic5.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-01-24 12:24:09.087820478 +0000
@@ -0,0 +1,30 @@
+/* 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;
+}
+
+unsigned int
+setfoo (unsigned int f)
+{
+  foo = f;
+}
Index: glibc-fsf-trunk-quilt/dlfcn/modstatic5.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ glibc-fsf-trunk-quilt/dlfcn/modstatic5.c	2013-01-23 03:12:02.036666536 +0000
@@ -0,0 +1,24 @@
+/* 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 <unistd.h>
+
+int
+my_getpagesize (void)
+{
+  return getpagesize ();
+}
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-01-24 08:10:13.656588393 +0000
@@ -0,0 +1,114 @@
+/* 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>
+
+static int
+do_test (void)
+{
+  unsigned int (*getfoo) (void);
+  void (*setfoo) (unsigned int);
+  unsigned int *foop;
+  unsigned int foo;
+  void *handle;
+
+  handle = dlopen ("modstatic3.so", RTLD_LAZY | RTLD_GLOBAL);
+  if (handle == NULL)
+    {
+      printf ("dlopen (modstatic3.so): %s\n", dlerror ());
+      return 1;
+    }
+
+  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;
+    }
+
+  foo = *foop;
+  if (foo != 0)
+    {
+      printf ("*foop: got 0x%x, expected 0x0\n", foo);
+      return 1;
+    }
+
+  foo = getfoo ();
+  if (foo != 0)
+    {
+      printf ("getfoo: got 0x%x, expected 0x0\n", foo);
+      return 1;
+    }
+
+  setfoo (0x5500ffaa);
+
+  foo = *foop;
+  if (foo != 0x5500ffaa)
+    {
+      printf ("*foop: got 0x%x, expected 0x5500ffaa\n", foo);
+      return 1;
+    }
+
+  foo = getfoo ();
+  if (foo != 0x5500ffaa)
+    {
+      printf ("getfoo: got 0x%x, expected 0x5500ffaa\n", foo);
+      return 1;
+    }
+
+  setfoo (0xaaff0055);
+
+  foo = *foop;
+  if (foo != 0xaaff0055)
+    {
+      printf ("*foop: got 0x%x, expected 0xaaff0055\n", foo);
+      return 1;
+    }
+
+  foo = getfoo ();
+  if (foo != 0xaaff0055)
+    {
+      printf ("getfoo: got 0x%x, expected 0xaaff0055\n", foo);
+      return 1;
+    }
+
+  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-01-24 08:12:43.657338293 +0000
@@ -0,0 +1,340 @@
+/* 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>
+
+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;
+
+  initial_handle = dlopen (NULL, RTLD_LAZY | RTLD_GLOBAL);
+  if (initial_handle == NULL)
+    {
+      printf ("dlopen [initial] (NULL): %s\n", dlerror ());
+      return 1;
+    }
+
+  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;
+    }
+
+  global_handle = dlopen ("modstatic3.so", RTLD_LAZY | RTLD_GLOBAL);
+  if (global_handle == NULL)
+    {
+      printf ("dlopen [global] (modstatic3.so): %s\n", dlerror ());
+      return 1;
+    }
+
+  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;
+    }
+
+  local_handle = dlopen (NULL, RTLD_LAZY | RTLD_LOCAL);
+  if (local_handle == NULL)
+    {
+      printf ("dlopen [local] (NULL): %s\n", dlerror ());
+      return 1;
+    }
+
+  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;
+    }
+
+  initial_foop = dlsym (initial_handle, "foo");
+  if (initial_foop == NULL)
+    {
+      printf ("dlsym [local] (foo): %s\n", dlerror ());
+      return 1;
+    }
+
+  initial_getfoo = dlsym (initial_handle, "getfoo");
+  if (initial_getfoo == NULL)
+    {
+      printf ("dlsym [local] (getfoo): %s\n", dlerror ());
+      return 1;
+    }
+
+  initial_setfoo = dlsym (initial_handle, "setfoo");
+  if (initial_setfoo == NULL)
+    {
+      printf ("dlsym [local] (setfoo): %s\n", dlerror ());
+      return 1;
+    }
+
+  foo = *initial_foop;
+  if (foo != 0)
+    {
+      printf ("*foop [initial]: got 0x%x, expected 0x0\n", foo);
+      return 1;
+    }
+
+  foo = *global_foop;
+  if (foo != 0)
+    {
+      printf ("*foop [global]: got 0x%x, expected 0x0\n", foo);
+      return 1;
+    }
+
+  foo = *local_foop;
+  if (foo != 0)
+    {
+      printf ("*foop [local]: got 0x%x, expected 0x0\n", foo);
+      return 1;
+    }
+
+  foo = initial_getfoo ();
+  if (foo != 0)
+    {
+      printf ("getfoo [initial]: got 0x%x, expected 0x0\n", foo);
+      return 1;
+    }
+
+  foo = global_getfoo ();
+  if (foo != 0)
+    {
+      printf ("getfoo [global]: got 0x%x, expected 0x0\n", foo);
+      return 1;
+    }
+
+  foo = local_getfoo ();
+  if (foo != 0)
+    {
+      printf ("getfoo [local]: got 0x%x, expected 0x0\n", foo);
+      return 1;
+    }
+
+  initial_setfoo (0x5500ffaa);
+
+  foo = *initial_foop;
+  if (foo != 0x5500ffaa)
+    {
+      printf ("*foop [initial]: got 0x%x, expected 0x5500ffaa\n", foo);
+      return 1;
+    }
+
+  foo = *global_foop;
+  if (foo != 0x5500ffaa)
+    {
+      printf ("*foop [global]: got 0x%x, expected 0x5500ffaa\n", foo);
+      return 1;
+    }
+
+  foo = *local_foop;
+  if (foo != 0x5500ffaa)
+    {
+      printf ("*foop [local]: got 0x%x, expected 0x5500ffaa\n", foo);
+      return 1;
+    }
+
+  foo = initial_getfoo ();
+  if (foo != 0x5500ffaa)
+    {
+      printf ("getfoo [initial]: got 0x%x, expected 0x5500ffaa\n", foo);
+      return 1;
+    }
+
+  foo = global_getfoo ();
+  if (foo != 0x5500ffaa)
+    {
+      printf ("getfoo [global]: got 0x%x, expected 0x5500ffaa\n", foo);
+      return 1;
+    }
+
+  foo = local_getfoo ();
+  if (foo != 0x5500ffaa)
+    {
+      printf ("getfoo [local]: got 0x%x, expected 0x5500ffaa\n", foo);
+      return 1;
+    }
+
+  global_setfoo (0xaaff0055);
+
+  foo = *initial_foop;
+  if (foo != 0xaaff0055)
+    {
+      printf ("*foop [initial]: got 0x%x, expected 0xaaff0055\n", foo);
+      return 1;
+    }
+
+  foo = *global_foop;
+  if (foo != 0xaaff0055)
+    {
+      printf ("*foop [global]: got 0x%x, expected 0xaaff0055\n", foo);
+      return 1;
+    }
+
+  foo = *local_foop;
+  if (foo != 0xaaff0055)
+    {
+      printf ("*foop [local]: got 0x%x, expected 0xaaff0055\n", foo);
+      return 1;
+    }
+
+  foo = initial_getfoo ();
+  if (foo != 0xaaff0055)
+    {
+      printf ("getfoo [initial]: got 0x%x, expected 0xaaff0055\n", foo);
+      return 1;
+    }
+
+  foo = global_getfoo ();
+  if (foo != 0xaaff0055)
+    {
+      printf ("getfoo [global]: got 0x%x, expected 0xaaff0055\n", foo);
+      return 1;
+    }
+
+  foo = local_getfoo ();
+  if (foo != 0xaaff0055)
+    {
+      printf ("getfoo [local]: got 0x%x, expected 0xaaff0055\n", foo);
+      return 1;
+    }
+
+  local_setfoo (0xff55aa00);
+
+  foo = *initial_foop;
+  if (foo != 0xff55aa00)
+    {
+      printf ("*foop [initial]: got 0x%x, expected 0xff55aa00\n", foo);
+      return 1;
+    }
+
+  foo = *global_foop;
+  if (foo != 0xff55aa00)
+    {
+      printf ("*foop [global]: got 0x%x, expected 0xff55aa00\n", foo);
+      return 1;
+    }
+
+  foo = *local_foop;
+  if (foo != 0xff55aa00)
+    {
+      printf ("*foop [local]: got 0x%x, expected 0xff55aa00\n", foo);
+      return 1;
+    }
+
+  foo = initial_getfoo ();
+  if (foo != 0xff55aa00)
+    {
+      printf ("getfoo [initial]: got 0x%x, expected 0xff55aa00\n", foo);
+      return 1;
+    }
+
+  foo = global_getfoo ();
+  if (foo != 0xff55aa00)
+    {
+      printf ("getfoo [global]: got 0x%x, expected 0xff55aa00\n", foo);
+      return 1;
+    }
+
+  foo = local_getfoo ();
+  if (foo != 0xff55aa00)
+    {
+      printf ("getfoo [local]: got 0x%x, expected 0xff55aa00\n", foo);
+      return 1;
+    }
+
+  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/dlfcn/tststatic5.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ glibc-fsf-trunk-quilt/dlfcn/tststatic5.c	2013-01-24 08:09:14.486499700 +0000
@@ -0,0 +1,59 @@
+/* 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>
+#include <unistd.h>
+
+static int
+do_test (void)
+{
+  int pagesize = getpagesize ();
+  int (*my_getpagesize) (void);
+  int my_pagesize;
+  void *handle;
+
+  handle = dlopen ("modstatic5.so", RTLD_LAZY | RTLD_GLOBAL);
+  if (handle == NULL)
+    {
+      printf ("dlopen (modstatic5.so): %s\n", dlerror ());
+      return 1;
+    }
+
+  my_getpagesize = dlsym (handle, "my_getpagesize");
+  if (my_getpagesize == NULL)
+    {
+      printf ("dlsym (my_getpagesize): %s\n", dlerror ());
+      return 1;
+    }
+
+  my_pagesize = my_getpagesize ();
+  if (my_pagesize != pagesize)
+    {
+      printf ("my_getpagesize: got %i, expected %i\n", my_pagesize, pagesize);
+      return 1;
+    }
+
+  my_getpagesize = NULL;
+  dlclose (handle);
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
Index: glibc-fsf-trunk-quilt/dlfcn/tststatic6.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ glibc-fsf-trunk-quilt/dlfcn/tststatic6.c	2013-01-24 08:08:54.587145321 +0000
@@ -0,0 +1,125 @@
+/* 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>
+#include <unistd.h>
+
+static int
+do_test (void)
+{
+  int (*my_initial_getpagesize) (void);
+  int (*my_global_getpagesize) (void);
+  int (*my_local_getpagesize) (void);
+  int pagesize = getpagesize ();
+  int my_initial_pagesize;
+  int my_global_pagesize;
+  int my_local_pagesize;
+  void *initial_handle;
+  void *global_handle;
+  void *local_handle;
+
+  initial_handle = dlopen (NULL, RTLD_LAZY | RTLD_GLOBAL);
+  if (initial_handle == NULL)
+    {
+      printf ("dlopen [initial] (NULL): %s\n", dlerror ());
+      return 1;
+    }
+
+  my_initial_getpagesize = dlsym (initial_handle, "my_getpagesize");
+  if (my_initial_getpagesize != NULL)
+    {
+      printf ("dlsym [initial] (my_getpagesize): got %p, expected NULL\n",
+	      my_initial_getpagesize);
+      return 1;
+    }
+
+  global_handle = dlopen ("modstatic5.so", RTLD_LAZY | RTLD_GLOBAL);
+  if (global_handle == NULL)
+    {
+      printf ("dlopen [global] (modstatic5.so): %s\n", dlerror ());
+      return 1;
+    }
+
+  my_global_getpagesize = dlsym (global_handle, "my_getpagesize");
+  if (my_global_getpagesize == NULL)
+    {
+      printf ("dlsym [global] (my_getpagesize): %s\n", dlerror ());
+      return 1;
+    }
+
+  local_handle = dlopen (NULL, RTLD_LAZY | RTLD_LOCAL);
+  if (local_handle == NULL)
+    {
+      printf ("dlopen [local] (NULL): %s\n", dlerror ());
+      return 1;
+    }
+
+  my_local_getpagesize = dlsym (local_handle, "my_getpagesize");
+  if (my_local_getpagesize == NULL)
+    {
+      printf ("dlsym [local] (my_getpagesize): %s\n", dlerror ());
+      return 1;
+    }
+
+  my_initial_getpagesize = dlsym (initial_handle, "my_getpagesize");
+  if (my_initial_getpagesize == NULL)
+    {
+      printf ("dlsym [initial] (my_getpagesize): %s\n", dlerror ());
+      return 1;
+    }
+
+  my_initial_pagesize = my_initial_getpagesize ();
+  if (my_initial_pagesize != pagesize)
+    {
+      printf ("my_getpagesize [initial]: got %i, expected %i\n",
+	      my_initial_pagesize, pagesize);
+      return 1;
+    }
+
+  my_global_pagesize = my_global_getpagesize ();
+  if (my_global_pagesize != pagesize)
+    {
+      printf ("my_getpagesize [global]: got %i, expected %i\n",
+	      my_global_pagesize, pagesize);
+      return 1;
+    }
+
+  my_local_pagesize = my_local_getpagesize ();
+  if (my_local_pagesize != pagesize)
+    {
+      printf ("my_getpagesize [local]: got %i, expected %i\n",
+	      my_local_pagesize, pagesize);
+      return 1;
+    }
+
+  my_initial_getpagesize = NULL;
+
+  my_local_getpagesize = NULL;
+  dlclose (local_handle);
+
+  my_global_getpagesize = NULL;
+  dlclose (global_handle);
+
+  dlclose (initial_handle);
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
Index: glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/ia64/dl-static.c
===================================================================
--- glibc-fsf-trunk-quilt.orig/ports/sysdeps/unix/sysv/linux/ia64/dl-static.c	2013-01-23 03:10:20.000000000 +0000
+++ glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/ia64/dl-static.c	2013-01-23 03:12:02.047777535 +0000
@@ -52,6 +52,10 @@ _dl_static_init (struct link_map *map)
   lookup_t loadbase;
   void (*f) (void *[]);
 
+  /* Nothing to do if opening self.  */
+  if (__builtin_expect (map->l_name[0] == '\0', 0))
+    return;
+
   __libc_lock_lock_recursive (_dl_static_lock);
 
   loadbase = _dl_lookup_symbol_x ("_dl_var_init", map, &ref,
Index: glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/dl-static.c
===================================================================
--- glibc-fsf-trunk-quilt.orig/ports/sysdeps/unix/sysv/linux/mips/dl-static.c	2013-01-23 03:10:20.000000000 +0000
+++ glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/dl-static.c	2013-01-23 03:12:02.047777535 +0000
@@ -64,6 +64,10 @@ _dl_static_init (struct link_map *l)
   void (*f) (void *[]);
   size_t i;
 
+  /* Nothing to do if opening self.  */
+  if (__builtin_expect (l->l_name[0] == '\0', 0))
+    return;
+
   __libc_lock_lock_recursive (_dl_static_lock);
 
   loadbase = _dl_lookup_symbol_x ("_dl_var_init", l, &ref, l->l_local_scope,


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