* [libc patch] __tls_get_addr with link_map * instead of modid
@ 2014-10-18 20:15 Jan Kratochvil
2014-10-18 21:20 ` Rich Felker
` (3 more replies)
0 siblings, 4 replies; 15+ messages in thread
From: Jan Kratochvil @ 2014-10-18 20:15 UTC (permalink / raw)
To: libc-alpha; +Cc: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 1538 bytes --]
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
[-- Attachment #2: glibctls1.patch --]
[-- Type: text/plain, Size: 4391 bytes --]
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.
\f
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
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [libc patch] __tls_get_addr with link_map * instead of modid
2014-10-18 20:15 [libc patch] __tls_get_addr with link_map * instead of modid Jan Kratochvil
@ 2014-10-18 21:20 ` Rich Felker
2014-10-18 21:27 ` Jan Kratochvil
2014-10-23 10:03 ` Alexandre Oliva
` (2 subsequent siblings)
3 siblings, 1 reply; 15+ messages in thread
From: Rich Felker @ 2014-10-18 21:20 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: libc-alpha, gdb-patches
On Sat, Oct 18, 2014 at 10:15:40PM +0200, Jan Kratochvil wrote:
> 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.
This sounds more appealing. I don't know how much interest you have in
non-glibc systems, but from our side with musl libc, we presently
don't have a libthread_db and don't plan to, so anything that makes
gdb work better without it (or even just preserves current
functionality without it) is preferable.
> 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).
I think this is the worst option.
> 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 don't see how this would work; how would you request the dynamic
linker to resolve that for you?
Rich
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [libc patch] __tls_get_addr with link_map * instead of modid
2014-10-18 21:20 ` Rich Felker
@ 2014-10-18 21:27 ` Jan Kratochvil
2014-10-18 21:44 ` Rich Felker
0 siblings, 1 reply; 15+ messages in thread
From: Jan Kratochvil @ 2014-10-18 21:27 UTC (permalink / raw)
To: Rich Felker; +Cc: libc-alpha, gdb-patches
On Sat, 18 Oct 2014 23:20:48 +0200, Rich Felker wrote:
> > 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 don't see how this would work; how would you request the dynamic
> linker to resolve that for you?
When the inferior is running the relocation is already resolved. So GDB can
just read the module id from relocation's location. The problem is that
'.rela.dyn' is not parsed by BFD so one would either have to extend BFD to
parse it or provide a separate '.rela.dyn' parser in GDB for each arch.
From '.rela.dyn' one can find the symbol name and relocation's location.
Relocation section '.rela.dyn' at offset 0x520 contains 10 entries:
Offset Info Type Symbol's Value Symbol's Name + Addend
0000000000200fd0 0000000a00000010 R_X86_64_DTPMOD64 0000000000000000 x + 0
0000000000200fd8 0000000a00000011 R_X86_64_DTPOFF64 0000000000000000 x + 0
7ac: 66 48 8d 3d 1c 08 20 data32 lea 0x20081c(%rip),%rdi # 200fd0 <_DYNAMIC+0x1d8>
7b3: 00
7b4: 66 66 48 e8 d4 fe ff data32 data32 callq 690 <__tls_get_addr@plt>
7bb: ff
But that is an offtopic discussion for this patch.
Jan
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [libc patch] __tls_get_addr with link_map * instead of modid
2014-10-18 21:27 ` Jan Kratochvil
@ 2014-10-18 21:44 ` Rich Felker
0 siblings, 0 replies; 15+ messages in thread
From: Rich Felker @ 2014-10-18 21:44 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: libc-alpha, gdb-patches
On Sat, Oct 18, 2014 at 11:27:27PM +0200, Jan Kratochvil wrote:
> On Sat, 18 Oct 2014 23:20:48 +0200, Rich Felker wrote:
> > > 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 don't see how this would work; how would you request the dynamic
> > linker to resolve that for you?
>
> When the inferior is running the relocation is already resolved. So GDB can
This is only the case if the module actually has a relocation for
local TLS contained in it. I'm not sure how you could assume this is
always the case, but maybe in cases where it's not true there's no
reasonable way you'd want to access TLS in that way.
Rich
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [libc patch] __tls_get_addr with link_map * instead of modid
2014-10-18 20:15 [libc patch] __tls_get_addr with link_map * instead of modid Jan Kratochvil
2014-10-18 21:20 ` Rich Felker
@ 2014-10-23 10:03 ` Alexandre Oliva
2014-10-23 12:52 ` Jan Kratochvil
2014-10-24 1:47 ` Mike Frysinger
2014-10-24 2:21 ` Carlos O'Donell
3 siblings, 1 reply; 15+ messages in thread
From: Alexandre Oliva @ 2014-10-23 10:03 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: libc-alpha, gdb-patches
On Oct 18, 2014, Jan Kratochvil <jan.kratochvil@redhat.com> wrote:
> * A new glibc function like __tls_get_addr that takes a link_map address
> rather than a module id.
dlinfo offers operations to both map a link_map (AKA dlopen handle) to
the modid, and to get the TLS base address for that link_map. I suppose
calling dlinfo directly is not an option, since there's no guarantee
that libdl will have been linked in.
However, the implementat of dlinfo RTLD_DI_TLS_DATA relies on
_dl_tls_get_addr_soft, that not only takes a struct link_map*, but also
refrains from assigning a TLS segment for the module in the running
thread when one isn't allocated already. I think this would be
preferrable behavior for a debugger, to avoid heisenbugs.
This symbol is not exported by ld.so, but this shouldn't stop GDB from
using it, since it is present in the symbol table as a local (hidden)
symbol.
--
Alexandre Oliva, freedom fighter http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/ FSF Latin America board member
Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [libc patch] __tls_get_addr with link_map * instead of modid
2014-10-23 10:03 ` Alexandre Oliva
@ 2014-10-23 12:52 ` Jan Kratochvil
0 siblings, 0 replies; 15+ messages in thread
From: Jan Kratochvil @ 2014-10-23 12:52 UTC (permalink / raw)
To: Alexandre Oliva; +Cc: libc-alpha, gdb-patches
On Thu, 23 Oct 2014 12:02:34 +0200, Alexandre Oliva wrote:
> dlinfo offers operations to both map a link_map (AKA dlopen handle) to
> the modid, and to get the TLS base address for that link_map. I suppose
> calling dlinfo directly is not an option, since there's no guarantee
> that libdl will have been linked in.
Thanks for the dlinfo() information; but I agree libdl is not an option for
the "GDB JIT" purpose.
> However, the implementat of dlinfo RTLD_DI_TLS_DATA relies on
> _dl_tls_get_addr_soft, that not only takes a struct link_map*, but also
> refrains from assigning a TLS segment for the module in the running
> thread when one isn't allocated already. I think this would be
> preferrable behavior for a debugger, to avoid heisenbugs.
OK, I will try to use _dl_tls_get_addr_soft for GDB as is.
Although I think the TLS segment allocation would be better for the "GDB JIT"
purpose. Imagine an inferior shared library:
__thread int tlsvar;
And user asking for:
(gdb) compile code tlsvar = 5;
I think it is better to do the TLS segment allocation than to refuse the
command to the user. But someone may have an opposite opinion.
> This symbol is not exported by ld.so, but this shouldn't stop GDB from
> using it, since it is present in the symbol table as a local (hidden)
> symbol.
It is OK although when we talk about it it is not perfect. Some distros strip
all shared libraries and then they have problem libthread_db cannot find
libpthread .symtab-only _thread_db_* symbols. _dl_tls_get_addr_soft() will
have the same problem. But that is mostly off-topic here now.
Thanks,
Jan
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [libc patch] __tls_get_addr with link_map * instead of modid
2014-10-18 20:15 [libc patch] __tls_get_addr with link_map * instead of modid Jan Kratochvil
2014-10-18 21:20 ` Rich Felker
2014-10-23 10:03 ` Alexandre Oliva
@ 2014-10-24 1:47 ` Mike Frysinger
2014-10-24 2:21 ` Carlos O'Donell
3 siblings, 0 replies; 15+ messages in thread
From: Mike Frysinger @ 2014-10-24 1:47 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: libc-alpha, gdb-patches
[-- Attachment #1: Type: text/plain, Size: 612 bytes --]
On 18 Oct 2014 22:15, Jan Kratochvil wrote:
> 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.
if access to an updated ia64 system is desired, i can make it happen.
$ /lib/libc.so.6.1 | head -1
GNU C Library (Gentoo 2.19-r1 p2) stable release version 2.19, by Roland McGrath et al.
$ ld --version | head -1
GNU ld (Gentoo 2.24 p1.4) 2.24
$ gcc --version | head -1
gcc (Gentoo 4.7.4 p1.1, pie-0.5.5) 4.7.4
$ uname -r -m
3.14.14-gentoo ia64
$ gdb --version | head -1
GNU gdb (Gentoo 7.6.2 p1) 7.6.2
-mike
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [libc patch] __tls_get_addr with link_map * instead of modid
2014-10-18 20:15 [libc patch] __tls_get_addr with link_map * instead of modid Jan Kratochvil
` (2 preceding siblings ...)
2014-10-24 1:47 ` Mike Frysinger
@ 2014-10-24 2:21 ` Carlos O'Donell
[not found] ` <20141024093834.GA24090@host2.jankratochvil.net>
3 siblings, 1 reply; 15+ messages in thread
From: Carlos O'Donell @ 2014-10-24 2:21 UTC (permalink / raw)
To: Jan Kratochvil, libc-alpha; +Cc: gdb-patches
On 10/18/2014 04:15 PM, Jan Kratochvil wrote:
> 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 do not think this is a good solution.
If you use this function in jit'd code, you've now deviated from what normal
TLS-accessing sequences look like. Now your code deviates from the published
tls.pdf in the call sequence, and is undocumented, though simple. On top of
that it's a stop-gap measure until we fix things correctly. Because of these
things I object to adding this function to ld's API.
I don't like libthread_db either, but it avoids us having to put a stop-gap
API in ld. I say stop-gap because the real solution is going to be to use
python/DWARF, not any API in ld.
I'm in favour of exactly 3 things:
* New function in libthread_db.
* Heuristics in gdb if libthread_db is not new enough.
* A python or DWARF based parser to replace libthread_db.
Cheers,
Carlos.
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2014-10-25 6:26 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-10-18 20:15 [libc patch] __tls_get_addr with link_map * instead of modid Jan Kratochvil
2014-10-18 21:20 ` Rich Felker
2014-10-18 21:27 ` Jan Kratochvil
2014-10-18 21:44 ` Rich Felker
2014-10-23 10:03 ` Alexandre Oliva
2014-10-23 12:52 ` Jan Kratochvil
2014-10-24 1:47 ` Mike Frysinger
2014-10-24 2:21 ` Carlos O'Donell
[not found] ` <20141024093834.GA24090@host2.jankratochvil.net>
2014-10-24 14:22 ` Carlos O'Donell
2014-10-24 14:40 ` Jan Kratochvil
2014-10-24 15:00 ` Carlos O'Donell
2014-10-25 5:55 ` Rich Felker
2014-10-25 6:14 ` Jan Kratochvil
2014-10-25 6:26 ` Rich Felker
2014-10-24 15:56 ` Pedro Alves
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox