* elf/tst-tls-dlinfo.c: New file.

* elf/Makefile (tests): Add it.
	($(objpfx)tst-tls-dlinfo): Depend on $(libdl).
	($(objpfx)tst-tls-dlinfo.out): Depend on $(objpfx)tst-tlsmod2.so.

	* dlfcn/dlfcn.h (RTLD_DI_PROFILENAME, RTLD_DI_PROFILEOUT): New enum
	values, reserve unsupported requested names used on Solaris.
	(RTLD_DI_TLS_MODID, RTLD_DI_TLS_DATA): New enum values.
	(RTLD_DI_MAX): Likewise.
	* dlfcn/dlinfo.c (dlinfo_doit): Handle RTLD_DI_TLS_MODID and
	RTLD_DI_TLS_DATA.

	* elf/dl-tls.c (_dl_tls_get_addr_soft): New function.
	* sysdeps/generic/ldsodefs.h: Declare it.
	* elf/Versions (ld: GLIBC_PRIVATE): Add it.
	* elf/link.h (struct dl_phdr_info): New members dlpi_tls_modid,
	dlpi_tls_data.
	* elf/dl-iteratephdr.c (__dl_iterate_phdr): Fill them in.

	* include/link.h: Don't copy contents from elf/link.h.
	Instead, #include it while #define'ing around link_map.
	* elf/dl-debug.c (_dl_debug_initialize): Add a cast.
	Add bogus extern decl to verify link_map members.
	* elf/loadtest.c (MAPS): New macro, cast _r_debug._r_map.
	(OUT, main): Use it in place of _r_debug._r_map.
	* elf/unload.c: Likewise.
	* elf/unload2.c: Likewise.
	* elf/neededtest.c (check_loaded_objects): Likewise.
	* elf/neededtest2.c (check_loaded_objects): Likewise.
	* elf/neededtest3.c (check_loaded_objects): Likewise.
	* elf/neededtest4.c (check_loaded_objects): Likewise.
	* elf/circleload1.c (check_loaded_objects): Likewise.
This commit is contained in:
Roland McGrath 2006-03-01 06:18:49 +00:00
parent 0b890d59bd
commit d78efd9f36
20 changed files with 313 additions and 136 deletions

View File

@ -1,5 +1,38 @@
2006-02-28 Roland McGrath <roland@redhat.com> 2006-02-28 Roland McGrath <roland@redhat.com>
* elf/tst-tls-dlinfo.c: New file.
* elf/Makefile (tests): Add it.
($(objpfx)tst-tls-dlinfo): Depend on $(libdl).
($(objpfx)tst-tls-dlinfo.out): Depend on $(objpfx)tst-tlsmod2.so.
* dlfcn/dlfcn.h (RTLD_DI_PROFILENAME, RTLD_DI_PROFILEOUT): New enum
values, reserve unsupported requested names used on Solaris.
(RTLD_DI_TLS_MODID, RTLD_DI_TLS_DATA): New enum values.
(RTLD_DI_MAX): Likewise.
* dlfcn/dlinfo.c (dlinfo_doit): Handle RTLD_DI_TLS_MODID and
RTLD_DI_TLS_DATA.
* elf/dl-tls.c (_dl_tls_get_addr_soft): New function.
* sysdeps/generic/ldsodefs.h: Declare it.
* elf/Versions (ld: GLIBC_PRIVATE): Add it.
* elf/link.h (struct dl_phdr_info): New members dlpi_tls_modid,
dlpi_tls_data.
* elf/dl-iteratephdr.c (__dl_iterate_phdr): Fill them in.
* include/link.h: Don't copy contents from elf/link.h.
Instead, #include it while #define'ing around link_map.
* elf/dl-debug.c (_dl_debug_initialize): Add a cast.
Add bogus extern decl to verify link_map members.
* elf/loadtest.c (MAPS): New macro, cast _r_debug._r_map.
(OUT, main): Use it in place of _r_debug._r_map.
* elf/unload.c: Likewise.
* elf/unload2.c: Likewise.
* elf/neededtest.c (check_loaded_objects): Likewise.
* elf/neededtest2.c (check_loaded_objects): Likewise.
* elf/neededtest3.c (check_loaded_objects): Likewise.
* elf/neededtest4.c (check_loaded_objects): Likewise.
* elf/circleload1.c (check_loaded_objects): Likewise.
* nscd/nscd_helper.c: Include <time.h> for `time' declaration. * nscd/nscd_helper.c: Include <time.h> for `time' declaration.
* include/fcntl.h: Declare __openat, __open64. Use libc_hidden_proto. * include/fcntl.h: Declare __openat, __open64. Use libc_hidden_proto.

View File

@ -1,5 +1,6 @@
/* User functions for run-time dynamic loading. /* User functions for run-time dynamic loading.
Copyright (C) 1995-1999,2000,2001,2003,2004 Free Software Foundation, Inc. Copyright (C) 1995-1999,2000,2001,2003,2004,2006
Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -135,6 +136,8 @@ enum
store the `struct link_map *' for HANDLE there. */ store the `struct link_map *' for HANDLE there. */
RTLD_DI_LINKMAP = 2, RTLD_DI_LINKMAP = 2,
RTLD_DI_CONFIGADDR = 3, /* Unsupported, defined by Solaris. */
/* Treat ARG as `Dl_serinfo *' (see below), and fill in to describe the /* Treat ARG as `Dl_serinfo *' (see below), and fill in to describe the
directories that will be searched for dependencies of this object. directories that will be searched for dependencies of this object.
RTLD_DI_SERINFOSIZE fills in just the `dls_cnt' and `dls_size' RTLD_DI_SERINFOSIZE fills in just the `dls_cnt' and `dls_size'
@ -147,7 +150,21 @@ enum
expand $ORIGIN in this shared object's dependency file names. */ expand $ORIGIN in this shared object's dependency file names. */
RTLD_DI_ORIGIN = 6, RTLD_DI_ORIGIN = 6,
RTLD_DI_CONFIGADDR = 3 /* Unsupported, defined by Solaris. */ RTLD_DI_PROFILENAME = 7, /* Unsupported, defined by Solaris. */
RTLD_DI_PROFILEOUT = 8, /* Unsupported, defined by Solaris. */
/* Treat ARG as `size_t *', and store there the TLS module ID
of this object's PT_TLS segment, as used in TLS relocations;
store zero if this object does not define a PT_TLS segment. */
RTLD_DI_TLS_MODID = 9,
/* Treat ARG as `void **', and store there a pointer to the calling
thread's TLS block corresponding to this object's PT_TLS segment.
Store a null pointer if this object does not define a PT_TLS
segment, or if the calling thread has not allocated a block for it. */
RTLD_DI_TLS_DATA = 10,
RTLD_DI_MAX = 10,
}; };

View File

@ -1,5 +1,5 @@
/* dlinfo -- Get information from the dynamic linker. /* dlinfo -- Get information from the dynamic linker.
Copyright (C) 2003, 2004 Free Software Foundation, Inc. Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -32,6 +32,10 @@ dlinfo (void *handle, int request, void *arg)
#else #else
# ifdef USE_TLS
# include <dl-tls.h>
# endif
struct dlinfo_args struct dlinfo_args
{ {
ElfW(Addr) caller; ElfW(Addr) caller;
@ -90,6 +94,24 @@ RTLD_SELF used in code not dynamically loaded"));
case RTLD_DI_ORIGIN: case RTLD_DI_ORIGIN:
strcpy (args->arg, l->l_origin); strcpy (args->arg, l->l_origin);
break; break;
case RTLD_DI_TLS_MODID:
*(size_t *) args->arg = 0;
#ifdef USE_TLS
*(size_t *) args->arg = l->l_tls_modid;
#endif
break;
case RTLD_DI_TLS_DATA:
{
void *data = NULL;
#ifdef USE_TLS
if (l->l_tls_modid != 0)
data = _dl_tls_get_addr_soft (l);
#endif
*(void **) args->arg = data;
break;
}
} }
} }

View File

@ -163,9 +163,11 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
neededtest3 neededtest4 unload2 lateglobal initfirst global \ neededtest3 neededtest4 unload2 lateglobal initfirst global \
restest2 next dblload dblunload reldep5 reldep6 reldep7 reldep8 \ restest2 next dblload dblunload reldep5 reldep6 reldep7 reldep8 \
circleload1 tst-tls3 tst-tls4 tst-tls5 tst-tls6 tst-tls7 tst-tls8 \ circleload1 tst-tls3 tst-tls4 tst-tls5 tst-tls6 tst-tls7 tst-tls8 \
tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-tls15 tst-align \ tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-tls15 \
tst-align2 $(tests-execstack-$(have-z-execstack)) tst-dlmodcount \ tst-tls-dlinfo \
tst-dlopenrpath tst-deep1 tst-dlmopen1 tst-dlmopen2 tst-dlmopen3 \ tst-align tst-align2 $(tests-execstack-$(have-z-execstack)) \
tst-dlmodcount tst-dlopenrpath tst-deep1 \
tst-dlmopen1 tst-dlmopen2 tst-dlmopen3 \
unload3 unload4 unload5 unload6 tst-audit1 tst-global1 order2 \ unload3 unload4 unload5 unload6 tst-audit1 tst-global1 order2 \
tst-stackguard1 tst-stackguard1
# reldep9 # reldep9
@ -700,6 +702,11 @@ $(objpfx)tst-tls14.out: $(objpfx)tst-tlsmod14b.so
$(objpfx)tst-tls15: $(libdl) $(objpfx)tst-tls15: $(libdl)
$(objpfx)tst-tls15.out: $(objpfx)tst-tlsmod15a.so $(objpfx)tst-tlsmod15b.so $(objpfx)tst-tls15.out: $(objpfx)tst-tlsmod15a.so $(objpfx)tst-tlsmod15b.so
$(objpfx)tst-tls-dlinfo: $(libdl)
$(objpfx)tst-tls-dlinfo.out: $(objpfx)tst-tlsmod2.so
CFLAGS-tst-align.c = $(stack-align-test-flags) CFLAGS-tst-align.c = $(stack-align-test-flags)
CFLAGS-tst-align2.c = $(stack-align-test-flags) CFLAGS-tst-align2.c = $(stack-align-test-flags)
CFLAGS-tst-alignmod.c = $(stack-align-test-flags) CFLAGS-tst-alignmod.c = $(stack-align-test-flags)

View File

@ -57,6 +57,7 @@ ld {
_dl_allocate_tls; _dl_deallocate_tls; _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_tls_setup; _dl_rtld_di_serinfo; _dl_tls_setup; _dl_rtld_di_serinfo;
_dl_tls_get_addr_soft;
_dl_make_stack_executable; _dl_make_stack_executable;
# Only here for gdb while a better method is developed. # Only here for gdb while a better method is developed.
_dl_debug_state; _dl_debug_state;

View File

@ -5,6 +5,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#define MAPS ((struct link_map *) _r_debug.r_map)
static int static int
check_loaded_objects (const char **loaded) check_loaded_objects (const char **loaded)
{ {
@ -24,7 +26,7 @@ check_loaded_objects (const char **loaded)
printf(" Name\n"); printf(" Name\n");
printf(" --------------------------------------------------------\n"); printf(" --------------------------------------------------------\n");
for (lm = _r_debug.r_map; lm; lm = lm->l_next) for (lm = MAPS; lm; lm = lm->l_next)
{ {
if (lm->l_name && lm->l_name[0]) if (lm->l_name && lm->l_name[0])
printf(" %s, count = %d\n", lm->l_name, (int) lm->l_direct_opencount); printf(" %s, count = %d\n", lm->l_name, (int) lm->l_direct_opencount);

View File

@ -1,5 +1,6 @@
/* Communicate dynamic linker state to the debugger at runtime. /* Communicate dynamic linker state to the debugger at runtime.
Copyright (C) 1996, 1998,2000,2002,2004,2005 Free Software Foundation, Inc. Copyright (C) 1996, 1998,2000,2002,2004,2005,2006
Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -19,6 +20,18 @@
#include <ldsodefs.h> #include <ldsodefs.h>
/* These are the members in the public `struct link_map' type.
Sanity check that the internal type and the public type match. */
#define VERIFY_MEMBER(name) \
(offsetof (struct link_map_public, name) == offsetof (struct link_map, name))
extern const int verify_link_map_members[(VERIFY_MEMBER (l_addr)
&& VERIFY_MEMBER (l_name)
&& VERIFY_MEMBER (l_ld)
&& VERIFY_MEMBER (l_next)
&& VERIFY_MEMBER (l_prev))
? 1 : -1];
/* This structure communicates dl state to the debugger. The debugger /* This structure communicates dl state to the debugger. The debugger
normally finds it via the DT_DEBUG entry in the dynamic section, but in normally finds it via the DT_DEBUG entry in the dynamic section, but in
a statically-linked program there is no dynamic section for the debugger a statically-linked program there is no dynamic section for the debugger
@ -46,7 +59,7 @@ _dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns)
/* Tell the debugger where to find the map of loaded objects. */ /* Tell the debugger where to find the map of loaded objects. */
r->r_version = 1 /* R_DEBUG_VERSION XXX */; r->r_version = 1 /* R_DEBUG_VERSION XXX */;
r->r_ldbase = ldbase ?: _r_debug.r_ldbase; r->r_ldbase = ldbase ?: _r_debug.r_ldbase;
r->r_map = GL(dl_ns)[ns]._ns_loaded; r->r_map = (void *) GL(dl_ns)[ns]._ns_loaded;
r->r_brk = (ElfW(Addr)) &_dl_debug_state; r->r_brk = (ElfW(Addr)) &_dl_debug_state;
} }

View File

@ -1,5 +1,5 @@
/* Get loaded objects program headers. /* Get loaded objects program headers.
Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. Copyright (C) 2001,2002,2003,2004,2006 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2001. Contributed by Jakub Jelinek <jakub@redhat.com>, 2001.
@ -68,6 +68,13 @@ __dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info,
info.dlpi_phnum = l->l_phnum; info.dlpi_phnum = l->l_phnum;
info.dlpi_adds = GL(dl_load_adds); info.dlpi_adds = GL(dl_load_adds);
info.dlpi_subs = GL(dl_load_adds) - nloaded; info.dlpi_subs = GL(dl_load_adds) - nloaded;
info.dlpi_tls_modid = 0;
info.dlpi_tls_data = NULL;
#ifdef USE_TLS
info.dlpi_tls_modid = l->l_tls_modid;
if (info.dlpi_tls_modid != 0)
info.dlpi_tls_data = _dl_tls_get_addr_soft (l);
#endif
ret = callback (&info, sizeof (struct dl_phdr_info), data); ret = callback (&info, sizeof (struct dl_phdr_info), data);
if (ret) if (ret)
break; break;

View File

@ -1,5 +1,5 @@
/* Thread-local storage handling in the ELF dynamic linker. Generic version. /* Thread-local storage handling in the ELF dynamic linker. Generic version.
Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. Copyright (C) 2002,2003,2004,2005,2006 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -735,9 +735,53 @@ __tls_get_addr (GET_ADDR_ARGS)
# endif # endif
/* Look up the module's TLS block as for __tls_get_addr,
but never touch anything. Return null if it's not allocated yet. */
void *
internal_function
_dl_tls_get_addr_soft (struct link_map *l)
{
if (__builtin_expect (l->l_tls_modid == 0, 0))
/* This module has no TLS segment. */
return NULL;
dtv_t *dtv = THREAD_DTV ();
if (__builtin_expect (dtv[0].counter != GL(dl_tls_generation), 0))
{
/* This thread's DTV is not completely current,
but it might already cover this module. */
if (l->l_tls_modid >= dtv[-1].counter)
/* Nope. */
return NULL;
size_t idx = l->l_tls_modid;
struct dtv_slotinfo_list *listp = GL(dl_tls_dtv_slotinfo_list);
while (idx >= listp->len)
{
idx -= listp->len;
listp = listp->next;
}
/* We've reached the slot for this module.
If its generation counter is higher than the DTV's,
this thread does not know about this module yet. */
if (dtv[0].counter < listp->slotinfo[idx].gen)
return NULL;
}
void *data = dtv[l->l_tls_modid].pointer.val;
if (__builtin_expect (data == TLS_DTV_UNALLOCATED, 0))
/* The DTV is current, but this thread has not yet needed
to allocate this module's segment. */
data = NULL;
return data;
}
void void
_dl_add_to_slotinfo (struct link_map *l) _dl_add_to_slotinfo (struct link_map *l)
{ {
/* Now that we know the object is loaded successfully add /* Now that we know the object is loaded successfully add
modules containing TLS data to the dtv info table. We modules containing TLS data to the dtv info table. We

View File

@ -1,6 +1,6 @@
/* Data structure for communication from the run-time dynamic linker for /* Data structure for communication from the run-time dynamic linker for
loaded ELF shared objects. loaded ELF shared objects.
Copyright (C) 1995-2001, 2004, 2005 Free Software Foundation, Inc. Copyright (C) 1995-2001, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -135,7 +135,6 @@ enum
la_symbind call. */ la_symbind call. */
}; };
struct dl_phdr_info struct dl_phdr_info
{ {
ElfW(Addr) dlpi_addr; ElfW(Addr) dlpi_addr;
@ -143,15 +142,24 @@ struct dl_phdr_info
const ElfW(Phdr) *dlpi_phdr; const ElfW(Phdr) *dlpi_phdr;
ElfW(Half) dlpi_phnum; ElfW(Half) dlpi_phnum;
/* Note: the next two members were introduced after the first /* Note: Following members were introduced after the first
version of this structure was available. Check the SIZE version of this structure was available. Check the SIZE
argument passed to the dl_iterate_phdr() callback to determine argument passed to the dl_iterate_phdr callback to determine
whether or not they are provided. */ whether or not each later member is available. */
/* Incremented when a new object may have been added. */ /* Incremented when a new object may have been added. */
unsigned long long int dlpi_adds; unsigned long long int dlpi_adds;
/* Incremented when an object may have been removed. */ /* Incremented when an object may have been removed. */
unsigned long long int dlpi_subs; unsigned long long int dlpi_subs;
/* If there is a PT_TLS segment, its module ID as used in
TLS relocations, else zero. */
size_t dlpi_tls_modid;
/* The address of the calling thread's instance of this module's
PT_TLS segment, if it has one and it has been allocated
in the calling thread, otherwise a null pointer. */
void *dlpi_tls_data;
}; };
__BEGIN_DECLS __BEGIN_DECLS

View File

@ -70,8 +70,10 @@ static const struct
#include <include/link.h> #include <include/link.h>
#define MAPS ((struct link_map *) _r_debug.r_map)
#define OUT \ #define OUT \
for (map = _r_debug.r_map; map != NULL; map = map->l_next) \ for (map = MAPS; map != NULL; map = map->l_next) \
if (map->l_type == lt_loaded) \ if (map->l_type == lt_loaded) \
printf ("name = \"%s\", direct_opencount = %d\n", \ printf ("name = \"%s\", direct_opencount = %d\n", \
map->l_name, (int) map->l_direct_opencount); \ map->l_name, (int) map->l_direct_opencount); \
@ -147,7 +149,7 @@ main (int argc, char *argv[])
{ {
/* In this case none of the objects above should be /* In this case none of the objects above should be
present. */ present. */
for (map = _r_debug.r_map; map != NULL; map = map->l_next) for (map = MAPS; map != NULL; map = map->l_next)
if (map->l_type == lt_loaded if (map->l_type == lt_loaded
&& (strstr (map->l_name, testobjs[0].name) != NULL && (strstr (map->l_name, testobjs[0].name) != NULL
|| strstr (map->l_name, testobjs[1].name) != NULL || strstr (map->l_name, testobjs[1].name) != NULL
@ -180,7 +182,7 @@ main (int argc, char *argv[])
} }
/* Check whether all files are unloaded. */ /* Check whether all files are unloaded. */
for (map = _r_debug.r_map; map != NULL; map = map->l_next) for (map = MAPS; map != NULL; map = map->l_next)
if (map->l_type == lt_loaded) if (map->l_type == lt_loaded)
{ {
printf ("name = \"%s\", direct_opencount = %d\n", printf ("name = \"%s\", direct_opencount = %d\n",

View File

@ -5,6 +5,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#define MAPS ((struct link_map *) _r_debug.r_map)
static int static int
check_loaded_objects (const char **loaded) check_loaded_objects (const char **loaded)
{ {
@ -24,7 +26,7 @@ check_loaded_objects (const char **loaded)
printf(" Name\n"); printf(" Name\n");
printf(" --------------------------------------------------------\n"); printf(" --------------------------------------------------------\n");
for (lm = _r_debug.r_map; lm; lm = lm->l_next) for (lm = MAPS; lm; lm = lm->l_next)
{ {
if (lm->l_name && lm->l_name[0]) if (lm->l_name && lm->l_name[0])
printf(" %s, count = %d\n", lm->l_name, (int) lm->l_direct_opencount); printf(" %s, count = %d\n", lm->l_name, (int) lm->l_direct_opencount);

View File

@ -5,6 +5,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#define MAPS ((struct link_map *) _r_debug.r_map)
static int static int
check_loaded_objects (const char **loaded) check_loaded_objects (const char **loaded)
{ {
@ -24,7 +26,7 @@ check_loaded_objects (const char **loaded)
printf(" Name\n"); printf(" Name\n");
printf(" --------------------------------------------------------\n"); printf(" --------------------------------------------------------\n");
for (lm = _r_debug.r_map; lm; lm = lm->l_next) for (lm = MAPS; lm; lm = lm->l_next)
{ {
if (lm->l_name && lm->l_name[0]) if (lm->l_name && lm->l_name[0])
printf(" %s, count = %d\n", lm->l_name, (int) lm->l_direct_opencount); printf(" %s, count = %d\n", lm->l_name, (int) lm->l_direct_opencount);

View File

@ -5,6 +5,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#define MAPS ((struct link_map *) _r_debug.r_map)
static int static int
check_loaded_objects (const char **loaded) check_loaded_objects (const char **loaded)
{ {
@ -24,7 +26,7 @@ check_loaded_objects (const char **loaded)
printf(" Name\n"); printf(" Name\n");
printf(" --------------------------------------------------------\n"); printf(" --------------------------------------------------------\n");
for (lm = _r_debug.r_map; lm; lm = lm->l_next) for (lm = MAPS; lm; lm = lm->l_next)
{ {
if (lm->l_name && lm->l_name[0]) if (lm->l_name && lm->l_name[0])
printf(" %s, count = %d\n", lm->l_name, (int) lm->l_direct_opencount); printf(" %s, count = %d\n", lm->l_name, (int) lm->l_direct_opencount);

View File

@ -5,6 +5,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#define MAPS ((struct link_map *) _r_debug.r_map)
static int static int
check_loaded_objects (const char **loaded) check_loaded_objects (const char **loaded)
{ {
@ -24,7 +26,7 @@ check_loaded_objects (const char **loaded)
printf(" Name\n"); printf(" Name\n");
printf(" --------------------------------------------------------\n"); printf(" --------------------------------------------------------\n");
for (lm = _r_debug.r_map; lm; lm = lm->l_next) for (lm = MAPS; lm; lm = lm->l_next)
{ {
if (lm->l_name && lm->l_name[0]) if (lm->l_name && lm->l_name[0])
printf(" %s, count = %d\n", lm->l_name, (int) lm->l_direct_opencount); printf(" %s, count = %d\n", lm->l_name, (int) lm->l_direct_opencount);

92
elf/tst-tls-dlinfo.c Normal file
View File

@ -0,0 +1,92 @@
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <tls.h>
#define TEST_FUNCTION do_test ()
static int
do_test (void)
{
#ifdef USE_TLS
static const char modname[] = "tst-tlsmod2.so";
int result = 0;
int *foop;
int (*fp) (int, int *);
void *h;
h = dlopen (modname, RTLD_LAZY);
if (h == NULL)
{
printf ("cannot open '%s': %s\n", modname, dlerror ());
exit (1);
}
fp = dlsym (h, "in_dso");
if (fp == NULL)
{
printf ("cannot get symbol 'in_dso': %s\n", dlerror ());
exit (1);
}
size_t modid = -1;
if (dlinfo (h, RTLD_DI_TLS_MODID, &modid))
{
printf ("dlinfo RTLD_DI_TLS_MODID failed: %s\n", dlerror ());
result = 1;
}
else
printf ("dlinfo says TLS module ID %Zu\n", modid);
void *block;
if (dlinfo (h, RTLD_DI_TLS_DATA, &block))
{
printf ("dlinfo RTLD_DI_TLS_DATA failed: %s\n", dlerror ());
result = 1;
}
else if (block != NULL)
{
printf ("dlinfo RTLD_DI_TLS_DATA says %p but should be unallocated\n",
block);
result = 1;
}
result |= fp (0, NULL);
foop = dlsym (h, "foo");
if (foop == NULL)
{
printf ("cannot get symbol 'foo' the second time: %s\n", dlerror ());
exit (1);
}
if (*foop != 16)
{
puts ("foo != 16");
result = 1;
}
/* Now the module's TLS block has been used and should appear. */
if (dlinfo (h, RTLD_DI_TLS_DATA, &block))
{
printf ("dlinfo RTLD_DI_TLS_DATA failed the second time: %s\n",
dlerror ());
result = 1;
}
else if (block != foop)
{
printf ("dlinfo RTLD_DI_TLS_DATA says %p but should be %p\n",
block, foop);
result = 1;
}
dlclose (h);
return result;
#else
return 0;
#endif
}
#include "../test-skeleton.c"

View File

@ -9,8 +9,10 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#define MAPS ((struct link_map *) _r_debug.r_map)
#define OUT \ #define OUT \
for (map = _r_debug.r_map; map != NULL; map = map->l_next) \ for (map = MAPS; map != NULL; map = map->l_next) \
if (map->l_type == lt_loaded) \ if (map->l_type == lt_loaded) \
printf ("name = \"%s\", direct_opencount = %d\n", \ printf ("name = \"%s\", direct_opencount = %d\n", \
map->l_name, (int) map->l_direct_opencount); \ map->l_name, (int) map->l_direct_opencount); \

View File

@ -6,8 +6,10 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#define MAPS ((struct link_map *) _r_debug.r_map)
#define OUT \ #define OUT \
for (map = _r_debug.r_map; map != NULL; map = map->l_next) \ for (map = MAPS; map != NULL; map = map->l_next) \
if (map->l_type == lt_loaded) \ if (map->l_type == lt_loaded) \
printf ("name = \"%s\", direct_opencount = %d\n", \ printf ("name = \"%s\", direct_opencount = %d\n", \
map->l_name, (int) map->l_direct_opencount); \ map->l_name, (int) map->l_direct_opencount); \

View File

@ -1,6 +1,6 @@
/* Data structure for communication from the run-time dynamic linker for /* Data structure for communication from the run-time dynamic linker for
loaded ELF shared objects. loaded ELF shared objects.
Copyright (C) 1995-2002, 2003, 2004, 2005 Free Software Foundation, Inc. Copyright (C) 1995-2002,2003,2004,2005,2006 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -18,67 +18,32 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */ 02111-1307 USA. */
#ifndef _LINK_H #ifndef _PRIVATE_LINK_H
#define _LINK_H 1 #define _PRIVATE_LINK_H 1
#ifdef _LINK_H
# error this should be impossible
#endif
/* Get most of the contents from the public header, but we define a
different `struct link_map' type for private use. The la_objopen
prototype uses the type, so we have to declare it separately. */
#define link_map link_map_public
#define la_objopen la_objopen_wrongproto
#include <elf/link.h>
#undef link_map
#undef la_objopen
struct link_map;
extern unsigned int la_objopen (struct link_map *__map, Lmid_t __lmid,
uintptr_t *__cookie);
#include <elf.h>
#include <dlfcn.h>
#include <stddef.h> #include <stddef.h>
#include <sys/types.h>
/* We use this macro to refer to ELF types independent of the native wordsize.
`ElfW(TYPE)' is used in place of `Elf32_TYPE' or `Elf64_TYPE'. */
#define ElfW(type) _ElfW (Elf, __ELF_NATIVE_CLASS, type)
#define _ElfW(e,w,t) _ElfW_1 (e, w, _##t)
#define _ElfW_1(e,w,t) e##w##t
#include <bits/elfclass.h> /* Defines __ELF_NATIVE_CLASS. */
#include <bits/link.h>
#include <bits/linkmap.h> #include <bits/linkmap.h>
#include <dl-lookupcfg.h> #include <dl-lookupcfg.h>
#include <tls.h> /* Defines USE_TLS. */ #include <tls.h> /* Defines USE_TLS. */
/* Rendezvous structure used by the run-time dynamic linker to communicate
details of shared object loading to the debugger. If the executable's
dynamic section has a DT_DEBUG element, the run-time linker sets that
element's value to the address where this structure can be found. */
struct r_debug
{
int r_version; /* Version number for this protocol. */
struct link_map *r_map; /* Head of the chain of loaded objects. */
/* This is the address of a function internal to the run-time linker,
that will always be called when the linker begins to map in a
library or unmap it, and again when the mapping change is complete.
The debugger can set a breakpoint at this address if it wants to
notice shared object mapping changes. */
ElfW(Addr) r_brk;
enum
{
/* This state value describes the mapping change taking place when
the `r_brk' address is called. */
RT_CONSISTENT, /* Mapping change is complete. */
RT_ADD, /* Beginning to add a new object. */
RT_DELETE /* Beginning to remove an object mapping. */
} r_state;
ElfW(Addr) r_ldbase; /* Base address the linker is loaded at. */
};
/* This is the instance of that structure used by the dynamic linker. */
extern struct r_debug _r_debug;
/* This symbol refers to the "dynamic structure" in the `.dynamic' section
of whatever module refers to `_DYNAMIC'. So, to find its own
`struct r_debug', a program could do:
for (dyn = _DYNAMIC; dyn->d_tag != DT_NULL; ++dyn)
if (dyn->d_tag == DT_DEBUG)
r_debug = (struct r_debug *) dyn->d_un.d_ptr;
*/
extern ElfW(Dyn) _DYNAMIC[];
/* Some internal data structures of the dynamic linker used in the /* Some internal data structures of the dynamic linker used in the
linker map. We only provide forward declarations. */ linker map. We only provide forward declarations. */
@ -316,45 +281,6 @@ struct link_map
} l_audit[0]; } l_audit[0];
}; };
/* Version numbers for la_version handshake interface. */
#define LAV_CURRENT 1
/* Activity types signaled through la_activity. */
enum
{
LA_ACT_CONSISTENT,
LA_ACT_ADD,
LA_ACT_DELETE
};
/* Values representing origin of name for dynamic loading. */
enum
{
LA_SER_ORIG = 0x01, /* Original name. */
LA_SER_LIBPATH = 0x02, /* Directory from LD_LIBRARY_PATH. */
LA_SER_RUNPATH = 0x04, /* Directory from RPATH/RUNPATH. */
LA_SER_CONFIG = 0x08, /* Found through ldconfig. */
LA_SER_DEFAULT = 0x40, /* Default directory. */
LA_SER_SECURE = 0x80 /* Unused. */
};
/* Values for la_objopen return value. */
enum
{
LA_FLG_BINDTO = 0x01, /* Audit symbols bound to this object. */
LA_FLG_BINDFROM = 0x02 /* Audit symbols bound from this object. */
};
/* Values for la_symbind flags parameter. */
enum
{
LA_SYMB_NOPLTENTER = 0x01, /* la_pltenter will not be called. */
LA_SYMB_NOPLTEXIT = 0x02, /* la_pltexit will not be called. */
LA_SYMB_STRUCTCALL = 0x04, /* Return value is a structure. */
LA_SYMB_DLSYM = 0x08, /* Binding due to dlsym call. */
LA_SYMB_ALTVALUE = 0x10 /* Value has been changed by a previous
la_symbind call. */
};
#if __ELF_NATIVE_CLASS == 32 #if __ELF_NATIVE_CLASS == 32
# define symbind symbind32 # define symbind symbind32
@ -364,22 +290,8 @@ enum
# error "__ELF_NATIVE_CLASS must be defined" # error "__ELF_NATIVE_CLASS must be defined"
#endif #endif
struct dl_phdr_info
{
ElfW(Addr) dlpi_addr;
const char *dlpi_name;
const ElfW(Phdr) *dlpi_phdr;
ElfW(Half) dlpi_phnum;
unsigned long long int dlpi_adds;
unsigned long long int dlpi_subs;
};
extern int dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info,
size_t size, void *data),
void *data);
extern int __dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info, extern int __dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info,
size_t size, void *data), size_t size, void *data),
void *data); void *data);
#endif /* link.h */ #endif /* include/link.h */

View File

@ -1113,6 +1113,11 @@ extern void _dl_add_to_slotinfo (struct link_map *l) attribute_hidden;
module with the given index. */ module with the given index. */
extern struct link_map *_dl_update_slotinfo (unsigned long int req_modid); extern struct link_map *_dl_update_slotinfo (unsigned long int req_modid);
/* Look up the module's TLS block as for __tls_get_addr,
but never touch anything. Return null if it's not allocated yet. */
extern void *_dl_tls_get_addr_soft (struct link_map *l) internal_function;
__END_DECLS __END_DECLS
#endif /* ldsodefs.h */ #endif /* ldsodefs.h */