From nobody Sat Sep 12 00:28:08 2026 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4hhXLx2fd2z6rbCF for ; Sat, 12 Sep 2026 00:28:09 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hhXLx0PVjz4myh for ; Sat, 12 Sep 2026 00:28:09 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1789172889; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=5Y75COHc6ydvI3EIQqjou5XyDdPlT8TGS7UL/ilgXYE=; b=GHPVuUpFW7jCibJVW5h0ZvoKoPZLzz7A5YBP8QEeAywwG7V857xt0ZZzQ1Rz8g73goSu9A MrBC3z20UMm716EJqmE90p19XIheYbmUxeg8PfoLnJxAzM9sAa9zzedm5fYAjC8+077JXh W+Pt9iLXk1s9R4M/FSKvtM6G9dxMNVLTDXWdF7n8ItIIHW1I2/3AUkE1U4XDh3QRZQZ1Hc NLIl3JoybwHBc7jJTVLtg0HpVi+Le5/0V/dtcfLG6ce+c19SFMmvN178T0RV/CWytA/FCL z3TcHIcMZkUmUuBNHqIGjW5VCDQAeX1D53Dx8Zxw1KkOA413QN/dzb33oyT7pg== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1789172889; b=D6vIGbXrdKgmSa7j1ua0l/pictkFBDr3VHCMNt1l/00SX1eu+dvtyXtHB/19oajx9jp/ti r4M9r7HqI36+i+TbMR1AZu0xcBMZHDgZ80ngFBc1Svvp5GhWCbl/7tgFCEzXtptSxlBXw7 4o0qwrHC/puCO5Qmjo2LMznEJgtA7pK/W8InssHTLgj3ps3yEWmVgKyNjX0+cdioUFYqKS xKU17d74MCAzrUfZnmTJxyDuEx7eHRZCcQqEmaNO/mAZES2kp4DcKLMOJvjo+LXTRUwHF4 8cI5WaK7Tv5IMMee2kdLqWyh5XYjip0TaUqzTeKCIOGbCrBh/7lGJAXb49DWsA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1789172889; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=5Y75COHc6ydvI3EIQqjou5XyDdPlT8TGS7UL/ilgXYE=; b=gbdFmE3aJ5gwoApJXTE605zbyoQ/lfCXw9tAAO5r8fSNIKBHcnyUp59ewYraIzxjZQeHqs b8x90lrltk5wHUqeo9rzHs0jxQcXe8WdC+ozp5wKyVZcM2P0gGM5AQVsX3qWTG1rK6aOeE 76KZju5Jt8FZ3IG2fTHvrHT6pd+SCrMAL9Jad3WGSeguxUmNPJrEd7s75fz0hTYagq5CCN L6k6h8Sm61a9oD0A9kkMGI0rPkklysu/bvHx5zOme5cX/JDxh5e2DFH95+0PEwGxSlDG1D j2k3mmHFH8WS6dbMj+23J4yzZAbOOY4ULOifL8Q1tlH/6g2pNMpYZwqd3v2YdQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hhXLw6Kffzd7R for ; Sat, 12 Sep 2026 00:28:08 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 4788e by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Sat, 12 Sep 2026 00:28:08 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Konstantin Belousov Subject: git: 858d63cf8a4f - stable/15 - amd64 rtld: implement support for TLSDESC relocation List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kib X-Git-Repository: src X-Git-Refname: refs/heads/stable/15 X-Git-Reftype: branch X-Git-Commit: 858d63cf8a4f1a41929a7440da866ea73ac12886 Auto-Submitted: auto-generated Date: Sat, 12 Sep 2026 00:28:08 +0000 Message-Id: <6aa49c98.4788e.4c2cdf54@gitrepo.freebsd.org> The branch stable/15 has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=858d63cf8a4f1a41929a7440da866ea73ac12886 commit 858d63cf8a4f1a41929a7440da866ea73ac12886 Author: Konstantin Belousov AuthorDate: 2026-08-26 09:41:59 +0000 Commit: Konstantin Belousov CommitDate: 2026-09-11 06:59:53 +0000 amd64 rtld: implement support for TLSDESC relocation (cherry picked from commit 76f5fccc5fbdf2a7b42f1e4aa71fe625be32fa13) --- libexec/rtld-elf/amd64/reloc.c | 94 ++++++++++++++++++++++++++++++++++- libexec/rtld-elf/amd64/rtld_machdep.h | 36 ++++++++++++-- libexec/rtld-elf/amd64/rtld_start.S | 42 +++++++++++++++- 3 files changed, 166 insertions(+), 6 deletions(-) diff --git a/libexec/rtld-elf/amd64/reloc.c b/libexec/rtld-elf/amd64/reloc.c index b1a2069edb2f..7d6487267352 100644 --- a/libexec/rtld-elf/amd64/reloc.c +++ b/libexec/rtld-elf/amd64/reloc.c @@ -53,6 +53,22 @@ #include "rtld.h" #include "rtld_tls.h" +void +md_obj_entry_init(Obj_Entry *obj) +{ + STAILQ_INIT(&obj->tlsdesc_dynargs); +} + +void +md_obj_entry_fini(Obj_Entry *obj) +{ + struct tlsdesc_dynarg *tda, *t; + + STAILQ_FOREACH_SAFE(tda, &obj->tlsdesc_dynargs, link, t) { + free(tda); + } +} + /* * Process the special R_X86_64_COPY relocations in the main program. These * copy data from a shared object into a region in the main program's BSS @@ -127,6 +143,61 @@ init_pltgot(Obj_Entry *obj) } } +static struct tlsdesc_dynarg * +reloc_tlsdesc_alloc(Obj_Entry *obj, Elf_Addr tlsoffs) +{ + struct tlsdesc_dynarg *tda; + + tda = xmalloc(sizeof(struct tlsdesc_dynarg)); + tda->tlsinfo.ti_module = obj->tlsindex; + tda->tlsinfo.ti_offset = tlsoffs; + STAILQ_INSERT_TAIL(&obj->tlsdesc_dynargs, tda, link); + return (tda); +} + +static void +reloc_tlsdesc(const Obj_Entry *obj, const Elf_Rela *rela, + struct tlsdesc *where, int flags, RtldLockState *lockstate) +{ + const Elf_Sym *def; + const Obj_Entry *defobj; + Elf_Addr offs; + + dbg("reloc_tlsdesc obj %s rela %p where %p", obj->path, rela, where); + offs = 0; + if (ELF_R_SYM(rela->r_info) != 0) { + def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, flags, + NULL, lockstate); + if (def == NULL) + rtld_die(); + if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { + _rtld_error("%s: IFUNC for TLSDESC reloc", + obj->path); + rtld_die(); + } + offs = def->st_value; + obj = defobj; + if (def->st_shndx == SHN_UNDEF) { + /* Weak undefined thread variable */ + where->entry = rtld_tlsdesc_undef; + where->addend = rela->r_addend; + return; + } + } + offs += rela->r_addend; + + if (obj->tlsoffset != 0) { + /* Variable is in initialy allocated TLS segment */ + where->entry = rtld_tlsdesc_static; + where->offset = offs - obj->tlsoffset; + } else { + /* TLS offest is unknown at load time, use dynamic resolving */ + where->entry = rtld_tlsdesc_dynamic; + where->arg = reloc_tlsdesc_alloc(__DECONST(Obj_Entry *, obj), + offs); + } +} + /* Process the non-PLT relocations. */ int reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags, @@ -313,6 +384,10 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags, case R_X86_64_IRELATIVE: obj->irelative_nonplt = true; break; + case R_X86_64_TLSDESC: + reloc_tlsdesc(obj, rela, (struct tlsdesc *)where, + flags, lockstate); + break; /* * missing: @@ -334,7 +409,7 @@ done: /* Process the PLT relocations. */ int -reloc_plt(Obj_Entry *obj, int flags __unused, RtldLockState *lockstate __unused) +reloc_plt(Obj_Entry *obj, int flags, RtldLockState *lockstate) { const Elf_Rela *relalim; const Elf_Rela *rela; @@ -344,10 +419,10 @@ reloc_plt(Obj_Entry *obj, int flags __unused, RtldLockState *lockstate __unused) for (rela = obj->pltrela; rela < relalim; rela++) { Elf_Addr *where; + where = (Elf_Addr *)(obj->relocbase + rela->r_offset); switch (ELF_R_TYPE(rela->r_info)) { case R_X86_64_JMP_SLOT: /* Relocate the GOT slot pointing into the PLT. */ - where = (Elf_Addr *)(obj->relocbase + rela->r_offset); *where += (Elf_Addr)obj->relocbase; break; @@ -355,6 +430,11 @@ reloc_plt(Obj_Entry *obj, int flags __unused, RtldLockState *lockstate __unused) obj->irelative = true; break; + case R_X86_64_TLSDESC: + reloc_tlsdesc(obj, rela, (struct tlsdesc *)where, + SYMLOOK_IN_PLT | flags, lockstate); + break; + default: _rtld_error("Unknown relocation type %x in PLT", (unsigned int)ELF_R_TYPE(rela->r_info)); @@ -580,3 +660,13 @@ calculate_first_tls_offset(size_t size, size_t align, size_t offset) { return (calculate_tls_offset(0, 0, size, align, offset)); } + +ptrdiff_t +rtld_tlsdesc_dynamic_impl(struct tlsdesc_dynarg *tda, struct tcb *tcb) +{ + tls_index *ti; + + ti = &tda->tlsinfo; + return ((ptrdiff_t)tls_get_addr_common(tcb, ti->ti_module, + ti->ti_offset) - (ptrdiff_t)tcb); +} diff --git a/libexec/rtld-elf/amd64/rtld_machdep.h b/libexec/rtld-elf/amd64/rtld_machdep.h index 53a3cd29f967..7eadba62b9f6 100644 --- a/libexec/rtld-elf/amd64/rtld_machdep.h +++ b/libexec/rtld-elf/amd64/rtld_machdep.h @@ -35,10 +35,14 @@ struct Struct_Obj_Entry; -#define MD_OBJ_ENTRY +#define MD_OBJ_ENTRY \ + STAILQ_HEAD(, tlsdesc_dynarg) tlsdesc_dynargs; -#define MD_OBJ_ENTRY_INIT(obj) -#define MD_OBJ_ENTRY_FINI(obj) +#define MD_OBJ_ENTRY_INIT(obj) md_obj_entry_init(obj) +#define MD_OBJ_ENTRY_FINI(obj) md_obj_entry_fini(obj) + +void md_obj_entry_init(struct Struct_Obj_Entry *obj); +void md_obj_entry_fini(struct Struct_Obj_Entry *obj); /* Return the address of the .dynamic section in the dynamic linker. */ Elf_Dyn *rtld_dynamic_addr(void); @@ -80,9 +84,35 @@ typedef struct { void *__tls_get_addr(tls_index *ti) __exported; +#define __NONE_ABI /* Cannot be expressed in C */ + +struct tlsdesc_dynarg +{ + tls_index tlsinfo; + STAILQ_ENTRY(tlsdesc_dynarg) link; +}; + +struct tlsdesc +{ + ptrdiff_t (*entry)(struct tlsdesc *) __NONE_ABI; + union { + Elf_Ssize addend; + Elf_Size offset; + struct tlsdesc_dynarg *arg; + }; +}; + #define md_abi_variant_hook(x) size_t calculate_first_tls_offset(size_t size, size_t align, size_t offset); size_t calculate_tls_offset(size_t prev_offset, size_t prev_size, size_t size, size_t align, size_t offset); + +ptrdiff_t rtld_tlsdesc_dynamic_impl(struct tlsdesc_dynarg *tda, + struct tcb *tcb); + +ptrdiff_t rtld_tlsdesc_static(struct tlsdesc *) __NONE_ABI; +ptrdiff_t rtld_tlsdesc_undef(struct tlsdesc *) __NONE_ABI; +ptrdiff_t rtld_tlsdesc_dynamic(struct tlsdesc *) __NONE_ABI; + #endif diff --git a/libexec/rtld-elf/amd64/rtld_start.S b/libexec/rtld-elf/amd64/rtld_start.S index dcc168a33c57..b1a619028fd0 100644 --- a/libexec/rtld-elf/amd64/rtld_start.S +++ b/libexec/rtld-elf/amd64/rtld_start.S @@ -184,15 +184,55 @@ rtld_tlsdesc_undef: .globl rtld_tlsdesc_undef .type rtld_tlsdesc_undef,@function .cfi_startproc + movq 8(%rax), %rax + subq %fs:0, %rax ret .cfi_endproc .size rtld_tlsdesc_undef, . - rtld_tlsdesc_undef rtld_tlsdesc_dynamic: - .globl rtld_tlsdesc_static + .globl rtld_tlsdesc_dynamic .type rtld_tlsdesc_dynamic,@function .cfi_startproc + pushq %rbp + /* XXXKIB cfi */ + movq %rsp,%rbp + pushq %rdx + pushq %rcx + pushq %rsi + pushq %rdi + movq 8(%rax), %rdi /* arg->arg */ + movq %fs:0, %rsi /* tcb */ + + movq 8(%rsi), %rcx /* dtv */ + movq (%rcx), %rdx /* dtv_gen */ + cmpq %rdx, tls_dtv_generation(%rip) + jne 2f + movq (%rdi), %rax /* arg->tlsinfo.ti_module */ + dec %rax + movq 16(%rcx, %rax, 8), %rax /* dtv_tls */ + testq %rax, %rax + je 2f + addq 8(%rdi), %rax /* arg->offset */ + subq %rsi, %rax +1: + popq %rdi + popq %rsi + popq %rcx + popq %rdx + popq %rbp ret +2: + pushq %r8 + pushq %r9 + pushq %r10 + pushq %r11 + call rtld_tlsdesc_dynamic_impl + popq %r11 + popq %r10 + popq %r9 + popq %r8 + jmp 1b .cfi_endproc .size rtld_tlsdesc_dynamic, . - rtld_tlsdesc_dynamic