This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB 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]

[libc patch] __tls_get_addr with link_map * instead of modid


Hi,

https://sourceware.org/glibc/wiki/Tools%20Interface%20NG
	From within the inferior: Functions that are inserted into a process's
	address space by the debugger need to be able to access the TLS area
	for that thread. GDB can use DWARF to to find the offset within the
	TLS of a variable and pass that in as a compile time offset into the
	function being inserted into the traced process's address space.
	However, to be able to get to the address of the TLS area for
	a particular thread, it needs to know the module id to make a call to
	__tls_get_addr(). This module id is burried in a private area of the
	link_map data structure which is subject to change. It is therefore
	proposed that we add a new function to libthread_db which extracts the
	module id from the link map. 

Other option suggested by Tom Tromey is implemented by this patch:

* A new glibc function like __tls_get_addr that takes a link_map address
  rather than a module id.

I expect I will have to also implement this Tom Tromey's suggestion to GDB but
I haven't tried to implement it yet:

* Bake more information about struct link_map into gdb (least preferred
  IMO).

Additionally one could also fetch the module id from R_X86_64_DTPMOD64 but that
would require arch specific code in GDB.  I do not plan to implement this way.


I have failed to test this patch on ia64 as I have available only RHEL-5 which
has too old ld and then I gave it up on too old Linux kernel include files.

I haven't written any GDB support for this patch yet.


Thanks,
Jan
libc/
2014-10-18  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* NEWS: Add _dl_tls_get_addr_link_map note.
	* elf/Makefile (tests): Add tst-tls20.
	($(objpfx)tst-tls20): New.
	* elf/Versions (GLIBC_2.21): New.
	* elf/dl-tls.c: Conditionally define GET_ADDR_FORWARD.
	(_dl_tls_get_addr_link_map): New function.
	* elf/tst-tls20.c: New file.
	* sysdeps/ia64/dl-tls.h (GET_ADDR_FORWARD): New.

diff --git a/NEWS b/NEWS
index f3e222d..3e3d33d 100644
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,9 @@ Version 2.21
 * The following bugs are resolved with this release:
 
   6652, 12926, 14171, 15884, 17266, 17363, 17370, 17371, 17411, 17460.
+
+* ELF thread-local storage support (TLS) has now new function
+  _dl_tls_get_addr_link_map in ld.so.
 
 Version 2.20
 
diff --git a/elf/Makefile b/elf/Makefile
index 94074f3..b634b8d 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -146,7 +146,7 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
 	 tst-stackguard1 tst-addr1 tst-thrlock \
 	 tst-unique1 tst-unique2 tst-unique3 tst-unique4 \
 	 tst-initorder tst-initorder2 tst-relsort1 tst-null-argv \
-	 tst-ptrguard1
+	 tst-ptrguard1 tst-tls20
 #	 reldep9
 ifeq ($(build-hardcoded-path-in-tests),yes)
 tests += tst-dlopen-aout
@@ -513,6 +513,7 @@ $(objpfx)tst-initordera3.so: $(objpfx)tst-initorderb2.so $(objpfx)tst-initorderb
 $(objpfx)tst-initordera4.so: $(objpfx)tst-initordera3.so
 $(objpfx)tst-initorder: $(objpfx)tst-initordera4.so $(objpfx)tst-initordera1.so $(objpfx)tst-initorderb2.so
 $(objpfx)tst-null-argv: $(objpfx)tst-null-argv-lib.so
+$(objpfx)tst-tls20: $(objpfx)ld.so
 
 tst-null-argv-ENV = LD_DEBUG=all LD_DEBUG_OUTPUT=$(objpfx)tst-null-argv.debug.out
 LDFLAGS-nodel2mod3.so = $(no-as-needed)
diff --git a/elf/Versions b/elf/Versions
index 23deda9..af9f824 100644
--- a/elf/Versions
+++ b/elf/Versions
@@ -50,6 +50,9 @@ ld {
     # stack canary
     __stack_chk_guard;
   }
+  GLIBC_2.21 {
+    _dl_tls_get_addr_link_map;
+  }
   GLIBC_PRIVATE {
     # Those are in the dynamic linker, but used by libc.so.
     __libc_enable_secure;
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
index 5204fda..4ac4550 100644
--- a/elf/dl-tls.c
+++ b/elf/dl-tls.c
@@ -547,6 +547,11 @@ rtld_hidden_def (_dl_deallocate_tls)
 # ifndef GET_ADDR_OFFSET
 #  define GET_ADDR_OFFSET ti->ti_offset
 # endif
+# ifndef GET_ADDR_FORWARD
+#  define GET_ADDR_FORWARD(modid, offset)	\
+   tls_index ti = { modid, offset };		\
+   return __tls_get_addr (&ti);
+# endif
 
 
 static void *
@@ -807,6 +812,15 @@ __tls_get_addr (GET_ADDR_ARGS)
 
   return (char *) p + GET_ADDR_OFFSET;
 }
+
+/* Provide __tls_get_addr interface using link_map *
+   when GET_ADDR_MODULE value is not known.  */
+void *
+_dl_tls_get_addr_link_map (const struct link_map *ti_module_link_map,
+			   unsigned long int ti_offset)
+{
+  GET_ADDR_FORWARD (ti_module_link_map->l_tls_modid, ti_offset)
+}
 #endif
 
 
diff --git a/elf/tst-tls20.c b/elf/tst-tls20.c
new file mode 100644
index 0000000..24dcb0d
--- /dev/null
+++ b/elf/tst-tls20.c
@@ -0,0 +1,24 @@
+#include <link.h>
+#include <string.h>
+#include <stdlib.h>
+
+extern
+  void *_dl_tls_get_addr_link_map (const struct link_map *ti_module_link_map,
+				   unsigned long int ti_offset);
+
+#define TLSVAR_OFFSET 0
+__thread int tlsvar;
+
+int
+main (void)
+{
+  /* Main executable is the first entry.
+     Cast it for internal libc headers compatibility.  */
+  struct link_map *map = (void *) _r_debug.r_map;
+  int *tlsvarp = _dl_tls_get_addr_link_map (map, TLSVAR_OFFSET);
+
+  if (tlsvarp != &tlsvar)
+    abort ();
+
+  return 0;
+}
diff --git a/sysdeps/ia64/dl-tls.h b/sysdeps/ia64/dl-tls.h
index 9e63c8e..22022c8 100644
--- a/sysdeps/ia64/dl-tls.h
+++ b/sysdeps/ia64/dl-tls.h
@@ -19,10 +19,12 @@
 
 /* On IA-64 the __tls_get_addr function take the module ID and the
    offset as parameters.  */
-#define GET_ADDR_ARGS		size_t tls_ia64_m, size_t tls_ia64_offset
-#define GET_ADDR_PARAM		tls_ia64_m, tls_ia64_offset
-#define GET_ADDR_MODULE		tls_ia64_m
-#define GET_ADDR_OFFSET		tls_ia64_offset
+#define GET_ADDR_ARGS			size_t tls_ia64_m, \
+					size_t tls_ia64_offset
+#define GET_ADDR_PARAM			tls_ia64_m, tls_ia64_offset
+#define GET_ADDR_MODULE			tls_ia64_m
+#define GET_ADDR_OFFSET			tls_ia64_offset
+#define GET_ADDR_FORWARD(modid, offset)	return __tls_get_addr (modid, offset);
 
 /* We have no tls_index type.  */
 #define DONT_USE_TLS_INDEX	1

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