|
|
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 |
}
|