about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-03-03 17:06:00 +0100
committerptitSeb <sebastien.chev@gmail.com>2021-03-03 17:06:00 +0100
commit9aabe9c97fecb77f70361e0e0df8380f1489fc81 (patch)
tree298c3b0f79079020b12dd2ed1a9a26ea136b2e81 /src
parent745a68f556537aaaaa8ee25a76b5757d3d3f7494 (diff)
downloadbox64-9aabe9c97fecb77f70361e0e0df8380f1489fc81.tar.gz
box64-9aabe9c97fecb77f70361e0e0df8380f1489fc81.zip
Added rt and pthread wrapped lib
Diffstat (limited to 'src')
-rwxr-xr-xsrc/library_list.h4
-rwxr-xr-xsrc/main.c6
-rw-r--r--src/wrapped/generated/functions_list.txt9
-rw-r--r--src/wrapped/generated/wrapper.c18
-rw-r--r--src/wrapped/generated/wrapper.h9
-rwxr-xr-xsrc/wrapped/wrappedlibpthread.c85
-rwxr-xr-xsrc/wrapped/wrappedlibpthread_private.h179
-rwxr-xr-xsrc/wrapped/wrappedlibrt.c75
-rwxr-xr-xsrc/wrapped/wrappedlibrt_private.h48
9 files changed, 431 insertions, 2 deletions
diff --git a/src/library_list.h b/src/library_list.h
index 7d24d334..3f1e5663 100755
--- a/src/library_list.h
+++ b/src/library_list.h
@@ -3,8 +3,8 @@
 #endif
 
 GO("libc.so.6", libc)
-//GO("libpthread.so.0", libpthread)
-//GO("librt.so.1", librt)
+GO("libpthread.so.0", libpthread)
+GO("librt.so.1", librt)
 //GO("libGL.so.1", libgl)
 //GO("libGL.so", libgl)
 //GO("libGLU.so.1", libglu)
diff --git a/src/main.c b/src/main.c
index 17b94f9b..b67b9789 100755
--- a/src/main.c
+++ b/src/main.c
@@ -858,6 +858,12 @@ int main(int argc, const char **argv, const char **env) {
         }
     }
     FreeCollection(&ld_preload);
+    // Call librarian to load all dependant elf
+    if(LoadNeededLibs(elf_header, my_context->maplib, &my_context->neededlibs, 0, my_context, emu)) {
+        printf_log(LOG_NONE, "Error: loading needed libs in elf %s\n", my_context->argv[0]);
+        FreeBox64Context(&my_context);
+        return -1;
+    }
 
     return 0;
 }
diff --git a/src/wrapped/generated/functions_list.txt b/src/wrapped/generated/functions_list.txt
index 147507f1..357ab0bd 100644
--- a/src/wrapped/generated/functions_list.txt
+++ b/src/wrapped/generated/functions_list.txt
@@ -1,14 +1,23 @@
 #() vFE
 #() vFv
+#() iFu
+#() iFp
+#() lFp
 #() pFE
 #() pFp
 #() vFpp
 #() iFEp
+#() iFip
+#() iFup
 #() pFEp
 #() iFEpp
+#() iFpiu
 #() pFEpi
 #() pFEpp
+#() iFEupp
 #() iFEpip
+#() iFEppp
+#() iFuipp
 #() pFEppi
 #() pFEppp
 #() iFipppi
diff --git a/src/wrapped/generated/wrapper.c b/src/wrapped/generated/wrapper.c
index 6598ae7e..1b34a0d7 100644
--- a/src/wrapped/generated/wrapper.c
+++ b/src/wrapped/generated/wrapper.c
@@ -71,30 +71,48 @@ void VulkanTox86(void* src, void* save);
 int of_convert(int);
 typedef void (*vFE_t)(x64emu_t*);
 typedef void (*vFv_t)(void);
+typedef int32_t (*iFu_t)(uint32_t);
+typedef int32_t (*iFp_t)(void*);
+typedef intptr_t (*lFp_t)(void*);
 typedef void* (*pFE_t)(x64emu_t*);
 typedef void* (*pFp_t)(void*);
 typedef void (*vFpp_t)(void*, void*);
 typedef int32_t (*iFEp_t)(x64emu_t*, void*);
+typedef int32_t (*iFip_t)(int32_t, void*);
+typedef int32_t (*iFup_t)(uint32_t, void*);
 typedef void* (*pFEp_t)(x64emu_t*, void*);
 typedef int32_t (*iFEpp_t)(x64emu_t*, void*, void*);
+typedef int32_t (*iFpiu_t)(void*, int32_t, uint32_t);
 typedef void* (*pFEpi_t)(x64emu_t*, void*, int32_t);
 typedef void* (*pFEpp_t)(x64emu_t*, void*, void*);
+typedef int32_t (*iFEupp_t)(x64emu_t*, uint32_t, void*, void*);
 typedef int32_t (*iFEpip_t)(x64emu_t*, void*, int32_t, void*);
+typedef int32_t (*iFEppp_t)(x64emu_t*, void*, void*, void*);
+typedef int32_t (*iFuipp_t)(uint32_t, int32_t, void*, void*);
 typedef void* (*pFEppi_t)(x64emu_t*, void*, void*, int32_t);
 typedef void* (*pFEppp_t)(x64emu_t*, void*, void*, void*);
 typedef int32_t (*iFipppi_t)(int32_t, void*, void*, void*, int32_t);
 
 void vFE(x64emu_t *emu, uintptr_t fcn) { vFE_t fn = (vFE_t)fcn; fn(emu); }
 void vFv(x64emu_t *emu, uintptr_t fcn) { vFv_t fn = (vFv_t)fcn; fn(); }
+void iFu(x64emu_t *emu, uintptr_t fcn) { iFu_t fn = (iFu_t)fcn; R_RAX=fn(*(uint32_t*)(R_RSP + 4)); }
+void iFp(x64emu_t *emu, uintptr_t fcn) { iFp_t fn = (iFp_t)fcn; R_RAX=fn(*(void**)(R_RSP + 4)); }
+void lFp(x64emu_t *emu, uintptr_t fcn) { lFp_t fn = (lFp_t)fcn; R_RAX=(intptr_t)fn(*(void**)(R_RSP + 4)); }
 void pFE(x64emu_t *emu, uintptr_t fcn) { pFE_t fn = (pFE_t)fcn; R_RAX=(uintptr_t)fn(emu); }
 void pFp(x64emu_t *emu, uintptr_t fcn) { pFp_t fn = (pFp_t)fcn; R_RAX=(uintptr_t)fn(*(void**)(R_RSP + 4)); }
 void vFpp(x64emu_t *emu, uintptr_t fcn) { vFpp_t fn = (vFpp_t)fcn; fn(*(void**)(R_RSP + 4), *(void**)(R_RSP + 12)); }
 void iFEp(x64emu_t *emu, uintptr_t fcn) { iFEp_t fn = (iFEp_t)fcn; R_RAX=fn(emu, *(void**)(R_RSP + 4)); }
+void iFip(x64emu_t *emu, uintptr_t fcn) { iFip_t fn = (iFip_t)fcn; R_RAX=fn(*(int32_t*)(R_RSP + 4), *(void**)(R_RSP + 8)); }
+void iFup(x64emu_t *emu, uintptr_t fcn) { iFup_t fn = (iFup_t)fcn; R_RAX=fn(*(uint32_t*)(R_RSP + 4), *(void**)(R_RSP + 8)); }
 void pFEp(x64emu_t *emu, uintptr_t fcn) { pFEp_t fn = (pFEp_t)fcn; R_RAX=(uintptr_t)fn(emu, *(void**)(R_RSP + 4)); }
 void iFEpp(x64emu_t *emu, uintptr_t fcn) { iFEpp_t fn = (iFEpp_t)fcn; R_RAX=fn(emu, *(void**)(R_RSP + 4), *(void**)(R_RSP + 12)); }
+void iFpiu(x64emu_t *emu, uintptr_t fcn) { iFpiu_t fn = (iFpiu_t)fcn; R_RAX=fn(*(void**)(R_RSP + 4), *(int32_t*)(R_RSP + 12), *(uint32_t*)(R_RSP + 16)); }
 void pFEpi(x64emu_t *emu, uintptr_t fcn) { pFEpi_t fn = (pFEpi_t)fcn; R_RAX=(uintptr_t)fn(emu, *(void**)(R_RSP + 4), *(int32_t*)(R_RSP + 12)); }
 void pFEpp(x64emu_t *emu, uintptr_t fcn) { pFEpp_t fn = (pFEpp_t)fcn; R_RAX=(uintptr_t)fn(emu, *(void**)(R_RSP + 4), *(void**)(R_RSP + 12)); }
+void iFEupp(x64emu_t *emu, uintptr_t fcn) { iFEupp_t fn = (iFEupp_t)fcn; R_RAX=fn(emu, *(uint32_t*)(R_RSP + 4), *(void**)(R_RSP + 8), *(void**)(R_RSP + 16)); }
 void iFEpip(x64emu_t *emu, uintptr_t fcn) { iFEpip_t fn = (iFEpip_t)fcn; R_RAX=fn(emu, *(void**)(R_RSP + 4), *(int32_t*)(R_RSP + 12), *(void**)(R_RSP + 16)); }
+void iFEppp(x64emu_t *emu, uintptr_t fcn) { iFEppp_t fn = (iFEppp_t)fcn; R_RAX=fn(emu, *(void**)(R_RSP + 4), *(void**)(R_RSP + 12), *(void**)(R_RSP + 20)); }
+void iFuipp(x64emu_t *emu, uintptr_t fcn) { iFuipp_t fn = (iFuipp_t)fcn; R_RAX=fn(*(uint32_t*)(R_RSP + 4), *(int32_t*)(R_RSP + 8), *(void**)(R_RSP + 12), *(void**)(R_RSP + 20)); }
 void pFEppi(x64emu_t *emu, uintptr_t fcn) { pFEppi_t fn = (pFEppi_t)fcn; R_RAX=(uintptr_t)fn(emu, *(void**)(R_RSP + 4), *(void**)(R_RSP + 12), *(int32_t*)(R_RSP + 20)); }
 void pFEppp(x64emu_t *emu, uintptr_t fcn) { pFEppp_t fn = (pFEppp_t)fcn; R_RAX=(uintptr_t)fn(emu, *(void**)(R_RSP + 4), *(void**)(R_RSP + 12), *(void**)(R_RSP + 20)); }
 void iFipppi(x64emu_t *emu, uintptr_t fcn) { iFipppi_t fn = (iFipppi_t)fcn; R_RAX=fn(*(int32_t*)(R_RSP + 4), *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(int32_t*)(R_RSP + 32)); }
diff --git a/src/wrapped/generated/wrapper.h b/src/wrapped/generated/wrapper.h
index 19ccf6b3..4700b365 100644
--- a/src/wrapped/generated/wrapper.h
+++ b/src/wrapped/generated/wrapper.h
@@ -32,15 +32,24 @@ typedef void (*wrapper_t)(x64emu_t* emu, uintptr_t fnc);
 
 void vFE(x64emu_t *emu, uintptr_t fnc);
 void vFv(x64emu_t *emu, uintptr_t fnc);
+void iFu(x64emu_t *emu, uintptr_t fnc);
+void iFp(x64emu_t *emu, uintptr_t fnc);
+void lFp(x64emu_t *emu, uintptr_t fnc);
 void pFE(x64emu_t *emu, uintptr_t fnc);
 void pFp(x64emu_t *emu, uintptr_t fnc);
 void vFpp(x64emu_t *emu, uintptr_t fnc);
 void iFEp(x64emu_t *emu, uintptr_t fnc);
+void iFip(x64emu_t *emu, uintptr_t fnc);
+void iFup(x64emu_t *emu, uintptr_t fnc);
 void pFEp(x64emu_t *emu, uintptr_t fnc);
 void iFEpp(x64emu_t *emu, uintptr_t fnc);
+void iFpiu(x64emu_t *emu, uintptr_t fnc);
 void pFEpi(x64emu_t *emu, uintptr_t fnc);
 void pFEpp(x64emu_t *emu, uintptr_t fnc);
+void iFEupp(x64emu_t *emu, uintptr_t fnc);
 void iFEpip(x64emu_t *emu, uintptr_t fnc);
+void iFEppp(x64emu_t *emu, uintptr_t fnc);
+void iFuipp(x64emu_t *emu, uintptr_t fnc);
 void pFEppi(x64emu_t *emu, uintptr_t fnc);
 void pFEppp(x64emu_t *emu, uintptr_t fnc);
 void iFipppi(x64emu_t *emu, uintptr_t fnc);
diff --git a/src/wrapped/wrappedlibpthread.c b/src/wrapped/wrappedlibpthread.c
new file mode 100755
index 00000000..d9b81d5b
--- /dev/null
+++ b/src/wrapped/wrappedlibpthread.c
@@ -0,0 +1,85 @@
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include "wrappedlibs.h"
+
+#include "debug.h"
+#include "wrapper.h"
+#include "bridge.h"
+#include "librarian/library_private.h"
+#include "x64emu.h"
+#include "emu/x64emu_private.h"
+#include "box64context.h"
+#include "librarian.h"
+
+const char* libpthreadName = "libpthread.so.0";
+#define LIBNAME libpthread
+
+
+//int my_pthread_create(x64emu_t *emu, void* t, void* attr, void* start_routine, void* arg); //implemented in thread.c
+//int my_pthread_key_create(x64emu_t* emu, void* key, void* dtor);
+//int my___pthread_key_create(x64emu_t* emu, void* key, void* dtor);
+//int my_pthread_once(x64emu_t* emu, void* once, void* cb);
+//int my___pthread_once(x64emu_t* emu, void* once, void* cb);
+//int my_pthread_cond_broadcast(x64emu_t* emu, void* cond);
+//int my_pthread_cond_destroy(x64emu_t* emu, void* cond);
+//int my_pthread_cond_init(x64emu_t* emu, void* cond, void* attr);
+//int my_pthread_cond_signal(x64emu_t* emu, void* cond);
+//int my_pthread_cond_timedwait(x64emu_t* emu, void* cond, void* mutex, void* abstime);
+//int my_pthread_cond_wait(x64emu_t* emu, void* cond, void* mutex);
+//int my_pthread_mutexattr_setkind_np(x64emu_t* emu, void* t, int kind);
+//int my_pthread_attr_setscope(x64emu_t* emu, void* attr, int scope);
+//void my__pthread_cleanup_push_defer(x64emu_t* emu, void* buffer, void* routine, void* arg);
+//void my__pthread_cleanup_push(x64emu_t* emu, void* buffer, void* routine, void* arg);
+//void my__pthread_cleanup_pop(x64emu_t* emu, void* buffer, int exec);
+//void my__pthread_cleanup_pop_restore(x64emu_t* emu, void* buffer, int exec);
+//int my_pthread_kill(x64emu_t* emu, void* thread, int sig);
+//int my_pthread_getaffinity_np(x64emu_t* emu, pthread_t thread, int cpusetsize, void* cpuset);
+//int my_pthread_setaffinity_np(x64emu_t* emu, pthread_t thread, int cpusetsize, void* cpuset);
+//int my_pthread_attr_setaffinity_np(x64emu_t* emu, void* attr, uint32_t cpusetsize, void* cpuset);
+
+
+//EXPORT int my_pthread_attr_setschedparam(x64emu_t* emu, void* attr, void* param)
+//{
+//    int policy;
+//    pthread_attr_getschedpolicy(attr, &policy);
+//    int pmin = sched_get_priority_min(policy);
+//    int pmax = sched_get_priority_max(policy);
+//    if(param) {
+//        int p = *(int*)param;
+//        if(p>=pmin && p<=pmax)
+//            return pthread_attr_setschedparam(attr, param);
+//    }
+//    printf_log(LOG_INFO, "Warning, call to pthread_attr_setschedparam(%p, %p[%d]) ignored\n", attr, param, param?(*(int*)param):-1);
+//    return 0;   // faking success
+//}
+
+EXPORT int32_t my_pthread_atfork(x64emu_t *emu, void* prepare, void* parent, void* child)
+{
+    // this is partly incorrect, because the emulated functions should be executed by actual fork and not by my_atfork...
+    if(my_context->atfork_sz==my_context->atfork_cap) {
+        my_context->atfork_cap += 4;
+        my_context->atforks = (atfork_fnc_t*)realloc(my_context->atforks, my_context->atfork_cap*sizeof(atfork_fnc_t));
+    }
+    int i = my_context->atfork_sz++;
+    my_context->atforks[i].prepare = (uintptr_t)prepare;
+    my_context->atforks[i].parent = (uintptr_t)parent;
+    my_context->atforks[i].child = (uintptr_t)child;
+    my_context->atforks[i].handle = NULL;
+    
+    return 0;
+}
+EXPORT int32_t my___pthread_atfork(x64emu_t *emu, void* prepare, void* parent, void* child) __attribute__((alias("my_pthread_atfork")));
+
+EXPORT void my___pthread_initialize()
+{
+    // nothing, the lib initialize itself now
+}
+
+#include "wrappedlib_init.h"
+
diff --git a/src/wrapped/wrappedlibpthread_private.h b/src/wrapped/wrappedlibpthread_private.h
new file mode 100755
index 00000000..e6f0f7f3
--- /dev/null
+++ b/src/wrapped/wrappedlibpthread_private.h
@@ -0,0 +1,179 @@
+#if !(defined(GO) && defined(GOM) && defined(GO2) && defined(DATA))
+#error meh!
+#endif
+// General note: pthread_t is unsigned long int
+// cpu_set_t is a struct with an array, default size is fixed for all architecture
+
+// __errno_location
+// fork
+// __fork
+// __h_errno_location
+// _IO_flockfile
+// _IO_ftrylockfile
+// _IO_funlockfile
+// __libc_allocate_rtsig
+// __libc_current_sigrtmax
+// __libc_current_sigrtmin
+GOM(pthread_atfork, iFEppp)
+GOM(__pthread_atfork, iFEppp)
+GOM(pthread_attr_destroy, iFEp)
+// pthread_attr_getaffinity_np
+//GO(pthread_attr_getdetachstate, iFpp)
+//GO(pthread_attr_getguardsize, iFpp)
+//GO(pthread_attr_getinheritsched, iFpp)
+//GO(pthread_attr_getschedparam, iFpp)
+//GO(pthread_attr_getschedpolicy, iFpp)
+//GO(pthread_attr_getscope, iFpp)
+//GOM(pthread_attr_getstack, iFEppp)
+//GO(pthread_attr_getstackaddr, iFpp)
+//GO(pthread_attr_getstacksize, iFpp)
+//GO(pthread_attr_init, iFp)
+//GOM(pthread_attr_setaffinity_np, iFEpup)
+//GO(pthread_attr_setdetachstate, iFpi)
+//GO(pthread_attr_setguardsize, iFpL)
+//GO(pthread_attr_setinheritsched, iFpi)
+//GO(pthread_attr_setschedparam, iFpp)
+//GO(pthread_attr_setschedpolicy, iFpi)
+//GO(pthread_attr_setscope, iFpi)
+//GOM(pthread_attr_setstack, iFEppL)
+//GO(pthread_attr_setstackaddr, iFpp)
+//GO(pthread_attr_setstacksize, iFpL)
+//GO(pthread_barrierattr_destroy, iFp)
+//GO(pthread_barrierattr_getpshared, iFpp)
+//GO(pthread_barrierattr_init, iFp)
+//GO(pthread_barrierattr_setpshared, iFpi)
+//GO(pthread_barrier_destroy, iFp)
+//GO(pthread_barrier_init, iFppu)
+//GO(pthread_barrier_wait, iFp)
+//GO(pthread_cancel, iFi)
+//GOM(_pthread_cleanup_pop, vFEpi)
+//GOM(_pthread_cleanup_pop_restore, vFEpi)
+//GOM(_pthread_cleanup_push, vFEppp)
+//GOM(_pthread_cleanup_push_defer, vFEppp)
+// __pthread_cleanup_routine
+//GO(pthread_condattr_destroy, iFp)
+//GO(pthread_condattr_getclock, iFpp)
+//GO(pthread_condattr_getpshared, iFpp)
+//GO(pthread_condattr_init, iFp)
+//GO(pthread_condattr_setclock, iFpp)
+//GO(pthread_condattr_setpshared, iFpi)
+//GOM(pthread_cond_broadcast, iFEp)
+//GOM(pthread_cond_destroy, iFEp)
+//GOM(pthread_cond_init, iFEpp)
+//GOM(pthread_cond_signal, iFEp)
+//GOM(pthread_cond_timedwait, iFEppp)
+//GOM(pthread_cond_wait, iFEpp)
+//GOM(pthread_create, iFEpppp)
+//GO(pthread_detach, iFu)
+//GO(pthread_equal, iFuu)
+//GOM(pthread_exit, vFEp)
+//GOM(pthread_getaffinity_np, iFEpup)
+//GO(pthread_getattr_np, iFup)
+//GO(pthread_getconcurrency, iFv)
+//GO(pthread_getcpuclockid, iFup)
+//GO(pthread_getschedparam, iFupp)
+//GO(__pthread_getspecific, pFu)
+//GO(pthread_getspecific, pFu)
+//GOM(pthread_getname_np, iFEppu)  //not present on Pandora
+//GOM(__pthread_initialize, vFv)  // doesn't exist anymore...
+// __pthread_initialize_minimal
+//GO(pthread_join, iFup)
+//GOM(__pthread_key_create, iFEpp)
+//GOM(pthread_key_create, iFEpp)
+//GO(pthread_key_delete, iFu)
+//GO(pthread_kill, iFEpi)
+// pthread_kill_other_threads_np
+//GO(__pthread_mutexattr_destroy, iFp)
+//GO(pthread_mutexattr_destroy, iFp)
+// pthread_mutexattr_getprioceiling
+// pthread_mutexattr_getprotocol
+// pthread_mutexattr_getpshared
+// pthread_mutexattr_getrobust_np
+//GO(pthread_mutexattr_gettype, iFpp)
+//GO(__pthread_mutexattr_init, iFp)
+//GO(pthread_mutexattr_init, iFp)
+// pthread_mutexattr_setprioceiling
+//GO(pthread_mutexattr_setprotocol, iFpp)
+//GO(pthread_mutexattr_setpshared, iFpi)
+// pthread_mutexattr_setrobust_np
+//GO(__pthread_mutexattr_settype, iFpi)
+//GO(pthread_mutexattr_settype, iFpi)
+// pthread_mutex_consistent_np
+//GO(__pthread_mutex_destroy, iFp)
+//GO(pthread_mutex_destroy, iFp)
+// pthread_mutex_getprioceiling
+//GO(__pthread_mutex_init, iFpp)
+//GO(pthread_mutex_init, iFpp)
+//GO(__pthread_mutex_lock, iFp)
+//GO(pthread_mutex_lock, iFp)
+// pthread_mutex_setprioceiling
+//GO(pthread_mutex_timedlock, iFpp)
+//GO(__pthread_mutex_trylock, iFp)
+//GO(pthread_mutex_trylock, iFp)
+//GO(__pthread_mutex_unlock, iFp)
+//GO(pthread_mutex_unlock, iFp)
+//GOM(pthread_once, iFEpp)
+//GOM(__pthread_once, iFEpp)
+//GOM(__pthread_register_cancel, vFEp)
+// __pthread_register_cancel_defer
+//GO(pthread_rwlockattr_destroy, vFp)
+//GO(pthread_rwlockattr_getkind_np, iFpp)
+// pthread_rwlockattr_getpshared
+//GO(pthread_rwlockattr_init, iFp)
+//GO(pthread_rwlockattr_setkind_np, iFpi)
+// pthread_rwlockattr_setpshared
+// __pthread_rwlock_destroy
+//GO(pthread_rwlock_destroy, iFp)
+//GO(__pthread_rwlock_init, iFpp)
+//GO(pthread_rwlock_init, iFpp)
+//GO(__pthread_rwlock_rdlock, iFp)
+//GO2(pthread_rwlock_rdlock, iFp, __pthread_rwlock_rdlock)    // not always defined
+// pthread_rwlock_timedrdlock
+// pthread_rwlock_timedwrlock
+// __pthread_rwlock_tryrdlock
+//GO(pthread_rwlock_tryrdlock, iFp)
+// __pthread_rwlock_trywrlock
+//GO(pthread_rwlock_trywrlock, iFp)
+//GO(__pthread_rwlock_unlock, iFp)
+//GO2(pthread_rwlock_unlock, iFp, __pthread_rwlock_unlock)   // not always defined
+//GO(__pthread_rwlock_wrlock, iFp)
+//GO2(pthread_rwlock_wrlock, iFp, __pthread_rwlock_wrlock)    // not always defined
+//GO(pthread_self, uFv)
+//GOM(pthread_setaffinity_np, iFELup)
+//GO(pthread_setcancelstate, iFip)
+//GO(pthread_setcanceltype, iFip)
+//GO(pthread_setconcurrency, iFi)
+//GOM(pthread_setname_np, iFEpp)   // not present on the Pandora
+//GO(pthread_setschedparam, iFuip)
+//GO(pthread_setschedprio, iFpi)
+//GO(__pthread_setspecific, iFup)
+//GO(pthread_setspecific, iFup)
+//GO(pthread_sigmask, iFipp)
+//GO(pthread_spin_destroy, iFp)
+//GO(pthread_spin_init, iFpi)
+//GO(pthread_spin_lock, iFp)
+//GO(pthread_spin_trylock, iFp)
+//GO(pthread_spin_unlock, iFp)
+//GO(pthread_testcancel, vFv)
+//GO(pthread_timedjoin_np, iFppp)
+//GO(pthread_tryjoin_np, iFpp)
+//GOM(__pthread_unregister_cancel, vFEp)
+// __pthread_unregister_cancel_restore
+// __pthread_unwind
+//GOM(__pthread_unwind_next, vFEp)
+//GO(pthread_yield, iFv)
+// raise
+// __res_state
+//GO(sem_close, iFp)
+//GO(sem_destroy, iFp)
+//GO(sem_getvalue, iFpp)
+//GO(sem_init, iFpiu)
+//GO(sem_open, pFpiuuuuuuu)    // use a vararg at 3rd arg, so putting lots of args to be sure, even if only 2 are needed
+//GO(sem_post, iFp)
+//GO(sem_timedwait, iFpp)
+//GO(sem_trywait, iFp)
+//GO(sem_unlink, iFp)
+//GO(sem_wait, iFp)
+// __sigaction
+// system
+// __vfork
diff --git a/src/wrapped/wrappedlibrt.c b/src/wrapped/wrappedlibrt.c
new file mode 100755
index 00000000..a6877c58
--- /dev/null
+++ b/src/wrapped/wrappedlibrt.c
@@ -0,0 +1,75 @@
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <signal.h>
+
+#include "wrappedlibs.h"
+
+#include "debug.h"
+#include "wrapper.h"
+#include "bridge.h"
+#include "librarian/library_private.h"
+#include "x64emu.h"
+#include "emu/x64emu_private.h"
+#include "callback.h"
+#include "librarian.h"
+#include "box64context.h"
+#include "emu/x64emu_private.h"
+
+#undef aio_suspend
+#undef aio_return
+#undef aio_write
+#undef aio_read
+#undef aio_error
+
+#undef clock_gettime
+
+const char* librtName = "librt.so.1";
+#define LIBNAME librt
+
+#define SUPER() \
+GO(0)   \
+GO(1)   \
+GO(2)   \
+GO(3)
+
+// sigev_notify
+#define GO(A)   \
+static uintptr_t my_sigev_notify_fct_##A = 0;   \
+static void my_sigev_notify_##A(void* sigval)    \
+{                                       \
+    RunFunction(my_context, my_sigev_notify_fct_##A, 1, sigval);\
+}
+SUPER()
+#undef GO
+static void* findsigev_notifyFct(void* fct)
+{
+    if(!fct) return fct;
+    if(GetNativeFnc((uintptr_t)fct))  return GetNativeFnc((uintptr_t)fct);
+    #define GO(A) if(my_sigev_notify_fct_##A == (uintptr_t)fct) return my_sigev_notify_##A;
+    SUPER()
+    #undef GO
+    #define GO(A) if(my_sigev_notify_fct_##A == 0) {my_sigev_notify_fct_##A = (uintptr_t)fct; return my_sigev_notify_##A; }
+    SUPER()
+    #undef GO
+    printf_log(LOG_NONE, "Warning, no more slot for libpng12 sigev_notify callback\n");
+    return NULL;
+}
+
+#undef SUPER
+
+EXPORT int my_timer_create(x64emu_t* emu, uint32_t clockid, void* sevp, timer_t* timerid)
+{
+    struct sigevent sevent;
+    memcpy(&sevent, sevp, sizeof(sevent));
+
+    if(sevent.sigev_notify == SIGEV_THREAD) {
+        sevent.sigev_notify_function = findsigev_notifyFct(sevent.sigev_notify_function);
+    }
+
+    return timer_create(clockid, &sevent, timerid);
+}
+
+#include "wrappedlib_init.h"
diff --git a/src/wrapped/wrappedlibrt_private.h b/src/wrapped/wrappedlibrt_private.h
new file mode 100755
index 00000000..5200b2fe
--- /dev/null
+++ b/src/wrapped/wrappedlibrt_private.h
@@ -0,0 +1,48 @@
+#if !(defined(GO) && defined(GOM) && defined(GO2) && defined(DATA))
+#error Meh...
+#endif
+
+//clockid_t is uint32?
+// pid_t is uint32 too? (for clock_getcpuclockid)
+// time_t is uint32?
+
+// aio_cancel
+// aio_cancel64
+// aio_error
+GO(aio_error64, iFp)
+// aio_fsync
+// aio_fsync64
+// aio_init
+// aio_read
+GO(aio_read64, iFp)
+// aio_return
+GO(aio_return64, lFp)
+// aio_suspend
+GO(aio_suspend64, iFip)
+// aio_write
+GO(aio_write64, iFp)
+GO(clock_getcpuclockid, iFup)
+GO(clock_getres, iFup)
+GO(clock_gettime, iFup)
+GO(clock_nanosleep, iFuipp)
+GO(clock_settime, iFup)
+// lio_listio
+// lio_listio64
+// mq_close
+GO(mq_getattr, iFip)
+// mq_notify
+// mq_open
+// __mq_open_2
+// mq_receive
+// mq_send
+// mq_setattr
+// mq_timedreceive
+// mq_timedsend
+// mq_unlink
+GO(shm_open, iFpiu)
+GO(shm_unlink, iFp)
+GOM(timer_create, iFEupp)
+GO(timer_delete, iFu)
+GO(timer_getoverrun, iFu)
+GO(timer_gettime, iFup)
+GO(timer_settime, iFuipp)