Blame SOURCES/glibc-rh1202952.patch

147e83
# 
147e83
# commit f8aeae347377f3dfa8cbadde057adf1827fb1d44
147e83
# Author: Alexandre Oliva <aoliva@redhat.com>
147e83
# Date:   Tue Mar 17 01:14:11 2015 -0300
147e83
# 
147e83
#     Fix DTV race, assert, DTV_SURPLUS Static TLS limit, and nptl_db garbage
147e83
#     
147e83
#     for  ChangeLog
147e83
#     
147e83
#         [BZ #17090]
147e83
#         [BZ #17620]
147e83
#         [BZ #17621]
147e83
#         [BZ #17628]
147e83
#         * NEWS: Update.
147e83
#         * elf/dl-tls.c (_dl_update_slotinfo): Clean up outdated DTV
147e83
#         entries with Static TLS too.  Skip entries past the end of the
147e83
#         allocated DTV, from Alan Modra.
147e83
#         (tls_get_addr_tail): Update to glibc_likely/unlikely.  Move
147e83
#         Static TLS DTV entry set up from...
147e83
#          (_dl_allocate_tls_init): ... here (fix modid assertion), ...
147e83
#         * elf/dl-reloc.c (_dl_nothread_init_static_tls): ... here...
147e83
#         * nptl/allocatestack.c (init_one_static_tls): ... and here...
147e83
#         * elf/dlopen.c (dl_open_worker): Drop l_tls_modid upper bound
147e83
#         for Static TLS.
147e83
#         * elf/tlsdeschtab.h (map_generation): Return size_t.  Check
147e83
#         that the slot we find is associated with the given map before
147e83
#         using its generation count.
147e83
#         * nptl_db/db_info.c: Include ldsodefs.h.
147e83
#         (rtld_global, dtv_slotinfo_list, dtv_slotinfo): New typedefs.
147e83
#         * nptl_db/structs.def (DB_RTLD_VARIABLE): New macro.
147e83
#         (DB_MAIN_VARIABLE, DB_RTLD_GLOBAL_FIELD): Likewise.
147e83
#         (link_map::l_tls_offset): New struct field.
147e83
#         (dtv_t::counter): Likewise.
147e83
#         (rtld_global): New struct.
147e83
#         (_rtld_global): New rtld variable.
147e83
#         (dl_tls_dtv_slotinfo_list): New rtld global field.
147e83
#         (dtv_slotinfo_list): New struct.
147e83
#         (dtv_slotinfo): Likewise.
147e83
#         * nptl_db/td_symbol_list.c: Drop gnu/lib-names.h include.
147e83
#         (td_lookup): Rename to...
147e83
#         (td_mod_lookup): ... this.  Use new mod parameter instead of
147e83
#         LIBPTHREAD_SO.
147e83
#         * nptl_db/td_thr_tlsbase.c: Include link.h.
147e83
#         (dtv_slotinfo_list, dtv_slotinfo): New functions.
147e83
#         (td_thr_tlsbase): Check DTV generation.  Compute Static TLS
147e83
#         addresses even if the DTV is out of date or missing them.
147e83
#         * nptl_db/fetch-value.c (_td_locate_field): Do not refuse to
147e83
#         index zero-length arrays.
147e83
#         * nptl_db/thread_dbP.h: Include gnu/lib-names.h.
147e83
#         (td_lookup): Make it a macro implemented in terms of...
147e83
#         (td_mod_lookup): ... this declaration.
147e83
#         * nptl_db/db-symbols.awk (DB_RTLD_VARIABLE): Override.
147e83
#         (DB_MAIN_VARIABLE): Likewise.
147e83
# 
147e83
diff -urN glibc-2.17-c758a686/elf/dl-open.c glibc-2.17-c758a686/elf/dl-open.c
147e83
--- glibc-2.17-c758a686/elf/dl-open.c	2012-12-24 22:02:13.000000000 -0500
147e83
+++ glibc-2.17-c758a686/elf/dl-open.c	2015-03-17 14:39:47.746505786 -0400
147e83
@@ -535,17 +535,7 @@
147e83
 	  && imap->l_tls_blocksize > 0)
147e83
 	{
147e83
 	  /* For static TLS we have to allocate the memory here and
147e83
-	     now.  This includes allocating memory in the DTV.  But we
147e83
-	     cannot change any DTV other than our own.  So, if we
147e83
-	     cannot guarantee that there is room in the DTV we don't
147e83
-	     even try it and fail the load.
147e83
-
147e83
-	     XXX We could track the minimum DTV slots allocated in
147e83
-	     all threads.  */
147e83
-	  if (! RTLD_SINGLE_THREAD_P && imap->l_tls_modid > DTV_SURPLUS)
147e83
-	    _dl_signal_error (0, "dlopen", NULL, N_("\
147e83
-cannot load any more object with static TLS"));
147e83
-
147e83
+	     now, but we can delay updating the DTV.  */
147e83
 	  imap->l_need_tls_init = 0;
147e83
 #ifdef SHARED
147e83
 	  /* Update the slot information data for at least the
147e83
diff -urN glibc-2.17-c758a686/elf/dl-reloc.c glibc-2.17-c758a686/elf/dl-reloc.c
147e83
--- glibc-2.17-c758a686/elf/dl-reloc.c	2012-12-24 22:02:13.000000000 -0500
147e83
+++ glibc-2.17-c758a686/elf/dl-reloc.c	2015-03-17 14:39:47.747505754 -0400
147e83
@@ -136,12 +136,6 @@
147e83
 # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
147e83
 #endif
147e83
 
147e83
-  /* Fill in the DTV slot so that a later LD/GD access will find it.  */
147e83
-  dtv_t *dtv = THREAD_DTV ();
147e83
-  assert (map->l_tls_modid <= dtv[-1].counter);
147e83
-  dtv[map->l_tls_modid].pointer.val = dest;
147e83
-  dtv[map->l_tls_modid].pointer.is_static = true;
147e83
-
147e83
   /* Initialize the memory.  */
147e83
   memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size),
147e83
 	  '\0', map->l_tls_blocksize - map->l_tls_initimage_size);
147e83
diff -urN glibc-2.17-c758a686/elf/dl-tls.c glibc-2.17-c758a686/elf/dl-tls.c
147e83
--- glibc-2.17-c758a686/elf/dl-tls.c	2015-03-17 14:39:31.335019227 -0400
147e83
+++ glibc-2.17-c758a686/elf/dl-tls.c	2015-03-17 14:42:48.443852579 -0400
147e83
@@ -432,17 +432,14 @@
147e83
 	  assert (listp->slotinfo[cnt].gen <= GL(dl_tls_generation));
147e83
 	  maxgen = MAX (maxgen, listp->slotinfo[cnt].gen);
147e83
 
147e83
+	  dtv[map->l_tls_modid].pointer.val = TLS_DTV_UNALLOCATED;
147e83
+	  dtv[map->l_tls_modid].pointer.is_static = false;
147e83
+
147e83
 	  if (map->l_tls_offset == NO_TLS_OFFSET
147e83
 	      || map->l_tls_offset == FORCED_DYNAMIC_TLS_OFFSET)
147e83
-	    {
147e83
-	      /* For dynamically loaded modules we simply store
147e83
-		 the value indicating deferred allocation.  */
147e83
-	      dtv[map->l_tls_modid].pointer.val = TLS_DTV_UNALLOCATED;
147e83
-	      dtv[map->l_tls_modid].pointer.is_static = false;
147e83
-	      continue;
147e83
-	    }
147e83
+	    continue;
147e83
 
147e83
-	  assert (map->l_tls_modid == cnt);
147e83
+	  assert (map->l_tls_modid == total + cnt);
147e83
 	  assert (map->l_tls_blocksize >= map->l_tls_initimage_size);
147e83
 #if TLS_TCB_AT_TP
147e83
 	  assert ((size_t) map->l_tls_offset >= map->l_tls_blocksize);
147e83
@@ -454,8 +451,6 @@
147e83
 #endif
147e83
 
147e83
 	  /* Copy the initialization image and clear the BSS part.  */
147e83
-	  dtv[map->l_tls_modid].pointer.val = dest;
147e83
-	  dtv[map->l_tls_modid].pointer.is_static = true;
147e83
 	  memset (__mempcpy (dest, map->l_tls_initimage,
147e83
 			     map->l_tls_initimage_size), '\0',
147e83
 		  map->l_tls_blocksize - map->l_tls_initimage_size);
147e83
@@ -623,13 +618,16 @@
147e83
 	      struct link_map *map = listp->slotinfo[cnt].map;
147e83
 	      if (map == NULL)
147e83
 		{
147e83
-		  /* If this modid was used at some point the memory
147e83
-		     might still be allocated.  */
147e83
-		  if (! dtv[total + cnt].pointer.is_static
147e83
-		      && dtv[total + cnt].pointer.val != TLS_DTV_UNALLOCATED)
147e83
+		  if (dtv[-1].counter >= total + cnt)
147e83
 		    {
147e83
-		      free (dtv[total + cnt].pointer.val);
147e83
+		      /* If this modid was used at some point the memory
147e83
+			 might still be allocated.  */
147e83
+		      if (! dtv[total + cnt].pointer.is_static
147e83
+			  && (dtv[total + cnt].pointer.val
147e83
+			      != TLS_DTV_UNALLOCATED))
147e83
+			free (dtv[total + cnt].pointer.val);
147e83
 		      dtv[total + cnt].pointer.val = TLS_DTV_UNALLOCATED;
147e83
+		      dtv[total + cnt].pointer.is_static = false;
147e83
 		    }
147e83
 
147e83
 		  continue;
147e83
@@ -693,10 +691,8 @@
147e83
 		   memalign and not malloc.  */
147e83
 		free (dtv[modid].pointer.val);
147e83
 
147e83
-	      /* This module is loaded dynamically- We defer memory
147e83
-		 allocation.  */
147e83
-	      dtv[modid].pointer.is_static = false;
147e83
 	      dtv[modid].pointer.val = TLS_DTV_UNALLOCATED;
147e83
+	      dtv[modid].pointer.is_static = false;
147e83
 
147e83
 	      if (modid == req_modid)
147e83
 		the_map = map;
147e83
@@ -734,13 +730,12 @@
147e83
       the_map = listp->slotinfo[idx].map;
147e83
     }
147e83
 
147e83
- again:
147e83
   /* Make sure that, if a dlopen running in parallel forces the
147e83
      variable into static storage, we'll wait until the address in the
147e83
      static TLS block is set up, and use that.  If we're undecided
147e83
      yet, make sure we make the decision holding the lock as well.  */
147e83
-  if (__builtin_expect (the_map->l_tls_offset
147e83
-			!= FORCED_DYNAMIC_TLS_OFFSET, 0))
147e83
+  if (__glibc_unlikely (the_map->l_tls_offset
147e83
+			!= FORCED_DYNAMIC_TLS_OFFSET))
147e83
     {
147e83
       __rtld_lock_lock_recursive (GL(dl_load_lock));
147e83
       if (__builtin_expect (the_map->l_tls_offset == NO_TLS_OFFSET, 1))
147e83
@@ -748,22 +743,28 @@
147e83
 	  the_map->l_tls_offset = FORCED_DYNAMIC_TLS_OFFSET;
147e83
 	  __rtld_lock_unlock_recursive (GL(dl_load_lock));
147e83
 	}
147e83
-      else
147e83
+      else if (__glibc_likely (the_map->l_tls_offset
147e83
+			       != FORCED_DYNAMIC_TLS_OFFSET))
147e83
 	{
147e83
+#if TLS_TCB_AT_TP
147e83
+	  void *p = (char *) THREAD_SELF - the_map->l_tls_offset;
147e83
+#elif TLS_DTV_AT_TP
147e83
+	  void *p = (char *) THREAD_SELF + the_map->l_tls_offset + TLS_PRE_TCB_SIZE;
147e83
+#else
147e83
+# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
147e83
+#endif
147e83
 	  __rtld_lock_unlock_recursive (GL(dl_load_lock));
147e83
-	  if (__builtin_expect (the_map->l_tls_offset
147e83
-				!= FORCED_DYNAMIC_TLS_OFFSET, 1))
147e83
-	    {
147e83
-	      void *p = dtv[GET_ADDR_MODULE].pointer.val;
147e83
-	      if (__builtin_expect (p == TLS_DTV_UNALLOCATED, 0))
147e83
-		goto again;
147e83
+	  dtv[GET_ADDR_MODULE].pointer.is_static = true;
147e83
+	  dtv[GET_ADDR_MODULE].pointer.val = p;
147e83
 
147e83
-	      return (char *) p + GET_ADDR_OFFSET;
147e83
-	    }
147e83
+	  return (char *) p + GET_ADDR_OFFSET;
147e83
 	}
147e83
+      else
147e83
+	__rtld_lock_unlock_recursive (GL(dl_load_lock));
147e83
+
147e83
     }
147e83
   void *p = dtv[GET_ADDR_MODULE].pointer.val = allocate_and_init (the_map);
147e83
-  dtv[GET_ADDR_MODULE].pointer.is_static = false;
147e83
+  assert (!dtv[GET_ADDR_MODULE].pointer.is_static);
147e83
 
147e83
   return (char *) p + GET_ADDR_OFFSET;
147e83
 }
147e83
diff -urN glibc-2.17-c758a686/elf/tlsdeschtab.h glibc-2.17-c758a686/elf/tlsdeschtab.h
147e83
--- glibc-2.17-c758a686/elf/tlsdeschtab.h	2012-12-24 22:02:13.000000000 -0500
147e83
+++ glibc-2.17-c758a686/elf/tlsdeschtab.h	2015-03-17 14:39:47.747505754 -0400
147e83
@@ -42,7 +42,7 @@
147e83
   return tdp->tlsinfo.ti_offset == tdq->tlsinfo.ti_offset;
147e83
 }
147e83
 
147e83
-inline static int
147e83
+inline static size_t
147e83
 map_generation (struct link_map *map)
147e83
 {
147e83
   size_t idx = map->l_tls_modid;
147e83
@@ -58,7 +58,7 @@
147e83
 	     we can assume that, if the generation count is zero, we
147e83
 	     still haven't determined the generation count for this
147e83
 	     module.  */
147e83
-	  if (listp->slotinfo[idx].gen)
147e83
+	  if (listp->slotinfo[idx].map == map && listp->slotinfo[idx].gen)
147e83
 	    return listp->slotinfo[idx].gen;
147e83
 	  else
147e83
 	    break;
147e83
diff -urN glibc-2.17-c758a686/nptl/allocatestack.c glibc-2.17-c758a686/nptl/allocatestack.c
147e83
--- glibc-2.17-c758a686/nptl/allocatestack.c	2015-03-17 14:39:31.342019008 -0400
147e83
+++ glibc-2.17-c758a686/nptl/allocatestack.c	2015-03-17 14:39:47.747505754 -0400
147e83
@@ -1157,7 +1157,6 @@
147e83
 static inline void __attribute__((always_inline))
147e83
 init_one_static_tls (struct pthread *curp, struct link_map *map)
147e83
 {
147e83
-  dtv_t *dtv = GET_DTV (TLS_TPADJ (curp));
147e83
 # if TLS_TCB_AT_TP
147e83
   void *dest = (char *) curp - map->l_tls_offset;
147e83
 # elif TLS_DTV_AT_TP
147e83
@@ -1166,11 +1165,9 @@
147e83
 #  error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
147e83
 # endif
147e83
 
147e83
-  /* Fill in the DTV slot so that a later LD/GD access will find it.  */
147e83
-  dtv[map->l_tls_modid].pointer.val = dest;
147e83
-  dtv[map->l_tls_modid].pointer.is_static = true;
147e83
-
147e83
-  /* Initialize the memory.  */
147e83
+  /* We cannot delay the initialization of the Static TLS area, since
147e83
+     it can be accessed with LE or IE, but since the DTV is only used
147e83
+     by GD and LD, we can delay its update to avoid a race.  */
147e83
   memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size),
147e83
 	  '\0', map->l_tls_blocksize - map->l_tls_initimage_size);
147e83
 }
147e83
diff -urN glibc-2.17-c758a686/nptl_db/db_info.c glibc-2.17-c758a686/nptl_db/db_info.c
147e83
--- glibc-2.17-c758a686/nptl_db/db_info.c	2012-12-24 22:02:13.000000000 -0500
147e83
+++ glibc-2.17-c758a686/nptl_db/db_info.c	2015-03-17 14:39:47.747505754 -0400
147e83
@@ -20,6 +20,7 @@
147e83
 
147e83
 #include "thread_dbP.h"
147e83
 #include <tls.h>
147e83
+#include <ldsodefs.h>
147e83
 
147e83
 typedef struct pthread pthread;
147e83
 typedef struct pthread_key_struct pthread_key_struct;
147e83
@@ -36,6 +37,9 @@
147e83
 } dtv;
147e83
 
147e83
 typedef struct link_map link_map;
147e83
+typedef struct rtld_global rtld_global;
147e83
+typedef struct dtv_slotinfo_list dtv_slotinfo_list;
147e83
+typedef struct dtv_slotinfo dtv_slotinfo;
147e83
 
147e83
 /* Actually static in nptl/init.c, but we only need it for typeof.  */
147e83
 extern bool __nptl_initial_report_events;
147e83
diff -urN glibc-2.17-c758a686/nptl_db/db-symbols.awk glibc-2.17-c758a686/nptl_db/db-symbols.awk
147e83
--- glibc-2.17-c758a686/nptl_db/db-symbols.awk	2012-12-24 22:02:13.000000000 -0500
147e83
+++ glibc-2.17-c758a686/nptl_db/db-symbols.awk	2015-03-17 14:39:47.747505754 -0400
147e83
@@ -2,6 +2,8 @@
147e83
 # we've just built.  It checks for all the symbols used in td_symbol_list.
147e83
 
147e83
 BEGIN {
147e83
+%define DB_RTLD_VARIABLE(name) /* Nothing. */
147e83
+%define DB_MAIN_VARIABLE(name) /* Nothing. */
147e83
 %define DB_LOOKUP_NAME(idx, name)		required[STRINGIFY (name)] = 1;
147e83
 %define DB_LOOKUP_NAME_TH_UNIQUE(idx, name)	th_unique[STRINGIFY (name)] = 1;
147e83
 %include "db-symbols.h"
147e83
diff -urN glibc-2.17-c758a686/nptl_db/fetch-value.c glibc-2.17-c758a686/nptl_db/fetch-value.c
147e83
--- glibc-2.17-c758a686/nptl_db/fetch-value.c	2012-12-24 22:02:13.000000000 -0500
147e83
+++ glibc-2.17-c758a686/nptl_db/fetch-value.c	2015-03-17 14:39:47.747505754 -0400
147e83
@@ -68,7 +68,8 @@
147e83
 	}
147e83
     }
147e83
 
147e83
-  if (idx != 0 && idx - (psaddr_t) 0 > DB_DESC_NELEM (desc))
147e83
+  if (idx != 0 && DB_DESC_NELEM (desc) != 0
147e83
+      && idx - (psaddr_t) 0 > DB_DESC_NELEM (desc))
147e83
     /* This is an internal indicator to callers with nonzero IDX
147e83
        that the IDX value is too big.  */
147e83
     return TD_NOAPLIC;
147e83
diff -urN glibc-2.17-c758a686/nptl_db/structs.def glibc-2.17-c758a686/nptl_db/structs.def
147e83
--- glibc-2.17-c758a686/nptl_db/structs.def	2012-12-24 22:02:13.000000000 -0500
147e83
+++ glibc-2.17-c758a686/nptl_db/structs.def	2015-03-17 14:44:29.779682236 -0400
147e83
@@ -22,6 +22,28 @@
147e83
 # define STRUCTS_DEF_DEFAULTS 1
147e83
 #endif
147e83
 
147e83
+#ifndef DB_RTLD_VARIABLE
147e83
+# define DB_RTLD_VARIABLE(name) DB_VARIABLE (name)
147e83
+#endif
147e83
+
147e83
+#ifndef DB_MAIN_VARIABLE
147e83
+# define DB_MAIN_VARIABLE(name) DB_VARIABLE (name)
147e83
+#endif
147e83
+
147e83
+#ifndef DB_RTLD_GLOBAL_FIELD
147e83
+# if !defined IS_IN_libpthread
147e83
+#  define DB_RTLD_GLOBAL_FIELD(field)		\
147e83
+  DB_STRUCT_FIELD (rtld_global, _##field)	\
147e83
+  DB_MAIN_VARIABLE (_##field)
147e83
+# elif defined SHARED
147e83
+#  define DB_RTLD_GLOBAL_FIELD(field)		\
147e83
+  DB_STRUCT_FIELD (rtld_global, _##field)
147e83
+# else
147e83
+#  define DB_RTLD_GLOBAL_FIELD(field)		\
147e83
+  DB_MAIN_VARIABLE (_##field)
147e83
+# endif
147e83
+#endif /* DB_RTLD_GLOBAL_FIELD */
147e83
+
147e83
 DB_STRUCT (pthread)
147e83
 DB_STRUCT_FIELD (pthread, list)
147e83
 DB_STRUCT_FIELD (pthread, report_events)
147e83
@@ -70,14 +92,31 @@
147e83
 DB_STRUCT_ARRAY_FIELD (pthread_key_data_level2, data)
147e83
 
147e83
 DB_STRUCT_FIELD (link_map, l_tls_modid)
147e83
+DB_STRUCT_FIELD (link_map, l_tls_offset)
147e83
 
147e83
 DB_STRUCT_ARRAY_FIELD (dtv, dtv)
147e83
 #define pointer_val pointer.val /* Field of anonymous struct in dtv_t.  */
147e83
 DB_STRUCT_FIELD (dtv_t, pointer_val)
147e83
+DB_STRUCT_FIELD (dtv_t, counter)
147e83
 #if !defined IS_IN_libpthread || TLS_TCB_AT_TP
147e83
 DB_STRUCT_FIELD (pthread, dtvp)
147e83
 #endif
147e83
 
147e83
+#if !(defined IS_IN_libpthread && !defined SHARED)
147e83
+DB_STRUCT (rtld_global)
147e83
+DB_RTLD_VARIABLE (_rtld_global)
147e83
+#endif
147e83
+DB_RTLD_GLOBAL_FIELD (dl_tls_dtv_slotinfo_list)
147e83
+
147e83
+DB_STRUCT (dtv_slotinfo_list)
147e83
+DB_STRUCT_FIELD (dtv_slotinfo_list, len)
147e83
+DB_STRUCT_FIELD (dtv_slotinfo_list, next)
147e83
+DB_STRUCT_ARRAY_FIELD (dtv_slotinfo_list, slotinfo)
147e83
+
147e83
+DB_STRUCT (dtv_slotinfo)
147e83
+DB_STRUCT_FIELD (dtv_slotinfo, gen)
147e83
+DB_STRUCT_FIELD (dtv_slotinfo, map)
147e83
+
147e83
 #ifdef STRUCTS_DEF_DEFAULTS
147e83
 # undef DB_STRUCT_ARRAY_FIELD
147e83
 # undef DB_ARRAY_VARIABLE
147e83
diff -urN glibc-2.17-c758a686/nptl_db/td_symbol_list.c glibc-2.17-c758a686/nptl_db/td_symbol_list.c
147e83
--- glibc-2.17-c758a686/nptl_db/td_symbol_list.c	2012-12-24 22:02:13.000000000 -0500
147e83
+++ glibc-2.17-c758a686/nptl_db/td_symbol_list.c	2015-03-17 14:39:47.747505754 -0400
147e83
@@ -18,7 +18,6 @@
147e83
    <http://www.gnu.org/licenses/>.  */
147e83
 
147e83
 #include <assert.h>
147e83
-#include <gnu/lib-names.h>
147e83
 #include "thread_dbP.h"
147e83
 
147e83
 static const char *symbol_list_arr[] =
147e83
@@ -41,12 +40,12 @@
147e83
 
147e83
 
147e83
 ps_err_e
147e83
-td_lookup (struct ps_prochandle *ps, int idx, psaddr_t *sym_addr)
147e83
+td_mod_lookup (struct ps_prochandle *ps, const char *mod,
147e83
+	       int idx, psaddr_t *sym_addr)
147e83
 {
147e83
   ps_err_e result;
147e83
   assert (idx >= 0 && idx < SYM_NUM_MESSAGES);
147e83
-  result = ps_pglobal_lookup (ps, LIBPTHREAD_SO, symbol_list_arr[idx],
147e83
-			      sym_addr);
147e83
+  result = ps_pglobal_lookup (ps, mod, symbol_list_arr[idx], sym_addr);
147e83
 
147e83
 #ifdef HAVE_ASM_GLOBAL_DOT_NAME
147e83
   /* For PowerPC, 64-bit uses dot symbols but 32-bit does not.
147e83
diff -urN glibc-2.17-c758a686/nptl_db/td_thr_tlsbase.c glibc-2.17-c758a686/nptl_db/td_thr_tlsbase.c
147e83
--- glibc-2.17-c758a686/nptl_db/td_thr_tlsbase.c	2012-12-24 22:02:13.000000000 -0500
147e83
+++ glibc-2.17-c758a686/nptl_db/td_thr_tlsbase.c	2015-03-17 14:39:47.748505723 -0400
147e83
@@ -17,14 +17,118 @@
147e83
    <http://www.gnu.org/licenses/>.  */
147e83
 
147e83
 #include "thread_dbP.h"
147e83
+#include <link.h>
147e83
 
147e83
+/* Get the DTV slotinfo list head entry from the dynamic loader state
147e83
+   into *LISTHEAD.  */
147e83
+static td_err_e
147e83
+dtv_slotinfo_list (td_thragent_t *ta,
147e83
+		   psaddr_t *listhead)
147e83
+{
147e83
+  td_err_e err;
147e83
+  psaddr_t head;
147e83
+
147e83
+  if (ta->ta_addr__rtld_global == 0
147e83
+      && td_mod_lookup (ta->ph, LD_SO, SYM__rtld_global,
147e83
+			&ta->ta_addr__rtld_global) != PS_OK)
147e83
+    ta->ta_addr__rtld_global = (void*)-1;
147e83
+
147e83
+  if (ta->ta_addr__rtld_global != (void*)-1)
147e83
+    {
147e83
+      err = DB_GET_FIELD (head, ta, ta->ta_addr__rtld_global,
147e83
+			  rtld_global, _dl_tls_dtv_slotinfo_list, 0);
147e83
+      if (err != TD_OK)
147e83
+	return err;
147e83
+    }
147e83
+  else
147e83
+    {
147e83
+      if (ta->ta_addr__dl_tls_dtv_slotinfo_list == 0
147e83
+	  && td_mod_lookup (ta->ph, NULL, SYM__dl_tls_dtv_slotinfo_list,
147e83
+			    &ta->ta_addr__dl_tls_dtv_slotinfo_list) != PS_OK)
147e83
+	return TD_ERR;
147e83
+
147e83
+      err = _td_fetch_value (ta, ta->ta_var__dl_tls_dtv_slotinfo_list,
147e83
+			     SYM_DESC__dl_tls_dtv_slotinfo_list,
147e83
+			     0, ta->ta_addr__dl_tls_dtv_slotinfo_list, &head;;
147e83
+      if (err != TD_OK)
147e83
+	return err;
147e83
+    }
147e83
+
147e83
+  *listhead = head;
147e83
+  return TD_OK;
147e83
+}
147e83
+
147e83
+/* Get the address of the DTV slotinfo entry for MODID into
147e83
+   *DTVSLOTINFO.  */
147e83
+static td_err_e
147e83
+dtv_slotinfo (td_thragent_t *ta,
147e83
+	      unsigned long int modid,
147e83
+	      psaddr_t *dtvslotinfo)
147e83
+{
147e83
+  td_err_e err;
147e83
+  psaddr_t slot, temp;
147e83
+  size_t slbase = 0;
147e83
+
147e83
+  err = dtv_slotinfo_list (ta, &slot);
147e83
+  if (err != TD_OK)
147e83
+    return err;
147e83
+
147e83
+  while (slot)
147e83
+    {
147e83
+      /* Get the number of entries in this list entry's array.  */
147e83
+      err = DB_GET_FIELD (temp, ta, slot, dtv_slotinfo_list, len, 0);
147e83
+      if (err != TD_OK)
147e83
+	return err;
147e83
+      size_t len = (uintptr_t)temp;
147e83
+
147e83
+      /* Did we find the list entry for modid?  */
147e83
+      if (modid < slbase + len)
147e83
+	break;
147e83
+
147e83
+      /* We didn't, so get the next list entry.  */
147e83
+      slbase += len;
147e83
+      err = DB_GET_FIELD (temp, ta, slot, dtv_slotinfo_list,
147e83
+			  next, 0);
147e83
+      if (err != TD_OK)
147e83
+	return err;
147e83
+      slot = temp;
147e83
+    }
147e83
+
147e83
+  /* We reached the end of the list and found nothing.  */
147e83
+  if (!slot)
147e83
+    return TD_ERR;
147e83
+
147e83
+  /* Take the slotinfo for modid from the list entry.  */
147e83
+  err = DB_GET_FIELD_ADDRESS (temp, ta, slot, dtv_slotinfo_list,
147e83
+			      slotinfo, modid - slbase);
147e83
+  if (err != TD_OK)
147e83
+    return err;
147e83
+  slot = temp;
147e83
+
147e83
+  *dtvslotinfo = slot;
147e83
+  return TD_OK;
147e83
+}
147e83
+
147e83
+/* Return in *BASE the base address of the TLS block for MODID within
147e83
+   TH.
147e83
+
147e83
+   It should return success and yield the correct pointer in any
147e83
+   circumstance where the TLS block for the module and thread
147e83
+   requested has already been initialized.
147e83
+
147e83
+   It should fail with TD_TLSDEFER only when the thread could not
147e83
+   possibly have observed any values in that TLS block.  That way, the
147e83
+   debugger can fall back to showing initial values from the PT_TLS
147e83
+   segment (and refusing attempts to mutate) for the TD_TLSDEFER case,
147e83
+   and never fail to make the values the program will actually see
147e83
+   available to the user of the debugger.  */
147e83
 td_err_e
147e83
 td_thr_tlsbase (const td_thrhandle_t *th,
147e83
 		unsigned long int modid,
147e83
 		psaddr_t *base)
147e83
 {
147e83
   td_err_e err;
147e83
-  psaddr_t dtv, dtvslot, dtvptr;
147e83
+  psaddr_t dtv, dtvslot, dtvptr, temp;
147e83
 
147e83
   if (modid < 1)
147e83
     return TD_NOTLS;
147e83
@@ -50,11 +154,75 @@
147e83
 	return TD_TLSDEFER;
147e83
     }
147e83
 
147e83
+  err = dtv_slotinfo (th->th_ta_p, modid, &temp);
147e83
+  if (err != TD_OK)
147e83
+    return err;
147e83
+
147e83
+  psaddr_t slot;
147e83
+  err = DB_GET_STRUCT (slot, th->th_ta_p, temp, dtv_slotinfo);
147e83
+  if (err != TD_OK)
147e83
+    return err;
147e83
+
147e83
+  /* Take the link_map from the slotinfo.  */
147e83
+  psaddr_t map;
147e83
+  err = DB_GET_FIELD_LOCAL (map, th->th_ta_p, slot, dtv_slotinfo, map, 0);
147e83
+  if (err != TD_OK)
147e83
+    return err;
147e83
+  if (!map)
147e83
+    return TD_ERR;
147e83
+
147e83
+  /* Ok, the modid is good, now find out what DTV generation it
147e83
+     requires.  */
147e83
+  err = DB_GET_FIELD_LOCAL (temp, th->th_ta_p, slot, dtv_slotinfo, gen, 0);
147e83
+  if (err != TD_OK)
147e83
+    return err;
147e83
+  size_t modgen = (uintptr_t)temp;
147e83
+
147e83
   /* Get the DTV pointer from the thread descriptor.  */
147e83
   err = DB_GET_FIELD (dtv, th->th_ta_p, pd, pthread, dtvp, 0);
147e83
   if (err != TD_OK)
147e83
     return err;
147e83
 
147e83
+  psaddr_t dtvgenloc;
147e83
+  /* Get the DTV generation count at dtv[0].counter.  */
147e83
+  err = DB_GET_FIELD_ADDRESS (dtvgenloc, th->th_ta_p, dtv, dtv, dtv, 0);
147e83
+  if (err != TD_OK)
147e83
+    return err;
147e83
+  err = DB_GET_FIELD (temp, th->th_ta_p, dtvgenloc, dtv_t, counter, 0);
147e83
+  if (err != TD_OK)
147e83
+    return err;
147e83
+  size_t dtvgen = (uintptr_t)temp;
147e83
+
147e83
+  /* Is the DTV current enough?  */
147e83
+  if (dtvgen < modgen)
147e83
+    {
147e83
+    try_static_tls:
147e83
+      /* If the module uses Static TLS, we're still good.  */
147e83
+      err = DB_GET_FIELD (temp, th->th_ta_p, map, link_map, l_tls_offset, 0);
147e83
+      if (err != TD_OK)
147e83
+	return err;
147e83
+      ptrdiff_t tlsoff = (uintptr_t)temp;
147e83
+
147e83
+      if (tlsoff != FORCED_DYNAMIC_TLS_OFFSET
147e83
+	  && tlsoff != NO_TLS_OFFSET)
147e83
+	{
147e83
+	  psaddr_t tp = pd;
147e83
+
147e83
+#if TLS_TCB_AT_TP
147e83
+	  dtvptr = tp - tlsoff;
147e83
+#elif TLS_DTV_AT_TP
147e83
+	  dtvptr = tp + tlsoff + TLS_PRE_TCB_SIZE;
147e83
+#else
147e83
+# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
147e83
+#endif
147e83
+
147e83
+	  *base = dtvptr;
147e83
+	  return TD_OK;
147e83
+	}
147e83
+
147e83
+      return TD_TLSDEFER;
147e83
+    }
147e83
+
147e83
   /* Find the corresponding entry in the DTV.  */
147e83
   err = DB_GET_FIELD_ADDRESS (dtvslot, th->th_ta_p, dtv, dtv, dtv, modid);
147e83
   if (err != TD_OK)
147e83
@@ -68,7 +236,7 @@
147e83
   /* It could be that the memory for this module is not allocated for
147e83
      the given thread.  */
147e83
   if ((uintptr_t) dtvptr & 1)
147e83
-    return TD_TLSDEFER;
147e83
+    goto try_static_tls;
147e83
 
147e83
   *base = dtvptr;
147e83
   return TD_OK;
147e83
diff -urN glibc-2.17-c758a686/nptl_db/thread_dbP.h glibc-2.17-c758a686/nptl_db/thread_dbP.h
147e83
--- glibc-2.17-c758a686/nptl_db/thread_dbP.h	2012-12-24 22:02:13.000000000 -0500
147e83
+++ glibc-2.17-c758a686/nptl_db/thread_dbP.h	2015-03-17 14:39:47.748505723 -0400
147e83
@@ -29,6 +29,7 @@
147e83
 #include "thread_db.h"
147e83
 #include "../nptl/pthreadP.h"  	/* This is for *_BITMASK only.  */
147e83
 #include <list.h>
147e83
+#include <gnu/lib-names.h>
147e83
 
147e83
 /* Indeces for the symbol names.  */
147e83
 enum
147e83
@@ -139,11 +140,11 @@
147e83
 }
147e83
 
147e83
 
147e83
-/* Internal wrapper around ps_pglobal_lookup.  */
147e83
-extern ps_err_e td_lookup (struct ps_prochandle *ps,
147e83
-			   int idx, psaddr_t *sym_addr) attribute_hidden;
147e83
-
147e83
-
147e83
+/* Internal wrappers around ps_pglobal_lookup.  */
147e83
+extern ps_err_e td_mod_lookup (struct ps_prochandle *ps, const char *modname,
147e83
+			       int idx, psaddr_t *sym_addr) attribute_hidden;
147e83
+#define td_lookup(ps, idx, sym_addr) \
147e83
+  td_mod_lookup ((ps), LIBPTHREAD_SO, (idx), (sym_addr))
147e83
 
147e83
 
147e83
 /* Store in psaddr_t VAR the address of inferior's symbol NAME.  */