From patchwork Sat Oct 18 20:15:40 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kratochvil X-Patchwork-Id: 3282 Received: (qmail 11228 invoked by alias); 18 Oct 2014 20:15:49 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 11208 invoked by uid 89); 18 Oct 2014 20:15:48 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-4.0 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.2 X-Spam-User: qpsmtpd, 2 recipients X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Sat, 18 Oct 2014 20:15:46 +0000 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s9IKFjEt003032 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Sat, 18 Oct 2014 16:15:45 -0400 Received: from host2.jankratochvil.net (ovpn-116-79.ams2.redhat.com [10.36.116.79]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s9IKFfsB000319 (version=TLSv1/SSLv3 cipher=AES128-GCM-SHA256 bits=128 verify=NO); Sat, 18 Oct 2014 16:15:43 -0400 Date: Sat, 18 Oct 2014 22:15:40 +0200 From: Jan Kratochvil To: libc-alpha@sourceware.org Cc: gdb-patches@sourceware.org Subject: [libc patch] __tls_get_addr with link_map * instead of modid Message-ID: <20141018201540.GA26252@host2.jankratochvil.net> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.23 (2014-03-12) X-IsSubscribed: yes 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 * 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 +#include +#include + +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