Page MenuHomeFreeBSD

D29633.id86989.diff
No OneTemporary

D29633.id86989.diff

diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h
--- a/lib/libthr/thread/thr_private.h
+++ b/lib/libthr/thread/thr_private.h
@@ -577,6 +577,10 @@
/* 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
--- a/lib/libthr/thread/thr_rtld.c
+++ b/lib/libthr/thread/thr_rtld.c
@@ -182,6 +182,29 @@
return (0);
}
+/*
+ * ABI bug workaround: This symbol must be present for rtld to accept
+ * RTLI_VERSION from RtldLockInfo
+ */
+char *_thr_dlerror_loc(void);
+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)
{
@@ -205,6 +228,7 @@
mprotect(NULL, 0, 0);
_rtld_get_stack_prot();
+ li.rtli_version = RTLI_VERSION;
li.lock_create = _thr_rtld_lock_create;
li.lock_destroy = _thr_rtld_lock_destroy;
li.rlock_acquire = _thr_rtld_rlock_acquire;
@@ -213,6 +237,9 @@
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.h b/libexec/rtld-elf/rtld.h
--- a/libexec/rtld-elf/rtld.h
+++ b/libexec/rtld-elf/rtld.h
@@ -389,6 +389,7 @@
Obj_Entry *globallist_next(const Obj_Entry *obj);
void obj_free(Obj_Entry *);
Obj_Entry *obj_new(void);
+Obj_Entry *obj_from_addr(const void *);
void _rtld_bind_start(void);
void *rtld_resolve_ifunc(const Obj_Entry *obj, const Elf_Sym *def);
void symlook_init(SymLook *, const char *);
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -124,7 +124,6 @@
static void map_stacks_exec(RtldLockState *);
static int obj_disable_relro(Obj_Entry *);
static int obj_enforce_relro(Obj_Entry *);
-static Obj_Entry *obj_from_addr(const void *);
static void objlist_call_fini(Objlist *, Obj_Entry *, RtldLockState *);
static void objlist_call_init(Objlist *, RtldLockState *);
static void objlist_clear(Objlist *);
@@ -195,7 +194,6 @@
/*
* 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 */
@@ -443,6 +441,8 @@
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;
@@ -927,14 +927,14 @@
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());
}
/*
@@ -943,7 +943,7 @@
static char *
errmsg_save(void)
{
- return error_message == NULL ? NULL : xstrdup(error_message);
+ return (xstrdup(lockinfo.dlerror_loc()));
}
/*
@@ -953,12 +953,12 @@
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 *
@@ -2687,7 +2687,7 @@
return (NULL);
}
-static Obj_Entry *
+Obj_Entry *
obj_from_addr(const void *addr)
{
Obj_Entry *obj;
@@ -3389,9 +3389,10 @@
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.h b/libexec/rtld-elf/rtld_lock.h
--- a/libexec/rtld-elf/rtld_lock.h
+++ b/libexec/rtld-elf/rtld_lock.h
@@ -30,7 +30,9 @@
#ifndef _RTLD_LOCK_H_
#define _RTLD_LOCK_H_
-#define RTLI_VERSION 0x01
+#define RTLI_VERSION_ONE 0x01
+#define RTLI_VERSION 0x02
+
#define MAX_RTLD_LOCKS 8
struct RtldLockInfo
@@ -44,6 +46,9 @@
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;
};
extern void _rtld_thread_init(struct RtldLockInfo *) __exported;
@@ -59,6 +64,8 @@
extern rtld_lock_t rtld_libc_lock;
extern rtld_lock_t rtld_phdr_lock;
+extern struct RtldLockInfo lockinfo;
+
#define RTLD_LOCK_UNLOCKED 0
#define RTLD_LOCK_RLOCKED 1
#define RTLD_LOCK_WLOCKED 2
@@ -72,6 +79,8 @@
void lock_upgrade(rtld_lock_t, RtldLockState *);
void lock_restart_for_upgrade(RtldLockState *);
+void dlerror_dflt_init(void);
+
#endif /* IN_RTLD */
#endif
diff --git a/libexec/rtld-elf/rtld_lock.c b/libexec/rtld-elf/rtld_lock.c
--- a/libexec/rtld-elf/rtld_lock.c
+++ b/libexec/rtld-elf/rtld_lock.c
@@ -59,6 +59,21 @@
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 */
@@ -192,7 +207,7 @@
/*
* Public interface exposed to the rest of the dynamic linker.
*/
-static struct RtldLockInfo lockinfo;
+struct RtldLockInfo lockinfo;
static struct RtldLockInfo deflockinfo;
static __inline int
@@ -299,6 +314,14 @@
}
}
+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 @@
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);
@@ -344,8 +370,24 @@
void
_rtld_thread_init(struct RtldLockInfo *pli)
{
- int flags, i;
+ const Obj_Entry *obj;
+ SymLook req;
void *locks[RTLD_LOCK_CNT];
+ int flags, i, res;
+
+ if (pli == NULL) {
+ lockinfo.rtli_version = RTLI_VERSION;
+ } else {
+ lockinfo.rtli_version = RTLI_VERSION_ONE;
+ obj = obj_from_addr(pli->lock_create);
+ if (obj != NULL) {
+ symlook_init(&req, "_thr_dlerror_loc");
+ req.flags = SYMLOOK_IN_PLT;
+ res = symlook_obj(&req, obj);
+ if (res == 0)
+ lockinfo.rtli_version = pli->rtli_version;
+ }
+ }
/* disable all locking while this function is running */
flags = thread_mask_set(~0);
@@ -389,6 +431,13 @@
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);

File Metadata

Mime Type
text/plain
Expires
Thu, Dec 26, 12:10 AM (11 m, 25 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15599790
Default Alt Text
D29633.id86989.diff (7 KB)

Event Timeline