rtld: workaround for broken ABI

Right now, libthr does not initialize RtldLockInfo.rtli_version when calling
_rtld_thread_init(), which makes versioning the interface troublesome.

Add a workaround: if the calling object of _rtld_thread_init() exports
the "_pli_rtli_version" symbol, then consider rtli_version initialized.
Otherwise, forcibly set it to RTLI_VERSION_ONE, currently defined as
RTLI_VERSION.

Export "_pli_rtli_version" from libthr and properly initialize rtli_version.

Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D29633
This commit is contained in:
Konstantin Belousov 2021-04-10 15:32:24 +03:00
parent 4d7f08c84b
commit 08bfbd4359
4 changed files with 30 additions and 2 deletions

View File

@ -296,6 +296,9 @@ FBSDprivate_1.0 {
_thread_size_key; _thread_size_key;
_thread_state_running; _thread_state_running;
_thread_state_zoombie; _thread_state_zoombie;
/* ABI bug workaround, indicate that pli->rtli_version is valid */
_pli_rtli_version;
}; };
FBSD_1.1 { FBSD_1.1 {

View File

@ -182,6 +182,13 @@ _thr_rtld_clr_flag(int mask __unused)
return (0); return (0);
} }
/*
* ABI bug workaround: This symbol must be present for rtld to accept
* RTLI_VERSION from RtldLockInfo
*/
extern char _pli_rtli_version;
char _pli_rtli_version;
void void
_thr_rtld_init(void) _thr_rtld_init(void)
{ {
@ -205,6 +212,7 @@ _thr_rtld_init(void)
mprotect(NULL, 0, 0); mprotect(NULL, 0, 0);
_rtld_get_stack_prot(); _rtld_get_stack_prot();
li.rtli_version = RTLI_VERSION;
li.lock_create = _thr_rtld_lock_create; li.lock_create = _thr_rtld_lock_create;
li.lock_destroy = _thr_rtld_lock_destroy; li.lock_destroy = _thr_rtld_lock_destroy;
li.rlock_acquire = _thr_rtld_rlock_acquire; li.rlock_acquire = _thr_rtld_rlock_acquire;

View File

@ -344,8 +344,23 @@ lockdflt_init(void)
void void
_rtld_thread_init(struct RtldLockInfo *pli) _rtld_thread_init(struct RtldLockInfo *pli)
{ {
int flags, i; const Obj_Entry *obj;
SymLook req;
void *locks[RTLD_LOCK_CNT]; 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, "_pli_rtli_version");
res = symlook_obj(&req, obj);
if (res == 0)
lockinfo.rtli_version = pli->rtli_version;
}
}
/* disable all locking while this function is running */ /* disable all locking while this function is running */
flags = thread_mask_set(~0); flags = thread_mask_set(~0);

View File

@ -30,7 +30,9 @@
#ifndef _RTLD_LOCK_H_ #ifndef _RTLD_LOCK_H_
#define _RTLD_LOCK_H_ #define _RTLD_LOCK_H_
#define RTLI_VERSION 0x01 #define RTLI_VERSION_ONE 0x01
#define RTLI_VERSION 0x01
#define MAX_RTLD_LOCKS 8 #define MAX_RTLD_LOCKS 8
struct RtldLockInfo struct RtldLockInfo