/**************************************************************************/ /* mmglue: midipix architecture- and target-specific bits for musl libc */ /* Copyright (C) 2013--2023 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.MMGLUE. */ /**************************************************************************/ #define _BSD_SOURCE #include #include #include #include #include #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; /* 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; } 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); } 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);