about summary refs log tree commit diff
path: root/elf/dl-tls.c
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>2006-03-01 06:18:49 +0000
committerRoland McGrath <roland@gnu.org>2006-03-01 06:18:49 +0000
commitd78efd9f369a8fc46229fc9224e10e3781eecc43 (patch)
tree2ab775602fdf94ce710efb518002de4a93bfab0e /elf/dl-tls.c
parent0b890d59bd75cb8ab9232ab72ed8674054e11fa3 (diff)
downloadglibc-d78efd9f369a8fc46229fc9224e10e3781eecc43.tar.gz
glibc-d78efd9f369a8fc46229fc9224e10e3781eecc43.tar.xz
glibc-d78efd9f369a8fc46229fc9224e10e3781eecc43.zip
* 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.
Diffstat (limited to 'elf/dl-tls.c')
-rw-r--r--elf/dl-tls.c48
1 files changed, 46 insertions, 2 deletions
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
index 4fed570d5c..a0f4f77ffa 100644
--- a/elf/dl-tls.c
+++ b/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,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