Skip to content

Commit

Permalink
* dlfcn/tst-dlinfo.c: New file.
Browse files Browse the repository at this point in the history
	* 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.
  • Loading branch information
Roland McGrath committed Mar 15, 2003
1 parent 124dcac commit 45e4762
Show file tree
Hide file tree
Showing 10 changed files with 396 additions and 61 deletions.
16 changes: 16 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
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.
(LIBC_START_MAIN, LIBC_START_MAIN_AUXVEC_ARG, MAIN_AUXVEC_ARG)
(INIT_MAIN_ARGS): Define, and #include <sysdeps/generic/libc-start.c>.
Expand Down
7 changes: 5 additions & 2 deletions NEWS
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
GNU C Library NEWS -- history of user-visible changes. 2003-3-2
Copyright (C) 1992-2002, 2003 Free Software Foundation, Inc.
GNU C Library NEWS -- history of user-visible changes. 2003-3-15
Copyright (C) 1992-2002,2003 Free Software Foundation, Inc.
See the end for copying conditions.

Please send GNU C library bug reports using the `glibcbug' script to
<bugs@gnu.org>. Please send questions and suggestions to <bug-glibc@gnu.org>.

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;
implemented by Paul Mackerras, Steven Munroe, and Roland McGrath.

Expand Down
8 changes: 6 additions & 2 deletions dlfcn/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
subdir := dlfcn
headers := bits/dlfcn.h dlfcn.h
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 \
defaultmod1.c defaultmod2.c errmsg1mod.c modatexit.c \
modcxaatexit.c modstatic.c \
Expand All @@ -37,7 +38,7 @@ libdl-shared-only-routines += eval

ifeq (yes,$(build-shared))
tests = glrefmain failtest tst-dladdr default errmsg1 tstcxaatexit \
bug-dlopen1 bug-dlsym1
bug-dlopen1 bug-dlsym1 tst-dlinfo
ifeq (yes,$(have-protected))
tests += tstatexit
endif
Expand Down Expand Up @@ -74,6 +75,9 @@ $(objpfx)failtest.out: $(objpfx)failtestmod.so
$(objpfx)tst-dladdr: $(libdl)
$(objpfx)tst-dladdr.out: $(objpfx)glreflib1.so

$(objpfx)tst-dlinfo: $(libdl)
$(objpfx)tst-dlinfo.out: $(objpfx)glreflib1.so

LDFLAGS-default = $(LDFLAGS-rdynamic)
$(objpfx)default: $(libdl) $(objpfx)defaultmod1.so $(objpfx)defaultmod2.so
$(objpfx)defaultmod1.so: $(libdl) $(common-objpfx)libc_nonshared.a
Expand Down
2 changes: 1 addition & 1 deletion dlfcn/Versions
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ libdl {
dlopen; dlvsym;
}
GLIBC_2.3.3 {
dladdr1;
dladdr1; dlinfo;
}
}
54 changes: 53 additions & 1 deletion dlfcn/dlfcn.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#define _DLFCN_H 1

#include <features.h>
#define __need_size_t
#include <stddef.h>

/* Collect various system dependent definitions and declarations. */
#include <bits/dlfcn.h>
Expand Down Expand Up @@ -100,7 +102,57 @@ enum
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

Expand Down
87 changes: 87 additions & 0 deletions dlfcn/dlinfo.c
Original file line number Diff line number Diff line change
@@ -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 changes: 96 additions & 0 deletions dlfcn/tst-dlinfo.c
Original file line number Diff line number Diff line change
@@ -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"
2 changes: 1 addition & 1 deletion elf/Versions
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,6 @@ ld {
_dl_unload_cache;
_rtld_global; _dl_tls_symaddr; _dl_allocate_tls; _dl_deallocate_tls;
_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;
}
}
Loading

0 comments on commit 45e4762

Please sign in to comment.