summaryrefslogtreecommitdiffhomepage
path: root/src/ldso/nt64
diff options
context:
space:
mode:
authormidipix <writeonce@midipix.org>2017-10-28 12:42:47 -0400
committermidipix <writeonce@midipix.org>2017-10-28 18:12:39 -0400
commiteea0a81bc57597d58ef72d01ea0f9ccdd236158f (patch)
treeeb385a4386af0364c2ab2583576559844d0d98cd /src/ldso/nt64
parent03bf9aba6d06016ee4c01ba10ad19f6029c4056d (diff)
downloadmmglue-eea0a81bc57597d58ef72d01ea0f9ccdd236158f.tar.bz2
mmglue-eea0a81bc57597d58ef72d01ea0f9ccdd236158f.tar.xz
ldso: implemented dlopen().
Diffstat (limited to 'src/ldso/nt64')
-rw-r--r--src/ldso/nt64/dynlink.c107
1 files changed, 98 insertions, 9 deletions
diff --git a/src/ldso/nt64/dynlink.c b/src/ldso/nt64/dynlink.c
index c1fab74..4115178 100644
--- a/src/ldso/nt64/dynlink.c
+++ b/src/ldso/nt64/dynlink.c
@@ -1,11 +1,108 @@
#define _BSD_SOURCE
#include <stdlib.h>
+#include <string.h>
#include <dlfcn.h>
#include "psxglue.h"
#include "pthread_impl.h"
-extern struct __ldso_vtbl * __ldso_vtbl;
+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;
+
+ /* prolog */
+ if (!file)
+ return __ldso_vtbl->dlopen(0,mode,0,&status);
+
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
+ pthread_rwlock_wrlock(&__ldso_lock);
+ __inhibit_ptc();
+
+ /* loader path environment variable to loader path vector */
+ 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;
+ }
+
+ /* dlopen */
+ base = (lpath && lpathv)
+ ? __ldso_vtbl->dlopen(file,mode,lpathv,&status)
+ : 0;
+
+ /* epilog */
+ 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;
+}
int __dladdr(const void * addr, Dl_info * info)
{
@@ -22,14 +119,6 @@ void *__dlsym(void * restrict p, const char * restrict s, void * restrict ra)
return __ldso_vtbl->dlsym(p,s,ra);
}
-void * dlopen(const char * file, int mode)
-{
- return __ldso_vtbl->dlopen(
- file,mode,
- getenv("LD_LIBRARY_PATH"),
- 0);
-}
-
int dlclose(void *p)
{
return __ldso_vtbl->dlclose(p);