On Tue, Apr 06, 2021 at 09:46:59PM +0300, Konstantin Belousov wrote:
> On Tue, Apr 06, 2021 at 02:35:59PM -0400, Jung-uk Kim wrote:
> > On 21. 4. 5., Konstantin Belousov wrote:
> > > The branch main has been updated by kib:
> > > 
> > > URL: 
> > > https://cgit.FreeBSD.org/src/commit/?id=d36d6816151705907393889d661cbfd25c630ca8
> > > 
> > > commit d36d6816151705907393889d661cbfd25c630ca8
> > > Author:     Konstantin Belousov <k...@freebsd.org>
> > > AuthorDate: 2021-04-05 03:05:44 +0000
> > > Commit:     Konstantin Belousov <k...@freebsd.org>
> > > CommitDate: 2021-04-06 00:23:08 +0000
> > > 
> > >     rtld dl_iterate_phdr(): dlpi_tls_data is wrong
> > >     
> > >     dl_iterate_phdr() dlpi_tls_data should provide the TLS module segment
> > >     address, and not the TLS init segment address as it does now.
> > >     
> > >     Reported by:    emacs...@gmail.com
> > >     PR:     254774
> > >     Sponsored by:   The FreeBSD Foundation
> > >     MFC after:      1 week
> > 
> > I started having strange hangs in various applications from yesterday,
> > e.g., Xorg, Thunderbird, etc.  Today, I updated ports tree from Git for
> > the first time and started updating packages.  Then, I experienced
> > similar problems, e.g., building editors/kate, multimedia/vlc, etc.,
> > were hanging.  I noticed some tools were stuck in urwlck state and I
> > found reverting this commit fixed the problem for me.
> > 
> > Please take a look.
> 
> Can you get backtrace for all threads in hanging process?
> I do not need debugging symbols for the apps, libc/libthr/rtld with debug
> info, installed by default from the base, should be enough.

Also you might try this.  It should help if my guess is right.
Only x86 handled ATM.

diff --git a/lib/libc/amd64/gen/Makefile.inc b/lib/libc/amd64/gen/Makefile.inc
index 30fb05f89cb7..4df3c044493e 100644
--- a/lib/libc/amd64/gen/Makefile.inc
+++ b/lib/libc/amd64/gen/Makefile.inc
@@ -1,7 +1,7 @@
 #      @(#)Makefile.inc        8.1 (Berkeley) 6/4/93
 # $FreeBSD$
 
-SRCS+= _setjmp.S _set_tp.c rfork_thread.S setjmp.S sigsetjmp.S \
+SRCS+= _setjmp.S _get_tp.c _set_tp.c rfork_thread.S setjmp.S sigsetjmp.S \
        fabs.S \
        infinity.c ldexp.c makecontext.c signalcontext.c \
        flt_rounds.c fpgetmask.c fpsetmask.c fpgetprec.c fpsetprec.c \
diff --git a/lib/libc/amd64/gen/_get_tp.c b/lib/libc/amd64/gen/_get_tp.c
new file mode 100644
index 000000000000..73770ca7fa08
--- /dev/null
+++ b/lib/libc/amd64/gen/_get_tp.c
@@ -0,0 +1,46 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2021 The FreeBSD Foundation
+ *
+ * This software were developed by Konstantin Belousov
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     $FreeBSD$
+ */
+
+#include <string.h>
+#include <stdint.h>
+#include <machine/sysarch.h>
+#include "libc_private.h"
+
+void *
+_get_tp(void)
+{
+       void **res;
+
+       /* This function is used by rtld, avoid ifuncs. */
+       __asm __volatile("movq %%fs:0, %0" : "=r" (res));
+       return (&res[1]);
+}
diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc
index 0ab717600e56..ab2c1409f879 100644
--- a/lib/libc/gen/Makefile.inc
+++ b/lib/libc/gen/Makefile.inc
@@ -172,6 +172,11 @@ SRCS+=     __getosreldate.c \
 
 CFLAGS.arc4random.c= -I${SRCTOP}/sys -I${SRCTOP}/sys/crypto/chacha20
 
+RTLD_HDRS= -I${SRCTOP}/libexec/rtld-elf \
+    -I${SRCTOP}/libexec/rtld-elf/${MACHINE_CPUARCH}
+CFLAGS.dlfcn.c= ${RTLD_HDRS}
+CFLAGS.tls.c= ${RTLD_HDRS}
+
 .PATH: ${SRCTOP}/contrib/libc-pwcache
 SRCS+= pwcache.c pwcache.h
 
diff --git a/lib/libc/gen/dlfcn.c b/lib/libc/gen/dlfcn.c
index 395a6d9402e8..337ad48fd691 100644
--- a/lib/libc/gen/dlfcn.c
+++ b/lib/libc/gen/dlfcn.c
@@ -43,10 +43,11 @@ __FBSDID("$FreeBSD$");
 #include "namespace.h"
 #include <pthread.h>
 #include "un-namespace.h"
+#include "rtld.h"
 #include "libc_private.h"
 #include "reentrant.h"
 
-static char sorry[] = "Service unavailable";
+static const char sorry[] = "Service unavailable";
 
 void _rtld_thread_init(void *);
 void _rtld_atfork_pre(int *);
@@ -91,7 +92,7 @@ char *
 dlerror(void)
 {
 
-       return (sorry);
+       return (__DECONST(char *, sorry));
 }
 
 #pragma weak dllockinit
@@ -195,8 +196,6 @@ dl_init_phdr_info(void)
        for (i = 0; i < phdr_info.dlpi_phnum; i++) {
                if (phdr_info.dlpi_phdr[i].p_type == PT_TLS) {
                        phdr_info.dlpi_tls_modid = 1;
-                       phdr_info.dlpi_tls_data =
-                           (void*)phdr_info.dlpi_phdr[i].p_vaddr;
                }
        }
        phdr_info.dlpi_adds = 1;
@@ -209,13 +208,17 @@ dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, 
size_t, void *) __unused,
     void *data __unused)
 {
 #ifndef IN_LIBDL
+       tls_index ti;
        int ret;
 
        __init_elf_aux_vector();
        if (__elf_aux_vector == NULL)
                return (1);
        _once(&dl_phdr_info_once, dl_init_phdr_info);
+       ti.ti_module = 1;
+       ti.ti_offset = 0;
        mutex_lock(&dl_phdr_info_lock);
+       phdr_info.dlpi_tls_data = __tls_get_addr(&ti);
        ret = callback(&phdr_info, sizeof(phdr_info), data);
        mutex_unlock(&dl_phdr_info_lock);
        return (ret);
diff --git a/lib/libc/gen/tls.c b/lib/libc/gen/tls.c
index 719391130827..8c525e3e996a 100644
--- a/lib/libc/gen/tls.c
+++ b/lib/libc/gen/tls.c
@@ -41,6 +41,7 @@
 #include <elf.h>
 #include <unistd.h>
 
+#include "rtld.h"
 #include "libc_private.h"
 
 #define        tls_assert(cond)        ((cond) ? (void) 0 :                    
\
@@ -96,35 +97,41 @@ void __libc_free_tls(void *tls, size_t tcbsize, size_t 
tcbalign);
 
 #ifndef PIC
 
-static size_t tls_static_space;
-static size_t tls_init_size;
-static size_t tls_init_align;
-static void *tls_init;
+static size_t libc_tls_static_space;
+static size_t libc_tls_init_size;
+static size_t libc_tls_init_align;
+static void *libc_tls_init;
 #endif
 
+void *
+__libc_tls_get_addr(void *vti)
+{
+       Elf_Addr **dtvp, *dtv;
+       tls_index *ti;
+
+       dtvp = _get_tp();
+       dtv = *dtvp;
+       ti = vti;
+       return ((void *)(dtv[ti->ti_module + 1] + ti->ti_offset));
+}
+
 #ifdef __i386__
 
 /* GNU ABI */
 
 __attribute__((__regparm__(1)))
 void *
-___libc_tls_get_addr(void *ti __unused)
+___libc_tls_get_addr(void *vti)
 {
-       return (0);
+       return (__libc_tls_get_addr(vti));
 }
 
 #endif
 
-void *
-__libc_tls_get_addr(void *ti __unused)
-{
-       return (0);
-}
-
 #ifndef PIC
 
 static void *
-malloc_aligned(size_t size, size_t align)
+libc_malloc_aligned(size_t size, size_t align)
 {
        void *mem, *res;
 
@@ -138,7 +145,7 @@ malloc_aligned(size_t size, size_t align)
 }
 
 static void
-free_aligned(void *ptr)
+libc_free_aligned(void *ptr)
 {
        void *mem;
        uintptr_t x;
@@ -201,12 +208,13 @@ get_tls_block_ptr(void *tcb, size_t tcbsize)
        /* Compute fragments sizes. */
        extra_size = tcbsize - TLS_TCB_SIZE;
 #if defined(__aarch64__) || defined(__arm__)
-       post_size =  roundup2(TLS_TCB_SIZE, tls_init_align) - TLS_TCB_SIZE;
+       post_size =  roundup2(TLS_TCB_SIZE, libc_tls_init_align) - TLS_TCB_SIZE;
 #else
        post_size = 0;
 #endif
        tls_block_size = tcbsize + post_size;
-       pre_size = roundup2(tls_block_size, tls_init_align) - tls_block_size;
+       pre_size = roundup2(tls_block_size, libc_tls_init_align) -
+           tls_block_size;
 
        return ((char *)tcb - pre_size - extra_size);
 }
@@ -225,7 +233,7 @@ __libc_free_tls(void *tcb, size_t tcbsize, size_t tcbalign 
__unused)
        tls = (Elf_Addr **)tcb;
        dtv = tls[0];
        __je_bootstrap_free(dtv);
-       free_aligned(get_tls_block_ptr(tcb, tcbsize));
+       libc_free_aligned(get_tls_block_ptr(tcb, tcbsize));
 }
 
 /*
@@ -259,21 +267,22 @@ __libc_allocate_tls(void *oldtcb, size_t tcbsize, size_t 
tcbalign)
                return (oldtcb);
 
        tls_assert(tcbalign >= TLS_TCB_ALIGN);
-       maxalign = MAX(tcbalign, tls_init_align);
+       maxalign = MAX(tcbalign, libc_tls_init_align);
 
        /* Compute fragmets sizes. */
        extra_size = tcbsize - TLS_TCB_SIZE;
 #if defined(__aarch64__) || defined(__arm__)
-       post_size = roundup2(TLS_TCB_SIZE, tls_init_align) - TLS_TCB_SIZE;
+       post_size = roundup2(TLS_TCB_SIZE, libc_tls_init_align) - TLS_TCB_SIZE;
 #else
        post_size = 0;
 #endif
        tls_block_size = tcbsize + post_size;
-       pre_size = roundup2(tls_block_size, tls_init_align) - tls_block_size;
-       tls_block_size += pre_size + tls_static_space;
+       pre_size = roundup2(tls_block_size, libc_tls_init_align) -
+           tls_block_size;
+       tls_block_size += pre_size + libc_tls_static_space;
 
        /* Allocate whole TLS block */
-       tls_block = malloc_aligned(tls_block_size, maxalign);
+       tls_block = libc_malloc_aligned(tls_block_size, maxalign);
        if (tls_block == NULL) {
                tls_msg("__libc_allocate_tls: Out of memory.\n");
                abort();
@@ -285,7 +294,7 @@ __libc_allocate_tls(void *oldtcb, size_t tcbsize, size_t 
tcbalign)
        if (oldtcb != NULL) {
                memcpy(tls_block, get_tls_block_ptr(oldtcb, tcbsize),
                    tls_block_size);
-               free_aligned(oldtcb);
+               libc_free_aligned(oldtcb);
 
                /* Adjust the DTV. */
                dtv = tcb[0];
@@ -302,8 +311,8 @@ __libc_allocate_tls(void *oldtcb, size_t tcbsize, size_t 
tcbalign)
                dtv[1] = 1;             /* Segments count. */
                dtv[2] = (Elf_Addr)(tls + DTV_OFFSET);
 
-               if (tls_init_size > 0)
-                       memcpy(tls, tls_init, tls_init_size);
+               if (libc_tls_init_size > 0)
+                       memcpy(tls, libc_tls_init, libc_tls_init_size);
        }
 
        return (tcb);
@@ -329,13 +338,13 @@ __libc_free_tls(void *tcb, size_t tcbsize __unused, 
size_t tcbalign)
         * Figure out the size of the initial TLS block so that we can
         * find stuff which ___tls_get_addr() allocated dynamically.
         */
-       tcbalign = MAX(tcbalign, tls_init_align);
-       size = roundup2(tls_static_space, tcbalign);
+       tcbalign = MAX(tcbalign, libc_tls_init_align);
+       size = roundup2(libc_tls_static_space, tcbalign);
 
        dtv = ((Elf_Addr**)tcb)[1];
        tlsend = (Elf_Addr) tcb;
        tlsstart = tlsend - size;
-       free_aligned((void*)tlsstart);
+       libc_free_aligned((void*)tlsstart);
        __je_bootstrap_free(dtv);
 }
 
@@ -350,12 +359,12 @@ __libc_allocate_tls(void *oldtls, size_t tcbsize, size_t 
tcbalign)
        Elf_Addr *dtv;
        Elf_Addr segbase, oldsegbase;
 
-       tcbalign = MAX(tcbalign, tls_init_align);
-       size = roundup2(tls_static_space, tcbalign);
+       tcbalign = MAX(tcbalign, libc_tls_init_align);
+       size = roundup2(libc_tls_static_space, tcbalign);
 
        if (tcbsize < 2 * sizeof(Elf_Addr))
                tcbsize = 2 * sizeof(Elf_Addr);
-       tls = malloc_aligned(size + tcbsize, tcbalign);
+       tls = libc_malloc_aligned(size + tcbsize, tcbalign);
        if (tls == NULL) {
                tls_msg("__libc_allocate_tls: Out of memory.\n");
                abort();
@@ -373,16 +382,16 @@ __libc_allocate_tls(void *oldtls, size_t tcbsize, size_t 
tcbalign)
 
        dtv[0] = 1;
        dtv[1] = 1;
-       dtv[2] = segbase - tls_static_space;
+       dtv[2] = segbase - libc_tls_static_space;
 
        if (oldtls) {
                /*
                 * Copy the static TLS block over whole.
                 */
                oldsegbase = (Elf_Addr) oldtls;
-               memcpy((void *)(segbase - tls_static_space),
-                   (const void *)(oldsegbase - tls_static_space),
-                   tls_static_space);
+               memcpy((void *)(segbase - libc_tls_static_space),
+                   (const void *)(oldsegbase - libc_tls_static_space),
+                   libc_tls_static_space);
 
                /*
                 * We assume that this block was the one we created with
@@ -390,10 +399,11 @@ __libc_allocate_tls(void *oldtls, size_t tcbsize, size_t 
tcbalign)
                 */
                _rtld_free_tls(oldtls, 2*sizeof(Elf_Addr), sizeof(Elf_Addr));
        } else {
-               memcpy((void *)(segbase - tls_static_space),
-                   tls_init, tls_init_size);
-               memset((void *)(segbase - tls_static_space + tls_init_size),
-                   0, tls_static_space - tls_init_size);
+               memcpy((void *)(segbase - libc_tls_static_space),
+                   libc_tls_init, libc_tls_init_size);
+               memset((void *)(segbase - libc_tls_static_space +
+                   libc_tls_init_size), 0,
+                   libc_tls_static_space - libc_tls_init_size);
        }
 
        return (void*) segbase;
@@ -457,11 +467,11 @@ _init_tls(void)
 
        for (i = 0; (unsigned) i < phnum; i++) {
                if (phdr[i].p_type == PT_TLS) {
-                       tls_static_space = roundup2(phdr[i].p_memsz,
+                       libc_tls_static_space = roundup2(phdr[i].p_memsz,
                            phdr[i].p_align);
-                       tls_init_size = phdr[i].p_filesz;
-                       tls_init_align = phdr[i].p_align;
-                       tls_init = (void*) phdr[i].p_vaddr;
+                       libc_tls_init_size = phdr[i].p_filesz;
+                       libc_tls_init_align = phdr[i].p_align;
+                       libc_tls_init = (void *)phdr[i].p_vaddr;
                        break;
                }
        }
diff --git a/lib/libc/i386/gen/Makefile.inc b/lib/libc/i386/gen/Makefile.inc
index 45e69cad1d0f..bad73852f6eb 100644
--- a/lib/libc/i386/gen/Makefile.inc
+++ b/lib/libc/i386/gen/Makefile.inc
@@ -1,6 +1,6 @@
 #      @(#)Makefile.inc        8.1 (Berkeley) 6/4/93
 # $FreeBSD$
 
-SRCS+= _ctx_start.S _setjmp.S _set_tp.c fabs.S \
+SRCS+= _ctx_start.S _setjmp.S _set_tp.c _get_tp.c fabs.S \
        flt_rounds.c infinity.c ldexp.c makecontext.c \
        rfork_thread.S setjmp.S signalcontext.c sigsetjmp.S
diff --git a/lib/libc/i386/gen/_get_tp.c b/lib/libc/i386/gen/_get_tp.c
new file mode 100644
index 000000000000..7910d752753f
--- /dev/null
+++ b/lib/libc/i386/gen/_get_tp.c
@@ -0,0 +1,45 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2021 The FreeBSD Foundation
+ *
+ * This software were developed by Konstantin Belousov
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     $FreeBSD$
+ */
+
+#include <string.h>
+#include <stdint.h>
+#include <machine/sysarch.h>
+#include "libc_private.h"
+
+void *
+_get_tp(void)
+{
+       void **res;
+
+       __asm __volatile("movl %%gs:0, %0" : "=r" (res));
+       return (&res[1]);
+}
diff --git a/lib/libc/include/libc_private.h b/lib/libc/include/libc_private.h
index 363e1057986b..5a524c0211d1 100644
--- a/lib/libc/include/libc_private.h
+++ b/lib/libc/include/libc_private.h
@@ -261,8 +261,9 @@ void _init_tls(void);
 int _once(pthread_once_t *, void (*)(void));
 
 /*
- * Set the TLS thread pointer
+ * Get/set the TLS thread pointer
  */
+void *_get_tp(void);
 void _set_tp(void *tp);
 
 /*
diff --git a/lib/libdl/Makefile b/lib/libdl/Makefile
index d91547352de4..831f0e68180c 100644
--- a/lib/libdl/Makefile
+++ b/lib/libdl/Makefile
@@ -6,6 +6,8 @@ SHLIB_MAJOR=1
 
 .PATH: ${SRCTOP}/lib/libc/gen
 CFLAGS+=-I${SRCTOP}/lib/libc/include
+CFLAGS+=-I${SRCTOP}/libexec/rtld-elf \
+    -I${SRCTOP}/libexec/rtld-elf/${MACHINE_CPUARCH}
 CFLAGS+=-DIN_LIBDL
 LDFLAGS+=-Wl,-F,libc.so.7
 VERSION_DEF=${SRCTOP}/lib/libc/Versions.def
diff --git a/libexec/rtld-elf/rtld-libc/Makefile.inc 
b/libexec/rtld-elf/rtld-libc/Makefile.inc
index d5f5993e3f16..7ffcb6e41ec7 100644
--- a/libexec/rtld-elf/rtld-libc/Makefile.inc
+++ b/libexec/rtld-elf/rtld-libc/Makefile.inc
@@ -67,6 +67,8 @@ _libc_other_objects+=syncicache abs
 _libc_other_objects+=syncicache
 .endif
 
+_libc_other_objects+=_get_tp
+
 # Extract all the .o files from libc_nossp_pic.a. This ensures that
 # we don't accidentally pull in the interposing table or similar by linking
 # directly against libc_nossp_pic.a
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index 19027518d3c2..2ed4c4c9cb44 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -166,6 +166,7 @@ static int symlook_list(SymLook *, const Objlist *, 
DoneList *);
 static int symlook_needed(SymLook *, const Needed_Entry *, DoneList *);
 static int symlook_obj1_sysv(SymLook *, const Obj_Entry *);
 static int symlook_obj1_gnu(SymLook *, const Obj_Entry *);
+static void *tls_get_addr_slow(Elf_Addr **, int, size_t, bool) __noinline;
 static void trace_loaded_objects(Obj_Entry *);
 static void unlink_object(Obj_Entry *);
 static void unload_object(Obj_Entry *, RtldLockState *lockstate);
@@ -3906,19 +3907,21 @@ dlinfo(void *handle, int request, void *p)
     return (error);
 }
 
+void *_get_tp(void);
+
 static void
 rtld_fill_dl_phdr_info(const Obj_Entry *obj, struct dl_phdr_info *phdr_info)
 {
-       tls_index ti;
+       Elf_Addr **dtvp;
 
        phdr_info->dlpi_addr = (Elf_Addr)obj->relocbase;
        phdr_info->dlpi_name = obj->path;
        phdr_info->dlpi_phdr = obj->phdr;
        phdr_info->dlpi_phnum = obj->phsize / sizeof(obj->phdr[0]);
        phdr_info->dlpi_tls_modid = obj->tlsindex;
-       ti.ti_module = obj->tlsindex;
-       ti.ti_offset = 0;
-       phdr_info->dlpi_tls_data = __tls_get_addr(&ti);
+       dtvp = _get_tp();
+       phdr_info->dlpi_tls_data = tls_get_addr_slow(dtvp, obj->tlsindex,
+           0, true);
        phdr_info->dlpi_adds = obj_loads;
        phdr_info->dlpi_subs = obj_loads - obj_count;
 }
@@ -4871,39 +4874,42 @@ unref_dag(Obj_Entry *root)
 /*
  * Common code for MD __tls_get_addr().
  */
-static void *tls_get_addr_slow(Elf_Addr **, int, size_t) __noinline;
 static void *
-tls_get_addr_slow(Elf_Addr **dtvp, int index, size_t offset)
+tls_get_addr_slow(Elf_Addr **dtvp, int index, size_t offset, bool locked)
 {
-    Elf_Addr *newdtv, *dtv;
-    RtldLockState lockstate;
-    int to_copy;
+       Elf_Addr *newdtv, *dtv;
+       RtldLockState lockstate;
+       int to_copy;
 
-    dtv = *dtvp;
-    /* Check dtv generation in case new modules have arrived */
-    if (dtv[0] != tls_dtv_generation) {
-       wlock_acquire(rtld_bind_lock, &lockstate);
-       newdtv = xcalloc(tls_max_index + 2, sizeof(Elf_Addr));
-       to_copy = dtv[1];
-       if (to_copy > tls_max_index)
-           to_copy = tls_max_index;
-       memcpy(&newdtv[2], &dtv[2], to_copy * sizeof(Elf_Addr));
-       newdtv[0] = tls_dtv_generation;
-       newdtv[1] = tls_max_index;
-       free(dtv);
-       lock_release(rtld_bind_lock, &lockstate);
-       dtv = *dtvp = newdtv;
-    }
+       dtv = *dtvp;
+       /* Check dtv generation in case new modules have arrived */
+       if (dtv[0] != tls_dtv_generation) {
+               if (!locked)
+                       wlock_acquire(rtld_bind_lock, &lockstate);
+               newdtv = xcalloc(tls_max_index + 2, sizeof(Elf_Addr));
+               to_copy = dtv[1];
+               if (to_copy > tls_max_index)
+                       to_copy = tls_max_index;
+               memcpy(&newdtv[2], &dtv[2], to_copy * sizeof(Elf_Addr));
+               newdtv[0] = tls_dtv_generation;
+               newdtv[1] = tls_max_index;
+               free(dtv);
+               if (!locked)
+                       lock_release(rtld_bind_lock, &lockstate);
+               dtv = *dtvp = newdtv;
+       }
 
-    /* Dynamically allocate module TLS if necessary */
-    if (dtv[index + 1] == 0) {
-       /* Signal safe, wlock will block out signals. */
-       wlock_acquire(rtld_bind_lock, &lockstate);
-       if (!dtv[index + 1])
-           dtv[index + 1] = (Elf_Addr)allocate_module_tls(index);
-       lock_release(rtld_bind_lock, &lockstate);
-    }
-    return ((void *)(dtv[index + 1] + offset));
+       /* Dynamically allocate module TLS if necessary */
+       if (dtv[index + 1] == 0) {
+               /* Signal safe, wlock will block out signals. */
+               if (!locked)
+                       wlock_acquire(rtld_bind_lock, &lockstate);
+               if (!dtv[index + 1])
+                       dtv[index + 1] = (Elf_Addr)allocate_module_tls(index);
+               if (!locked)
+                       lock_release(rtld_bind_lock, &lockstate);
+       }
+       return ((void *)(dtv[index + 1] + offset));
 }
 
 void *
@@ -4916,7 +4922,7 @@ tls_get_addr_common(Elf_Addr **dtvp, int index, size_t 
offset)
        if (__predict_true(dtv[0] == tls_dtv_generation &&
            dtv[index + 1] != 0))
                return ((void *)(dtv[index + 1] + offset));
-       return (tls_get_addr_slow(dtvp, index, offset));
+       return (tls_get_addr_slow(dtvp, index, offset, false));
 }
 
 #if defined(__aarch64__) || defined(__arm__) || defined(__mips__) || \
diff --git a/libexec/rtld-elf/rtld_lock.h b/libexec/rtld-elf/rtld_lock.h
index 339028c568dc..9aa769b1f7e6 100644
--- a/libexec/rtld-elf/rtld_lock.h
+++ b/libexec/rtld-elf/rtld_lock.h
@@ -46,9 +46,13 @@ struct RtldLockInfo
        void  (*at_fork)(void);
 };
 
-extern void _rtld_thread_init(struct RtldLockInfo *) __exported;
-extern void _rtld_atfork_pre(int *) __exported;
-extern void _rtld_atfork_post(int *) __exported;
+#if defined(IN_RTLD) || defined(PTHREAD_KERNEL)
+
+void _rtld_thread_init(struct RtldLockInfo *) __exported;
+void _rtld_atfork_pre(int *) __exported;
+void _rtld_atfork_post(int *) __exported;
+
+#endif /* IN_RTLD || PTHREAD_KERNEL */
 
 #ifdef IN_RTLD
 
_______________________________________________
dev-commits-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-all
To unsubscribe, send any mail to "dev-commits-src-all-unsubscr...@freebsd.org"

Reply via email to