[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

r6660 - in glibc-package/branches/glibc-2.21/debian: . patches patches/any



Author: aurel32
Date: 2015-10-19 10:54:13 +0000 (Mon, 19 Oct 2015)
New Revision: 6660

Added:
   glibc-package/branches/glibc-2.21/debian/patches/any/cvs-tls-dtv.diff
Modified:
   glibc-package/branches/glibc-2.21/debian/changelog
   glibc-package/branches/glibc-2.21/debian/patches/series
Log:
patches/any/cvs-tls-dtv.diff: new patch from upstream to fix fix DTV race,
assert, and DTV_SURPLUS Static TLS limit.  This also reduces the failure
rate of nptl/tst-stack4.  Closes: #793641.

Modified: glibc-package/branches/glibc-2.21/debian/changelog
===================================================================
--- glibc-package/branches/glibc-2.21/debian/changelog	2015-10-19 10:49:58 UTC (rev 6659)
+++ glibc-package/branches/glibc-2.21/debian/changelog	2015-10-19 10:54:13 UTC (rev 6660)
@@ -5,6 +5,9 @@
     to fix a set-but-unused warning in nptl/allocatestack.c, causing a
     build failure.
   * patches/hppa/local-stack-grows-up.diff: rebase.
+  * patches/any/cvs-tls-dtv.diff: new patch from upstream to fix fix DTV race,
+    assert, and DTV_SURPLUS Static TLS limit.  This also reduces the failure
+    rate of nptl/tst-stack4.  Closes: #793641.
 
  -- Aurelien Jarno <aurel32@debian.org>  Mon, 19 Oct 2015 07:05:23 +0200
 

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

Modified: glibc-package/branches/glibc-2.21/debian/patches/series
===================================================================
--- glibc-package/branches/glibc-2.21/debian/patches/series	2015-10-19 10:49:58 UTC (rev 6659)
+++ glibc-package/branches/glibc-2.21/debian/patches/series	2015-10-19 10:54:13 UTC (rev 6660)
@@ -270,3 +270,4 @@
 any/local-math-logb.diff
 any/cvs-ld_pointer_guard.diff
 any/cvs-mangle-tls_dtor_list.diff
+any/cvs-tls-dtv.diff


Reply to: