Blame src/ldso/nt32/dynlink.c

716654
/**************************************************************************/
716654
/*  mmglue: midipix architecture- and target-specific bits for musl libc  */
716654
/*  Copyright (C) 2013--2023  SysDeer Technologies, LLC                   */
000ff7
/*  Released under GPLv2 and GPLv3; see COPYING.MMGLUE.                   */
716654
/**************************************************************************/
716654
296178
#define _BSD_SOURCE
296178
6f8ae4
#include <unistd.h>
6f8ae4
#include <stdint.h>
ca0f58
#include <stdlib.h>
eea0a8
#include <string.h>
296178
#include <dlfcn.h>
296178
#include "psxglue.h"
296178
#include "pthread_impl.h"
296178
eea0a8
extern const struct __ldso_vtbl * __ldso_vtbl;
eea0a8
extern const struct __psx_vtbl *  __psx_vtbl;
eea0a8
eea0a8
static pthread_rwlock_t __ldso_lock;
eea0a8
eea0a8
void * dlopen(const char * file, int mode)
eea0a8
{
eea0a8
	int		status;
eea0a8
	void *		base;
eea0a8
	int		cs;
eea0a8
	char *		ch;
eea0a8
	char *		next;
eea0a8
	char *		epath;
eea0a8
	char *		lpath;
eea0a8
	const char **	lpathv;
eea0a8
	const char **	epathv;
eea0a8
	char		lpathbuf[2048];
eea0a8
	const char *	lpathvbuf[64];
eea0a8
	int		i;
eea0a8
eea0a8
	/* prolog */
eea0a8
	if (!file)
eea0a8
		return __ldso_vtbl->dlopen(0,mode,0,&status);
eea0a8
eea0a8
	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
eea0a8
	pthread_rwlock_wrlock(&__ldso_lock);
eea0a8
	__inhibit_ptc();
eea0a8
eea0a8
	/* loader path environment variable to loader path vector */
eea0a8
	if ((epath = getenv("LD_LIBRARY_PATH"))) {
eea0a8
		lpath = (strncpy(lpathbuf,epath,2048) < &lpathbuf[2048])
eea0a8
			? lpathbuf
eea0a8
			: strdup(epath);
eea0a8
eea0a8
		if ((i = !!lpath))
eea0a8
			for (ch=lpath; *ch; ch++)
eea0a8
				if (*ch == ':')
eea0a8
					i++;
eea0a8
eea0a8
		lpathv = (++i < 64)
eea0a8
			? lpathvbuf
eea0a8
			: calloc(++i,sizeof(char *));
eea0a8
	} else {
eea0a8
		lpath    = lpathbuf;
eea0a8
		lpathv   = lpathvbuf;
eea0a8
		lpath[0] = 0;
eea0a8
	}
eea0a8
eea0a8
	if (lpath && lpathv) {
eea0a8
		ch     = lpath;
eea0a8
		next   = *ch ? ch : 0;
eea0a8
		epathv = lpathv;
eea0a8
eea0a8
		for (; next; ) {
eea0a8
			*epathv++ = (*next == ':')
eea0a8
				? "."
eea0a8
				: next;
eea0a8
eea0a8
			ch = &next[1];
eea0a8
eea0a8
			for (; *ch; ) {
eea0a8
				if (*ch == ':') {
eea0a8
					*ch = 0;
eea0a8
					ch  = 0;
eea0a8
				} else {
eea0a8
					ch++;
eea0a8
				}
eea0a8
			}
eea0a8
eea0a8
			next = *ch ? ch : 0;
eea0a8
		}
eea0a8
eea0a8
		*epathv = 0;
eea0a8
	}
eea0a8
eea0a8
	/* dlopen */
eea0a8
	base = (lpath && lpathv)
eea0a8
		? __ldso_vtbl->dlopen(file,mode,lpathv,&status)
eea0a8
		: 0;
eea0a8
eea0a8
	/* epilog */
eea0a8
	if (lpath && (lpath != lpathbuf))
eea0a8
		free(lpath);
eea0a8
eea0a8
	if (lpathv && (lpathv != lpathvbuf))
eea0a8
		free(lpathv);
eea0a8
eea0a8
	__release_ptc();
eea0a8
	pthread_rwlock_unlock(&__ldso_lock);
eea0a8
eea0a8
	if (base)
eea0a8
		__psx_vtbl->do_global_ctors_fn();
eea0a8
eea0a8
	pthread_setcancelstate(cs, 0);
eea0a8
eea0a8
	return base;
eea0a8
}
296178
724fbc
void * __dldopen(int fd, int mode)
724fbc
{
724fbc
	int		status;
724fbc
	void *		base;
724fbc
	int		cs;
724fbc
724fbc
	/* prolog */
724fbc
	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
724fbc
	pthread_rwlock_wrlock(&__ldso_lock);
724fbc
	__inhibit_ptc();
724fbc
724fbc
	/* dldopen */
724fbc
	base = __ldso_vtbl->dldopen(fd,mode,&status);
724fbc
724fbc
	/* epilog */
724fbc
	__release_ptc();
724fbc
	pthread_rwlock_unlock(&__ldso_lock);
724fbc
724fbc
	if (base)
724fbc
		__psx_vtbl->do_global_ctors_fn();
724fbc
724fbc
	pthread_setcancelstate(cs, 0);
724fbc
724fbc
	return base;
724fbc
}
724fbc
724fbc
void * __dlsopen(const char * file, int mode)
724fbc
{
724fbc
	int		status;
724fbc
	void *		base;
724fbc
	int		cs;
724fbc
724fbc
	/* prolog */
724fbc
	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
724fbc
	pthread_rwlock_wrlock(&__ldso_lock);
724fbc
	__inhibit_ptc();
724fbc
724fbc
	/* dlsopen */
724fbc
	base = __ldso_vtbl->dlsopen(file,mode,&status);
724fbc
724fbc
	/* epilog */
724fbc
	__release_ptc();
724fbc
	pthread_rwlock_unlock(&__ldso_lock);
724fbc
724fbc
	if (base)
724fbc
		__psx_vtbl->do_global_ctors_fn();
724fbc
724fbc
	pthread_setcancelstate(cs, 0);
724fbc
724fbc
	return base;
724fbc
}
724fbc
296178
int __dladdr(const void * addr, Dl_info * info)
296178
{
296178
	return __ldso_vtbl->dladdr(addr,info);
296178
}
296178
296178
int __dlinfo(void * dso, int req, void * res)
296178
{
e6ac10
	return (__ldso_vtbl->dlinfo(dso,req,res)) ? -1 : 0;
296178
}
296178
b82ad8
void *__dlsym(void * restrict p, const char * restrict s)
296178
{
b82ad8
	return __ldso_vtbl->dlsym(p,s,0);
296178
}
296178
296178
int dlclose(void *p)
296178
{
296178
        return __ldso_vtbl->dlclose(p);
296178
}
296178
296178
char * dlerror(void)
296178
{
296178
	return __ldso_vtbl->dlerror();
296178
}
296178
d88860
weak_alias(__dlsym,dlsym);
0bbce1
weak_alias(__dladdr,dladdr);
d88860
weak_alias(__dlinfo,dlinfo);