This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC][PATCH][BZ #17381]Fetching tls from non native core files



Overview

In order to fetch TLS variable values from non-native (target) core dump file in GDB, a few functions in GLIBC are added, some of them are modified in order to work with both host and target platforms.
This overview describes both of GDB and GLIBC changes.

GLIBC

The problem was how to modify functions designed to work with host platform to read TLS data from target platforms. Platform dependent macros used to calculate start of TLS block are defined in compile time. The idea was to dump those (target) macro values into the core file and later retrieve them on the host platform in order to calculate start of TLS block for target.

td_thr_tlsbase() is modified in order to work with both host and target platforms. td_ta_init_consts() is a new function used for initialization of host TLS macros. td_ta_init_target_consts() is a new function used for initialization of target TLS macros.

GDB

GDB will use these functions in order to fetch TLS variables values from non-native (target) core file.


Regards,
 Nikola and Djordje

td_thr_tlsbase tls fetching formula was resolved in build time. It was
dependent of TLS_TCB_AT_TP, TLS_DTV_AT_TP, TLS_PRE_TCB_SIZE and
NO_TLS_OFFSET. Now it is resolved in runtime in order to achieve cross
core file tls fetching functionality. Macros that are used for fetching
are now kept in thread agent and they are initialized in td_ta_new() on
values for host architecture. When libthread_db user wants to use it for
fetching tls variable from non native core file he will need to call new
function td_ta_init_target_consts(). This function will read those
constants. They are written similarly as size of pthread.


nptl_db/ChangeLog:

2017-06-27 Nikola Prica <nikola.prica@rt-rk.com>
           Djordje Todorovic <djordje.todorovic@rt-rk.com>

	* td_ta_init_target_consts.c: New file.
	* Makefile: Include new file.
	* Versions: New function
	* db-symbols.h: [DB_CONST]
	* db_info.c: [DB_CONST]. Defining [TLS_PRE_TCB_SIZE]
	as 0 if not defined.
	* fetch-value.c: (_td_check_constant) New function
	which takes body of most of (_td_check_size_of) body which
	is refactored regarding that.
	* structs.def: Defining TLS_PRE_TCB_SIZE, TLS_TCB_AT_TP,
	TLS_DTV_AT_TP, NO_TLS_OFFSET constants.
	* td_ta_new.c: (td_ta_init_target_consts) initializes
	thread fetching constants in thread agent.
	* td_thr_tlsbase.c: (td_thr_tlsbase) is modified to work
	for multiple architectures by changing tls fetching formula
	to be evaluated in runtime.
	* thread_db.h: New declaration
	* thread_dbP.h: [DB_CONST], [DB_GET_CONST]

diff --git nptl_db/Makefile nptl_db/Makefile
index 8dc67f4..1b953b3 100644
--- nptl_db/Makefile
+++ nptl_db/Makefile
@@ -44,6 +44,7 @@ libthread_db-routines = td_init td_log td_ta_new td_ta_delete \
 			td_ta_set_event td_ta_event_getmsg \
 			td_ta_clear_event td_symbol_list \
 			td_thr_tlsbase td_thr_tls_get_addr \
+			td_ta_init_target_consts \
 			fetch-value

 libthread_db-inhibit-o = $(filter-out .os,$(object-suffixes))
diff --git nptl_db/Versions nptl_db/Versions
index 063493c..f6ca418 100644
--- nptl_db/Versions
+++ nptl_db/Versions
@@ -21,4 +21,7 @@ libthread_db {
   GLIBC_2.3.3 {
     td_thr_tlsbase;
   }
+  GLIBC_2.26 {
+    td_ta_init_target_consts;
+  }
 }
diff --git nptl_db/db-symbols.h nptl_db/db-symbols.h
index 1572ed5..0aa8832 100644
--- nptl_db/db-symbols.h
+++ nptl_db/db-symbols.h
@@ -23,6 +23,8 @@

 #define DB_STRUCT(type)	\
   DB_LOOKUP_NAME (SYM_SIZEOF_##type, _thread_db_sizeof_##type)
+#define DB_CONST(name) \
+  DB_LOOKUP_NAME (SYM_CONST_##name, _thread_db_const_##name)
 #define DB_STRUCT_FIELD(type, field) \
   DB_LOOKUP_NAME (SYM_##type##_FIELD_##field, _thread_db_##type##_##field)
 #define DB_SYMBOL(name) \
@@ -36,6 +38,7 @@
 # include "structs.def"

 # undef DB_STRUCT
+# undef DB_CONST
 # undef DB_FUNCTION
 # undef DB_SYMBOL
 # undef DB_VARIABLE
diff --git nptl_db/db_info.c nptl_db/db_info.c
index cdf9666..d3a97aa 100644
--- nptl_db/db_info.c
+++ nptl_db/db_info.c
@@ -68,9 +68,15 @@ DESC (_thread_db_pthread_dtvp,
       - (TLS_TCB_SIZE == 0 ? sizeof (tcbhead_t) : 0), union dtv *)
 #endif

+/* Definition of this macro is neccessary for enabling cross core debugging */
+#ifndef TLS_PRE_TCB_SIZE
+#define TLS_PRE_TCB_SIZE 0
+#endif

 #define DB_STRUCT(type) \
   const uint32_t _thread_db_sizeof_##type = sizeof (type);
+#define DB_CONST(name) \
+  const int32_t _thread_db_const_##name = name;
 #define DB_STRUCT_FIELD(type, field) \
   DESC (_thread_db_##type##_##field, \
 	offsetof (type, field), ((type *) 0)->field)
@@ -83,6 +89,7 @@ DESC (_thread_db_pthread_dtvp,
 #define DB_FUNCTION(name) /* Nothing.  */
 #include "structs.def"
 #undef DB_STRUCT
+#undef DB_CONST
 #undef DB_STRUCT_FIELD
 #undef DB_SYMBOL
 #undef DB_FUNCTION
diff --git nptl_db/fetch-value.c nptl_db/fetch-value.c
index 95a746e..f836fce 100644
--- nptl_db/fetch-value.c
+++ nptl_db/fetch-value.c
@@ -22,21 +22,28 @@
 #include <stdint.h>

 td_err_e
+_td_check_constant (td_thragent_t *ta, uint32_t *sizep, int sizep_name)
+{
+  psaddr_t descptr;
+  ps_err_e err = td_lookup (ta->ph, sizep_name, &descptr);
+  if (err == PS_NOSYM)
+    return TD_NOCAPAB;
+  if (err == PS_OK)
+    err = ps_pdread (ta->ph, descptr, sizep, sizeof *sizep);
+  if (err != PS_OK)
+    return TD_ERR;
+  if (*sizep & 0xff000000U)
+    *sizep = bswap_32 (*sizep);
+  return TD_OK;
+}
+
+
+
+td_err_e
 _td_check_sizeof (td_thragent_t *ta, uint32_t *sizep, int sizep_name)
 {
   if (*sizep == 0)
-    {
-      psaddr_t descptr;
-      ps_err_e err = td_lookup (ta->ph, sizep_name, &descptr);
-      if (err == PS_NOSYM)
-	return TD_NOCAPAB;
-      if (err == PS_OK)
-	err = ps_pdread (ta->ph, descptr, sizep, sizeof *sizep);
-      if (err != PS_OK)
-	return TD_ERR;
-      if (*sizep & 0xff000000U)
-	*sizep = bswap_32 (*sizep);
-    }
+      return _td_check_constant(ta,sizep, sizep_name);
   return TD_OK;
 }

diff --git nptl_db/structs.def nptl_db/structs.def
index 8a65afd..aea5384 100644
--- nptl_db/structs.def
+++ nptl_db/structs.def
@@ -44,6 +44,11 @@
 # endif
 #endif /* DB_RTLD_GLOBAL_FIELD */

+DB_CONST (TLS_PRE_TCB_SIZE)
+DB_CONST (TLS_TCB_AT_TP)
+DB_CONST (TLS_DTV_AT_TP)
+DB_CONST (NO_TLS_OFFSET)
+
 DB_STRUCT (pthread)
 DB_STRUCT_FIELD (pthread, list)
 DB_STRUCT_FIELD (pthread, report_events)
diff --git nptl_db/td_ta_init_target_consts.c nptl_db/td_ta_init_target_consts.c
new file mode 100644
index 0000000..d430022
--- /dev/null
+++ nptl_db/td_ta_init_target_consts.c
@@ -0,0 +1,58 @@
+/* Initialization function of thread debugger support library.
+   Copyright (C) 1999-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "thread_dbP.h"
+
+td_err_e
+td_ta_init_target_consts (td_thragent_t *ta)
+{
+  td_err_e err;
+
+  err = _td_check_constant (ta, DB_GET_CONST (&ta, TLS_TCB_AT_TP),
+                            SYM_CONST_TLS_TCB_AT_TP);
+  if ( err != TD_OK)
+    return err;
+  err = _td_check_constant (ta, DB_GET_CONST (&ta, TLS_DTV_AT_TP),
+                            SYM_CONST_TLS_DTV_AT_TP);
+  if ( err != TD_OK)
+    return err;
+
+ if (!(DB_GET_CONST (ta, TLS_TCB_AT_TP) ^ DB_GET_CONST (ta, TLS_DTV_AT_TP)))
+    return TD_ERR;
+
+
+  if (DB_GET_CONST (ta, TLS_DTV_AT_TP))
+    {
+      err = _td_check_constant (ta, DB_GET_CONST (&ta, TLS_PRE_TCB_SIZE),
+                                SYM_CONST_TLS_PRE_TCB_SIZE);
+      if ( err != TD_OK)
+        return err;
+    }
+  else
+    {
+      DB_GET_CONST (ta, TLS_PRE_TCB_SIZE) = 0;
+    }
+
+  err = _td_check_constant (ta, DB_GET_CONST (&ta, NO_TLS_OFFSET),
+                            SYM_CONST_NO_TLS_OFFSET);
+  if ( err != TD_OK)
+    return err;
+
+  return TD_OK;
+}
\ No newline at end of file
diff --git nptl_db/td_ta_new.c nptl_db/td_ta_new.c
index aec2356..7d924af 100644
--- nptl_db/td_ta_new.c
+++ nptl_db/td_ta_new.c
@@ -21,6 +21,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <version.h>
+#include <link.h>

 #include "thread_dbP.h"

@@ -29,6 +30,21 @@
    be exactly one so we don't spend much though on making it fast.  */
 LIST_HEAD (__td_agent_list);

+static void
+td_ta_init_consts (td_thragent_t *ta)
+{
+  DB_GET_CONST (ta, TLS_TCB_AT_TP) = TLS_TCB_AT_TP;
+  DB_GET_CONST (ta, TLS_DTV_AT_TP) = TLS_DTV_AT_TP;
+#if TLS_DTV_AT_TP
+  DB_GET_CONST (ta, TLS_PRE_TCB_SIZE) = TLS_PRE_TCB_SIZE;
+#elif TLS_TCB_AT_TP
+  DB_GET_CONST (ta, TLS_PRE_TCB_SIZE) = 0;
+#else
+# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+#endif
+  DB_GET_CONST (ta, NO_TLS_OFFSET) = NO_TLS_OFFSET;
+}
+

 td_err_e
 td_ta_new (struct ps_prochandle *ps, td_thragent_t **ta)
@@ -60,5 +76,7 @@ td_ta_new (struct ps_prochandle *ps, td_thragent_t **ta)
   /* Now add the new agent descriptor to the list.  */
   list_add (&(*ta)->list, &__td_agent_list);

+  td_ta_init_consts (*ta);
+
   return TD_OK;
 }
diff --git nptl_db/td_thr_tlsbase.c nptl_db/td_thr_tlsbase.c
index 11d7ad3..dd6afbc 100644
--- nptl_db/td_thr_tlsbase.c
+++ nptl_db/td_thr_tlsbase.c
@@ -202,19 +202,17 @@ td_thr_tlsbase (const td_thrhandle_t *th,
       if (err != TD_OK)
 	return err;
       ptrdiff_t tlsoff = (uintptr_t)temp;
+      int8_t no_tls_offset = DB_GET_CONST (th->th_ta_p, NO_TLS_OFFSET);
+      int8_t forced_dynamic_tls_offset = no_tls_offset - 1;

-      if (tlsoff != FORCED_DYNAMIC_TLS_OFFSET
-	  && tlsoff != NO_TLS_OFFSET)
+      if (tlsoff != forced_dynamic_tls_offset
+	  && tlsoff != no_tls_offset)
 	{
 	  psaddr_t tp = pd;
+ int8_t variant_sign = ((DB_GET_CONST(th->th_ta_p, TLS_TCB_AT_TP)) ? (-1) : (1)); + uint32_t tls_pre_tcb_size = DB_GET_CONST (th->th_ta_p, TLS_PRE_TCB_SIZE);

-#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
+	  dtvptr = tp + variant_sign * tlsoff + tls_pre_tcb_size;

 	  *base = dtvptr;
 	  return TD_OK;
diff --git nptl_db/thread_db.h nptl_db/thread_db.h
index d8e82b7..60cce58 100644
--- nptl_db/thread_db.h
+++ nptl_db/thread_db.h
@@ -409,6 +409,10 @@ extern td_err_e td_thr_tlsbase (const td_thrhandle_t *__th,
 				unsigned long int __modid,
 				psaddr_t *__base);

+/* Set thread_db constants for fetching tls. This should only be called when
+   fetching tls from cross target core file. */
+extern td_err_e td_ta_init_target_consts (td_thragent_t *ta);
+
 /* Get address of thread local variable.  */
 extern td_err_e td_thr_tls_get_addr (const td_thrhandle_t *__th,
 				     psaddr_t __map_address, size_t __offset,
diff --git nptl_db/thread_dbP.h nptl_db/thread_dbP.h
index c88ee29..1a67888 100644
--- nptl_db/thread_dbP.h
+++ nptl_db/thread_dbP.h
@@ -36,12 +36,14 @@
 enum
   {
 # define DB_STRUCT(type)		SYM_SIZEOF_##type,
+# define DB_CONST(name)		SYM_CONST_##name,
 # define DB_STRUCT_FIELD(type, field)	SYM_##type##_FIELD_##field,
 # define DB_SYMBOL(name)		SYM_##name,
 # define DB_FUNCTION(name)		SYM_##name,
 # define DB_VARIABLE(name)		SYM_##name, SYM_DESC_##name,
 # include "structs.def"
 # undef DB_STRUCT
+# undef DB_CONST
 # undef DB_STRUCT_FIELD
 # undef DB_SYMBOL
 # undef DB_FUNCTION
@@ -88,6 +90,8 @@ struct td_thragent
   /* Cached values read from the inferior.  */
 # define DB_STRUCT(type) \
   uint32_t ta_sizeof_##type;
+# define DB_CONST(name) \
+  uint32_t ta_const_##name;
 # define DB_STRUCT_FIELD(type, field) \
   db_desc_t ta_field_##type##_##field;
 # define DB_SYMBOL(name) \
@@ -99,6 +103,7 @@ struct td_thragent
   db_desc_t ta_var_##name;
 # include "structs.def"
 # undef DB_STRUCT
+# undef DB_CONST
 # undef DB_STRUCT_FIELD
 # undef DB_FUNCTION
 # undef DB_SYMBOL
@@ -229,6 +234,9 @@ extern td_err_e _td_fetch_value_local (td_thragent_t *ta,
    : _td_store_value ((ta), (ta)->ta_var_##name, SYM_DESC_##name, 	      \
 		      (psaddr_t) 0 + (idx), (ta)->ta_addr_##name, (value)))

+
+#define DB_GET_CONST(ta, name) ta->ta_const_##name
+
 /* Helper functions for those.  */
 extern td_err_e _td_store_value (td_thragent_t *ta,
 				 db_desc_t field, int descriptor_name,
@@ -261,6 +269,8 @@ extern td_err_e _td_store_value_local (td_thragent_t *ta,

 extern td_err_e _td_check_sizeof (td_thragent_t *ta, uint32_t *sizep,
 				  int sizep_name) attribute_hidden;
+extern td_err_e _td_check_constant (td_thragent_t *ta, uint32_t *sizep,
+          int sizep_name) attribute_hidden;

 extern td_err_e __td_ta_lookup_th_unique (const td_thragent_t *ta,
 					  lwpid_t lwpid, td_thrhandle_t *th);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]