about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/emu/x64emu_private.h1
-rwxr-xr-xsrc/emu/x64syscall.c15
-rwxr-xr-xsrc/include/callback.h2
-rwxr-xr-xsrc/libtools/threads.c78
-rw-r--r--src/wrapped/generated/functions_list.txt7
-rw-r--r--src/wrapped/generated/wrappedlibctypes.h3
-rw-r--r--src/wrapped/generated/wrappednss3types.h4
-rw-r--r--src/wrapped/generated/wrapper.c5
-rw-r--r--src/wrapped/generated/wrapper.h2
-rwxr-xr-xsrc/wrapped/wrappedlibc.c107
-rwxr-xr-xsrc/wrapped/wrappedlibc_private.h6
-rwxr-xr-xsrc/wrapped/wrappednss3.c41
-rwxr-xr-xsrc/wrapped/wrappednss3_private.h44
13 files changed, 257 insertions, 58 deletions
diff --git a/src/emu/x64emu_private.h b/src/emu/x64emu_private.h
index cf81d316..114731eb 100755
--- a/src/emu/x64emu_private.h
+++ b/src/emu/x64emu_private.h
@@ -73,6 +73,7 @@ typedef struct x64emu_s {
     forkpty_t*  forkpty_info;
     int         exit;
     int         quitonlongjmp;  // quit if longjmp is called
+    int         quitonexit;     // quit if exit/_exit is called
     int         longjmp;        // if quit because of longjmp
     // scratch stack, used for alignement of double and 64bits ints on arm. 200 elements should be enough
     uint64_t    scratch[200];
diff --git a/src/emu/x64syscall.c b/src/emu/x64syscall.c
index fc237939..4ca3547e 100755
--- a/src/emu/x64syscall.c
+++ b/src/emu/x64syscall.c
@@ -54,6 +54,9 @@ void* my_mmap64(x64emu_t* emu, void *addr, unsigned long length, int prot, int f
 int my_munmap(x64emu_t* emu, void* addr, unsigned long length);
 int my_mprotect(x64emu_t* emu, void *addr, unsigned long len, int prot);
 void* my_mremap(x64emu_t* emu, void* old_addr, size_t old_size, size_t new_size, int flags, void* new_addr);
+#ifndef NO_ALIGN
+int32_t my_epoll_wait(x64emu_t* emu, int32_t epfd, void* events, int32_t maxevents, int32_t timeout);
+#endif
 
 // cannot include <fcntl.h>, it conflict with some asm includes...
 #ifndef O_NONBLOCK
@@ -471,7 +474,7 @@ void EXPORT x64Syscall(x64emu_t *emu)
             break;
         #endif
         #ifndef __NR_rename
-	case 82: // sys_rename
+	    case 82: // sys_rename
 	    *(int64_t*)&R_RAX = rename((void*)R_RDI, (void*)R_RSI);
 	    break;
         #endif
@@ -499,6 +502,11 @@ void EXPORT x64Syscall(x64emu_t *emu)
             R_RAX = (uintptr_t)time((void*)R_RDI);
             break;
         #endif
+        #if !defined(__NR_epoll_wait) && !defined(NO_ALIGN)
+        case 232:
+            R_RAX = my_epoll_wait(emu, (int)R_EDI, (void*)R_RSI, (int)R_EDX, (int)R_R8d);
+            break;
+        #endif
         #ifndef __NR_inotify_init
         case 253:
             R_EAX = (int)syscall(__NR_inotify_init1, 0);
@@ -698,6 +706,11 @@ uintptr_t EXPORT my_syscall(x64emu_t *emu)
         case 201: // sys_time
             return (uintptr_t)time((void*)R_RSI);
         #endif
+        #if !defined(__NR_epoll_wait) && !defined(NO_ALIGN)
+        case 232:
+            R_RAX = my_epoll_wait(emu, (int)R_ESI, (void*)R_RDX, (int)R_ECX, (int)R_R8d);
+            break;
+        #endif
         #ifndef __NR_inotify_init
         case 253:
             return (int)syscall(__NR_inotify_init1, 0);
diff --git a/src/include/callback.h b/src/include/callback.h
index b9482fc1..dba59ee8 100755
--- a/src/include/callback.h
+++ b/src/include/callback.h
@@ -7,6 +7,6 @@ typedef struct x64emu_s x64emu_t;
 
 uint64_t RunFunction(box64context_t *context, uintptr_t fnc, int nargs, ...);
 // use emu state to run function
-uint64_t RunFunctionWithEmu(x64emu_t *emu, int QuitOnLongJump, uintptr_t fnc, int nargs, ...);
+uint64_t RunFunctionWithEmu(x64emu_t *emu, int QuitOnLongJumpExit, uintptr_t fnc, int nargs, ...);
 
 #endif //__CALLBACK_H__
\ No newline at end of file
diff --git a/src/libtools/threads.c b/src/libtools/threads.c
index 684c5fdc..7dc7cb76 100755
--- a/src/libtools/threads.c
+++ b/src/libtools/threads.c
@@ -180,6 +180,11 @@ void thread_set_emu(x64emu_t* emu)
 	// create the key
 	pthread_once(&thread_key_once, thread_key_alloc);
 	emuthread_t *et = (emuthread_t*)pthread_getspecific(thread_key);
+	if(!emu) {
+		if(et) free(et);
+		pthread_setspecific(thread_key, NULL);
+		return;
+	}
 	if(!et) {
 		et = (emuthread_t*)calloc(1, sizeof(emuthread_t));
 	} else {
@@ -672,27 +677,37 @@ EXPORT int my_pthread_key_create(x64emu_t* emu, void* key, void* dtor)
 EXPORT int my___pthread_key_create(x64emu_t* emu, void* key, void* dtor) __attribute__((alias("my_pthread_key_create")));
 
 pthread_mutex_t* getAlignedMutex(pthread_mutex_t* m);
-
+void updateAlignedMutex(pthread_mutex_t* m, pthread_mutex_t* real);
 
 EXPORT int my_pthread_cond_timedwait(x64emu_t* emu, pthread_cond_t* cond, void* mutex, void* abstime)
 {
 	(void)emu;
-	return pthread_cond_timedwait(cond, getAlignedMutex((pthread_mutex_t*)mutex), (const struct timespec*)abstime);
+	pthread_mutex_t *real = getAlignedMutex(mutex);
+	int ret = pthread_cond_timedwait(cond, real, (const struct timespec*)abstime);
+	updateAlignedMutex(mutex, real);
+	return ret;
 }
 EXPORT int my_pthread_cond_wait(x64emu_t* emu, pthread_cond_t* cond, void* mutex)
 {
 	(void)emu;
-	return pthread_cond_wait(cond, getAlignedMutex((pthread_mutex_t*)mutex));
+	pthread_mutex_t *real = getAlignedMutex(mutex);
+	int ret = pthread_cond_wait(cond, real);
+	updateAlignedMutex(mutex, real);
+	return ret;
 }
 EXPORT int my_pthread_cond_clockwait(x64emu_t *emu, pthread_cond_t* cond, void* mutex, __clockid_t __clock_id, const struct timespec* __abstime)
 {
 	(void)emu;
-	if(real_pthread_cond_clockwait)
-		return real_pthread_cond_clockwait(cond, getAlignedMutex((pthread_mutex_t*)mutex), __clock_id, (void*)__abstime);
-	else {
+	int ret;
+	if(real_pthread_cond_clockwait) {
+		pthread_mutex_t *real = getAlignedMutex(mutex);
+		ret = real_pthread_cond_clockwait(cond, real, __clock_id, (void*)__abstime);
+		updateAlignedMutex(mutex, real);
+	} else {
 		errno = EINVAL;
-		return -1;
+		ret = -1;
 	}
+	return ret;
 }
 
 EXPORT void my__pthread_cleanup_push_defer(x64emu_t* emu, void* buffer, void* routine, void* arg)
@@ -771,6 +786,7 @@ EXPORT int my_pthread_kill(x64emu_t* emu, void* thread, int sig)
 pthread_mutex_t* getAlignedMutex(pthread_mutex_t* m) {
 	return m;
 }
+void updateAlignedMutex(pthread_mutex_t* m, pthread_mutex_t* real) { }
 #else
 #define MUTEXES_SIZE	64
 typedef struct mutexes_block_s {
@@ -850,8 +866,12 @@ pthread_mutex_t* GetMutex(int k)
 
 // x86_64 pthread_mutex_t is 40 bytes (ARM64 one is 48)
 typedef struct aligned_mutex_s {
-	struct aligned_mutex_s *self;
-	uint64_t	dummy;
+	//struct aligned_mutex_s *self;
+	//uint64_t	dummy;
+	int lock;
+	unsigned int count;
+  	int owner;
+	unsigned int nusers;
 	int kind;	// kind position on x86_64
 	int k;
 	pthread_mutex_t* m;
@@ -864,11 +884,11 @@ pthread_mutex_t* getAlignedMutexWithInit(pthread_mutex_t* m, int init)
 	if(!m)
 		return NULL;
 	aligned_mutex_t* am = (aligned_mutex_t*)m;
-	if(init && (am->sign==SIGNMTX && am->self==am))
+	if(init && (am->sign==SIGNMTX /*&& am->self==am*/))
 		return am->m;
 	int k = NewMutex();
-	// check again, it might be created now becayse NewMutex is under mutex
-	if(init && (am->sign==SIGNMTX && am->self==am)) {
+	// check again, it might be created now because NewMutex is under mutex
+	if(init && (am->sign==SIGNMTX /*&& am->self==am*/)) {
 		FreeMutex(k);
 		return am->m;
 	}
@@ -887,7 +907,7 @@ pthread_mutex_t* getAlignedMutexWithInit(pthread_mutex_t* m, int init)
 			((int*)ret)[3+__PTHREAD_MUTEX_HAVE_PREV] = kind;		// inject in new one (i.e. "init" it)
 		}
 	}
-	am->self = am;
+	//am->self = am;
 	am->sign = SIGNMTX;
 	am->k = k;
 	am->m = ret;
@@ -897,6 +917,13 @@ pthread_mutex_t* getAlignedMutex(pthread_mutex_t* m)
 {
 	return getAlignedMutexWithInit(m, 1);
 }
+void updateAlignedMutex(pthread_mutex_t* m, pthread_mutex_t* real)
+{
+	aligned_mutex_t* e = (aligned_mutex_t*)m;
+	e->kind = real->__data.__kind;
+	e->lock = real->__data.__lock;
+	e->owner = real->__data.__owner;
+}
 
 EXPORT int my_pthread_mutex_destroy(pthread_mutex_t *m)
 {
@@ -1000,31 +1027,46 @@ EXPORT int my_pthread_mutex_init(pthread_mutex_t *m, my_mutexattr_t *att)
 	my_mutexattr_t mattr = {0};
 	if(att)
 		mattr.x86 = att->x86;
-	return pthread_mutex_init(getAlignedMutexWithInit(m, 0), att?(&mattr.nat):NULL);
+	pthread_mutex_t *real = getAlignedMutexWithInit(m, 0);
+	int ret = pthread_mutex_init(real, att?(&mattr.nat):NULL);
+	updateAlignedMutex(m, real);
+	return ret;
 }
 EXPORT int my___pthread_mutex_init(pthread_mutex_t *m, my_mutexattr_t *att) __attribute__((alias("my_pthread_mutex_init")));
 
 EXPORT int my_pthread_mutex_lock(pthread_mutex_t *m)
 {
-	return pthread_mutex_lock(getAlignedMutex(m));
+	pthread_mutex_t *real = getAlignedMutex(m);
+	int ret = pthread_mutex_lock(real);
+	updateAlignedMutex(m, real);
+	return ret;
 }
 EXPORT int my___pthread_mutex_lock(pthread_mutex_t *m) __attribute__((alias("my_pthread_mutex_lock")));
 
 EXPORT int my_pthread_mutex_timedlock(pthread_mutex_t *m, const struct timespec * t)
 {
-	return pthread_mutex_timedlock(getAlignedMutex(m), t);
+	pthread_mutex_t *real = getAlignedMutex(m);
+	int ret = pthread_mutex_timedlock(real, t);
+	updateAlignedMutex(m, real);
+	return ret;
 }
 EXPORT int my___pthread_mutex_trylock(pthread_mutex_t *m, const struct timespec * t) __attribute__((alias("my_pthread_mutex_timedlock")));
 
 EXPORT int my_pthread_mutex_trylock(pthread_mutex_t *m)
 {
-	return pthread_mutex_trylock(getAlignedMutex(m));
+	pthread_mutex_t *real = getAlignedMutex(m);
+	int ret = pthread_mutex_trylock(real);
+	updateAlignedMutex(m, real);
+	return ret;
 }
 EXPORT int my___pthread_mutex_unlock(pthread_mutex_t *m) __attribute__((alias("my_pthread_mutex_trylock")));
 
 EXPORT int my_pthread_mutex_unlock(pthread_mutex_t *m)
 {
-	return pthread_mutex_unlock(getAlignedMutex(m));
+	pthread_mutex_t *real = getAlignedMutex(m);
+	int ret = pthread_mutex_unlock(real);
+	updateAlignedMutex(m, real);
+	return ret;
 }
 
 typedef union my_condattr_s {
diff --git a/src/wrapped/generated/functions_list.txt b/src/wrapped/generated/functions_list.txt
index 65bf8028..2f8acdc6 100644
--- a/src/wrapped/generated/functions_list.txt
+++ b/src/wrapped/generated/functions_list.txt
@@ -87,6 +87,7 @@
 #() pFV
 #() HFi
 #() HFp
+#() vFEi
 #() vFEp
 #() vFii
 #() vFiI
@@ -1148,6 +1149,7 @@
 #() iFpippi
 #() iFpippW
 #() iFpippp
+#() iFpIppp
 #() iFpCCCC
 #() iFpuill
 #() iFpuipi
@@ -2786,6 +2788,9 @@ wrappedlibc:
   - _Jv_RegisterClasses
   - __cxa_pure_virtual
   - __stack_chk_fail
+- vFi:
+  - _exit
+  - exit
 - vFp:
   - _ITM_deregisterTMCloneTable
   - __cxa_finalize
@@ -3434,6 +3439,8 @@ wrappednspr4:
 wrappednss3:
 - vFp:
   - PK11_SetPasswordFunc
+- iFpp:
+  - CERT_RegisterAlternateOCSPAIAInfoCallBack
 wrappednssutil3:
 wrappedopenal:
 - vFv:
diff --git a/src/wrapped/generated/wrappedlibctypes.h b/src/wrapped/generated/wrappedlibctypes.h
index 74166f2c..2de2464a 100644
--- a/src/wrapped/generated/wrappedlibctypes.h
+++ b/src/wrapped/generated/wrappedlibctypes.h
@@ -12,6 +12,7 @@
 #endif
 
 typedef void (*vFv_t)(void);
+typedef void (*vFi_t)(int64_t);
 typedef void (*vFp_t)(void*);
 typedef int64_t (*iFv_t)(void);
 typedef int64_t (*iFi_t)(int64_t);
@@ -88,6 +89,8 @@ typedef int64_t (*iFppipppp_t)(void*, void*, int64_t, void*, void*, void*, void*
 	GO(_Jv_RegisterClasses, vFv_t) \
 	GO(__cxa_pure_virtual, vFv_t) \
 	GO(__stack_chk_fail, vFv_t) \
+	GO(_exit, vFi_t) \
+	GO(exit, vFi_t) \
 	GO(_ITM_deregisterTMCloneTable, vFp_t) \
 	GO(__cxa_finalize, vFp_t) \
 	GO(fork, iFv_t) \
diff --git a/src/wrapped/generated/wrappednss3types.h b/src/wrapped/generated/wrappednss3types.h
index b61ede44..640f7da6 100644
--- a/src/wrapped/generated/wrappednss3types.h
+++ b/src/wrapped/generated/wrappednss3types.h
@@ -12,8 +12,10 @@
 #endif
 
 typedef void (*vFp_t)(void*);
+typedef int64_t (*iFpp_t)(void*, void*);
 
 #define SUPER() ADDED_FUNCTIONS() \
-	GO(PK11_SetPasswordFunc, vFp_t)
+	GO(PK11_SetPasswordFunc, vFp_t) \
+	GO(CERT_RegisterAlternateOCSPAIAInfoCallBack, iFpp_t)
 
 #endif // __wrappednss3TYPES_H_
diff --git a/src/wrapped/generated/wrapper.c b/src/wrapped/generated/wrapper.c
index 3bb9c270..3fcebe43 100644
--- a/src/wrapped/generated/wrapper.c
+++ b/src/wrapped/generated/wrapper.c
@@ -121,6 +121,7 @@ typedef void* (*pFp_t)(void*);
 typedef void* (*pFV_t)(void*);
 typedef unsigned __int128 (*HFi_t)(int64_t);
 typedef unsigned __int128 (*HFp_t)(void*);
+typedef void (*vFEi_t)(x64emu_t*, int64_t);
 typedef void (*vFEp_t)(x64emu_t*, void*);
 typedef void (*vFii_t)(int64_t, int64_t);
 typedef void (*vFiI_t)(int64_t, int64_t);
@@ -1182,6 +1183,7 @@ typedef int64_t (*iFpipip_t)(void*, int64_t, void*, int64_t, void*);
 typedef int64_t (*iFpippi_t)(void*, int64_t, void*, void*, int64_t);
 typedef int64_t (*iFpippW_t)(void*, int64_t, void*, void*, uint16_t);
 typedef int64_t (*iFpippp_t)(void*, int64_t, void*, void*, void*);
+typedef int64_t (*iFpIppp_t)(void*, int64_t, void*, void*, void*);
 typedef int64_t (*iFpCCCC_t)(void*, uint8_t, uint8_t, uint8_t, uint8_t);
 typedef int64_t (*iFpuill_t)(void*, uint64_t, int64_t, intptr_t, intptr_t);
 typedef int64_t (*iFpuipi_t)(void*, uint64_t, int64_t, void*, int64_t);
@@ -2254,6 +2256,7 @@ void pFp(x64emu_t *emu, uintptr_t fcn) { pFp_t fn = (pFp_t)fcn; R_RAX=(uintptr_t
 void pFV(x64emu_t *emu, uintptr_t fcn) { pFV_t fn = (pFV_t)fcn; R_RAX=(uintptr_t)fn((void*)(R_RSP + 8)); }
 void HFi(x64emu_t *emu, uintptr_t fcn) { HFi_t fn = (HFi_t)fcn; unsigned __int128 u128 = fn((int64_t)R_RDI); R_RAX=(u128&0xFFFFFFFFFFFFFFFFL); R_RDX=(u128>>64)&0xFFFFFFFFFFFFFFFFL; }
 void HFp(x64emu_t *emu, uintptr_t fcn) { HFp_t fn = (HFp_t)fcn; unsigned __int128 u128 = fn((void*)R_RDI); R_RAX=(u128&0xFFFFFFFFFFFFFFFFL); R_RDX=(u128>>64)&0xFFFFFFFFFFFFFFFFL; }
+void vFEi(x64emu_t *emu, uintptr_t fcn) { vFEi_t fn = (vFEi_t)fcn; fn(emu, (int64_t)R_RDI); }
 void vFEp(x64emu_t *emu, uintptr_t fcn) { vFEp_t fn = (vFEp_t)fcn; fn(emu, (void*)R_RDI); }
 void vFii(x64emu_t *emu, uintptr_t fcn) { vFii_t fn = (vFii_t)fcn; fn((int64_t)R_RDI, (int64_t)R_RSI); }
 void vFiI(x64emu_t *emu, uintptr_t fcn) { vFiI_t fn = (vFiI_t)fcn; fn((int64_t)R_RDI, (int64_t)R_RSI); }
@@ -3315,6 +3318,7 @@ void iFpipip(x64emu_t *emu, uintptr_t fcn) { iFpipip_t fn = (iFpipip_t)fcn; R_RA
 void iFpippi(x64emu_t *emu, uintptr_t fcn) { iFpippi_t fn = (iFpippi_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (int64_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (int64_t)R_R8); }
 void iFpippW(x64emu_t *emu, uintptr_t fcn) { iFpippW_t fn = (iFpippW_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (int64_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (uint16_t)R_R8); }
 void iFpippp(x64emu_t *emu, uintptr_t fcn) { iFpippp_t fn = (iFpippp_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (int64_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8); }
+void iFpIppp(x64emu_t *emu, uintptr_t fcn) { iFpIppp_t fn = (iFpIppp_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (int64_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8); }
 void iFpCCCC(x64emu_t *emu, uintptr_t fcn) { iFpCCCC_t fn = (iFpCCCC_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (uint8_t)R_RSI, (uint8_t)R_RDX, (uint8_t)R_RCX, (uint8_t)R_R8); }
 void iFpuill(x64emu_t *emu, uintptr_t fcn) { iFpuill_t fn = (iFpuill_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (uint64_t)R_RSI, (int64_t)R_RDX, (intptr_t)R_RCX, (intptr_t)R_R8); }
 void iFpuipi(x64emu_t *emu, uintptr_t fcn) { iFpuipi_t fn = (iFpuipi_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (uint64_t)R_RSI, (int64_t)R_RDX, (void*)R_RCX, (int64_t)R_R8); }
@@ -5281,6 +5285,7 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &iFpippi) return 1;
 	if (fun == &iFpippW) return 1;
 	if (fun == &iFpippp) return 1;
+	if (fun == &iFpIppp) return 1;
 	if (fun == &iFpCCCC) return 1;
 	if (fun == &iFpuill) return 1;
 	if (fun == &iFpuipi) return 1;
diff --git a/src/wrapped/generated/wrapper.h b/src/wrapped/generated/wrapper.h
index 5d8b6b5b..9a08256f 100644
--- a/src/wrapped/generated/wrapper.h
+++ b/src/wrapped/generated/wrapper.h
@@ -120,6 +120,7 @@ void pFp(x64emu_t *emu, uintptr_t fnc);
 void pFV(x64emu_t *emu, uintptr_t fnc);
 void HFi(x64emu_t *emu, uintptr_t fnc);
 void HFp(x64emu_t *emu, uintptr_t fnc);
+void vFEi(x64emu_t *emu, uintptr_t fnc);
 void vFEp(x64emu_t *emu, uintptr_t fnc);
 void vFii(x64emu_t *emu, uintptr_t fnc);
 void vFiI(x64emu_t *emu, uintptr_t fnc);
@@ -1181,6 +1182,7 @@ void iFpipip(x64emu_t *emu, uintptr_t fnc);
 void iFpippi(x64emu_t *emu, uintptr_t fnc);
 void iFpippW(x64emu_t *emu, uintptr_t fnc);
 void iFpippp(x64emu_t *emu, uintptr_t fnc);
+void iFpIppp(x64emu_t *emu, uintptr_t fnc);
 void iFpCCCC(x64emu_t *emu, uintptr_t fnc);
 void iFpuill(x64emu_t *emu, uintptr_t fnc);
 void iFpuipi(x64emu_t *emu, uintptr_t fnc);
diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c
index 3c1b7a82..6d5cab3e 100755
--- a/src/wrapped/wrappedlibc.c
+++ b/src/wrapped/wrappedlibc.c
@@ -1673,6 +1673,10 @@ EXPORT int32_t my_nftw64(x64emu_t* emu, void* pathname, void* B, int32_t nopenfd
     return nftw64(pathname, findnftw64Fct(B), nopenfd, flags);
 }
 
+EXPORT char** my_environ = NULL;
+EXPORT char** my__environ = NULL;
+EXPORT char** my___environ = NULL;  // all aliases
+
 EXPORT int32_t my_execv(x64emu_t* emu, const char* path, char* const argv[])
 {
     int self = isProcSelf(path, "exe");
@@ -1692,7 +1696,15 @@ EXPORT int32_t my_execv(x64emu_t* emu, const char* path, char* const argv[])
         memcpy(newargv+1, argv+skip_first, sizeof(char*)*(n+1));
         if(self) newargv[1] = emu->context->fullpath; else newargv[1] = skip_first?argv[skip_first]:path;
         printf_log(LOG_DEBUG, " => execv(\"%s\", %p [\"%s\", \"%s\", \"%s\"...:%d])\n", newargv[0], newargv, newargv[0], n?newargv[1]:"", (n>1)?newargv[2]:"",n);
-        int ret = execv(newargv[0], (char* const*)newargv);
+        char** envv = NULL;
+        if(my_environ!=my_context->envv) envv = my_environ;
+        if(my__environ!=my_context->envv) envv = my__environ;
+        if(my___environ!=my_context->envv) envv = my___environ;
+        int ret;
+        if(envv)
+            ret = execve(newargv[0], (char* const*)newargv, envv);
+        else
+            ret = execv(newargv[0], (char* const*)newargv);
         free(newargv);
         return ret;
     }
@@ -1705,11 +1717,11 @@ EXPORT int32_t my_execve(x64emu_t* emu, const char* path, char* const argv[], ch
     int self = isProcSelf(path, "exe");
     int x64 = FileIsX64ELF(path);
     int x86 = my_context->box86path?FileIsX86ELF(path):0;
+    printf_log(LOG_INFO/*LOG_DEBUG*/, "execve(\"%s\", %p, %p) is x64=%d x86=%d (my_context->envv=%p, environ=%p\n", path, argv, envp, x64, x86, my_context->envv, environ);
     // hack to update the environ var if needed
     if(envp == my_context->envv && environ) {
         envp = environ;
     }
-    printf_log(LOG_DEBUG, "execve(\"%s\", %p, %p) is x64=%d x86=%d\n", path, argv, envp, x64, x86);
     #if 1
     if (x64 || x86 || self) {
         int skip_first = 0;
@@ -1761,7 +1773,15 @@ EXPORT int32_t my_execvp(x64emu_t* emu, const char* path, char* const argv[])
             newargv[j+1] = argv[j];
         if(self) newargv[1] = emu->context->fullpath;
         printf_log(LOG_DEBUG, " => execvp(\"%s\", %p [\"%s\", \"%s\"...:%d])\n", newargv[0], newargv, newargv[1], i?newargv[2]:"", i);
-        int ret = execvp(newargv[0], newargv);
+        char** envv = NULL;
+        if(my_environ!=my_context->envv) envv = my_environ;
+        if(my__environ!=my_context->envv) envv = my__environ;
+        if(my___environ!=my_context->envv) envv = my___environ;
+        int ret;
+        if(envv)
+            ret = execvpe(newargv[0], newargv, envv);
+        else
+            ret = execvp(newargv[0], newargv);
         free(newargv);
         return ret;
     }
@@ -1771,6 +1791,7 @@ EXPORT int32_t my_execvp(x64emu_t* emu, const char* path, char* const argv[])
         // uname -m is redirected to box64 -m
         path = my_context->box64path;
         char *argv2[3] = { my_context->box64path, argv[1], NULL };
+        
         return execvp(path, argv2);
     }
 
@@ -1821,7 +1842,15 @@ EXPORT int32_t my_execlp(x64emu_t* emu, const char* path)
         newargv[j++] = getVargN(emu, k+1);
     if(self) newargv[1] = emu->context->fullpath;
     printf_log(LOG_DEBUG, " => execlp(\"%s\", %p [\"%s\", \"%s\"...:%d])\n", newargv[0], newargv, newargv[1], i?newargv[2]:"", i);
-    int ret = execvp(newargv[0], newargv);
+    char** envv = NULL;
+    if(my_environ!=my_context->envv) envv = my_environ;
+    if(my__environ!=my_context->envv) envv = my__environ;
+    if(my___environ!=my_context->envv) envv = my___environ;
+    int ret;
+    if(envv)
+        ret = execvpe(newargv[0], newargv, envv);
+    else
+        ret = execvp(newargv[0], newargv);
     free(newargv);
     return ret;
 }
@@ -2687,8 +2716,40 @@ EXPORT int my_stime(x64emu_t* emu, const time_t *t)
     return -1;
 }
 
+int GetTID();
+#ifdef ANDROID
+void updateGlibcTidCache() {}
+#else
+struct glibc_pthread {
+#if defined(NO_ALIGN)
+    char header[704];
+#else
+    void* header[24];
+#endif
+  void* list[2];
+  pid_t tid;
+};
+pid_t getGlibcCachedTid() {
+  pthread_mutex_t lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+  pthread_mutex_lock(&lock);
+  pid_t tid = lock.__data.__owner;
+  pthread_mutex_unlock(&lock);
+  pthread_mutex_destroy(&lock);
+  return tid;
+}
+void updateGlibcTidCache() {
+  pid_t real_tid = GetTID();
+  pid_t cached_tid = getGlibcCachedTid();
+  if (cached_tid != real_tid) {
+    pid_t* cached_tid_location =
+        &((struct glibc_pthread*)(pthread_self()))->tid;
+    *cached_tid_location = real_tid;
+  }
+}
+#endif
 typedef struct clone_arg_s {
  uintptr_t stack;
+ x64emu_t *emu;
  uintptr_t fnc;
  void* args;
  int stack_clone_used;
@@ -2697,12 +2758,20 @@ typedef struct clone_arg_s {
 static int clone_fn(void* p)
 {
     clone_arg_t* arg = (clone_arg_t*)p;
-    x64emu_t *emu = thread_get_emu();
+    updateGlibcTidCache();  // update cache tid if needed
+    x64emu_t *emu = arg->emu;
     R_RSP = arg->stack;
-    int ret = RunFunction(my_context, arg->fnc, 1, arg->args);
+    emu->quitonexit = 1;
+    thread_set_emu(emu);
+    int ret = RunFunctionWithEmu(emu, 0, arg->fnc, 1, arg->args);
+    int exited = (emu->quitonexit==2);
+    thread_set_emu(NULL);
+    FreeX64Emu(&emu);
     if(arg->stack_clone_used)
         my_context->stack_clone_used = 0;
     free(arg);
+    /*if(exited)
+        exit(ret);*/
     return ret;
 }
 
@@ -2711,12 +2780,15 @@ EXPORT int my_clone(x64emu_t* emu, void* fn, void* stack, int flags, void* args,
     printf_log(LOG_DEBUG, "my_clone(fn:%p(%s), stack:%p, 0x%x, args:%p, %p, %p, %p)", fn, getAddrFunctionName((uintptr_t)fn), stack, flags, args, parent, tls, child);
     void* mystack = NULL;
     clone_arg_t* arg = (clone_arg_t*)calloc(1, sizeof(clone_arg_t));
+    x64emu_t * newemu = NewX64Emu(emu->context, R_RIP, (uintptr_t)stack, 0, 0);
+    SetupX64Emu(newemu);
+    CloneEmu(newemu, emu);
     if(my_context->stack_clone_used) {
         printf_log(LOG_DEBUG, " no free stack_clone ");
-        mystack = malloc(4*1024*1024);  // stack for own process... memory leak, but no practical way to remove it
+        mystack = malloc(1024*1024);  // stack for own process... memory leak, but no practical way to remove it
     } else {
         if(!my_context->stack_clone)
-            my_context->stack_clone = malloc(4*1024*1024);
+            my_context->stack_clone = malloc(1024*1024);
         mystack = my_context->stack_clone;
         printf_log(LOG_DEBUG, " using stack_clone ");
         my_context->stack_clone_used = 1;
@@ -2726,7 +2798,9 @@ EXPORT int my_clone(x64emu_t* emu, void* fn, void* stack, int flags, void* args,
     arg->args = args;
     arg->fnc = (uintptr_t)fn;
     arg->tls = tls;
-    // x86_64 raw clone is long clone(unsigned long flags, void *stack, int *parent_tid, int *child_tid, unsigned long tls);
+    arg->emu = newemu;
+    if(flags|(CLONE_VM|CLONE_VFORK|CLONE_SETTLS)==flags)   // that's difficult to setup, so lets ignore all those flags :S
+        flags&=~(CLONE_VM|CLONE_VFORK|CLONE_SETTLS);
     int64_t ret = clone(clone_fn, (void*)((uintptr_t)mystack+1024*1024), flags, arg, parent, NULL, child);
     return (uintptr_t)ret;
 }
@@ -2754,10 +2828,19 @@ EXPORT size_t my_strlcat(x64emu_t* emu, void* dst, void* src, size_t l)
     return s+strlen(src);
 }
 
+EXPORT void my_exit(x64emu_t* emu, int code)
+{
+    if(emu->quitonexit) {
+        emu->quit = 1;
+        R_EAX = code;
+        emu->quitonexit = 2;
+        return;
+    }
+    exit(code);
+}
+
+EXPORT void my__exit(x64emu_t* emu, int code) __attribute__((alias("my_exit")));
 
-EXPORT char** my_environ = NULL;
-EXPORT char** my__environ = NULL;
-EXPORT char** my___environ = NULL;  // all aliases
 
 EXPORT char* my___progname = NULL;
 EXPORT char* my___progname_full = NULL;
diff --git a/src/wrapped/wrappedlibc_private.h b/src/wrapped/wrappedlibc_private.h
index 281d1c8c..52c82f78 100755
--- a/src/wrapped/wrappedlibc_private.h
+++ b/src/wrapped/wrappedlibc_private.h
@@ -299,8 +299,8 @@ GOM(execv, iFEpp)
 GOWM(execve, iFEppp)
 GOM(execvp, iFEpp)
 GOW(execvpe, iFppp)
-GO(_exit, vFi)
-GO(exit, vFi)
+GOM(_exit, vFEi)
+GOM(exit, vFEi)
 GOW(_Exit, vFi)
 GO(explicit_bzero, vFpL)
 //GO(__explicit_bzero_chk, 
@@ -2087,7 +2087,7 @@ GOW(wait3, iFpip)
 GOW(wait4, iFipip)
 GOW(waitid, iFuupi)
 GO(__waitpid, lFlpi)
-GOW(waitpid, iFipi)
+GOW(waitpid, lFlpi)
 GOM(warn, vFEpV)
 GOM(warnx, vFEpV)
 GOW(wcpcpy, pFpp)
diff --git a/src/wrapped/wrappednss3.c b/src/wrapped/wrappednss3.c
index 76a0acdc..75ae1cc3 100755
--- a/src/wrapped/wrappednss3.c
+++ b/src/wrapped/wrappednss3.c
@@ -55,6 +55,39 @@ static void* find_PK11PasswordFunc_Fct(void* fct)
     return NULL;
 }
 
+// CERT_StringFromCertFcn ...
+#define GO(A)   \
+static uintptr_t my_CERT_StringFromCertFcn_fct_##A = 0;                             \
+static void* my_CERT_StringFromCertFcn_##A(void* a)                                 \
+{                                                                                   \
+    return (void*)RunFunction(my_context, my_CERT_StringFromCertFcn_fct_##A, 1, a); \
+}
+SUPER()
+#undef GO
+static void* find_CERT_StringFromCertFcn_Fct(void* fct)
+{
+    if(!fct) return fct;
+    if(GetNativeFnc((uintptr_t)fct))  return GetNativeFnc((uintptr_t)fct);
+    #define GO(A) if(my_CERT_StringFromCertFcn_fct_##A == (uintptr_t)fct) return my_CERT_StringFromCertFcn_##A;
+    SUPER()
+    #undef GO
+    #define GO(A) if(my_CERT_StringFromCertFcn_fct_##A == 0) {my_CERT_StringFromCertFcn_fct_##A = (uintptr_t)fct; return my_CERT_StringFromCertFcn_##A; }
+    SUPER()
+    #undef GO
+    printf_log(LOG_NONE, "Warning, no more slot for nss3 CERT_StringFromCertFcn callback\n");
+    return NULL;
+}
+static void* reverse_CERT_StringFromCertFcn_Fct(library_t* lib, void* fct)
+{
+    if(!fct) return fct;
+    if(CheckBridged(lib->priv.w.bridge, fct))
+        return (void*)CheckBridged(lib->priv.w.bridge, fct);
+    #define GO(A) if(my_CERT_StringFromCertFcn_##A == fct) return (void*)my_CERT_StringFromCertFcn_fct_##A;
+    SUPER()
+    #undef GO
+    return (void*)AddBridge(lib->priv.w.bridge, pFp, fct, 0, NULL);
+}
+
 #undef SUPER
 
 EXPORT void my_PK11_SetPasswordFunc(x64emu_t* emu, void* f)
@@ -62,6 +95,14 @@ EXPORT void my_PK11_SetPasswordFunc(x64emu_t* emu, void* f)
     my->PK11_SetPasswordFunc(find_PK11PasswordFunc_Fct(f));
 }
 
+EXPORT int my_CERT_RegisterAlternateOCSPAIAInfoCallBack(x64emu_t* emu, void* f, void** old)
+{
+    int ret = my->CERT_RegisterAlternateOCSPAIAInfoCallBack(find_CERT_StringFromCertFcn_Fct(f), old);
+    if(old)
+        *old = reverse_CERT_StringFromCertFcn_Fct(my_lib, *old);
+    return ret;
+}
+
 #define CUSTOM_INIT \
     getMy(lib);
 
diff --git a/src/wrapped/wrappednss3_private.h b/src/wrapped/wrappednss3_private.h
index bd17fed8..e213bdfd 100755
--- a/src/wrapped/wrappednss3_private.h
+++ b/src/wrapped/wrappednss3_private.h
@@ -31,7 +31,7 @@ DATA(CERT_CertificateTemplate, 480)
 //GO(CERT_CertTimesValid, 
 //GO(CERT_ChangeCertTrust, 
 //GO(CERT_CheckCertUsage, 
-//GO(CERT_CheckCertValidTimes, 
+GO(CERT_CheckCertValidTimes, iFpIi)
 //GO(CERT_CheckNameSpace, 
 //GO(CERT_CheckOCSPStatus, 
 //GO(CERT_ClearOCSPCache, 
@@ -59,10 +59,10 @@ DATA(CERT_CertificateTemplate, 480)
 //GO(CERT_CreateValidity, 
 //GO(CERT_CRLCacheRefreshIssuer, 
 //DATA(CERT_CrlTemplate, 
-//GO(CERT_DecodeAltNameExtension, 
+GO(CERT_DecodeAltNameExtension, pFpp)
 //GO(CERT_DecodeAuthInfoAccessExtension, 
 //GO(CERT_DecodeAuthKeyID, 
-//GO(CERT_DecodeAVAValue, 
+GO(CERT_DecodeAVAValue, pFp)
 //GO(CERT_DecodeBasicConstraintValue, 
 //GO(CERT_DecodeCertificatePoliciesExtension, 
 //GO(CERT_DecodeCRLDistributionPoints, 
@@ -79,10 +79,10 @@ DATA(CERT_CertificateTemplate, 480)
 //GO(CERT_DecodeUserNotice, 
 //GO(CERT_DerNameToAscii, 
 //GO(CERT_DestroyCertArray, 
-//GO(CERT_DestroyCertificate, 
-//GO(CERT_DestroyCertificateList, 
+GO(CERT_DestroyCertificate, vFp)
+GO(CERT_DestroyCertificateList, vFp)
 //GO(CERT_DestroyCertificatePoliciesExtension, 
-//GO(CERT_DestroyCertificateRequest, 
+GO(CERT_DestroyCertificateRequest, vFp)
 //GO(CERT_DestroyCertList, 
 //GO(CERT_DestroyCERTRevocationFlags, 
 //GO(CERT_DestroyName, 
@@ -95,7 +95,7 @@ DATA(CERT_CertificateTemplate, 480)
 //GO(CERT_DisableOCSPChecking, 
 //GO(CERT_DisableOCSPDefaultResponder, 
 //GO(CERT_DistNamesFromCertList, 
-//GO(CERT_DupCertificate, 
+GO(CERT_DupCertificate, pFp)
 //GO(CERT_DupCertList, 
 //GO(CERT_DupDistNames, 
 //GO(CERT_EnableOCSPChecking, 
@@ -116,7 +116,7 @@ DATA(CERT_CertificateTemplate, 480)
 //GO(CERT_EncodePolicyMappingExtension, 
 //GO(CERT_EncodeSubjectKeyID, 
 //GO(CERT_EncodeUserNotice, 
-//GO(CERT_ExtractPublicKey, 
+GO(CERT_ExtractPublicKey, pFp)
 //GO(CERT_FilterCertListByCANames, 
 //GO(CERT_FilterCertListByUsage, 
 //GO(CERT_FilterCertListForUserCerts, 
@@ -130,7 +130,7 @@ DATA(CERT_CertificateTemplate, 480)
 //GO(CERT_FindCertByNicknameOrEmailAddrForUsage, 
 //GO(CERT_FindCertByNicknameOrEmailAddrForUsageCX, 
 //GO(CERT_FindCertBySubjectKeyID, 
-//GO(CERT_FindCertExtension, 
+GO(CERT_FindCertExtension, iFppp)
 //GO(CERT_FindCertIssuer, 
 //GO(CERT_FindCRLEntryReasonExten, 
 //GO(CERT_FindCRLNumberExten, 
@@ -147,7 +147,7 @@ DATA(CERT_CertificateTemplate, 480)
 //GO(CERT_FreeDistNames, 
 //GO(CERT_FreeNicknames, 
 //GO(CERT_GenTime2FormattedAscii, 
-//GO(CERT_GetAVATag, 
+GO(CERT_GetAVATag, iFp)
 //GO(CERT_GetCertChainFromCert, 
 GO(CERT_GetCertEmailAddress, pFp)
 //GO(CERT_GetCertificateDer, 
@@ -168,7 +168,7 @@ GO(CERT_GetCommonName, pFp)
 //GO(CERT_GetConstrainedCertificateNames, 
 GO(CERT_GetCountryName, pFp)
 //GO(CERT_GetDBContentVersion, 
-//GO(CERT_GetDefaultCertDB, 
+GO(CERT_GetDefaultCertDB, pFv)
 GO(CERT_GetDomainComponentName, pFp)
 //GO(CERT_GetEncodedOCSPResponse, 
 //GO(CERT_GetFirstEmailAddress, 
@@ -176,7 +176,7 @@ GO(CERT_GetDomainComponentName, pFp)
 //GO(CERT_GetImposedNameConstraints, 
 GO(CERT_GetLocalityName, pFp)
 //GO(CERT_GetNextEmailAddress, 
-//GO(CERT_GetNextGeneralName, 
+GO(CERT_GetNextGeneralName, pFp)
 //GO(CERT_GetNextNameConstraint, 
 //GO(CERT_GetOCSPAuthorityInfoAccessLocation, 
 //GO(CERT_GetOCSPResponseStatus, 
@@ -212,13 +212,13 @@ DATA(CERT_NameTemplate, 4*sizeof(void*))
 //GO(CERT_NameToAsciiInvertible, 
 //GO(CERT_NewCertList, 
 //GO(__CERT_NewTempCertificate, 
-//GO(CERT_NewTempCertificate, 
+GO(CERT_NewTempCertificate, pFpppii)
 //GO(CERT_NicknameStringsFromCertList, 
 //GO(CERT_OCSPCacheSettings, 
 //GO(CERT_OpenCertDBFilename, 
-//GO(CERT_PKIXVerifyCert, 
+GO(CERT_PKIXVerifyCert, iFpIppp)
 //GO(CERT_PostOCSPRequest, 
-//GO(CERT_RegisterAlternateOCSPAIAInfoCallBack, 
+GOM(CERT_RegisterAlternateOCSPAIAInfoCallBack, iFEpp)
 //GO(CERT_RemoveCertListNode, 
 //GO(CERT_RFC1485_EscapeAndQuote, 
 //GO(CERT_SaveSMimeProfile, 
@@ -251,7 +251,7 @@ DATA(CERT_SignedDataTemplate, 160)
 //GO(CERT_VerifySignedDataWithPublicKey, 
 //GO(CERT_VerifySignedDataWithPublicKeyInfo, 
 //GO(DER_AsciiToTime, 
-//GO(DER_DecodeTimeChoice, 
+GO(DER_DecodeTimeChoice, iFpp)
 //GO(DER_Encode, 
 //GO(DER_EncodeTimeChoice, 
 //GO(DER_GeneralizedDayToAscii, 
@@ -648,10 +648,10 @@ GO(PK11_WriteRawAttribute, iFipLp)
 //GO(PORT_ArenaStrdup, 
 //GO(PORT_ArenaUnmark, 
 //GO(PORT_ArenaZAlloc, 
-//GO(PORT_Free, 
-//GO(PORT_FreeArena, 
-//GO(PORT_GetError, 
-//GO(PORT_NewArena, 
+GO(PORT_Free, vFp)
+GO(PORT_FreeArena, vFpi)
+GO(PORT_GetError, iFv)
+GO(PORT_NewArena, pFL)
 //GO(PORT_Realloc, 
 //GO(PORT_SetError, 
 //GO(PORT_SetUCS2_ASCIIConversionFunction, 
@@ -715,7 +715,7 @@ DATA(SEC_IA5StringTemplate, 4*sizeof(void*)) //R type
 //GO(SECITEM_CompareItem, 
 //GO(SECITEM_CopyItem, 
 //GO(SECITEM_DupItem, 
-//GO(SECITEM_FreeItem, 
+GO(SECITEM_FreeItem, iFpi)
 //GO(SECITEM_ItemsAreEqual, 
 //GO(SECITEM_ZfreeItem, 
 //GO(SECKEY_AddPrivateKeyToListTail, 
@@ -806,7 +806,7 @@ GO(SECMOD_ReleaseReadLock, vFp)
 //DATA(SEC_NullTemplate,    //R type
 //DATA(SEC_ObjectIDTemplate,    //R type
 DATA(SEC_OctetStringTemplate, 4*sizeof(void*))   //R type
-//GO(SECOID_AddEntry, 
+GO(SECOID_AddEntry, iFp)
 DATA(SECOID_AlgorithmIDTemplate, 16*sizeof(void*))   //R type
 //GO(SECOID_CompareAlgorithmID, 
 //GO(SECOID_CopyAlgorithmID,