http://thread.gmane.org/gmane.comp.lib.glibc.user/579 http://sources.redhat.com/bugzilla/show_bug.cgi?id=11929 http://bugs.gentoo.org/332927 a simple statically linked app fails with glibc-2.12: $ cat test.c main(){getpwnam("root");} $ gcc -static test.c $ ./a.out a.out: ../sysdeps/unix/sysv/linux/getpagesize.c:32: __getpagesize: Assertion `_rtld_global_ro._dl_pagesize != 0' failed. Aborted (core dumped) the crux of the matter seems to be the fact that static apps with glibc will dynamically load nss shared libraries when necessary. the static code will initialize GLRO(dl_pagesize) just fine from the kernel auxv, but this being the static code paths, GLRO(dl_pagesize) expands into _dl_pagesize. when the nss shared libraries are loaded up, the ldso is also mapped in, but it doesnt process the kernel auxv (_dl_sysdep_start() is not called). so the shared library GLRO(dl_pagesize) expands into _rtld_global_ro._dl_pagesize and that field stays at 0. then when the nss shared libs process the request and gets to the standard "passwd" database, it calls the shared lib versions of malloc/stdio which rely on the __getpagesize() function. but this being in the shared library, it reads the shared GLRO(dl_pagesize) which is 0, and the assert() is triggered. i think running nscd makes things work because its nss module that talks to the nscd daemon doesnt call any routines that implicitly rely on __getpagesize(). this all started happening after this commit: From 8f4a5048eea6536ee85c0f2670adbb97d71e427d Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Sat, 27 Mar 2010 06:19:50 -0700 Subject: [PATCH] Optimize __getpagesize a bit. if we look at the ia64 port, we see that it has had similar logic for its __getpagesize function forever. so take its DL_STATIC_INIT code and move it up to the common linux tree. 2010-08-18 Mike Frysinger * sysdeps/unix/sysv/linux/ia64/Makefile: Move dl-static addition to sysdep vars for subdir==elf to ... * sysdeps/unix/sysv/linux/Makefile: ... here. * sysdeps/unix/sysv/linux/ia64/dl-static.c: Move file to ... * sysdeps/unix/sysv/linux/dl-static.c: ... here. * sysdeps/unix/sysv/linux/ia64/ldsodefs.h: Delete, and move the DL_STATIC_INIT defines to ... * sysdeps/unix/sysv/linux/ldsodefs.h: ... here. * sysdeps/unix/sysv/linux/ia64/getpagesize.c: Delete. diff --git a/sysdeps/unix/sysv/linux/ia64/Makefile b/sysdeps/unix/sysv/linux/ia64/Makefile index d9a35a7..3bb1ce0 100644 --- a/sysdeps/unix/sysv/linux/ia64/Makefile +++ b/sysdeps/unix/sysv/linux/ia64/Makefile @@ -12,12 +12,6 @@ sysdep_headers += sys/io.h sysdep_routines += ioperm clone2 endif -ifeq ($(subdir),elf) -sysdep-dl-routines += dl-static -sysdep_routines += $(sysdep-dl-routines) -sysdep-rtld-routines += $(sysdep-dl-routines) -endif - ifeq ($(subdir),rt) librt-routines += rt-sysdep endif diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index 4302bd3..37c56a3 100644 --- a/sysdeps/unix/sysv/linux/Makefile +++ b/sysdeps/unix/sysv/linux/Makefile @@ -147,7 +147,9 @@ sysdep_routines += xstatconv internal_statvfs internal_statvfs64 \ endif ifeq ($(subdir),elf) -sysdep-rtld-routines += dl-brk dl-sbrk +sysdep-dl-routines += dl-static +sysdep_routines += dl-static +sysdep-rtld-routines += dl-brk dl-sbrk dl-static CPPFLAGS-lddlibc4 += -DNOT_IN_libc endif diff --git a/sysdeps/unix/sysv/linux/ia64/dl-static.c b/sysdeps/unix/sysv/linux/ia64/dl-static.c deleted file mode 100644 index 4efc077..0000000 --- a/sysdeps/unix/sysv/linux/ia64/dl-static.c +++ /dev/null @@ -1,69 +0,0 @@ -/* Variable initialization. IA-64 version. - Copyright (C) 2001, 2002, 2003, 2004 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include - -#ifdef SHARED - -void -_dl_var_init (void *array[]) -{ - /* It has to match "variables" below. */ - enum - { - DL_PAGESIZE = 0, - DL_CLKTCK - }; - - GLRO(dl_pagesize) = *((size_t *) array[DL_PAGESIZE]); - GLRO(dl_clktck) = *((int *) array[DL_CLKTCK]); -} - -#else -#include - -__libc_lock_define_initialized_recursive (static, _dl_static_lock) - -static void *variables[] = -{ - &GLRO(dl_pagesize), - &GLRO(dl_clktck) -}; - -void -_dl_static_init (struct link_map *map) -{ - const ElfW(Sym) *ref = NULL; - lookup_t loadbase; - void (*f) (void *[]); - - __libc_lock_lock_recursive (_dl_static_lock); - - loadbase = _dl_lookup_symbol_x ("_dl_var_init", map, &ref, - map->l_local_scope, NULL, 0, 1, NULL); - if (ref != NULL) - { - f = (void (*) (void *[])) DL_SYMBOL_ADDRESS (loadbase, ref); - f (variables); - } - - __libc_lock_unlock_recursive (_dl_static_lock); -} - -#endif diff --git a/sysdeps/unix/sysv/linux/dl-static.c b/sysdeps/unix/sysv/linux/dl-static.c new file mode 100644 index 0000000..fa70811 --- /dev/null +++ b/sysdeps/unix/sysv/linux/dl-static.c @@ -0,0 +1,69 @@ +/* Variable initialization. + Copyright (C) 2001, 2002, 2003, 2004, 2010 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#ifdef SHARED + +void +_dl_var_init (void *array[]) +{ + /* It has to match "variables" below. */ + enum + { + DL_PAGESIZE = 0, + DL_CLKTCK + }; + + GLRO(dl_pagesize) = *((size_t *) array[DL_PAGESIZE]); + GLRO(dl_clktck) = *((int *) array[DL_CLKTCK]); +} + +#else +#include + +__libc_lock_define_initialized_recursive (static, _dl_static_lock) + +static void *variables[] = +{ + &GLRO(dl_pagesize), + &GLRO(dl_clktck) +}; + +void +_dl_static_init (struct link_map *map) +{ + const ElfW(Sym) *ref = NULL; + lookup_t loadbase; + void (*f) (void *[]); + + __libc_lock_lock_recursive (_dl_static_lock); + + loadbase = _dl_lookup_symbol_x ("_dl_var_init", map, &ref, + map->l_local_scope, NULL, 0, 1, NULL); + if (ref != NULL) + { + f = (void (*) (void *[])) DL_SYMBOL_ADDRESS (loadbase, ref); + f (variables); + } + + __libc_lock_unlock_recursive (_dl_static_lock); +} + +#endif diff --git a/sysdeps/unix/sysv/linux/ia64/ldsodefs.h b/sysdeps/unix/sysv/linux/ia64/ldsodefs.h deleted file mode 100644 index 31af624..0000000 --- a/sysdeps/unix/sysv/linux/ia64/ldsodefs.h +++ /dev/null @@ -1,33 +0,0 @@ -/* Run-time dynamic linker data structures for loaded ELF shared objects. IA64. - Copyright (C) 2001 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#ifndef _LDSODEFS_H - -/* Get the real definitions. */ -#include_next - -/* Now define our stuff. */ - -/* We need special support to initialize DSO loaded for statically linked - binaries. */ -extern void _dl_static_init (struct link_map *map); -#undef DL_STATIC_INIT -#define DL_STATIC_INIT(map) _dl_static_init (map) - -#endif /* ldsodefs.h */ diff --git a/sysdeps/unix/sysv/linux/ldsodefs.h b/sysdeps/unix/sysv/linux/ldsodefs.h index 5d5b1b4..ecb5d4f 100644 --- a/sysdeps/unix/sysv/linux/ldsodefs.h +++ b/sysdeps/unix/sysv/linux/ldsodefs.h @@ -36,6 +36,12 @@ extern void _dl_aux_init (ElfW(auxv_t) *av) internal_function; /* Initialization which is normally done by the dynamic linker. */ extern void _dl_non_dynamic_init (void) internal_function; +/* We need special support to initialize DSO loaded for statically linked + binaries. */ +extern void _dl_static_init (struct link_map *map); +#undef DL_STATIC_INIT +#define DL_STATIC_INIT(map) _dl_static_init (map) + /* We can assume that the kernel always provides the AT_UID, AT_EUID, AT_GID, and AT_EGID values in the auxiliary vector from 2.4.0 or so on. */ #if __ASSUME_AT_XID diff --git a/sysdeps/unix/sysv/linux/ia64/getpagesize.c b/sysdeps/unix/sysv/linux/ia64/getpagesize.c deleted file mode 100644 index 1155dfd..0000000 --- a/sysdeps/unix/sysv/linux/ia64/getpagesize.c +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright (C) 1999, 2000, 2001, 2002, 2004 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include -#include -#include - -#include -#include -#include - -/* Return the system page size. The return value will depend on how - the kernel is configured. A program must use this call to - determine the page size to ensure proper alignment for calls such - as mmap and friends. --davidm 99/11/30 */ - -int -__getpagesize () -{ - assert (GLRO(dl_pagesize) != 0); - return GLRO(dl_pagesize); -} -libc_hidden_def (__getpagesize) -weak_alias (__getpagesize, getpagesize)