* 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 <jreiser@BitWagon.com> [PR libc/1185].

	* elf/dl-dst.h: Fix typo.
	* elf/dl-open.c: Likewise.

1999-06-26  Zack Weinberg  <zack@rabi.columbia.edu>

	* 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  <drepper@cygnus.com>
This commit is contained in:
Ulrich Drepper 1999-06-28 15:52:36 +00:00
parent 738d1a5a43
commit b3fc5f84d1
17 changed files with 214 additions and 175 deletions

View File

@ -1,3 +1,37 @@
1999-06-28 Ulrich Drepper <drepper@cygnus.com>
* 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 <jreiser@BitWagon.com> [PR libc/1185].
* elf/dl-dst.h: Fix typo.
* elf/dl-open.c: Likewise.
1999-06-26 Zack Weinberg <zack@rabi.columbia.edu>
* 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 <drepper@cygnus.com>
* sysdeps/unix/sysv/linux/gethostid.c: Test for gethostbyname_r

View File

@ -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.

View File

@ -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; \

122
elf/dl-libc.c Normal file
View File

@ -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 <zack@rabi.columbia.edu>, 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 <dlfcn.h>
#include <stdlib.h>
#include <ldsodefs.h>
/* 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);
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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; \
})

View File

@ -22,7 +22,7 @@
#include <assert.h>
#include <gconv.h>
#include <sys/param.h>
#include <dlfcn.h>
#include <ldsodefs.h>
int

View File

@ -25,6 +25,7 @@
#include <sys/param.h>
#include <bits/libc-lock.h>
#include <dlfcn.h>
#include <ldsodefs.h>
#include <gconv_int.h>

View File

@ -26,10 +26,8 @@
#include <bits/libc-lock.h>
#include <sys/param.h>
#include <ldsodefs.h>
#include <gconv_int.h>
/* 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);
}

View File

@ -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)

View File

@ -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

View File

@ -28,7 +28,7 @@
#include <bits/libc-lock.h>
#endif
#include <ldsodefs.h>
#include <dlfcn.h>
#include <stdio.h>
#include <string.h>

View File

@ -26,7 +26,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ldsodefs.h> /* We need some help from ld.so. */
#if !defined DO_STATIC_NSS || defined PIC
# include <gnu/lib-names.h>
@ -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);

View File

@ -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 <drepper@cygnus.com>, 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);
}

View File

@ -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 <drepper@cygnus.com>, 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);
}

View File

@ -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 <drepper@cygnus.com>, 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);
}