From b3fc5f84d13573b9494fb1f0db9b5e80679e5098 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Mon, 28 Jun 1999 15:52:36 +0000 Subject: [PATCH] Update. * sysdeps/libm-ieee754/e_gamma_r.c: Initialize *signgamp for NaN returns. * sysdeps/libm-ieee754/e_gammaf_r.c: Likewise. * sysdeps/libm-ieee754/e_gammal_r.c: Likewise. Reported by John Reiser [PR libc/1185]. * elf/dl-dst.h: Fix typo. * elf/dl-open.c: Likewise. 1999-06-26 Zack Weinberg * elf/dl-libc.c: New file, provides three functions: __libc_dlopen, __libc_dlclose, __libc_dlsym. * include/dlfcn.h: Prototype them. Prototype _dl_addr. * elf/Makefile (routines): Add dl-libc.c. * elf/dl-profstub.c (_dl_mcount_wrapper): Change type of argument to void *. * elf/ldsodefs.h: Change proto and use of _dl_mcount_wrapper to match. * iconv/gconv.c: Include dlfcn.h. * iconv/gconv_db.c: Likewise. * malloc/mtrace.c: Likewise. Don't include ldsodefs.h. * iconv/gconv_int.h (struct __gconv_loaded_object): Change `handle' to a void *. (__gconv_find_func): Delete prototype. * iconv/gconv_dl.c: Don't include ldsodefs.h. Remove dlerror_run and related functions and structs. Use __libc_dlopen, __libc_dlsym, __libc_dlclose. * nss/nsswitch.c: Likewise. 1999-06-28 Ulrich Drepper --- ChangeLog | 34 +++++++++++ elf/Makefile | 2 +- elf/dl-dst.h | 2 +- elf/dl-libc.c | 122 ++++++++++++++++++++++++++++++++++++++ elf/dl-open.c | 2 +- elf/dl-profstub.c | 5 +- elf/ldsodefs.h | 4 +- iconv/gconv.c | 2 +- iconv/gconv_db.c | 1 + iconv/gconv_dl.c | 93 +++-------------------------- iconv/gconv_int.h | 6 +- include/dlfcn.h | 7 +++ malloc/mtrace.c | 2 +- nss/nsswitch.c | 77 +++--------------------- sysdeps/libm-ieee754/e_gamma_r.c | 10 +++- sysdeps/libm-ieee754/e_gammaf_r.c | 10 +++- sysdeps/libm-ieee754/e_gammal_r.c | 10 +++- 17 files changed, 214 insertions(+), 175 deletions(-) create mode 100644 elf/dl-libc.c diff --git a/ChangeLog b/ChangeLog index 2c8874b..48bc56b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,39 @@ 1999-06-28 Ulrich Drepper + * sysdeps/libm-ieee754/e_gamma_r.c: Initialize *signgamp for NaN + returns. + * sysdeps/libm-ieee754/e_gammaf_r.c: Likewise. + * sysdeps/libm-ieee754/e_gammal_r.c: Likewise. + Reported by John Reiser [PR libc/1185]. + + * elf/dl-dst.h: Fix typo. + * elf/dl-open.c: Likewise. + +1999-06-26 Zack Weinberg + + * elf/dl-libc.c: New file, provides three functions: + __libc_dlopen, __libc_dlclose, __libc_dlsym. + * include/dlfcn.h: Prototype them. Prototype _dl_addr. + * elf/Makefile (routines): Add dl-libc.c. + * elf/dl-profstub.c (_dl_mcount_wrapper): Change type of + argument to void *. + * elf/ldsodefs.h: Change proto and use of _dl_mcount_wrapper to match. + + * iconv/gconv.c: Include dlfcn.h. + * iconv/gconv_db.c: Likewise. + * malloc/mtrace.c: Likewise. Don't include ldsodefs.h. + + * iconv/gconv_int.h (struct __gconv_loaded_object): Change + `handle' to a void *. + (__gconv_find_func): Delete prototype. + + * iconv/gconv_dl.c: Don't include ldsodefs.h. Remove + dlerror_run and related functions and structs. Use + __libc_dlopen, __libc_dlsym, __libc_dlclose. + * nss/nsswitch.c: Likewise. + +1999-06-28 Ulrich Drepper + * sysdeps/unix/sysv/linux/gethostid.c: Test for gethostbyname_r function correctly. diff --git a/elf/Makefile b/elf/Makefile index 6c52643..b5145ea 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -22,7 +22,7 @@ subdir := elf headers = elf.h bits/elfclass.h bits/dlfcn.h link.h dlfcn.h routines = $(dl-routines) dl-open dl-close dl-symbol dl-support \ - dl-addr enbl-secure dl-profstub dl-origin + dl-addr enbl-secure dl-profstub dl-origin dl-libc # The core dynamic linking functions are in libc for the static and # profiled libraries. diff --git a/elf/dl-dst.h b/elf/dl-dst.h index 4b014d6..ca32e25 100644 --- a/elf/dl-dst.h +++ b/elf/dl-dst.h @@ -33,7 +33,7 @@ extern size_t _dl_dst_count (const char *name, int is_path); -/* Guess from the number of DSTs the length of the restul string. */ +/* Guess from the number of DSTs the length of the result string. */ #define DL_DST_REQUIRED(l, name, len, cnt) \ ({ \ size_t origin_len; \ diff --git a/elf/dl-libc.c b/elf/dl-libc.c new file mode 100644 index 0000000..afb3f2d --- /dev/null +++ b/elf/dl-libc.c @@ -0,0 +1,122 @@ +/* Handle loading and unloading shared objects for internal libc purposes. + Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Zack Weinberg , 1999. + + 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. */ + +#include +#include +#include + +/* The purpose of this file is to provide wrappers around the dynamic + linker error mechanism (similar to dlopen() et al in libdl) which + are usable from within libc. Generally we want to throw away the + string that dlerror() would return and just pass back a null pointer + for errors. This also lets the rest of libc not know about the error + handling mechanism. + + Much of this code came from gconv_dl.c with slight modifications. */ + +static int +internal_function +dlerror_run (void (*operate) (void *), void *args) +{ + char *last_errstring = NULL; + int result; + + (void) _dl_catch_error (&last_errstring, operate, args); + + result = last_errstring != NULL; + if (result) + free (last_errstring); + + return result; +} + +/* These functions are called by dlerror_run... */ + +struct do_dlopen_args +{ + /* Argument to do_dlopen. */ + const char *name; + + /* Return from do_dlopen. */ + struct link_map *map; +}; + +struct do_dlsym_args +{ + /* Arguments to do_dlsym. */ + struct link_map *map; + const char *name; + + /* Return values of do_dlsym. */ + ElfW(Addr) loadbase; + const ElfW(Sym) *ref; +}; + +static void +do_dlopen (void *ptr) +{ + struct do_dlopen_args *args = (struct do_dlopen_args *) ptr; + /* Open and relocate the shared object. */ + args->map = _dl_open (args->name, RTLD_LAZY, NULL); +} + +static void +do_dlsym (void *ptr) +{ + struct do_dlsym_args *args = (struct do_dlsym_args *) ptr; + args->ref = NULL; + args->loadbase = _dl_lookup_symbol (args->name, &args->ref, + args->map->l_local_scope, + args->map->l_name, 0); +} + +static void +do_dlclose (void *ptr) +{ + _dl_close ((struct link_map *) ptr); +} + +/* ... and these functions call dlerror_run. */ + +void * +__libc_dlopen (const char *__name) +{ + struct do_dlopen_args args; + args.name = __name; + + return (dlerror_run (do_dlopen, &args) ? NULL : (void *) args.map); +} + +void * +__libc_dlsym (void *__map, const char *__name) +{ + struct do_dlsym_args args; + args.map = __map; + args.name = __name; + + return (dlerror_run (do_dlsym, &args) ? NULL + : (void *) (args.loadbase + args.ref->st_value)); +} + +int +__libc_dlclose (void *__map) +{ + return dlerror_run (do_dlclose, __map); +} diff --git a/elf/dl-open.c b/elf/dl-open.c index 149badd..a9d81c7 100644 --- a/elf/dl-open.c +++ b/elf/dl-open.c @@ -127,7 +127,7 @@ dl_open_worker (void *a) /* If the substitution failed don't try to load. */ if (*new_file == '\0') _dl_signal_error (0, "dlopen", - "empty dynamics string token substitution"); + "empty dynamic string token substitution"); /* Now we have a new file name. */ file = new_file; diff --git a/elf/dl-profstub.c b/elf/dl-profstub.c index 10db640..55304a7 100644 --- a/elf/dl-profstub.c +++ b/elf/dl-profstub.c @@ -28,9 +28,10 @@ extern struct link_map *_dl_profile_map; void -_dl_mcount_wrapper (ElfW(Addr) selfpc) +_dl_mcount_wrapper (void *selfpc) { - _dl_mcount ((ElfW(Addr)) __builtin_return_address (0), selfpc); + _dl_mcount ((ElfW(Addr)) __builtin_return_address (0), + (ElfW(Addr)) selfpc); } diff --git a/elf/ldsodefs.h b/elf/ldsodefs.h index f8db76c..bd33ba1 100644 --- a/elf/ldsodefs.h +++ b/elf/ldsodefs.h @@ -407,7 +407,7 @@ extern void _dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc); /* This function is simply a wrapper around the _dl_mcount function which does not require a FROMPC parameter since this is the calling function. */ -extern void _dl_mcount_wrapper (ElfW(Addr) selfpc); +extern void _dl_mcount_wrapper (void *selfpc); /* Show the members of the auxiliary array passed up from the kernel. */ @@ -432,7 +432,7 @@ extern const struct r_strlenpair *_dl_important_hwcaps (const char *platform, helps do it. */ #define _CALL_DL_FCT(fctp, args) \ ({ if (_dl_profile_map != NULL) \ - _dl_mcount_wrapper ((ElfW(Addr)) fctp); \ + _dl_mcount_wrapper (fctp); \ (*fctp) args; \ }) diff --git a/iconv/gconv.c b/iconv/gconv.c index 828db9d..3120f00 100644 --- a/iconv/gconv.c +++ b/iconv/gconv.c @@ -22,7 +22,7 @@ #include #include #include - +#include #include int diff --git a/iconv/gconv_db.c b/iconv/gconv_db.c index 727be41..3929299 100644 --- a/iconv/gconv_db.c +++ b/iconv/gconv_db.c @@ -25,6 +25,7 @@ #include #include +#include #include #include diff --git a/iconv/gconv_dl.c b/iconv/gconv_dl.c index dc90986..7d327ed 100644 --- a/iconv/gconv_dl.c +++ b/iconv/gconv_dl.c @@ -26,10 +26,8 @@ #include #include -#include #include - /* This is a tuning parameter. If a transformation module is not used anymore it gets not immediately unloaded. Instead we wait a certain number of load attempts for further modules. If none of the @@ -39,13 +37,10 @@ before unloading. */ #define TRIES_BEFORE_UNLOAD 2 - /* Array of loaded objects. This is shared by all threads so we have to use semaphores to access it. */ static void *loaded; - - /* Comparison function for searching `loaded_object' tree. */ static int known_compare (const void *p1, const void *p2) @@ -58,70 +53,6 @@ known_compare (const void *p1, const void *p2) return (intptr_t) s1->handle - (intptr_t) s2->handle; } - -static void -do_open (void *a) -{ - struct __gconv_loaded_object *args = (struct __gconv_loaded_object *) a; - /* Open and relocate the shared object. */ - args->handle = _dl_open (args->name, RTLD_LAZY, NULL); -} - - -static int -internal_function -dlerror_run (void (*operate) (void *), void *args) -{ - char *last_errstring = NULL; - int result; - - (void) _dl_catch_error (&last_errstring, operate, args); - - result = last_errstring != NULL; - if (result) - free (last_errstring); - - return result; -} - - -struct get_sym_args -{ - /* Arguments to get_sym. */ - struct link_map *map; - const char *name; - - /* Return values of get_sym. */ - ElfW(Addr) loadbase; - const ElfW(Sym) *ref; -}; - -static void -get_sym (void *a) -{ - struct get_sym_args *args = (struct get_sym_args *) a; - args->ref = NULL; - args->loadbase = _dl_lookup_symbol (args->name, &args->ref, - args->map->l_local_scope, - args->map->l_name, 0); -} - - -void * -internal_function -__gconv_find_func (void *handle, const char *name) -{ - struct get_sym_args args; - - args.map = handle; - args.name = name; - - return (dlerror_run (get_sym, &args) ? NULL - : (void *) (args.loadbase + args.ref->st_value)); -} - - - /* Open the gconv database if necessary. A non-negative return value means success. */ struct __gconv_loaded_object * @@ -170,9 +101,10 @@ __gconv_find_shlib (const char *name) { if (found->counter < -TRIES_BEFORE_UNLOAD) { - if (dlerror_run (do_open, found) == 0) + found->handle = __libc_dlopen (found->name); + if (found->handle != NULL) { - found->fct = __gconv_find_func (found->handle, "gconv"); + found->fct = __libc_dlsym (found->handle, "gconv"); if (found->fct == NULL) { /* Argh, no conversion function. There is something @@ -182,10 +114,8 @@ __gconv_find_shlib (const char *name) } else { - found->init_fct = __gconv_find_func (found->handle, - "gconv_init"); - found->end_fct = __gconv_find_func (found->handle, - "gconv_end"); + found->init_fct = __libc_dlsym (found->handle, "gconv_init"); + found->end_fct = __libc_dlsym (found->handle, "gconv_end"); /* We have succeeded in loading the shared object. */ found->counter = 1; @@ -224,11 +154,8 @@ do_release_shlib (const void *nodep, VISIT value, int level) { if (--obj->counter < -TRIES_BEFORE_UNLOAD && obj->handle != NULL) { - /* Unload the shared object. We don't use the trick to - catch errors since in the case an error is signalled - something is really wrong. */ - _dl_close (obj->handle); - + /* Unload the shared object. */ + __libc_dlclose (obj->handle); obj->handle = NULL; } } @@ -258,11 +185,9 @@ do_release_all (void *nodep) { struct __gconv_loaded_object *obj = (struct __gconv_loaded_object *) nodep; - /* Unload the shared object. We don't use the trick to - catch errors since in the case an error is signalled - something is really wrong. */ + /* Unload the shared object. */ if (obj->handle != NULL) - _dl_close (obj->handle); + __libc_dlclose (obj->handle); free (obj); } diff --git a/iconv/gconv_int.h b/iconv/gconv_int.h index 29f495c..6048319 100644 --- a/iconv/gconv_int.h +++ b/iconv/gconv_int.h @@ -51,7 +51,7 @@ struct __gconv_loaded_object int counter; /* The handle for the shared object. */ - struct link_map *handle; + void *handle; /* Pointer to the functions the module defines. */ __gconv_fct fct; @@ -135,10 +135,6 @@ extern int __gconv_close_transform (struct __gconv_step *__steps, extern struct __gconv_loaded_object *__gconv_find_shlib (const char *__name) internal_function; -/* Find function named NAME in shared object referenced by HANDLE. */ -void *__gconv_find_func (void *handle, const char *name) - internal_function; - /* Release shared object. If no further reference is available unload the object. */ extern int __gconv_release_shlib (struct __gconv_loaded_object *__handle) diff --git a/include/dlfcn.h b/include/dlfcn.h index 9558197..f875a63 100644 --- a/include/dlfcn.h +++ b/include/dlfcn.h @@ -4,4 +4,11 @@ /* Now define the internal interfaces. */ extern void *__dlvsym __P ((void *__handle, __const char *__name, __const char *__version)); + +extern void *__libc_dlopen __P ((__const char *__name)); +extern void *__libc_dlsym __P ((void *__map, __const char *__name)); +extern int __libc_dlclose __P ((void *__map)); +extern int _dl_addr __P ((const void *address, Dl_info *info)) + internal_function; + #endif diff --git a/malloc/mtrace.c b/malloc/mtrace.c index c539cb4..4e6e1e5 100644 --- a/malloc/mtrace.c +++ b/malloc/mtrace.c @@ -28,7 +28,7 @@ #include #endif -#include +#include #include #include diff --git a/nss/nsswitch.c b/nss/nsswitch.c index 0fac09e..f125026 100644 --- a/nss/nsswitch.c +++ b/nss/nsswitch.c @@ -26,7 +26,6 @@ #include #include #include -#include /* We need some help from ld.so. */ #if !defined DO_STATIC_NSS || defined PIC # include @@ -245,60 +244,6 @@ __nss_configure_lookup (const char *dbname, const char *service_line) } -#if !defined DO_STATIC_NSS || defined PIC -static int -nss_dlerror_run (void (*operate) (void *), void *args) -{ - char *last_errstring = NULL; - int result; - - (void) _dl_catch_error (&last_errstring, operate, args); - - result = last_errstring != NULL; - if (result) - free (last_errstring); - - return result; -} - - -struct do_open_args -{ - /* Argument to do_open. */ - char *shlib_name; - service_user *ni; -}; - -struct get_sym_args -{ - /* Arguments to get_sym. */ - struct link_map *map; - char *name; - - /* Return values of get_sym. */ - ElfW(Addr) loadbase; - const ElfW(Sym) *ref; -}; - -static void -do_open (void *a) -{ - struct do_open_args *args = (struct do_open_args *) a; - /* Open and relocate the shared object. */ - args->ni->library->lib_handle = _dl_open (args->shlib_name, RTLD_LAZY, NULL); -} - -static void -get_sym (void *a) -{ - struct get_sym_args *args = (struct get_sym_args *) a; - args->ref = NULL; - args->loadbase = _dl_lookup_symbol (args->name, &args->ref, - args->map->l_local_scope, - args->map->l_name, 0); -} -#endif - /* Comparison function for searching NI->known tree. */ static int known_compare (const void *p1, const void *p2) @@ -376,18 +321,17 @@ __nss_lookup_function (service_user *ni, const char *fct_name) size_t shlen = (7 + strlen (ni->library->name) + 3 + strlen (__nss_shlib_revision) + 1); int saved_errno = errno; - struct do_open_args args; - args.shlib_name = __alloca (shlen); - args.ni = ni; + char shlib_name[shlen]; /* Construct shared object name. */ - __stpcpy (__stpcpy (__stpcpy (__stpcpy (args.shlib_name, + __stpcpy (__stpcpy (__stpcpy (__stpcpy (shlib_name, "libnss_"), ni->library->name), ".so"), __nss_shlib_revision); - if (nss_dlerror_run (do_open, &args) != 0) + ni->library->lib_handle = __libc_dlopen (shlib_name); + if (ni->library->lib_handle == NULL) { /* Failed to load the library. */ ni->library->lib_handle = (void *) -1l; @@ -400,22 +344,19 @@ __nss_lookup_function (service_user *ni, const char *fct_name) result = NULL; else { - /* Get the desired function. Again, GNU ld.so magic ahead. */ + /* Get the desired function. */ size_t namlen = (5 + strlen (ni->library->name) + 1 + strlen (fct_name) + 1); - struct get_sym_args args; - args.name = __alloca (namlen); - args.map = ni->library->lib_handle; + char name[namlen]; /* Construct the function name. */ - __stpcpy (__stpcpy (__stpcpy (__stpcpy (args.name, "_nss_"), + __stpcpy (__stpcpy (__stpcpy (__stpcpy (name, "_nss_"), ni->library->name), "_"), fct_name); /* Look up the symbol. */ - result = (nss_dlerror_run (get_sym, &args) ? NULL - : (void *) (args.loadbase + args.ref->st_value)); + result = __libc_dlsym (ni->library->lib_handle, name); } #else /* We can't get function address dynamically in static linking. */ @@ -796,7 +737,7 @@ free_mem (void) { service_library *oldl = library; - _dl_close (library->lib_handle); + __libc_dlclose (library->lib_handle); library = library->next; free (oldl); diff --git a/sysdeps/libm-ieee754/e_gamma_r.c b/sysdeps/libm-ieee754/e_gamma_r.c index 901f145..bd802c2 100644 --- a/sysdeps/libm-ieee754/e_gamma_r.c +++ b/sysdeps/libm-ieee754/e_gamma_r.c @@ -1,5 +1,5 @@ /* Implementation of gamma function according to ISO C. - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1997. @@ -34,11 +34,15 @@ __ieee754_gamma_r (double x, int *signgamp) EXTRACT_WORDS (hx, lx, x); if (((hx & 0x7fffffff) | lx) == 0) - /* Return value for x == 0 is NaN with invalid exception. */ - return x / x; + { + /* Return value for x == 0 is NaN with invalid exception. */ + *signgamp = 0; + return x / x; + } if (hx < 0 && (u_int32_t) hx < 0xfff00000 && __rint (x) == x) { /* Return value for integer x < 0 is NaN with invalid exception. */ + *signgamp = 0; return (x - x) / (x - x); } diff --git a/sysdeps/libm-ieee754/e_gammaf_r.c b/sysdeps/libm-ieee754/e_gammaf_r.c index bf79ffe..926905e 100644 --- a/sysdeps/libm-ieee754/e_gammaf_r.c +++ b/sysdeps/libm-ieee754/e_gammaf_r.c @@ -1,5 +1,5 @@ /* Implementation of gamma function according to ISO C. - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1997. @@ -33,11 +33,15 @@ __ieee754_gammaf_r (float x, int *signgamp) GET_FLOAT_WORD (hx, x); if ((hx & 0x7fffffff) == 0) - /* Return value for x == 0 is NaN with invalid exception. */ - return x / x; + { + /* Return value for x == 0 is NaN with invalid exception. */ + *signgamp = 0; + return x / x; + } if (hx < 0 && (u_int32_t) hx < 0xff800000 && __rintf (x) == x) { /* Return value for integer x < 0 is NaN with invalid exception. */ + *signgamp = 0; return (x - x) / (x - x); } diff --git a/sysdeps/libm-ieee754/e_gammal_r.c b/sysdeps/libm-ieee754/e_gammal_r.c index 4fd4988..1049924 100644 --- a/sysdeps/libm-ieee754/e_gammal_r.c +++ b/sysdeps/libm-ieee754/e_gammal_r.c @@ -1,5 +1,5 @@ /* Implementation of gamma function according to ISO C. - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1997. @@ -33,11 +33,15 @@ __ieee754_gammal_r (long double x, int *signgamp) GET_LDOUBLE_WORDS (es, hx, lx, x); if (((es & 0x7fff) | hx | lx) == 0) - /* Return value for x == 0 is NaN with invalid exception. */ - return x / x; + { + /* Return value for x == 0 is NaN with invalid exception. */ + *signgamp = 0; + return x / x; + } if ((hx & 0x8000) != 0 && (hx & 0x7fff) != 0x7fff && __rintl (x) == x) { /* Return value for integer x < 0 is NaN with invalid exception. */ + *signgamp = 0; return (x - x) / (x - x); } -- 2.7.4