diff --git a/arch/nt32/psxglue.h b/arch/nt32/psxglue.h index d8e653a..b8f22b8 100644 --- a/arch/nt32/psxglue.h +++ b/arch/nt32/psxglue.h @@ -14,6 +14,8 @@ struct __ldso_vtbl { int (*dlinfo) (void * dso, int req, void * res); void * (*dlsym) (void * p, const char * s, void * ra); void * (*dlopen) (const char * file, int mode, const char ** pathv, int * status); + void * (*dldopen) (int fd, int mode, int * status); + void * (*dlsopen) (const char * file, int mode, int * status); int (*dlclose) (void *p); char * (*dlerror) (void); void (*tlsreset) (void); diff --git a/arch/nt64/psxglue.h b/arch/nt64/psxglue.h index d8e653a..b8f22b8 100644 --- a/arch/nt64/psxglue.h +++ b/arch/nt64/psxglue.h @@ -14,6 +14,8 @@ struct __ldso_vtbl { int (*dlinfo) (void * dso, int req, void * res); void * (*dlsym) (void * p, const char * s, void * ra); void * (*dlopen) (const char * file, int mode, const char ** pathv, int * status); + void * (*dldopen) (int fd, int mode, int * status); + void * (*dlsopen) (const char * file, int mode, int * status); int (*dlclose) (void *p); char * (*dlerror) (void); void (*tlsreset) (void); diff --git a/include/sys/ldso.h b/include/sys/ldso.h new file mode 100644 index 0000000..8013b6a --- /dev/null +++ b/include/sys/ldso.h @@ -0,0 +1,15 @@ +#ifndef _SYS_LDSO_H +#define _SYS_LDSO_H + +#ifdef __cplusplus +extern "C" { +#endif + +void * __dldopen(int, int); +void * __dlsopen(const char *, int); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/project/arch.mk b/project/arch.mk index a33fd09..76bca17 100644 --- a/project/arch.mk +++ b/project/arch.mk @@ -24,6 +24,7 @@ LDFLAGS_CONFIG += -Wl,--exclude-symbols=___errno_location TARGET_SYS_HEADERS = \ $(PROJECT_DIR)/include/sys/debug.h \ + $(PROJECT_DIR)/include/sys/ldso.h \ $(PROJECT_DIR)/include/sys/unwind.h \ install-headers: install-target-sys-headers diff --git a/src/ldso/nt32/dynlink.c b/src/ldso/nt32/dynlink.c index a585fbb..c0a1f04 100644 --- a/src/ldso/nt32/dynlink.c +++ b/src/ldso/nt32/dynlink.c @@ -106,6 +106,58 @@ void * dlopen(const char * file, int mode) return base; } +void * __dldopen(int fd, int mode) +{ + int status; + void * base; + int cs; + + /* prolog */ + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); + pthread_rwlock_wrlock(&__ldso_lock); + __inhibit_ptc(); + + /* dldopen */ + base = __ldso_vtbl->dldopen(fd,mode,&status); + + /* epilog */ + __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; + + /* prolog */ + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); + pthread_rwlock_wrlock(&__ldso_lock); + __inhibit_ptc(); + + /* dlsopen */ + base = __ldso_vtbl->dlsopen(file,mode,&status); + + /* epilog */ + __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); diff --git a/src/ldso/nt64/dynlink.c b/src/ldso/nt64/dynlink.c index a585fbb..c0a1f04 100644 --- a/src/ldso/nt64/dynlink.c +++ b/src/ldso/nt64/dynlink.c @@ -106,6 +106,58 @@ void * dlopen(const char * file, int mode) return base; } +void * __dldopen(int fd, int mode) +{ + int status; + void * base; + int cs; + + /* prolog */ + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); + pthread_rwlock_wrlock(&__ldso_lock); + __inhibit_ptc(); + + /* dldopen */ + base = __ldso_vtbl->dldopen(fd,mode,&status); + + /* epilog */ + __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; + + /* prolog */ + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); + pthread_rwlock_wrlock(&__ldso_lock); + __inhibit_ptc(); + + /* dlsopen */ + base = __ldso_vtbl->dlsopen(file,mode,&status); + + /* epilog */ + __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);