mirror of
git://sourceware.org/git/glibc.git
synced 2024-11-27 03:41:23 +08:00
Update.
1998-06-18 16:40 Ulrich Drepper <drepper@cygnus.com> * libc.map: Add _dl_profile_map, _dl_profile_output, _dl_start_profile, _dl_mcount, _dl_mcount_wrapper. * elf/Makefile (routines): Add dl-profstub. * elf/dl-profstub.c: New file. * elf/dl-support.c: Don't define _dl_profile_map. * elf/rtld.c: Likewise. * elf/dlfcn.h: Define DL_CALL_FCT macro. * elf/ldsodefs.h: Declare _dl_profile_output, _dl_mcount_wrapper. Define _CALL_DL_FCT. * iconv/gconv.c: Use _CALL_DL_FCT to call function from dynamically loaded object. * iconv/gconv_db.c: Likewise. * iconv/skeleton.c: Likewise. * nss/getXXbyYY_r.c: Likewise. * nss/getXXent_r.c: Likewise. * nss/nsswitch.c: Likewise.
This commit is contained in:
parent
2827300fbe
commit
5ad49c0707
19
ChangeLog
19
ChangeLog
@ -1,3 +1,22 @@
|
||||
1998-06-18 16:40 Ulrich Drepper <drepper@cygnus.com>
|
||||
|
||||
* libc.map: Add _dl_profile_map, _dl_profile_output, _dl_start_profile,
|
||||
_dl_mcount, _dl_mcount_wrapper.
|
||||
* elf/Makefile (routines): Add dl-profstub.
|
||||
* elf/dl-profstub.c: New file.
|
||||
* elf/dl-support.c: Don't define _dl_profile_map.
|
||||
* elf/rtld.c: Likewise.
|
||||
* elf/dlfcn.h: Define DL_CALL_FCT macro.
|
||||
* elf/ldsodefs.h: Declare _dl_profile_output, _dl_mcount_wrapper.
|
||||
Define _CALL_DL_FCT.
|
||||
* iconv/gconv.c: Use _CALL_DL_FCT to call function from dynamically
|
||||
loaded object.
|
||||
* iconv/gconv_db.c: Likewise.
|
||||
* iconv/skeleton.c: Likewise.
|
||||
* nss/getXXbyYY_r.c: Likewise.
|
||||
* nss/getXXent_r.c: Likewise.
|
||||
* nss/nsswitch.c: Likewise.
|
||||
|
||||
1998-06-18 12:29 Ulrich Drepper <drepper@cygnus.com>
|
||||
|
||||
* sysdeps/libm-i387/e_scalb.S: Fix bug in FPU stack handling.
|
||||
|
@ -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-addr enbl-secure dl-profstub
|
||||
|
||||
# The core dynamic linking functions are in libc for the static and
|
||||
# profiled libraries.
|
||||
|
@ -101,9 +101,27 @@ _dl_open (const char *file, int mode)
|
||||
magic ward. */
|
||||
asm ("" : "=r" (reloc) : "0" (reloc));
|
||||
|
||||
(*reloc) (l, _dl_object_relocation_scope (l),
|
||||
((mode & RTLD_BINDING_MASK) == RTLD_LAZY
|
||||
|| _dl_profile != NULL), _dl_profile != NULL);
|
||||
#ifdef PIC
|
||||
if (_dl_profile != NULL)
|
||||
{
|
||||
/* If this here is the shared object which we want to profile
|
||||
make sure the profile is started. We can find out whether
|
||||
this is necessary or not by observing the `_dl_profile_map'
|
||||
variable. If was NULL but is not NULL afterwars we must
|
||||
start the profiling. */
|
||||
struct link_map *old_profile_map = _dl_profile_map;
|
||||
|
||||
(*reloc) (l, _dl_object_relocation_scope (l), 1, 1);
|
||||
|
||||
if (old_profile_map == NULL && _dl_profile_map != NULL)
|
||||
/* We must prepare the profiling. */
|
||||
_dl_start_profile (_dl_profile_map, _dl_profile_output);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
(*reloc) (l, _dl_object_relocation_scope (l),
|
||||
(mode & RTLD_BINDING_MASK) == RTLD_LAZY, 0);
|
||||
|
||||
*_dl_global_scope_end = NULL;
|
||||
}
|
||||
|
||||
|
43
elf/dl-profstub.c
Normal file
43
elf/dl-profstub.c
Normal file
@ -0,0 +1,43 @@
|
||||
/* Helper definitions for profiling of shared libraries.
|
||||
Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
|
||||
|
||||
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 <elf.h>
|
||||
#include <elf/ldsodefs.h>
|
||||
|
||||
/* This is the map for the shared object we profile. It is defined here
|
||||
only because we test for this value being NULL or not. */
|
||||
struct link_map *_dl_profile_map;
|
||||
|
||||
|
||||
void
|
||||
_dl_mcount_wrapper (ElfW(Addr) selfpc)
|
||||
{
|
||||
_dl_mcount ((ElfW(Addr)) __builtin_return_address (0), selfpc);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_dl_mcount_wrapper_check (void *selfpc)
|
||||
{
|
||||
if (_dl_profile_map != NULL)
|
||||
_dl_mcount ((ElfW(Addr)) __builtin_return_address (0),
|
||||
(ElfW(Addr)) selfpc);
|
||||
}
|
@ -53,7 +53,6 @@ struct r_search_path *_dl_search_paths;
|
||||
|
||||
/* We never do profiling. */
|
||||
const char *_dl_profile;
|
||||
struct link_map *_dl_profile_map;
|
||||
|
||||
/* Names of shared object for which the RPATHs should be ignored. */
|
||||
const char *_dl_inhibit_rpath;
|
||||
|
30
elf/dlfcn.h
30
elf/dlfcn.h
@ -1,5 +1,5 @@
|
||||
/* User functions for run-time dynamic loading.
|
||||
Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995, 1996, 1997, 1998 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
|
||||
@ -70,6 +70,34 @@ typedef struct
|
||||
} Dl_info;
|
||||
extern int dladdr __P ((const void *__address, Dl_info *__info));
|
||||
|
||||
#ifdef __USE_GNU
|
||||
/* To support profiling of shared objects it is a good idea to call
|
||||
the function found using `dlsym' using the following macro since
|
||||
these calls do not use the PLT. But this would mean the dynamic
|
||||
loader has no chance to find out when the function is called. The
|
||||
macro applies the necessary magic so that profiling is possible.
|
||||
Rewrite
|
||||
foo = (*fctp) (arg1, arg2);
|
||||
into
|
||||
foo = DL_CALL_FCT (fctp, (arg1, arg2));
|
||||
*/
|
||||
# if __GNUC__ >= 2
|
||||
/* Do not ever use this variable directly, it is internal! */
|
||||
extern struct link_map *_dl_profile_map;
|
||||
|
||||
# define DL_CALL_FCT(fctp, args) \
|
||||
(__extension__ ({ if (_dl_profile_map != NULL) \
|
||||
_dl_mcount_wrapper_check (fctp); \
|
||||
(*fctp) args; })
|
||||
# else
|
||||
/* This feature is not available without GCC. */
|
||||
# define DL_CALL_FCT(fctp, args) (*fctp) args
|
||||
# endif
|
||||
|
||||
/* This function calls the profiling functions. */
|
||||
extern void _dl_mcount_wrapper_check __P ((void *__selfpc));
|
||||
#endif
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* dlfcn.h */
|
||||
|
@ -127,6 +127,8 @@ extern int _dl_zerofd;
|
||||
extern const char *_dl_profile;
|
||||
/* Map of shared object to be profiled. */
|
||||
extern struct link_map *_dl_profile_map;
|
||||
/* Filename of the output file. */
|
||||
extern const char *_dl_profile_output;
|
||||
|
||||
/* If nonzero the appropriate debug information is printed. */
|
||||
extern int _dl_debug_libs;
|
||||
@ -409,6 +411,11 @@ extern void _dl_start_profile (struct link_map *map, const char *output_dir)
|
||||
/* The actual functions used to keep book on the calls. */
|
||||
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);
|
||||
|
||||
|
||||
/* Show the members of the auxiliary array passed up from the kernel. */
|
||||
extern void _dl_show_auxv (void) internal_function;
|
||||
@ -424,6 +431,18 @@ extern const struct r_strlenpair *_dl_important_hwcaps (const char *platform,
|
||||
size_t *max_capstrlen)
|
||||
internal_function;
|
||||
|
||||
|
||||
/* When we do profiling we have the problem that uses of `dlopen'ed
|
||||
objects don't use the PLT but instead use a pointer to the function.
|
||||
We still want to have profiling data and in these cases we must do
|
||||
the work of calling `_dl_mcount' ourself. The following macros
|
||||
helps do it. */
|
||||
#define _CALL_DL_FCT(fctp, args) \
|
||||
({ if (_dl_profile_map != NULL) \
|
||||
_dl_mcount_wrapper ((ElfW(Addr)) fctp); \
|
||||
(*fctp) args; \
|
||||
})
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* ldsodefs.h */
|
||||
|
@ -73,7 +73,6 @@ unsigned long _dl_hwcap;
|
||||
struct r_search_path *_dl_search_paths;
|
||||
const char *_dl_profile;
|
||||
const char *_dl_profile_output;
|
||||
struct link_map *_dl_profile_map;
|
||||
int _dl_debug_libs;
|
||||
int _dl_debug_impcalls;
|
||||
int _dl_debug_bindings;
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <assert.h>
|
||||
#include <gconv.h>
|
||||
#include <sys/param.h>
|
||||
#include <elf/ldsodefs.h>
|
||||
|
||||
|
||||
int
|
||||
@ -40,7 +41,8 @@ __gconv (gconv_t cd, const char **inbuf, const char *inbufend, char **outbuf,
|
||||
|
||||
if (inbuf == NULL || *inbuf == NULL)
|
||||
/* We just flush. */
|
||||
result = (*cd->steps->fct) (cd->steps, cd->data, NULL, NULL, converted, 1);
|
||||
result = _CALL_DL_FCT (cd->steps->fct,
|
||||
(cd->steps, cd->data, NULL, NULL, converted, 1));
|
||||
else
|
||||
{
|
||||
const char *last_start;
|
||||
@ -52,8 +54,9 @@ __gconv (gconv_t cd, const char **inbuf, const char *inbufend, char **outbuf,
|
||||
do
|
||||
{
|
||||
last_start = *inbuf;
|
||||
result = (*cd->steps->fct) (cd->steps, cd->data, inbuf, inbufend,
|
||||
converted, 0);
|
||||
result = _CALL_DL_FCT (cd->steps->fct,
|
||||
(cd->steps, cd->data, inbuf, inbufend,
|
||||
converted, 0));
|
||||
}
|
||||
while (result == GCONV_EMPTY_INPUT && last_start != *inbuf
|
||||
&& *inbuf + cd->steps->min_needed_from <= inbufend);
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <bits/libc-lock.h>
|
||||
#include <elf/ldsodefs.h>
|
||||
|
||||
#include <gconv_int.h>
|
||||
|
||||
@ -154,7 +155,7 @@ free_derivation (void *p)
|
||||
|
||||
for (cnt = 0; cnt < deriv->nsteps; ++cnt)
|
||||
if (deriv->steps[cnt].end_fct)
|
||||
(*deriv->steps[cnt].end_fct) (&deriv->steps[cnt]);
|
||||
_CALL_DL_FCT (deriv->steps[cnt].end_fct, (&deriv->steps[cnt]));
|
||||
|
||||
free ((struct gconv_step *) deriv->steps);
|
||||
free (deriv);
|
||||
@ -220,7 +221,7 @@ gen_steps (struct derivation_step *best, const char *toset,
|
||||
|
||||
/* Call the init function. */
|
||||
if (result[step_cnt].init_fct != NULL)
|
||||
(*result[step_cnt].init_fct) (&result[step_cnt]);
|
||||
_CALL_DL_FCT (result[step_cnt].init_fct, (&result[step_cnt]));
|
||||
|
||||
current = current->last;
|
||||
}
|
||||
@ -231,7 +232,7 @@ gen_steps (struct derivation_step *best, const char *toset,
|
||||
while (++step_cnt < *nsteps)
|
||||
{
|
||||
if (result[step_cnt].end_fct != NULL)
|
||||
(*result[step_cnt].end_fct) (&result[step_cnt]);
|
||||
_CALL_DL_FCT (result[step_cnt].end_fct, (&result[step_cnt]));
|
||||
#ifndef STATIC_GCONV
|
||||
__gconv_release_shlib (result[step_cnt].shlib_handle);
|
||||
#endif
|
||||
|
@ -82,6 +82,7 @@
|
||||
#define __need_size_t
|
||||
#define __need_NULL
|
||||
#include <stddef.h>
|
||||
#include <elf/ldsodefs.h>
|
||||
|
||||
|
||||
/* The direction objects. */
|
||||
@ -218,7 +219,8 @@ FUNCTION_NAME (struct gconv_step *step, struct gconv_step_data *data,
|
||||
if (status == GCONV_OK)
|
||||
#endif
|
||||
/* Give the modules below the same chance. */
|
||||
status = (*fct) (next_step, next_data, NULL, NULL, written, 1);
|
||||
status = _CALL_DL_FCT (fct, (next_step, next_data, NULL, NULL,
|
||||
written, 1));
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -284,8 +286,8 @@ FUNCTION_NAME (struct gconv_step *step, struct gconv_step_data *data,
|
||||
const char *outerr = data->outbuf;
|
||||
int result;
|
||||
|
||||
result = (*fct) (next_step, next_data, &outerr, outbuf,
|
||||
written, 0);
|
||||
result = _CALL_DL_FCT (fct, (next_step, next_data, &outerr,
|
||||
outbuf, written, 0));
|
||||
|
||||
if (result != GCONV_EMPTY_INPUT)
|
||||
{
|
||||
|
4
libc.map
4
libc.map
@ -474,7 +474,8 @@ GLIBC_2.1 {
|
||||
# global variables
|
||||
_IO_2_1_stdin_; _IO_2_1_stdout_; _IO_2_1_stderr_;
|
||||
__gconv_alias_db; __gconv_nmodules; __gconv_modules_db;
|
||||
_dl_profile; __libc_stack_end;
|
||||
_dl_profile; _dl_profile_map; _dl_profile_output; _dl_start_profile;
|
||||
__libc_stack_end;
|
||||
|
||||
# This is for ix86 only.
|
||||
_fp_hw;
|
||||
@ -491,6 +492,7 @@ GLIBC_2.1 {
|
||||
__xstat64; __fxstat64; __lxstat64;
|
||||
__pread64; __pwrite64;
|
||||
__backtrace; __backtrace_symbols;
|
||||
_dl_mcount; _dl_mcount_wrapper;
|
||||
|
||||
# helper functions
|
||||
__libc_current_sigrtmin; __libc_current_sigrtmax; __libc_allocate_rtsig;
|
||||
|
@ -161,8 +161,8 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer,
|
||||
|
||||
while (no_more == 0)
|
||||
{
|
||||
status = (*fct) (ADD_VARIABLES, resbuf, buffer, buflen,
|
||||
&errno H_ERRNO_VAR);
|
||||
status = _CALL_DL_FCT (fct, (ADD_VARIABLES, resbuf, buffer, buflen,
|
||||
&errno H_ERRNO_VAR));
|
||||
|
||||
/* The status is NSS_STATUS_TRYAGAIN and errno is ERANGE the
|
||||
provided buffer is too small. In this case we should give
|
||||
|
@ -164,7 +164,7 @@ SETFUNC_NAME (STAYOPEN)
|
||||
while (! no_more)
|
||||
{
|
||||
int is_last_nip = nip == last_nip;
|
||||
enum nss_status status = (*fct) (STAYOPEN_VAR);
|
||||
enum nss_status status = _CALL_DL_FCT (fct, (STAYOPEN_VAR));
|
||||
|
||||
no_more = __nss_next (&nip, SETFUNC_NAME_STRING, (void **) &fct,
|
||||
status, 0);
|
||||
@ -201,7 +201,7 @@ ENDFUNC_NAME (void)
|
||||
while (! no_more)
|
||||
{
|
||||
/* Ignore status, we force check in __NSS_NEXT. */
|
||||
(void) (*fct) ();
|
||||
_CALL_DL_FCT (fct, ());
|
||||
|
||||
if (nip == last_nip)
|
||||
/* We have processed all services which were used. */
|
||||
@ -245,7 +245,8 @@ INTERNAL (REENTRANT_GETNAME) (LOOKUP_TYPE *resbuf, char *buffer, size_t buflen,
|
||||
{
|
||||
int is_last_nip = nip == last_nip;
|
||||
|
||||
status = (*fct) (resbuf, buffer, buflen, &errno H_ERRNO_VAR);
|
||||
status = _CALL_DL_FCT (fct,
|
||||
(resbuf, buffer, buflen, &errno H_ERRNO_VAR));
|
||||
|
||||
/* The the status is NSS_STATUS_TRYAGAIN and errno is ERANGE the
|
||||
provided buffer is too small. In this case we should give
|
||||
@ -276,7 +277,7 @@ INTERNAL (REENTRANT_GETNAME) (LOOKUP_TYPE *resbuf, char *buffer, size_t buflen,
|
||||
(void **) &sfct);
|
||||
|
||||
if (! no_more)
|
||||
status = (*sfct) (STAYOPEN_TMPVAR);
|
||||
status = _CALL_DL_FCT (sfct, (STAYOPEN_TMPVAR));
|
||||
else
|
||||
status = NSS_STATUS_NOTFOUND;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1996, 1997, 1998 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
|
||||
@ -26,6 +26,7 @@
|
||||
#include <nss.h>
|
||||
#include <resolv.h>
|
||||
#include <search.h>
|
||||
#include <elf/ldsodefs.h>
|
||||
|
||||
|
||||
/* Actions performed after lookup finished. */
|
||||
|
Loading…
Reference in New Issue
Block a user