From a8874eadae699b5d4583aab3a860e06ecfcf5e5a Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Mon, 12 Aug 1996 02:44:03 +0000 Subject: Last minute change. Mon Aug 12 04:33:09 1996 Ulrich Drepper * nss/nsswitch.c (__nss_database_lookup): Always release locks before returning. Reported by Miles Bader. (distributes): Add databases.def. --- ChangeLog | 10 ++-- Makerules | 4 +- autolock.sh | 45 ++++++++++++++++++ config.make.in | 1 + configure.in | 2 + nss.h | 1 + nss/Makefile | 5 +- nss/XXX-lookup.c | 11 +++-- nss/databases.def | 31 ++++++++++++ nss/nss.h | 54 +++++++++++++++++++++ nss/nsswitch.c | 116 +++++++++++++++++++++++++++++++++------------ nss/nsswitch.h | 15 +----- string/Makefile | 2 + sysdeps/alpha/divrem.h | 4 +- sysdeps/alpha/dl-machine.h | 28 +++++------ sysdeps/generic/sbrk.c | 21 +++++--- 16 files changed, 271 insertions(+), 79 deletions(-) create mode 100755 autolock.sh create mode 100644 nss.h create mode 100644 nss/databases.def create mode 100644 nss/nss.h diff --git a/ChangeLog b/ChangeLog index ac5bb966b6..c563e74df9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Mon Aug 12 04:33:09 1996 Ulrich Drepper + + * nss/nsswitch.c (__nss_database_lookup): Always release locks + before returning. Reported by Miles Bader. + Mon Aug 12 03:31:58 1996 Ulrich Drepper * nss/nsswitch.c (__nss_configure_lookup): New function. @@ -11,7 +16,7 @@ Mon Aug 12 03:31:58 1996 Ulrich Drepper * nss.h: New file. Wrapper around nss/nss.h. * nss/Makefile (headers): Add nss.h. - (distributes): Add databases.h. + (distributes): Add databases.def. Sun Aug 11 16:19:42 1996 Ulrich Drepper @@ -27,9 +32,6 @@ Sun Aug 11 16:19:42 1996 Ulrich Drepper * string/Makefile: Add -fno-builtin for tst-strlen.c, too. - * elf/dl-lookup.c (_dl_lookup_symbol): Allow self-referencing. - Patch by David Mosberger-Tang. - Sun Aug 11 01:12:38 1996 Richard Henderson * sysdeps/alpha/dl-machine.h (elf_alpha_fix_plt): Optimize LD_BIND_NOW diff --git a/Makerules b/Makerules index f2d190a57a..4248dad91c 100644 --- a/Makerules +++ b/Makerules @@ -455,8 +455,8 @@ object-suffixes-left := $(object-suffixes) include $(o-iterator) define do-ar $(patsubst %,cd %;,$(objdir)) \ -$(AR) cru$(verbose) ${O%-lib} \ - $(patsubst $(objpfx)%,%,$^) +$(AUTOLOCK) ${O%-lib}.lck $(AR) cru$(verbose) ${O%-lib} \ + $(patsubst $(objpfx)%,%,$^) rm -f $@ touch $@ endef diff --git a/autolock.sh b/autolock.sh new file mode 100755 index 0000000000..88e27332e6 --- /dev/null +++ b/autolock.sh @@ -0,0 +1,45 @@ +#! /bin/sh +# interlock - wrap program invocation in lock to allow +# parallel builds to work. +# Written by Tom Tromey , Aug 10 1996 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Usage: +# interlock lock-dir-name program args-to-program... + +dirname="$1" +program="$2" + +shift +shift + +while (mkdir $dirname > /dev/null 2>&1 && exit 1 || exit 0); do + # Wait a bit. + sleep 1 +done + +# Race condition here: if interrupted after the loop but before this +# trap, the lock can be left around. +trap "rmdir $dirname > /dev/null 2>&1" 1 2 3 15 + +# We have the lock, so run the program. +$program ${1+"$@"} +ret=$? + +# Release the lock. +rmdir $dirname > /dev/null 2>&1 + +exit $ret diff --git a/config.make.in b/config.make.in index b099199c36..a496e29f0d 100644 --- a/config.make.in +++ b/config.make.in @@ -34,6 +34,7 @@ CC = @CC@ BUILD_CC = @BUILD_CC@ CFLAGS = @CFLAGS@ AR = @AR@ +AUTOLOCK = @AUTOLOCK@ RANLIB = @RANLIB@ AS = $(CC) -c diff --git a/configure.in b/configure.in index 631a035e92..aebc785904 100644 --- a/configure.in +++ b/configure.in @@ -308,6 +308,8 @@ fi AC_PROG_CPP AC_CHECK_TOOL(AR, ar) AC_CHECK_TOOL(RANLIB, ranlib, :) +AUTOLOCK="`(cd $srcdir; pwd)`/autolock.sh" +AC_SUBST(AUTOLOCK) AC_CACHE_CHECK(for signed size_t type, libc_cv_signed_size_t, [dnl echo '#include diff --git a/nss.h b/nss.h new file mode 100644 index 0000000000..0541335c18 --- /dev/null +++ b/nss.h @@ -0,0 +1 @@ +#include diff --git a/nss/Makefile b/nss/Makefile index f23f5f3fbb..5dcae4d40e 100644 --- a/nss/Makefile +++ b/nss/Makefile @@ -21,13 +21,16 @@ # subdir := nss +headers := nss.h distribute := nsswitch.h XXX-lookup.c getXXbyYY.c getXXbyYY_r.c \ - getXXent.c getXXent_r.c + getXXent.c getXXent_r.c databases.def # This is the trivial part which goes into libc itself. routines = nsswitch $(addsuffix -lookup,$(databases)) # These are the databases that go through nss dispatch. +# Caution: if you add a database here, you must add its real name +# in databases.def, too. databases = proto service hosts network grp pwd rpc ethers \ spwd diff --git a/nss/XXX-lookup.c b/nss/XXX-lookup.c index 4a2d25cb42..1b43018d47 100644 --- a/nss/XXX-lookup.c +++ b/nss/XXX-lookup.c @@ -35,25 +35,26 @@ Boston, MA 02111-1307, USA. */ #define CONCAT3_1(Pre, Name, Post) CONCAT3_2 (Pre, Name, Post) #define CONCAT3_2(Pre, Name, Post) Pre##Name##Post +#define DATABASE_NAME_SYMBOL CONCAT3_1 (__nss_, DATABASE_NAME, _database) #define DATABASE_NAME_STRING STRINGIFY1 (DATABASE_NAME) #define STRINGIFY1(Name) STRINGIFY2 (Name) #define STRINGIFY2(Name) #Name #ifndef DEFAULT_CONFIG -#define DEFAULT_CONFIG 0 +#define DEFAULT_CONFIG NULL #endif -static service_user *database = NULL; +service_user *DATABASE_NAME_SYMBOL = NULL; int DB_LOOKUP_FCT (service_user **ni, const char *fct_name, void **fctp) { - if (database == NULL + if (DATABASE_NAME_SYMBOL == NULL && __nss_database_lookup (DATABASE_NAME_STRING, DEFAULT_CONFIG, - &database) < 0) + &DATABASE_NAME_SYMBOL) < 0) return -1; - *ni = database; + *ni = DATABASE_NAME_SYMBOL; return __nss_lookup (ni, fct_name, fctp); } diff --git a/nss/databases.def b/nss/databases.def new file mode 100644 index 0000000000..98772bac76 --- /dev/null +++ b/nss/databases.def @@ -0,0 +1,31 @@ +/* List of all databases defined for the NSS in GNU C Library. +Copyright (C) 1996 Free Software Foundation, Inc. +This file is part of the GNU C Library. +Contributed by Ulrich Drepper , 1996. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* This list must be kept sorted!!! */ + +DEFINE_DATABASE (ethers) +DEFINE_DATABASE (group) +DEFINE_DATABASE (hosts) +DEFINE_DATABASE (networks) +DEFINE_DATABASE (passwd) +DEFINE_DATABASE (protocols) +DEFINE_DATABASE (rpc) +DEFINE_DATABASE (services) +DEFINE_DATABASE (shadow) diff --git a/nss/nss.h b/nss/nss.h new file mode 100644 index 0000000000..e9acb93bcc --- /dev/null +++ b/nss/nss.h @@ -0,0 +1,54 @@ +/* Copyright (C) 1996 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 Library General Public License as +published by the Free Software Foundation; either version 2 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* Define interface to NSS. This is meant for the interface functions + and for implementors of new services. */ + +#ifndef _NSS_H + +#define _NSS_H 1 +#include + +/* Revision number of NSS interface (must be a string). */ +#define NSS_SHLIB_REVISION ".1" + + +__BEGIN_DECLS + +/* Possible results of lookup using a nss_* function. */ +enum nss_status +{ + NSS_STATUS_TRYAGAIN = -2, + NSS_STATUS_UNAVAIL, + NSS_STATUS_NOTFOUND, + NSS_STATUS_SUCCESS, +}; + + +/* Overwrite service selection for database DBNAME using specification + in STRING. + This function should only be used by system programs which have to + work around non-existing services (e.e., while booting). + Attention: Using this function repeatedly will slowly eat up the + whole memory since previous selection data cannot be freed. */ +extern int __nss_configure_lookup __P ((__const char *__dbname, + __const char *__string)); + +__END_DECLS + +#endif /* nss.h */ diff --git a/nss/nsswitch.c b/nss/nsswitch.c index 1349e0ca08..0a4c9482d2 100644 --- a/nss/nsswitch.c +++ b/nss/nsswitch.c @@ -19,6 +19,7 @@ Boston, MA 02111-1307, USA. */ #include #include +#include #include #include #include @@ -30,7 +31,6 @@ Boston, MA 02111-1307, USA. */ #include "../elf/link.h" /* We need some help from ld.so. */ /* Prototypes for the local functions. */ -static void nss_init (void); static void *nss_lookup_function (service_user *ni, const char *fct_name); static name_database *nss_parse_file (const char *fname); static name_database_entry *nss_getline (char *line); @@ -39,6 +39,27 @@ static service_library *nss_new_service (name_database *database, const char *name); +/* Declare external database variables. */ +#define DEFINE_DATABASE(name) \ + extern service_user *__nss_##name##_database; \ + weak_extern (__nss_##name##_database) +#include "databases.def" +#undef DEFINE_DATABASE + +/* Structure to map database name to variable. */ +static struct +{ + const char *name; + service_user **dbp; +} databases[] = +{ +#define DEFINE_DATABASE(name) \ + { #name, &__nss_##name##_database }, +#include "databases.def" +#undef DEFINE_DATABASE +}; + + __libc_lock_define_initialized (static, lock) @@ -50,35 +71,29 @@ static int nss_initialized; static name_database *service_table; -static void -nss_init (void) -{ - /* Prevent multiple threads to change the service table. */ - __libc_lock_lock (lock); - - if (service_table == NULL) - service_table = nss_parse_file (_PATH_NSSWITCH_CONF); - - __libc_lock_unlock (lock); -} - - /* -1 == database not found 0 == database entry pointer stored */ int __nss_database_lookup (const char *database, const char *defconfig, service_user **ni) { - name_database_entry *entry; + /* Prevent multiple threads to change the service table. */ + __libc_lock_lock (lock); - if (nss_initialized == 0) - nss_init (); + /* Reconsider database variable in case some other thread called + `__nss_configure_lookup' while we waited for the lock. */ + if (*ni != NULL) + return 0; + + if (nss_initialized == 0 && service_table == NULL) + /* Read config file. */ + service_table = nss_parse_file (_PATH_NSSWITCH_CONF); /* Test whether configuration data is available. */ - if (service_table) + if (service_table != NULL) { - /* Return first `service_user' entry for DATABASE. - XXX Will use perfect hashing function for known databases. */ + /* Return first `service_user' entry for DATABASE. */ + name_database_entry *entry; /* XXX Could use some faster mechanism here. But each database is only requested once and so this might not be critical. */ @@ -91,17 +106,14 @@ __nss_database_lookup (const char *database, const char *defconfig, } /* No configuration data is available, either because nsswitch.conf - doesn't exist or because it doesn't have a line for this database. */ - entry = malloc (sizeof *entry); - if (entry == NULL) - return -1; - entry->name = database; - /* DEFCONFIG specifies the default service list for this database, + doesn't exist or because it doesn't has a line for this database. + + DEFCONFIG specifies the default service list for this database, or null to use the most common default. */ - entry->service = nss_parse_service_list (defconfig ?: - "compat [NOTFOUND=return] files"); + *ni = nss_parse_service_list (defconfig ?: "compat [NOTFOUND=return] files"); + + __libc_lock_unlock (lock); - *ni = entry->service; return 0; } @@ -168,6 +180,48 @@ __nss_next (service_user **ni, const char *fct_name, void **fctp, int status, } +int +__nss_configure_lookup (const char *dbname, const char *service_line) +{ + service_user *new_db; + size_t cnt; + + for (cnt = 0; cnt < sizeof databases; ++cnt) + if (strcmp (dbname, databases[cnt].name) == 0) + break; + + if (cnt == sizeof databases) + { + errno = EINVAL; + return -1; + } + + /* Test whether it is really used. */ + if (databases[cnt].dbp == NULL) + /* Nothing to do, but we could do. */ + return 0; + + /* Try to generate new data. */ + new_db = nss_parse_service_list (service_line); + if (new_db == NULL) + { + /* Illegal service specification. */ + errno = EINVAL; + return -1; + } + + /* Prevent multiple threads to change the service table. */ + __libc_lock_lock (lock); + + /* Install new rules. */ + *databases[cnt].dbp = new_db; + + __libc_lock_unlock (lock); + + return 0; +} + + static int nss_dlerror_run (void (*operate) (void)) { @@ -385,7 +439,9 @@ nss_parse_file (const char *fname) } -/* Read the source names: ` ( "[" "=" "]" )*'. */ +/* Read the source names: + `( ( "[" "!"? ( "=" )+ "]" )? )*' + */ static service_user * nss_parse_service_list (const char *line) { diff --git a/nss/nsswitch.h b/nss/nsswitch.h index c4d4d11193..0c99f147fd 100644 --- a/nss/nsswitch.h +++ b/nss/nsswitch.h @@ -23,24 +23,11 @@ Boston, MA 02111-1307, USA. */ #include #include +#include #include #include -/* Revision number of NSS interface (must be a string). */ -#define NSS_SHLIB_REVISION ".1" - - -/* Possible results of lookup using a nss_* function. */ -enum nss_status -{ - NSS_STATUS_TRYAGAIN = -2, - NSS_STATUS_UNAVAIL, - NSS_STATUS_NOTFOUND, - NSS_STATUS_SUCCESS, -}; - - /* Actions performed after lookup finished. */ typedef enum { diff --git a/string/Makefile b/string/Makefile index f67e7247d4..c120b7da2c 100644 --- a/string/Makefile +++ b/string/Makefile @@ -45,3 +45,5 @@ distribute := memcopy.h pagecopy.h include ../Rules tester-ENV = LANGUAGE=C +CFLAGS-tester.c = -fno-builtin +CFLAGS-tst-strlen.c = -fno-builtin diff --git a/sysdeps/alpha/divrem.h b/sysdeps/alpha/divrem.h index b5b66ae10b..eaf892b3c6 100644 --- a/sysdeps/alpha/divrem.h +++ b/sysdeps/alpha/divrem.h @@ -29,8 +29,8 @@ division. The C compiler expects the functions These are not normal C functions: instead of the normal calling sequence, these expect their arguments in registers t10 and t11, and -return the result in t12 (aka pv). Registers AT and v0 may be -clobbered (assembly temporary), anything else must be saved. */ +return the result in t12 (aka pv). Register AT may be clobbered +(assembly temporary), anything else must be saved. */ #include diff --git a/sysdeps/alpha/dl-machine.h b/sysdeps/alpha/dl-machine.h index b900b769ee..a75011fccb 100644 --- a/sysdeps/alpha/dl-machine.h +++ b/sysdeps/alpha/dl-machine.h @@ -135,8 +135,8 @@ _dl_runtime_resolve: stq $29, 160($sp) .mask 0x27ff01ff, -168 /* Set up our $gp */ - br $gp, .+4 - ldgp $gp, 0($gp) + br $gp, 0f +0: ldgp $gp, 0($gp) .prologue 1 /* Set up the arguments for _dl_runtime_resolve. */ /* $16 = link_map out of plt0 */ @@ -145,7 +145,7 @@ _dl_runtime_resolve: mov $28, $17 /* Do the fixup */ bsr $26, fixup..ng - /* Move the destination address to a safe place. */ + /* Move the destination address into position. */ mov $0, $27 /* Restore program registers. */ ldq $26, 0($sp) @@ -169,19 +169,16 @@ _dl_runtime_resolve: ldq $24, 144($sp) ldq $25, 152($sp) ldq $29, 160($sp) + /* Flush the Icache after having modified the .plt code. */ + imb /* Clean up and turn control to the destination */ lda $sp, 168($sp) jmp $31, ($27) .end _dl_runtime_resolve"); -/* The PLT uses Elf_Rel relocs. */ +/* The PLT uses Elf64_Rela relocs. */ #define elf_machine_relplt elf_machine_rela -/* Mask identifying addresses reserved for the user program, - where the dynamic linker should not map anything. */ -/* FIXME */ -#define ELF_MACHINE_USER_ADDRESS_MASK (~0x1FFFFFFFFUL) - /* Initial entry point code for the dynamic linker. The C function `_dl_start' is the real entry point; its return value is the user program's entry point. */ @@ -191,8 +188,8 @@ _dl_runtime_resolve: .globl _start .globl _dl_start_user _start: - br $gp,.+4 - ldgp $gp, 0($gp) + br $gp,0f +0: ldgp $gp, 0($gp) /* Pass pointer to argument block to _dl_start. */ mov $sp, $16 bsr $26, _dl_start..ng @@ -226,7 +223,7 @@ _dl_start_user: mov $9, $27 jmp ($9)"); -/* Nonzero iff TYPE describes relocation of a PLT entry, so +/* Nonzero iff TYPE describes relocation of a PLT entry, so PLT entries should not be allowed to define the value. */ #define elf_machine_pltrel_p(type) ((type) == R_ALPHA_JMP_SLOT) @@ -302,9 +299,10 @@ elf_alpha_fix_plt(struct link_map *l, plte[2] = 0x6bfb0000; } - /* Flush the instruction cache now that we've diddled. Tag it as - modifying memory to checkpoint memory writes during optimization. */ - asm volatile("call_pal 0x86" : : : "memory"); + /* At this point, if we've been doing runtime resolution, Icache is dirty. + This will be taken care of in _dl_runtime_resolve. If instead we are + doing this as part of non-lazy startup relocation, that bit of code + hasn't made it into Icache yet, so there's nothing to clean up. */ } /* Perform the relocation specified by RELOC and SYM (which is fully resolved). diff --git a/sysdeps/generic/sbrk.c b/sysdeps/generic/sbrk.c index 698f814e2b..92ad8c4102 100644 --- a/sysdeps/generic/sbrk.c +++ b/sysdeps/generic/sbrk.c @@ -22,6 +22,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ extern void *__curbrk; extern int __brk (void *addr); +#ifdef PIC +extern int __libc_is_static; +weak_extern (__libc_is_static) +#endif + /* Extend the process's data space by INCREMENT. If INCREMENT is negative, shrink data space by - INCREMENT. Return start of new space allocated, or -1 for errors. */ @@ -30,12 +35,16 @@ __sbrk (ptrdiff_t increment) { void *oldbrk; - /* Always update __curbrk from the kernel's brk value. That way two - separate instances of __brk and __sbrk can share the heap, returning - interleaved pieces of it. This happens when libc.so is loaded by - dlopen in a statically-linked program that already uses __brk. */ - if (__brk (0) < 0) - return (void *) -1; + /* If this is not part of the dynamic library or the library is used + via dynamic loading in a statically linked program update + __curbrk from the kernel's brk value. That way two separate + instances of __brk and __sbrk can share the heap, returning + interleaved pieces of it. */ +#ifdef PIC + if (__curbrk == NULL || &__libc_is_static == NULL) +#endif + if (__brk (0) < 0) + return (void *) -1; if (increment == 0) return __curbrk; -- cgit v1.2.3