This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[libc patch] __tls_get_addr with link_map * instead of modid
- From: Jan Kratochvil <jan dot kratochvil at redhat dot com>
- To: libc-alpha at sourceware dot org
- Cc: gdb-patches at sourceware dot org
- Date: Sat, 18 Oct 2014 22:15:40 +0200
- Subject: [libc patch] __tls_get_addr with link_map * instead of modid
- Authentication-results: sourceware.org; auth=none
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