This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: [PATCH][BZ #15022] Correct global-scope dlopen issues in static executables
- From: OndÅej BÃlka <neleai at seznam dot cz>
- To: "Maciej W. Rozycki" <macro at codesourcery dot com>
- Cc: Roland McGrath <roland at hack dot frob dot com>, libc-alpha at sourceware dot org
- Date: Mon, 7 Oct 2013 20:43:01 +0200
- Subject: Re: [PATCH][BZ #15022] Correct global-scope dlopen issues in static executables
- Authentication-results: sourceware.org; auth=none
- References: <alpine dot DEB dot 1 dot 10 dot 1301152056590 dot 4834 at tp dot orcam dot me dot uk> <20130116215545 dot 7A37A2C0B0 at topped-with-meat dot com> <alpine dot DEB dot 1 dot 10 dot 1301240655220 dot 4834 at tp dot orcam dot me dot uk>
This patch looks unreviewed since january.
On Thu, Jan 24, 2013 at 12:33:20PM +0000, Maciej W. Rozycki wrote:
> 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,
--
Your computer hasn't been returning all the bits it gets from the Internet.