]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
* elf/tst-tls-dlinfo.c: New file.
authorRoland McGrath <roland@gnu.org>
Wed, 1 Mar 2006 06:18:49 +0000 (06:18 +0000)
committerRoland McGrath <roland@gnu.org>
Wed, 1 Mar 2006 06:18:49 +0000 (06:18 +0000)
* 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.

20 files changed:
ChangeLog
dlfcn/dlfcn.h
dlfcn/dlinfo.c
elf/Makefile
elf/Versions
elf/circleload1.c
elf/dl-debug.c
elf/dl-iteratephdr.c
elf/dl-tls.c
elf/link.h
elf/loadtest.c
elf/neededtest.c
elf/neededtest2.c
elf/neededtest3.c
elf/neededtest4.c
elf/tst-tls-dlinfo.c [new file with mode: 0644]
elf/unload.c
elf/unload2.c
include/link.h
sysdeps/generic/ldsodefs.h

index 6ccf70ada29bced7954dbf99ff68cde299061384..b35cd50a36fdf45d333ac72fad3c35938e628f22 100644 (file)
--- a/ChangeLog
+++ b/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.
index 42c25b8b633337317913bc86b66c62f6024544af..7e373eddf93cefb7ed632086b30ab4b747f620ed 100644 (file)
@@ -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,
   };
 
 
index 44af55a3039101ebdcf7e203aff660be3618e170..b1e2b009a5e29d2d6a06eafe883ca3f7a2b86bc1 100644 (file)
@@ -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;
+      }
     }
 }
 
index 5cd78c2f83e9e410fdf24d4de446d8467ef47de2..791341758e9c1b97061d5feabcfb33652f2bc8bb 100644 (file)
@@ -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)
index 87e27c5a7a9e5d8383aeec0f3877f0fbe016846f..967ebdb3a5b6d53843f8dc58ed7bd1f922fcecca 100644 (file)
@@ -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;
index f5f886a1da39d38f810bf63170d3336228f9e678..990ff84a848b6e34f73074fa609c1fa177eeab38 100644 (file)
@@ -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);
index bc7d793435e8e6768c8de29b98df6c28dd2f4d8d..d00fe87fbbfb006c9f573c0a1d963fdb04092872 100644 (file)
@@ -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
 
 #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;
     }
 
index 6ed90c73b139212a7030384963434c1e5add589f..52a114421d20df074d64186f8a075acfa2b1902d 100644 (file)
@@ -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;
index 4fed570d5c2e576a2a13cc6848002c7d2b1483c3..a0f4f77ffa58d333acedc1c97f3a52340d489113 100644 (file)
@@ -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,9 +735,53 @@ __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)
+_dl_add_to_slotinfo (struct link_map *l)
 {
   /* Now that we know the object is loaded successfully add
      modules containing TLS data to the dtv info table.  We
index fdda019cbefb04d4c2531b46a0cde54688f11ebe..076531d6e746d34a244db477dcd283a8e08c06dd 100644 (file)
@@ -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
index ee106ea1523e83f45907de2423422150dd17c4fb..727469b49679777f19f2f5cdb3fd41b2422e847b 100644 (file)
@@ -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",
index 6c7a952066ca70e431b5ee7105af39c1ed47aeb2..3cea4993144902afd94f77c4a0b4c81e9c1265e3 100644 (file)
@@ -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);
index b682f15792bd72a2816999f83d2e8466d1bca923..17c75f2ba3f2bc442c5c61dc8c8c502260fa257d 100644 (file)
@@ -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);
index ea1dcf47949a6ddb82c2e9bc11c87d455922b3e4..41970cf2c7c39ea777fae9a005c67a12b0071b09 100644 (file)
@@ -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);
index 7514bed4990a9761f559d065670dd8ce9d70e4da..bd79341fb24484587cd6171ee1e91bd65b87b027 100644 (file)
@@ -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);
diff --git a/elf/tst-tls-dlinfo.c b/elf/tst-tls-dlinfo.c
new file mode 100644 (file)
index 0000000..e97b508
--- /dev/null
@@ -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"
index ffb33482c0d6b2e56076d04313a3d77a144c87dd..4566f226f8555337b005538956111b7843c67624 100644 (file)
@@ -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);                    \
index e14c6f06afdcf286c087e2009607bc6d3a3f6450..eef2bfd42688f1572658c89918e8c62b46d12d81 100644 (file)
@@ -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);                    \
index 0c352640969220ab0b37159f8b075bcbcf4743f4..3079ae873955051d9be9144e616f50eac842d8a2 100644 (file)
@@ -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
    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
 
-#include <elf.h>
-#include <dlfcn.h>
-#include <stddef.h>
-#include <sys/types.h>
+#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);
 
-/* 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 <stddef.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 */
index b5f7c3cae57334406822190ec00912dce8a1fea8..13fefd9e8344bea717e1b17369dddd3d68c8cb30 100644 (file)
@@ -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 */