| #define _BSD_SOURCE |
| |
| #include <unistd.h> |
| #include <stdint.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <dlfcn.h> |
| #include "psxglue.h" |
| #include "pthread_impl.h" |
| |
| extern const struct __ldso_vtbl * __ldso_vtbl; |
| extern const struct __psx_vtbl * __psx_vtbl; |
| |
| static pthread_rwlock_t __ldso_lock; |
| |
| void * dlopen(const char * file, int mode) |
| { |
| int status; |
| void * base; |
| int cs; |
| char * ch; |
| char * next; |
| char * epath; |
| char * lpath; |
| const char ** lpathv; |
| const char ** epathv; |
| char lpathbuf[2048]; |
| const char * lpathvbuf[64]; |
| int i; |
| |
| |
| if (!file) |
| return __ldso_vtbl->dlopen(0,mode,0,&status); |
| |
| pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); |
| pthread_rwlock_wrlock(&__ldso_lock); |
| __inhibit_ptc(); |
| |
| |
| if ((epath = getenv("LD_LIBRARY_PATH"))) { |
| lpath = (strncpy(lpathbuf,epath,2048) < &lpathbuf[2048]) |
| ? lpathbuf |
| : strdup(epath); |
| |
| if ((i = !!lpath)) |
| for (ch=lpath; *ch; ch++) |
| if (*ch == ':') |
| i++; |
| |
| lpathv = (++i < 64) |
| ? lpathvbuf |
| : calloc(++i,sizeof(char *)); |
| } else { |
| lpath = lpathbuf; |
| lpathv = lpathvbuf; |
| lpath[0] = 0; |
| } |
| |
| if (lpath && lpathv) { |
| ch = lpath; |
| next = *ch ? ch : 0; |
| epathv = lpathv; |
| |
| for (; next; ) { |
| *epathv++ = (*next == ':') |
| ? "." |
| : next; |
| |
| ch = &next[1]; |
| |
| for (; *ch; ) { |
| if (*ch == ':') { |
| *ch = 0; |
| ch = 0; |
| } else { |
| ch++; |
| } |
| } |
| |
| next = *ch ? ch : 0; |
| } |
| |
| *epathv = 0; |
| } |
| |
| |
| base = (lpath && lpathv) |
| ? __ldso_vtbl->dlopen(file,mode,lpathv,&status) |
| : 0; |
| |
| |
| if (lpath && (lpath != lpathbuf)) |
| free(lpath); |
| |
| if (lpathv && (lpathv != lpathvbuf)) |
| free(lpathv); |
| |
| __release_ptc(); |
| pthread_rwlock_unlock(&__ldso_lock); |
| |
| if (base) |
| __psx_vtbl->do_global_ctors_fn(); |
| |
| pthread_setcancelstate(cs, 0); |
| |
| return base; |
| } |
| |
| void * __dldopen(int fd, int mode) |
| { |
| int status; |
| void * base; |
| int cs; |
| |
| |
| pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); |
| pthread_rwlock_wrlock(&__ldso_lock); |
| __inhibit_ptc(); |
| |
| |
| base = __ldso_vtbl->dldopen(fd,mode,&status); |
| |
| |
| __release_ptc(); |
| pthread_rwlock_unlock(&__ldso_lock); |
| |
| if (base) |
| __psx_vtbl->do_global_ctors_fn(); |
| |
| pthread_setcancelstate(cs, 0); |
| |
| return base; |
| } |
| |
| void * __dlsopen(const char * file, int mode) |
| { |
| int status; |
| void * base; |
| int cs; |
| |
| |
| pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); |
| pthread_rwlock_wrlock(&__ldso_lock); |
| __inhibit_ptc(); |
| |
| |
| base = __ldso_vtbl->dlsopen(file,mode,&status); |
| |
| |
| __release_ptc(); |
| pthread_rwlock_unlock(&__ldso_lock); |
| |
| if (base) |
| __psx_vtbl->do_global_ctors_fn(); |
| |
| pthread_setcancelstate(cs, 0); |
| |
| return base; |
| } |
| |
| int __dladdr(const void * addr, Dl_info * info) |
| { |
| return __ldso_vtbl->dladdr(addr,info); |
| } |
| |
| int __dlinfo(void * dso, int req, void * res) |
| { |
| return (__ldso_vtbl->dlinfo(dso,req,res)) ? -1 : 0; |
| } |
| |
| void *__dlsym(void * restrict p, const char * restrict s) |
| { |
| return __ldso_vtbl->dlsym(p,s,0); |
| } |
| |
| int dlclose(void *p) |
| { |
| return __ldso_vtbl->dlclose(p); |
| } |
| |
| char * dlerror(void) |
| { |
| return __ldso_vtbl->dlerror(); |
| } |
| |
| weak_alias(__dlsym,dlsym); |
| weak_alias(__dladdr,dladdr); |
| weak_alias(__dlinfo,dlinfo); |