From nobody Sat Sep 05 22:00:40 2026 X-Original-To: dev-commits-src-all@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 4hcnMX70Pdz6rCTv for ; Sat, 05 Sep 2026 22:00:40 +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 4hcnMX3VFYz3xjg for ; Sat, 05 Sep 2026 22:00:40 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1788645640; 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=QqNdWktgyrdfbnpFbjW9EofGoS9VqOncpcjFEj/3icI=; b=r1kDMPduHgjdeNE6kraQCgHzpcBnnVy9jXYYHUGm7R4lI3j8yyh+v+kLPK2TNLTH16u8vA LwxzdnJACPDebrVWssNXUFwSLNjWX25IptUSvgnG1TaM45SwWKWY8GtGvJPEQpdaOW2ZiE CWyZd9VgxWfPZequN7IyfrmVuAsU+Y/OvIoV5zW6N8Zdbuig1xk54tuHCgRjYB1X7t+gNv xgcEhfMkhZOBbJzQPQyLM4FPmuZJXFj6d9et4XffwifxbmU71fxVS0UTLgHS2ginQ77Jbh fYJ9NreKYPTNYYDZHU21sw6DinI1n+Ze83trARSExt5fxDs65WvvFnWdSXwYFA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1788645640; a=rsa-sha256; cv=none; b=CwGSXukE6ILlznG0UhDkSQqwwX3Ob1zbZgyj+4jYvULDt2gL9WCz6eAvBIz1slr1ih1eib j9cp4J/8ZZJ7zUydLTVipA0Xxi1JPZVaGTmyGrRJR0Esqf8c1ZYOc5JV2whfHaafXJRscF 9EE6cDN4buhy9t+oWlXJlpgKEWxYPA8txjrDup5v1y2xx/Zh+DQkcev7D10b7J/dbEep+C sBbmalJPiuKbQ+ToW85prnhdWV/+VlTsXt8Auw58aW2biwkddObUa+YBW4JKFaJYP5pLYY QSEH1840myie61HoeSPnI9frwvPHIWx5BFPS0KSFQ+/I4N/RzZkKoAdNUEDGUA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1788645640; 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=QqNdWktgyrdfbnpFbjW9EofGoS9VqOncpcjFEj/3icI=; b=h18Y1vNAUSSsrogky9XiZNgQKRlxv9F5sajlmvVtqXVEQxUUDeLBokDycHtdLiQOzMfQfz SNqn3Gb8A6GxUUEOMLOkgoIVxOKQHL6ageQTCQFUBrHG6ikJokAeoDTuFYPETzGN2dTNRO 0p6n9BvrkoBNvFj+dPkmaJLoNmnO7ufxiI1VdmmG70RfsRI64nX7LWKkbcnKrjt+UbMfBB qfzF6tUOJCrQcU9ZNJzfDONy8526wCxLCZsirB7Z5RwC10/L3B8iCVGDJo4a+ySABJNfTL LJSCS8pZZWH5VchR8V6c24oSjwnMhB/K3ZFIqN+WVGS1Obx9VRrWbL1pJGrqAA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hcnMX2RqQz12xY for ; Sat, 05 Sep 2026 22:00:40 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 18f0e by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Sat, 05 Sep 2026 22:00:40 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Konstantin Belousov Subject: git: d45d7aea6197 - main - i386 rtld: implement support for TLSDESC relocation List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@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/main X-Git-Reftype: branch X-Git-Commit: d45d7aea6197a91b794808d508295a74ce5be0cd Auto-Submitted: auto-generated Date: Sat, 05 Sep 2026 22:00:40 +0000 Message-Id: <6a9c9108.18f0e.293b04ce@gitrepo.freebsd.org> The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=d45d7aea6197a91b794808d508295a74ce5be0cd commit d45d7aea6197a91b794808d508295a74ce5be0cd Author: Konstantin Belousov AuthorDate: 2026-08-25 12:26:50 +0000 Commit: Konstantin Belousov CommitDate: 2026-09-05 22:00:10 +0000 i386 rtld: implement support for TLSDESC relocation Discussed with: jrtc27 Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D59269 --- libexec/rtld-elf/amd64/rtld_start.S | 25 ++++++++++ libexec/rtld-elf/i386/reloc.c | 95 +++++++++++++++++++++++++++++++++++- libexec/rtld-elf/i386/rtld_machdep.h | 31 ++++++++++-- libexec/rtld-elf/i386/rtld_start.S | 36 ++++++++++++++ 4 files changed, 183 insertions(+), 4 deletions(-) diff --git a/libexec/rtld-elf/amd64/rtld_start.S b/libexec/rtld-elf/amd64/rtld_start.S index 7f85a9f94d5c..dcc168a33c57 100644 --- a/libexec/rtld-elf/amd64/rtld_start.S +++ b/libexec/rtld-elf/amd64/rtld_start.S @@ -171,4 +171,29 @@ rtld_dynamic_addr: .cfi_endproc .size rtld_dynamic_addr, . - rtld_dynamic_addr +rtld_tlsdesc_static: + .globl rtld_tlsdesc_static + .type rtld_tlsdesc_static,@function + .cfi_startproc + movq 8(%rax), %rax + ret + .cfi_endproc + .size rtld_tlsdesc_static, . - rtld_tlsdesc_static + +rtld_tlsdesc_undef: + .globl rtld_tlsdesc_undef + .type rtld_tlsdesc_undef,@function + .cfi_startproc + ret + .cfi_endproc + .size rtld_tlsdesc_undef, . - rtld_tlsdesc_undef + +rtld_tlsdesc_dynamic: + .globl rtld_tlsdesc_static + .type rtld_tlsdesc_dynamic,@function + .cfi_startproc + ret + .cfi_endproc + .size rtld_tlsdesc_dynamic, . - rtld_tlsdesc_dynamic + .section .note.GNU-stack,"",%progbits diff --git a/libexec/rtld-elf/i386/reloc.c b/libexec/rtld-elf/i386/reloc.c index 060b3cb147e3..5dd495f2056c 100644 --- a/libexec/rtld-elf/i386/reloc.c +++ b/libexec/rtld-elf/i386/reloc.c @@ -51,6 +51,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_386_COPY relocations in the main program. These * copy data from a shared object into a region in the main program's BSS @@ -125,6 +141,60 @@ 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_Rel *rel, + struct tlsdesc *where, int flags, RtldLockState *lockstate) +{ + const Elf_Sym *def; + const Obj_Entry *defobj; + Elf_Addr offs; + + dbg("reloc_tlsdesc obj %s rel %p where %p", obj->path, rel, where); + offs = 0; + if (ELF_R_SYM(rel->r_info) != 0) { + def = find_symdef(ELF_R_SYM(rel->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; + return; + } + } + offs += where->offset; + + 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, @@ -271,6 +341,10 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags, case R_386_IRELATIVE: obj->irelative_nonplt = true; break; + case R_386_TLS_DESC: + reloc_tlsdesc(obj, rel, (struct tlsdesc *)where, + flags, lockstate); + break; default: _rtld_error( "%s: Unsupported relocation type %d in non-PLT relocations", @@ -295,10 +369,10 @@ reloc_plt(Obj_Entry *obj, int flags __unused, RtldLockState *lockstate __unused) for (rel = obj->pltrel; rel < rellim; rel++) { Elf_Addr *where; + where = (Elf_Addr *)(obj->relocbase + rel->r_offset); switch (ELF_R_TYPE(rel->r_info)) { case R_386_JMP_SLOT: /* Relocate the GOT slot pointing into the PLT. */ - where = (Elf_Addr *)(obj->relocbase + rel->r_offset); *where += (Elf_Addr)obj->relocbase; break; @@ -306,6 +380,11 @@ reloc_plt(Obj_Entry *obj, int flags __unused, RtldLockState *lockstate __unused) obj->irelative = true; break; + case R_386_TLS_DESC: + reloc_tlsdesc(obj, rel, (struct tlsdesc *)where, + SYMLOOK_IN_PLT | flags, lockstate); + break; + default: _rtld_error("Unknown relocation type %x in PLT", ELF_R_TYPE(rel->r_info)); @@ -552,3 +631,17 @@ calculate_first_tls_offset(size_t size, size_t align, size_t offset) { return (calculate_tls_offset(0, 0, size, align, offset)); } + +__GNU_ABI ptrdiff_t +rtld_tlsdesc_dynamic_impl(struct tlsdesc *tdp) +{ + struct tlsdesc_dynarg *tda; + struct tcb *tcb; + tls_index *ti; + + tda = tdp->arg; + ti = &tda->tlsinfo; + tcb = _tcb_get(); + return ((ptrdiff_t)tls_get_addr_common(tcb, ti->ti_module, + ti->ti_offset) - (ptrdiff_t)tcb); +} diff --git a/libexec/rtld-elf/i386/rtld_machdep.h b/libexec/rtld-elf/i386/rtld_machdep.h index 574eafe432db..50c2a1bef94e 100644 --- a/libexec/rtld-elf/i386/rtld_machdep.h +++ b/libexec/rtld-elf/i386/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. */ #define rtld_dynamic(obj) \ @@ -83,10 +87,31 @@ typedef struct { void *___tls_get_addr(tls_index *ti) __GNU_ABI __exported; void *__tls_get_addr(tls_index *ti) __exported; +struct tlsdesc_dynarg +{ + tls_index tlsinfo; + STAILQ_ENTRY(tlsdesc_dynarg) link; +}; + +struct tlsdesc +{ + ptrdiff_t (*entry)(struct tlsdesc *) __GNU_ABI; + union { + 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 *tdp) __GNU_ABI; + +ptrdiff_t rtld_tlsdesc_static(struct tlsdesc *) __GNU_ABI; +ptrdiff_t rtld_tlsdesc_undef(struct tlsdesc *) __GNU_ABI; +ptrdiff_t rtld_tlsdesc_dynamic(struct tlsdesc *) __GNU_ABI; + #endif diff --git a/libexec/rtld-elf/i386/rtld_start.S b/libexec/rtld-elf/i386/rtld_start.S index 9dbe32d27628..d81f2d17fff4 100644 --- a/libexec/rtld-elf/i386/rtld_start.S +++ b/libexec/rtld-elf/i386/rtld_start.S @@ -95,4 +95,40 @@ _rtld_bind_start: leal 4(%esp),%esp # Discard reloff, do not change eflags ret # "Return" to target address +rtld_tlsdesc_static: + .globl rtld_tlsdesc_static + .type rtld_tlsdesc_static,@function + .cfi_startproc + movl 4(%eax), %eax + ret + .cfi_endproc + .size rtld_tlsdesc_static, . - rtld_tlsdesc_static + +rtld_tlsdesc_undef: + .globl rtld_tlsdesc_undef + .type rtld_tlsdesc_undef,@function + .cfi_startproc + movl 4(%eax), %eax + subl %gs:0, %eax + ret + .cfi_endproc + .size rtld_tlsdesc_undef, . - rtld_tlsdesc_undef + +rtld_tlsdesc_dynamic: + .globl rtld_tlsdesc_dynamic + .type rtld_tlsdesc_dynamic,@function + .cfi_startproc + pushl %ebp + /* XXXKIB cfi */ + movl %esp, %ebp + pushl %edx + pushl %ecx + call rtld_tlsdesc_dynamic_impl + popl %ecx + popl %edx + popl %ebp + ret + .cfi_endproc + .size rtld_tlsdesc_dynamic, . - rtld_tlsdesc_dynamic + .section .note.GNU-stack,"",%progbits