summaryrefslogtreecommitdiff
path: root/elf
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1997-03-29 17:32:35 +0000
committerUlrich Drepper <drepper@redhat.com>1997-03-29 17:32:35 +0000
commit993b3242cdc37152fbbc7fbd5ce22b2734b04b23 (patch)
treed3c4fc94e027728055d96a370d034b6fb685cf85 /elf
parente7fd8a39abd3a9c9d2139e686b17efb5dc3bf444 (diff)
Update.
1997-03-29 17:39 Ulrich Drepper <drepper@cygnus.com> * math/Makefile (routines): Add carg, s_ccosh and s_csinh. * math/complex.h: Add C++ protection. * math/libm-test.c (cexp_test): Correct a few bugs. (csinh_test): New function. (ccosh_test): New function. (cacos_test): New function. (cacosh_test): New function. (casinh_test): New function. (catanh_test): New function. (main): Add calls to csinh_test and ccosh_test. * misc/Makefile (tests): Add tst-tsearch. Add rule to link tst-tsearch against libm. * misc/tsearch.c: Rewritten to use Red-Black-Tree algorithm by Bernd Schmidt <crux@Pool.Informatik.RWTH-Aachen.DE>. * misc/tst-tsearch.c: New file. * stdio-common/bug5.c: Clear LD_LIBRARY_PATH environment variable before using system. * stdio-common/test-popen.c: Clear LD_LIBRARY_PATH environment variable before using popen. * sysdeps/libm-ieee754/s_cexp.c: Correct handling of special cases. * sysdeps/libm-ieee754/s_cexpf.c: Likewise. * sysdeps/libm-ieee754/s_cexpl.c: Likewise. * sysdeps/libm-i387/s_cexp.S: New file. ix87 specific implementation of complex exponential function. * sysdeps/libm-i387/s_cexpf.S: New file. * sysdeps/libm-i387/s_cexpl.S: New file. * sysdeps/libm-ieee754/s_ccosh.c: New file. Implementation of complex cosh function. * sysdeps/libm-ieee754/s_ccoshf.c: New file. * sysdeps/libm-ieee754/s_ccoshl.c: New file. * sysdeps/libm-ieee754/s_csinh.c: New file. Implementation of complex sinh function. * sysdeps/libm-ieee754/s_csinhf.c: New file. * sysdeps/libm-ieee754/s_csinhl.c: New file. * math/carg.c: New file. Generic implementatio of carg function. * math/cargf.c: New file. * math/cargl.c: New file. 1997-03-29 16:07 Ulrich Drepper <drepper@cygnus.com> * sysdeps/posix/system.c: Update copyright. 1997-03-29 04:18 Ulrich Drepper <drepper@cygnus.com> * elf/dl-error.c (_dl_catch_error): Add another argument which is passed to OPERATE. (_dl_receive_error): Likewise. * elf/link.h: Change prototypes for _dl_catch_error and _dl_receive_error to reflect above change. * elf/dl-deps.c: Don't use nested function. Call _dl_catch_error with additional argument with pointer to data. * elf/dlclose.c: Likewise. * elf/dlerror.c: Likewise. * elf/dlopen.c: Likewise. * elf/dlsym.c: Likewise. * elf/dlvsym.c: Likewise. * elf/rtld.c: Likewise. * nss/nsswitch.c: Likewise. Patch by Bernd Schmidt <crux@Pool.Informatik.RWTH-Aachen.DE>. 1997-03-28 21:14 Miguel de Icaza <miguel@nuclecu.unam.mx> * elf/dl-error.c: Manually set up the values of "c", this avoids a call to memcpy and a zero 152 bytes structure. * sysdeps/sparc/dl-machine.h (elf_machine_rela): Test RTLD_BOOTSTRAP to avoid performing relative relocs on a second pass. * sysdeps/sparc/udiv_qrnnd.S: Make the code PIC aware. * sysdeps/unix/sysv/linux/sparc/Dist: Add kernel_stat.h and kernel_sigaction.h Add Linux/SPARC specific definitions. * sysdeps/unix/sysv/linux/sparc/fcntlbits.h: New file. * sysdeps/unix/sysv/linux/sparc/ioctls.h: New file. * sysdeps/unix/sysv/linux/sparc/kernel_sigaction.h: New file. * sysdeps/unix/sysv/linux/sparc/kernel_stat.h: New file. * sysdeps/unix/sysv/linux/sparc/sigaction.h: New file. * sysdeps/unix/sysv/linux/sparc/signum.h: New file. * sysdeps/unix/sysv/linux/sparc/termbits.h: New file. 1997-03-28 13:06 Philip Blundell <pjb27@cam.ac.uk> * sysdeps/posix/getaddrinfo.c (gaih_inet_serv): Use __getservbyname_r() not getservbyname(). (BROKEN_LIKE_POSIX): Define to 1 so we get strict POSIX behaviour.
Diffstat (limited to 'elf')
-rw-r--r--elf/dl-deps.c45
-rw-r--r--elf/dl-error.c18
-rw-r--r--elf/dlclose.c13
-rw-r--r--elf/dlerror.c4
-rw-r--r--elf/dlopen.c30
-rw-r--r--elf/dlsym.c90
-rw-r--r--elf/dlvsym.c109
-rw-r--r--elf/link.h17
-rw-r--r--elf/rtld.c80
9 files changed, 272 insertions, 134 deletions
diff --git a/elf/dl-deps.c b/elf/dl-deps.c
index 7a6772979b..e2fd340822 100644
--- a/elf/dl-deps.c
+++ b/elf/dl-deps.c
@@ -22,6 +22,29 @@
#include <dlfcn.h>
#include <stdlib.h>
+struct openaux_args
+{
+ /* The arguments to openaux. */
+ struct link_map *map;
+ int trace_mode;
+ const char *strtab;
+ ElfW(Dyn) *d;
+
+ /* The return value of openaux. */
+ struct link_map *aux;
+};
+
+static void
+openaux (void *a)
+{
+ struct openaux_args *args = (struct openaux_args *) a;
+
+ args->aux = _dl_map_object (args->map, args->strtab + args->d->d_un.d_val,
+ (args->map->l_type == lt_executable
+ ? lt_library : args->map->l_type),
+ args->trace_mode);
+}
+
void
_dl_map_object_deps (struct link_map *map,
struct link_map **preloads, unsigned int npreloads,
@@ -75,27 +98,21 @@ _dl_map_object_deps (struct link_map *map,
/* There is at least one auxiliary library specified. We try to
load it, and if we can, use its symbols in preference to our
own. But if we can't load it, we just silently ignore it. */
- const char *strtab
+ struct openaux_args args;
+ args.strtab
= ((void *) map->l_addr + map->l_info[DT_STRTAB]->d_un.d_ptr);
- ElfW(Dyn) *d;
+ args.map = map;
+ args.trace_mode = trace_mode;
- for (d = map->l_ld; d->d_tag != DT_NULL; ++d)
- if (d->d_tag == DT_AUXILIARY)
+ for (args.d = map->l_ld; args.d->d_tag != DT_NULL; ++args.d)
+ if (args.d->d_tag == DT_AUXILIARY)
{
- struct link_map *aux;
- void openaux (void)
- {
- aux = _dl_map_object (map, strtab + d->d_un.d_val,
- (map->l_type == lt_executable
- ? lt_library : map->l_type),
- trace_mode);
- }
char *errstring;
const char *objname;
- if (! _dl_catch_error (&errstring, &objname, openaux))
+ if (! _dl_catch_error (&errstring, &objname, openaux, &args))
/* The auxiliary object is actually there. Use it as
the first search element, even before MAP itself. */
- preload (aux);
+ preload (args.aux);
}
}
diff --git a/elf/dl-error.c b/elf/dl-error.c
index 263bd65eb0..e2565bb348 100644
--- a/elf/dl-error.c
+++ b/elf/dl-error.c
@@ -85,19 +85,25 @@ _dl_signal_error (int errcode,
int
_dl_catch_error (char **errstring,
const char **objname,
- void (*operate) (void))
+ void (*operate) (void *),
+ void *args)
{
int errcode;
- struct catch *old, c = { errstring: NULL, objname: NULL };
- /* We need not handle `receiver' since setting a `catch' is handle
+ struct catch *old, c;
+ /* We need not handle `receiver' since setting a `catch' is handled
before it. */
+ /* Some systems (.e.g, SPARC) handle constructors to local variables
+ inefficient. So we initialize `c' by hand. */
+ c.errstring = NULL;
+ c.objname = NULL;
+
old = catch;
errcode = setjmp (c.env);
if (errcode == 0)
{
catch = &c;
- (*operate) ();
+ (*operate) (args);
catch = old;
*errstring = NULL;
*objname = NULL;
@@ -112,7 +118,7 @@ _dl_catch_error (char **errstring,
}
void
-_dl_receive_error (receiver_fct fct, void (*operate) (void))
+_dl_receive_error (receiver_fct fct, void (*operate) (void *), void *args)
{
struct catch *old_catch;
receiver_fct old_receiver;
@@ -124,7 +130,7 @@ _dl_receive_error (receiver_fct fct, void (*operate) (void))
catch = NULL;
receiver = fct;
- (*operate) ();
+ (*operate) (args);
catch = old_catch;
receiver = old_receiver;
diff --git a/elf/dlclose.c b/elf/dlclose.c
index 6a142119f7..d96ffc9cc1 100644
--- a/elf/dlclose.c
+++ b/elf/dlclose.c
@@ -20,13 +20,14 @@
#include <link.h>
#include <dlfcn.h>
+static void
+dlclose_doit (void *handle)
+{
+ _dl_close (handle);
+}
+
int
dlclose (void *handle)
{
- void doit (void)
- {
- _dl_close (handle);
- }
-
- return _dlerror_run (doit) ? -1 : 0;
+ return _dlerror_run (dlclose_doit, handle) ? -1 : 0;
}
diff --git a/elf/dlerror.c b/elf/dlerror.c
index 9e55bc7c76..e2b1ac94a9 100644
--- a/elf/dlerror.c
+++ b/elf/dlerror.c
@@ -64,7 +64,7 @@ dlerror (void)
}
int
-_dlerror_run (void (*operate) (void))
+_dlerror_run (void (*operate) (void *), void *args)
{
if (last_errstring != NULL)
/* Free the error string from the last failed command. This can
@@ -72,6 +72,6 @@ _dlerror_run (void (*operate) (void))
free (last_errstring);
last_errcode = _dl_catch_error (&last_errstring, &last_object_name,
- operate);
+ operate, args);
return last_errstring != NULL;
}
diff --git a/elf/dlopen.c b/elf/dlopen.c
index c2cf8cd58d..4963e9962e 100644
--- a/elf/dlopen.c
+++ b/elf/dlopen.c
@@ -21,15 +21,31 @@
#include <link.h>
#include <dlfcn.h>
-void *
-dlopen (const char *file, int mode)
+struct dlopen_args
{
+ /* The arguments for dlopen_doit. */
+ const char *file;
+ int mode;
+ /* The return value of dlopen_doit. */
struct link_map *new;
+};
+
- void doit (void)
- {
- new = _dl_open (file ?: "", mode);
- }
+static void
+dlopen_doit (void *a)
+{
+ struct dlopen_args *args = (struct dlopen_args *) a;
+
+ args->new = _dl_open (args->file ?: "", args->mode);
+}
+
+
+void *
+dlopen (const char *file, int mode)
+{
+ struct dlopen_args args;
+ args.file = file;
+ args.mode = mode;
- return _dlerror_run (doit) ? NULL : new;
+ return _dlerror_run (dlopen_doit, &args) ? NULL : args.new;
}
diff --git a/elf/dlsym.c b/elf/dlsym.c
index d05619bfb4..1072f16ce1 100644
--- a/elf/dlsym.c
+++ b/elf/dlsym.c
@@ -22,47 +22,71 @@
#include <dlfcn.h>
#include <setjmp.h>
-
-void *
-dlsym (void *handle, const char *name)
+struct dlsym_args
{
- ElfW(Addr) caller = (ElfW(Addr)) __builtin_return_address (0);
+ /* The arguments to dlsym_doit. */
+ void *handle;
+ const char *name;
+ struct r_found_version version;
+ ElfW(Addr) caller;
+ /* The return values of dlsym_doit. */
ElfW(Addr) loadbase;
- const ElfW(Sym) *ref = NULL;
- void doit (void)
+ const ElfW(Sym) *ref;
+};
+
+
+static void
+dlsym_doit (void *a)
+{
+ struct dlsym_args *args = (struct dlsym_args *) a;
+ args->ref = NULL;
+
+ if (args->handle == NULL)
+ /* Search the global scope. */
+ args->loadbase = _dl_lookup_symbol (args->name, &args->ref,
+ &(_dl_global_scope
+ ?: _dl_default_scope)[2],
+ NULL, 0);
+ else if (args->handle == RTLD_NEXT)
{
- if (handle == NULL)
- /* Search the global scope. */
- loadbase = _dl_lookup_symbol
- (name, &ref, &(_dl_global_scope ?: _dl_default_scope)[2], NULL, 0);
- else if (handle == RTLD_NEXT)
- {
- struct link_map *l, *match;
+ struct link_map *l, *match;
- /* Find the highest-addressed object that CALLER is not below. */
- match = NULL;
- for (l = _dl_loaded; l; l = l->l_next)
- if (caller >= l->l_addr && (!match || match->l_addr < l->l_addr))
- match = l;
+ /* Find the highest-addressed object that CALLER is not below. */
+ match = NULL;
+ for (l = _dl_loaded; l; l = l->l_next)
+ if (args->caller >= l->l_addr && (!match || match->l_addr < l->l_addr))
+ match = l;
- if (! match)
- _dl_signal_error (0, NULL, _("\
+ if (! match)
+ _dl_signal_error (0, NULL, _("\
RTLD_NEXT used in code not dynamically loaded"));
- l = match;
- while (l->l_loader)
- l = l->l_loader;
+ l = match;
+ while (l->l_loader)
+ l = l->l_loader;
- loadbase = _dl_lookup_symbol_skip (name, &ref, &_dl_loaded, NULL, l);
- }
- else
- {
- /* Search the scope of the given object. */
- struct link_map *map = handle;
- struct link_map *mapscope[2] = { map, NULL };
- loadbase = _dl_lookup_symbol (name, &ref, mapscope, map->l_name, 0);
- }
+ args->loadbase = _dl_lookup_symbol_skip (args->name, &args->ref,
+ &_dl_loaded, NULL, l);
}
+ else
+ {
+ /* Search the scope of the given object. */
+ struct link_map *map = args->handle;
+ struct link_map *mapscope[2] = { map, NULL };
+ args->loadbase = _dl_lookup_symbol (args->name, &args->ref, mapscope,
+ map->l_name, 0);
+ }
+}
+
+
+void *
+dlsym (void *handle, const char *name)
+{
+ struct dlsym_args args;
+ args.caller = (ElfW(Addr)) __builtin_return_address (0);
+ args.handle = handle;
+ args.name = name;
- return _dlerror_run (doit) ? NULL : (void *) (loadbase + ref->st_value);
+ return (_dlerror_run (dlsym_doit, &args)
+ ? NULL : (void *) (args.loadbase + args.ref->st_value));
}
diff --git a/elf/dlvsym.c b/elf/dlvsym.c
index b3d4c1aeee..ca8e25d9df 100644
--- a/elf/dlvsym.c
+++ b/elf/dlvsym.c
@@ -24,57 +24,82 @@
#include <dl-hash.h>
-void *
-__dlvsym (void *handle, const char *name, const char *version_str)
+struct dlvsym_args
{
- ElfW(Addr) caller = (ElfW(Addr)) __builtin_return_address (0);
- ElfW(Addr) loadbase;
+ /* The arguments to dlvsym_doit. */
+ void *handle;
+ const char *name;
struct r_found_version version;
- const ElfW(Sym) *ref = NULL;
- void doit (void)
+ ElfW(Addr) caller;
+ /* The return values of dlvsym_doit. */
+ ElfW(Addr) loadbase;
+ const ElfW(Sym) *ref;
+};
+
+
+static void
+dlvsym_doit (void *a)
+{
+ struct dlvsym_args *args = (struct dlvsym_args *)a;
+ args->ref = NULL;
+
+ if (args->handle == NULL)
+ /* Search the global scope. */
+ args->loadbase = _dl_lookup_versioned_symbol (args->name, &args->ref,
+ &(_dl_global_scope
+ ?: _dl_default_scope)[2],
+ NULL, &args->version, 0);
+ else if (args->handle == RTLD_NEXT)
{
- if (handle == NULL)
- /* Search the global scope. */
- loadbase = _dl_lookup_versioned_symbol
- (name, &ref, &(_dl_global_scope ?: _dl_default_scope)[2], NULL,
- &version, 0);
- else if (handle == RTLD_NEXT)
- {
- struct link_map *l, *match;
-
- /* Find the highest-addressed object that CALLER is not below. */
- match = NULL;
- for (l = _dl_loaded; l; l = l->l_next)
- if (caller >= l->l_addr && (!match || match->l_addr < l->l_addr))
- match = l;
-
- if (! match)
- _dl_signal_error (0, NULL, _("\
+ struct link_map *l, *match;
+
+ /* Find the highest-addressed object that CALLER is not below. */
+ match = NULL;
+ for (l = _dl_loaded; l; l = l->l_next)
+ if (args->caller >= l->l_addr && (!match || match->l_addr < l->l_addr))
+ match = l;
+
+ if (! match)
+ _dl_signal_error (0, NULL, _("\
RTLD_NEXT used in code not dynamically loaded"));
- l = match;
- while (l->l_loader)
- l = l->l_loader;
-
- loadbase = _dl_lookup_versioned_symbol_skip
- (name, &ref, &_dl_loaded, NULL, &version, l);
- }
- else
- {
- /* Search the scope of the given object. */
- struct link_map *map = handle;
- struct link_map *mapscope[2] = { map, NULL };
- loadbase = _dl_lookup_versioned_symbol
- (name, &ref, mapscope, map->l_name, &version, 0);
- }
+ l = match;
+ while (l->l_loader)
+ l = l->l_loader;
+
+ args->loadbase = _dl_lookup_versioned_symbol_skip (args->name,
+ &args->ref,
+ &_dl_loaded,
+ NULL, &args->version,
+ l);
+ }
+ else
+ {
+ /* Search the scope of the given object. */
+ struct link_map *map = args->handle;
+ struct link_map *mapscope[2] = { map, NULL };
+ args->loadbase = _dl_lookup_versioned_symbol (args->name, &args->ref,
+ mapscope, map->l_name,
+ &args->version, 0);
}
+}
+
+void *
+__dlvsym (void *handle, const char *name, const char *version_str)
+{
+ struct dlvsym_args args;
+
+ args.handle = handle;
+ args.name = name;
+ args.caller = (ElfW(Addr)) __builtin_return_address (0);
/* Compute hash value to the version string. */
- version.name = version_str;
- version.hash = _dl_elf_hash (version_str);
+ args.version.name = version_str;
+ args.version.hash = _dl_elf_hash (version_str);
/* We don't have a specific file where the symbol can be found. */
- version.filename = NULL;
+ args.version.filename = NULL;
- return _dlerror_run (doit) ? NULL : (void *) (loadbase + ref->st_value);
+ return (_dlerror_run (dlvsym_doit, &args)
+ ? NULL : (void *) (args.loadbase + args.ref->st_value));
}
weak_alias (__dlvsym, dlvsym)
diff --git a/elf/link.h b/elf/link.h
index 3934aed8e2..0e58996b04 100644
--- a/elf/link.h
+++ b/elf/link.h
@@ -238,21 +238,26 @@ extern void _dl_signal_error (int errcode,
error, *ERRSTRING is set to null. If there is an error, *ERRSTRING and
*OBJECT are set to the strings passed to _dl_signal_error, and the error
code passed is the return value. ERRSTRING if nonzero points to a
- malloc'ed string which the caller has to free after use. */
+ malloc'ed string which the caller has to free after use.
+ ARGS is passed as argument to OPERATE. */
extern int _dl_catch_error (char **errstring,
const char **object,
- void (*operate) (void));
+ void (*operate) (void *),
+ void *args);
/* Call OPERATE, receiving errors from `dl_signal_error'. Unlike
`_dl_catch_error' the operation is resumed after the OPERATE
- function returns. */
-extern void _dl_receive_error (receiver_fct fct, void (*operate) (void));
+ function returns.
+ ARGS is passed as argument to OPERATE. */
+extern void _dl_receive_error (receiver_fct fct, void (*operate) (void *),
+ void *args);
/* Helper function for <dlfcn.h> functions. Runs the OPERATE function via
_dl_catch_error. Returns zero for success, nonzero for failure; and
- arranges for `dlerror' to return the error details. */
-extern int _dlerror_run (void (*operate) (void));
+ arranges for `dlerror' to return the error details.
+ ARGS is passed as argument to OPERATE. */
+extern int _dlerror_run (void (*operate) (void *), void *args);
/* Open the shared object NAME and map in its segments.
diff --git a/elf/rtld.c b/elf/rtld.c
index d6bd516dfc..6f9737e060 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -140,6 +140,55 @@ _dl_start (void *arg)
void _start (void);
+/* Some helper functions. */
+
+/* Arguments to relocate_doit. */
+struct relocate_args
+{
+ struct link_map *l;
+ int lazy;
+};
+
+struct map_args
+{
+ /* Argument to map_doit. */
+ char *str;
+ /* Return value of map_doit. */
+ struct link_map *main_map;
+};
+
+/* Arguments to version_check_doit. */
+struct version_check_args
+{
+ struct link_map *main_map;
+ int doexit;
+};
+
+static void
+relocate_doit (void *a)
+{
+ struct relocate_args *args = (struct relocate_args *) a;
+
+ _dl_relocate_object (args->l, _dl_object_relocation_scope (args->l),
+ args->lazy);
+}
+
+static void
+map_doit (void *a)
+{
+ struct map_args *args = (struct map_args *)a;
+ args->main_map = _dl_map_object (NULL, args->str, lt_library, 0);
+}
+
+static void
+version_check_doit (void *a)
+{
+ struct version_check_args *args = (struct version_check_args *)a;
+ if (_dl_check_all_versions (args->main_map, 1) && args->doexit)
+ /* We cannot start the application. Abort now. */
+ _exit (1);
+}
+
unsigned int _dl_skip_args; /* Nonzero if we were run directly. */
static void
@@ -234,14 +283,13 @@ of this helper program; chances are you did not intend to run this program.\n",
if (mode == verify)
{
- void doit (void)
- {
- main_map = _dl_map_object (NULL, _dl_argv[0], lt_library, 0);
- }
char *err_str = NULL;
const char *obj_name __attribute__ ((unused));
+ struct map_args args;
- (void) _dl_catch_error (&err_str, &obj_name, doit);
+ args.str = _dl_argv[0];
+ (void) _dl_catch_error (&err_str, &obj_name, map_doit, &args);
+ main_map = args.main_map;
if (err_str != NULL)
{
free (err_str);
@@ -469,14 +517,10 @@ of this helper program; chances are you did not intend to run this program.\n",
/* Now let us see whether all libraries are available in the
versions we need. */
{
- void doit (void)
- {
- if (_dl_check_all_versions (main_map, 1) && mode == normal)
- /* We cannot start the application. Abort now. */
- _exit (1);
- }
-
- _dl_receive_error (print_missing_version, doit);
+ struct version_check_args args;
+ args.doexit = mode == normal;
+ args.main_map = main_map;
+ _dl_receive_error (print_missing_version, version_check_doit, &args);
}
if (mode != normal)
@@ -535,11 +579,10 @@ of this helper program; chances are you did not intend to run this program.\n",
else if (lazy >= 0)
{
/* We have to do symbol dependency testing. */
+ struct relocate_args args;
struct link_map *l;
- void doit (void)
- {
- _dl_relocate_object (l, _dl_object_relocation_scope (l), lazy);
- }
+
+ args.lazy = lazy;
l = _dl_loaded;
while (l->l_next)
@@ -548,7 +591,8 @@ of this helper program; chances are you did not intend to run this program.\n",
{
if (l != &_dl_rtld_map && l->l_opencount > 0)
{
- _dl_receive_error (print_unresolved, doit);
+ args.l = l;
+ _dl_receive_error (print_unresolved, relocate_doit, &args);
*_dl_global_scope_end = NULL;
}
l = l->l_prev;