The branch stable/13 has been updated by kib:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=7bbfb5d959329fe0c322c0b59c9268b75ddddace

commit 7bbfb5d959329fe0c322c0b59c9268b75ddddace
Author:     Konstantin Belousov <k...@freebsd.org>
AuthorDate: 2021-04-07 22:02:33 +0000
Commit:     Konstantin Belousov <k...@freebsd.org>
CommitDate: 2021-04-23 11:14:08 +0000

    rtld: make dlerror() thread-local
    
    (cherry picked from commit 4d9128da54f8f8e2a29190ffb18880c4f116a205)
---
 lib/libthr/thread/thr_private.h |  4 ++++
 lib/libthr/thread/thr_rtld.c    | 21 +++++++++++++++++++++
 libexec/rtld-elf/rtld.c         | 38 ++++++++++++++++++++------------------
 libexec/rtld-elf/rtld_lock.c    | 33 +++++++++++++++++++++++++++++++++
 libexec/rtld-elf/rtld_lock.h    |  7 ++++++-
 5 files changed, 84 insertions(+), 19 deletions(-)

diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h
index a1258940a896..a5bbc5997d30 100644
--- a/lib/libthr/thread/thr_private.h
+++ b/lib/libthr/thread/thr_private.h
@@ -577,6 +577,10 @@ struct pthread {
 
        /* pthread_set/get_name_np */
        char                    *name;
+
+       /* rtld thread-local dlerror message and seen control */
+       char                    dlerror_msg[512];
+       int                     dlerror_seen;
 };
 
 #define THR_SHOULD_GC(thrd)                                            \
diff --git a/lib/libthr/thread/thr_rtld.c b/lib/libthr/thread/thr_rtld.c
index 5848fc6d5f61..1967ea14859d 100644
--- a/lib/libthr/thread/thr_rtld.c
+++ b/lib/libthr/thread/thr_rtld.c
@@ -189,6 +189,24 @@ _thr_rtld_clr_flag(int mask __unused)
 extern char _pli_rtli_version;
 char _pli_rtli_version;
 
+static char *
+_thr_dlerror_loc(void)
+{
+       struct pthread *curthread;
+
+       curthread = _get_curthread();
+       return (curthread->dlerror_msg);
+}
+
+static int *
+_thr_dlerror_seen(void)
+{
+       struct pthread *curthread;
+
+       curthread = _get_curthread();
+       return (&curthread->dlerror_seen);
+}
+
 void
 _thr_rtld_init(void)
 {
@@ -221,6 +239,9 @@ _thr_rtld_init(void)
        li.thread_set_flag = _thr_rtld_set_flag;
        li.thread_clr_flag = _thr_rtld_clr_flag;
        li.at_fork = NULL;
+       li.dlerror_loc = _thr_dlerror_loc;
+       li.dlerror_loc_sz = sizeof(curthread->dlerror_msg);
+       li.dlerror_seen = _thr_dlerror_seen;
 
        /*
         * Preresolve the symbols needed for the fork interposer.  We
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index 5e99b8db8ff7..d50774868908 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -195,7 +195,6 @@ int __sys_openat(int, const char *, int, ...);
 /*
  * Data declarations.
  */
-static char *error_message;    /* Message for dlerror(), or NULL */
 struct r_debug r_debug __exported;     /* for GDB; */
 static bool libmap_disable;    /* Disable libmap */
 static bool ld_loadfltr;       /* Immediate filters processing */
@@ -441,6 +440,8 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry 
**objp)
     assert(aux_info[AT_BASE] != NULL);
     init_rtld((caddr_t) aux_info[AT_BASE]->a_un.a_ptr, aux_info);
 
+    dlerror_dflt_init();
+
     __progname = obj_rtld.path;
     argv0 = argv[0] != NULL ? argv[0] : "(null)";
     environ = env;
@@ -919,14 +920,14 @@ _rtld_bind(Obj_Entry *obj, Elf_Size reloff)
 void
 _rtld_error(const char *fmt, ...)
 {
-    static char buf[512];
-    va_list ap;
+       va_list ap;
 
-    va_start(ap, fmt);
-    rtld_vsnprintf(buf, sizeof buf, fmt, ap);
-    error_message = buf;
-    va_end(ap);
-    LD_UTRACE(UTRACE_RTLD_ERROR, NULL, NULL, 0, 0, error_message);
+       va_start(ap, fmt);
+       rtld_vsnprintf(lockinfo.dlerror_loc(), lockinfo.dlerror_loc_sz,
+           fmt, ap);
+       va_end(ap);
+       *lockinfo.dlerror_seen() = 0;
+       LD_UTRACE(UTRACE_RTLD_ERROR, NULL, NULL, 0, 0, lockinfo.dlerror_loc());
 }
 
 /*
@@ -935,7 +936,7 @@ _rtld_error(const char *fmt, ...)
 static char *
 errmsg_save(void)
 {
-    return error_message == NULL ? NULL : xstrdup(error_message);
+       return (xstrdup(lockinfo.dlerror_loc()));
 }
 
 /*
@@ -945,12 +946,12 @@ errmsg_save(void)
 static void
 errmsg_restore(char *saved_msg)
 {
-    if (saved_msg == NULL)
-       error_message = NULL;
-    else {
-       _rtld_error("%s", saved_msg);
-       free(saved_msg);
-    }
+       if (saved_msg == NULL)
+               _rtld_error("");
+       else {
+               _rtld_error("%s", saved_msg);
+               free(saved_msg);
+       }
 }
 
 static const char *
@@ -3369,9 +3370,10 @@ dlclose_locked(void *handle, RtldLockState *lockstate)
 char *
 dlerror(void)
 {
-    char *msg = error_message;
-    error_message = NULL;
-    return msg;
+       if (*(lockinfo.dlerror_seen()) != 0)
+               return (NULL);
+       *lockinfo.dlerror_seen() = 1;
+       return (lockinfo.dlerror_loc());
 }
 
 /*
diff --git a/libexec/rtld-elf/rtld_lock.c b/libexec/rtld-elf/rtld_lock.c
index 4d54c687ee6f..94e931c2f760 100644
--- a/libexec/rtld-elf/rtld_lock.c
+++ b/libexec/rtld-elf/rtld_lock.c
@@ -59,6 +59,21 @@ void _rtld_thread_init(struct RtldLockInfo *) __exported;
 void _rtld_atfork_pre(int *) __exported;
 void _rtld_atfork_post(int *) __exported;
 
+static char def_dlerror_msg[512];
+static int def_dlerror_seen_val;
+
+static char *
+def_dlerror_loc(void)
+{
+       return (def_dlerror_msg);
+}
+
+static int *
+def_dlerror_seen(void)
+{
+       return (&def_dlerror_seen_val);
+}
+
 #define WAFLAG         0x1     /* A writer holds the lock */
 #define RC_INCR                0x2     /* Adjusts count of readers desiring 
lock */
 
@@ -299,6 +314,14 @@ lock_restart_for_upgrade(RtldLockState *lockstate)
        }
 }
 
+void
+dlerror_dflt_init(void)
+{
+       lockinfo.dlerror_loc = def_dlerror_loc;
+       lockinfo.dlerror_loc_sz = sizeof(def_dlerror_msg);
+       lockinfo.dlerror_seen = def_dlerror_seen;
+}
+
 void
 lockdflt_init(void)
 {
@@ -313,6 +336,9 @@ lockdflt_init(void)
        deflockinfo.thread_set_flag = def_thread_set_flag;
        deflockinfo.thread_clr_flag = def_thread_clr_flag;
        deflockinfo.at_fork = NULL;
+       deflockinfo.dlerror_loc = def_dlerror_loc;
+       deflockinfo.dlerror_loc_sz = sizeof(def_dlerror_msg);
+       deflockinfo.dlerror_seen = def_dlerror_seen;
 
        for (i = 0; i < RTLD_LOCK_CNT; i++) {
                rtld_locks[i].mask   = (1 << i);
@@ -404,6 +430,13 @@ _rtld_thread_init(struct RtldLockInfo *pli)
        lockinfo.thread_set_flag = pli->thread_set_flag;
        lockinfo.thread_clr_flag = pli->thread_clr_flag;
        lockinfo.at_fork = pli->at_fork;
+       if (lockinfo.rtli_version > RTLI_VERSION_ONE && pli != NULL) {
+               strlcpy(pli->dlerror_loc(), lockinfo.dlerror_loc(),
+                   lockinfo.dlerror_loc_sz);
+               lockinfo.dlerror_loc = pli->dlerror_loc;
+               lockinfo.dlerror_loc_sz = pli->dlerror_loc_sz;
+               lockinfo.dlerror_seen = pli->dlerror_seen;
+       }
 
        /* restore thread locking state, this time with new locks */
        thread_mask_clear(~0);
diff --git a/libexec/rtld-elf/rtld_lock.h b/libexec/rtld-elf/rtld_lock.h
index 7a61a1a525e2..fdbdc9917075 100644
--- a/libexec/rtld-elf/rtld_lock.h
+++ b/libexec/rtld-elf/rtld_lock.h
@@ -31,7 +31,7 @@
 #define        _RTLD_LOCK_H_
 
 #define        RTLI_VERSION_ONE        0x01
-#define        RTLI_VERSION            0x01
+#define        RTLI_VERSION            0x02
 
 #define        MAX_RTLD_LOCKS  8
 
@@ -46,6 +46,9 @@ struct RtldLockInfo
        int   (*thread_set_flag)(int);
        int   (*thread_clr_flag)(int);
        void  (*at_fork)(void);
+       char *(*dlerror_loc)(void);
+       int  *(*dlerror_seen)(void);
+       int   dlerror_loc_sz;
 };
 
 #if defined(IN_RTLD) || defined(PTHREAD_KERNEL)
@@ -80,6 +83,8 @@ void  lock_release(rtld_lock_t, RtldLockState *);
 void   lock_upgrade(rtld_lock_t, RtldLockState *);
 void   lock_restart_for_upgrade(RtldLockState *);
 
+void   dlerror_dflt_init(void);
+
 #endif /* IN_RTLD */
 
 #endif
_______________________________________________
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