mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-30 22:43:12 +03:00
* dlfcn/tst-dlinfo.c: New file.
* dlfcn/Makefile (tests): Add tst-dlinfo. ($(objpfx)tst-dlinfo): New target. * dlfcn/dlinfo.c: New file. * dlfcn/Makefile (libdl-routines): Add it. * dlfcn/Versions (libdl: GLIBC_2.3.3): Add dlinfo. * dlfcn/dlfcn.h [__USE_GNU]: Declare dlinfo. [__USE_GNU] (RTLD_DI_*): New enum constants. [__USE_GNU] (Dl_serpath, Dl_serinfo): New types. * elf/dl-load.c (cache_rpath): New inline function. (_dl_map_object): Use it. (_dl_rtld_di_serinfo): New function. * sysdeps/generic/ldsodefs.h: Declare it. * elf/Versions (ld: GLIBC_PRIVATE): Add it.
This commit is contained in:
16
ChangeLog
16
ChangeLog
@ -1,5 +1,21 @@
|
|||||||
2003-03-15 Roland McGrath <roland@redhat.com>
|
2003-03-15 Roland McGrath <roland@redhat.com>
|
||||||
|
|
||||||
|
* dlfcn/tst-dlinfo.c: New file.
|
||||||
|
* dlfcn/Makefile (tests): Add tst-dlinfo.
|
||||||
|
($(objpfx)tst-dlinfo): New target.
|
||||||
|
|
||||||
|
* dlfcn/dlinfo.c: New file.
|
||||||
|
* dlfcn/Makefile (libdl-routines): Add it.
|
||||||
|
* dlfcn/Versions (libdl: GLIBC_2.3.3): Add dlinfo.
|
||||||
|
* dlfcn/dlfcn.h [__USE_GNU]: Declare dlinfo.
|
||||||
|
[__USE_GNU] (RTLD_DI_*): New enum constants.
|
||||||
|
[__USE_GNU] (Dl_serpath, Dl_serinfo): New types.
|
||||||
|
* elf/dl-load.c (cache_rpath): New inline function.
|
||||||
|
(_dl_map_object): Use it.
|
||||||
|
(_dl_rtld_di_serinfo): New function.
|
||||||
|
* sysdeps/generic/ldsodefs.h: Declare it.
|
||||||
|
* elf/Versions (ld: GLIBC_PRIVATE): Add it.
|
||||||
|
|
||||||
* sysdeps/powerpc/elf/libc-start.c (AUX_VECTOR_INIT): Define it.
|
* sysdeps/powerpc/elf/libc-start.c (AUX_VECTOR_INIT): Define it.
|
||||||
(LIBC_START_MAIN, LIBC_START_MAIN_AUXVEC_ARG, MAIN_AUXVEC_ARG)
|
(LIBC_START_MAIN, LIBC_START_MAIN_AUXVEC_ARG, MAIN_AUXVEC_ARG)
|
||||||
(INIT_MAIN_ARGS): Define, and #include <sysdeps/generic/libc-start.c>.
|
(INIT_MAIN_ARGS): Define, and #include <sysdeps/generic/libc-start.c>.
|
||||||
|
7
NEWS
7
NEWS
@ -1,5 +1,5 @@
|
|||||||
GNU C Library NEWS -- history of user-visible changes. 2003-3-2
|
GNU C Library NEWS -- history of user-visible changes. 2003-3-15
|
||||||
Copyright (C) 1992-2002, 2003 Free Software Foundation, Inc.
|
Copyright (C) 1992-2002,2003 Free Software Foundation, Inc.
|
||||||
See the end for copying conditions.
|
See the end for copying conditions.
|
||||||
|
|
||||||
Please send GNU C library bug reports using the `glibcbug' script to
|
Please send GNU C library bug reports using the `glibcbug' script to
|
||||||
@ -7,6 +7,9 @@ Please send GNU C library bug reports using the `glibcbug' script to
|
|||||||
|
|
||||||
Version 2.3.3
|
Version 2.3.3
|
||||||
|
|
||||||
|
* New functions `dladdr1' and `dlinfo' in <dlfcn.h> provide more ways to
|
||||||
|
interrogate the dynamic linker, compatible with the Solaris interface.
|
||||||
|
|
||||||
* ELF thread-local storage support (TLS) now works on PowerPC and PowerPC64;
|
* ELF thread-local storage support (TLS) now works on PowerPC and PowerPC64;
|
||||||
implemented by Paul Mackerras, Steven Munroe, and Roland McGrath.
|
implemented by Paul Mackerras, Steven Munroe, and Roland McGrath.
|
||||||
|
|
||||||
|
@ -19,7 +19,8 @@
|
|||||||
subdir := dlfcn
|
subdir := dlfcn
|
||||||
headers := bits/dlfcn.h dlfcn.h
|
headers := bits/dlfcn.h dlfcn.h
|
||||||
extra-libs := libdl
|
extra-libs := libdl
|
||||||
libdl-routines := dlopen dlclose dlsym dlvsym dlerror dladdr dladdr1 eval
|
libdl-routines := dlopen dlclose dlsym dlvsym dlerror dladdr dladdr1 dlinfo \
|
||||||
|
eval
|
||||||
distribute := dlopenold.c glreflib1.c glreflib2.c failtestmod.c eval.c \
|
distribute := dlopenold.c glreflib1.c glreflib2.c failtestmod.c eval.c \
|
||||||
defaultmod1.c defaultmod2.c errmsg1mod.c modatexit.c \
|
defaultmod1.c defaultmod2.c errmsg1mod.c modatexit.c \
|
||||||
modcxaatexit.c modstatic.c \
|
modcxaatexit.c modstatic.c \
|
||||||
@ -37,7 +38,7 @@ libdl-shared-only-routines += eval
|
|||||||
|
|
||||||
ifeq (yes,$(build-shared))
|
ifeq (yes,$(build-shared))
|
||||||
tests = glrefmain failtest tst-dladdr default errmsg1 tstcxaatexit \
|
tests = glrefmain failtest tst-dladdr default errmsg1 tstcxaatexit \
|
||||||
bug-dlopen1 bug-dlsym1
|
bug-dlopen1 bug-dlsym1 tst-dlinfo
|
||||||
ifeq (yes,$(have-protected))
|
ifeq (yes,$(have-protected))
|
||||||
tests += tstatexit
|
tests += tstatexit
|
||||||
endif
|
endif
|
||||||
@ -74,6 +75,9 @@ $(objpfx)failtest.out: $(objpfx)failtestmod.so
|
|||||||
$(objpfx)tst-dladdr: $(libdl)
|
$(objpfx)tst-dladdr: $(libdl)
|
||||||
$(objpfx)tst-dladdr.out: $(objpfx)glreflib1.so
|
$(objpfx)tst-dladdr.out: $(objpfx)glreflib1.so
|
||||||
|
|
||||||
|
$(objpfx)tst-dlinfo: $(libdl)
|
||||||
|
$(objpfx)tst-dlinfo.out: $(objpfx)glreflib1.so
|
||||||
|
|
||||||
LDFLAGS-default = $(LDFLAGS-rdynamic)
|
LDFLAGS-default = $(LDFLAGS-rdynamic)
|
||||||
$(objpfx)default: $(libdl) $(objpfx)defaultmod1.so $(objpfx)defaultmod2.so
|
$(objpfx)default: $(libdl) $(objpfx)defaultmod1.so $(objpfx)defaultmod2.so
|
||||||
$(objpfx)defaultmod1.so: $(libdl) $(common-objpfx)libc_nonshared.a
|
$(objpfx)defaultmod1.so: $(libdl) $(common-objpfx)libc_nonshared.a
|
||||||
|
@ -6,6 +6,6 @@ libdl {
|
|||||||
dlopen; dlvsym;
|
dlopen; dlvsym;
|
||||||
}
|
}
|
||||||
GLIBC_2.3.3 {
|
GLIBC_2.3.3 {
|
||||||
dladdr1;
|
dladdr1; dlinfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,8 @@
|
|||||||
#define _DLFCN_H 1
|
#define _DLFCN_H 1
|
||||||
|
|
||||||
#include <features.h>
|
#include <features.h>
|
||||||
|
#define __need_size_t
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
/* Collect various system dependent definitions and declarations. */
|
/* Collect various system dependent definitions and declarations. */
|
||||||
#include <bits/dlfcn.h>
|
#include <bits/dlfcn.h>
|
||||||
@ -100,7 +102,57 @@ enum
|
|||||||
RTLD_DL_LINKMAP = 2
|
RTLD_DL_LINKMAP = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
|
||||||
|
/* Get information about the shared object HANDLE refers to.
|
||||||
|
REQUEST is from among the values below, and determines the use of ARG.
|
||||||
|
|
||||||
|
On success, returns zero. On failure, returns -1 and records an error
|
||||||
|
message to be fetched with `dlerror'. */
|
||||||
|
extern int dlinfo (void *__restrict __handle,
|
||||||
|
int __request, void *__restrict __arg);
|
||||||
|
|
||||||
|
/* These are the possible values for the REQUEST argument to `dlinfo'. */
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
/* Treat ARG as `struct link_map **';
|
||||||
|
store the `struct link_map *' for HANDLE there. */
|
||||||
|
RTLD_DI_LINKMAP = 2,
|
||||||
|
|
||||||
|
/* Treat ARG as `Dl_serinfo *' (see below), and fill in to describe the
|
||||||
|
directories that will be searched for dependencies of this object.
|
||||||
|
RTLD_DI_SERINFOSIZE fills in just the `dls_cnt' and `dls_size'
|
||||||
|
entries to indicate the size of the buffer that must be passed to
|
||||||
|
RTLD_DI_SERINFO to fill in the full information. */
|
||||||
|
RTLD_DI_SERINFO = 4,
|
||||||
|
RTLD_DI_SERINFOSIZE = 5,
|
||||||
|
|
||||||
|
/* Treat ARG as `char *', and store there the directory name used to
|
||||||
|
expand $ORIGIN in this shared object's dependency file names. */
|
||||||
|
RTLD_DI_ORIGIN = 6,
|
||||||
|
|
||||||
|
RTLD_DI_LMID = 1, /* Unsupported, defined by Solaris. */
|
||||||
|
RTLD_DI_CONFIGADDR = 3 /* Unsupported, defined by Solaris. */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* This is the type of elements in `Dl_serinfo', below.
|
||||||
|
The `dls_name' member points to space in the buffer passed to `dlinfo'. */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char *dls_name; /* Name of library search path directory. */
|
||||||
|
unsigned int dls_flags; /* Indicates where this directory came from. */
|
||||||
|
} Dl_serpath;
|
||||||
|
|
||||||
|
/* This is the structure that must be passed (by reference) to `dlinfo' for
|
||||||
|
the RTLD_DI_SERINFO and RTLD_DI_SERINFOSIZE requests. */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
size_t dls_size; /* Size in bytes of the whole buffer. */
|
||||||
|
unsigned int dls_cnt; /* Number of elements in `dls_serpath'. */
|
||||||
|
Dl_serpath dls_serpath[1]; /* Actually longer, dls_cnt elements. */
|
||||||
|
} Dl_serinfo;
|
||||||
|
#endif /* __USE_GNU */
|
||||||
|
|
||||||
|
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
|
||||||
|
87
dlfcn/dlinfo.c
Normal file
87
dlfcn/dlinfo.c
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/* dlinfo -- Get information from the dynamic linker.
|
||||||
|
Copyright (C) 2003 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 Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with the GNU C Library; if not, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307 USA. */
|
||||||
|
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <link.h>
|
||||||
|
#include <ldsodefs.h>
|
||||||
|
#include <libintl.h>
|
||||||
|
|
||||||
|
struct dlinfo_args
|
||||||
|
{
|
||||||
|
ElfW(Addr) caller;
|
||||||
|
void *handle;
|
||||||
|
int request;
|
||||||
|
void *arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
dlinfo_doit (void *argsblock)
|
||||||
|
{
|
||||||
|
struct dlinfo_args *const args = argsblock;
|
||||||
|
struct link_map *l = args->handle;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (args->handle == RTLD_SELF)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* Find the highest-addressed object that CALLER is not below. */
|
||||||
|
for (l = GL(dl_loaded); l != NULL; l = l->l_next)
|
||||||
|
if (caller >= l->l_map_start && caller < l->l_map_end)
|
||||||
|
/* There must be exactly one DSO for the range of the virtual
|
||||||
|
memory. Otherwise something is really broken. */
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (l == NULL)
|
||||||
|
_dl_signal_error (0, NULL, NULL, N_("\
|
||||||
|
RTLD_SELF used in code not dynamically loaded"));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch (args->request)
|
||||||
|
{
|
||||||
|
case RTLD_DI_LMID:
|
||||||
|
case RTLD_DI_CONFIGADDR:
|
||||||
|
default:
|
||||||
|
_dl_signal_error (0, NULL, NULL, N_("unsupported dlinfo request"));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RTLD_DI_LINKMAP:
|
||||||
|
*(struct link_map **) args->arg = l;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RTLD_DI_SERINFO:
|
||||||
|
_dl_rtld_di_serinfo (l, args->arg, false);
|
||||||
|
break;
|
||||||
|
case RTLD_DI_SERINFOSIZE:
|
||||||
|
_dl_rtld_di_serinfo (l, args->arg, true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RTLD_DI_ORIGIN:
|
||||||
|
strcpy (args->arg, l->l_origin);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
dlinfo (void *handle, int request, void *arg)
|
||||||
|
{
|
||||||
|
struct dlinfo_args args = { (ElfW(Addr)) RETURN_ADDRESS (0),
|
||||||
|
handle, request, arg };
|
||||||
|
return _dlerror_run (&dlinfo_doit, &args) ? -1 : 0;
|
||||||
|
}
|
96
dlfcn/tst-dlinfo.c
Normal file
96
dlfcn/tst-dlinfo.c
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/* Test for dlinfo.
|
||||||
|
Copyright (C) 2003 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 Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with the GNU C Library; if not, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307 USA. */
|
||||||
|
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <error.h>
|
||||||
|
|
||||||
|
#define TEST_FUNCTION do_test ()
|
||||||
|
|
||||||
|
static int
|
||||||
|
do_test (void)
|
||||||
|
{
|
||||||
|
int status = 0;
|
||||||
|
|
||||||
|
void *handle = dlopen ("glreflib1.so", RTLD_NOW);
|
||||||
|
if (handle == NULL)
|
||||||
|
error (EXIT_FAILURE, 0, "cannot load: glreflib1.so: %s", dlerror ());
|
||||||
|
|
||||||
|
#define TRY(req, arg) \
|
||||||
|
if (dlinfo (handle, req, arg) != 0) \
|
||||||
|
{ \
|
||||||
|
printf ("dlinfo failed for %s: %s\n", #req, dlerror ()); \
|
||||||
|
status = 1; \
|
||||||
|
} \
|
||||||
|
else
|
||||||
|
|
||||||
|
struct link_map *l;
|
||||||
|
TRY (RTLD_DI_LINKMAP, &l)
|
||||||
|
{
|
||||||
|
if (l != handle)
|
||||||
|
{
|
||||||
|
printf ("bogus link_map? %p != %p\n", l, handle);
|
||||||
|
status = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char origin[8192]; /* >= PATH_MAX, in theory */
|
||||||
|
TRY (RTLD_DI_ORIGIN, origin)
|
||||||
|
{
|
||||||
|
printf ("origin: %s\n", origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
Dl_serinfo counts;
|
||||||
|
TRY (RTLD_DI_SERINFOSIZE, &counts)
|
||||||
|
{
|
||||||
|
Dl_serinfo *buf = alloca (counts.dls_size);
|
||||||
|
buf->dls_cnt = counts.dls_cnt;
|
||||||
|
buf->dls_size = counts.dls_size;
|
||||||
|
printf ("%u library directories\n", buf->dls_cnt);
|
||||||
|
TRY (RTLD_DI_SERINFO, buf)
|
||||||
|
{
|
||||||
|
if (counts.dls_cnt != buf->dls_cnt)
|
||||||
|
{
|
||||||
|
printf ("??? became %u library directories\n", buf->dls_cnt);
|
||||||
|
status = 1;
|
||||||
|
}
|
||||||
|
for (unsigned int i = 0; i < buf->dls_cnt; ++i)
|
||||||
|
printf ("\t%#02x\t%s\n",
|
||||||
|
buf->dls_serpath[i].dls_flags,
|
||||||
|
buf->dls_serpath[i].dls_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long int lmid = 0xdeadbeefUL;
|
||||||
|
if (dlinfo (handle, RTLD_DI_LMID, &lmid) != 0)
|
||||||
|
printf ("dlinfo refuses RTLD_DI_LMID: %s\n", dlerror ());
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf ("dlinfo RTLD_DI_LMID worked? %#lx\n", lmid);
|
||||||
|
status = lmid == 0xdeadbeefUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef TRY
|
||||||
|
dlclose (handle);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "../test-skeleton.c"
|
@ -51,6 +51,6 @@ ld {
|
|||||||
_dl_unload_cache;
|
_dl_unload_cache;
|
||||||
_rtld_global; _dl_tls_symaddr; _dl_allocate_tls; _dl_deallocate_tls;
|
_rtld_global; _dl_tls_symaddr; _dl_allocate_tls; _dl_deallocate_tls;
|
||||||
_dl_get_tls_static_info; _dl_allocate_tls_init;
|
_dl_get_tls_static_info; _dl_allocate_tls_init;
|
||||||
_dl_get_origin; _dl_tls_setup;
|
_dl_get_origin; _dl_tls_setup; _dl_rtld_di_serinfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
175
elf/dl-load.c
175
elf/dl-load.c
@ -576,6 +576,34 @@ decompose_rpath (struct r_search_path_struct *sps,
|
|||||||
sps->malloced = 1;
|
sps->malloced = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Make sure cached path information is stored in *SP
|
||||||
|
and return true if there are any paths to search there. */
|
||||||
|
static inline bool
|
||||||
|
cache_rpath (struct link_map *l,
|
||||||
|
struct r_search_path_struct *sp,
|
||||||
|
int tag,
|
||||||
|
const char *what)
|
||||||
|
{
|
||||||
|
if (sp->dirs == (void *) -1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (sp->dirs != NULL)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (l->l_info[tag] == NULL)
|
||||||
|
{
|
||||||
|
/* There is no path. */
|
||||||
|
sp->dirs = (void *) -1;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure the cache information is available. */
|
||||||
|
decompose_rpath (sp, (const char *) (D_PTR (l, l_info[DT_STRTAB])
|
||||||
|
+ l->l_info[tag]->d_un.d_val),
|
||||||
|
l, what);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
internal_function
|
internal_function
|
||||||
@ -1747,29 +1775,9 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
|
|||||||
/* First try the DT_RPATH of the dependent object that caused NAME
|
/* First try the DT_RPATH of the dependent object that caused NAME
|
||||||
to be loaded. Then that object's dependent, and on up. */
|
to be loaded. Then that object's dependent, and on up. */
|
||||||
for (l = loader; fd == -1 && l; l = l->l_loader)
|
for (l = loader; fd == -1 && l; l = l->l_loader)
|
||||||
{
|
if (cache_rpath (l, &l->l_rpath_dirs, DT_RPATH, "RPATH"))
|
||||||
if (l->l_rpath_dirs.dirs == NULL)
|
fd = open_path (name, namelen, preloaded, &l->l_rpath_dirs,
|
||||||
{
|
&realname, &fb);
|
||||||
if (l->l_info[DT_RPATH] == NULL)
|
|
||||||
{
|
|
||||||
/* There is no path. */
|
|
||||||
l->l_rpath_dirs.dirs = (void *) -1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Make sure the cache information is available. */
|
|
||||||
size_t ptrval = (D_PTR (l, l_info[DT_STRTAB])
|
|
||||||
+ l->l_info[DT_RPATH]->d_un.d_val);
|
|
||||||
decompose_rpath (&l->l_rpath_dirs,
|
|
||||||
(const char *) ptrval, l, "RPATH");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (l->l_rpath_dirs.dirs != (void *) -1)
|
|
||||||
fd = open_path (name, namelen, preloaded, &l->l_rpath_dirs,
|
|
||||||
&realname, &fb);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If dynamically linked, try the DT_RPATH of the executable
|
/* If dynamically linked, try the DT_RPATH of the executable
|
||||||
itself. */
|
itself. */
|
||||||
@ -1785,37 +1793,12 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
|
|||||||
fd = open_path (name, namelen, preloaded, &env_path_list,
|
fd = open_path (name, namelen, preloaded, &env_path_list,
|
||||||
&realname, &fb);
|
&realname, &fb);
|
||||||
|
|
||||||
/* Look at the RUNPATH information for this binary.
|
/* Look at the RUNPATH information for this binary. */
|
||||||
|
if (fd == -1 && loader != NULL
|
||||||
Note that this is no real loop. 'while' is used only to enable
|
&& cache_rpath (loader, &loader->l_runpath_dirs,
|
||||||
us to use 'break' instead of a 'goto' to jump to the end. The
|
DT_RUNPATH, "RUNPATH"))
|
||||||
loop is always left after the first round. */
|
fd = open_path (name, namelen, preloaded,
|
||||||
while (fd == -1 && loader != NULL
|
&loader->l_runpath_dirs, &realname, &fb);
|
||||||
&& loader->l_runpath_dirs.dirs != (void *) -1)
|
|
||||||
{
|
|
||||||
if (loader->l_runpath_dirs.dirs == NULL)
|
|
||||||
{
|
|
||||||
if (loader->l_info[DT_RUNPATH] == NULL)
|
|
||||||
{
|
|
||||||
/* No RUNPATH. */
|
|
||||||
loader->l_runpath_dirs.dirs = (void *) -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Make sure the cache information is available. */
|
|
||||||
size_t ptrval = (D_PTR (loader, l_info[DT_STRTAB])
|
|
||||||
+ loader->l_info[DT_RUNPATH]->d_un.d_val);
|
|
||||||
decompose_rpath (&loader->l_runpath_dirs,
|
|
||||||
(const char *) ptrval, loader, "RUNPATH");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (loader->l_runpath_dirs.dirs != (void *) -1)
|
|
||||||
fd = open_path (name, namelen, preloaded,
|
|
||||||
&loader->l_runpath_dirs, &realname, &fb);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fd == -1
|
if (fd == -1
|
||||||
&& (__builtin_expect (! preloaded, 1)
|
&& (__builtin_expect (! preloaded, 1)
|
||||||
@ -1939,3 +1922,87 @@ cannot create shared object descriptor"));
|
|||||||
return _dl_map_object_from_fd (name, fd, &fb, realname, loader, type, mode);
|
return _dl_map_object_from_fd (name, fd, &fb, realname, loader, type, mode);
|
||||||
}
|
}
|
||||||
INTDEF (_dl_map_object)
|
INTDEF (_dl_map_object)
|
||||||
|
|
||||||
|
void
|
||||||
|
internal_function
|
||||||
|
_dl_rtld_di_serinfo (struct link_map *loader, Dl_serinfo *si, bool counting)
|
||||||
|
{
|
||||||
|
if (counting)
|
||||||
|
{
|
||||||
|
si->dls_cnt = 0;
|
||||||
|
si->dls_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int idx = 0;
|
||||||
|
char *allocptr = (char *) &si->dls_serpath[si->dls_cnt];
|
||||||
|
inline void add_path (const struct r_search_path_struct *sps,
|
||||||
|
unsigned int flags)
|
||||||
|
# define add_path(sps, flags) add_path(sps, 0) /* XXX */
|
||||||
|
{
|
||||||
|
if (sps->dirs != (void *) -1)
|
||||||
|
{
|
||||||
|
struct r_search_path_elem **dirs = sps->dirs;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
const struct r_search_path_elem *const r = *dirs++;
|
||||||
|
if (counting)
|
||||||
|
{
|
||||||
|
si->dls_cnt++;
|
||||||
|
si->dls_size += r->dirnamelen;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dl_serpath *const sp = &si->dls_serpath[idx++];
|
||||||
|
sp->dls_name = allocptr;
|
||||||
|
allocptr = __mempcpy (allocptr,
|
||||||
|
r->dirname, r->dirnamelen - 1);
|
||||||
|
*allocptr++ = '\0';
|
||||||
|
sp->dls_flags = flags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (*dirs != NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* When the object has the RUNPATH information we don't use any RPATHs. */
|
||||||
|
if (loader->l_info[DT_RUNPATH] == NULL)
|
||||||
|
{
|
||||||
|
/* First try the DT_RPATH of the dependent object that caused NAME
|
||||||
|
to be loaded. Then that object's dependent, and on up. */
|
||||||
|
|
||||||
|
struct link_map *l = loader;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (cache_rpath (l, &l->l_rpath_dirs, DT_RPATH, "RPATH"))
|
||||||
|
add_path (&l->l_rpath_dirs, XXX_RPATH);
|
||||||
|
l = l->l_loader;
|
||||||
|
}
|
||||||
|
while (l != NULL);
|
||||||
|
|
||||||
|
/* If dynamically linked, try the DT_RPATH of the executable itself. */
|
||||||
|
l = GL(dl_loaded);
|
||||||
|
if (l != NULL && l->l_type != lt_loaded && l != loader)
|
||||||
|
if (cache_rpath (l, &l->l_rpath_dirs, DT_RPATH, "RPATH"))
|
||||||
|
add_path (&l->l_rpath_dirs, XXX_RPATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try the LD_LIBRARY_PATH environment variable. */
|
||||||
|
add_path (&env_path_list, XXX_ENV);
|
||||||
|
|
||||||
|
/* Look at the RUNPATH information for this binary. */
|
||||||
|
if (cache_rpath (loader, &loader->l_runpath_dirs, DT_RUNPATH, "RUNPATH"))
|
||||||
|
add_path (&loader->l_runpath_dirs, XXX_RUNPATH);
|
||||||
|
|
||||||
|
/* XXX
|
||||||
|
Here is where ld.so.cache gets checked, but we don't have
|
||||||
|
a way to indicate that in the results for Dl_serinfo. */
|
||||||
|
|
||||||
|
/* Finally, try the default path. */
|
||||||
|
if (!(loader->l_flags_1 & DF_1_NODEFLIB))
|
||||||
|
add_path (&rtld_search_dirs, XXX_default);
|
||||||
|
|
||||||
|
if (counting)
|
||||||
|
/* Count the struct size before the string area, which we didn't
|
||||||
|
know before we completed dls_cnt. */
|
||||||
|
si->dls_size += (char *) &si->dls_serpath[si->dls_cnt] - (char *) si;
|
||||||
|
}
|
||||||
|
@ -554,6 +554,16 @@ extern void _dl_setup_hash (struct link_map *map)
|
|||||||
internal_function attribute_hidden;
|
internal_function attribute_hidden;
|
||||||
|
|
||||||
|
|
||||||
|
/* Collect the directories in the search path for LOADER's dependencies.
|
||||||
|
The data structure is defined in <dlfcn.h>. If COUNTING is true,
|
||||||
|
SI->dls_cnt and SI->dls_size are set; if false, those must be as set
|
||||||
|
by a previous call with COUNTING set, and SI must point to SI->dls_size
|
||||||
|
bytes to be used in filling in the result. */
|
||||||
|
extern void _dl_rtld_di_serinfo (struct link_map *loader,
|
||||||
|
Dl_serinfo *si, bool counting)
|
||||||
|
internal_function;
|
||||||
|
|
||||||
|
|
||||||
/* Search loaded objects' symbol tables for a definition of the symbol
|
/* Search loaded objects' symbol tables for a definition of the symbol
|
||||||
referred to by UNDEF. *SYM is the symbol table entry containing the
|
referred to by UNDEF. *SYM is the symbol table entry containing the
|
||||||
reference; it is replaced with the defining symbol, and the base load
|
reference; it is replaced with the defining symbol, and the base load
|
||||||
|
Reference in New Issue
Block a user