mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-09 14:50:05 +00:00
* 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:
parent
0b890d59bd
commit
d78efd9f36
33
ChangeLog
33
ChangeLog
@ -1,5 +1,38 @@
|
||||
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.
|
||||
|
||||
* include/fcntl.h: Declare __openat, __open64. Use libc_hidden_proto.
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* 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.
|
||||
|
||||
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. */
|
||||
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
|
||||
directories that will be searched for dependencies of this object.
|
||||
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. */
|
||||
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,
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* 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.
|
||||
|
||||
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
|
||||
|
||||
# ifdef USE_TLS
|
||||
# include <dl-tls.h>
|
||||
# endif
|
||||
|
||||
struct dlinfo_args
|
||||
{
|
||||
ElfW(Addr) caller;
|
||||
@ -90,6 +94,24 @@ RTLD_SELF used in code not dynamically loaded"));
|
||||
case RTLD_DI_ORIGIN:
|
||||
strcpy (args->arg, l->l_origin);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
13
elf/Makefile
13
elf/Makefile
@ -163,9 +163,11 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
|
||||
neededtest3 neededtest4 unload2 lateglobal initfirst global \
|
||||
restest2 next dblload dblunload reldep5 reldep6 reldep7 reldep8 \
|
||||
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-align2 $(tests-execstack-$(have-z-execstack)) tst-dlmodcount \
|
||||
tst-dlopenrpath tst-deep1 tst-dlmopen1 tst-dlmopen2 tst-dlmopen3 \
|
||||
tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-tls15 \
|
||||
tst-tls-dlinfo \
|
||||
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 \
|
||||
tst-stackguard1
|
||||
# reldep9
|
||||
@ -700,6 +702,11 @@ $(objpfx)tst-tls14.out: $(objpfx)tst-tlsmod14b.so
|
||||
$(objpfx)tst-tls15: $(libdl)
|
||||
$(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-align2.c = $(stack-align-test-flags)
|
||||
CFLAGS-tst-alignmod.c = $(stack-align-test-flags)
|
||||
|
@ -57,6 +57,7 @@ ld {
|
||||
_dl_allocate_tls; _dl_deallocate_tls;
|
||||
_dl_get_tls_static_info; _dl_allocate_tls_init;
|
||||
_dl_tls_setup; _dl_rtld_di_serinfo;
|
||||
_dl_tls_get_addr_soft;
|
||||
_dl_make_stack_executable;
|
||||
# Only here for gdb while a better method is developed.
|
||||
_dl_debug_state;
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAPS ((struct link_map *) _r_debug.r_map)
|
||||
|
||||
static int
|
||||
check_loaded_objects (const char **loaded)
|
||||
{
|
||||
@ -24,7 +26,7 @@ check_loaded_objects (const char **loaded)
|
||||
|
||||
printf(" Name\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])
|
||||
printf(" %s, count = %d\n", lm->l_name, (int) lm->l_direct_opencount);
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* 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.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
@ -19,6 +20,18 @@
|
||||
|
||||
#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
|
||||
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
|
||||
@ -46,7 +59,7 @@ _dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns)
|
||||
/* Tell the debugger where to find the map of loaded objects. */
|
||||
r->r_version = 1 /* R_DEBUG_VERSION XXX */;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* 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.
|
||||
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_adds = GL(dl_load_adds);
|
||||
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);
|
||||
if (ret)
|
||||
break;
|
||||
|
46
elf/dl-tls.c
46
elf/dl-tls.c
@ -1,5 +1,5 @@
|
||||
/* 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.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
@ -735,6 +735,50 @@ __tls_get_addr (GET_ADDR_ARGS)
|
||||
# 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
|
||||
_dl_add_to_slotinfo (struct link_map *l)
|
||||
|
18
elf/link.h
18
elf/link.h
@ -1,6 +1,6 @@
|
||||
/* Data structure for communication from the run-time dynamic linker for
|
||||
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.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
@ -135,7 +135,6 @@ enum
|
||||
la_symbind call. */
|
||||
};
|
||||
|
||||
|
||||
struct dl_phdr_info
|
||||
{
|
||||
ElfW(Addr) dlpi_addr;
|
||||
@ -143,15 +142,24 @@ struct dl_phdr_info
|
||||
const ElfW(Phdr) *dlpi_phdr;
|
||||
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
|
||||
argument passed to the dl_iterate_phdr() callback to determine
|
||||
whether or not they are provided. */
|
||||
argument passed to the dl_iterate_phdr callback to determine
|
||||
whether or not each later member is available. */
|
||||
|
||||
/* Incremented when a new object may have been added. */
|
||||
unsigned long long int dlpi_adds;
|
||||
/* Incremented when an object may have been removed. */
|
||||
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
|
||||
|
@ -70,8 +70,10 @@ static const struct
|
||||
|
||||
#include <include/link.h>
|
||||
|
||||
#define MAPS ((struct link_map *) _r_debug.r_map)
|
||||
|
||||
#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) \
|
||||
printf ("name = \"%s\", direct_opencount = %d\n", \
|
||||
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
|
||||
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
|
||||
&& (strstr (map->l_name, testobjs[0].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. */
|
||||
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)
|
||||
{
|
||||
printf ("name = \"%s\", direct_opencount = %d\n",
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAPS ((struct link_map *) _r_debug.r_map)
|
||||
|
||||
static int
|
||||
check_loaded_objects (const char **loaded)
|
||||
{
|
||||
@ -24,7 +26,7 @@ check_loaded_objects (const char **loaded)
|
||||
|
||||
printf(" Name\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])
|
||||
printf(" %s, count = %d\n", lm->l_name, (int) lm->l_direct_opencount);
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAPS ((struct link_map *) _r_debug.r_map)
|
||||
|
||||
static int
|
||||
check_loaded_objects (const char **loaded)
|
||||
{
|
||||
@ -24,7 +26,7 @@ check_loaded_objects (const char **loaded)
|
||||
|
||||
printf(" Name\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])
|
||||
printf(" %s, count = %d\n", lm->l_name, (int) lm->l_direct_opencount);
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAPS ((struct link_map *) _r_debug.r_map)
|
||||
|
||||
static int
|
||||
check_loaded_objects (const char **loaded)
|
||||
{
|
||||
@ -24,7 +26,7 @@ check_loaded_objects (const char **loaded)
|
||||
|
||||
printf(" Name\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])
|
||||
printf(" %s, count = %d\n", lm->l_name, (int) lm->l_direct_opencount);
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAPS ((struct link_map *) _r_debug.r_map)
|
||||
|
||||
static int
|
||||
check_loaded_objects (const char **loaded)
|
||||
{
|
||||
@ -24,7 +26,7 @@ check_loaded_objects (const char **loaded)
|
||||
|
||||
printf(" Name\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])
|
||||
printf(" %s, count = %d\n", lm->l_name, (int) lm->l_direct_opencount);
|
||||
|
92
elf/tst-tls-dlinfo.c
Normal file
92
elf/tst-tls-dlinfo.c
Normal 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"
|
@ -9,8 +9,10 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define MAPS ((struct link_map *) _r_debug.r_map)
|
||||
|
||||
#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) \
|
||||
printf ("name = \"%s\", direct_opencount = %d\n", \
|
||||
map->l_name, (int) map->l_direct_opencount); \
|
||||
|
@ -6,8 +6,10 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define MAPS ((struct link_map *) _r_debug.r_map)
|
||||
|
||||
#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) \
|
||||
printf ("name = \"%s\", direct_opencount = %d\n", \
|
||||
map->l_name, (int) map->l_direct_opencount); \
|
||||
|
132
include/link.h
132
include/link.h
@ -1,6 +1,6 @@
|
||||
/* Data structure for communication from the run-time dynamic linker for
|
||||
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.
|
||||
|
||||
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
|
||||
02111-1307 USA. */
|
||||
|
||||
#ifndef _LINK_H
|
||||
#define _LINK_H 1
|
||||
#ifndef _PRIVATE_LINK_H
|
||||
#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 <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 <dl-lookupcfg.h>
|
||||
#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
|
||||
linker map. We only provide forward declarations. */
|
||||
@ -316,45 +281,6 @@ struct link_map
|
||||
} 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
|
||||
# define symbind symbind32
|
||||
@ -364,22 +290,8 @@ enum
|
||||
# error "__ELF_NATIVE_CLASS must be defined"
|
||||
#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,
|
||||
size_t size, void *data),
|
||||
void *data);
|
||||
|
||||
#endif /* link.h */
|
||||
#endif /* include/link.h */
|
||||
|
@ -1113,6 +1113,11 @@ extern void _dl_add_to_slotinfo (struct link_map *l) attribute_hidden;
|
||||
module with the given index. */
|
||||
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
|
||||
|
||||
#endif /* ldsodefs.h */
|
||||
|
Loading…
Reference in New Issue
Block a user