From patchwork Thu Aug 17 18:12:26 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tatsuyuki Ishi X-Patchwork-Id: 1822500 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.a=rsa-sha256 header.s=default header.b=YJ3tkzuY; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=sourceware.org (client-ip=8.43.85.97; helo=server2.sourceware.org; envelope-from=libc-alpha-bounces+incoming=patchwork.ozlabs.org@sourceware.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4RRY5Y6Yy7z22PN for ; Fri, 18 Aug 2023 04:13:05 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id ABF763853568 for ; Thu, 17 Aug 2023 18:13:03 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org ABF763853568 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1692295983; bh=hrDFw5LioZAcr5dZUkEpow9RVvw7FUy5TO4zeAVZcO0=; h=To:Cc:Subject:Date:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From:Reply-To:From; b=YJ3tkzuYZWzzRggAMCQMRHXh0LN2Cv0xiPfvzdtZp5t67FmiXpnYbXI7TKxMOxZ/0 /JUQVgNCFrqL8DckKg4G5qlnKBFnGk6c366Eb72zyjKoNmjzZpW4r4rWI6M8ZYpcAl 6WhLveRme0dKrJnHrYSSndfFQPNClSVxiVqtoJ1Y= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pf1-x42d.google.com (mail-pf1-x42d.google.com [IPv6:2607:f8b0:4864:20::42d]) by sourceware.org (Postfix) with ESMTPS id CBA6D385C6DE for ; Thu, 17 Aug 2023 18:12:45 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org CBA6D385C6DE Received: by mail-pf1-x42d.google.com with SMTP id d2e1a72fcca58-6873f64a290so18692b3a.0 for ; Thu, 17 Aug 2023 11:12:45 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1692295964; x=1692900764; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=hrDFw5LioZAcr5dZUkEpow9RVvw7FUy5TO4zeAVZcO0=; b=DLsA5ERAYM6Z5gN4qS5uiKudNA+YWJ3EZ6exURANT/BZT8jcWCmE0C1VP6NA3gwtIJ 5bIVtr2d6bytwpwFkg3vnKBv8/g3yF1xYWKrn8Q0T9QF9Zvyj52shKP5CZhOwlnMebw/ /ZX3R6G6K6VdmIkGA2BzPtHR2PgahihWTs8UMruLmRS1lSU/wodI7kalGR4d6/ZHuLUF b/ska0qsueEN53Qma5/m7Nku5INqRT9iy3rLKIQHBunQKWKgZmnW2sB35ott2FvyUVa/ MqE9dCbzyETnfKM8Zc3+c4Ny7ShQJPLNRlUKtqpbqioA9D2AoBMXQCMrxL7iJGNIVUQt cA/Q== X-Gm-Message-State: AOJu0YyVYv0LVkNJd2kT2FG2H3HJnyMGqVgmv2IxIQCJI6Siaa1GxBLj 2gMV1KwJxF9y9QWmPqXYOmhxZh9hWH9ealZp X-Google-Smtp-Source: AGHT+IEd9S86zcSe8A+Gv/rcV2Mee5LXvryXfeBmrtFAMSmXYxM1lZqP614P84oqWS+Bk4AICDxdmw== X-Received: by 2002:a05:6a00:3395:b0:677:3439:874a with SMTP id cm21-20020a056a00339500b006773439874amr294098pfb.3.1692295964134; Thu, 17 Aug 2023 11:12:44 -0700 (PDT) Received: from localhost (zz20184013906F627101.userreverse.dion.ne.jp. [111.98.113.1]) by smtp.gmail.com with ESMTPSA id a14-20020aa7864e000000b006827c26f148sm56767pfo.195.2023.08.17.11.12.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 17 Aug 2023 11:12:43 -0700 (PDT) To: libc-alpha@sourceware.org Cc: rui314@gmail.com, ruiu@bluewhale.systems, Tatsuyuki Ishi Subject: [PATCH] RISC-V: Implement TLS Descriptors. Date: Fri, 18 Aug 2023 03:12:26 +0900 Message-ID: <20230817181228.122674-2-ishitatsuyuki@gmail.com> X-Mailer: git-send-email 2.41.0 MIME-Version: 1.0 X-Spam-Status: No, score=-10.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Tatsuyuki Ishi via Libc-alpha From: Tatsuyuki Ishi Reply-To: Tatsuyuki Ishi Errors-To: libc-alpha-bounces+incoming=patchwork.ozlabs.org@sourceware.org Sender: "Libc-alpha" This is mostly based off AArch64 implementation, with some adaptations to different TLS DTV offsets and calling conventions. --- No regression in binutils and gcc tests for rv64gc, tested alongside the gcc and binutils implementation (posted at the same time). This contribution is made on behalf of Blue Whale Systems, which has copyright assignment on file with the FSF. sysdeps/riscv/Makefile | 8 ++ sysdeps/riscv/dl-lookupcfg.h | 27 +++++ sysdeps/riscv/dl-machine.h | 27 +++++ sysdeps/riscv/dl-tlsdesc.S | 204 +++++++++++++++++++++++++++++++++++ sysdeps/riscv/dl-tlsdesc.h | 49 +++++++++ sysdeps/riscv/linkmap.h | 1 + sysdeps/riscv/tlsdesc.c | 38 +++++++ sysdeps/riscv/tlsdesc.sym | 19 ++++ 8 files changed, 373 insertions(+) create mode 100644 sysdeps/riscv/dl-lookupcfg.h create mode 100644 sysdeps/riscv/dl-tlsdesc.S create mode 100644 sysdeps/riscv/dl-tlsdesc.h create mode 100644 sysdeps/riscv/tlsdesc.c create mode 100644 sysdeps/riscv/tlsdesc.sym diff --git a/sysdeps/riscv/Makefile b/sysdeps/riscv/Makefile index 8fb10b164f..bb4bcd29b2 100644 --- a/sysdeps/riscv/Makefile +++ b/sysdeps/riscv/Makefile @@ -2,6 +2,14 @@ ifeq ($(subdir),misc) sysdep_headers += sys/asm.h endif +ifeq ($(subdir),elf) +sysdep-dl-routines += tlsdesc dl-tlsdesc +endif + +ifeq ($(subdir),csu) +gen-as-const-headers += tlsdesc.sym +endif + # RISC-V's assembler also needs to know about PIC as it changes the definition # of some assembler macros. ASFLAGS-.os += $(pic-ccflag) diff --git a/sysdeps/riscv/dl-lookupcfg.h b/sysdeps/riscv/dl-lookupcfg.h new file mode 100644 index 0000000000..c003a27f63 --- /dev/null +++ b/sysdeps/riscv/dl-lookupcfg.h @@ -0,0 +1,27 @@ +/* Configuration of lookup functions. + Copyright (C) 2006-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + . */ + +#define DL_UNMAP_IS_SPECIAL + +#include_next + +struct link_map; + +extern void _dl_unmap (struct link_map *map); + +#define DL_UNMAP(map) _dl_unmap (map) \ No newline at end of file diff --git a/sysdeps/riscv/dl-machine.h b/sysdeps/riscv/dl-machine.h index c0c9bd93ad..ad5b3b20d0 100644 --- a/sysdeps/riscv/dl-machine.h +++ b/sysdeps/riscv/dl-machine.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -219,6 +220,32 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[], } break; + case R_RISCV_TLSDESC: + struct tlsdesc *td = (struct tlsdesc *) addr_field; + if (sym == NULL) + { + td->entry = _dl_tlsdesc_undefweak; + td->arg = reloc->r_addend; + } + else + { +# ifndef SHARED + CHECK_STATIC_TLS (map, sym_map); +# else + if (!TRY_STATIC_TLS (map, sym_map)) + { + td->entry = _dl_tlsdesc_dynamic; + td->arg = _dl_make_tlsdesc_dynamic (sym_map, sym->st_value + reloc->r_addend); + } + else +# endif + { + td->entry = _dl_tlsdesc_return; + td->arg = (void *)(TLS_TPREL_VALUE(sym_map, sym) + reloc->r_addend); + } + } + break; + case R_RISCV_COPY: { if (__glibc_unlikely (sym == NULL)) diff --git a/sysdeps/riscv/dl-tlsdesc.S b/sysdeps/riscv/dl-tlsdesc.S new file mode 100644 index 0000000000..bc48939739 --- /dev/null +++ b/sysdeps/riscv/dl-tlsdesc.S @@ -0,0 +1,204 @@ +/* Thread-local storage handling in the ELF dynamic linker. + RISC-V version. + Copyright (C) 2023 Free Software Foundation, Inc. + + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include + +#ifdef __riscv_float_abi_soft +# define FRAME_SIZE (-((-12 * SZREG) & ALMASK)) +#else +# define FRAME_SIZE (-((-12 * SZREG - 20 * SZFREG) & ALMASK)) +#endif + + .text + + /* Compute the thread pointer offset for symbols in the static + TLS block. The offset is the same for all threads. + Prototype: + _dl_tlsdesc_return (tlsdesc *) ; + */ +ENTRY (_dl_tlsdesc_return) + REG_L a0, SZREG(a0) + jr t0 +END (_dl_tlsdesc_return) + + /* Handler for undefined weak TLS symbols. + Prototype: + _dl_tlsdesc_undefweak (tlsdesc *); + + The second word of the descriptor contains the addend. + Return the addend minus the thread pointer. This ensures + that when the caller adds on the thread pointer it gets back + the addend. */ + +ENTRY (_dl_tlsdesc_undefweak) + REG_L a0, SZREG(a0) + sub a0, a0, tp + jr t0 +END (_dl_tlsdesc_undefweak) + +#ifdef SHARED + /* Handler for dynamic TLS symbols. + Prototype: + _dl_tlsdesc_dynamic (tlsdesc *) ; + + The second word of the descriptor points to a + tlsdesc_dynamic_arg structure. + + Returns the offset between the thread pointer and the + object referenced by the argument. + + unsigned long + _dl_tlsdesc_dynamic (struct tlsdesc *tdp) + { + struct tlsdesc_dynamic_arg *td = tdp->arg; + dtv_t *dtv = *(dtv_t **)((char *)__thread_pointer + TCBHEAD_DTV); + if (__builtin_expect (td->gen_count <= dtv[0].counter + && (dtv[td->tlsinfo.ti_module].pointer.val + != TLS_DTV_UNALLOCATED), + 1)) + return dtv[td->tlsinfo.ti_module].pointer.val + + td->tlsinfo.ti_offset + - __thread_pointer; + + return ___tls_get_addr (&td->tlsinfo) - __thread_pointer; + } + */ + +ENTRY (_dl_tlsdesc_dynamic) + /* Save just enough registers to support fast path, if we fall + into slow path we will save additional registers. */ + add sp, sp, -3*SZREG + REG_S t0, 0*SZREG(sp) + REG_S t1, 1*SZREG(sp) + REG_S t2, 2*SZREG(sp) + + /* t0 = dtv */ + REG_L t0, TCBHEAD_DTV(tp) + /* a0 = tdp->arg */ + REG_L a0, TLSDESC_ARG(a0) + /* t1 = td->gen_count */ + REG_L t1, TLSDESC_GEN_COUNT(a0) + /* t2 = dtv[0].counter */ + REG_L t2, DTV_COUNTER(t0) + bltu t2, t1, .Lslow + /* t1 = td->tlsinfo.ti_module */ + REG_L t1, TLSDESC_MODID(a0) + slli t1, t1, PTRLOG + 1 /* sizeof(dtv_t) == sizeof(void*) * 2 */ + add t1, t1, t0 + /* t1 = dtv[td->tlsinfo.ti_module].pointer.val */ + REG_L t1, 0(t1) + li t2, TLS_DTV_UNALLOCATED + beq t1, t2, .Lslow + /* t2 = td->tlsinfo.ti_offset */ + REG_L t2, TLSDESC_MODOFF(a0) + add a0, t1, t2 +.Lret: + sub a0, a0, tp + REG_L t0, 0*SZREG(sp) + REG_L t1, 1*SZREG(sp) + REG_L t2, 2*SZREG(sp) + add sp, sp, 3*SZREG + jr t0 +.Lslow: + /* This is the slow path. We need to call __tls_get_addr() which + means we need to save and restore all the register that the + callee will trash. */ + + /* Save the remaining registers that we must treat as caller save. */ + addi sp, sp, -FRAME_SIZE + REG_S ra, 0*SZREG(sp) + REG_S a1, 1*SZREG(sp) + REG_S a2, 2*SZREG(sp) + REG_S a3, 3*SZREG(sp) + REG_S a4, 4*SZREG(sp) + REG_S a5, 5*SZREG(sp) + REG_S a6, 6*SZREG(sp) + REG_S a7, 7*SZREG(sp) + REG_S t3, 8*SZREG(sp) + REG_S t4, 9*SZREG(sp) + REG_S t5, 10*SZREG(sp) + REG_S t6, 11*SZREG(sp) +#ifndef __riscv_float_abi_soft + FREG_S ft0, (12*SZREG + 0*SZFREG)(sp) + FREG_S ft1, (12*SZREG + 1*SZFREG)(sp) + FREG_S ft2, (12*SZREG + 2*SZFREG)(sp) + FREG_S ft3, (12*SZREG + 3*SZFREG)(sp) + FREG_S ft4, (12*SZREG + 4*SZFREG)(sp) + FREG_S ft5, (12*SZREG + 5*SZFREG)(sp) + FREG_S ft6, (12*SZREG + 6*SZFREG)(sp) + FREG_S ft7, (12*SZREG + 7*SZFREG)(sp) + FREG_S fa0, (12*SZREG + 8*SZFREG)(sp) + FREG_S fa1, (12*SZREG + 9*SZFREG)(sp) + FREG_S fa2, (12*SZREG + 10*SZFREG)(sp) + FREG_S fa3, (12*SZREG + 11*SZFREG)(sp) + FREG_S fa4, (12*SZREG + 12*SZFREG)(sp) + FREG_S fa5, (12*SZREG + 13*SZFREG)(sp) + FREG_S fa6, (12*SZREG + 14*SZFREG)(sp) + FREG_S fa7, (12*SZREG + 15*SZFREG)(sp) + FREG_S ft8, (12*SZREG + 16*SZFREG)(sp) + FREG_S ft9, (12*SZREG + 17*SZFREG)(sp) + FREG_S ft10, (12*SZREG + 18*SZFREG)(sp) + FREG_S ft11, (12*SZREG + 19*SZFREG)(sp) +#endif + + addi a0, a0, SZREG + call __tls_get_addr + addi a0, a0, -TLS_DTV_OFFSET + + REG_L ra, 0*SZREG(sp) + REG_L a1, 1*SZREG(sp) + REG_L a2, 2*SZREG(sp) + REG_L a3, 3*SZREG(sp) + REG_L a4, 4*SZREG(sp) + REG_L a5, 5*SZREG(sp) + REG_L a6, 6*SZREG(sp) + REG_L a7, 7*SZREG(sp) + REG_L t3, 8*SZREG(sp) + REG_L t4, 9*SZREG(sp) + REG_L t5, 10*SZREG(sp) + REG_L t6, 11*SZREG(sp) +#ifndef __riscv_float_abi_soft + FREG_L ft0, (12*SZREG + 0*SZFREG)(sp) + FREG_L ft1, (12*SZREG + 1*SZFREG)(sp) + FREG_L ft2, (12*SZREG + 2*SZFREG)(sp) + FREG_L ft3, (12*SZREG + 3*SZFREG)(sp) + FREG_L ft4, (12*SZREG + 4*SZFREG)(sp) + FREG_L ft5, (12*SZREG + 5*SZFREG)(sp) + FREG_L ft6, (12*SZREG + 6*SZFREG)(sp) + FREG_L ft7, (12*SZREG + 7*SZFREG)(sp) + FREG_L fa0, (12*SZREG + 8*SZFREG)(sp) + FREG_L fa1, (12*SZREG + 9*SZFREG)(sp) + FREG_L fa2, (12*SZREG + 10*SZFREG)(sp) + FREG_L fa3, (12*SZREG + 11*SZFREG)(sp) + FREG_L fa4, (12*SZREG + 12*SZFREG)(sp) + FREG_L fa5, (12*SZREG + 13*SZFREG)(sp) + FREG_L fa6, (12*SZREG + 14*SZFREG)(sp) + FREG_L fa7, (12*SZREG + 15*SZFREG)(sp) + FREG_L ft8, (12*SZREG + 16*SZFREG)(sp) + FREG_L ft9, (12*SZREG + 17*SZFREG)(sp) + FREG_L ft10, (12*SZREG + 18*SZFREG)(sp) + FREG_L ft11, (12*SZREG + 19*SZFREG)(sp) +#endif + addi sp, sp, FRAME_SIZE + j .Lret +END (_dl_tlsdesc_dynamic) +#endif diff --git a/sysdeps/riscv/dl-tlsdesc.h b/sysdeps/riscv/dl-tlsdesc.h new file mode 100644 index 0000000000..3156f34e9c --- /dev/null +++ b/sysdeps/riscv/dl-tlsdesc.h @@ -0,0 +1,49 @@ +/* Thread-local storage descriptor handling in the ELF dynamic linker. + RISC-V version. + Copyright (C) 2011-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + . */ + +#ifndef _DL_TLSDESC_H +# define _DL_TLSDESC_H 1 + +#include + +/* Type used to represent a TLS descriptor in the GOT. */ +struct tlsdesc +{ + ptrdiff_t (*entry) (struct tlsdesc *); + void *arg; +}; + +/* Type used as the argument in a TLS descriptor for a symbol that + needs dynamic TLS offsets. */ +struct tlsdesc_dynamic_arg +{ + tls_index tlsinfo; + size_t gen_count; +}; + +extern unsigned long attribute_hidden + _dl_tlsdesc_return(struct tlsdesc *), + _dl_tlsdesc_undefweak(struct tlsdesc *); + +# ifdef SHARED +extern void *_dl_make_tlsdesc_dynamic (struct link_map *, size_t); +extern unsigned long attribute_hidden _dl_tlsdesc_dynamic(struct tlsdesc *); +# endif + +#endif /* _DL_TLSDESC_H */ \ No newline at end of file diff --git a/sysdeps/riscv/linkmap.h b/sysdeps/riscv/linkmap.h index ac170bb342..2fa3f6d43f 100644 --- a/sysdeps/riscv/linkmap.h +++ b/sysdeps/riscv/linkmap.h @@ -1,4 +1,5 @@ struct link_map_machine { ElfW(Addr) plt; /* Address of .plt. */ + void *tlsdesc_table; /* Address of TLS descriptor hash table. */ }; diff --git a/sysdeps/riscv/tlsdesc.c b/sysdeps/riscv/tlsdesc.c new file mode 100644 index 0000000000..a76aaa9fc5 --- /dev/null +++ b/sysdeps/riscv/tlsdesc.c @@ -0,0 +1,38 @@ +/* Manage TLS descriptors. RISC-V version. + Copyright (C) 2005-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include +#include +#include + +/* Unmap the dynamic object, but also release its TLS descriptor table + if there is one. */ + +void +_dl_unmap (struct link_map *map) +{ + _dl_unmap_segments (map); + +#ifdef SHARED + if (map->l_mach.tlsdesc_table) + htab_delete (map->l_mach.tlsdesc_table); +#endif +} diff --git a/sysdeps/riscv/tlsdesc.sym b/sysdeps/riscv/tlsdesc.sym new file mode 100644 index 0000000000..652e72ea58 --- /dev/null +++ b/sysdeps/riscv/tlsdesc.sym @@ -0,0 +1,19 @@ +#include +#include +#include +#include +#include +#include + +-- + +-- Abuse tls.h macros to derive offsets relative to the thread register. + +TLSDESC_ARG offsetof(struct tlsdesc, arg) +TLSDESC_GEN_COUNT offsetof(struct tlsdesc_dynamic_arg, gen_count) +TLSDESC_MODID offsetof(struct tlsdesc_dynamic_arg, tlsinfo.ti_module) +TLSDESC_MODOFF offsetof(struct tlsdesc_dynamic_arg, tlsinfo.ti_offset) +TCBHEAD_DTV offsetof(tcbhead_t, dtv) - sizeof(tcbhead_t) - TLS_TCB_OFFSET +DTV_COUNTER offsetof(dtv_t, counter) +TLS_DTV_UNALLOCATED TLS_DTV_UNALLOCATED +TLS_DTV_OFFSET TLS_DTV_OFFSET