From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 75087 invoked by alias); 24 May 2019 16:24:37 -0000 Mailing-List: contact gdb-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sourceware.org Received: (qmail 74992 invoked by uid 89); 24 May 2019 16:24:26 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-6.4 required=5.0 tests=AWL,BAYES_00,SPF_HELO_PASS autolearn=ham version=3.3.1 spammy=computing, ids, hoped, locating 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 ESMTP; Fri, 24 May 2019 16:24:14 +0000 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 20C9775733; Fri, 24 May 2019 16:24:03 +0000 (UTC) Received: from oldenburg2.str.redhat.com (dhcp-192-219.str.redhat.com [10.33.192.219]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 435195C2E0; Fri, 24 May 2019 16:23:59 +0000 (UTC) From: Florian Weimer To: Simon Marchi Cc: gdb@sourceware.org, Carlos O'Donell Subject: Re: Getting offset of inital-exec TLS variables on GNU/Linux References: <87o941pej8.fsf@oldenburg2.str.redhat.com> <19f008ac-ffb7-5e15-ae6c-5fc00791c964@simark.ca> <87a7flp2tm.fsf@oldenburg2.str.redhat.com> Date: Fri, 24 May 2019 19:32:00 -0000 Message-ID: <874l5jq0rm.fsf@oldenburg2.str.redhat.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.1 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-IsSubscribed: yes X-SW-Source: 2019-05/txt/msg00046.txt.bz2 * Simon Marchi: > On 2019-05-17 10:34 a.m., Florian Weimer wrote: >> * Simon Marchi: >>=20 >>> On 2019-05-17 6:21 a.m., Florian Weimer wrote: >>>> Is it possible to obtain the offset of initial-exec TLS variable on >>>> GNU/Linux? >>>> >>>> It doesn't seem so because GDB executes the DWARF to access the TLS >>>> variable, so the offset is an implementation detail. Although it is >>>> often visible at the ELF layer. >>>> >>>> Thanks, >>>> Florian >>> >>> Can you clarify a little bit? >>> >>> You are looking for the offset the variable from which point of referen= ce: >>> >>> - The start of the TLS area of this module? >>> - The start of the TLS area of the current thread? >>=20 >> The offset from something related to the thread pointer to the variable, >> for cases where this is constant (specifically, initial-exec TLS >> variables). >>=20 >>> Also, are you looking for something you can find statically, with just = the >>> executable, or are you working in the context of the live process? >>=20 >> I have a live process, and it would be best if the information matched >> that process (even if it uses different libraries than those currently >> installed in the file system). > > Hi Florian, > > I am still a bit unsure of what you are looking for concretely. Are > you looking for a GDB command to print this offset? Do you need to > compute the offset in an external tool? what information are you > starting with? I think that a bit more context would help us help you. I had hoped to get this offset so that I can access the TLS variable without loading libthread_db. I'd be fine with getting the module TLS offset from internal data structures. > GDB uses libthread_db to get the location of TLS variables, which > leaves all implementation details about this to glibc. And since you > are a glibc maintainer, I am not too sure what I can teach you about > this, as you probably know more about this than I do. If I have libpthread_db loaded and can somehow get the thread pointer (e.g., $fs_base on x86-64), then I can get the constant I want just by computing the different between the two, like this: (gdb) print (void *)&tcache - (void *)$fs_base $9 =3D -80 Going back a bit, I'm not sure what the API contract is for DW_OP_GNU_push_tls_address. It's not really clear to me if under the ELF TLS ABI, there is an expectation that the dynamic linker always allocates the TLS space for a DSO as a single block. I've perused the two documents for the GNU ELF TLS ABI, and this is never spelled out explicitly. Outside debugging information, a TLS relocation for non-initial-exec TLS always consists of a pair of a module ID and an offset. Therefore, it should be possible to lazily allocate individual TLS variables within a DSO, by assigning them separate module IDs. But what seems to happen in practice is that there is just one TLS block per DSO, which is allocated at once once the first TLS variable is accessed. Furthermore, the entire TLS block is allocated non-lazily if there is a single initial-exec TLS variable in a DSO. Based on that, I conclude that the module IDs are used only to share TLS variables for the same symbol across multiple modules. Due to this restriction, the module ID for a TLS variable can be inferred from the object that contains the DW_OP_GNU_push_tls_address opcode (and hopefully locating the object based on symbol name in the debugger matches the way dynamic linker search symbols). I wonder if all this implicitly but firmly encodes a correspondence between the argument to DW_OP_GNU_push_tls_address and the offset of a TLS variable, within the TLS block for a DSO=E2=80=94if the DSO has the DF_STATIC_TLS flag set. Asumming this is indeed true, we could add the TLS offset of a DSO to the public part of the link map in the glibc dynamic loader to help debuggers. For TLS variables defined in DF_STATIC_TLS DSOs, it should then be possible to access the TLS variable without the help of libthread_db, assuming that we teach GDB how to compute the TLS variable address from the thread pointer, DSO TLS offset, and variable offset (something binutils seems to know for several targets already, to implement relaxations). Would this be a reasonable thing to do? (Cc:ing Carlos, who probably knows what is really going on here.) Thanks, Florian