Blame src/ldso/nt64/dynlink.c

860627
#define _BSD_SOURCE
860627
6f8ae4
#include <unistd.h>
6f8ae4
#include <stdint.h>
ca0f58
#include <stdlib.h>
eea0a8
#include <string.h>
860627
#include <dlfcn.h>
3c3117
#include "psxglue.h"
860627
#include "pthread_impl.h"
860627
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
}
3c3117
860627
int __dladdr(const void * addr, Dl_info * info)
860627
{
3c3117
	return __ldso_vtbl->dladdr(addr,info);
860627
}
860627
860627
int __dlinfo(void * dso, int req, void * res)
860627
{
e6ac10
	return (__ldso_vtbl->dlinfo(dso,req,res)) ? -1 : 0;
860627
}
860627
b82ad8
void *__dlsym(void * restrict p, const char * restrict s)
860627
{
b82ad8
	return __ldso_vtbl->dlsym(p,s,0);
860627
}
860627
860627
int dlclose(void *p)
860627
{
3c3117
        return __ldso_vtbl->dlclose(p);
860627
}
860627
860627
char * dlerror(void)
860627
{
3c3117
	return __ldso_vtbl->dlerror();
860627
}
860627
860627
void __reset_tls(void)
860627
{
3c3117
	__ldso_vtbl->reset_tls();
860627
}
860627
860627
void *__copy_tls(unsigned char * mem)
860627
{
860627
	/**
860627
	 * this is always the simple case, since:
860627
	 * emutls is based on PE named sections; and
860627
	 * tls allocation and initialization are handled by clone(2)
860627
	**/
860627
860627
        pthread_t td;
5085e9
	uintptr_t addr;
860627
5085e9
	addr = (uintptr_t)mem;
5085e9
	addr >>= 4;
5085e9
	addr <<= 4;
5085e9
	addr +=  16;
860627
5085e9
	td = (struct __pthread *)addr;
5085e9
	td->dtv = 0;
860627
860627
	return td;
860627
}