about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-03-03 16:43:42 +0100
committerptitSeb <sebastien.chev@gmail.com>2021-03-03 16:43:42 +0100
commitf4829a8ce42b1abbcc8621802d6c6fad3a56cd5d (patch)
tree211276c3587721126ded00be46487bf23b605591 /src
parentf73fbd3cee38b4c0086c934d73972375c9c8c7d6 (diff)
downloadbox64-f4829a8ce42b1abbcc8621802d6c6fad3a56cd5d.tar.gz
box64-f4829a8ce42b1abbcc8621802d6c6fad3a56cd5d.zip
More infrastructure added to elf and x64 emu
Diffstat (limited to 'src')
-rwxr-xr-xsrc/box64context.c68
-rwxr-xr-xsrc/dynarec/dynarec.c216
-rwxr-xr-xsrc/elfs/elfloader.c203
-rwxr-xr-xsrc/elfs/elfloader_private.h14
-rwxr-xr-xsrc/emu/x64emu.c72
-rwxr-xr-xsrc/emu/x64run.c118
-rwxr-xr-xsrc/emu/x64run_private.c787
-rwxr-xr-xsrc/emu/x64syscall.c186
-rwxr-xr-xsrc/emu/x64tls.c213
-rwxr-xr-xsrc/include/box64context.h92
-rwxr-xr-xsrc/include/callback.h12
-rwxr-xr-xsrc/include/dynarec.h8
-rwxr-xr-xsrc/include/elfloader.h70
-rwxr-xr-xsrc/include/librarian.h51
-rwxr-xr-xsrc/include/library.h36
-rwxr-xr-xsrc/include/wrappedlibs.h21
-rwxr-xr-xsrc/include/x64emu.h4
-rwxr-xr-xsrc/include/x64run.h10
-rwxr-xr-xsrc/include/x64tls.h13
-rwxr-xr-xsrc/librarian/librarian.c588
-rwxr-xr-xsrc/librarian/librarian_private.h44
-rwxr-xr-xsrc/librarian/library.c700
-rwxr-xr-xsrc/librarian/library_private.h101
-rwxr-xr-xsrc/library_list.h146
-rwxr-xr-xsrc/libtools/threads.c40
-rwxr-xr-xsrc/tools/callback.c86
-rw-r--r--src/wrapped/generated/functions_list.txt15
-rw-r--r--src/wrapped/generated/wrapper.c102
-rw-r--r--src/wrapped/generated/wrapper.h50
-rwxr-xr-xsrc/wrapped/wrappedldlinux.c42
-rwxr-xr-xsrc/wrapped/wrappedldlinux_private.h25
-rwxr-xr-xsrc/wrapped/wrappedlib_init.h239
-rwxr-xr-xsrc/wrapped/wrappedlib_undefs.h23
-rwxr-xr-xsrc/wrapped/wrappedlibc.c2590
-rwxr-xr-xsrc/wrapped/wrappedlibc_private.h2238
-rwxr-xr-xsrc/wrapped/wrappedlibdl.c415
-rwxr-xr-xsrc/wrapped/wrappedlibdl_private.h14
37 files changed, 9404 insertions, 248 deletions
diff --git a/src/box64context.c b/src/box64context.c
index fa4b74b7..4c75e98e 100755
--- a/src/box64context.c
+++ b/src/box64context.c
@@ -13,7 +13,10 @@
 #include "threads.h"
 #include "x64trace.h"
 #include "bridge.h"
-
+#include "librarian.h"
+#include "library.h"
+#include "wrapper.h"
+#include "x64emu.h"
 
 EXPORTDYN
 void initAllHelpers(box64context_t* context)
@@ -35,7 +38,7 @@ void finiAllHelpers(box64context_t* context)
         return;
     fini_pthread_helper(context);
     //fini_signal_helper();
-    //cleanAlternate();
+    cleanAlternate();
     fini_custommem_helper(context);
     finied = 1;
 }
@@ -80,16 +83,28 @@ box64context_t *NewBox64Context(int argc)
 
     init_custommem_helper(context);
 
+    context->maplib = NewLibrarian(context, 1);
+    context->local_maplib = NewLibrarian(context, 1);
     context->system = NewBridge();
     // create vsyscall
-//    context->vsyscall = AddBridge(context->system, vFv, x64Syscall, 0);
+    context->vsyscall = AddBridge(context->system, vFv, x64Syscall, 0);
     context->box64lib = dlopen(NULL, RTLD_NOW|RTLD_GLOBAL);
-    //context->dlprivate = NewDLPrivate();
+    context->dlprivate = NewDLPrivate();
 
     context->argc = argc;
     context->argv = (char**)calloc(context->argc+1, sizeof(char*));
 
+    pthread_mutex_init(&context->mutex_once, NULL);
+    pthread_mutex_init(&context->mutex_once2, NULL);
+    pthread_mutex_init(&context->mutex_trace, NULL);
+#ifndef DYNAREC
+    pthread_mutex_init(&context->mutex_lock, NULL);
+#else
+    pthread_mutex_init(&context->mutex_dyndump, NULL);
+#endif
+    pthread_mutex_init(&context->mutex_tls, NULL);
     pthread_mutex_init(&context->mutex_thread, NULL);
+    pthread_key_create(&context->tlskey, free_tlsdatasize);
 
 
     for (int i=0; i<4; ++i) context->canary[i] = 1 +  getrand(255);
@@ -107,8 +122,21 @@ void FreeBox64Context(box64context_t** context)
     if(!context)
         return;
     
+    if(--(*context)->forked >= 0)
+        return;
+
     box64context_t* ctx = *context;   // local copy to do the cleanning
 
+    for(int i=0; i<ctx->elfsize; ++i) {
+        FreeElfHeader(&ctx->elfs[i]);
+    }
+    free(ctx->elfs);
+
+    if(ctx->maplib)
+        FreeLibrarian(&ctx->maplib);
+    if(ctx->local_maplib)
+        FreeLibrarian(&ctx->local_maplib);
+
     FreeCollection(&ctx->box64_path);
     FreeCollection(&ctx->box64_ld_lib);
     FreeCollection(&ctx->box64_emulated_libs);
@@ -118,12 +146,21 @@ void FreeBox64Context(box64context_t** context)
     if(ctx->zydis)
         DeleteX64Trace(ctx);
 
+    if(ctx->deferedInitList)
+        free(ctx->deferedInitList);
+
     free(ctx->argv);
     
     for (int i=0; i<ctx->envc; ++i)
         free(ctx->envv[i]);
     free(ctx->envv);
 
+    if(ctx->atfork_sz) {
+        free(ctx->atforks);
+        ctx->atforks = NULL;
+        ctx->atfork_sz = ctx->atfork_cap = 0;
+    }
+
     for(int i=0; i<MAX_SIGNAL; ++i)
         if(ctx->signals[i]!=0 && ctx->signals[i]!=1) {
             signal(i, SIG_DFL);
@@ -133,7 +170,7 @@ void FreeBox64Context(box64context_t** context)
 
     CleanStackSize(ctx);
 
-    //FreeDLPrivate(&ctx->dlprivate);
+    FreeDLPrivate(&ctx->dlprivate);
 
     free(ctx->stack);
 
@@ -142,6 +179,10 @@ void FreeBox64Context(box64context_t** context)
 
     FreeBridge(&ctx->system);
 
+//    freeGLProcWrapper(ctx);
+//    freeALProcWrapper(ctx);
+
+
     void* ptr;
     if ((ptr = pthread_getspecific(ctx->tlskey)) != NULL) {
         free_tlsdatasize(ptr);
@@ -152,8 +193,22 @@ void FreeBox64Context(box64context_t** context)
     if(ctx->tlsdata)
         free(ctx->tlsdata);
 
+    pthread_mutex_destroy(&ctx->mutex_once);
+    pthread_mutex_destroy(&ctx->mutex_once2);
+    pthread_mutex_destroy(&ctx->mutex_trace);
+#ifndef DYNAREC
+    pthread_mutex_destroy(&ctx->mutex_lock);
+#else
+    pthread_mutex_destroy(&ctx->mutex_dyndump);
+#endif
+    pthread_mutex_destroy(&ctx->mutex_tls);
     pthread_mutex_destroy(&ctx->mutex_thread);
 
+    free_neededlib(&ctx->neededlibs);
+
+    if(ctx->emu_sig)
+        FreeX64Emu(&ctx->emu_sig);
+
     finiAllHelpers(ctx);
 
     free(ctx);
@@ -187,7 +242,7 @@ int AddTLSPartition(box64context_t* context, int tlssize) {
 
     return -context->tlssize;   // negative offset
 }
-/*
+
 void add_neededlib(needed_libs_t* needed, library_t* lib)
 {
     if(!needed)
@@ -209,4 +264,3 @@ void free_neededlib(needed_libs_t* needed)
         free(needed->libs);
     needed->libs = NULL;
 }
-*/
\ No newline at end of file
diff --git a/src/dynarec/dynarec.c b/src/dynarec/dynarec.c
new file mode 100755
index 00000000..c88cd61f
--- /dev/null
+++ b/src/dynarec/dynarec.c
@@ -0,0 +1,216 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <errno.h>
+#include <setjmp.h>
+
+#include "debug.h"
+#include "box64context.h"
+#include "dynarec.h"
+#include "emu/x64emu_private.h"
+#include "tools/bridge_private.h"
+#include "x64run.h"
+#include "x64emu.h"
+#include "box64stack.h"
+#include "callback.h"
+#include "emu/x64run_private.h"
+#include "x64trace.h"
+#include "threads.h"
+#ifdef DYNAREC
+#include "dynablock.h"
+#include "dynablock_private.h"
+#endif
+
+#ifdef DYNAREC
+#ifdef ARM
+void arm_prolog(x64emu_t* emu, void* addr) EXPORTDYN;
+void arm_epilog() EXPORTDYN;
+void arm_epilog_fast() EXPORTDYN;
+#endif
+#endif
+
+#ifdef DYNAREC
+#ifdef HAVE_TRACE
+uintptr_t getX64Address(dynablock_t* db, uintptr_t arm_addr);
+#endif
+void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2)
+{
+    #ifdef HAVE_TRACE
+    if(!addr) {
+        x2-=8;  // actual PC is 2 instructions ahead
+        dynablock_t* db = FindDynablockFromNativeAddress(x2);
+        printf_log(LOG_NONE, "Warning, jumping to NULL address from %p (db=%p, x86addr=%p)\n", x2, db, db?(void*)getX86Address(db, (uintptr_t)x2):NULL);
+    }
+    #endif
+    dynablock_t* current = NULL;
+    void * jblock;
+    dynablock_t* block = DBGetBlock(emu, addr, 1, &current);
+    if(!block) {
+        // no block, let link table as is...
+        //tableupdate(arm_epilog, addr, table);
+        return arm_epilog;
+    }
+    if(!block->done) {
+        // not finished yet... leave linker
+        //tableupdate(arm_linker, addr, table);
+        return arm_epilog;
+    }
+    if(!(jblock=block->block)) {
+        // null block, but done: go to epilog, no linker here
+        return arm_epilog;
+    }
+    //dynablock_t *father = block->father?block->father:block;
+    return jblock;
+}
+#endif
+
+void DynaCall(x64emu_t* emu, uintptr_t addr)
+{
+    // prepare setjump for signal handling
+    emu_jmpbuf_t *ejb = NULL;
+    int jmpbuf_reset = 0;
+    if(emu->type == EMUTYPE_MAIN) {
+        ejb = GetJmpBuf();
+        if(!ejb->jmpbuf_ok) {
+            ejb->emu = emu;
+            ejb->jmpbuf_ok = 1;
+            jmpbuf_reset = 1;
+            if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf)) {
+                printf_log(LOG_DEBUG, "Setjmp DynaCall, fs=0x%x\n", ejb->emu->segs[_FS]);
+                addr = R_RIP;   // not sure if it should still be inside DynaCall!
+            }
+        }
+    }
+#ifdef DYNAREC
+    if(!box86_dynarec)
+#endif
+        EmuCall(emu, addr);
+#ifdef DYNAREC
+    else {
+        uint64_t old_rsp = R_RSP;
+        uint64_t old_rbx = R_RBX;
+        uint64_t old_rdi = R_RDI;
+        uint64_t old_rsi = R_RSI;
+        uint64_t old_rbp = R_RBP;
+        uint64_t old_rip = R_RIP;
+        PushExit(emu);
+        R_RIP = addr;
+        emu->df = d_none;
+        dynablock_t* block = NULL;
+        dynablock_t* current = NULL;
+        while(!emu->quit) {
+            block = DBGetBlock(emu, R_RIP, 1, &current);
+            current = block;
+            if(!block || !block->block || !block->done) {
+                // no block, of block doesn't have DynaRec content (yet, temp is not null)
+                // Use interpreter (should use single instruction step...)
+                dynarec_log(LOG_DEBUG, "%04d|Calling Interpretor @%p, emu=%p\n", GetTID(), (void*)R_RIP, emu);
+                Run(emu, 1);
+            } else {
+                dynarec_log(LOG_DEBUG, "%04d|Calling DynaRec Block @%p (%p) of %d x86 instructions (father=%p) emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize ,block->father, emu);
+                CHECK_FLAGS(emu);
+                // block is here, let's run it!
+                #ifdef ARM
+                arm_prolog(emu, block->block);
+                #endif
+            }
+            if(emu->fork) {
+                int forktype = emu->fork;
+                emu->quit = 0;
+                emu->fork = 0;
+                emu = x86emu_fork(emu, forktype);
+                if(emu->type == EMUTYPE_MAIN) {
+                    ejb = GetJmpBuf();
+                    ejb->emu = emu;
+                    ejb->jmpbuf_ok = 1;
+                    jmpbuf_reset = 1;
+                    if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf)) {
+                        printf_log(LOG_DEBUG, "Setjmp inner DynaCall, fs=0x%x\n", ejb->emu->segs[_FS]);
+                        addr = R_RIP;
+                    }
+                }
+            }
+        }
+        emu->quit = 0;  // reset Quit flags...
+        emu->df = d_none;
+        if(emu->quitonlongjmp && emu->longjmp) {
+            emu->longjmp = 0;   // don't change anything because of the longjmp
+        } else {
+            R_RBX = old_rbx;
+            R_RDI = old_rdi;
+            R_RSI = old_rsi;
+            R_RBP = old_rbp;
+            R_RSP = old_rsp;
+            R_RIP = old_rip;  // and set back instruction pointer
+        }
+    }
+#endif
+    // clear the setjmp
+    if(ejb && jmpbuf_reset)
+        ejb->jmpbuf_ok = 0;
+}
+
+int DynaRun(x64emu_t* emu)
+{
+    // prepare setjump for signal handling
+    emu_jmpbuf_t *ejb = NULL;
+#ifdef DYNAREC
+    int jmpbuf_reset = 1;
+#endif
+    if(emu->type == EMUTYPE_MAIN) {
+        ejb = GetJmpBuf();
+        if(!ejb->jmpbuf_ok) {
+            ejb->emu = emu;
+            ejb->jmpbuf_ok = 1;
+#ifdef DYNAREC
+            jmpbuf_reset = 1;
+#endif
+            if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf))
+                printf_log(LOG_DEBUG, "Setjmp DynaRun, fs=0x%x\n", ejb->emu->segs[_FS]);
+        }
+    }
+#ifdef DYNAREC
+    if(!box86_dynarec)
+#endif
+        return Run(emu, 0);
+#ifdef DYNAREC
+    else {
+        dynablock_t* block = NULL;
+        dynablock_t* current = NULL;
+        while(!emu->quit) {
+            block = DBGetBlock(emu, R_RIP, 1, &current);
+            current = block;
+            if(!block || !block->block || !block->done) {
+                // no block, of block doesn't have DynaRec content (yet, temp is not null)
+                // Use interpreter (should use single instruction step...)
+                dynarec_log(LOG_DEBUG, "%04d|Running Interpretor @%p, emu=%p\n", GetTID(), (void*)R_RIP, emu);
+                Run(emu, 1);
+            } else {
+                dynarec_log(LOG_DEBUG, "%04d|Running DynaRec Block @%p (%p) of %d x86 insts (father=%p) emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize, block->father, emu);
+                // block is here, let's run it!
+                #ifdef ARM
+                arm_prolog(emu, block->block);
+                #endif
+            }
+            if(emu->fork) {
+                int forktype = emu->fork;
+                emu->quit = 0;
+                emu->fork = 0;
+                emu = x86emu_fork(emu, forktype);
+                if(emu->type == EMUTYPE_MAIN) {
+                    ejb = GetJmpBuf();
+                    ejb->emu = emu;
+                    ejb->jmpbuf_ok = 1;
+                    jmpbuf_reset = 1;
+                    if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf))
+                        printf_log(LOG_DEBUG, "Setjmp inner DynaRun, fs=0x%x\n", ejb->emu->segs[_FS]);
+                }
+            }
+        }
+    }
+    // clear the setjmp
+    if(ejb && jmpbuf_reset)
+        ejb->jmpbuf_ok = 0;
+    return 0;
+#endif
+}
\ No newline at end of file
diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c
index 1c87f7fc..bf90c9e1 100755
--- a/src/elfs/elfloader.c
+++ b/src/elfs/elfloader.c
@@ -16,24 +16,24 @@
 #include "debug.h"
 #include "elfload_dump.h"
 #include "elfloader_private.h"
-//#include "librarian.h"
-//#include "x86run.h"
-//#include "bridge.h"
-//#include "wrapper.h"
+#include "librarian.h"
+#include "x64run.h"
+#include "bridge.h"
+#include "wrapper.h"
 #include "box64context.h"
-//#include "library.h"
-//#include "x86emu.h"
-//#include "box64stack.h"
-//#include "callback.h"
+#include "library.h"
+#include "x64emu.h"
+#include "box64stack.h"
+#include "callback.h"
 //#include "dynarec.h"
-//#include "box64stack.h"
+#include "box64stack.h"
 #include "custommem.h"
 #include "wine_tools.h"
-//#ifdef DYNAREC
-//#include "dynablock.h"
-//#endif
-//#include "../emu/x86emu_private.h"
-//#include "x86tls.h"
+#ifdef DYNAREC
+#include "dynablock.h"
+#endif
+#include "../emu/x64emu_private.h"
+#include "x64tls.h"
 
 void* my__IO_2_1_stderr_ = NULL;
 void* my__IO_2_1_stdin_  = NULL;
@@ -349,8 +349,8 @@ int ReloadElfMemory(FILE* f, box64context_t* context, elfheader_t* head)
     // TLS data are just a copy, no need to re-load it
     return 0;
 }
-#if 0
-int FindR386COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint32_t** p)
+
+int FindR64COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint64_t** p)
 {
     if(!h)
         return 0;
@@ -362,9 +362,9 @@ int FindR386COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint32_t*
         int t = ELF64_R_TYPE(rel[i].r_info);
         Elf64_Sym *sym = &h->DynSym[ELF64_R_SYM(rel[i].r_info)];
         const char* symname = SymName(h, sym);
-        if(!strcmp(symname, name) && t==R_386_COPY) {
+        if(!strcmp(symname, name) && t==R_X86_64_COPY) {
             *offs = sym->st_value + h->delta;
-            *p = (uint32_t*)(rel[i].r_offset + h->delta);
+            *p = (uint64_t*)(rel[i].r_offset + h->delta);
             return 1;
         }
     }
@@ -378,25 +378,23 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
         Elf64_Sym *sym = &head->DynSym[ELF64_R_SYM(rel[i].r_info)];
         int bind = ELF64_ST_BIND(sym->st_info);
         const char* symname = SymName(head, sym);
-        uint32_t ndx = sym->st_shndx;
-        uint32_t *p = (uint32_t*)(rel[i].r_offset + head->delta);
+        uint64_t ndx = sym->st_shndx;
+        uint64_t *p = (uint64_t*)(rel[i].r_offset + head->delta);
         uintptr_t offs = 0;
         uintptr_t end = 0;
         uintptr_t tmp = 0;
-        elfheader_t* h_tls = head;
         if(bind==STB_LOCAL) {
             offs = sym->st_value + head->delta;
             end = offs + sym->st_size;
         } else {
             // this is probably very very wrong. A proprer way to get reloc need to be writen, but this hack seems ok for now
             // at least it work for half-life, unreal, ut99, zsnes, Undertale, ColinMcRae Remake, FTL, ShovelKnight...
-            if(bind==STB_GLOBAL && (ndx==10 || ndx==19) && t!=R_386_GLOB_DAT) {
+            if(bind==STB_GLOBAL && (ndx==10 || ndx==19) && t!=R_X86_64_GLOB_DAT) {
                 offs = sym->st_value + head->delta;
                 end = offs + sym->st_size;
             }
             // so weak symbol are the one left
             if(!offs && !end) {
-                h_tls = NULL;
                 if(local_maplib)
                     GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end);
                 if(!offs && !end)
@@ -404,48 +402,27 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
             }
         }
         uintptr_t globoffs, globend;
-        uint32_t* globp;
-        int delta;
+        uint64_t* globp;
         switch(t) {
-            case R_386_NONE:
+            case R_X86_64_NONE:
                 // can be ignored
                 printf_log(LOG_DUMP, "Ignoring %s @%p (%p)\n", DumpRelType(t), p, (void*)(p?(*p):0));
                 break;
-            case R_386_TLS_TPOFF:
-                // Negated offset in static TLS block
-                {
-                    if(h_tls)
-                        offs = sym->st_value;
-                    else {
-                        if(local_maplib)
-                            h_tls = GetGlobalSymbolElf(local_maplib, symname);
-                        if(!h_tls)
-                            h_tls = GetGlobalSymbolElf(maplib, symname);
-                    }
-                    if(h_tls) {
-                        delta = *(int*)p;
-                        printf_log(LOG_DUMP, "Applying %s %s on %s @%p (%d -> %d)\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, delta, (int32_t)offs + h_tls->tlsbase);
-                        *p = (uint32_t)((int32_t)offs + h_tls->tlsbase);
-                    } else {
-                        printf_log(LOG_INFO, "Warning, cannot apply %s %s on %s @%p (%d), no elf_header found\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, (int32_t)offs);
-                    }
-                }
-                break;
-            case R_386_PC32:
+            case R_X86_64_PC32:
                     if (!offs) {
-                        printf_log(LOG_NONE, "Error: Global Symbol %s not found, cannot apply R_386_PC32 @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
+                        printf_log(LOG_NONE, "Error: Global Symbol %s not found, cannot apply R_X86_64_PC32 @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
                     }
                     offs = (offs - (uintptr_t)p);
                     if(!offs)
-                        printf_log(LOG_DUMP, "Apply %s R_386_PC32 @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)(*(uintptr_t*)p+offs));
+                        printf_log(LOG_DUMP, "Apply %s R_X86_64_PC32 @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)(*(uintptr_t*)p+offs));
                     *p += offs;
                 break;
-            case R_386_GLOB_DAT:
-                if(head!=my_context->elfs[0] && !IsGlobalNoWeakSymbolInNative(maplib, symname) && FindR386COPYRel(my_context->elfs[0], symname, &globoffs, &globp)) {
+            case R_X86_64_GLOB_DAT:
+                if(head!=my_context->elfs[0] && !IsGlobalNoWeakSymbolInNative(maplib, symname) && FindR64COPYRel(my_context->elfs[0], symname, &globoffs, &globp)) {
                     // set global offs / size for the symbol
                     offs = sym->st_value + head->delta;
                     end = offs + sym->st_size;
-                    printf_log(LOG_DUMP, "Apply %s R_386_GLOB_DAT with R_386_COPY @%p/%p (%p/%p -> %p/%p) size=%d on sym=%s \n", (bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0), (void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, sym->st_size, symname);
+                    printf_log(LOG_DUMP, "Apply %s R_X86_64_GLOB_DAT with R_X86_64_COPY @%p/%p (%p/%p -> %p/%p) size=%ld on sym=%s \n", (bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0), (void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, sym->st_size, symname);
                     *p = globoffs;
                     AddWeakSymbol(GetGlobalData(maplib), symname, offs, end-offs+1);
                 } else {
@@ -456,14 +433,14 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
                     }
                     if (!offs) {
                         if(strcmp(symname, "__gmon_start__"))
-                            printf_log(LOG_NONE, "Error: Global Symbol %s not found, cannot apply R_386_GLOB_DAT @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
+                            printf_log(LOG_NONE, "Error: Global Symbol %s not found, cannot apply R_X86_64_GLOB_DAT @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
                     } else {
-                        printf_log(LOG_DUMP, "Apply %s R_386_GLOB_DAT @%p (%p -> %p) on sym=%s\n", (bind==STB_LOCAL)?"Local":"Global", p, (void*)(p?(*p):0), (void*)offs, symname);
+                        printf_log(LOG_DUMP, "Apply %s R_X86_64_GLOB_DAT @%p (%p -> %p) on sym=%s\n", (bind==STB_LOCAL)?"Local":"Global", p, (void*)(p?(*p):0), (void*)offs, symname);
                         *p = offs;
                     }
                 }
                 break;
-            case R_386_COPY:
+            case R_X86_64_COPY:
                 if(offs) {
                     uintptr_t old_offs = offs;
                     uintptr_t old_end = end;
@@ -479,7 +456,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
                         offs = old_offs;
                         end = old_end;
                     }
-                    printf_log(LOG_DUMP, "Apply %s R_386_COPY @%p with sym=%s, @%p size=%d (", (bind==STB_LOCAL)?"Local":"Global", p, symname, (void*)offs, sym->st_size);
+                    printf_log(LOG_DUMP, "Apply %s R_X86_64_COPY @%p with sym=%s, @%p size=%ld (", (bind==STB_LOCAL)?"Local":"Global", p, symname, (void*)offs, sym->st_size);
                     memmove(p, (void*)offs, sym->st_size);
                     if(LOG_DUMP<=box64_log) {
                         uint32_t*k = (uint32_t*)p;
@@ -488,64 +465,23 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
                         printf_log(LOG_DUMP, "%s)\n", (sym->st_size>128)?" ...":"");
                     }
                 } else {
-                    printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_386_COPY @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
+                    printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_X86_64_COPY @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
                 }
                 break;
-            case R_386_RELATIVE:
-                printf_log(LOG_DUMP, "Apply %s R_386_RELATIVE @%p (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, *(void**)p, (void*)((*p)+head->delta));
+            case R_X86_64_RELATIVE:
+                printf_log(LOG_DUMP, "Apply %s R_X86_64_RELATIVE @%p (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, *(void**)p, (void*)((*p)+head->delta));
                 *p += head->delta;
                 break;
-            case R_386_32:
+            case R_X86_64_64:
                 if (!offs) {
-                    printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_386_32 @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
+                    printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_X86_64_64 @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
 //                    return -1;
                 } else {
-                    printf_log(LOG_DUMP, "Apply %s R_386_32 @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)(offs+*(uint32_t*)p));
+                    printf_log(LOG_DUMP, "Apply %s R_X86_64_64 @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)(offs+*(uint32_t*)p));
                     *p += offs;
                 }
                 break;
-            case R_386_TLS_DTPMOD32:
-                // ID of module containing symbol
-                if(!symname || symname[0]=='\0' || bind==STB_LOCAL)
-                    offs = getElfIndex(my_context, head);
-                else {
-                    if(!h_tls) {
-                        if(local_maplib)
-                            h_tls = GetGlobalSymbolElf(local_maplib, symname);
-                        if(!h_tls)
-                            h_tls = GetGlobalSymbolElf(maplib, symname);
-                    }
-                    offs = getElfIndex(my_context, h_tls);
-                }
-                if(p) {
-                    printf_log(LOG_DUMP, "Apply %s %s @%p with sym=%s (%p -> %p)\n", "R_386_TLS_DTPMOD32", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)offs);
-                    *p = offs;
-                } else {
-                    printf_log(LOG_NONE, "Warning, Symbol %s or Elf not found, but R_386_TLS_DTPMOD32 Slot Offset is NULL \n", symname);
-                }
-                break;
-            case R_386_TLS_DTPOFF32:
-                // Offset in TLS block
-                if (!offs && !end) {
-                    if(bind==STB_WEAK) {
-                        printf_log(LOG_INFO, "Warning: Weak Symbol %s not found, cannot apply R_386_TLS_DTPOFF32 @%p (%p)\n", symname, p, *(void**)p);
-                    } else {
-                        printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_386_TLS_DTPOFF32 @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
-                    }
-//                    return -1;
-                } else {
-                    if(h_tls)
-                        offs = sym->st_value;
-                    if(p) {
-                        int tlsoffset = offs;    // it's not an offset in elf memory
-                        printf_log(LOG_DUMP, "Apply %s R_386_TLS_DTPOFF32 @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, (void*)tlsoffset, (void*)offs);
-                        *p = tlsoffset;
-                    } else {
-                        printf_log(LOG_NONE, "Warning, Symbol %s found, but R_386_TLS_DTPOFF32 Slot Offset is NULL \n", symname);
-                    }
-                }
-                break;
-            case R_386_JMP_SLOT:
+            case R_X86_64_JUMP_SLOT:
                 // apply immediatly for gobject closure marshal or for LOCAL binding. Also, apply immediatly if it doesn't jump in the got
                 tmp = (uintptr_t)(*p);
                 if (bind==STB_LOCAL 
@@ -555,21 +491,21 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
                   ) {
                     if (!offs) {
                         if(bind==STB_WEAK) {
-                            printf_log(LOG_INFO, "Warning: Weak Symbol %s not found, cannot apply R_386_JMP_SLOT @%p (%p)\n", symname, p, *(void**)p);
+                            printf_log(LOG_INFO, "Warning: Weak Symbol %s not found, cannot apply R_X86_64_JUMP_SLOT @%p (%p)\n", symname, p, *(void**)p);
                         } else {
-                            printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_386_JMP_SLOT @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
+                            printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_X86_64_JUMP_SLOT @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
                         }
     //                    return -1;
                     } else {
                         if(p) {
-                            printf_log(LOG_DUMP, "Apply %s R_386_JMP_SLOT @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)offs);
+                            printf_log(LOG_DUMP, "Apply %s R_X86_64_JUMP_SLOT @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)offs);
                             *p = offs;
                         } else {
                             printf_log(LOG_NONE, "Warning, Symbol %s found, but Jump Slot Offset is NULL \n", symname);
                         }
                     }
                 } else {
-                    printf_log(LOG_DUMP, "Preparing (if needed) %s R_386_JMP_SLOT @%p (0x%x->0x%0x) with sym=%s to be apply later\n", (bind==STB_LOCAL)?"Local":"Global", p, *p, *p+head->delta, symname);
+                    printf_log(LOG_DUMP, "Preparing (if needed) %s R_X86_64_JUMP_SLOT @%p (0x%lx->0x%0lx) with sym=%s to be apply later\n", (bind==STB_LOCAL)?"Local":"Global", p, *p, *p+head->delta, symname);
                     *p += head->delta;
                 }
                 break;
@@ -589,21 +525,21 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
         uintptr_t offs = 0;
         uintptr_t end = 0;
         switch(ELF64_R_TYPE(rela[i].r_info)) {
-            case R_386_NONE:
-            case R_386_PC32:
+            case R_X86_64_NONE:
+            case R_X86_64_PC32:
                 // can be ignored
                 break;
-            case R_386_COPY:
+            case R_X86_64_COPY:
                 if(local_maplib)
                     GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head);
                 if(!offs)
                     GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head);
                 if(offs) {
                     // add r_addend to p?
-                    printf_log(LOG_DUMP, "Apply R_386_COPY @%p with sym=%s, @%p size=%d\n", p, symname, (void*)offs, sym->st_size);
+                    printf_log(LOG_DUMP, "Apply R_X86_64_COPY @%p with sym=%s, @%p size=%ld\n", p, symname, (void*)offs, sym->st_size);
                     memcpy(p, (void*)(offs+rela[i].r_addend), sym->st_size);
                 } else {
-                    printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply RELA R_386_COPY @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
+                    printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply RELA R_X86_64_COPY @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
                 }
                 break;
             default:
@@ -663,7 +599,7 @@ int RelocateElfPlt(lib_t *maplib, lib_t *local_maplib, elfheader_t* head)
    
     return 0;
 }
-#endif
+
 void CalcStack(elfheader_t* elf, uint32_t* stacksz, int* stackalign)
 {
     if(*stacksz < elf->stacksz)
@@ -708,7 +644,7 @@ uintptr_t GetFunctionAddress(elfheader_t* h, const char* name)
     if(sym) return sym->st_value;
     return 0;
 }
-#if 0
+
 uintptr_t GetEntryPoint(lib_t* maplib, elfheader_t* h)
 {
     uintptr_t ep = h->entrypoint + h->delta;
@@ -739,12 +675,12 @@ uintptr_t GetEntryPoint(lib_t* maplib, elfheader_t* h)
     */
     return ep;
 }
-#endif
+
 uintptr_t GetLastByte(elfheader_t* h)
 {
     return (uintptr_t)h->memory/* + h->delta*/ + h->memsz;
 }
-#if 0
+
 void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* weaksymbols, kh_mapsymbols_t* localsymbols, elfheader_t* h)
 {
     printf_log(LOG_DUMP, "Will look for Symbol to add in SymTable(%d)\n", h->numSymTab);
@@ -812,7 +748,7 @@ $PLATFORM – Expands to the processor type of the current machine (see the
 uname(1) man page description of the -i option). For more details of this token
 expansion, see “System Specific Shared Objects”
 */
-int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, int local, box64context_t *box64, x86emu_t* emu)
+int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, int local, box64context_t *box64, x64emu_t* emu)
 {
     DumpDynamicRPath(h);
     // update RPATH first
@@ -874,7 +810,7 @@ int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, int
         }
     return 0;
 }
-#endif
+
 int ElfCheckIfUseTCMallocMinimal(elfheader_t* h)
 {
     if(!h)
@@ -889,8 +825,8 @@ int ElfCheckIfUseTCMallocMinimal(elfheader_t* h)
         }
     return 0;
 }
-#if 0
-void RunElfInit(elfheader_t* h, x86emu_t *emu)
+
+void RunElfInit(elfheader_t* h, x64emu_t *emu)
 {
     if(!h || h->init_done)
         return;
@@ -924,7 +860,7 @@ void RunElfInit(elfheader_t* h, x86emu_t *emu)
 }
 
 EXPORTDYN
-void RunDeferedElfInit(x86emu_t *emu)
+void RunDeferedElfInit(x64emu_t *emu)
 {
     box64context_t* context = GetEmuContext(emu);
     if(!context->deferedInit)
@@ -939,7 +875,7 @@ void RunDeferedElfInit(x86emu_t *emu)
     context->deferedInitCap = context->deferedInitSz = 0;
 }
 
-void RunElfFini(elfheader_t* h, x86emu_t *emu)
+void RunElfFini(elfheader_t* h, x64emu_t *emu)
 {
     if(!h || h->fini_done)
         return;
@@ -1110,7 +1046,7 @@ typedef struct my_dl_phdr_info_s {
     int             dlpi_phnum;
 } my_dl_phdr_info_t;
 
-static int dl_iterate_phdr_callback(x86emu_t *emu, void* F, my_dl_phdr_info_t *info, size_t size, void* data)
+static int dl_iterate_phdr_callback(x64emu_t *emu, void* F, my_dl_phdr_info_t *info, size_t size, void* data)
 {
     int ret = RunFunctionWithEmu(emu, 0, (uintptr_t)F, 3, info, size, data);
     return ret;
@@ -1151,7 +1087,7 @@ static void* find_dl_iterate_phdr_Fct(void* fct)
 }
 #undef SUPER
 
-EXPORT int my_dl_iterate_phdr(x86emu_t *emu, void* F, void *data) {
+EXPORT int my_dl_iterate_phdr(x64emu_t *emu, void* F, void *data) {
     printf_log(LOG_INFO, "Warning: call to partially implemented dl_iterate_phdr(%p, %p)\n", F, data);
     box64context_t *context = GetEmuContext(emu);
     const char* empty = "";
@@ -1217,7 +1153,7 @@ void CreateMemorymapFile(box64context_t* context, int fd)
     for (int i=0; i<h->numPHEntries; ++i) {
         if (h->PHEntries[i].p_memsz == 0) continue;
 
-        sprintf(buff, "%08x-%08x %c%c%c%c %08x %02x:%02x %ld %s\n", (uintptr_t)h->PHEntries[i].p_vaddr + h->delta,
+        sprintf(buff, "%016lx-%016lx %c%c%c%c %016lx %02x:%02x %ld %s\n", (uintptr_t)h->PHEntries[i].p_vaddr + h->delta,
             (uintptr_t)h->PHEntries[i].p_vaddr + h->PHEntries[i].p_memsz + h->delta,
             (h->PHEntries[i].p_type & (PF_R|PF_X) ? 'r':'-'), (h->PHEntries[i].p_type & PF_W ? 'w':'-'),
             (h->PHEntries[i].p_type & PF_X ? 'x':'-'), 'p', // p for private or s for shared
@@ -1236,12 +1172,12 @@ void ElfAttachLib(elfheader_t* head, library_t* lib)
 }
 
 uintptr_t pltResolver = ~0;
-EXPORT void PltResolver(x86emu_t* emu)
+EXPORT void PltResolver(x64emu_t* emu)
 {
-    uintptr_t addr = Pop32(emu);
-    int slot = (int)Pop32(emu);
+    uintptr_t addr = Pop64(emu);
+    int slot = (int)Pop64(emu);
     elfheader_t *h = (elfheader_t*)addr;
-    printf_log(LOG_DEBUG, "PltResolver: Addr=%p, Slot=%d Return=%p: elf is %s\n", (void*)addr, slot, *(void**)(R_ESP), h->name);
+    printf_log(LOG_DEBUG, "PltResolver: Addr=%p, Slot=%d Return=%p: elf is %s\n", (void*)addr, slot, *(void**)(R_RSP), h->name);
 
     Elf64_Rel * rel = (Elf64_Rel *)(h->jmprel + h->delta + slot);
 
@@ -1260,12 +1196,12 @@ EXPORT void PltResolver(x86emu_t* emu)
         GetGlobalSymbolStartEnd(my_context->maplib, symname, &offs, &end);
 
     if (!offs) {
-        printf_log(LOG_NONE, "Error: PltReolver: Symbol %s not found, cannot apply R_386_JMP_SLOT @%p (%p) in %s\n", symname, p, *(void**)p, h->name);
+        printf_log(LOG_NONE, "Error: PltReolver: Symbol %s not found, cannot apply R_X86_64_JUMP_SLOT @%p (%p) in %s\n", symname, p, *(void**)p, h->name);
         emu->quit = 1;
         return;
     } else {
         if(p) {
-            printf_log(LOG_DEBUG, "PltReolver: Apply %s R_386_JMP_SLOT @%p with sym=%s (%p -> %p / %s)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)offs, ElfName(FindElfAddress(my_context, offs)));
+            printf_log(LOG_DEBUG, "PltReolver: Apply %s R_X86_64_JUMP_SLOT @%p with sym=%s (%p -> %p / %s)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)offs, ElfName(FindElfAddress(my_context, offs)));
             *p = offs;
         } else {
             printf_log(LOG_NONE, "PltReolver: Warning, Symbol %s found, but Jump Slot Offset is NULL \n", symname);
@@ -1273,6 +1209,5 @@ EXPORT void PltResolver(x86emu_t* emu)
     }
 
     // jmp to function
-    R_EIP = offs;
+    R_RIP = offs;
 }
-#endif
\ No newline at end of file
diff --git a/src/elfs/elfloader_private.h b/src/elfs/elfloader_private.h
index 8de85633..8e95175d 100755
--- a/src/elfs/elfloader_private.h
+++ b/src/elfs/elfloader_private.h
@@ -1,12 +1,12 @@
 #ifndef __ELFLOADER_PRIVATE_H_
 #define __ELFLOADER_PRIVATE_H_
 
-//#ifdef DYNAREC
-//typedef struct dynablocklist_s dynablocklist_t;
-//#endif
+#ifdef DYNAREC
+typedef struct dynablocklist_s dynablocklist_t;
+#endif
 
-//typedef struct library_s library_t;
-//typedef struct needed_libs_s needed_libs_t;
+typedef struct library_s library_t;
+typedef struct needed_libs_s needed_libs_t;
 
 #include <pthread.h>
 
@@ -82,8 +82,8 @@ struct elfheader_s {
     uint64_t*   multiblock_size;
     int         multiblock_n;
 
-    //library_t   *lib;
-    //needed_libs_t *neededlibs;
+    library_t   *lib;
+    needed_libs_t *neededlibs;
 };
 
 #define R_X86_64_NONE		0	/* No reloc */
diff --git a/src/emu/x64emu.c b/src/emu/x64emu.c
index 3ce6b63e..ea3cc138 100755
--- a/src/emu/x64emu.c
+++ b/src/emu/x64emu.c
@@ -14,8 +14,8 @@
 #include "box64context.h"
 #include "x64run.h"
 #include "x64run_private.h"
-//#include "callback.h"
-//#include "bridge.h"
+#include "callback.h"
+#include "bridge.h"
 #ifdef DYNAREC
 #include "custommem.h"
 #endif
@@ -43,16 +43,16 @@ uint32_t* GetParityTab()
     return x86emu_parity_tab;
 }
 
-//void PushExit(x64emu_t* emu)
-//{
-//    uintptr_t endMarker = AddCheckBridge(my_context->system, NULL, NULL, 0);
-//    Push(emu, endMarker);
-//}
+void PushExit(x64emu_t* emu)
+{
+    uintptr_t endMarker = AddCheckBridge(my_context->system, NULL, NULL, 0);
+    Push(emu, endMarker);
+}
 
-//void* GetExit()
-//{
-//    return (void*)AddCheckBridge(my_context->system, NULL, NULL, 0);
-//}
+void* GetExit()
+{
+    return (void*)AddCheckBridge(my_context->system, NULL, NULL, 0);
+}
 
 static void internalX64Setup(x64emu_t* emu, box64context_t *context, uintptr_t start, uintptr_t stack, int stacksize, int ownstack)
 {
@@ -403,31 +403,31 @@ void UnimpOpcode(x64emu_t* emu)
     emu->error |= ERR_UNIMPL;
 }
 
-//void EmuCall(x64emu_t* emu, uintptr_t addr)
-//{
-//    uint64_t old_rsp = R_RSP;
-//    uint64_t old_rbx = R_RBX;
-//    uint64_t old_rdi = R_RDI;
-//    uint64_t old_rsi = R_RSI;
-//    uint64_t old_rbp = R_RBP;
-//    uint64_t old_rip = R_RIP;
-//    PushExit(emu);
-//    R_RIP = addr;
-//    emu->df = d_none;
-//    Run(emu, 0);
-//    emu->quit = 0;  // reset Quit flags...
-//    emu->df = d_none;
-//    if(emu->quitonlongjmp && emu->longjmp) {
-//        emu->longjmp = 0;   // don't change anything because of the longjmp
-//    } else {
-//        R_RBX = old_ebx;
-//        R_RDI = old_edi;
-//        R_RSI = old_esi;
-//        R_RBP = old_ebp;
-//        R_RSP = old_esp;
-//        R_RIP = old_eip;  // and set back instruction pointer
-//    }
-//}
+void EmuCall(x64emu_t* emu, uintptr_t addr)
+{
+    uint64_t old_rsp = R_RSP;
+    uint64_t old_rbx = R_RBX;
+    uint64_t old_rdi = R_RDI;
+    uint64_t old_rsi = R_RSI;
+    uint64_t old_rbp = R_RBP;
+    uint64_t old_rip = R_RIP;
+    PushExit(emu);
+    R_RIP = addr;
+    emu->df = d_none;
+    Run(emu, 0);
+    emu->quit = 0;  // reset Quit flags...
+    emu->df = d_none;
+    if(emu->quitonlongjmp && emu->longjmp) {
+        emu->longjmp = 0;   // don't change anything because of the longjmp
+    } else {
+        R_RBX = old_rbx;
+        R_RDI = old_rdi;
+        R_RSI = old_rsi;
+        R_RBP = old_rbp;
+        R_RSP = old_rsp;
+        R_RIP = old_rip;  // and set back instruction pointer
+    }
+}
 
 uint64_t ReadTSC(x64emu_t* emu)
 {
diff --git a/src/emu/x64run.c b/src/emu/x64run.c
new file mode 100755
index 00000000..39533d8b
--- /dev/null
+++ b/src/emu/x64run.c
@@ -0,0 +1,118 @@
+#define _GNU_SOURCE
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "debug.h"
+#include "box64stack.h"
+#include "x64emu.h"
+#include "x64run.h"
+#include "x64emu_private.h"
+#include "x64run_private.h"
+//#include "x64primop.h"
+#include "x64trace.h"
+#include "x87emu_private.h"
+#include "box64context.h"
+//#include "my_cpuid.h"
+#include "bridge.h"
+//#include "signals.h"
+#ifdef DYNAREC
+#include "../dynarec/arm_lock_helper.h"
+#endif
+
+int my_setcontext(x64emu_t* emu, void* ucp);
+
+int Run(x64emu_t *emu, int step)
+{
+    uint8_t opcode;
+    uint8_t nextop;
+    reg64_t *oped;
+    uint8_t tmp8u, tmp8u2;
+    int8_t tmp8s;
+    uint16_t tmp16u, tmp16u2;
+    int16_t tmp16s;
+    uint32_t tmp32u, tmp32u2, tmp32u3;
+    uint64_t tmp64u, tmp64u2, tmp64u3;
+    int32_t tmp32s, tmp32s2;
+    int64_t tmp64s, tmp64s2;
+    uintptr_t ip;
+    double d;
+    float f;
+    int64_t ll;
+    sse_regs_t *opex, eax1;
+    mmx_regs_t *opem, eam1;
+
+    if(emu->quit)
+        return 0;
+
+    //ref opcode: http://ref.x64asm.net/geek32.html#xA1
+    printf_log(LOG_DEBUG, "Run X86 (%p), RIP=%p, Stack=%p\n", emu, (void*)R_RIP, emu->context->stack);
+#define F8      *(uint8_t*)(ip++)
+#define F8S     *(int8_t*)(ip++)
+#define F16     *(uint16_t*)(ip+=2, ip-2)
+#define F32     *(uint32_t*)(ip+=4, ip-4)
+#define F32S    *(int32_t*)(ip+=4, ip-4)
+#define PK(a)   *(uint8_t*)(ip+a)
+#ifdef DYNAREC
+#define STEP if(step) goto stepout;
+#else
+#define STEP
+#endif
+
+x64emurun:
+    ip = R_RIP;
+
+//#include "modrm.h"
+    while(1) {
+#ifdef HAVE_TRACE
+        __builtin_prefetch((void*)ip, 0, 0); 
+        emu->prev2_ip = emu->prev_ip;
+        emu->prev_ip = R_RIP;
+        R_RIP=ip;
+        if(my_context->dec && (
+            (trace_end == 0) 
+            || ((ip >= trace_start) && (ip < trace_end))) )
+                PrintTrace(emu, ip, 0);
+#endif
+
+        opcode = F8;
+        switch(opcode) {
+
+        default:
+            emu->old_ip = R_RIP;
+            R_RIP = ip;
+            UnimpOpcode(emu);
+            goto fini;
+        }
+    }
+#ifdef DYNAREC
+stepout:
+    emu->old_ip = R_RIP;
+    R_RIP = ip;
+    return 0;
+#endif
+
+fini:
+    // fork handling
+//    if(emu->fork) {
+//        if(step)
+//            return 0;
+//        int forktype = emu->fork;
+//        emu->quit = 0;
+//        emu->fork = 0;
+//        emu = x64emu_fork(emu, forktype);
+//        goto x64emurun;
+//    }
+    // setcontext handling
+//    else if(emu->uc_link) {
+//        emu->quit = 0;
+//        my_setcontext(emu, emu->uc_link);
+//        goto x64emurun;
+//    }
+    return 0;
+}
diff --git a/src/emu/x64run_private.c b/src/emu/x64run_private.c
new file mode 100755
index 00000000..5ceae0a3
--- /dev/null
+++ b/src/emu/x64run_private.c
@@ -0,0 +1,787 @@
+#define _GNU_SOURCE         /* See feature_test_macros(7) */
+#include <dlfcn.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_TRACE
+#include <unistd.h>
+#include <sys/syscall.h>
+#endif
+
+#include "debug.h"
+#include "box64stack.h"
+#include "x64emu.h"
+#include "x64run.h"
+#include "x64run_private.h"
+#include "x64emu_private.h"
+#include "box64context.h"
+#include "x64run.h"
+#include "librarian.h"
+#include "elfloader.h"
+#ifdef HAVE_TRACE
+#include "x64trace.h"
+#endif
+#include "x64tls.h"
+
+#define PARITY2(x)   (((emu->x64emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
+#define PARITY(x)   (PARITY2((x)>>32)^PARITY2((x)&0xffffffff))
+#define XOR2(x) 	(((x) ^ ((x)>>1)) & 0x1)
+
+int32_t EXPORT my___libc_start_main(x64emu_t* emu, int *(main) (int, char * *, char * *), int argc, char * * ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (* stack_end))
+{
+    //TODO: register rtld_fini
+    //TODO: register fini
+    // let's cheat and set all args...
+    Push(emu, (uint64_t)my_context->envv);
+    Push(emu, (uint64_t)my_context->argv);
+    Push(emu, (uint64_t)my_context->argc);
+    if(init) {
+        PushExit(emu);
+        R_RIP=(uint64_t)*init;
+        printf_log(LOG_DEBUG, "Calling init(%p) from __libc_start_main\n", *init);
+        DynaRun(emu);
+        if(emu->error)  // any error, don't bother with more
+            return 0;
+        emu->quit = 0;
+    }
+    printf_log(LOG_DEBUG, "Transfert to main(%d, %p, %p)=>%p from __libc_start_main\n", my_context->argc, my_context->argv, my_context->envv, main);
+    // call main and finish
+    PushExit(emu);
+    R_RIP=(uint64_t)main;
+#ifdef DYNAREC
+    DynaRun(emu);
+#endif
+    return 0;
+}
+
+const char* GetNativeName(void* p)
+{
+    static char buff[500] = {0};
+    Dl_info info;
+    if(dladdr(p, &info)==0) {
+        const char *ret = GetNameOffset(my_context->maplib, p);
+        if(ret)
+            return ret;
+        sprintf(buff, "%s(%p)", "???", p);
+        return buff;
+    } else {
+        if(info.dli_sname) {
+            strcpy(buff, info.dli_sname);
+            if(info.dli_fname) {
+                strcat(buff, " ("); strcat(buff, info.dli_fname); strcat(buff, ")");
+            }
+        } else {
+            sprintf(buff, "%s(%s/%p)", "???", info.dli_fname, p);
+            return buff;
+        }
+    }
+    return buff;
+}
+#if 0
+void UpdateFlags(x64emu_t *emu)
+{
+    uint32_t cc;
+    uint32_t lo, hi;
+    uint32_t bc;
+    uint32_t cnt;
+
+    switch(emu->df) {
+        case d_none:
+            return;
+        case d_add8:
+            CONDITIONAL_SET_FLAG(emu->res & 0x100, F_CF);
+            CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+
+            cc = (emu->op1 & emu->op2) | ((~emu->res) & (emu->op1 | emu->op2));
+            CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
+            CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+            break;
+        case d_add16:
+            CONDITIONAL_SET_FLAG(emu->res & 0x10000, F_CF);
+            CONDITIONAL_SET_FLAG((emu->res & 0xffff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            cc = (emu->op1 & emu->op2) | ((~emu->res) & (emu->op1 | emu->op2));
+            CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
+            CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+            break;
+        case d_add32:
+            lo = (emu->op2 & 0xFFFF) + (emu->op1 & 0xFFFF);
+            hi = (lo >> 16) + (emu->op2 >> 16) + (emu->op1 >> 16);
+            CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
+            CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            cc = (emu->op1 & emu->op2) | ((~emu->res) & (emu->op1 | emu->op2));
+            CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
+            CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+            break;
+        case d_and8:
+            CLEAR_FLAG(F_OF);
+            CLEAR_FLAG(F_CF);
+            CLEAR_FLAG(F_AF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
+            CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            break;
+        case d_and16:
+            CLEAR_FLAG(F_OF);
+            CLEAR_FLAG(F_CF);
+            CLEAR_FLAG(F_AF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
+            CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            break;
+        case d_and32:
+            CLEAR_FLAG(F_OF);
+            CLEAR_FLAG(F_CF);
+            CLEAR_FLAG(F_AF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
+            CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            break;
+        case d_dec8:
+            CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
+            CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            bc = (emu->res & (~emu->op1 | 1)) | (~emu->op1 & 1);
+            CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
+            CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+            break;
+        case d_dec16:
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
+            CONDITIONAL_SET_FLAG((emu->res & 0xffff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            bc = (emu->res & (~emu->op1 | 1)) | (~emu->op1 & 1);
+            CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
+            CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+            break;
+        case d_dec32:
+            CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
+            CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            bc = (emu->res & (~emu->op1 | 1)) | (~emu->op1 & 1);
+            CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
+            CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+            break;
+        case d_inc8:
+            CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            cc = ((1 & emu->op1) | (~emu->res)) & (1 | emu->op1);
+            CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
+            CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+            break;
+        case d_inc16:
+            CONDITIONAL_SET_FLAG((emu->res & 0xffff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            cc = (1 & emu->op1) | ((~emu->res) & (1 | emu->op1));
+            CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
+            CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+            break;
+        case d_inc32:
+            CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            cc = (1 & emu->op1) | ((~emu->res) & (1 | emu->op1));
+            CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
+            CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+            break;
+        case d_imul8:
+            lo = emu->res & 0xff;
+            hi = (emu->res>>8)&0xff;
+            if (((lo & 0x80) == 0 && hi == 0x00) ||
+                ((lo & 0x80) != 0 && hi == 0xFF)) {
+                CLEAR_FLAG(F_CF);
+                CLEAR_FLAG(F_OF);
+            } else {
+                SET_FLAG(F_CF);
+                SET_FLAG(F_OF);
+            }
+            CONDITIONAL_SET_FLAG(PARITY(lo & 0xff), F_PF);
+            break;
+        case d_imul16:
+            lo = (uint16_t)emu->res;
+            hi = (uint16_t)(emu->res >> 16);
+            if (((lo & 0x8000) == 0 && hi == 0x00) ||
+                ((lo & 0x8000) != 0 && hi == 0xFFFF)) {
+                CLEAR_FLAG(F_CF);
+                CLEAR_FLAG(F_OF);
+            } else {
+                SET_FLAG(F_CF);
+                SET_FLAG(F_OF);
+            }
+            CONDITIONAL_SET_FLAG(PARITY(lo & 0xff), F_PF);
+            break;
+        case d_imul32:
+            if (((emu->res & 0x80000000) == 0 && emu->op1 == 0x00) ||
+                ((emu->res & 0x80000000) != 0 && emu->op1 == 0xFFFFFFFF)) {
+                CLEAR_FLAG(F_CF);
+                CLEAR_FLAG(F_OF);
+            } else {
+                SET_FLAG(F_CF);
+                SET_FLAG(F_OF);
+            }
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            break;
+        case d_mul8:
+            lo = emu->res & 0xff;
+            hi = (emu->res>>8)&0xff;
+            if (hi == 0) {
+                CLEAR_FLAG(F_CF);
+                CLEAR_FLAG(F_OF);
+            } else {
+                SET_FLAG(F_CF);
+                SET_FLAG(F_OF);
+            }
+            CONDITIONAL_SET_FLAG(PARITY(lo & 0xff), F_PF);
+            break;
+        case d_mul16:
+            lo = (uint16_t)emu->res;
+            hi = (uint16_t)(emu->res >> 16);
+            if (hi == 0) {
+                CLEAR_FLAG(F_CF);
+                CLEAR_FLAG(F_OF);
+            } else {
+                SET_FLAG(F_CF);
+                SET_FLAG(F_OF);
+            }
+            CONDITIONAL_SET_FLAG(PARITY(lo & 0xff), F_PF);
+            break;
+        case d_mul32:
+            if (emu->op1 == 0) {
+                CLEAR_FLAG(F_CF);
+                CLEAR_FLAG(F_OF);
+            } else {
+                SET_FLAG(F_CF);
+                SET_FLAG(F_OF);
+            }
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            break;
+        case d_or8:
+            CLEAR_FLAG(F_OF);
+            CLEAR_FLAG(F_CF);
+            CLEAR_FLAG(F_AF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
+            CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            break;
+        case d_or16:
+            CLEAR_FLAG(F_OF);
+            CLEAR_FLAG(F_CF);
+            CLEAR_FLAG(F_AF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
+            CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            break;
+        case d_or32:
+            CLEAR_FLAG(F_OF);
+            CLEAR_FLAG(F_CF);
+            CLEAR_FLAG(F_AF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
+            CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            break;
+        case d_neg8:
+            CONDITIONAL_SET_FLAG(emu->op1 != 0, F_CF);
+            CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            bc = emu->res | emu->op1;
+            CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
+            CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+            break;
+        case d_neg16:
+            CONDITIONAL_SET_FLAG(emu->op1 != 0, F_CF);
+            CONDITIONAL_SET_FLAG((emu->res & 0xffff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            bc = emu->res | emu->op1;
+            CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
+            CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+            break;
+        case d_neg32:
+            CONDITIONAL_SET_FLAG(emu->op1 != 0, F_CF);
+            CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            bc = emu->res | emu->op1;
+            CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
+            CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+            break;
+        case d_shl8:
+            if (emu->op2 < 8) {
+                cnt = emu->op2 % 8;
+                if (cnt > 0) {
+                    cc = emu->op1 & (1 << (8 - cnt));
+                    CONDITIONAL_SET_FLAG(cc, F_CF);
+                    CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
+                    CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
+                    CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+                }
+                if (cnt == 1) {
+                    CONDITIONAL_SET_FLAG((((emu->res & 0x80) == 0x80) ^(ACCESS_FLAG(F_CF) != 0)), F_OF);
+                } else {
+                    CLEAR_FLAG(F_OF);
+                }
+            } else {
+                CONDITIONAL_SET_FLAG((emu->op1 << (emu->op2-1)) & 0x80, F_CF);
+                CLEAR_FLAG(F_OF);
+                CLEAR_FLAG(F_SF);
+                SET_FLAG(F_PF);
+                SET_FLAG(F_ZF);
+            }
+            break;
+        case d_shl16:
+            if (emu->op2 < 16) {
+                cnt = emu->op2 % 16;
+                if (cnt > 0) {
+                    cc = emu->op1 & (1 << (16 - cnt));
+                    CONDITIONAL_SET_FLAG(cc, F_CF);
+                    CONDITIONAL_SET_FLAG((emu->res & 0xffff) == 0, F_ZF);
+                    CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
+                    CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+                }
+                if (cnt == 1) {
+                    CONDITIONAL_SET_FLAG(((!!(emu->res & 0x8000)) ^(ACCESS_FLAG(F_CF) != 0)), F_OF);
+                } else {
+                    CLEAR_FLAG(F_OF);
+                }
+            } else {
+                CONDITIONAL_SET_FLAG((emu->op1 << (emu->op2-1)) & 0x8000, F_CF);
+                CLEAR_FLAG(F_OF);
+                CLEAR_FLAG(F_SF);
+                SET_FLAG(F_PF);
+                SET_FLAG(F_ZF);
+            }
+            break;
+        case d_shl32:
+            if (emu->op2 > 0) {
+                cc = emu->op1 & (1 << (32 - emu->op2));
+                CONDITIONAL_SET_FLAG(cc, F_CF);
+                CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
+                CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
+                CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            }
+            if (emu->op2 == 1) {
+                CONDITIONAL_SET_FLAG(((!!(emu->res & 0x80000000)) ^
+                                        (ACCESS_FLAG(F_CF) != 0)), F_OF);
+            } else {
+                CLEAR_FLAG(F_OF);
+            }
+            break;
+        case d_sar8:
+            if (emu->op2 < 8) {
+                if(emu->op2) {
+                    cc = emu->op1 & (1 << (emu->op2 - 1));
+                    CONDITIONAL_SET_FLAG(cc, F_CF);
+                    CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
+                    CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+                    CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
+                }
+            } else {
+                if (emu->op1&0x80) {
+                    SET_FLAG(F_CF);
+                    CLEAR_FLAG(F_ZF);
+                    SET_FLAG(F_SF);
+                    SET_FLAG(F_PF);
+                } else {
+                    CLEAR_FLAG(F_CF);
+                    SET_FLAG(F_ZF);
+                    CLEAR_FLAG(F_SF);
+                    SET_FLAG(F_PF);
+                }
+            }
+            break;
+        case d_sar16:
+            if (emu->op2 < 16) {
+                if(emu->op2) {
+                    cc = emu->op1 & (1 << (emu->op2 - 1));
+                    CONDITIONAL_SET_FLAG(cc, F_CF);
+                    CONDITIONAL_SET_FLAG((emu->res & 0xffff) == 0, F_ZF);
+                    CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
+                    CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+                }
+            } else {
+                if (emu->op1&0x8000) {
+                    SET_FLAG(F_CF);
+                    CLEAR_FLAG(F_ZF);
+                    SET_FLAG(F_SF);
+                    SET_FLAG(F_PF);
+                } else {
+                    CLEAR_FLAG(F_CF);
+                    SET_FLAG(F_ZF);
+                    CLEAR_FLAG(F_SF);
+                    SET_FLAG(F_PF);
+                }
+            }
+            break;
+        case d_sar32:
+            if(emu->op2) {
+                cc = emu->op1 & (1 << (emu->op2 - 1));
+                CONDITIONAL_SET_FLAG(cc, F_CF);
+                CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
+                CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
+                CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            }
+            break;
+        case d_shr8:
+            if (emu->op2 < 8) {
+                cnt = emu->op2 % 8;
+                if (cnt > 0) {
+                    cc = emu->op1 & (1 << (cnt - 1));
+                    CONDITIONAL_SET_FLAG(cc, F_CF);
+                    CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
+                    CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
+                    CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+                }
+                if (cnt == 1) {
+                    CONDITIONAL_SET_FLAG(XOR2(emu->res >> 6), F_OF);
+                }
+            } else {
+                CONDITIONAL_SET_FLAG((emu->op1 >> (emu->op2-1)) & 0x1, F_CF);
+                CLEAR_FLAG(F_SF);
+                SET_FLAG(F_PF);
+                SET_FLAG(F_ZF);
+            }
+            break;
+        case d_shr16:
+            if (emu->op2 < 16) {
+                cnt = emu->op2 % 16;
+                if (cnt > 0) {
+                    cc = emu->op1 & (1 << (cnt - 1));
+                    CONDITIONAL_SET_FLAG(cc, F_CF);
+                    CONDITIONAL_SET_FLAG((emu->res & 0xffff) == 0, F_ZF);
+                    CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
+                    CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+                }
+                if (cnt == 1) {
+                    CONDITIONAL_SET_FLAG(XOR2(emu->res >> 14), F_OF);
+                }
+            } else {
+                CLEAR_FLAG(F_CF);
+                SET_FLAG(F_ZF);
+                CLEAR_FLAG(F_SF);
+                SET_FLAG(F_PF);
+            }
+            break;
+        case d_shr32:
+            cnt = emu->op2;
+            if (cnt > 0) {
+                cc = emu->op1 & (1 << (cnt - 1));
+                CONDITIONAL_SET_FLAG(cc, F_CF);
+                CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
+                CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
+                CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            }
+            if (cnt == 1) {
+                CONDITIONAL_SET_FLAG(XOR2(emu->res >> 30), F_OF);
+            }
+            break;
+        case d_sub8:
+            CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
+            CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
+            CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
+            CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
+            CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+            break;
+        case d_sub16:
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
+            CONDITIONAL_SET_FLAG((emu->res & 0xffff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
+            CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
+            CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
+            CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+            break;
+        case d_sub32:
+            CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
+            CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
+            CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
+            CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
+            CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+            break;
+        case d_xor8:
+            CLEAR_FLAG(F_OF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
+            CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            CLEAR_FLAG(F_CF);
+            CLEAR_FLAG(F_AF);
+            break;
+        case d_xor16:
+            CLEAR_FLAG(F_OF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
+            CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            CLEAR_FLAG(F_CF);
+            CLEAR_FLAG(F_AF);
+            break;
+        case d_xor32:
+            CLEAR_FLAG(F_OF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
+            CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            CLEAR_FLAG(F_CF);
+            CLEAR_FLAG(F_AF);
+            break;
+        case d_cmp8:
+            CLEAR_FLAG(F_CF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
+            CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
+            CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
+            CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
+            CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+            break;
+        case d_cmp16:
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
+            CONDITIONAL_SET_FLAG((emu->res & 0xffff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
+            CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
+            CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
+            CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+            break;
+        case d_cmp32:
+        	CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
+        	CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
+        	CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+        	bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
+        	CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
+        	CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
+        	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+            break;
+        case d_tst8:
+        	CLEAR_FLAG(F_OF);
+        	CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
+        	CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
+        	CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+        	CLEAR_FLAG(F_CF);
+            break;
+        case d_tst16:
+            CLEAR_FLAG(F_OF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
+            CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            CLEAR_FLAG(F_CF);
+            break;
+        case d_tst32:
+        	CLEAR_FLAG(F_OF);
+        	CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
+        	CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
+        	CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+        	CLEAR_FLAG(F_CF);
+            break;
+        case d_adc8:
+            CONDITIONAL_SET_FLAG(emu->res & 0x100, F_CF);
+            CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            cc = (emu->op1 & emu->op2) | ((~emu->res) & (emu->op1 | emu->op2));
+            CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
+            CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+            break;
+        case d_adc16:
+            CONDITIONAL_SET_FLAG(emu->res & 0x10000, F_CF);
+            CONDITIONAL_SET_FLAG((emu->res & 0xffff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            cc = (emu->op1 & emu->op2) | ((~emu->res) & (emu->op1 | emu->op2));
+            CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
+            CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+            break;
+        case d_adc32:
+            if(emu->res == (emu->op1+emu->op2)) {
+                lo = (emu->op1 & 0xFFFF) + (emu->op2 & 0xFFFF);
+            } else {
+                lo = 1 + (emu->op1 & 0xFFFF) + (emu->op2 & 0xFFFF);
+            }
+            hi = (lo >> 16) + (emu->op1 >> 16) + (emu->op2 >> 16);
+            CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
+            CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            cc = (emu->op2 & emu->op1) | ((~emu->res) & (emu->op2 | emu->op1));
+            CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
+            CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+            break;
+        case d_sbb8:
+            CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
+            CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
+            CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
+            CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
+            CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+            break;
+        case d_sbb16:
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
+            CONDITIONAL_SET_FLAG((emu->res & 0xffff) == 0, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
+            CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
+            CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
+            CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+            break;
+        case d_sbb32:
+            CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
+            CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
+            CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
+            bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
+            CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
+            CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
+            CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+            break;
+        case d_rol8:
+            if(emu->op2 == 1) {
+                CONDITIONAL_SET_FLAG((emu->res + (emu->res >> 7)) & 1, F_OF);
+            }
+        	CONDITIONAL_SET_FLAG(emu->res & 0x1, F_CF);
+            break;
+        case d_rol16:
+            if(emu->op2 == 1) {
+                CONDITIONAL_SET_FLAG((emu->res + (emu->res >> 15)) & 1, F_OF);
+            }
+        	CONDITIONAL_SET_FLAG(emu->res & 0x1, F_CF);
+            break;
+        case d_rol32:
+            if(emu->op2 == 1) {
+                CONDITIONAL_SET_FLAG((emu->res + (emu->res >> 31)) & 1, F_OF);
+            }
+        	CONDITIONAL_SET_FLAG(emu->res & 0x1, F_CF);
+            break;
+        case d_ror8:
+            if(emu->op2 == 1) {
+                CONDITIONAL_SET_FLAG(XOR2(emu->res >> 6), F_OF);
+            }
+            CONDITIONAL_SET_FLAG(emu->res & (1 << 7), F_CF);
+            break;
+        case d_ror16:
+            if(emu->op2 == 1) {
+                CONDITIONAL_SET_FLAG(XOR2(emu->res >> 14), F_OF);
+            }
+            CONDITIONAL_SET_FLAG(emu->res & (1 << 15), F_CF);
+            break;
+        case d_ror32:
+            if(emu->op2 == 1) {
+                CONDITIONAL_SET_FLAG(XOR2(emu->res >> 30), F_OF);
+            }
+            CONDITIONAL_SET_FLAG(emu->res & (1 << 31), F_CF);
+            break;
+
+        case d_unknown:
+            printf_log(LOG_NONE, "Box86: %p trying to evaluate Unknown defered Flags\n", (void*)R_RIP);
+            break;
+    }
+    RESET_FLAGS(emu);
+}
+#endif
+
+uintptr_t GetSegmentBaseEmu(x64emu_t* emu, int seg)
+{
+    if(emu->segs_serial[seg] != emu->context->sel_serial) {
+        emu->segs_offs[seg] = (uintptr_t)GetSegmentBase(emu->segs[seg]);
+        emu->segs_serial[seg] = emu->context->sel_serial;
+    }
+    return emu->segs_offs[seg];
+}
+
+
+const char* getAddrFunctionName(uintptr_t addr)
+{
+    static char ret[1000];
+    uint32_t sz = 0;
+    uintptr_t start = 0;
+    const char* symbname = FindNearestSymbolName(FindElfAddress(my_context, addr), (void*)addr, &start, &sz);
+    if(symbname && addr>=start && (addr<(start+sz) || !sz)) {
+        if(addr==start)
+            sprintf(ret, "%s/%s", ElfName(FindElfAddress(my_context, addr)), symbname);
+        else
+            sprintf(ret, "%s/%s + %ld", ElfName(FindElfAddress(my_context, addr)), symbname, addr - start);
+    } else
+        sprintf(ret, "???");
+    return ret;
+}
+
+void printFunctionAddr(uintptr_t nextaddr, const char* text)
+{
+    uint32_t sz = 0;
+    uintptr_t start = 0;
+    const char* symbname = FindNearestSymbolName(FindElfAddress(my_context, nextaddr), (void*)nextaddr, &start, &sz);
+    if(symbname && nextaddr>=start && (nextaddr<(start+sz) || !sz)) {
+        if(nextaddr==start)
+            printf_log(LOG_NONE, " (%s%s/%s)", text, ElfName(FindElfAddress(my_context, nextaddr)), symbname);
+        else
+            printf_log(LOG_NONE, " (%s%s/%s + %ld)", text, ElfName(FindElfAddress(my_context, nextaddr)), symbname, nextaddr - start);
+    }
+}
+
+#ifdef HAVE_TRACE
+extern uint64_t start_cnt;
+#define PK(a)   (*(uint8_t*)(ip+a))
+#define PK32(a)   (*(int32_t*)((uint8_t*)(ip+a)))
+#define PK64(a)   (*(int64_t*)((uint8_t*)(ip+a)))
+
+void PrintTrace(x64emu_t* emu, uintptr_t ip, int dynarec)
+{
+    if(start_cnt) --start_cnt;
+    if(!start_cnt && my_context->dec && (
+            (trace_end == 0) 
+            || ((ip >= trace_start) && (ip < trace_end))) ) {
+        int tid = syscall(SYS_gettid);
+        pthread_mutex_lock(&my_context->mutex_trace);
+#ifdef DYNAREC
+        if((my_context->trace_tid != tid) || (my_context->trace_dynarec!=dynarec)) {
+            printf_log(LOG_NONE, "Thread %04d| (%s) |\n", tid, dynarec?"dyn":"int");
+            my_context->trace_tid = tid;
+            my_context->trace_dynarec = dynarec;
+        }
+#else
+        if(my_context->trace_tid != tid) {
+            printf_log(LOG_NONE, "Thread %04d|\n", tid);
+            my_context->trace_tid = tid;
+        }
+#endif
+        printf_log(LOG_NONE, "%s", DumpCPURegs(emu, ip));
+        if(PK(0)==0xcc && PK(1)=='S' && PK(2)=='C') {
+            uint64_t a = *(uint64_t*)(ip+3);
+            if(a==0) {
+                printf_log(LOG_NONE, "%p: Exit x86emu\n", (void*)ip);
+            } else {
+                printf_log(LOG_NONE, "%p: Native call to %p => %s\n", (void*)ip, (void*)a, GetNativeName(*(void**)(ip+7)));
+            }
+        } else {
+            printf_log(LOG_NONE, "%s", DecodeX64Trace(my_context->dec, ip));
+            uint8_t peek = PK(0);
+            if(peek==0xC3 || peek==0xC2) {
+                printf_log(LOG_NONE, " => %p", *(void**)(R_RSP));
+                printFunctionAddr(*(uintptr_t*)(R_RSP), "=> ");
+            } else if(peek==0x55) {
+                printf_log(LOG_NONE, " => STACK_TOP: %p", *(void**)(R_RSP));
+                printFunctionAddr(ip, "here: ");
+            } else if(peek==0xE8) { // Call
+                uintptr_t nextaddr = ip + 5 + PK64(1);
+                printFunctionAddr(nextaddr, "=> ");
+            } else if(peek==0xFF) {
+                if(PK(1)==0x25) {
+                    uintptr_t nextaddr = ip + 6 + PK64(2);
+                    printFunctionAddr(nextaddr, "=> ");
+                }
+            }
+            printf_log(LOG_NONE, "\n");
+        }
+        pthread_mutex_unlock(&my_context->mutex_trace);
+    }
+}
+
+#endif
diff --git a/src/emu/x64syscall.c b/src/emu/x64syscall.c
new file mode 100755
index 00000000..5359939c
--- /dev/null
+++ b/src/emu/x64syscall.c
@@ -0,0 +1,186 @@
+#define _GNU_SOURCE         /* See feature_test_macros(7) */
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/syscall.h>   /* For SYS_xxx definitions */
+#include <unistd.h>
+#include <time.h>
+#include <sys/mman.h>
+#include <sys/select.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <asm/stat.h>
+#include <errno.h>
+#include <sched.h>
+#include <sys/wait.h>
+#include <sys/utsname.h>
+#include <sys/resource.h>
+#include <poll.h>
+
+#include "debug.h"
+#include "box64stack.h"
+#include "x64emu.h"
+#include "x64run.h"
+#include "x64emu_private.h"
+#include "x64run_private.h"
+//#include "x64primop.h"
+#include "x64trace.h"
+//#include "myalign.h"
+#include "box64context.h"
+//#include "callback.h"
+//#include "signals.h"
+//#include "x64tls.h"
+
+typedef struct x64_sigaction_s x64_sigaction_t;
+
+
+//int32_t my_getrandom(x64emu_t* emu, void* buf, uint32_t buflen, uint32_t flags);
+//int of_convert(int flag);
+//int32_t my_open(x64emu_t* emu, void* pathname, int32_t flags, uint32_t mode);
+
+//int my_sigaction(x64emu_t* emu, int signum, const x86_sigaction_t *act, x86_sigaction_t *oldact);
+//int32_t my_execve(x64emu_t* emu, const char* path, char* const argv[], char* const envp[]);
+//void* my_mmap(x64emu_t* emu, void *addr, unsigned long length, int prot, int flags, int fd, int offset);
+//void* my_mmap64(x64emu_t* emu, void *addr, unsigned long length, int prot, int flags, int fd, int64_t offset);
+//int my_munmap(x64emu_t* emu, void* addr, unsigned long length);
+//int my_mprotect(x64emu_t* emu, void *addr, unsigned long len, int prot);
+
+// cannot include <fcntl.h>, it conflict with some asm includes...
+#ifndef O_NONBLOCK
+#define O_NONBLOCK 04000
+#endif
+#undef fcntl
+int fcntl(int fd, int cmd, ... /* arg */ );
+
+// Syscall table for x86_64 can be found 
+typedef struct scwrap_s {
+    int x64s;
+    int nats;
+    int nbpars;
+} scwrap_t;
+
+scwrap_t syscallwrap[] = {
+    { 0, __NR_read, 3 },  // wrapped so SA_RESTART can be handled by libc
+    { 1, __NR_write, 3 }, // same
+    { 2, __NR_open, 3 },  // flags need transformation
+    { 3, __NR_close, 1 },   // wrapped so SA_RESTART can be handled by libc
+    { 4, __NR_stat, 2 },
+    { 5, __NR_fstat, 2},
+};
+
+struct mmap_arg_struct {
+    unsigned long addr;
+    unsigned long len;
+    unsigned long prot;
+    unsigned long flags;
+    unsigned long fd;
+    unsigned long offset;
+};
+
+//struct x86_pt_regs {
+//	long ebx;
+//	long ecx;
+//	long edx;
+//	long esi;
+//	long edi;
+//	long ebp;
+//	long eax;
+//	int  xds;
+//	int  xes;
+//	int  xfs;
+//	int  xgs;
+//	long orig_eax;
+//	long eip;
+//	int  xcs;
+//	long eflags;
+//	long esp;
+//	int  xss;
+//};
+
+//int clone_fn(void* arg)
+//{
+//    x64emu_t *emu = (x64emu_t*)arg;
+//    R_RAX = 0;
+//    DynaRun(emu);
+//    int ret = R_EAX;
+//    FreeX64Emu(&emu);
+//    return ret;
+//}
+
+void EXPORT x64Syscall(x64emu_t *emu)
+{
+    RESET_FLAGS(emu);
+    uint32_t s = R_EAX;
+    printf_log(LOG_DEBUG, "%p: Calling syscall 0x%02X (%d) %p %p %p %p %p %p", (void*)R_RIP, s, s, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_R10, (void*)R_R8, (void*)R_R9); 
+    // check wrapper first
+    int cnt = sizeof(syscallwrap) / sizeof(scwrap_t);
+    for (int i=0; i<cnt; i++) {
+        if(syscallwrap[i].x64s == s) {
+            int sc = syscallwrap[i].nats;
+            switch(syscallwrap[i].nbpars) {
+                case 0: *(int64_t*)&R_RAX = syscall(sc); break;
+                case 1: *(int64_t*)&R_RAX = syscall(sc, R_RDI); break;
+                case 2: if(s==33) {printf_log(LOG_DUMP, " => sys_access(\"%s\", %ld)\n", (char*)R_RDI, R_RSI);}; *(int64_t*)&R_RAX = syscall(sc, R_RDI, R_RSI); break;
+                case 3: *(int64_t*)&R_RAX = syscall(sc, R_RDI, R_RSI, R_RDX); break;
+                case 4: *(int64_t*)&R_RAX = syscall(sc, R_RDI, R_RSI, R_RDX, R_R10); break;
+                case 5: *(int64_t*)&R_RAX = syscall(sc, R_RDI, R_RSI, R_RDX, R_R10, R_R8); break;
+                case 6: *(int64_t*)&R_RAX = syscall(sc, R_RDI, R_RSI, R_RDX, R_R10, R_R8, R_R9); break;
+                default:
+                   printf_log(LOG_NONE, "ERROR, Unimplemented syscall wrapper (%d, %d)\n", s, syscallwrap[i].nbpars); 
+                   emu->quit = 1;
+                   return;
+            }
+            printf_log(LOG_DEBUG, " => 0x%x\n", R_EAX);
+            return;
+        }
+    }
+    switch (s) {
+        default:
+            printf_log(LOG_INFO, "Error: Unsupported Syscall 0x%02Xh (%d)\n", s, s);
+            emu->quit = 1;
+            emu->error |= ERR_UNIMPL;
+            return;
+    }
+    printf_log(LOG_DEBUG, " => 0x%x\n", R_EAX);
+}
+
+#define stack(n) (R_RSP+8+n)
+#define i32(n)  *(int32_t*)stack(n)
+#define u32(n)  *(uint32_t*)stack(n)
+#define u64(n)  *(uint64_t*)stack(n)
+#define p(n)    *(void**)stack(n)
+
+uint32_t EXPORT my_syscall(x64emu_t *emu)
+{
+    uint32_t s = R_EDI;;
+    printf_log(LOG_DUMP, "%p: Calling libc syscall 0x%02X (%d) %p %p %p %p %p\n", (void*)R_RIP, s, s, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9); 
+    // check wrapper first
+    int cnt = sizeof(syscallwrap) / sizeof(scwrap_t);
+    for (int i=0; i<cnt; i++) {
+        if(syscallwrap[i].x64s == s) {
+            int sc = syscallwrap[i].nats;
+            switch(syscallwrap[i].nbpars) {
+                case 0: return syscall(sc);
+                case 1: return syscall(sc, R_RSI);
+                case 2: return syscall(sc, R_RSI, R_RDX);
+                case 3: return syscall(sc, R_RSI, R_RDX, R_RCX);
+                case 4: return syscall(sc, R_RSI, R_RDX, R_RCX, R_R8);
+                case 5: return syscall(sc, R_RSI, R_RDX, R_RCX, R_R8, R_R9);
+                case 6: return syscall(sc, R_RSI, R_RDX, R_RCX, R_R8, R_R9, u64(0));
+                default:
+                   printf_log(LOG_NONE, "ERROR, Unimplemented syscall wrapper (%d, %d)\n", s, syscallwrap[i].nbpars); 
+                   emu->quit = 1;
+                   return 0;
+            }
+        }
+    }
+    switch (s) {
+        default:
+            printf_log(LOG_INFO, "Error: Unsupported libc Syscall 0x%02X (%d)\n", s, s);
+            emu->quit = 1;
+            emu->error |= ERR_UNIMPL;
+    }
+    return 0;
+}
diff --git a/src/emu/x64tls.c b/src/emu/x64tls.c
new file mode 100755
index 00000000..b76646b5
--- /dev/null
+++ b/src/emu/x64tls.c
@@ -0,0 +1,213 @@
+// Handling of TLS calls, include x86 specifi set_thread_area
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "debug.h"
+#include "box64context.h"
+#include "x64emu.h"
+#include "x64tls.h"
+#include "elfloader.h"
+
+typedef struct thread_area_s
+{
+             int  entry_number;
+        uintptr_t base_addr;
+    unsigned int  limit;
+    unsigned int  seg_32bit:1;
+    unsigned int  contents:2;
+    unsigned int  read_exec_only:1;
+    unsigned int  limit_in_pages:1;
+    unsigned int  seg_not_present:1;
+    unsigned int  useable:1;
+} thread_area_t;
+
+static pthread_once_t thread_key_once0 = PTHREAD_ONCE_INIT;
+static pthread_once_t thread_key_once1 = PTHREAD_ONCE_INIT;
+static pthread_once_t thread_key_once2 = PTHREAD_ONCE_INIT;
+
+static void thread_key_alloc0() {
+	pthread_key_create(&my_context->segtls[0].key, NULL);
+}
+static void thread_key_alloc1() {
+	pthread_key_create(&my_context->segtls[1].key, NULL);
+}
+static void thread_key_alloc2() {
+	pthread_key_create(&my_context->segtls[2].key, NULL);
+}
+
+uint32_t my_set_thread_area(thread_area_t* td)
+{
+    printf_log(LOG_DEBUG, "set_thread_area(%p[%d/base=%p/limit=%u/32bits:%u/%u/%u...])\n", td, td->entry_number, (void*)td->base_addr, td->limit_in_pages, td->seg_32bit, td->contents, td->read_exec_only);
+
+    int isempty = 0;
+    // first, check if the "user_desc", here td, is "empty"
+    if(td->read_exec_only==1 && td->seg_not_present==1)
+        if( !td->base_addr 
+         && !td->limit
+         && !td->seg_32bit 
+         && !td->contents 
+         && !td->limit_in_pages 
+         && !td->useable)
+            isempty = 1;
+    int idx = td->entry_number;
+    if(idx==-1) {
+        // find a free one
+        for (int i=0; i<3 && idx==-1; ++i)
+            if(!my_context->segtls[i].present)
+                idx=i;
+        if(idx==-1) {
+            errno = ESRCH;
+            return (uint32_t)-1;
+        }
+        idx+=7;
+        td->entry_number = idx;
+    }
+    if(isempty && (td->entry_number<7 || td->entry_number>7+2)) {
+        errno = EINVAL;
+        return (uint32_t)-1;
+    }
+    if(isempty) {
+        memset(&my_context->segtls[td->entry_number-7], 0, sizeof(base_segment_t));
+        return 0;
+    }
+    if((idx<7 || idx>7+2)) {
+        errno = EINVAL;
+        return (uint32_t)-1;
+    }
+
+    my_context->segtls[idx-7].base = td->base_addr;
+    my_context->segtls[idx-7].limit = td->limit;
+    my_context->segtls[idx-7].present = 1;
+    switch (idx-7) {
+        case 0:	pthread_once(&thread_key_once0, thread_key_alloc0); break;
+        case 1:	pthread_once(&thread_key_once1, thread_key_alloc1); break;
+        case 2:	pthread_once(&thread_key_once2, thread_key_alloc2); break;
+    }
+
+    pthread_setspecific(my_context->segtls[idx-7].key, (void*)my_context->segtls[idx-7].base);
+
+    ResetSegmentsCache(thread_get_emu());
+
+    return 0;
+}
+
+uint32_t my_modify_ldt(x64emu_t* emu, int op, thread_area_t* td, int size)
+{
+    printf_log(/*LOG_DEBUG*/LOG_INFO, "modify_ldt(0x%x, %p[0x%x/base=%p/limit=%u/32bits:%u/%u/%u...], %d)\n", op, td, td->entry_number, (void*)td->base_addr, td->limit_in_pages, td->seg_32bit, td->contents, td->read_exec_only, size);
+    if(!td) {
+        errno = EFAULT;
+        return (uint32_t)-1;
+    }
+    if(op!=0x11) {
+        errno = ENOSYS;
+        return (uint32_t)-1;
+    }
+    if(!td->seg_32bit) {
+        // not handling 16bits segments for now
+        errno = EINVAL;
+        return (uint32_t)-1;
+    }
+
+    int idx = td->entry_number - 7;
+    if(idx<0 || idx>2) {
+        errno = EINVAL;
+        return (uint32_t)-1;
+    }
+
+    /*
+    my_context->segtls[idx].base = td->base_addr;
+    my_context->segtls[idx].limit = td->limit;
+    pthread_setspecific(my_context->segtls[idx].key, (void*)my_context->segtls[idx].base);
+    */
+    
+    ResetSegmentsCache(thread_get_emu());
+
+    return 0;
+}
+
+#define POS_TLS     0x50
+
+static tlsdatasize_t* setupTLSData(box64context_t* context)
+{
+    // Setup the GS segment:
+    int dtsize = context->elfsize*8;
+    void *ptr = (char*)malloc(context->tlssize+4+POS_TLS+dtsize);
+    memcpy(ptr, context->tlsdata, context->tlssize);
+    tlsdatasize_t *data = (tlsdatasize_t*)calloc(1, sizeof(tlsdatasize_t));
+    data->tlsdata = ptr;
+    data->tlssize = context->tlssize;
+    pthread_setspecific(context->tlskey, data);
+    // copy canary...
+    memset((void*)((uintptr_t)ptr+context->tlssize), 0, POS_TLS+dtsize);            // set to 0 remining bytes
+    memcpy((void*)((uintptr_t)ptr+context->tlssize+0x14), context->canary, 4);      // put canary in place
+    uintptr_t tlsptr = (uintptr_t)ptr+context->tlssize;
+    memcpy((void*)((uintptr_t)ptr+context->tlssize+0x0), &tlsptr, 4);
+    uintptr_t dtp = (uintptr_t)ptr+context->tlssize+POS_TLS;
+    memcpy((void*)(tlsptr+0x4), &dtp, 4);
+    if(dtsize) {
+        for (int i=0; i<context->elfsize; ++i) {
+            // set pointer
+            dtp = (uintptr_t)ptr + (context->tlssize + GetTLSBase(context->elfs[i]));
+            memcpy((void*)((uintptr_t)ptr+context->tlssize+POS_TLS+i*8), &dtp, 4);
+            memcpy((void*)((uintptr_t)ptr+context->tlssize+POS_TLS+i*8+4), &i, 4); // index
+        }
+    }
+    memcpy((void*)((uintptr_t)ptr+context->tlssize+0x10), &context->vsyscall, 4);  // address of vsyscall
+    return data;
+}
+
+void* fillTLSData(box64context_t *context)
+{
+        pthread_mutex_lock(&context->mutex_tls);
+        tlsdatasize_t *data = setupTLSData(context);
+        pthread_mutex_unlock(&context->mutex_tls);
+        return data;
+}
+
+void* resizeTLSData(box64context_t *context, void* oldptr)
+{
+        pthread_mutex_lock(&context->mutex_tls);
+        tlsdatasize_t* oldata = (tlsdatasize_t*)oldptr;
+        tlsdatasize_t *data = setupTLSData(context);
+        // copy the relevent old part, in case something changed
+        memcpy((void*)((uintptr_t)data->tlsdata+(context->tlssize-oldata->tlssize)), oldata->tlsdata, oldata->tlssize);
+        // all done, update new size, free old pointer and exit
+        pthread_mutex_unlock(&context->mutex_tls);
+        free_tlsdatasize(oldptr);
+        return data;
+}
+
+static void* GetSeg33Base()
+{
+    tlsdatasize_t* ptr;
+    if ((ptr = (tlsdatasize_t*)pthread_getspecific(my_context->tlskey)) == NULL) {
+        ptr = (tlsdatasize_t*)fillTLSData(my_context);
+    }
+    if(ptr->tlssize != my_context->tlssize)
+        ptr = (tlsdatasize_t*)resizeTLSData(my_context, ptr);
+    return ptr->tlsdata+ptr->tlssize;
+}
+
+void* GetSegmentBase(uint32_t desc)
+{
+    if(!desc) {
+        printf_log(LOG_NONE, "Warning, accessing segment NULL\n");
+        return NULL;
+    }
+    int base = desc>>3;
+    if(base==0xe || base==0xf)
+        return NULL;    // regular value...
+    if(base==0x6)
+        return GetSeg33Base();
+
+    if(base>6 && base<10 && my_context->segtls[base-7].present) {
+        void* ptr = pthread_getspecific(my_context->segtls[base-7].key);
+        return ptr;
+    }
+
+    printf_log(LOG_NONE, "Warning, accessing segment unknown 0x%x or unset\n", desc);
+    return NULL;
+}
diff --git a/src/include/box64context.h b/src/include/box64context.h
index 9eca567e..c9c25bf3 100755
--- a/src/include/box64context.h
+++ b/src/include/box64context.h
@@ -11,7 +11,22 @@ typedef struct zydis_s zydis_t;
 typedef struct zydis_dec_s zydis_dec_t;
 typedef struct lib_s lib_t;
 typedef struct bridge_s bridge_t;
+typedef struct dlprivate_s dlprivate_t;
+typedef struct kh_symbolmap_s kh_symbolmap_t;
+typedef struct library_s library_t;
 typedef struct kh_threadstack_s kh_threadstack_t;
+typedef struct atfork_fnc_s {
+    uintptr_t prepare;
+    uintptr_t parent;
+    uintptr_t child;
+    void*     handle;
+} atfork_fnc_t;
+#ifdef DYNAREC
+typedef struct dynablock_s      dynablock_t;
+typedef struct dynablocklist_s  dynablocklist_t;
+typedef struct mmaplist_s       mmaplist_t;
+typedef struct kh_dynablocks_s  kh_dynablocks_t;
+#endif
 
 typedef void* (*procaddess_t)(const char* name);
 typedef void* (*vkprocaddess_t)(void* instance, const char* name);
@@ -25,6 +40,22 @@ typedef struct tlsdatasize_s {
 
 void free_tlsdatasize(void* p);
 
+typedef struct needed_libs_s {
+    int         cap;
+    int         size;
+    library_t   **libs;
+} needed_libs_t;
+
+void add_neededlib(needed_libs_t* needed, library_t* lib);
+void free_neededlib(needed_libs_t* needed);
+
+typedef struct base_segment_s {
+    uintptr_t       base;
+    uint64_t        limit;
+    int             present;
+    pthread_key_t   key;
+} base_segment_t;
+
 typedef struct box64context_s {
     path_collection_t   box64_path;     // PATH env. variable
     path_collection_t   box64_ld_lib;   // LD_LIBRARY_PATH env. variable
@@ -56,7 +87,8 @@ typedef struct box64context_s {
     int                 elfcap;
     int                 elfsize;        // number of elf loaded
 
-    int                 deferedInit;
+
+    needed_libs_t       neededlibs;     // needed libs for main elf
 
     uintptr_t           ep;             // entry point
 
@@ -66,12 +98,62 @@ typedef struct box64context_s {
     kh_threadstack_t    *stacksizes;    // stack sizes attributes for thread (temporary)
     bridge_t            *system;        // other bridges
     uintptr_t           vsyscall;       // vsyscall bridge value
-
+    dlprivate_t         *dlprivate;     // dlopen library map
+    kh_symbolmap_t      *glwrappers;    // the map of wrapper for glProcs (for GLX or SDL1/2)
+    kh_symbolmap_t      *glmymap;       // link to the mysymbolmap of libGL
+    procaddess_t        glxprocaddress;
+    kh_symbolmap_t      *alwrappers;    // the map of wrapper for alGetProcAddress
+    kh_symbolmap_t      *almymap;       // link to the mysymbolmap if libOpenAL
+    kh_symbolmap_t      *vkwrappers;    // the map of wrapper for VulkanProcs (TODO: check SDL2)
+    kh_symbolmap_t      *vkmymap;       // link to the mysymbolmap of libGL
+    vkprocaddess_t      vkprocaddress;
+
+    pthread_mutex_t     mutex_once;
+    pthread_mutex_t     mutex_once2;
+    pthread_mutex_t     mutex_trace;
+    #ifndef DYNAREC
+    pthread_mutex_t     mutex_lock;     // dynarec build will use their own mecanism
+    #else
+    pthread_mutex_t     mutex_dyndump;
+    int                 trace_dynarec;
+    #endif
+    pthread_mutex_t     mutex_tls;
     pthread_mutex_t     mutex_thread;
 
+    library_t           *libclib;       // shortcut to libc library (if loaded, so probably yes)
+    library_t           *sdl1lib;       // shortcut to SDL1 library (if loaded)
+    void*               sdl1allocrw;
+    void*               sdl1freerw;
+    library_t           *sdl1mixerlib;
+    library_t           *sdl2lib;       // shortcut to SDL2 library (if loaded)
+    void*               sdl2allocrw;
+    void*               sdl2freerw;
+    library_t           *sdl2mixerlib;
+    library_t           *x11lib;
+    library_t           *libxcb;
+    library_t           *libxcbxfixes;
+    library_t           *libxcbshape;
+    library_t           *libxcbshm;
+    library_t           *libxcbrandr;
+    library_t           *libxcbimage;
+    library_t           *libxcbkeysyms;
+    library_t           *libxcbxtest;
+    library_t           *zlib;
+    library_t           *vorbisfile;
+    library_t           *vorbis;
+    library_t           *asound;
+    library_t           *pulse;
+    library_t           *d3dadapter9;
+
+    int                 deferedInit;
+    elfheader_t         **deferedInitList;
+    int                 deferedInitSz;
+    int                 deferedInitCap;
+
     pthread_key_t       tlskey;     // then tls key to have actual tlsdata
     void*               tlsdata;    // the initial global tlsdata
     int32_t             tlssize;    // wanted size of tlsdata
+    base_segment_t      segtls[3];  // only handling 0/1/2 descriptors
 
     uintptr_t           *auxval_start;
 
@@ -81,6 +163,12 @@ typedef struct box64context_s {
 
     zydis_dec_t         *dec;           // trace
 
+    int                 forked;         //  how many forks... cleanup only when < 0
+
+    atfork_fnc_t        *atforks;       // fnc for atfork...
+    int                 atfork_sz;
+    int                 atfork_cap;
+
     uint8_t             canary[4];
 
     uintptr_t           signals[MAX_SIGNAL];
diff --git a/src/include/callback.h b/src/include/callback.h
new file mode 100755
index 00000000..b9482fc1
--- /dev/null
+++ b/src/include/callback.h
@@ -0,0 +1,12 @@
+#ifndef __CALLBACK_H__
+#define __CALLBACK_H__
+
+#include <stdint.h>
+
+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, ...);
+
+#endif //__CALLBACK_H__
\ No newline at end of file
diff --git a/src/include/dynarec.h b/src/include/dynarec.h
new file mode 100755
index 00000000..a68c6d6a
--- /dev/null
+++ b/src/include/dynarec.h
@@ -0,0 +1,8 @@
+#ifndef __DYNAREC_H_
+#define __DYNAREC_H_
+
+typedef struct x64emu_s x64emu_t;
+
+void DynaCall(x64emu_t* emu, uintptr_t addr); // try to use DynaRec... Fallback to EmuCall if no dynarec available
+
+#endif // __DYNAREC_H_
\ No newline at end of file
diff --git a/src/include/elfloader.h b/src/include/elfloader.h
index 28ce4844..a4d2cb6b 100755
--- a/src/include/elfloader.h
+++ b/src/include/elfloader.h
@@ -3,20 +3,20 @@
 #include <stdio.h>
 
 typedef struct elfheader_s elfheader_t;
-//typedef struct lib_s lib_t;
-//typedef struct library_s library_t;
-//typedef struct kh_mapsymbols_s kh_mapsymbols_t;
+typedef struct lib_s lib_t;
+typedef struct library_s library_t;
+typedef struct kh_mapsymbols_s kh_mapsymbols_t;
 typedef struct box64context_s box64context_t;
-//typedef struct x86emu_s x86emu_t;
-//typedef struct needed_libs_s needed_libs_t;
-//#ifdef DYNAREC
-//typedef struct dynablocklist_s dynablocklist_t;
-//#endif
+typedef struct x64emu_s x64emu_t;
+typedef struct needed_libs_s needed_libs_t;
+#ifdef DYNAREC
+typedef struct dynablocklist_s dynablocklist_t;
+#endif
 
 elfheader_t* LoadAndCheckElfHeader(FILE* f, const char* name, int exec); // exec : 0 = lib, 1 = exec
 void FreeElfHeader(elfheader_t** head);
 const char* ElfName(elfheader_t* head);
-//void ElfAttachLib(elfheader_t* head, library_t* lib);
+void ElfAttachLib(elfheader_t* head, library_t* lib);
 
 // return 0 if OK
 int CalcLoadAddr(elfheader_t* head);
@@ -24,34 +24,34 @@ int AllocElfMemory(box64context_t* context, elfheader_t* head, int mainbin);
 void FreeElfMemory(elfheader_t* head);
 int LoadElfMemory(FILE* f, box64context_t* context, elfheader_t* head);
 int ReloadElfMemory(FILE* f, box64context_t* context, elfheader_t* head);
-//int RelocateElf(lib_t *maplib, lib_t* local_maplib, elfheader_t* head);
-//int RelocateElfPlt(lib_t *maplib, lib_t* local_maplib, elfheader_t* head);
+int RelocateElf(lib_t *maplib, lib_t* local_maplib, elfheader_t* head);
+int RelocateElfPlt(lib_t *maplib, lib_t* local_maplib, elfheader_t* head);
 void CalcStack(elfheader_t* h, uint32_t* stacksz, int* stackalign);
-//uintptr_t GetEntryPoint(lib_t* maplib, elfheader_t* h);
+uintptr_t GetEntryPoint(lib_t* maplib, elfheader_t* h);
 uintptr_t GetLastByte(elfheader_t* h);
-//void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* weaksymbols, kh_mapsymbols_t* localsymbols, elfheader_t* h);
-//int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, int local, box64context_t *box86, x86emu_t* emu);
-//uintptr_t GetElfInit(elfheader_t* h);
-//uintptr_t GetElfFini(elfheader_t* h);
-//void RunElfInit(elfheader_t* h, x86emu_t *emu);
-//void RunElfFini(elfheader_t* h, x86emu_t *emu);
-//void RunDeferedElfInit(x86emu_t *emu);
-//void* GetBaseAddress(elfheader_t* h);
-//void* GetElfDelta(elfheader_t* h);
-//uint32_t GetBaseSize(elfheader_t* h);
-//int IsAddressInElfSpace(elfheader_t* h, uintptr_t addr);
-//elfheader_t* FindElfAddress(box64context_t *context, uintptr_t addr);
-//const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uint32_t* sz);
-//int32_t GetTLSBase(elfheader_t* h);
-//uint32_t GetTLSSize(elfheader_t* h);
-//void* GetTLSPointer(box64context_t* context, elfheader_t* h);
-//void* GetDTatOffset(box64context_t* context, int index, int offset);
-//#ifdef DYNAREC
-//dynablocklist_t* GetDynablocksFromAddress(box64context_t *context, uintptr_t addr);
-//dynablocklist_t* GetDynablocksFromElf(elfheader_t* h);
-//#endif
-//void ResetSpecialCaseMainElf(elfheader_t* h);
-//void CreateMemorymapFile(box64context_t* context, int fd);
+void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* weaksymbols, kh_mapsymbols_t* localsymbols, elfheader_t* h);
+int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, int local, box64context_t *box86, x64emu_t* emu);
+uintptr_t GetElfInit(elfheader_t* h);
+uintptr_t GetElfFini(elfheader_t* h);
+void RunElfInit(elfheader_t* h, x64emu_t *emu);
+void RunElfFini(elfheader_t* h, x64emu_t *emu);
+void RunDeferedElfInit(x64emu_t *emu);
+void* GetBaseAddress(elfheader_t* h);
+void* GetElfDelta(elfheader_t* h);
+uint32_t GetBaseSize(elfheader_t* h);
+int IsAddressInElfSpace(elfheader_t* h, uintptr_t addr);
+elfheader_t* FindElfAddress(box64context_t *context, uintptr_t addr);
+const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uint32_t* sz);
+int32_t GetTLSBase(elfheader_t* h);
+uint32_t GetTLSSize(elfheader_t* h);
+void* GetTLSPointer(box64context_t* context, elfheader_t* h);
+void* GetDTatOffset(box64context_t* context, int index, int offset);
+#ifdef DYNAREC
+dynablocklist_t* GetDynablocksFromAddress(box64context_t *context, uintptr_t addr);
+dynablocklist_t* GetDynablocksFromElf(elfheader_t* h);
+#endif
+void ResetSpecialCaseMainElf(elfheader_t* h);
+void CreateMemorymapFile(box64context_t* context, int fd);
 
 int ElfCheckIfUseTCMallocMinimal(elfheader_t* h);   // return 1 if tcmalloc is used
 
diff --git a/src/include/librarian.h b/src/include/librarian.h
new file mode 100755
index 00000000..a25fcd7b
--- /dev/null
+++ b/src/include/librarian.h
@@ -0,0 +1,51 @@
+#ifndef __LIBRARIAN_H_
+#define __LIBRARIAN_H_
+#include <stdint.h>
+
+typedef struct lib_s lib_t;
+typedef struct bridge_s bridge_t;
+typedef struct library_s library_t;
+typedef struct kh_mapsymbols_s kh_mapsymbols_t;
+typedef struct dlprivate_s dlprivate_t;
+typedef struct box64context_s  box64context_t;
+typedef struct x64emu_s x64emu_t;
+typedef struct elfheader_s elfheader_t;
+typedef struct needed_libs_s needed_libs_t;
+typedef struct kh_mapoffsets_s kh_mapoffsets_t;
+typedef char* cstr_t;
+
+lib_t *NewLibrarian(box64context_t* context, int ownlibs);
+void FreeLibrarian(lib_t **maplib);
+dlprivate_t *NewDLPrivate();
+void FreeDLPrivate(dlprivate_t **lib);
+
+box64context_t* GetLibrarianContext(lib_t* maplib);
+kh_mapsymbols_t* GetMapSymbol(lib_t* maplib);
+kh_mapsymbols_t* GetWeakSymbol(lib_t* maplib);
+kh_mapsymbols_t* GetLocalSymbol(lib_t* maplib);
+kh_mapsymbols_t* GetGlobalData(lib_t* maplib);
+int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, int local, const char* path, box64context_t* box86, x64emu_t* emu); // 0=success, 1=error
+library_t* GetLibMapLib(lib_t* maplib, const char* name);
+library_t* GetLibInternal(const char* name);
+uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name);
+int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self);
+int GetSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self);
+int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end);
+int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end);
+int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self);
+int GetNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self);
+elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name);
+int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name);
+
+void AddSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz); // replace if already there
+uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name);
+void AddWeakSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz); // don't add if already there
+int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end);
+const char* GetSymbolName(kh_mapsymbols_t* mapsymbols, void* p, uintptr_t* offs, uint32_t* sz);
+
+const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint32_t* sz, const char** libname, void** base);
+
+void AddOffsetSymbol(lib_t *maplib, void* offs, const char* name);
+const char* GetNameOffset(lib_t *maplib, void* offs);
+
+#endif //__LIBRARIAN_H_
\ No newline at end of file
diff --git a/src/include/library.h b/src/include/library.h
new file mode 100755
index 00000000..d33b1126
--- /dev/null
+++ b/src/include/library.h
@@ -0,0 +1,36 @@
+#ifndef __LIBRARY_H_
+#define __LIBRARY_H_
+#include <stdint.h>
+
+typedef struct library_s       library_t;
+typedef struct lib_s           lib_t;
+typedef struct kh_symbolmap_s  kh_symbolmap_t;
+typedef struct box64context_s  box64context_t;
+typedef struct x64emu_s        x64emu_t;
+typedef struct needed_libs_s   needed_libs_t;
+
+library_t *NewLibrary(const char* path, box64context_t* box86);
+int AddSymbolsLibrary(lib_t* maplib, library_t* lib, x64emu_t* emu);
+int FinalizeLibrary(library_t* lib, lib_t* local_maplib, x64emu_t* emu);
+int ReloadLibrary(library_t* lib, x64emu_t* emu);
+void InactiveLibrary(library_t* lib);
+void Free1Library(library_t **lib);
+
+char* GetNameLib(library_t *lib);
+int IsSameLib(library_t* lib, const char* path);    // check if lib is same (path -> name)
+int GetLibSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end);
+int GetLibNoWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end);
+int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end);
+void fillGLProcWrapper(box64context_t* context);
+void freeGLProcWrapper(box64context_t* context);
+void fillALProcWrapper(box64context_t* context);
+void freeALProcWrapper(box64context_t* context);
+needed_libs_t* GetNeededLibs(library_t* lib);
+int GetNeededLibN(library_t* lib);
+library_t* GetNeededLib(library_t* lib, int idx);
+lib_t* GetMaplib(library_t* lib);
+
+int GetElfIndex(library_t* lib);    // -1 if no elf (i.e. native)
+void* GetHandle(library_t* lib);    // NULL if not native
+
+#endif //__LIBRARY_H_
\ No newline at end of file
diff --git a/src/include/wrappedlibs.h b/src/include/wrappedlibs.h
new file mode 100755
index 00000000..d8cf3a64
--- /dev/null
+++ b/src/include/wrappedlibs.h
@@ -0,0 +1,21 @@
+#ifndef __WRAPPEDLIBS_H__
+#define __WRAPPEDLIBS_H__
+#include <stdint.h>
+
+typedef struct library_s library_t;
+typedef struct box64context_s  box64context_t;
+
+typedef int (*wrappedlib_init_t)(library_t * lib, box64context_t* box64);  // 0 = success
+typedef void (*wrappedlib_fini_t)(library_t * lib);
+typedef int (*wrappedlib_get_t)(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz);
+
+typedef struct wrappedlib_s {
+    const char*         name;
+    wrappedlib_init_t   init;
+    wrappedlib_fini_t   fini;
+    wrappedlib_get_t    get;
+    wrappedlib_get_t    getnoweak;
+    wrappedlib_get_t    getlocal;
+} wrappedlib_t;
+
+#endif //__WRAPPEDLIBS_H__
\ No newline at end of file
diff --git a/src/include/x64emu.h b/src/include/x64emu.h
index ff19339b..f0ad24dd 100755
--- a/src/include/x64emu.h
+++ b/src/include/x64emu.h
@@ -42,8 +42,8 @@ void ResetSegmentsCache(x64emu_t *emu);
 const char* DumpCPURegs(x64emu_t* emu, uintptr_t ip);
 
 void StopEmu(x64emu_t* emu, const char* reason);
-//void PushExit(x64emu_t* emu);
-//void* GetExit();
+void PushExit(x64emu_t* emu);
+void* GetExit();
 void EmuCall(x64emu_t* emu, uintptr_t addr);
 void AddCleanup(x64emu_t *emu, void *p);
 void AddCleanup1Arg(x64emu_t *emu, void *p, void* a);
diff --git a/src/include/x64run.h b/src/include/x64run.h
index 6b7333f7..78903bbc 100755
--- a/src/include/x64run.h
+++ b/src/include/x64run.h
@@ -3,12 +3,12 @@
 #include <stdint.h>
 
 typedef struct x64emu_s x64emu_t;
-//int Run(x64emu_t *emu, int step); // 0 if run was successfull, 1 if error in x86 world
-//int DynaRun(x64emu_t *emu);
+int Run(x64emu_t *emu, int step); // 0 if run was successfull, 1 if error in x86 world
+int DynaRun(x64emu_t *emu);
 
-//uint32_t LibSyscall(x64emu_t *emu);
-//void PltResolver(x64emu_t* emu);
-//extern uintptr_t pltResolver;
+uint32_t LibSyscall(x64emu_t *emu);
+void PltResolver(x64emu_t* emu);
+extern uintptr_t pltResolver;
 int GetTID();
 
 #endif //__X64RUN_H_
\ No newline at end of file
diff --git a/src/include/x64tls.h b/src/include/x64tls.h
new file mode 100755
index 00000000..61f58887
--- /dev/null
+++ b/src/include/x64tls.h
@@ -0,0 +1,13 @@
+#ifndef __X64_TLS_H__
+#define __X64_TLS_H__
+
+typedef struct thread_area_s thread_area_t;
+
+uint32_t my_set_thread_area(thread_area_t* td);
+uint32_t my_modify_ldt(x64emu_t* emu, int op, thread_area_t* td, int size);
+
+void* fillTLSData(box64context_t *context);
+void* resizeTLSData(box64context_t *context, void* oldptr);
+void* GetSegmentBase(uint32_t desc);
+
+#endif //__X64_TLS_H__
\ No newline at end of file
diff --git a/src/librarian/librarian.c b/src/librarian/librarian.c
new file mode 100755
index 00000000..5f429c88
--- /dev/null
+++ b/src/librarian/librarian.c
@@ -0,0 +1,588 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <pthread.h>
+
+#include "debug.h"
+#include "librarian.h"
+#include "librarian_private.h"
+#include "library.h"
+#include "library_private.h"
+#include "x64emu.h"
+#include "box64context.h"
+#include "elfloader.h"
+
+#include "bridge.h"
+
+KHASH_MAP_IMPL_STR(mapsymbols, onesymbol_t);
+KHASH_MAP_IMPL_INT(mapoffsets, cstr_t);
+
+lib_t *NewLibrarian(box64context_t* context, int ownlibs)
+{
+    lib_t *maplib = (lib_t*)calloc(1, sizeof(lib_t));
+    
+    maplib->mapsymbols = kh_init(mapsymbols);
+    maplib->weaksymbols = kh_init(mapsymbols);
+    maplib->localsymbols = kh_init(mapsymbols);
+    maplib->mapoffsets = kh_init(mapoffsets);
+    maplib->globaldata = kh_init(mapsymbols);
+    maplib->bridge = NewBridge();
+
+    maplib->context = context;
+
+    maplib->ownlibs = ownlibs;
+
+    return maplib;
+}
+void FreeLibrarian(lib_t **maplib)
+{
+    // should that be in reverse order?
+    if(!maplib || !*maplib)
+        return;
+    
+    if((*maplib)->ownlibs) {
+        printf_log(LOG_DEBUG, "Closing %d libs from maplib %p\n", (*maplib)->libsz, *maplib);
+        for (int i=0; i<(*maplib)->libsz; ++i) {
+            printf_log(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i].lib->name);
+            Free1Library(&(*maplib)->libraries[i].lib);
+        }
+    }
+    free((*maplib)->libraries);
+    (*maplib)->libraries = NULL;
+
+    if((*maplib)->mapsymbols) {
+        kh_destroy(mapsymbols, (*maplib)->mapsymbols);
+    }
+    if((*maplib)->weaksymbols) {
+        kh_destroy(mapsymbols, (*maplib)->weaksymbols);
+    }
+    if((*maplib)->localsymbols) {
+        kh_destroy(mapsymbols, (*maplib)->localsymbols);
+    }
+    if((*maplib)->mapoffsets) {
+        kh_destroy(mapoffsets, (*maplib)->mapoffsets);
+    }
+    if((*maplib)->globaldata) {
+        kh_destroy(mapsymbols, (*maplib)->globaldata);
+    }
+    (*maplib)->libsz = (*maplib)->libcap = 0;
+
+    if((*maplib)->bridge)
+        FreeBridge(&(*maplib)->bridge);
+
+    free(*maplib);
+    *maplib = NULL;
+
+}
+
+box64context_t* GetLibrarianContext(lib_t* maplib)
+{
+    return maplib->context;
+}
+
+kh_mapsymbols_t* GetMapSymbol(lib_t* maplib)
+{
+    return maplib->mapsymbols;
+}
+
+kh_mapsymbols_t* GetWeakSymbol(lib_t* maplib)
+{
+    return maplib->weaksymbols;
+}
+
+kh_mapsymbols_t* GetLocalSymbol(lib_t* maplib)
+{
+    return maplib->localsymbols;
+}
+
+kh_mapsymbols_t* GetGlobalData(lib_t* maplib)
+{
+    return maplib->globaldata;
+}
+
+library_t* getLib(lib_t* maplib, const char* path)
+{
+    for(int i=0; i<maplib->libsz; ++i) {
+        onelib_t *onelib = &maplib->libraries[i];
+        if(IsSameLib(onelib->lib, path)) {
+            return onelib->lib;
+        }
+    }
+    return NULL;
+}
+
+static int libraryInMapLib(lib_t* maplib, library_t* lib)
+{
+    if(!maplib)
+        return 0;
+    for(int i=0; i<maplib->libsz; ++i)
+        if(maplib->libraries[i].lib==lib)
+            return 1;
+    return 0;
+}
+
+void MapLibAddLib(lib_t* maplib, library_t* lib)
+{
+    if (maplib->libsz == maplib->libcap) {
+        maplib->libcap += 8;
+        maplib->libraries = (onelib_t*)realloc(maplib->libraries, maplib->libcap*sizeof(onelib_t));
+    }
+    maplib->libraries[maplib->libsz].lib = lib;
+    maplib->libraries[maplib->libsz].name = GetNameLib(lib);
+    ++maplib->libsz;
+}
+
+void MapLibAddMapLib(lib_t* dest, lib_t* src)
+{
+    if(!src)
+        return;
+    for(int i=0; i<src->libsz; ++i) {
+        library_t* lib = src->libraries[i].lib;
+        if(!lib) continue;
+        if(lib->maplib && src!=lib->maplib) {   //TODO: find why is src!=lib->maplib needed
+            MapLibAddMapLib(dest, lib->maplib);
+            free(lib->maplib);
+            lib->maplib = NULL;
+        }
+        if(!libraryInMapLib(dest, lib))
+            MapLibAddLib(dest, lib);
+    }
+}
+
+void MapLibRemoveLib(lib_t* maplib, library_t* lib)
+{
+    if(!maplib || !lib)
+        return;
+    int idx = 0;
+    while(idx<maplib->libsz && maplib->libraries[idx].lib!=lib) ++idx;
+    if(idx==maplib->libsz)  //not found
+        return;
+    --maplib->libsz;
+    if(idx!=(maplib->libsz))
+        memmove(&maplib->libraries[idx], &maplib->libraries[idx+1], sizeof(onelib_t)*(maplib->libsz-idx));
+    maplib->libraries[maplib->libsz].lib = NULL;
+    maplib->libraries[maplib->libsz].name = NULL;
+}
+
+EXPORTDYN
+int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, int local, const char* path, box64context_t* box64, x64emu_t* emu)
+{
+    printf_log(LOG_DEBUG, "Trying to add \"%s\" to maplib%s\n", path, local?" (local)":"");
+    // first check if lib is already loaded
+    library_t *lib = getLib(my_context->maplib, path);
+    if(lib) {
+        add_neededlib(neededlibs, lib);
+        printf_log(LOG_DEBUG, "Already present in maplib => success\n");
+        return 0;
+    }
+    // check also in the local loaded lib
+    lib = getLib(my_context->local_maplib, path);
+    if(lib) {
+        printf_log(LOG_DEBUG, "Already present in local_maplib => success\n");
+        if(local) {
+            // add lib to maplib...
+            if(maplib) {
+                if(lib->maplib) {
+                    MapLibAddMapLib(maplib, lib->maplib);
+                }
+                if(!libraryInMapLib(maplib, lib))
+                    MapLibAddLib(maplib, lib);
+            }
+        } else {
+            // promote lib from local to global...
+            // for add the depending local libs...
+            if(lib->maplib) {
+                MapLibAddMapLib(my_context->maplib, lib->maplib);
+                free(lib->maplib);
+                lib->maplib = NULL;
+            }
+            if(!libraryInMapLib(my_context->maplib, lib))
+                MapLibAddLib(my_context->maplib, lib);
+            MapLibRemoveLib(my_context->local_maplib, lib);
+        }
+        add_neededlib(neededlibs, lib);
+        return 0;
+    }
+    // load a new one
+    lib = NewLibrary(path, box64);
+    if(!lib) {
+        printf_log(LOG_DEBUG, "Faillure to create lib => fail\n");
+        return 1;   //Error
+    }
+
+    add_neededlib(neededlibs, lib);
+
+    // add lib now
+    if(local) {
+        MapLibAddLib(my_context->local_maplib, lib);
+        if(maplib)
+            MapLibAddLib(maplib, lib);
+        lib->maplib = NewLibrarian(box64, 0);
+        MapLibAddLib(lib->maplib, lib);
+    } else {
+        MapLibAddLib(my_context->maplib, lib);
+    }
+
+    if(!maplib)
+        maplib = (local)?lib->maplib:my_context->maplib;
+
+    int mainelf = GetElfIndex(lib);
+
+    if(mainelf==-1) {
+        // It's a native libs, just add wrapped symbols to global map
+        if(AddSymbolsLibrary(maplib, lib, emu)) {   // also add needed libs
+            printf_log(LOG_DEBUG, "Failure to Add lib => fail\n");
+            return 1;
+        }
+    } else {
+        // it's an emulated lib, 
+        // lets load dependancies before adding symbols and launch init sequence
+        if(LoadNeededLibs(box64->elfs[mainelf], maplib, &lib->needed, 0, box64, emu)) {
+            printf_log(LOG_DEBUG, "Failure to Add dependant lib => fail\n");
+            return 1;
+        }
+        // some special case, where dependancies may not be correct
+        if(!strcmp(GetNameLib(lib), "libCgGL.so")) {
+            AddNeededLib(maplib, &lib->needed, 0, "libGL.so.1", box64, emu);
+        }
+        if(!strcmp(GetNameLib(lib), "libmss.so.6")) {
+            AddNeededLib(maplib, &lib->needed, 0, "libSDL-1.2.so.0", box64, emu);
+            AddNeededLib(maplib, &lib->needed, 0, "libdl.so.2", box64, emu);
+        }
+        // add symbols
+        if(AddSymbolsLibrary(maplib, lib, emu)) {   // also add needed libs
+            printf_log(LOG_DEBUG, "Failure to Add lib => fail\n");
+            return 1;
+        }
+
+        // finalize the lib
+        if(FinalizeLibrary(lib, local?maplib:NULL, emu)) {
+            printf_log(LOG_DEBUG, "Failure to finalizing lib => fail\n");
+            return 1;
+        }
+    }
+    // success
+    printf_log(LOG_DEBUG, "Created lib and added to maplib => success\n");
+    
+    return 0;
+}
+
+library_t* GetLibMapLib(lib_t* maplib, const char* name)
+{
+    printf_log(LOG_DEBUG, "Trying to Get \"%s\" to maplib\n", name);
+    return getLib(maplib, name);
+}
+
+library_t* GetLibInternal(const char* name)
+{
+    printf_log(LOG_DEBUG, "Trying to Get \"%s\" to maplib\n", name);
+    library_t* lib = getLib(my_context->maplib, name);
+    if(!lib) lib = getLib(my_context->local_maplib, name);
+    return lib;
+}
+
+EXPORTDYN
+uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name)
+{
+    uintptr_t start = 0, end = 0;
+    if(GetGlobalSymbolStartEnd(maplib, name, &start, &end))
+        return start;
+    return 0;
+}
+
+int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self)
+{
+    //excude self if defined
+    if(maplib->context->elfs[0]!=self) {
+        if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end))
+            if(*start)
+                return 1;
+        if(GetSymbolStartEnd(maplib->weaksymbols, name, start, end))
+            if(*start)
+                return 1;
+    }
+    for(int i=0; i<maplib->libsz; ++i) {
+        if(GetElfIndex(maplib->libraries[i].lib)==-1 || (maplib->context->elfs[GetElfIndex(maplib->libraries[i].lib)]!=self))
+            if(GetLibSymbolStartEnd(maplib->libraries[i].lib, name, start, end))
+                if(*start)
+                    return 1;
+    }
+    // if self defined, give it another chance with self...
+    if(self) {
+        if(maplib->context->elfs[0]==self) {
+            if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end))
+                if(*start)
+                    return 1;
+            if(GetSymbolStartEnd(maplib->weaksymbols, name, start, end))
+                if(*start)
+                    return 1;
+        }
+        for(int i=0; i<maplib->libsz; ++i) {
+            if(GetElfIndex(maplib->libraries[i].lib)!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i].lib)]==self))
+                if(GetLibSymbolStartEnd(maplib->libraries[i].lib, name, start, end))
+                    if(*start)
+                        return 1;
+        }
+    }
+    // nope, not found
+    return 0;
+}
+static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end)
+{
+    // search non-weak symbol, from older to newer (first GLOBAL object wins)
+    if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end))
+        if(*start)
+            return 1;
+    // TODO: create a temporary map to search lib only 1 time, and in order of needed...
+    // search in needed libs from neededlibs first, in order
+    for(int i=0; i<my_context->neededlibs.size; ++i)
+        if(GetLibNoWeakSymbolStartEnd(my_context->neededlibs.libs[i], name, start, end))
+            if(*start)
+                return 1;
+    // search in global symbols
+    for(int i=0; i<maplib->libsz; ++i) {
+        if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i].lib, name, start, end))
+            if(*start)
+                return 1;
+    }
+
+    // library from newer to older, weak only now
+    for(int i=maplib->libsz-1; i>=0; --i) {
+        if(GetLibSymbolStartEnd(maplib->libraries[i].lib, name, start, end))    // only weak symbol haven't been found yet
+            if(*start)
+                return 1;
+    }
+    if(GetSymbolStartEnd(maplib->weaksymbols, name, start, end))
+        if(*start)
+            return 1;
+    // nope, not found
+    return 0;
+}
+//void** my_GetGTKDisplay();
+//void** my_GetGthreadsGotInitialized();
+int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end)
+{
+    if(GetGlobalSymbolStartEnd_internal(maplib, name, start, end)) {
+        if(start && end && *end==*start) {  // object is of 0 sized, try to see an "_END" object of null size
+            uintptr_t start2, end2;
+            char* buff = (char*)malloc(strlen(name) + strlen("_END") + 1);
+            strcpy(buff, name);
+            strcat(buff, "_END");
+            if(GetGlobalSymbolStartEnd_internal(maplib, buff, &start2, &end2)) {
+                if(end2>*end && start2==end2)
+                    *end = end2;
+            }
+            free(buff);
+        }
+        return 1;
+    }
+    // some special case symbol, defined inside box64 itself
+//    if(!strcmp(name, "gdk_display")) {
+//        *start = (uintptr_t)my_GetGTKDisplay();
+//        *end = *start+sizeof(void*);
+//        printf_log(LOG_INFO, "Using global gdk_display for gdk-x11 (%p:%p)\n", start, *(void**)start);
+//        return 1;
+//    }
+//    if(!strcmp(name, "g_threads_got_initialized")) {
+//        *start = (uintptr_t)my_GetGthreadsGotInitialized();
+//        *end = *start+sizeof(int);
+//        printf_log(LOG_INFO, "Using global g_threads_got_initialized for gthread2 (%p:%p)\n", start, *(void**)start);
+//        return 1;
+//    }
+    // not found...
+    return 0;
+}
+
+elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name)
+{
+    uintptr_t start = 0;
+    uintptr_t end = 0;
+    if(GetSymbolStartEnd(maplib->mapsymbols, name, &start, &end))
+        return maplib->context->elfs[0];
+    if(GetSymbolStartEnd(maplib->weaksymbols, name, &start, &end))
+        return maplib->context->elfs[0];
+    for(int i=0; i<maplib->libsz; ++i) {
+        if(GetLibSymbolStartEnd(maplib->libraries[i].lib, name, &start, &end)) {
+            int idx = GetElfIndex(maplib->libraries[i].lib);
+            if(idx==-1) {
+                printf_log(LOG_NONE, "Warning, getting Elf info for a native symbol \"%s\" from lib \"%s\"\n", name, GetNameLib(maplib->libraries[i].lib));
+                return NULL;
+            }
+            return maplib->context->elfs[idx];
+        }
+    }
+    // nope, not found
+    return NULL;
+}
+
+int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end)
+{
+    if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end))
+        if(*start || *end)
+            return 1;
+    for(int i=0; i<maplib->libsz; ++i)
+        if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i].lib, name, start, end))
+            if(*start || *end)
+                return 1;
+    // nope, not found
+    return 0;
+}
+
+int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name)
+{
+    uintptr_t start, end;
+    for(int i=0; i<maplib->libsz; ++i)
+        if(GetElfIndex(maplib->libraries[i].lib)==-1)
+            if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i].lib, name, &start, &end))
+                if(start || end)
+                    return 1;
+    // nope, not found
+    return 0;
+
+}
+
+int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self)
+{
+    if(maplib->context->elfs[0]==self || !self) {
+        if(GetSymbolStartEnd(maplib->localsymbols, name, start, end))
+            if(*start || *end)
+                return 1;
+        if(self)
+            return 0;
+    }
+    for(int i=0; i<maplib->libsz; ++i) {
+        if(GetElfIndex(maplib->libraries[i].lib)!=-1 && (!self || maplib->context->elfs[GetElfIndex(maplib->libraries[i].lib)]==self)) {
+            if(GetLibLocalSymbolStartEnd(maplib->libraries[i].lib, name, start, end))
+                if(*start)
+                    return 1;
+            if(self)
+                return 0;
+        }
+    }
+    return 0;
+}
+
+int GetSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self)
+{
+    if(maplib->context->elfs[0]==self) {
+        if(GetSymbolStartEnd(maplib->localsymbols, name, start, end))
+            if(*start || *end)
+                return 1;
+    } else {
+        for(int i=0; i<maplib->libsz; ++i) {
+            if(GetElfIndex(maplib->libraries[i].lib)!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i].lib)]==self))
+                if(GetLibSymbolStartEnd(maplib->libraries[i].lib, name, start, end))
+                    if(*start || *end)
+                        return 1;
+        }
+    }
+    return 0;
+}
+
+int GetNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self)
+{
+    if(maplib->context->elfs[0]==self) {
+        if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end))
+            if(*start || *end)
+                return 1;
+    } else {
+        for(int i=0; i<maplib->libsz; ++i) {
+            if(GetElfIndex(maplib->libraries[i].lib)!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i].lib)]==self))
+                if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i].lib, name, start, end))
+                    if(*start || *end)
+                        return 1;
+        }
+    }
+    return 0;
+}
+
+
+void AddSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz)
+{
+    int ret;
+    khint_t k = kh_put(mapsymbols, mapsymbols, name, &ret);
+    kh_value(mapsymbols, k).offs = addr;
+    kh_value(mapsymbols, k).sz = sz;
+}
+uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name)
+{
+    khint_t k = kh_get(mapsymbols, mapsymbols, name);
+    if(k==kh_end(mapsymbols))
+        return 0;
+    return kh_val(mapsymbols, k).offs;
+}
+void AddWeakSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz)
+{
+    int ret;
+    khint_t k = kh_put(mapsymbols, mapsymbols, name, &ret);
+    if(ret==0)
+        return; // Symbol already there, don't touch it
+    kh_value(mapsymbols, k).offs = addr;
+    kh_value(mapsymbols, k).sz = sz;
+}
+
+int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end)
+{
+    khint_t k = kh_get(mapsymbols, mapsymbols, name);
+    if(k==kh_end(mapsymbols))
+        return 0;
+    *start = kh_val(mapsymbols, k).offs;
+    *end = *start + kh_val(mapsymbols, k).sz;
+    return 1;
+}
+
+const char* GetSymbolName(kh_mapsymbols_t* mapsymbols, void* p, uintptr_t* start, uint32_t* sz)
+{
+    uintptr_t addr = (uintptr_t)p;
+    onesymbol_t *one;
+    kh_foreach_value_ref(mapsymbols, one, 
+        if((one->offs >= addr) && (one->offs+one->sz<addr)) {
+            *start  = one->offs;
+            *sz = one->sz;
+            return kh_key(mapsymbols, __i);
+        }
+    );
+    return NULL;
+}
+
+const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint32_t* sz, const char** libname, void** base)
+{
+    // first, search in self...
+    const char* ret = NULL;
+    uintptr_t offs = 0;
+    uint32_t size = 0;
+    elfheader_t* h = FindElfAddress(my_context, (uintptr_t)p);
+    if(h) {
+        ret = FindNearestSymbolName(h, p, &offs, &size);
+    }
+    if(h) {
+        if(start)
+            *start = (void*)offs;
+        if(sz)
+            *sz = size;
+        if(libname)
+            *libname = ElfName(h);
+        if(base)
+            *base = GetBaseAddress(h);
+        return ret;
+    }
+    // TODO: then search in the other libs...
+    return NULL;
+}
+
+void AddOffsetSymbol(lib_t *maplib, void* offs, const char* name)
+{
+    int ret;
+    khint_t k = kh_put(mapoffsets, maplib->mapoffsets, (uintptr_t)offs, &ret);
+    kh_value(maplib->mapoffsets, k) = (cstr_t)name;
+}
+
+const char* GetNameOffset(lib_t *maplib, void* offs)
+{
+    if(!maplib || !maplib->mapoffsets)
+        return NULL;
+    khint_t k = kh_get(mapoffsets, maplib->mapoffsets, (uintptr_t)offs);
+    if (k!=kh_end(maplib->mapoffsets))
+        return kh_value(maplib->mapoffsets, k);
+    return NULL;
+}
diff --git a/src/librarian/librarian_private.h b/src/librarian/librarian_private.h
new file mode 100755
index 00000000..d70b048f
--- /dev/null
+++ b/src/librarian/librarian_private.h
@@ -0,0 +1,44 @@
+#ifndef __LIBRARIAN_PRIVATE_H_
+#define __LIBRARIAN_PRIVATE_H_
+#include <stdint.h>
+
+#include "custommem.h"
+#include "khash.h"
+
+typedef struct box64context_s box64context_t;
+
+typedef struct onesymbol_s {
+    uintptr_t   offs;
+    uint32_t    sz;
+    // need to track type of symbol?
+    // need to track origin?
+} onesymbol_t;
+
+typedef struct {
+    char        *name;
+    library_t   *lib;
+} onelib_t;
+
+typedef char* cstr_t;
+
+KHASH_MAP_DECLARE_STR(mapsymbols, onesymbol_t)
+
+KHASH_MAP_DECLARE_INT(mapoffsets, cstr_t);
+
+typedef struct lib_s {
+    khash_t(mapsymbols)   *mapsymbols;
+    khash_t(mapsymbols)   *weaksymbols;
+    khash_t(mapsymbols)   *localsymbols;
+    khash_t(mapoffsets)   *mapoffsets;
+    khash_t(mapsymbols)   *globaldata;
+    onelib_t              *libraries;
+    int                   libsz;
+    int                   libcap;
+    int                   ownlibs;
+
+    box64context_t*       context;
+    
+    bridge_t              *bridge;        // all x86 -> arm bridge
+} lib_t;
+
+#endif //__LIBRARIAN_PRIVATE_H_
diff --git a/src/librarian/library.c b/src/librarian/library.c
new file mode 100755
index 00000000..bcd8248a
--- /dev/null
+++ b/src/librarian/library.c
@@ -0,0 +1,700 @@
+#define _GNU_SOURCE
+#define __USE_GNU
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "debug.h"
+#include "library.h"
+#include "elfloader.h"
+#include "bridge.h"
+#include "library_private.h"
+#include "khash.h"
+#include "box64context.h"
+#include "fileutils.h"
+#include "librarian.h"
+#include "librarian_private.h"
+#include "pathcoll.h"
+#include "x64emu.h"
+
+#include "wrappedlibs.h"
+// create the native lib list
+#define GO(P, N) int wrapped##N##_init(library_t* lib, box64context_t *box64); \
+                 void wrapped##N##_fini(library_t* lib);\
+                 int wrapped##N##_get(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz); \
+                 int wrapped##N##_getnoweak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz);
+#include "library_list.h"
+#undef GO
+
+#define GO(P, N) {P, wrapped##N##_init, wrapped##N##_fini, wrapped##N##_get, wrapped##N##_getnoweak},
+wrappedlib_t wrappedlibs[] = {
+#include "library_list.h"
+};
+#undef GO
+
+typedef struct bridged_s {
+    char*       name;
+    uintptr_t   start;
+    uint32_t    end;
+} bridged_t;
+
+KHASH_MAP_INIT_STR(bridgemap, bridged_t)
+
+KHASH_MAP_IMPL_STR(datamap, uint32_t)
+KHASH_MAP_IMPL_STR(symbolmap, wrapper_t)
+KHASH_MAP_IMPL_STR(symbol2map, symbol2_t)
+
+char* Path2Name(const char* path)
+{
+    char* name = (char*)calloc(1, MAX_PATH);
+    char* p = strrchr(path, '/');
+    strcpy(name, (p)?(p+1):path);
+    // name should be libXXX.so.A(.BB.CCCC)
+    // so keep only 2 dot after ".so" (if any)
+    p = strstr(name, ".so");
+    if(p) {
+        p=strchr(p+3, '.');   // this one is ok
+        //if(p) p=strchr(p+1, '.');// this one is ok too
+        if(p) p=strchr(p+1, '.');// this one is not
+        if(p) *p = '\0';
+    }
+    return name;
+}
+int NbDot(const char* name)
+{
+    char *p = strstr(name, ".so");
+    if(!p)
+        return -1;
+    int ret = 0;
+    while(p) {
+        p = strchr(p+1, '.');
+        if(p) ++ret;
+    }
+    return ret;
+}
+
+void EmuLib_Fini(library_t* lib)
+{
+    kh_destroy(mapsymbols, lib->priv.n.mapsymbols);
+    kh_destroy(mapsymbols, lib->priv.n.localsymbols);
+}
+
+int EmuLib_Get(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz)
+{
+    khint_t k;
+    // symbols...
+    k = kh_get(mapsymbols, lib->priv.n.mapsymbols, name);
+    if(k!=kh_end(lib->priv.n.mapsymbols)) {
+        *offs = kh_value(lib->priv.n.mapsymbols, k).offs;
+        *sz = kh_value(lib->priv.n.mapsymbols, k).sz;
+        return 1;
+    }
+    // weak symbols...
+    k = kh_get(mapsymbols, lib->priv.n.weaksymbols, name);
+    if(k!=kh_end(lib->priv.n.weaksymbols)) {
+        *offs = kh_value(lib->priv.n.weaksymbols, k).offs;
+        *sz = kh_value(lib->priv.n.weaksymbols, k).sz;
+        return 1;
+    }
+    return 0;
+}
+int EmuLib_GetNoWeak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz)
+{
+    khint_t k;
+    k = kh_get(mapsymbols, lib->priv.n.mapsymbols, name);
+    if(k!=kh_end(lib->priv.n.mapsymbols)) {
+        *offs = kh_value(lib->priv.n.mapsymbols, k).offs;
+        *sz = kh_value(lib->priv.n.mapsymbols, k).sz;
+        return 1;
+    }
+    return 0;
+}
+int EmuLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz)
+{
+    khint_t k;
+    k = kh_get(mapsymbols, lib->priv.n.localsymbols, name);
+    if(k!=kh_end(lib->priv.n.localsymbols)) {
+        *offs = kh_value(lib->priv.n.localsymbols, k).offs;
+        *sz = kh_value(lib->priv.n.localsymbols, k).sz;
+        return 1;
+    }
+    return 0;
+}
+
+int NativeLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz)
+{
+    return 0;
+}
+
+static void initNativeLib(library_t *lib, box64context_t* context) {
+    int nb = sizeof(wrappedlibs) / sizeof(wrappedlib_t);
+    for (int i=0; i<nb; ++i) {
+        if(strcmp(lib->name, wrappedlibs[i].name)==0) {
+            if(wrappedlibs[i].init(lib, context)) {
+                // error!
+                printf_log(LOG_NONE, "Error initializing native %s (last dlerror is %s)\n", lib->name, dlerror());
+                return; // non blocker...
+            }
+            printf_log(LOG_INFO, "Using native(wrapped) %s\n", lib->name);
+            lib->priv.w.box64lib = context->box64lib;
+            lib->context = context;
+            lib->fini = wrappedlibs[i].fini;
+            lib->get = wrappedlibs[i].get;
+            lib->getnoweak = wrappedlibs[i].getnoweak;
+            lib->getlocal = NativeLib_GetLocal;
+            lib->type = 0;
+            // Call librarian to load all dependant elf
+            for(int i=0; i<lib->priv.w.needed; ++i) {
+                if(AddNeededLib(context->maplib, &lib->needed, 0, lib->priv.w.neededlibs[i], context, NULL)) {  // probably all native, not emulated, so that's fine
+                    printf_log(LOG_NONE, "Error: loading needed libs in elf %s\n", lib->priv.w.neededlibs[i]);
+                    return;
+                }
+            }
+            break;
+        }
+    }
+}
+
+static int loadEmulatedLib(const char* libname, library_t *lib, box64context_t* context)
+{
+    if(FileExist(libname, IS_FILE))
+    {
+        FILE *f = fopen(libname, "rb");
+        if(!f) {
+            printf_log(LOG_NONE, "Error: Cannot open %s\n", libname);
+            return 0;
+        }
+        elfheader_t *elf_header = LoadAndCheckElfHeader(f, libname, 0);
+        if(!elf_header) {
+            printf_log(LOG_DEBUG, "Error: reading elf header of %s\n", libname);    // this one can be too alarming...
+            fclose(f);
+            return 0;
+        }
+        int mainelf = AddElfHeader(context, elf_header);
+
+        if(CalcLoadAddr(elf_header)) {
+            printf_log(LOG_NONE, "Error: reading elf header of %s\n", libname);
+            fclose(f);
+            return 0;
+        }
+        // allocate memory
+        if(AllocElfMemory(context, elf_header, 0)) {
+            printf_log(LOG_NONE, "Error: allocating memory for elf %s\n", libname);
+            fclose(f);
+            return 0;
+        }
+        // Load elf into memory
+        if(LoadElfMemory(f, context, elf_header)) {
+            printf_log(LOG_NONE, "Error: loading in memory elf %s\n", libname);
+            fclose(f);
+            return 0;
+        }
+        // can close the file now
+        fclose(f);
+
+        ElfAttachLib(elf_header, lib);
+
+        lib->type = 1;
+        lib->fini = EmuLib_Fini;
+        lib->get = EmuLib_Get;
+        lib->getnoweak = EmuLib_GetNoWeak;
+        lib->getlocal = EmuLib_GetLocal;
+        lib->priv.n.elf_index = mainelf;
+        lib->priv.n.mapsymbols = kh_init(mapsymbols);
+        lib->priv.n.weaksymbols = kh_init(mapsymbols);
+        lib->priv.n.localsymbols = kh_init(mapsymbols);
+
+        printf_log(LOG_INFO, "Using emulated %s\n", libname);
+        return 1;
+    }
+    return 0;
+}
+
+static void initEmulatedLib(const char* path, library_t *lib, box64context_t* context)
+{
+    char libname[MAX_PATH];
+    strcpy(libname, path);
+    int found = FileExist(libname, IS_FILE);
+    if(!found && !strchr(path, '/'))
+        for(int i=0; i<context->box64_ld_lib.size; ++i)
+        {
+            strcpy(libname, context->box64_ld_lib.paths[i]);
+            strcat(libname, path);
+            if(FileExist(libname, IS_FILE))
+                if(loadEmulatedLib(libname, lib, context))
+                    return;
+        }
+    else
+        loadEmulatedLib(libname, lib, context);
+}
+
+library_t *NewLibrary(const char* path, box64context_t* context)
+{
+    printf_log(LOG_DEBUG, "Trying to load \"%s\"\n", path);
+    library_t *lib = (library_t*)calloc(1, sizeof(library_t));
+    lib->path = strdup(path);
+    lib->name = Path2Name(path);
+    lib->nbdot = NbDot(lib->name);
+    lib->context = context;
+    lib->type = -1;
+    printf_log(LOG_DEBUG, "Simplified name is \"%s\"\n", lib->name);
+    if(box64_nopulse) {
+        if(strstr(lib->name, "libpulse.so")==lib->name || strstr(lib->name, "libpulse-simple.so")==lib->name) {
+            Free1Library(&lib);
+            return NULL;
+        }
+    }
+    if(box64_novulkan) {
+        if(strstr(lib->name, "libvulkan.so")==lib->name) {
+            Free1Library(&lib);
+            return NULL;
+        }
+    }
+    int notwrapped = FindInCollection(lib->name, &context->box64_emulated_libs);
+    // And now, actually loading a library
+    // look for native(wrapped) libs first
+    if(!notwrapped)
+        initNativeLib(lib, context);
+    // then look for a native one
+    if(lib->type==-1)
+        initEmulatedLib(path, lib, context);
+    // still not loaded but notwrapped indicated: use wrapped...
+    if(lib->type==-1 && notwrapped)
+        initNativeLib(lib, context);
+    // nothing loaded, so error...
+    if(lib->type==-1)
+    {
+        Free1Library(&lib);
+        return NULL;
+    }
+
+    lib->bridgemap = kh_init(bridgemap);
+
+    return lib;
+}
+int AddSymbolsLibrary(lib_t *maplib, library_t* lib, x64emu_t* emu)
+{
+    lib->active = 1;
+    if(lib->type==1) {
+        elfheader_t *elf_header = lib->context->elfs[lib->priv.n.elf_index];
+        // add symbols
+        AddSymbols(maplib, lib->priv.n.mapsymbols, lib->priv.n.weaksymbols, lib->priv.n.localsymbols, elf_header);
+    }
+    return 0;
+}
+int FinalizeLibrary(library_t* lib, lib_t* local_maplib, x64emu_t* emu)
+{
+    if(!lib)
+        return 0;
+    if(lib->type==1) {
+        if(lib->priv.n.finalized)
+            return 0;
+        lib->priv.n.finalized = 1;
+        elfheader_t *elf_header = my_context->elfs[lib->priv.n.elf_index];
+        // finalize relocations
+        if(RelocateElf(my_context->maplib, local_maplib, elf_header)) {
+            printf_log(LOG_NONE, "Error: relocating symbols in elf %s\n", lib->name);
+            return 1;
+        }
+        RelocateElfPlt(my_context->maplib, local_maplib, elf_header);
+        if(trace_func) {
+            if (GetGlobalSymbolStartEnd(my_context->maplib, trace_func, &trace_start, &trace_end)) {
+                SetTraceEmu(trace_start, trace_end);
+                printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", trace_func, (void*)trace_start, (void*)trace_end);
+                free(trace_func);
+                trace_func = NULL;
+            } else if(GetLibLocalSymbolStartEnd(lib, trace_func, &trace_start, &trace_end)) {
+                SetTraceEmu(trace_start, trace_end);
+                printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", trace_func, (void*)trace_start, (void*)trace_end);
+                free(trace_func);
+                trace_func = NULL;
+            }
+        }
+        RunElfInit(elf_header, emu);
+    }
+    if(box64_dynarec && strcmp(lib->name, "libfmod.so")==0) {
+        if (GetGlobalSymbolStartEnd(lib->maplib?lib->maplib:my_context->maplib, "FSOUND_Mixer_FPU_Ramp", &fmod_smc_start, &fmod_smc_end)) {
+            printf_log(LOG_INFO, "Detected libfmod with potential SMC part, applying workaround in Dynarec\n");
+        }
+    }
+    return 0;
+}
+
+int ReloadLibrary(library_t* lib, x64emu_t* emu)
+{
+    lib->active = 1;
+    if(lib->type==1) {
+        elfheader_t *elf_header = lib->context->elfs[lib->priv.n.elf_index];
+        // reload image in memory and re-run the mapping
+        char libname[MAX_PATH];
+        strcpy(libname, lib->path);
+        int found = FileExist(libname, IS_FILE);
+        if(!found && !strchr(lib->path, '/'))
+            for(int i=0; i<lib->context->box64_ld_lib.size; ++i)
+            {
+                strcpy(libname, lib->context->box64_ld_lib.paths[i]);
+                strcat(libname, lib->path);
+                if(FileExist(libname, IS_FILE))
+                    break;
+            }
+        if(!FileExist(libname, IS_FILE)) {
+            printf_log(LOG_NONE, "Error: open file to re-load elf %s\n", libname);
+            return 1;   // failed to reload...
+        }
+        FILE *f = fopen(libname, "rb");
+        if(!f) {
+            printf_log(LOG_NONE, "Error: cannot open file to re-load elf %s (errno=%d/%s)\n", libname, errno, strerror(errno));
+            return 1;   // failed to reload...
+        }
+        if(ReloadElfMemory(f, lib->context, elf_header)) {
+            printf_log(LOG_NONE, "Error: re-loading in memory elf %s\n", libname);
+            fclose(f);
+            return 1;
+        }
+        // can close the file now
+        fclose(f);
+        if(RelocateElf(lib->context->maplib, lib->maplib, elf_header)) {
+            printf_log(LOG_NONE, "Error: relocating symbols in elf %s\n", lib->name);
+            return 1;
+        }
+        RelocateElfPlt(lib->context->maplib, lib->maplib, elf_header);
+        // init (will use PltRelocator... because some other libs are not yet resolved)
+        RunElfInit(elf_header, emu);
+    }
+    return 0;
+}
+
+void InactiveLibrary(library_t* lib)
+{
+    lib->active = 0;
+}
+
+void Free1Library(library_t **lib)
+{
+    if(!(*lib)) return;
+
+    if((*lib)->type!=-1 && (*lib)->fini) {
+        (*lib)->fini(*lib);
+    }
+    free((*lib)->name);
+    free((*lib)->path);
+    free((*lib)->altmy);
+
+    if((*lib)->bridgemap) {
+        bridged_t *br;
+        kh_foreach_value_ref((*lib)->bridgemap, br,
+            free(br->name);
+        );
+        kh_destroy(bridgemap, (*lib)->bridgemap);
+    }
+    if((*lib)->symbolmap)
+        kh_destroy(symbolmap, (*lib)->symbolmap);
+    if((*lib)->wsymbolmap)
+        kh_destroy(symbolmap, (*lib)->wsymbolmap);
+    if((*lib)->datamap)
+        kh_destroy(datamap, (*lib)->datamap);
+    if((*lib)->wdatamap)
+        kh_destroy(datamap, (*lib)->wdatamap);
+    if((*lib)->mydatamap)
+        kh_destroy(datamap, (*lib)->mydatamap);
+    if((*lib)->mysymbolmap)
+        kh_destroy(symbolmap, (*lib)->mysymbolmap);
+    if((*lib)->stsymbolmap)
+        kh_destroy(symbolmap, (*lib)->stsymbolmap);
+    if((*lib)->symbol2map)
+        kh_destroy(symbol2map, (*lib)->symbol2map);
+    free_neededlib(&(*lib)->needed);
+
+    if((*lib)->maplib)
+        FreeLibrarian(&(*lib)->maplib);
+
+    free(*lib);
+    *lib = NULL;
+}
+
+char* GetNameLib(library_t *lib)
+{
+    return lib->name;
+}
+int IsSameLib(library_t* lib, const char* path)
+{
+    int ret = 0;
+    if(!lib) 
+        return 0;
+    char* name = Path2Name(path);
+    if(strcmp(name, lib->name)==0)
+        ret=1;
+    else {
+        int n = NbDot(name);
+        if(n>=0 && n<lib->nbdot)
+            if(strncmp(name, lib->name, strlen(name))==0)
+                ret=1;
+    }
+
+    free(name);
+    return ret;
+}
+int GetLibSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end)
+{
+    if(!name[0] || !lib->active)
+        return 0;
+    khint_t k;
+    // check first if already in the map
+    k = kh_get(bridgemap, lib->bridgemap, name);
+    if(k!=kh_end(lib->bridgemap)) {
+        *start = kh_value(lib->bridgemap, k).start;
+        *end = kh_value(lib->bridgemap, k).end;
+        return 1;
+    }
+    // get a new symbol
+    if(lib->get(lib, name, start, end)) {
+        *end += *start;     // lib->get(...) gives size, not end
+        char* symbol = strdup(name);
+        int ret;
+        k = kh_put(bridgemap, lib->bridgemap, symbol, &ret);
+        kh_value(lib->bridgemap, k).name = symbol;
+        kh_value(lib->bridgemap, k).start = *start;
+        kh_value(lib->bridgemap, k).end = *end;
+        return 1;
+    }
+    // nope
+    return 0;
+}
+int GetLibNoWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end)
+{
+    if(!name[0] || !lib->active)
+        return 0;
+    khint_t k;
+    // get a new symbol
+    if(lib->getnoweak(lib, name, start, end)) {
+        *end += *start;     // lib->get(...) gives size, not end
+        // check if already in the map
+        k = kh_get(bridgemap, lib->bridgemap, name);
+        if(k!=kh_end(lib->bridgemap)) {
+            *start = kh_value(lib->bridgemap, k).start;
+            *end = kh_value(lib->bridgemap, k).end;
+            return 1;
+        }
+        char* symbol = strdup(name);
+        int ret;
+        k = kh_put(bridgemap, lib->bridgemap, symbol, &ret);
+        kh_value(lib->bridgemap, k).name = symbol;
+        kh_value(lib->bridgemap, k).start = *start;
+        kh_value(lib->bridgemap, k).end = *end;
+        return 1;
+    }
+    // nope
+    return 0;
+}
+int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end)
+{
+    if(!name[0] || !lib->active)
+        return 0;
+    khint_t k;
+    // check first if already in the map
+    k = kh_get(bridgemap, lib->bridgemap, name);
+    if(k!=kh_end(lib->bridgemap)) {
+        *start = kh_value(lib->bridgemap, k).start;
+        *end = kh_value(lib->bridgemap, k).end;
+        return 1;
+    }
+    // get a new symbol
+    if(lib->getlocal(lib, name, start, end)) {
+        *end += *start;     // lib->get(...) gives size, not end
+        char* symbol = strdup(name);
+        int ret;
+        k = kh_put(bridgemap, lib->bridgemap, symbol, &ret);
+        kh_value(lib->bridgemap, k).name = symbol;
+        kh_value(lib->bridgemap, k).start = *start;
+        kh_value(lib->bridgemap, k).end = *end;
+        return 1;
+    }
+    // nope
+    return 0;
+}
+int GetElfIndex(library_t* lib)
+{
+    if(!lib || lib->type!=1)
+        return -1;
+    return lib->priv.n.elf_index;
+}
+
+int getSymbolInMaps(library_t*lib, const char* name, int noweak, uintptr_t *addr, uint32_t *size)
+{
+    if(!lib->active)
+        return 0;
+    khint_t k;
+    void* symbol;
+    // check in datamap
+    k = kh_get(datamap, lib->datamap, name);
+    if (k!=kh_end(lib->datamap)) {
+        symbol = dlsym(lib->priv.w.lib, kh_key(lib->datamap, k));
+        if(symbol) {
+            // found!
+            *addr = (uintptr_t)symbol;
+            *size = kh_value(lib->datamap, k);
+            return 1;
+        }
+    }
+    if(!noweak) {
+        k = kh_get(datamap, lib->wdatamap, name);
+        if (k!=kh_end(lib->wdatamap)) {
+            symbol = dlsym(lib->priv.w.lib, kh_key(lib->wdatamap, k));
+            if(symbol) {
+                // found!
+                *addr = (uintptr_t)symbol;
+                *size = kh_value(lib->wdatamap, k);
+                return 1;
+            }
+        }
+    }
+    // check in mydatamap
+    k = kh_get(datamap, lib->mydatamap, name);
+    if (k!=kh_end(lib->mydatamap)) {
+        char buff[200];
+        if(lib->altmy)
+            strcpy(buff, lib->altmy);
+        else
+            strcpy(buff, "my_");
+        strcat(buff, name);
+        symbol = dlsym(lib->priv.w.box64lib, buff);
+        if(!symbol)
+            printf_log(LOG_NONE, "Warning, data %s not found\n", buff);
+        if(symbol) {
+            // found!
+            *addr = (uintptr_t)symbol;
+            *size = kh_value(lib->mydatamap, k);
+            return 1;
+        }
+    }
+    // check in mysymbolmap
+    k = kh_get(symbolmap, lib->mysymbolmap, name);
+    if (k!=kh_end(lib->mysymbolmap)) {
+        char buff[200];
+        if(lib->altmy)
+            strcpy(buff, lib->altmy);
+        else
+            strcpy(buff, "my_");
+        strcat(buff, name);
+        symbol = dlsym(lib->priv.w.box64lib, buff);
+        if(!symbol) {
+            printf_log(LOG_NONE, "Warning, function %s not found\n", buff);
+        } else 
+            AddOffsetSymbol(lib->context->maplib, symbol, name);
+        *addr = AddBridge(lib->priv.w.bridge, kh_value(lib->mysymbolmap, k), symbol, 0);
+        *size = sizeof(void*);
+        return 1;
+    }
+    // check in stsymbolmap (return struct...)
+    k = kh_get(symbolmap, lib->stsymbolmap, name);
+    if (k!=kh_end(lib->stsymbolmap)) {
+        char buff[200];
+        if(lib->altmy)
+            strcpy(buff, lib->altmy);
+        else
+            strcpy(buff, "my_");
+        strcat(buff, name);
+        symbol = dlsym(lib->priv.w.box64lib, buff);
+        if(!symbol) {
+            printf_log(LOG_NONE, "Warning, function %s not found\n", buff);
+        } else 
+            AddOffsetSymbol(lib->context->maplib, symbol, name);
+        *addr = AddBridge(lib->priv.w.bridge, kh_value(lib->stsymbolmap, k), symbol, 4);    // all of this for this little "4"
+        *size = sizeof(void*);
+        return 1;
+    }
+    // check in symbolmap
+    k = kh_get(symbolmap, lib->symbolmap, name);
+    if (k!=kh_end(lib->symbolmap)) {
+        symbol = dlsym(lib->priv.w.lib, name);
+        if(!symbol && lib->priv.w.altprefix) {
+            char newname[200];
+            strcpy(newname, lib->priv.w.altprefix);
+            strcat(newname, name);
+            symbol = dlsym(lib->priv.w.lib, newname);
+        }
+        if(!symbol) {
+            printf_log(LOG_INFO, "Warning, function %s not found in lib %s\n", name, lib->name);
+            return 0;
+        } else 
+            AddOffsetSymbol(lib->context->maplib, symbol, name);
+        *addr = AddBridge(lib->priv.w.bridge, kh_value(lib->symbolmap, k), symbol, 0);
+        *size = sizeof(void*);
+        return 1;
+    }
+    if(!noweak) {
+        k = kh_get(symbolmap, lib->wsymbolmap, name);
+        if (k!=kh_end(lib->wsymbolmap)) {
+            symbol = dlsym(lib->priv.w.lib, name);
+            if(!symbol && lib->priv.w.altprefix) {
+                char newname[200];
+                strcpy(newname, lib->priv.w.altprefix);
+                strcat(newname, name);
+                symbol = dlsym(lib->priv.w.lib, newname);
+            }
+            if(!symbol) {
+                printf_log(LOG_INFO, "Warning, function %s not found in lib %s\n", name, lib->name);
+                return 0;
+            } else 
+                AddOffsetSymbol(lib->context->maplib, symbol, name);
+            *addr = AddBridge(lib->priv.w.bridge, kh_value(lib->wsymbolmap, k), symbol, 0);
+            *size = sizeof(void*);
+            return 1;
+        }
+    }
+    // check in symbol2map
+    k = kh_get(symbol2map, lib->symbol2map, name);
+    if (k!=kh_end(lib->symbol2map)) 
+        if(!noweak || !kh_value(lib->symbol2map, k).weak)
+        {
+            symbol = dlsym(lib->priv.w.lib, kh_value(lib->symbol2map, k).name);
+            if(!symbol)
+                symbol = dlsym(RTLD_DEFAULT, kh_value(lib->symbol2map, k).name);    // search globaly maybe
+            if(!symbol) {
+                printf_log(LOG_INFO, "Warning, function %s not found in lib %s\n", kh_value(lib->symbol2map, k).name, lib->name);
+                return 0;
+            } else 
+                AddOffsetSymbol(lib->context->maplib, symbol, name);
+            *addr = AddBridge(lib->priv.w.bridge, kh_value(lib->symbol2map, k).w, symbol, 0);
+            *size = sizeof(void*);
+            return 1;
+        }
+
+    return 0;
+}
+
+int GetNeededLibN(library_t* lib) {
+    return lib->needed.size;
+}
+library_t* GetNeededLib(library_t* lib, int idx)
+{
+    if(idx<0 || idx>=lib->needed.size)
+        return NULL;
+    return lib->needed.libs[idx];
+}
+needed_libs_t* GetNeededLibs(library_t* lib)
+{
+    return &lib->needed;
+}
+
+void* GetHandle(library_t* lib)
+{
+    if(!lib)
+        return NULL;
+    if(lib->type!=0)
+        return NULL;
+    return lib->priv.w.lib;
+}
+
+lib_t* GetMaplib(library_t* lib)
+{
+    if(!lib)
+        return NULL;
+    return lib->maplib;
+}
\ No newline at end of file
diff --git a/src/librarian/library_private.h b/src/librarian/library_private.h
new file mode 100755
index 00000000..78a7da94
--- /dev/null
+++ b/src/librarian/library_private.h
@@ -0,0 +1,101 @@
+#ifndef __LIBRARY_PRIVATE_H_
+#define __LIBRARY_PRIVATE_H_
+#include <stdint.h>
+
+#include "custommem.h"
+#include "khash.h"
+#include "wrappedlibs.h"
+#include "box64context.h"
+
+typedef struct lib_s    lib_t;
+typedef struct bridge_s bridge_t;
+typedef struct kh_bridgemap_s kh_bridgemap_t;
+typedef struct kh_mapsymbols_s kh_mapsymbols_t;
+
+typedef struct x64emu_s x64emu_t;
+typedef void (*wrapper_t)(x64emu_t* emu, uintptr_t fnc);
+
+typedef struct symbol2_s {
+    wrapper_t    w;
+    const char*  name;
+    int          weak;
+} symbol2_t;
+
+KHASH_MAP_DECLARE_STR(symbolmap, wrapper_t)
+KHASH_MAP_DECLARE_STR(symbol2map, symbol2_t)
+KHASH_MAP_DECLARE_STR(datamap, uint32_t)
+
+
+#ifndef MAX_PATH
+#define MAX_PATH 4096
+#endif
+
+typedef struct wlib_s {
+    bridge_t        *bridge;
+    void*           lib;        // dlopen result
+    void*           priv;       // actual private
+    void*           p2;         // second private
+    void*           box64lib;   // ref to the dlopen on box86 itself from context
+    char*           altprefix;  // if function names are mangled..
+    int             needed;
+    char**          neededlibs;
+} wlib_t;
+
+typedef struct nlib_s {
+    int             elf_index;
+    int             finalized;
+    kh_mapsymbols_t *mapsymbols;
+    kh_mapsymbols_t *weaksymbols;
+    kh_mapsymbols_t *localsymbols;
+} nlib_t;
+
+typedef struct library_s {
+    char*               name;   // <> path
+    char*               path;   // original path
+    int                 nbdot;  // nombre of "." after .so
+    int                 type;   // 0: native(wrapped) 1: emulated(elf) -1: undetermined
+    int                 active;
+    wrappedlib_fini_t   fini;
+    wrappedlib_get_t    get;        // get weak and no weak
+    wrappedlib_get_t    getnoweak;  // get only non weak symbol
+    wrappedlib_get_t    getlocal;
+    union {
+        wlib_t  w;     
+        nlib_t  n;
+    }                   priv;  // private lib data
+    box64context_t      *context;   // parent context
+    kh_bridgemap_t      *bridgemap;
+    kh_symbolmap_t      *symbolmap;
+    kh_symbolmap_t      *wsymbolmap;
+    kh_symbolmap_t      *mysymbolmap;
+    kh_symbolmap_t      *stsymbolmap;
+    kh_symbol2map_t     *symbol2map;
+    kh_datamap_t        *datamap;
+    kh_datamap_t        *wdatamap;
+    kh_datamap_t        *mydatamap;
+    char                *altmy;      // to avoid duplicate symbol, like with SDL1/SDL2
+    needed_libs_t       needed;
+    lib_t               *maplib;    // local maplib, for dlopen'd library with LOCAL binding (most of the dlopen)
+} library_t;
+
+// type for map elements
+typedef struct map_onesymbol_s {
+    const char* name;
+    wrapper_t   w;
+    int         weak;
+} map_onesymbol_t;
+typedef struct map_onesymbol2_s {
+    const char* name;
+    wrapper_t   w;
+    int         weak;
+    const char* name2;
+} map_onesymbol2_t;
+typedef struct map_onedata_s {
+    const char* name;
+    uint32_t    sz;
+    int         weak;
+} map_onedata_t;
+
+int getSymbolInMaps(library_t*lib, const char* name, int noweak, uintptr_t *addr, uint32_t *size);  // Add bridges to functions
+
+#endif //__LIBRARY_PRIVATE_H_
\ No newline at end of file
diff --git a/src/library_list.h b/src/library_list.h
new file mode 100755
index 00000000..7d24d334
--- /dev/null
+++ b/src/library_list.h
@@ -0,0 +1,146 @@
+#ifndef GO
+#error Nope
+#endif
+
+GO("libc.so.6", libc)
+//GO("libpthread.so.0", libpthread)
+//GO("librt.so.1", librt)
+//GO("libGL.so.1", libgl)
+//GO("libGL.so", libgl)
+//GO("libGLU.so.1", libglu)
+//GO("libX11.so.6", libx11)
+//GO("libasound.so.2", libasound)
+//GO("libdl.so.2", libdl)
+//GO("libm.so.6", libm)
+//GO("libSDL2-2.0.so.0", sdl2)
+//GO("libSDL2-2.0.so.1", sdl2)
+//GO("libSDL2.so", sdl2)
+//GO("libsdl2-2.0.so.0", sdl2)
+//GO("libSDL2_mixer-2.0.so.0", sdl2mixer)
+//GO("libSDL2_image-2.0.so.0", sdl2image)
+//GO("libSDL2_ttf-2.0.so.0", sdl2ttf)
+//GO("libSDL-1.2.so.0", sdl1)
+//GO("libSDL-1.1.so.0", sdl1)
+//GO("libSDL_mixer-1.2.so.0", sdl1mixer)
+//GO("libSDL_image-1.2.so.0", sdl1image)
+//GO("libSDL_ttf-2.0.so.0", sdl1ttf)
+//GO("libsmpeg-0.4.so.0", smpeg)
+//GO("libsmpeg2-2.0.so.0", smpeg2)
+//GO("libvorbisfile.so.3", vorbisfile)
+//GO("libvorbis.so.0", libvorbis)
+//GO("libogg.so.0", libogg)
+//GO("libpng12.so.0", png12)
+//GO("libpng16.so.16", png16)
+//GO("libXxf86vm.so.1", libxxf86vm)
+//GO("libXinerama.so.1", xinerama)
+//GO("libXrandr.so.2", libxrandr)
+//GO("libXext.so.6", libxext)
+//GO("libXfixes.so.3", libxfixes)
+//GO("libXcursor.so.1", libxcursor)
+//GO("libXrender.so.1", libxrender)
+//GO("libXi.so.6", libxi)
+//GO("libXss.so.1", libxss)
+//GO("libXpm.so.4", libxpm)
+//GO("libXau.so.6", libxau)
+//GO("libXdmcp.so.6", libxdmcp)
+//GO("libX11-xcb.so.1", libx11xcb)
+//GO("libxcb.so.1", libxcb)
+//GO("libxcb-xfixes.so.0", libxcbxfixes)
+//GO("libxcb-shape.so.0", libxcbshape)
+//GO("libxcb-shm.so.0", libxcbshm)
+//GO("libxcb-randr.so.0", libxcbrandr)
+//GO("libxcb-image.so.0", libxcbimage)
+//GO("libxcb-keysyms.so.1", libxcbkeysyms)
+//GO("libxcb-xtest.so.0", libxcbxtest)
+//GO("libxcb-dri2.so.0", libxcbdri2)
+//GO("libxcb-dri3.so.0", libxcbdri3)
+//GO("libxcb-present.so.0", libxcbpresent)
+//GO("libXtst.so.6", libxtst)
+//GO("libXt.so.6", libxt)
+//GO("libXcomposite.so.1", libxcomposite)
+//GO("libXdamage.so.1", libxdamage)
+//GO("libXmu.so.6", libxmu)
+//GO("libz.so.1", libz)
+//GO("libopenal.so.1", openal)
+//GO("libopenal.so.0", openal)
+//GO("libopenal.so", openal)
+//GO("openal.so", openal)
+//GO("libalut.so.0", alut)
+//GO("libjpeg.so.8", libjpeg)
+//GO("libjpeg.so.62", libjpeg62)
+//GO("libturbojpeg.so.0", turbojpeg)
+//GO("libcurl.so.4", curl)
+//GO("libcurl-gnutls.so.4", curl)
+//GO("libudev.so.0", udev0)
+//GO("libudev.so.1", udev1)
+//GO("libdbus-1.so.3", dbus)
+//GO("libiconv.so.2", iconv)
+//GO("libdrm.so.2", libdrm)
+//GO("libcrypto.so.1", crypto)
+//GO("libssl.so.1", libssl)
+//GO("libcrypt.so.1", libcrypt)
+//GO("libutil.so.1", util)
+//GO("libuuid.so.1", libuuid)
+//GO("libresolv.so.2", libresolv)
+//GO("libpulse-simple.so.0", pulsesimple)
+//GO("libpulse.so.0", pulse)
+//GO("libsndfile.so.1", libsndfile)
+//GO("libgtk-x11-2.0.so.0", gtkx112)
+//GO("libgdk-x11-2.0.so.0", gdkx112)
+//GO("libgtk-3.so.0", gtk3)
+//GO("libgdk-3.so.0", gdk3)
+//GO("libgdk_pixbuf-2.0.so.0", gdkpixbuf2)
+//GO("libgio-2.0.so.0", gio2)
+//GO("libgmodule-2.0.so.0", gmodule2)
+//GO("libgobject-2.0.so.0", gobject2)
+//GO("libglib-2.0.so.0", glib2)
+//GO("libgthread-2.0.so.0", gthread2)
+//GO("libgstreamer-0.10.so.0", gstreamer010)
+//GO("libgstinterfaces-0.10.so.0", gstinterfaces010)
+//GO("libdbusmenu-gtk.so.4", dbusmenugtk)
+//GO("libdbusmenu-glib.so.4", dbusmenuglib)
+//GO("libdbus-glib-1.so.2", dbusglib1)
+//GO("libgudev-1.0.so.0", gudev1)
+//GO("libappindicator.so.1", appindicator)
+//GO("libatk-1.0.so.0", atk)
+//GO("libpangoft2-1.0.so", pangoft2)
+//GO("libpangoft2-1.0.so.0", pangoft2)
+//GO("libpangocairo-1.0.so.0", pangocairo)
+//GO("libcairo.so.2", cairo)
+//GO("libpango-1.0.so.0", pango)
+//GO("libnm.so.0", libnm)
+//GO("libnm-glib.so.4", libnm)
+//GO("libnm-util.so.2", libnm)
+//GO("libfontconfig.so.1", fontconfig)
+//GO("libfreetype.so.6", freetype)
+//GO("libbz2.so.1", bz2)
+//GO("libSM.so.6", libsm)
+//GO("libICE.so.6", libice)
+//GO("libusb-1.0.so.0", libusb1)
+//GO("libncursesw.so.5", libncursesw)
+//GO("libformw.so.5", libformw)
+//GO("libncurses.so.5", libncurses)
+//GO("libtinfo.so.5", libtinfo)
+//GO("libncurses.so.6", libncurses6)
+//GO("libtinfo.so.6", libtinfo6)
+//GO("libtcmalloc_minimal.so.4", tcmallocminimal)
+//GO("libmpg123.so.0", mpg123)
+//GO("libgnutls.so.30", gnutls)
+//GO("libcups.so.2", libcups)
+//GO("d3dadapter9.so.1", d3dadapter9)
+//GO("libvulkan.so.1", vulkan)
+//GO("libvulkan.so", vulkan)
+//GO("libwayland-client.so.0", waylandclient)
+//GO("libxml2.so.2", xml2)
+//GO("libxslt.so.1", xslt)
+//GO("libldap_r-2.4.so.2", ldapr)
+//GO("liblber-2.4.so.2", lber)
+//GO("libnsl.so.1", nsl)
+//GO("liblcms2.so.2", lcms2)
+//GO("libkrb5.so.3", krb5)
+//GO("libgssapi_krb5.so.2", gssapikrb5)
+//GO("libtiff.so.5", libtiff)
+
+GO("ld-linux-x86-64.so.2", ldlinux)
+
+//GO("crashhandler.so", crashhandler)
diff --git a/src/libtools/threads.c b/src/libtools/threads.c
index a245d6a9..64cc414a 100755
--- a/src/libtools/threads.c
+++ b/src/libtools/threads.c
@@ -12,7 +12,7 @@
 #include "box64context.h"
 #include "threads.h"
 #include "emu/x64emu_private.h"
-//#include "tools/bridge_private.h"
+#include "tools/bridge_private.h"
 #include "x64run.h"
 #include "x64emu.h"
 #include "box64stack.h"
@@ -22,7 +22,7 @@
 #include "emu/x64run_private.h"
 #include "x64trace.h"
 //#include "dynarec.h"
-//#include "bridge.h"
+#include "bridge.h"
 #ifdef DYNAREC
 #include "dynablock.h"
 #endif
@@ -756,31 +756,31 @@ EXPORT int my_pthread_mutex_unlock(pthread_mutex_t *m)
 
 #endif
 #endif
-//static void emujmpbuf_destroy(void* p)
-//{
-//	emu_jmpbuf_t *ej = (emu_jmpbuf_t*)p;
-//	free(ej->jmpbuf);
-//	free(ej);
-//}
+static void emujmpbuf_destroy(void* p)
+{
+	emu_jmpbuf_t *ej = (emu_jmpbuf_t*)p;
+	free(ej->jmpbuf);
+	free(ej);
+}
 
-//static pthread_key_t jmpbuf_key;
+static pthread_key_t jmpbuf_key;
 
-//emu_jmpbuf_t* GetJmpBuf()
-//{
-//	emu_jmpbuf_t *ejb = (emu_jmpbuf_t*)pthread_getspecific(jmpbuf_key);
-//	if(!ejb) {
-//		ejb = (emu_jmpbuf_t*)calloc(1, sizeof(emu_jmpbuf_t));
-//		ejb->jmpbuf = calloc(1, sizeof(struct __jmp_buf_tag));
-//		pthread_setspecific(jmpbuf_key, ejb);
-//	}
-//	return ejb;
-//}
+emu_jmpbuf_t* GetJmpBuf()
+{
+	emu_jmpbuf_t *ejb = (emu_jmpbuf_t*)pthread_getspecific(jmpbuf_key);
+	if(!ejb) {
+		ejb = (emu_jmpbuf_t*)calloc(1, sizeof(emu_jmpbuf_t));
+		ejb->jmpbuf = calloc(1, sizeof(struct __jmp_buf_tag));
+		pthread_setspecific(jmpbuf_key, ejb);
+	}
+	return ejb;
+}
 
 void init_pthread_helper()
 {
 //	InitCancelThread();
 //	mapcond = kh_init(mapcond);
-//	pthread_key_create(&jmpbuf_key, emujmpbuf_destroy);
+	pthread_key_create(&jmpbuf_key, emujmpbuf_destroy);
 #ifndef NOALIGN
 //	unaligned_mutex = kh_init(mutex);
 #endif
diff --git a/src/tools/callback.c b/src/tools/callback.c
new file mode 100755
index 00000000..8c46139e
--- /dev/null
+++ b/src/tools/callback.c
@@ -0,0 +1,86 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "debug.h"
+#include "x64emu.h"
+#include "x64run.h"
+#include "emu/x64emu_private.h"
+#include "emu/x64run_private.h"
+#include "box64context.h"
+#include "box64stack.h"
+#include "dynarec.h"
+
+EXPORTDYN
+uint64_t RunFunction(box64context_t *context, uintptr_t fnc, int nargs, ...)
+{
+    x64emu_t *emu = thread_get_emu();
+
+    if(nargs>6)
+        R_ESP -= (nargs-6)*4;   // need to push in reverse order
+
+    uint64_t *p = (uint64_t*)R_RSP;
+
+    va_list va;
+    va_start (va, nargs);
+    for (int i=0; i<nargs; ++i) {
+        if(i<6) {
+            int nn[] = {_DI, _SI, _DX, _CX, _R8, _R9};
+            emu->regs[nn[i]].q[0] = va_arg(va, uint64_t);
+        } else {
+            *p = va_arg(va, uint64_t);
+            p++;
+        }
+    }
+    va_end (va);
+
+    DynaCall(emu, fnc);
+    if(nargs>6)
+        R_ESP+=((nargs-6)*4);
+
+    uint64_t ret = R_RAX;
+
+    return ret;
+}
+
+EXPORTDYN
+uint64_t RunFunctionWithEmu(x64emu_t *emu, int QuitOnLongJump, uintptr_t fnc, int nargs, ...)
+{
+    if(nargs>6)
+        R_ESP -= (nargs-6)*4;   // need to push in reverse order
+
+    uint64_t *p = (uint64_t*)R_RSP;
+
+    va_list va;
+    va_start (va, nargs);
+    for (int i=0; i<nargs; ++i) {
+        if(i<6) {
+            int nn[] = {_DI, _SI, _DX, _CX, _R8, _R9};
+            emu->regs[nn[i]].q[0] = va_arg(va, uint64_t);
+        } else {
+            *p = va_arg(va, uint64_t);
+            p++;
+        }
+    }
+    va_end (va);
+
+    uintptr_t oldip = R_RIP;
+    int old_quit = emu->quit;
+    int oldlong = emu->quitonlongjmp;
+
+    emu->quit = 0;
+    emu->quitonlongjmp = QuitOnLongJump;
+
+    DynaCall(emu, fnc);
+
+    if(oldip==R_RIP && nargs>6)
+        R_ESP+=((nargs-6)*4);   // restore stack only if EIP is the one expected (else, it means return value is not the one expected)
+
+    emu->quit = old_quit;
+    emu->quitonlongjmp = oldlong;
+
+
+    return R_RAX;
+}
diff --git a/src/wrapped/generated/functions_list.txt b/src/wrapped/generated/functions_list.txt
new file mode 100644
index 00000000..147507f1
--- /dev/null
+++ b/src/wrapped/generated/functions_list.txt
@@ -0,0 +1,15 @@
+#() vFE
+#() vFv
+#() pFE
+#() pFp
+#() vFpp
+#() iFEp
+#() pFEp
+#() iFEpp
+#() pFEpi
+#() pFEpp
+#() iFEpip
+#() pFEppi
+#() pFEppp
+#() iFipppi
+#() pFEv -> pFE
diff --git a/src/wrapped/generated/wrapper.c b/src/wrapped/generated/wrapper.c
new file mode 100644
index 00000000..6598ae7e
--- /dev/null
+++ b/src/wrapped/generated/wrapper.c
@@ -0,0 +1,102 @@
+/*****************************************************************
+ * File automatically generated by rebuild_wrappers.py (v1.2.0.09)
+ *****************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "wrapper.h"
+#include "emu/x64emu_private.h"
+#include "emu/x87emu_private.h"
+#include "regs.h"
+#include "x64emu.h"
+
+typedef union ui64_s {
+    int64_t     i;
+    uint64_t    u;
+    uint32_t    d[2];
+} ui64_t;
+
+typedef struct _2uint_struct_s {
+	uint32_t	a;
+	uint32_t	b;
+} _2uint_struct_t;
+
+extern void* my__IO_2_1_stderr_;
+extern void* my__IO_2_1_stdin_ ;
+extern void* my__IO_2_1_stdout_;
+
+static void* io_convert(void* v)
+{
+	if(!v)
+		return v;
+	if(v==my__IO_2_1_stderr_)
+		return stderr;
+	if(v==my__IO_2_1_stdin_)
+		return stdin;
+	if(v==my__IO_2_1_stdout_)
+		return stdout;
+	return v;
+}
+
+typedef struct my_GValue_s
+{
+  int         g_type;
+  union {
+    int        v_int;
+    int64_t    v_int64;
+    uint64_t   v_uint64;
+    float      v_float;
+    double     v_double;
+    void*      v_pointer;
+  } data[2];
+} my_GValue_t;
+
+static void alignGValue(my_GValue_t* v, void* value)
+{
+    v->g_type = *(int*)value;
+    memcpy(v->data, value+4, 2*sizeof(double));
+}
+static void unalignGValue(void* value, my_GValue_t* v)
+{
+    *(int*)value = v->g_type;
+    memcpy(value+4, v->data, 2*sizeof(double));
+}
+
+void* VulkanFromx86(void* src, void** save);
+void VulkanTox86(void* src, void* save);
+
+#define ST0val ST0.d
+
+int of_convert(int);
+typedef void (*vFE_t)(x64emu_t*);
+typedef void (*vFv_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 void* (*pFEp_t)(x64emu_t*, void*);
+typedef int32_t (*iFEpp_t)(x64emu_t*, void*, void*);
+typedef void* (*pFEpi_t)(x64emu_t*, void*, int32_t);
+typedef void* (*pFEpp_t)(x64emu_t*, void*, void*);
+typedef int32_t (*iFEpip_t)(x64emu_t*, void*, int32_t, 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 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 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 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 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 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)); }
+
+void pFEv(x64emu_t *emu, uintptr_t fcn) { pFE_t fn = (pFE_t)fcn; R_RAX=(uintptr_t)fn(emu); }
diff --git a/src/wrapped/generated/wrapper.h b/src/wrapped/generated/wrapper.h
new file mode 100644
index 00000000..19ccf6b3
--- /dev/null
+++ b/src/wrapped/generated/wrapper.h
@@ -0,0 +1,50 @@
+/*****************************************************************
+ * File automatically generated by rebuild_wrappers.py (v1.2.0.09)
+ *****************************************************************/
+#ifndef __WRAPPER_H_
+#define __WRAPPER_H_
+#include <stdint.h>
+#include <string.h>
+
+typedef struct x64emu_s x64emu_t;
+
+// the generic wrapper pointer functions
+typedef void (*wrapper_t)(x64emu_t* emu, uintptr_t fnc);
+
+// list of defined wrapper
+// v = void, i = int32, u = uint32, U/I= (u)int64
+// l = signed long, L = unsigned long (long is an int with the size of a pointer)
+// p = pointer, P = callback
+// f = float, d = double, D = long double, K = fake long double
+// V = vaargs, E = current x86emu struct, e = ref to current x86emu struct
+// 0 = constant 0, 1 = constant 1
+// o = stdout
+// C = unsigned byte c = char
+// W = unsigned short w = short
+// O = libc O_ flags bitfield
+// S = _IO_2_1_stdXXX_ pointer (or FILE*)
+// Q = ...
+// 2 = struct of 2 uint
+// P = Vulkan struture pointer
+// G = a single GValue pointer
+// N = ... automatically sending 1 arg
+// M = ... automatically sending 2 args
+
+void vFE(x64emu_t *emu, uintptr_t fnc);
+void vFv(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 pFEp(x64emu_t *emu, uintptr_t fnc);
+void iFEpp(x64emu_t *emu, uintptr_t fnc);
+void pFEpi(x64emu_t *emu, uintptr_t fnc);
+void pFEpp(x64emu_t *emu, uintptr_t fnc);
+void iFEpip(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);
+
+void pFEv(x64emu_t *emu, uintptr_t fnc);
+
+#endif //__WRAPPER_H_
diff --git a/src/wrapped/wrappedldlinux.c b/src/wrapped/wrappedldlinux.c
new file mode 100755
index 00000000..56b581a0
--- /dev/null
+++ b/src/wrapped/wrappedldlinux.c
@@ -0,0 +1,42 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define _GNU_SOURCE         /* See feature_test_macros(7) */
+#include <dlfcn.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 "elfloader.h"
+#include "box64context.h"
+
+typedef struct my_tls_s {
+    int         i;
+    uint32_t     o;
+} my_tls_t;
+
+EXPORT void* my___tls_get_addr(x64emu_t* emu, void* p)
+{
+    my_tls_t *t = (my_tls_t*)p;
+    return GetDTatOffset(emu->context, t->i, t->o);
+}
+
+EXPORT void* my____tls_get_addr(x64emu_t* emu)
+{
+    // the GNU version (with 3 '_') use register for the parameter!
+    my_tls_t *t = (my_tls_t*)R_RAX;
+    return GetDTatOffset(emu->context, t->i, t->o);
+}
+
+
+const char* ldlinuxName = "ld-linux-x86-64.so.2";
+#define LIBNAME ldlinux
+
+// define all standard library functions
+#include "wrappedlib_init.h"
+
diff --git a/src/wrapped/wrappedldlinux_private.h b/src/wrapped/wrappedldlinux_private.h
new file mode 100755
index 00000000..1c829369
--- /dev/null
+++ b/src/wrapped/wrappedldlinux_private.h
@@ -0,0 +1,25 @@
+#if defined(GO) && defined(GOM) && defined(GO2) && defined(DATA)
+
+// _dl_allocate_tls
+// _dl_allocate_tls_init
+// _dl_argv //type B
+// _dl_cache_libcmp
+// _dl_deallocate_tls
+// _dl_debug_state
+// _dl_get_tls_static_info
+// _dl_make_stack_executable
+// _dl_mcount
+// _dl_rtld_di_serinfo
+// _dl_tls_setup
+DATA(__libc_enable_secure, 4)
+DATA(__libc_stack_end, 4)
+DATA(__pointer_chk_guard, 4)
+// _r_debug //type B
+DATA(_rtld_global, 4)
+DATA(_rtld_global_ro, 4)
+DATA(__stack_chk_guard, 4)
+// defini dans glibc/sysdeps/i386/dl-tls.h
+GOM(___tls_get_addr, pFEv)       //the parameter tls_index is in a register (EAX?)
+GOM(__tls_get_addr, pFEp)        //same, but the parameter is in the stack
+
+#endif
\ No newline at end of file
diff --git a/src/wrapped/wrappedlib_init.h b/src/wrapped/wrappedlib_init.h
new file mode 100755
index 00000000..3f946286
--- /dev/null
+++ b/src/wrapped/wrappedlib_init.h
@@ -0,0 +1,239 @@
+#ifndef LIBNAME
+#error Meh
+#endif
+
+#define FUNC3(M,N) wrapped##M##N
+#define FUNC2(M,N) FUNC3(M,N)
+#define FUNC(N) FUNC2(LIBNAME,N)
+#define QUOTE(M) #M
+#define PRIVATE2(P) QUOTE(wrapped##P##_private.h)
+#define PRIVATE(P) PRIVATE2(P)
+#define MAPNAME3(N,M) N##M
+#define MAPNAME2(N,M) MAPNAME3(N,M)
+#define MAPNAME(N) MAPNAME2(LIBNAME,N)
+// prepare the maps
+#define GO(N, W)
+#define GOW(N, W)
+#define GOM(N, W)
+#define GOS(N, W)
+#define GO2(N, W, O)
+#define DATA(N, S)
+#define DATAV(N, S)
+#define DATAB(N, S)
+#define DATAM(N, S)
+
+// #define the 4 maps first
+#undef GO
+#define GO(N, W) {#N, W, 0},
+static const map_onesymbol_t MAPNAME(symbolmap)[] = {
+    #include PRIVATE(LIBNAME)
+};
+#undef GO
+#define GO(N, W)
+#undef GOW
+#define GOW(N, W) {#N, W, 1},
+static const map_onesymbol_t MAPNAME(wsymbolmap)[] = {
+    #include PRIVATE(LIBNAME)
+};
+#undef GOW
+#define GOW(N, W)
+#undef GOM
+#define GOM(N, W) {#N, W, 0},
+static const map_onesymbol_t MAPNAME(mysymbolmap)[] = {
+    #include PRIVATE(LIBNAME)
+};
+#undef GOM
+#define GOM(N, W)
+#undef GOS
+#define GOS(N, W) {#N, W, 0},
+static const map_onesymbol_t MAPNAME(stsymbolmap)[] = {
+    #include PRIVATE(LIBNAME)
+};
+#undef GOS
+#define GOS(N, W)
+#undef GO2
+#define GO2(N, W, O) {#N, W, 0, #O},
+static const map_onesymbol2_t MAPNAME(symbol2map)[] = {
+    #include PRIVATE(LIBNAME)
+};
+#undef GO2
+#define GO2(N, W, O)
+#undef DATA
+#undef DATAV
+#undef DATAB
+#define DATA(N, S) {#N, S, 0},
+#define DATAV(N, S) {#N, S, 1},
+#define DATAB(N, S) {#N, S, 0},
+static const map_onedata_t MAPNAME(datamap)[] = {
+    #include PRIVATE(LIBNAME)
+};
+#undef DATA
+#undef DATAV
+#undef DATAB
+#define DATA(N, S)
+#define DATAV(N, S)
+#define DATAB(N, S)
+#undef DATAM
+#define DATAM(N, S) {#N, S, 0},
+static const map_onedata_t MAPNAME(mydatamap)[] = {
+    #include PRIVATE(LIBNAME)
+};
+#include "wrappedlib_undefs.h"
+
+
+
+int FUNC(_init)(library_t* lib, box64context_t* box64)
+{
+// Init first
+    free(lib->path); lib->path=NULL;
+#ifdef PRE_INIT
+    PRE_INIT
+#endif
+    {
+        lib->priv.w.lib = dlopen(MAPNAME(Name), RTLD_LAZY | RTLD_GLOBAL);
+        if(!lib->priv.w.lib) {
+#ifdef ALTNAME
+        lib->priv.w.lib = dlopen(ALTNAME, RTLD_LAZY | RTLD_GLOBAL);
+        if(!lib->priv.w.lib)
+#endif
+#ifdef ALTNAME2
+            {
+            lib->priv.w.lib = dlopen(ALTNAME2, RTLD_LAZY | RTLD_GLOBAL);
+            if(!lib->priv.w.lib)
+#endif
+                return -1;
+#ifdef ALTNAME2
+                else lib->path = strdup(ALTNAME2);
+            } else lib->path = strdup(ALTNAME);
+#endif
+        } else lib->path = strdup(MAPNAME(Name));
+    }
+    lib->priv.w.bridge = NewBridge();
+// Create maps
+    lib->symbolmap = kh_init(symbolmap);
+    lib->wsymbolmap = kh_init(symbolmap);
+    lib->mysymbolmap = kh_init(symbolmap);
+    lib->stsymbolmap = kh_init(symbolmap);
+    lib->symbol2map = kh_init(symbol2map);
+    lib->datamap = kh_init(datamap);
+    lib->wdatamap = kh_init(datamap);
+    lib->mydatamap = kh_init(datamap);
+
+    khint_t k;
+    int ret;
+    int cnt;
+
+    // populates maps...
+    cnt = sizeof(MAPNAME(symbolmap))/sizeof(map_onesymbol_t);
+    for (int i=0; i<cnt; ++i) {
+        k = kh_put(symbolmap, lib->symbolmap, MAPNAME(symbolmap)[i].name, &ret);
+        kh_value(lib->symbolmap, k) = MAPNAME(symbolmap)[i].w;
+    }
+    cnt = sizeof(MAPNAME(wsymbolmap))/sizeof(map_onesymbol_t);
+    for (int i=0; i<cnt; ++i) {
+        k = kh_put(symbolmap, lib->wsymbolmap, MAPNAME(wsymbolmap)[i].name, &ret);
+        kh_value(lib->wsymbolmap, k) = MAPNAME(wsymbolmap)[i].w;
+    }
+    cnt = sizeof(MAPNAME(mysymbolmap))/sizeof(map_onesymbol_t);
+    for (int i=0; i<cnt; ++i) {
+        k = kh_put(symbolmap, lib->mysymbolmap, MAPNAME(mysymbolmap)[i].name, &ret);
+        kh_value(lib->mysymbolmap, k) = MAPNAME(mysymbolmap)[i].w;
+    }
+    cnt = sizeof(MAPNAME(stsymbolmap))/sizeof(map_onesymbol_t);
+    for (int i=0; i<cnt; ++i) {
+        k = kh_put(symbolmap, lib->stsymbolmap, MAPNAME(stsymbolmap)[i].name, &ret);
+        kh_value(lib->stsymbolmap, k) = MAPNAME(stsymbolmap)[i].w;
+    }
+    cnt = sizeof(MAPNAME(symbol2map))/sizeof(map_onesymbol2_t);
+    for (int i=0; i<cnt; ++i) {
+        k = kh_put(symbol2map, lib->symbol2map, MAPNAME(symbol2map)[i].name, &ret);
+        kh_value(lib->symbol2map, k).name = MAPNAME(symbol2map)[i].name2;
+        kh_value(lib->symbol2map, k).w = MAPNAME(symbol2map)[i].w;
+        kh_value(lib->symbol2map, k).weak = MAPNAME(symbol2map)[i].weak;
+    }
+    cnt = sizeof(MAPNAME(datamap))/sizeof(map_onedata_t);
+    for (int i=0; i<cnt; ++i) {
+        if(MAPNAME(datamap)[i].weak) {
+            k = kh_put(datamap, lib->wdatamap, MAPNAME(datamap)[i].name, &ret);
+            kh_value(lib->wdatamap, k) = MAPNAME(datamap)[i].sz;
+        } else {
+            k = kh_put(datamap, lib->datamap, MAPNAME(datamap)[i].name, &ret);
+            kh_value(lib->datamap, k) = MAPNAME(datamap)[i].sz;
+        }
+    }
+    cnt = sizeof(MAPNAME(mydatamap))/sizeof(map_onedata_t);
+    for (int i=0; i<cnt; ++i) {
+        k = kh_put(datamap, lib->mydatamap, MAPNAME(mydatamap)[i].name, &ret);
+        kh_value(lib->mydatamap, k) = MAPNAME(mydatamap)[i].sz;
+    }
+#ifdef CUSTOM_INIT
+    CUSTOM_INIT
+#endif
+    
+    return 0;
+}
+
+int FUNC(_fini)(library_t* lib)
+{
+#ifdef CUSTOM_FINI
+    CUSTOM_FINI
+#endif
+    if(lib->priv.w.lib)
+        dlclose(lib->priv.w.lib);
+    lib->priv.w.lib = NULL;
+    if(lib->priv.w.altprefix)
+        free(lib->priv.w.altprefix);
+    if(lib->priv.w.neededlibs) {
+        for(int i=0; i<lib->priv.w.needed; ++i)
+            free(lib->priv.w.neededlibs[i]);
+        free(lib->priv.w.neededlibs);
+    }
+    FreeBridge(&lib->priv.w.bridge);
+    return 1;
+}
+
+int FUNC(_get)(library_t* lib, const char* name, uintptr_t *offs, uint32_t *sz)
+{
+    uintptr_t addr = 0;
+    uint32_t size = 0;
+#ifdef CUSTOM_FAIL
+    void* symbol = NULL;
+#endif
+//PRE
+    if (!getSymbolInMaps(lib, name, 0, &addr, &size)) {
+#ifdef CUSTOM_FAIL
+    CUSTOM_FAIL
+#else
+        return 0;
+#endif
+    }
+//POST
+    if(!addr && !size)
+        return 0;
+    *offs = addr;
+    *sz = size;
+    return 1;
+}
+
+int FUNC(_getnoweak)(library_t* lib, const char* name, uintptr_t *offs, uint32_t *sz)
+{
+    uintptr_t addr = 0;
+    uint32_t size = 0;
+#ifdef CUSTOM_FAIL
+    void* symbol = NULL;
+#endif
+//PRE
+    if (!getSymbolInMaps(lib, name, 1, &addr, &size)) {
+#ifdef CUSTOM_FAIL
+    CUSTOM_FAIL
+#else
+        return 0;
+#endif
+    }
+//POST
+    if(!addr && !size)
+        return 0;
+    *offs = addr;
+    *sz = size;
+    return 1;
+}
diff --git a/src/wrapped/wrappedlib_undefs.h b/src/wrapped/wrappedlib_undefs.h
new file mode 100755
index 00000000..7c6ac84b
--- /dev/null
+++ b/src/wrapped/wrappedlib_undefs.h
@@ -0,0 +1,23 @@
+// regular symbol mapped to itself
+#undef GO
+
+// regular symbol mapped to itself, but weak (unimplemented for now)
+#undef GOW
+
+// symbol mapped to my_symbol
+#undef GOM
+
+// symbol mapped to another one
+#undef GO2
+
+// data
+#undef DATA
+
+// data, Weak (type V)
+#undef DATAV
+
+// data, Uninitialized (type B)
+#undef DATAB
+
+// data, "my_" type
+#undef DATAM
diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c
new file mode 100755
index 00000000..dce09009
--- /dev/null
+++ b/src/wrapped/wrappedlibc.c
@@ -0,0 +1,2590 @@
+#define _LARGEFILE_SOURCE 1
+#define _FILE_OFFSET_BITS 64
+#define _GNU_SOURCE         /* See feature_test_macros(7) */
+#include <stdlib.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <string.h>
+#include <wchar.h>
+#include <dlfcn.h>
+#include <signal.h>
+#include <errno.h>
+#include <err.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/select.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <glob.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <search.h>
+#include <sys/types.h>
+#include <poll.h>
+#include <sys/epoll.h>
+#include <ftw.h>
+#include <sys/syscall.h> 
+#include <sys/socket.h>
+#include <sys/utsname.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <setjmp.h>
+#include <sys/vfs.h>
+#include <spawn.h>
+
+#include "wrappedlibs.h"
+
+#include "box64stack.h"
+#include "x64emu.h"
+#include "debug.h"
+#include "wrapper.h"
+#include "bridge.h"
+//#include "callback.h"
+#include "librarian.h"
+#include "librarian/library_private.h"
+#include "emu/x64emu_private.h"
+#include "box64context.h"
+//#include "myalign.h"
+//#include "signals.h"
+#include "fileutils.h"
+#include "auxval.h"
+#include "elfloader.h"
+#include "bridge.h"
+
+
+#define LIBNAME libc
+const char* libcName = "libc.so.6";
+
+static library_t* my_lib = NULL;
+
+typedef int (*iFL_t)(unsigned long);
+typedef void (*vFpp_t)(void*, void*);
+typedef void (*vFipp_t)(int32_t, void*, void*);
+typedef int32_t (*iFpi_t)(void*, int32_t);
+typedef int32_t (*iFpp_t)(void*, void*);
+typedef int32_t (*iFpL_t)(void*, size_t);
+typedef int32_t (*iFiip_t)(int32_t, int32_t, void*);
+typedef int32_t (*iFipp_t)(int32_t, void*, void*);
+typedef int32_t (*iFppi_t)(void*, void*, int32_t);
+typedef int32_t (*iFpup_t)(void*, uint32_t, void*);
+typedef int32_t (*iFpuu_t)(void*, uint32_t, uint32_t);
+typedef int32_t (*iFiiII_t)(int, int, int64_t, int64_t);
+typedef int32_t (*iFiiiV_t)(int, int, int, ...);
+typedef int32_t (*iFippi_t)(int32_t, void*, void*, int32_t);
+typedef int32_t (*iFpppp_t)(void*, void*, void*, void*);
+typedef int32_t (*iFpipp_t)(void*, int32_t, void*, void*);
+typedef int32_t (*iFppii_t)(void*, void*, int32_t, int32_t);
+typedef int32_t (*iFipuu_t)(int32_t, void*, uint32_t, uint32_t);
+typedef int32_t (*iFipiI_t)(int32_t, void*, int32_t, int64_t);
+typedef int32_t (*iFipuup_t)(int32_t, void*, uint32_t, uint32_t, void*);
+typedef int32_t (*iFiiV_t)(int32_t, int32_t, ...);
+typedef void* (*pFp_t)(void*);
+
+#define SUPER() \
+    GO(_ITM_addUserCommitAction, iFpup_t)   \
+    GO(_IO_file_stat, iFpp_t)
+
+
+typedef struct libc_my_s {
+    #define GO(A, B)    B   A;
+    SUPER()
+    #undef GO
+} libc_my_t;
+
+void* getLIBCMy(library_t* lib)
+{
+    libc_my_t* my = (libc_my_t*)calloc(1, sizeof(libc_my_t));
+    #define GO(A, W) my->A = (W)dlsym(lib->priv.w.lib, #A);
+    SUPER()
+    #undef GO
+    return my;
+}
+#undef SUPER
+
+void freeLIBCMy(void* lib)
+{
+    // empty for now
+}
+#if 0
+// utility functions
+#define SUPER() \
+GO(0)   \
+GO(1)   \
+GO(2)   \
+GO(3)   \
+GO(4)   \
+GO(5)   \
+GO(6)   \
+GO(7)   \
+GO(8)   \
+GO(9)   \
+GO(10)  \
+GO(11)  \
+GO(12)  \
+GO(13)  \
+GO(14)  \
+GO(15)
+
+// compare
+#define GO(A)   \
+static uintptr_t my_compare_fct_##A = 0;        \
+static int my_compare_##A(void* a, void* b)     \
+{                                               \
+    return (int)RunFunction(my_context, my_compare_fct_##A, 2, a, b);\
+}
+SUPER()
+#undef GO
+static void* findcompareFct(void* fct)
+{
+    if(!fct) return NULL;
+    void* p;
+    if((p = GetNativeFnc((uintptr_t)fct))) return p;
+    #define GO(A) if(my_compare_fct_##A == (uintptr_t)fct) return my_compare_##A;
+    SUPER()
+    #undef GO
+    #define GO(A) if(my_compare_fct_##A == 0) {my_compare_fct_##A = (uintptr_t)fct; return my_compare_##A; }
+    SUPER()
+    #undef GO
+    printf_log(LOG_NONE, "Warning, no more slot for libc compare callback\n");
+    return NULL;
+}
+
+// ftw
+#define GO(A)   \
+static uintptr_t my_ftw_fct_##A = 0;                                      \
+static int my_ftw_##A(void* fpath, void* sb, int flag)                       \
+{                                                                               \
+    return (int)RunFunction(my_context, my_ftw_fct_##A, 3, fpath, sb, flag);   \
+}
+SUPER()
+#undef GO
+static void* findftwFct(void* fct)
+{
+    if(!fct) return NULL;
+    void* p;
+    if((p = GetNativeFnc((uintptr_t)fct))) return p;
+    #define GO(A) if(my_ftw_fct_##A == (uintptr_t)fct) return my_ftw_##A;
+    SUPER()
+    #undef GO
+    #define GO(A) if(my_ftw_fct_##A == 0) {my_ftw_fct_##A = (uintptr_t)fct; return my_ftw_##A; }
+    SUPER()
+    #undef GO
+    printf_log(LOG_NONE, "Warning, no more slot for libc ftw callback\n");
+    return NULL;
+}
+
+// ftw64
+#define GO(A)   \
+static uintptr_t my_ftw64_fct_##A = 0;                      \
+static int my_ftw64_##A(void* fpath, void* sb, int flag)    \
+{                                                           \
+    struct i386_stat64 i386st;                              \
+    UnalignStat64(sb, &i386st);                             \
+    return (int)RunFunction(my_context, my_ftw64_fct_##A, 3, fpath, &i386st, flag);  \
+}
+SUPER()
+#undef GO
+static void* findftw64Fct(void* fct)
+{
+    if(!fct) return NULL;
+    #define GO(A) if(my_ftw64_fct_##A == (uintptr_t)fct) return my_ftw64_##A;
+    SUPER()
+    #undef GO
+    #define GO(A) if(my_ftw64_fct_##A == 0) {my_ftw64_fct_##A = (uintptr_t)fct; return my_ftw64_##A; }
+    SUPER()
+    #undef GO
+    printf_log(LOG_NONE, "Warning, no more slot for libc ftw64 callback\n");
+    return NULL;
+}
+
+// nftw
+#define GO(A)   \
+static uintptr_t my_nftw_fct_##A = 0;                                   \
+static int my_nftw_##A(void* fpath, void* sb, int flag, void* ftwbuff)  \
+{                                                                       \
+    return (int)RunFunction(my_context, my_nftw_fct_##A, 4, fpath, sb, flag, ftwbuff);   \
+}
+SUPER()
+#undef GO
+static void* findnftwFct(void* fct)
+{
+    if(!fct) return NULL;
+    void* p;
+    if((p = GetNativeFnc((uintptr_t)fct))) return p;
+    #define GO(A) if(my_nftw_fct_##A == (uintptr_t)fct) return my_nftw_##A;
+    SUPER()
+    #undef GO
+    #define GO(A) if(my_nftw_fct_##A == 0) {my_nftw_fct_##A = (uintptr_t)fct; return my_nftw_##A; }
+    SUPER()
+    #undef GO
+    printf_log(LOG_NONE, "Warning, no more slot for libc nftw callback\n");
+    return NULL;
+}
+
+// nftw64
+#define GO(A)   \
+static uintptr_t my_nftw64_fct_##A = 0;                                     \
+static int my_nftw64_##A(void* fpath, void* sb, int flag, void* ftwbuff)    \
+{                                                                           \
+    struct i386_stat64 i386st;                                              \
+    UnalignStat64(sb, &i386st);                                             \
+    return (int)RunFunction(my_context, my_nftw64_fct_##A, 4, fpath, &i386st, flag, ftwbuff);   \
+}
+SUPER()
+#undef GO
+static void* findnftw64Fct(void* fct)
+{
+    if(!fct) return NULL;
+    #define GO(A) if(my_nftw64_fct_##A == (uintptr_t)fct) return my_nftw64_##A;
+    SUPER()
+    #undef GO
+    #define GO(A) if(my_nftw64_fct_##A == 0) {my_nftw64_fct_##A = (uintptr_t)fct; return my_nftw64_##A; }
+    SUPER()
+    #undef GO
+    printf_log(LOG_NONE, "Warning, no more slot for libc nftw64 callback\n");
+    return NULL;
+}
+
+// globerr
+#define GO(A)   \
+static uintptr_t my_globerr_fct_##A = 0;                                        \
+static int my_globerr_##A(void* epath, int eerrno)                              \
+{                                                                               \
+    return (int)RunFunction(my_context, my_globerr_fct_##A, 2, epath, eerrno);  \
+}
+SUPER()
+#undef GO
+static void* findgloberrFct(void* fct)
+{
+    if(!fct) return NULL;
+    void* p;
+    if((p = GetNativeFnc((uintptr_t)fct))) return p;
+    #define GO(A) if(my_globerr_fct_##A == (uintptr_t)fct) return my_globerr_##A;
+    SUPER()
+    #undef GO
+    #define GO(A) if(my_globerr_fct_##A == 0) {my_globerr_fct_##A = (uintptr_t)fct; return my_globerr_##A; }
+    SUPER()
+    #undef GO
+    printf_log(LOG_NONE, "Warning, no more slot for libc globerr callback\n");
+    return NULL;
+}
+#undef dirent
+// filter_dir
+#define GO(A)   \
+static uintptr_t my_filter_dir_fct_##A = 0;                               \
+static int my_filter_dir_##A(const struct dirent* a)                    \
+{                                                                       \
+    return (int)RunFunction(my_context, my_filter_dir_fct_##A, 1, a);     \
+}
+SUPER()
+#undef GO
+static void* findfilter_dirFct(void* fct)
+{
+    if(!fct) return NULL;
+    void* p;
+    if((p = GetNativeFnc((uintptr_t)fct))) return p;
+    #define GO(A) if(my_filter_dir_fct_##A == (uintptr_t)fct) return my_filter_dir_##A;
+    SUPER()
+    #undef GO
+    #define GO(A) if(my_filter_dir_fct_##A == 0) {my_filter_dir_fct_##A = (uintptr_t)fct; return my_filter_dir_##A; }
+    SUPER()
+    #undef GO
+    printf_log(LOG_NONE, "Warning, no more slot for libc filter_dir callback\n");
+    return NULL;
+}
+// compare_dir
+#define GO(A)   \
+static uintptr_t my_compare_dir_fct_##A = 0;                                  \
+static int my_compare_dir_##A(const struct dirent* a, const struct dirent* b)    \
+{                                                                           \
+    return (int)RunFunction(my_context, my_compare_dir_fct_##A, 2, a, b);     \
+}
+SUPER()
+#undef GO
+static void* findcompare_dirFct(void* fct)
+{
+    if(!fct) return NULL;
+    void* p;
+    if((p = GetNativeFnc((uintptr_t)fct))) return p;
+    #define GO(A) if(my_compare_dir_fct_##A == (uintptr_t)fct) return my_compare_dir_##A;
+    SUPER()
+    #undef GO
+    #define GO(A) if(my_compare_dir_fct_##A == 0) {my_compare_dir_fct_##A = (uintptr_t)fct; return my_compare_dir_##A; }
+    SUPER()
+    #undef GO
+    printf_log(LOG_NONE, "Warning, no more slot for libc compare_dir callback\n");
+    return NULL;
+}
+
+// filter64
+#define GO(A)   \
+static uintptr_t my_filter64_fct_##A = 0;                               \
+static int my_filter64_##A(const struct dirent64* a)                    \
+{                                                                       \
+    return (int)RunFunction(my_context, my_filter64_fct_##A, 1, a);     \
+}
+SUPER()
+#undef GO
+static void* findfilter64Fct(void* fct)
+{
+    if(!fct) return NULL;
+    void* p;
+    if((p = GetNativeFnc((uintptr_t)fct))) return p;
+    #define GO(A) if(my_filter64_fct_##A == (uintptr_t)fct) return my_filter64_##A;
+    SUPER()
+    #undef GO
+    #define GO(A) if(my_filter64_fct_##A == 0) {my_filter64_fct_##A = (uintptr_t)fct; return my_filter64_##A; }
+    SUPER()
+    #undef GO
+    printf_log(LOG_NONE, "Warning, no more slot for libc filter64 callback\n");
+    return NULL;
+}
+// compare64
+#define GO(A)   \
+static uintptr_t my_compare64_fct_##A = 0;                                      \
+static int my_compare64_##A(const struct dirent64* a, const struct dirent64* b) \
+{                                                                               \
+    return (int)RunFunction(my_context, my_compare64_fct_##A, 2, a, b);         \
+}
+SUPER()
+#undef GO
+static void* findcompare64Fct(void* fct)
+{
+    if(!fct) return NULL;
+    void* p;
+    if((p = GetNativeFnc((uintptr_t)fct))) return p;
+    #define GO(A) if(my_compare64_fct_##A == (uintptr_t)fct) return my_compare64_##A;
+    SUPER()
+    #undef GO
+    #define GO(A) if(my_compare64_fct_##A == 0) {my_compare64_fct_##A = (uintptr_t)fct; return my_compare64_##A; }
+    SUPER()
+    #undef GO
+    printf_log(LOG_NONE, "Warning, no more slot for libc compare64 callback\n");
+    return NULL;
+}
+
+#undef SUPER
+
+// some my_XXX declare and defines
+int32_t my___libc_start_main(x64emu_t* emu, int *(main) (int, char * *, char * *), 
+    int argc, char * * ubp_av, void (*init) (void), void (*fini) (void), 
+    void (*rtld_fini) (void), void (* stack_end)); // implemented in x86run_private.c
+EXPORT void my___libc_init_first(x64emu_t* emu, int argc, char* arg0, char** b)
+{
+    // do nothing specific for now
+    return;
+}
+#endif
+uint64_t my_syscall(x64emu_t *emu); // implemented in x86syscall.c
+void EXPORT my___stack_chk_fail(x64emu_t* emu)
+{
+    char buff[200];
+    #ifdef HAVE_TRACE
+    sprintf(buff, "%p: Stack is corrupted, aborting (prev IP=%p->%p)\n", (void*)emu->old_ip, (void*)emu->prev2_ip, (void*)emu->prev_ip);
+    #else
+    sprintf(buff, "%p: Stack is corrupted, aborting\n", (void*)emu->old_ip);
+    #endif
+    StopEmu(emu, buff);
+}
+void EXPORT my___gmon_start__(x64emu_t *emu)
+{
+    printf_log(LOG_DEBUG, "__gmon_start__ called (dummy call)\n");
+}
+#if 0
+int EXPORT my___cxa_atexit(x64emu_t* emu, void* p, void* a, void* d)
+{
+    AddCleanup1Arg(emu, p, a);
+    return 0;
+}
+void EXPORT my___cxa_finalize(x64emu_t* emu, void* p)
+{
+    if(!p) {
+        // p is null, call (and remove) all Cleanup functions
+        CallAllCleanup(emu);
+        return;
+    }
+        CallCleanup(emu, p);
+}
+int EXPORT my_atexit(x64emu_t* emu, void *p)
+{
+    AddCleanup(emu, p);
+    return 0;
+}
+
+int my_getcontext(x64emu_t* emu, void* ucp);
+int my_setcontext(x64emu_t* emu, void* ucp);
+int my_makecontext(x64emu_t* emu, void* ucp, void* fnc, int32_t argc, void* argv);
+int my_swapcontext(x64emu_t* emu, void* ucp1, void* ucp2);
+
+// All signal and context functions defined in signals.c
+
+// All fts function defined in myfts.c
+
+// getauxval implemented in auxval.c
+
+
+// this one is defined in elfloader.c
+int my_dl_iterate_phdr(x64emu_t *emu, void* F, void *data);
+
+
+pid_t EXPORT my_fork(x64emu_t* emu)
+{
+    // execute atforks prepare functions, in reverse order
+    for (int i=my_context->atfork_sz-1; i>=0; --i)
+        if(my_context->atforks[i].prepare)
+            RunFunctionWithEmu(emu, 0, my_context->atforks[i].prepare, 0);
+    int type = emu->type;
+    pid_t v;
+    v = fork();
+    if(type == EMUTYPE_MAIN)
+        thread_set_emu(emu);
+    if(v<0) {
+        printf_log(LOG_NONE, "BOX86: Warning, fork errored... (%d)\n", v);
+        // error...
+    } else if(v>0) {  
+        // execute atforks parent functions
+        for (int i=0; i<my_context->atfork_sz; --i)
+            if(my_context->atforks[i].parent)
+                RunFunctionWithEmu(emu, 0, my_context->atforks[i].parent, 0);
+
+    } else /*if(v==0)*/ {
+        // execute atforks child functions
+        for (int i=0; i<my_context->atfork_sz; --i)
+            if(my_context->atforks[i].child)
+                RunFunctionWithEmu(emu, 0, my_context->atforks[i].child, 0);
+    }
+    return v;
+}
+pid_t EXPORT my___fork(x64emu_t* emu) __attribute__((alias("my_fork")));
+pid_t EXPORT my_vfork(x64emu_t* emu)
+{
+    #if 1
+    emu->quit = 1;
+    emu->fork = 1;  // use regular fork...
+    return 0;
+    #else
+    return 0;
+    #endif
+}
+
+int EXPORT my_uname(struct utsname *buf)
+{
+    // sizeof(struct utsname)==390 on i686, and also on ARM, so this seem safe
+    int ret = uname(buf);
+    strcpy(buf->machine, /*(box64_steam)?"x86_64":*/"i686");
+    return ret;
+}
+
+// X86_O_RDONLY 0x00
+#define X86_O_WRONLY       0x01     // octal     01
+#define X86_O_RDWR         0x02     // octal     02
+#define X86_O_CREAT        0x40     // octal     0100
+#define X86_O_EXCL         0x80     // octal     0200
+#define X86_O_NOCTTY       0x100    // octal     0400
+#define X86_O_TRUNC        0x200    // octal    01000
+#define X86_O_APPEND       0x400    // octal    02000
+#define X86_O_NONBLOCK     0x800    // octal    04000
+#define X86_O_SYNC         0x101000 // octal 04010000
+#define X86_O_DSYNC        0x1000   // octal   010000
+#define X86_O_RSYNC        O_SYNC
+#define X86_FASYNC         020000
+#define X86_O_DIRECT       040000
+#define X86_O_LARGEFILE    0100000
+#define X86_O_DIRECTORY    0200000
+#define X86_O_NOFOLLOW     0400000
+#define X86_O_NOATIME      01000000
+#define X86_O_CLOEXEC      02000000
+#define X86_O_TMPFILE      020200000
+
+#ifndef O_TMPFILE
+#define O_TMPFILE (020000000 | O_DIRECTORY)
+#endif
+
+#define SUPER()     \
+    GO(O_WRONLY)    \
+    GO(O_RDWR)      \
+    GO(O_CREAT)     \
+    GO(O_EXCL)      \
+    GO(O_NOCTTY)    \
+    GO(O_TRUNC)     \
+    GO(O_APPEND)    \
+    GO(O_NONBLOCK)  \
+    GO(O_SYNC)      \
+    GO(O_DSYNC)     \
+    GO(O_RSYNC)     \
+    GO(FASYNC)      \
+    GO(O_DIRECT)    \
+    GO(O_LARGEFILE) \
+    GO(O_TMPFILE)   \
+    GO(O_DIRECTORY) \
+    GO(O_NOFOLLOW)  \
+    GO(O_NOATIME)   \
+    GO(O_CLOEXEC)   \
+
+// x86->arm
+int of_convert(int a)
+{
+    if(!a || a==-1) return a;
+    int b=0;
+    #define GO(A) if((a&X86_##A)==X86_##A) {a&=~X86_##A; b|=A;}
+    SUPER();
+    #undef GO
+    if(a) {
+        printf_log(LOG_NONE, "Warning, of_convert(...) left over 0x%x, converted 0x%x\n", a, b);
+    }
+    return a|b;
+}
+
+// arm->x86
+int of_unconvert(int a)
+{
+    if(!a || a==-1) return a;
+    int b=0;
+    #define GO(A) if((a&A)==A) {a&=~A; b|=X86_##A;}
+    SUPER();
+    #undef GO
+    if(a) {
+        printf_log(LOG_NONE, "Warning, of_unconvert(...) left over 0x%x, converted 0x%x\n", a, b);
+    }
+    return a|b;
+}
+#undef SUPER
+
+
+EXPORT void* my__ZGTtnaX (size_t a) { printf("warning _ZGTtnaX called\n"); return NULL; }
+EXPORT void my__ZGTtdlPv (void* a) { printf("warning _ZGTtdlPv called\n"); }
+EXPORT uint8_t my__ITM_RU1(const uint8_t * a) { printf("warning _ITM_RU1 called\n"); return 0; }
+EXPORT uint32_t my__ITM_RU4(const uint32_t * a) { printf("warning _ITM_RU4 called\n"); return 0; }
+EXPORT uint64_t my__ITM_RU8(const uint64_t * a) { printf("warning _ITM_RU8 called\n"); return 0; }
+EXPORT void my__ITM_memcpyRtWn(void * a, const void * b, size_t c) {printf("warning _ITM_memcpyRtWn called\n");  }
+EXPORT void my__ITM_memcpyRnWt(void * a, const void * b, size_t c) {printf("warning _ITM_memcpyRtWn called\n"); }
+
+EXPORT void my_longjmp(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p, int32_t __val);
+EXPORT void my__longjmp(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p, int32_t __val) __attribute__((alias("my_longjmp")));
+EXPORT void my_siglongjmp(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p, int32_t __val) __attribute__((alias("my_longjmp")));
+EXPORT void my___longjmp_chk(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p, int32_t __val) __attribute__((alias("my_longjmp")));
+
+EXPORT int32_t my_setjmp(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p);
+EXPORT int32_t my__setjmp(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p) __attribute__((alias("my_setjmp")));
+EXPORT int32_t my___sigsetjmp(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p) __attribute__((alias("my_setjmp")));
+#if 0
+EXPORT void my_exit(x64emu_t *emu, int32_t status)
+{
+    R_EAX = (uint32_t)status;
+    emu->quit = 1;
+}
+EXPORT void my__exit(x64emu_t *emu, int32_t status) __attribute__((alias("my_exit")));
+EXPORT void my__Exit(x64emu_t *emu, int32_t status) __attribute__((alias("my_exit")));
+#endif
+void myStackAlign(const char* fmt, uint32_t* st, uint32_t* mystack); // align st into mystack according to fmt (for v(f)printf(...))
+typedef int (*iFpp_t)(void*, void*);
+typedef int (*iFppp_t)(void*, void*, void*);
+typedef int (*iFpupp_t)(void*, uint32_t, void*, void*);
+EXPORT int my_printf(x64emu_t *emu, void* fmt, void* b, va_list V) {
+    #ifndef NOALIGN
+    // need to align on arm
+    myStackAlign((const char*)fmt, b, emu->scratch);
+    PREPARE_VALIST;
+    void* f = vprintf;
+    return ((iFpp_t)f)(fmt, VARARGS);
+    #else
+    // other platform don't need that
+    return vprintf((const char*)fmt, V);
+    #endif
+}
+EXPORT int my___printf_chk(x64emu_t *emu, void* fmt, void* b, va_list V) __attribute__((alias("my_printf")));
+
+EXPORT int my_vprintf(x64emu_t *emu, void* fmt, void* b, va_list V) {
+    #ifndef NOALIGN
+    // need to align on arm
+    myStackAlign((const char*)fmt, (uint32_t*)b, emu->scratch);
+    PREPARE_VALIST;
+    void* f = vprintf;
+    return ((iFpp_t)f)(fmt, VARARGS);
+    #else
+    // other platform don't need that
+    void* f = vprintf;
+    return ((iFpp_t)f)(fmt, (uint32_t*)b);
+    #endif
+}
+EXPORT int my___vprintf_chk(x64emu_t *emu, void* fmt, void* b, va_list V) __attribute__((alias("my_vprintf")));
+
+EXPORT int my_vfprintf(x64emu_t *emu, void* F, void* fmt, void* b) {
+    #ifndef NOALIGN
+    // need to align on arm
+    myStackAlign((const char*)fmt, (uint32_t*)b, emu->scratch);
+    PREPARE_VALIST;
+    void* f = vfprintf;
+    return ((iFppp_t)f)(F, fmt, VARARGS);
+    #else
+    // other platform don't need that
+    void* f = vfprintf;
+    return ((iFppp_t)f)(F, fmt, (uint32_t*)b);
+    #endif
+}
+EXPORT int my___vfprintf_chk(x64emu_t *emu, void* F, void* fmt, void* b) __attribute__((alias("my_vfprintf")));
+EXPORT int my__IO_vfprintf(x64emu_t *emu, void* F, void* fmt, void* b) __attribute__((alias("my_vfprintf")));
+
+EXPORT int my_fprintf(x64emu_t *emu, void* F, void* fmt, void* b, va_list V)  {
+    #ifndef NOALIGN
+    // need to align on arm
+    myStackAlign((const char*)fmt, b, emu->scratch);
+    PREPARE_VALIST;
+    void* f = vfprintf;
+    return ((iFppp_t)f)(F, fmt, VARARGS);
+    #else
+    // other platform don't need that
+    return vfprintf((FILE*)F, (const char*)fmt, V);
+    #endif
+}
+EXPORT int my___fprintf_chk(x64emu_t *emu, void* F, void* fmt, void* b, va_list V) __attribute__((alias("my_fprintf")));
+
+EXPORT int my_wprintf(x64emu_t *emu, void* fmt, void* b, va_list V) {
+    #ifndef NOALIGN
+    // need to align on arm
+    myStackAlignW((const char*)fmt, b, emu->scratch);
+    PREPARE_VALIST;
+    void* f = vwprintf;
+    return ((iFpp_t)f)(fmt, VARARGS);
+    #else
+    // other platform don't need that
+    return vwprintf((const wchar_t*)fmt, V);
+    #endif
+}
+EXPORT int my___wprintf_chk(x64emu_t *emu, int flag, void* fmt, void* b, va_list V) {
+    #ifndef NOALIGN
+    // need to align on arm
+    myStackAlignW((const char*)fmt, b, emu->scratch);
+    PREPARE_VALIST;
+    void* f = vwprintf;
+    return ((iFpp_t)f)(fmt, VARARGS);
+    #else
+    // other platform don't need that
+    return vwprintf((const wchar_t*)fmt, V);
+    #endif
+}
+EXPORT int my_fwprintf(x64emu_t *emu, void* F, void* fmt, void* b, va_list V)  {
+    #ifndef NOALIGN
+    // need to align on arm
+    myStackAlignW((const char*)fmt, b, emu->scratch);
+    PREPARE_VALIST;
+    void* f = vfwprintf;
+    return ((iFppp_t)f)(F, fmt, VARARGS);
+    #else
+    // other platform don't need that
+    return vfwprintf((FILE*)F, (const wchar_t*)fmt, V);
+    #endif
+}
+EXPORT int my___fwprintf_chk(x64emu_t *emu, void* F, void* fmt, void* b, va_list V) __attribute__((alias("my_fwprintf")));
+
+EXPORT int my_vfwprintf(x64emu_t *emu, void* F, void* fmt, void* b) {
+    #ifndef NOALIGN
+    myStackAlignW((const char*)fmt, b, emu->scratch);
+    PREPARE_VALIST;
+    void* f = vfwprintf;
+    return ((iFppp_t)f)(F, fmt, VARARGS);
+    #else
+    void* f = vfwprintf;
+    return ((iFppp_t)f)(F, fmt, b);
+    #endif
+}
+
+EXPORT int my_vwprintf(x64emu_t *emu, void* fmt, void* b) {
+    #ifndef NOALIGN
+    myStackAlignW((const char*)fmt, b, emu->scratch);
+    PREPARE_VALIST;
+    void* f = vwprintf;
+    return ((iFpp_t)f)(fmt, VARARGS);
+    #else
+    void* f = vwprintf;
+    return ((iFpp_t)f)(fmt, b);
+    #endif
+}
+
+EXPORT void *my_div(void *result, int numerator, int denominator) {
+    *(div_t *)result = div(numerator, denominator);
+    return result;
+}
+
+EXPORT int my_snprintf(x64emu_t* emu, void* buff, uint32_t s, void * fmt, void * b, va_list V) {
+    #ifndef NOALIGN
+    // need to align on arm
+    myStackAlign((const char*)fmt, b, emu->scratch);
+    PREPARE_VALIST;
+    void* f = vsnprintf;
+    int r = ((iFpupp_t)f)(buff, s, fmt, VARARGS);
+    return r;
+    #else
+    return vsnprintf((char*)buff, s, (char*)fmt, V);
+    #endif
+}
+EXPORT int my___snprintf_chk(x64emu_t* emu, void* buff, uint32_t s, void * fmt, void * b, va_list V) __attribute__((alias("my_snprintf")));
+EXPORT int my___snprintf(x64emu_t* emu, void* buff, uint32_t s, void * fmt, void * b, va_list V) __attribute__((alias("my_snprintf")));
+
+EXPORT int my_sprintf(x64emu_t* emu, void* buff, void * fmt, void * b, va_list V) {
+    #ifndef NOALIGN
+    // need to align on arm
+    myStackAlign((const char*)fmt, b, emu->scratch);
+    PREPARE_VALIST;
+    void* f = vsprintf;
+    return ((iFppp_t)f)(buff, fmt, VARARGS);
+    #else
+    return vsprintf((char*)buff, (char*)fmt, V);
+    #endif
+}
+EXPORT int my___sprintf_chk(x64emu_t* emu, void* buff, void * fmt, void * b, va_list V) __attribute__((alias("my_sprintf")));
+
+EXPORT int my_asprintf(x64emu_t* emu, void** buff, void * fmt, void * b, va_list V) {
+    #ifndef NOALIGN
+    // need to align on arm
+    myStackAlign((const char*)fmt, b, emu->scratch);
+    PREPARE_VALIST;
+    void* f = vasprintf;
+    return ((iFppp_t)f)(buff, fmt, VARARGS);
+    #else
+    return vasprintf((char**)buff, (char*)fmt, V);
+    #endif
+}
+EXPORT int my___asprintf(x64emu_t* emu, void** buff, void * fmt, void * b, va_list V) __attribute__((alias("my_asprintf")));
+
+
+EXPORT int my_vsprintf(x64emu_t* emu, void* buff,  void * fmt, void * b, va_list V) {
+    #ifndef NOALIGN
+    // need to align on arm
+    myStackAlign((const char*)fmt, (uint32_t*)b, emu->scratch);
+    PREPARE_VALIST;
+    void* f = vsprintf;
+    int r = ((iFppp_t)f)(buff, fmt, VARARGS);
+    return r;
+    #else
+    void* f = vsprintf;
+    int r = ((iFppp_t)f)(buff, fmt, (uint32_t*)b);
+    return r;
+    #endif
+}
+EXPORT int my___vsprintf_chk(x64emu_t* emu, void* buff, void * fmt, void * b, va_list V) __attribute__((alias("my_vsprintf")));
+
+#ifdef POWERPCLE
+EXPORT int my_vfscanf(x64emu_t* emu, void* stream, void* fmt, void* b) // probably uneeded to do a GOM, a simple wrap should enough
+{
+    //myStackAlign((const char*)fmt, (uint32_t*)b, emu->scratch);
+    PREPARE_VALIST_(b);
+    void* f = vfscanf;
+
+    return ((iFppp_t)f)(stream, fmt, VARARGS_(b));
+}
+
+
+
+EXPORT int my_vsscanf(x64emu_t* emu, void* stream, void* fmt, void* b)
+{
+    //myStackAlign((const char*)fmt, (uint32_t*)b, emu->scratch);
+    PREPARE_VALIST_(b);
+    void* f = vsscanf;
+
+    return ((iFppp_t)f)(stream, fmt, VARARGS_(b));
+}
+
+EXPORT int my__vsscanf(x64emu_t* emu, void* stream, void* fmt, void* b) __attribute__((alias("my_vsscanf")));
+EXPORT int my_sscanf(x64emu_t* emu, void* stream, void* fmt, void* b) __attribute__((alias("my_vsscanf")));
+
+EXPORT int my__IO_vfscanf(x64emu_t* emu, void* stream, void* fmt, void* b) __attribute__((alias("my_vfscanf")));
+EXPORT int my___isoc99_vsscanf(x64emu_t* emu, void* stream, void* fmt, void* b) __attribute__((alias("my_vsscanf")));
+
+EXPORT int my___isoc99_vfscanf(x64emu_t* emu, void* stream, void* fmt, void* b) __attribute__((alias("my_vfscanf")));
+EXPORT int my___isoc99_fscanf(x64emu_t* emu, void* stream, void* fmt, void* b) __attribute__((alias("my_vfscanf")));
+
+EXPORT int my___isoc99_sscanf(x64emu_t* emu, void* stream, void* fmt, void* b)
+{
+  void* f = sscanf;
+  PREPARE_VALIST;
+
+  return ((iFppp_t)f)(stream, fmt, VARARGS);
+}
+#endif
+
+EXPORT int my_vsnprintf(x64emu_t* emu, void* buff, uint32_t s, void * fmt, void * b, va_list V) {
+    #ifndef NOALIGN
+    // need to align on arm
+    myStackAlign((const char*)fmt, (uint32_t*)b, emu->scratch);
+    PREPARE_VALIST;
+    void* f = vsnprintf;
+    int r = ((iFpupp_t)f)(buff, s, fmt, VARARGS);
+    return r;
+    #else
+    void* f = vsnprintf;
+    int r = ((iFpupp_t)f)(buff, s, fmt, (uint32_t*)b);
+    return r;
+    #endif
+}
+EXPORT int my___vsnprintf(x64emu_t* emu, void* buff, uint32_t s, void * fmt, void * b, va_list V) __attribute__((alias("my_vsnprintf")));
+EXPORT int my___vsnprintf_chk(x64emu_t* emu, void* buff, uint32_t s, void * fmt, void * b, va_list V) __attribute__((alias("my_vsnprintf")));
+
+EXPORT int my_vasprintf(x64emu_t* emu, void* strp, void* fmt, void* b, va_list V)
+{
+    #ifndef NOALIGN
+    // need to align on arm
+    myStackAlign((const char*)fmt, (uint32_t*)b, emu->scratch);
+    PREPARE_VALIST;
+    void* f = vasprintf;
+    int r = ((iFppp_t)f)(strp, fmt, VARARGS);
+    return r;
+    #else
+    void* f = vasprintf;
+    int r = ((iFppp_t)f)(strp, fmt, (uint32_t*)b);
+    return r;
+    #endif
+}
+EXPORT int my___vasprintf_chk(x64emu_t* emu, void* strp, int flags, void* fmt, void* b, va_list V)
+{
+    #ifndef NOALIGN
+    // need to align on arm
+    myStackAlign((const char*)fmt, (uint32_t*)b, emu->scratch);
+    PREPARE_VALIST;
+    void* f = vasprintf;
+    int r = ((iFppp_t)f)(strp, fmt, VARARGS);
+    return r;
+    #else
+    void* f = vasprintf;
+    int r = ((iFppp_t)f)(strp, fmt, (uint32_t*)b);
+    return r;
+    #endif
+}
+
+EXPORT int my___asprintf_chk(x64emu_t* emu, void* result_ptr, int flags, void* fmt, void* b, va_list V)
+{
+    #ifndef NOALIGN
+    myStackAlign((const char*)fmt, b, emu->scratch);
+    PREPARE_VALIST;
+    void* f = vasprintf;
+    return ((iFppp_t)f)(result_ptr, fmt, VARARGS);
+    #else
+    return vasprintf((char**)result_ptr, (char*)fmt, V);
+    #endif
+}
+
+EXPORT int my_vswprintf(x64emu_t* emu, void* buff, uint32_t s, void * fmt, void * b, va_list V) {
+    #ifndef NOALIGN
+    // need to align on arm
+    myStackAlignW((const char*)fmt, (uint32_t*)b, emu->scratch);
+    PREPARE_VALIST;
+    void* f = vswprintf;
+    int r = ((iFpupp_t)f)(buff, s, fmt, VARARGS);
+    return r;
+    #else
+    void* f = vswprintf;
+    int r = ((iFpupp_t)f)(buff, s, fmt, (uint32_t*)b);
+    return r;
+    #endif
+}
+EXPORT int my___vswprintf(x64emu_t* emu, void* buff, uint32_t s, void * fmt, void * b, va_list V) __attribute__((alias("my_vswprintf")));
+EXPORT int my___vswprintf_chk(x64emu_t* emu, void* buff, uint32_t s, void * fmt, void * b, va_list V) __attribute__((alias("my_vswprintf")));
+
+EXPORT void my_verr(x64emu_t* emu, int eval, void* fmt, void* b) {
+    #ifndef NOALIGN
+    myStackAlignW((const char*)fmt, (uint32_t*)b, emu->scratch);
+    PREPARE_VALIST;
+    void* f = verr;
+    ((vFipp_t)f)(eval, fmt, VARARGS);
+    #else
+    void* f = verr;
+    ((vFipp_t)f)(eval, fmt, (uint32_t*)b);
+    #endif
+}
+
+EXPORT void my_vwarn(x64emu_t* emu, void* fmt, void* b) {
+    #ifndef NOALIGN
+    myStackAlignW((const char*)fmt, (uint32_t*)b, emu->scratch);
+    PREPARE_VALIST;
+    void* f = vwarn;
+    ((vFpp_t)f)(fmt, VARARGS);
+    #else
+    void* f = vwarn;
+    ((vFpp_t)f)(fmt, (uint32_t*)b);
+    #endif
+}
+
+EXPORT int my___swprintf_chk(x64emu_t* emu, void* s, uint32_t n, int32_t flag, uint32_t slen, void* fmt, void * b)
+{
+    #ifndef NOALIGN
+    myStackAlignW((const char*)fmt, b, emu->scratch);
+    PREPARE_VALIST;
+    void* f = vswprintf;
+    int r = ((iFpupp_t)f)(s, n, fmt, VARARGS);
+    return r;
+    #else
+    void* f = vswprintf;
+    int r = ((iFpupp_t)f)(s, n, fmt, b);
+    return r;
+    #endif
+}
+EXPORT int my_swprintf(x64emu_t* emu, void* s, uint32_t n, void* fmt, void *b)
+{
+    #ifndef NOALIGN
+    myStackAlignW((const char*)fmt, b, emu->scratch);
+    PREPARE_VALIST;
+    void* f = vswprintf;
+    int r = ((iFpupp_t)f)(s, n, fmt, VARARGS);
+    return r;
+    #else
+    void* f = vswprintf;
+    int r = ((iFpupp_t)f)(s, n, fmt, b);
+    return r;
+    #endif
+}
+
+EXPORT void my__ITM_addUserCommitAction(x64emu_t* emu, void* cb, uint32_t b, void* c)
+{
+    // disabled for now... Are all this _ITM_ stuff really mendatory?
+    #if 0
+    // quick and dirty... Should store the callback to be removed later....
+    libc_my_t *my = (libc_my_t *)emu->context->libclib->priv.w.p2;
+    x64emu_t *cbemu = AddCallback(emu, (uintptr_t)cb, 1, c, NULL, NULL, NULL);
+    my->_ITM_addUserCommitAction(libc1ArgCallback, b, cbemu);
+    // should keep track of cbemu to remove at some point...
+    #else
+    printf("warning _ITM_addUserCommitAction called\n");
+    #endif
+}
+EXPORT void my__ITM_registerTMCloneTable(x64emu_t* emu, void* p, uint32_t s) {}
+EXPORT void my__ITM_deregisterTMCloneTable(x64emu_t* emu, void* p) {}
+
+
+struct i386_stat {
+	uint64_t  st_dev;
+	uint32_t  __pad1;
+	uint32_t  st_ino;
+	uint32_t  st_mode;
+	uint32_t  st_nlink;
+	uint32_t  st_uid;
+	uint32_t  st_gid;
+	uint64_t  st_rdev;
+	uint32_t  __pad2;
+	int32_t   st_size;
+	int32_t   st_blksize;
+	int32_t   st_blocks;
+	int32_t   st_atime_sec;
+	uint32_t  st_atime_nsec;
+	int32_t   st_mtime_sec;
+	uint32_t  st_mtime_nsec;
+	int32_t   st_ctime_sec;
+	uint32_t  st_ctime_nsec;
+	uint32_t  __unused4;
+	uint32_t  __unused5;
+} __attribute__((packed));
+
+static int FillStatFromStat64(int vers, const struct stat64 *st64, void *st32)
+{
+    struct i386_stat *i386st = (struct i386_stat *)st32;
+
+    if (vers != 3)
+    {
+        errno = EINVAL;
+        return -1;
+    }
+
+    i386st->st_dev = st64->st_dev;
+    i386st->__pad1 = 0;
+    if (fix_64bit_inodes)
+    {
+        i386st->st_ino = st64->st_ino ^ (st64->st_ino >> 32);
+    }
+    else
+    {
+        i386st->st_ino = st64->st_ino;
+        if ((st64->st_ino >> 32) != 0)
+        {
+            errno = EOVERFLOW;
+            return -1;
+        }
+    }
+    i386st->st_mode = st64->st_mode;
+    i386st->st_nlink = st64->st_nlink;
+    i386st->st_uid = st64->st_uid;
+    i386st->st_gid = st64->st_gid;
+    i386st->st_rdev = st64->st_rdev;
+    i386st->__pad2 = 0;
+    i386st->st_size = st64->st_size;
+    if ((i386st->st_size >> 31) != (int32_t)(st64->st_size >> 32))
+    {
+        errno = EOVERFLOW;
+        return -1;
+    }
+    i386st->st_blksize = st64->st_blksize;
+    i386st->st_blocks = st64->st_blocks;
+    if ((i386st->st_blocks >> 31) != (int32_t)(st64->st_blocks >> 32))
+    {
+        errno = EOVERFLOW;
+        return -1;
+    }
+    i386st->st_atime_sec = st64->st_atim.tv_sec;
+    i386st->st_atime_nsec = st64->st_atim.tv_nsec;
+    i386st->st_mtime_sec = st64->st_mtim.tv_sec;
+    i386st->st_mtime_nsec = st64->st_mtim.tv_nsec;
+    i386st->st_ctime_sec = st64->st_ctim.tv_sec;
+    i386st->st_ctime_nsec = st64->st_ctim.tv_nsec;
+    i386st->__unused4 = 0;
+    i386st->__unused5 = 0;
+    return 0;
+}
+
+EXPORT int my___fxstat(x64emu_t *emu, int vers, int fd, void* buf)
+{
+    if (vers == 1)
+    {
+        static iFiip_t f = NULL;
+        if(!f) {
+            library_t* lib = my_lib;
+            if(!lib)
+            {
+                errno = EINVAL;
+                return -1;
+            }
+            f = (iFiip_t)dlsym(lib->priv.w.lib, "__fxstat");
+        }
+
+        return f(vers, fd, buf);
+    }
+    struct stat64 st;
+    int r = fstat64(fd, &st);
+    if (r) return r;
+    r = FillStatFromStat64(vers, &st, buf);
+    return r;
+}
+
+EXPORT int my___fxstat64(x64emu_t *emu, int vers, int fd, void* buf)
+{
+    struct stat64 st;
+    int r = fstat64(fd, &st);
+    //int r = syscall(__NR_stat64, fd, &st);
+    UnalignStat64(&st, buf);
+    return r;
+}
+
+EXPORT int my___xstat(x64emu_t* emu, int v, void* path, void* buf)
+{
+    if (v == 1)
+    {
+        static iFipp_t f = NULL;
+        if(!f) {
+            library_t* lib = my_lib;
+            if(!lib)
+            {
+                errno = EINVAL;
+                return -1;
+            }
+            f = (iFipp_t)dlsym(lib->priv.w.lib, "__xstat");
+        }
+
+        return f(v, path, buf);
+    }
+    struct stat64 st;
+    int r = stat64((const char*)path, &st);
+    if (r) return r;
+    r = FillStatFromStat64(v, &st, buf);
+    return r;
+}
+
+EXPORT int my___xstat64(x64emu_t* emu, int v, void* path, void* buf)
+{
+    struct stat64 st;
+    int r = stat64((const char*)path, &st);
+    UnalignStat64(&st, buf);
+    return r;
+}
+
+EXPORT int my___lxstat(x64emu_t* emu, int v, void* name, void* buf)
+{
+    if (v == 1)
+    {
+        static iFipp_t f = NULL;
+        if(!f) {
+            library_t* lib = my_lib;
+            if(!lib)
+            {
+                errno = EINVAL;
+                return -1;
+            }
+            f = (iFipp_t)dlsym(lib->priv.w.lib, "__lxstat");
+        }
+
+        return f(v, name, buf);
+    }
+    struct stat64 st;
+    int r = lstat64((const char*)name, &st);
+    if (r) return r;
+    r = FillStatFromStat64(v, &st, buf);
+    return r;
+}
+
+EXPORT int my___lxstat64(x64emu_t* emu, int v, void* name, void* buf)
+{
+    struct stat64 st;
+    int r = lstat64((const char*)name, &st);
+    UnalignStat64(&st, buf);
+    return r;
+}
+
+EXPORT int my___fxstatat(x64emu_t* emu, int v, int d, void* path, void* buf, int flags)
+{
+    struct  stat64 st;
+    int r = fstatat64(d, path, &st, flags);
+    if (r) return r;
+    r = FillStatFromStat64(v, &st, buf);
+    return r;
+}
+
+EXPORT int my___fxstatat64(x64emu_t* emu, int v, int d, void* path, void* buf, int flags)
+{
+    struct  stat64 st;
+    int r = fstatat64(d, path, &st, flags);
+    UnalignStat64(&st, buf);
+    return r;
+}
+
+EXPORT int my__IO_file_stat(x64emu_t* emu, void* f, void* buf)
+{
+    struct stat64 st;
+    libc_my_t *my = (libc_my_t *)emu->context->libclib->priv.w.p2;
+    int r = my->_IO_file_stat(f, &st);
+    UnalignStat64(&st, buf);
+    return r;
+}
+
+EXPORT int my_fstatfs64(int fd, void* buf)
+{
+    struct statfs64 st;
+    int r = fstatfs64(fd, &st);
+    UnalignStatFS64(&st, buf);
+    return r;
+}
+
+EXPORT int my_statfs64(const char* path, void* buf)
+{
+    struct statfs64 st;
+    int r = statfs64(path, &st);
+    UnalignStatFS64(&st, buf);
+    return r;
+}
+
+
+typedef struct compare_r_s {
+    x64emu_t* emu;
+    uintptr_t f;
+    void*     data;
+    int       r;
+} compare_r_t;
+
+static int my_compare_r_cb(void* a, void* b, compare_r_t* arg)
+{
+    return (int)RunFunctionWithEmu(arg->emu, 0, arg->f, 2+arg->r, a, b, arg->data);
+}
+EXPORT void my_qsort(x64emu_t* emu, void* base, size_t nmemb, size_t size, void* fnc)
+{
+    compare_r_t args;
+    args.emu = emu; args.f = (uintptr_t)fnc; args.r = 0; args.data = NULL;
+    qsort_r(base, nmemb, size, (__compar_d_fn_t)my_compare_r_cb, &args);
+}
+EXPORT void my_qsort_r(x64emu_t* emu, void* base, size_t nmemb, size_t size, void* fnc, void* data)
+{
+    compare_r_t args;
+    args.emu = emu; args.f = (uintptr_t)fnc; args.r = 1; args.data = data;
+    qsort_r(base, nmemb, size, (__compar_d_fn_t)my_compare_r_cb, &args);
+}
+
+EXPORT void* my_bsearch(x64emu_t* emu, void* key, void* base, size_t nmemb, size_t size, void* fnc)
+{
+    return bsearch(key, base, nmemb, size, findcompareFct(fnc));
+}
+
+EXPORT void* my_lsearch(x64emu_t* emu, void* key, void* base, size_t* nmemb, size_t size, void* fnc)
+{
+    return lsearch(key, base, nmemb, size, findcompareFct(fnc));
+}
+EXPORT void* my_lfind(x64emu_t* emu, void* key, void* base, size_t* nmemb, size_t size, void* fnc)
+{
+    return lfind(key, base, nmemb, size, findcompareFct(fnc));
+}
+
+
+struct i386_dirent {
+    uint32_t d_ino;
+    int32_t  d_off;
+    uint16_t d_reclen;
+    uint8_t  d_type;
+    char     d_name[256];
+};
+
+EXPORT void* my_readdir(x64emu_t* emu, void* dirp)
+{
+    if (fix_64bit_inodes)
+    {
+        struct dirent64 *dp64 = readdir64((DIR *)dirp);
+        if (!dp64) return NULL;
+        uint32_t ino32 = dp64->d_ino ^ (dp64->d_ino >> 32);
+        int32_t off32 = dp64->d_off;
+        struct i386_dirent *dp32 = (struct i386_dirent *)&(dp64->d_off);
+        dp32->d_ino = ino32;
+        dp32->d_off = off32;
+        dp32->d_reclen -= 8;
+        return dp32;
+    }
+    else
+    {
+        static pFp_t f = NULL;
+        if(!f) {
+            library_t* lib = my_lib;
+            if(!lib) return NULL;
+            f = (pFp_t)dlsym(lib->priv.w.lib, "readdir");
+        }
+
+        return f(dirp);
+    }
+}
+
+EXPORT int32_t my_readdir_r(x64emu_t* emu, void* dirp, void* entry, void** result)
+{
+    struct dirent64 d64, *dp64;
+    if (fix_64bit_inodes && (sizeof(d64.d_name) > 1))
+    {
+        static iFppp_t f = NULL;
+        if(!f) {
+            library_t* lib = my_lib;
+            if(!lib)
+            {
+                *result = NULL;
+                return 0;
+            }
+            f = (iFppp_t)dlsym(lib->priv.w.lib, "readdir64_r");
+        }
+
+        int r = f(dirp, &d64, &dp64);
+        if (r || !dp64 || !entry)
+        {
+            *result = NULL;
+            return r;
+        }
+
+        struct i386_dirent *dp32 = (struct i386_dirent *)entry;
+        int namelen = dp64->d_reclen - offsetof(struct dirent64, d_name);
+        if (namelen > sizeof(dp32->d_name))
+        {
+            *result = NULL;
+            return ENAMETOOLONG;
+        }
+
+        dp32->d_ino = dp64->d_ino ^ (dp64->d_ino >> 32);
+        dp32->d_off = dp64->d_off;
+        dp32->d_reclen = namelen + offsetof(struct i386_dirent, d_name);
+        dp32->d_type = dp64->d_type;
+        memcpy(dp32->d_name, dp64->d_name, namelen);
+        *result = dp32;
+        return 0;
+    }
+    else
+    {
+        static iFppp_t f = NULL;
+        if(!f) {
+            library_t* lib = my_lib;
+            if(!lib)
+            {
+                *result = NULL;
+                return 0;
+            }
+            f = (iFppp_t)dlsym(lib->priv.w.lib, "readdir_r");
+        }
+
+        return f(dirp, entry, result);
+    }
+}
+
+static int isProcSelf(const char *path, const char* w)
+{
+    if(strncmp(path, "/proc/", 6)==0) {
+        char tmp[64];
+        // check if self ....
+        sprintf(tmp, "/proc/self/%s", w);
+        if(strcmp((const char*)path, tmp)==0)
+            return 1;
+        // check if self PID ....
+        pid_t pid = getpid();
+        sprintf(tmp, "/proc/%d/%s", pid, w);
+        if(strcmp((const char*)path, tmp)==0)
+            return 1;
+    }
+    return 0;
+}
+
+EXPORT int32_t my_readlink(x64emu_t* emu, void* path, void* buf, uint32_t sz)
+{
+    if(isProcSelf((const char*)path, "exe")) {
+        // special case for self...
+        return strlen(strncpy((char*)buf, emu->context->fullpath, sz));
+    }
+    return readlink((const char*)path, (char*)buf, sz);
+}
+#ifndef NOALIGN
+
+static int nCPU = 0;
+static double bogoMips = 100.;
+
+void grabNCpu() {
+    nCPU = 1;  // default number of CPU to 1
+    FILE *f = fopen("/proc/cpuinfo", "r");
+    size_t dummy;
+    if(f) {
+        nCPU = 0;
+        size_t len = 0;
+        char* line = NULL;
+        while ((dummy = getline(&line, &len, f)) != -1) {
+            if(!strncmp(line, "processor\t", strlen("processor\t")))
+                ++nCPU;
+            if(!nCPU && !strncmp(line, "BogoMIPS\t", strlen("BogoMIPS\t"))) {
+                // grab 1st BogoMIPS
+                float tmp;
+                if(sscanf(line, "BogoMIPS\t: %g", &tmp)==1)
+                    bogoMips = tmp;
+            }
+        }
+        if(line) free(line);
+        fclose(f);
+        if(!nCPU) nCPU=1;
+    }
+}
+void CreateCPUInfoFile(int fd)
+{
+    size_t dummy;
+    char buff[600];
+    double freq = 600.0; // default to 600 MHz
+    // try to get actual ARM max speed:
+    FILE *f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq", "r");
+    if(f) {
+        int r;
+        if(1==fscanf(f, "%d", &r))
+            freq = r/1000.;
+        fclose(f);
+    }
+    if(!nCPU)
+        grabNCpu();
+    int n = nCPU;
+    // generate fake CPUINFO
+    int gigahertz=(freq>=1000.);
+    #define P \
+    dummy = write(fd, buff, strlen(buff))
+    for (int i=0; i<n; ++i) {
+        sprintf(buff, "processor\t: %d\n", i);
+        P;
+        sprintf(buff, "vendor_id\t: GenuineIntel\n");
+        P;
+        sprintf(buff, "cpu family\t: 6\n");
+        P;
+        sprintf(buff, "model\t\t: 1\n");
+        P;
+        sprintf(buff, "model name\t: Intel Pentium IV @ %g%cHz\n", gigahertz?(freq/1000.):freq, gigahertz?'G':'M');
+        P;
+        sprintf(buff, "stepping\t: 1\nmicrocode\t: 0x10\n");
+        P;
+        sprintf(buff, "cpu MHz\t\t: %g\n", freq);
+        P;
+        sprintf(buff, "cache size\t: %d\n", 4096);
+        P;
+        sprintf(buff, "physical id\t: %d\nsiblings\t: %d\n", i, n);
+        P;
+        sprintf(buff, "core id\t\t:%d\ncpu cores\t: %d\n", i, 1);
+        P;
+        sprintf(buff, "bogomips\t: %g\n", bogoMips);
+        P;
+        sprintf(buff, "flags\t\t: fpu cx8 sep cmov clflush mmx sse sse2 rdtscp ssse3 fma fxsr cx16 movbe pni\n");
+        P;
+        sprintf(buff, "\n");
+        P;
+    }
+    (void)dummy;
+    #undef P
+}
+static int isCpuTopology(const char* p) {
+    if(strstr(p, "/sys/devices/system/cpu/cpu")!=p)
+        return -1;  //nope
+    if( FileExist(p, -1))
+        return -1;  //no need to fake it
+    char buf[512];
+    const char* p2 = p + strlen("/sys/devices/system/cpu/cpu");
+    int n = 0;
+    while(*p2>='0' && *p2<='9') {
+        n = n*10+ *p2 - '0';
+        ++p2;
+    }
+    if(!nCPU)
+        grabNCpu();
+    if(n>=nCPU) // filter for non existing cpu
+        return -1;
+    snprintf(buf, 512, "/sys/devices/system/cpu/cpu%d/topology/core_id", n);
+    if(!strcmp(p, buf))
+        return n;
+    return -1;
+}
+static void CreateCPUTopologyCoreID(int fd, int cpu)
+{
+    char buf[512];
+    snprintf(buf, 512, "%d\n", cpu);
+    size_t dummy = write(fd, buf, strlen(buf));
+    (void)dummy;
+}
+
+
+#define TMP_CPUINFO "box64_tmpcpuinfo"
+#define TMP_CPUTOPO "box64_tmpcputopo%d"
+#endif
+#define TMP_MEMMAP  "box64_tmpmemmap"
+#define TMP_CMDLINE "box64_tmpcmdline"
+EXPORT int32_t my_open(x64emu_t* emu, void* pathname, int32_t flags, uint32_t mode)
+{
+    if(isProcSelf((const char*) pathname, "cmdline")) {
+        // special case for self command line...
+        #if 0
+        char tmpcmdline[200] = {0};
+        char tmpbuff[100] = {0};
+        sprintf(tmpbuff, "%s/cmdlineXXXXXX", getenv("TMP")?getenv("TMP"):".");
+        int tmp = mkstemp(tmpbuff);
+        int dummy;
+        if(tmp<0) return open(pathname, flags, mode);
+        dummy = write(tmp, emu->context->fullpath, strlen(emu->context->fullpath)+1);
+        for (int i=1; i<emu->context->argc; ++i)
+            dummy = write(tmp, emu->context->argv[i], strlen(emu->context->argv[i])+1);
+        lseek(tmp, 0, SEEK_SET);
+        #else
+        int tmp = shm_open(TMP_CMDLINE, O_RDWR | O_CREAT, S_IRWXU);
+        if(tmp<0) return open(pathname, flags, mode);
+        shm_unlink(TMP_CMDLINE);    // remove the shm file, but it will still exist because it's currently in use
+        int dummy = write(tmp, emu->context->fullpath, strlen(emu->context->fullpath)+1);
+        (void)dummy;
+        for (int i=1; i<emu->context->argc; ++i)
+            dummy = write(tmp, emu->context->argv[i], strlen(emu->context->argv[i])+1);
+        lseek(tmp, 0, SEEK_SET);
+        #endif
+        return tmp;
+    }
+    if(isProcSelf((const char*)pathname, "exe")) {
+        return open(emu->context->fullpath, flags, mode);
+    }
+    #ifndef NOALIGN
+    if(strcmp((const char*)pathname, "/proc/cpuinfo")==0) {
+        // special case for cpuinfo
+        int tmp = shm_open(TMP_CPUINFO, O_RDWR | O_CREAT, S_IRWXU);
+        if(tmp<0) return open(pathname, flags, mode); // error fallback
+        shm_unlink(TMP_CPUINFO);    // remove the shm file, but it will still exist because it's currently in use
+        CreateCPUInfoFile(tmp);
+        lseek(tmp, 0, SEEK_SET);
+        return tmp;
+    }
+    if(isCpuTopology((const char*)pathname)!=-1) {
+        int n = isCpuTopology((const char*)pathname);
+        char buf[512];
+        snprintf(buf, 512, TMP_CPUTOPO, n);
+        int tmp = shm_open(buf, O_RDWR | O_CREAT, S_IRWXU);
+        if(tmp<0) return open(pathname, flags, mode); // error fallback
+        shm_unlink(buf);    // remove the shm file, but it will still exist because it's currently in use
+        CreateCPUTopologyCoreID(tmp, n);
+        lseek(tmp, 0, SEEK_SET);
+        return tmp;
+    }
+    #endif
+    int ret = open(pathname, flags, mode);
+    return ret;
+}
+EXPORT int32_t my___open(x64emu_t* emu, void* pathname, int32_t flags, uint32_t mode) __attribute__((alias("my_open")));
+
+#ifdef DYNAREC
+static int hasDBFromAddress(uintptr_t addr)
+{
+    int idx = (addr>>DYNAMAP_SHIFT);
+    return getDB(idx)?1:0;
+}
+#endif
+
+EXPORT int32_t my_read(int fd, void* buf, uint32_t count)
+{
+    int ret = read(fd, buf, count);
+#ifdef DYNAREC
+    if(ret!=count && ret>0) {
+        // continue reading...
+        void* p = buf+ret;
+        if(hasDBFromAddress((uintptr_t)p)) {
+            // allow writing the whole block (this happens with HalfLife, libMiles load code directly from .mix and other file like that)
+            unprotectDB((uintptr_t)p, count-ret);
+            int l;
+            do {
+                l = read(fd, p, count-ret); 
+                if(l>0) {
+                    p+=l; ret+=l;
+                }
+            } while(l>0);
+        }
+    }
+#endif
+    return ret;
+}
+
+EXPORT int32_t my_open64(x64emu_t* emu, void* pathname, int32_t flags, uint32_t mode)
+{
+    if(isProcSelf((const char*)pathname, "cmdline")) {
+        // special case for self command line...
+        #if 0
+        char tmpcmdline[200] = {0};
+        char tmpbuff[100] = {0};
+        sprintf(tmpbuff, "%s/cmdlineXXXXXX", getenv("TMP")?getenv("TMP"):".");
+        int tmp = mkstemp64(tmpbuff);
+        int dummy;
+        if(tmp<0) return open64(pathname, flags, mode);
+        dummy = write(tmp, emu->context->fullpath, strlen(emu->context->fullpath)+1);
+        for (int i=1; i<emu->context->argc; ++i)
+            dummy = write(tmp, emu->context->argv[i], strlen(emu->context->argv[i])+1);
+        lseek64(tmp, 0, SEEK_SET);
+        #else
+        int tmp = shm_open(TMP_CMDLINE, O_RDWR | O_CREAT, S_IRWXU);
+        if(tmp<0) return open64(pathname, flags, mode);
+        shm_unlink(TMP_CMDLINE);    // remove the shm file, but it will still exist because it's currently in use
+        int dummy = write(tmp, emu->context->fullpath, strlen(emu->context->fullpath)+1);
+        (void)dummy;
+        for (int i=1; i<emu->context->argc; ++i)
+            dummy = write(tmp, emu->context->argv[i], strlen(emu->context->argv[i])+1);
+        lseek(tmp, 0, SEEK_SET);
+        #endif
+        return tmp;
+    }
+    if(isProcSelf((const char*)pathname, "exe")) {
+        return open64(emu->context->fullpath, flags, mode);
+    }
+    #ifndef NOALIGN
+    if(strcmp((const char*)pathname, "/proc/cpuinfo")==0) {
+        // special case for cpuinfo
+        int tmp = shm_open(TMP_CPUINFO, O_RDWR | O_CREAT, S_IRWXU);
+        if(tmp<0) return open64(pathname, flags, mode); // error fallback
+        shm_unlink(TMP_CPUINFO);    // remove the shm file, but it will still exist because it's currently in use
+        CreateCPUInfoFile(tmp);
+        lseek(tmp, 0, SEEK_SET);
+        return tmp;
+    }
+    if(isCpuTopology((const char*)pathname)!=-1) {
+        int n = isCpuTopology((const char*)pathname);
+        char buf[512];
+        snprintf(buf, 512, TMP_CPUTOPO, n);
+        int tmp = shm_open(buf, O_RDWR | O_CREAT, S_IRWXU);
+        if(tmp<0) return open64(pathname, flags, mode); // error fallback
+        shm_unlink(buf);    // remove the shm file, but it will still exist because it's currently in use
+        CreateCPUTopologyCoreID(tmp, n);
+        lseek(tmp, 0, SEEK_SET);
+        return tmp;
+    }
+    #endif
+    return open64(pathname, flags, mode);
+}
+
+EXPORT FILE* my_fopen(x64emu_t* emu, const char* path, const char* mode)
+{
+    if(isProcSelf(path, "maps")) {
+        // special case for self memory map
+        int tmp = shm_open(TMP_MEMMAP, O_RDWR | O_CREAT, S_IRWXU);
+        if(tmp<0) return fopen(path, mode); // error fallback
+        shm_unlink(TMP_MEMMAP);    // remove the shm file, but it will still exist because it's currently in use
+        CreateMemorymapFile(emu->context, tmp);
+        lseek(tmp, 0, SEEK_SET);
+        return fdopen(tmp, mode);
+    }
+    #ifndef NOALIGN
+    if(strcmp(path, "/proc/cpuinfo")==0) {
+        // special case for cpuinfo
+        int tmp = shm_open(TMP_CPUINFO, O_RDWR | O_CREAT, S_IRWXU);
+        if(tmp<0) return fopen(path, mode); // error fallback
+        shm_unlink(TMP_CPUINFO);    // remove the shm file, but it will still exist because it's currently in use
+        CreateCPUInfoFile(tmp);
+        lseek(tmp, 0, SEEK_SET);
+        return fdopen(tmp, mode);
+    }
+    if(isCpuTopology(path)!=-1) {
+        int n = isCpuTopology(path);
+        char buf[512];
+        snprintf(buf, 512, TMP_CPUTOPO, n);
+        int tmp = shm_open(buf, O_RDWR | O_CREAT, S_IRWXU);
+        if(tmp<0) return fopen(path, mode); // error fallback
+        shm_unlink(buf);    // remove the shm file, but it will still exist because it's currently in use
+        CreateCPUTopologyCoreID(tmp, n);
+        lseek(tmp, 0, SEEK_SET);
+        return fdopen(tmp, mode);;
+    }
+    #endif
+    if(isProcSelf(path, "exe")) {
+        return fopen(emu->context->fullpath, mode);
+    }
+    return fopen(path, mode);
+}
+
+EXPORT FILE* my_fopen64(x64emu_t* emu, const char* path, const char* mode)
+{
+    if(isProcSelf(path, "maps")) {
+        // special case for self memory map
+        int tmp = shm_open(TMP_MEMMAP, O_RDWR | O_CREAT, S_IRWXU);
+        if(tmp<0) return fopen64(path, mode); // error fallback
+        shm_unlink(TMP_MEMMAP);    // remove the shm file, but it will still exist because it's currently in use
+        CreateMemorymapFile(emu->context, tmp);
+        lseek(tmp, 0, SEEK_SET);
+        return fdopen(tmp, mode);
+    }
+    #ifndef NOALIGN
+    if(strcmp(path, "/proc/cpuinfo")==0) {
+        // special case for cpuinfo
+        int tmp = shm_open(TMP_CPUINFO, O_RDWR | O_CREAT, S_IRWXU);
+        if(tmp<0) return fopen64(path, mode); // error fallback
+        shm_unlink(TMP_CPUINFO);    // remove the shm file, but it will still exist because it's currently in use
+        CreateCPUInfoFile(tmp);
+        lseek(tmp, 0, SEEK_SET);
+        return fdopen(tmp, mode);
+    }
+    if(isCpuTopology(path)!=-1) {
+        int n = isCpuTopology(path);
+        char buf[512];
+        snprintf(buf, 512, TMP_CPUTOPO, n);
+        int tmp = shm_open(buf, O_RDWR | O_CREAT, S_IRWXU);
+        if(tmp<0) return fopen(path, mode); // error fallback
+        shm_unlink(buf);    // remove the shm file, but it will still exist because it's currently in use
+        CreateCPUTopologyCoreID(tmp, n);
+        lseek(tmp, 0, SEEK_SET);
+        return fdopen(tmp, mode);;
+    }
+    #endif
+    if(isProcSelf(path, "exe")) {
+        return fopen64(emu->context->fullpath, mode);
+    }
+    return fopen64(path, mode);
+}
+
+
+EXPORT int my_mkstemps64(x64emu_t* emu, char* template, int suffixlen)
+{
+    library_t* lib = my_lib;
+    if(!lib) return 0;
+    void* f = dlsym(lib->priv.w.lib, "mkstemps64");
+    if(f)
+        return ((iFpi_t)f)(template, suffixlen);
+    // implement own version...
+    // TODO: check size of template, and if really XXXXXX is there
+    char* fname = strdup(template);
+    do {
+        strcpy(fname, template);
+        char num[8];
+        sprintf(num, "%06d", rand()%999999);
+        memcpy(fname+strlen(fname)-suffixlen-6, num, 6);
+    } while(!FileExist(fname, -1));
+    int ret = open64(fname, O_EXCL);
+    free(fname);
+    return ret;
+}
+
+EXPORT int32_t my_ftw(x64emu_t* emu, void* pathname, void* B, int32_t nopenfd)
+{
+    static iFppi_t f = NULL;
+    if(!f) {
+        library_t* lib = my_lib;
+        if(!lib) return 0;
+        f = (iFppi_t)dlsym(lib->priv.w.lib, "ftw");
+    }
+
+    return f(pathname, findftwFct(B), nopenfd);
+}
+
+EXPORT int32_t my_nftw(x64emu_t* emu, void* pathname, void* B, int32_t nopenfd, int32_t flags)
+{
+    static iFppii_t f = NULL;
+    if(!f) {
+        library_t* lib = my_lib;
+        if(!lib) return 0;
+        f = (iFppii_t)dlsym(lib->priv.w.lib, "nftw");
+    }
+
+    return f(pathname, findnftwFct(B), nopenfd, flags);
+}
+
+EXPORT void* my_ldiv(x64emu_t* emu, void* p, int32_t num, int32_t den)
+{
+    *((ldiv_t*)p) = ldiv(num, den);
+    return p;
+}
+
+#ifndef NOALIGN
+EXPORT int my_epoll_create(x64emu_t* emu, int size)
+{
+    return epoll_create(size);
+}
+EXPORT int my_epoll_create1(x64emu_t* emu, int flags)
+{
+    return epoll_create1(flags);
+}
+EXPORT int32_t my_epoll_ctl(x64emu_t* emu, int32_t epfd, int32_t op, int32_t fd, void* event)
+{
+    struct epoll_event _event[1] = {0};
+    if(event && (op!=EPOLL_CTL_DEL))
+        AlignEpollEvent(_event, event, 1);
+    return epoll_ctl(epfd, op, fd, event?_event:event);
+}
+EXPORT int32_t my_epoll_wait(x64emu_t* emu, int32_t epfd, void* events, int32_t maxevents, int32_t timeout)
+{
+    struct epoll_event _events[maxevents];
+    //AlignEpollEvent(_events, events, maxevents);
+    int32_t ret = epoll_wait(epfd, events?_events:NULL, maxevents, timeout);
+    if(ret>0)
+        UnalignEpollEvent(events, _events, ret);
+    return ret;
+}
+#endif
+
+EXPORT int32_t my_glob(x64emu_t *emu, void* pat, int32_t flags, void* errfnc, void* pglob)
+{
+    static iFpipp_t f = NULL;
+    if(!f) {
+        library_t* lib = my_lib;
+        if(!lib) return 0;
+        f = (iFpipp_t)dlsym(lib->priv.w.lib, "glob");
+    }
+
+    return f(pat, flags, findgloberrFct(errfnc), pglob);
+}
+
+EXPORT int32_t my_glob64(x64emu_t *emu, void* pat, int32_t flags, void* errfnc, void* pglob)
+{
+    return glob64(pat, flags, findgloberrFct(errfnc), pglob);
+}
+
+EXPORT int my_scandir64(x64emu_t *emu, void* dir, void* namelist, void* sel, void* comp)
+{
+    return scandir64(dir, namelist, findfilter64Fct(sel), findcompare64Fct(comp));
+}
+
+EXPORT int my_scandir(x64emu_t *emu, void* dir, void* namelist, void* sel, void* comp)
+{
+    static iFpppp_t f = NULL;
+    if(!f) {
+        library_t* lib = my_lib;
+        if(!lib) return 0;
+        f = (iFpppp_t)dlsym(lib->priv.w.lib, "scandir");
+    }
+
+    return f(dir, namelist, findfilter_dirFct(sel), findcompare_dirFct(comp));
+}
+
+EXPORT int my_ftw64(x64emu_t* emu, void* filename, void* func, int descriptors)
+{
+    return ftw64(filename, findftw64Fct(func), descriptors);
+}
+
+EXPORT int32_t my_nftw64(x64emu_t* emu, void* pathname, void* B, int32_t nopenfd, int32_t flags)
+{
+    return nftw64(pathname, findnftw64Fct(B), nopenfd, flags);
+}
+
+EXPORT int32_t my_execv(x64emu_t* emu, const char* path, char* const argv[])
+{
+    int self = isProcSelf(path, "exe");
+    int x86 = FileIsX86ELF(path);
+    printf_log(LOG_DEBUG, "execv(\"%s\", %p) is x86=%d\n", path, argv, x86);
+    #if 1
+    if ((x86 || self) && argv) {
+        int skip_first = 0;
+        if(strlen(path)>=strlen("wine-preloader") && strcmp(path+strlen(path)-strlen("wine-preloader"), "wine-preloader")==0)
+            skip_first++;
+        // count argv...
+        int n=skip_first;
+        while(argv[n]) ++n;
+        const char** newargv = (const char**)calloc(n+2, sizeof(char*));
+        newargv[0] = emu->context->box64path;
+        memcpy(newargv+1, argv+skip_first, sizeof(char*)*(n+1));
+        if(self) newargv[1] = emu->context->fullpath;
+        printf_log(LOG_DEBUG, " => execv(\"%s\", %p [\"%s\", \"%s\", \"%s\"...:%d])\n", emu->context->box64path, newargv, newargv[0], n?newargv[1]:"", (n>1)?newargv[2]:"",n);
+        int ret = execv(newargv[0], (char* const*)newargv);
+        free(newargv);
+        return ret;
+    }
+    #endif
+    if(self && !argv)
+        return execv(emu->context->box64path, argv);
+    return execv(path, argv);
+}
+
+EXPORT int32_t my_execve(x64emu_t* emu, const char* path, char* const argv[], char* const envp[])
+{
+    int self = isProcSelf(path, "exe");
+    int x86 = FileIsX86ELF(path);
+    printf_log(LOG_DEBUG, "execv(\"%s\", %p) is x86=%d\n", path, argv, x86);
+    #if 1
+    if ((x86 || self) && argv) {
+        int skip_first = 0;
+        if(strlen(path)>=strlen("wine-preloader") && strcmp(path+strlen(path)-strlen("wine-preloader"), "wine-preloader")==0)
+            skip_first++;
+        // count argv...
+        int n=skip_first;
+        while(argv[n]) ++n;
+        const char** newargv = (const char**)calloc(n+2, sizeof(char*));
+        newargv[0] = emu->context->box64path;
+        memcpy(newargv+1, argv+skip_first, sizeof(char*)*(n+1));
+        if(self) newargv[1] = emu->context->fullpath;
+        printf_log(LOG_DEBUG, " => execv(\"%s\", %p [\"%s\", \"%s\", \"%s\"...:%d])\n", emu->context->box64path, newargv, newargv[0], n?newargv[1]:"", (n>1)?newargv[2]:"",n);
+        int ret = execve(newargv[0], (char* const*)newargv, envp);
+        free(newargv);
+        return ret;
+    }
+    #endif
+    if(self && !argv)
+        return execve(emu->context->box64path, argv, envp);
+    return execve(path, argv, envp);
+}
+
+// execvp should use PATH to search for the program first
+EXPORT int32_t my_execvp(x64emu_t* emu, const char* path, char* const argv[])
+{
+    // need to use BOX86_PATH / PATH here...
+    char* fullpath = ResolveFile(path, &my_context->box64_path);
+    // use fullpath...
+    int self = isProcSelf(fullpath, "exe");
+    int x86 = FileIsX86ELF(fullpath);
+    printf_log(LOG_DEBUG, "execvp(\"%s\", %p), IsX86=%d / fullpath=\"%s\"\n", path, argv, x86, fullpath);
+    free(fullpath);
+    if ((x86 || self) && argv) {
+        // count argv...
+        int i=0;
+        while(argv[i]) ++i;
+        char** newargv = (char**)calloc(i+2, sizeof(char*));
+        newargv[0] = emu->context->box64path;
+        for (int j=0; j<i; ++j)
+            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);
+        free(newargv);
+        return ret;
+    }
+    if(self && !argv)
+        return execvp(emu->context->box64path, argv);
+    // fullpath is gone, so the search will only be on PATH, not on BOX86_PATH (is that an issue?)
+    return execvp(path, argv);
+}
+
+// execvp should use PATH to search for the program first
+EXPORT int32_t my_posix_spawnp(x64emu_t* emu, pid_t* pid, const char* path, 
+    const posix_spawn_file_actions_t *actions, const posix_spawnattr_t* attrp,  char* const argv[], char* const envp[])
+{
+    // need to use BOX86_PATH / PATH here...
+    char* fullpath = ResolveFile(path, &my_context->box64_path);
+    // use fullpath...
+    int self = isProcSelf(fullpath, "exe");
+    int x86 = FileIsX86ELF(fullpath);
+    printf_log(LOG_DEBUG, "posix_spawnp(%p, \"%s\", %p, %p, %p, %p), IsX86=%d / fullpath=\"%s\"\n", pid, path, actions, attrp, argv, envp, x86, fullpath);
+    free(fullpath);
+    if ((x86 || self)) {
+        // count argv...
+        int i=0;
+        while(argv[i]) ++i;
+        char** newargv = (char**)calloc(i+2, sizeof(char*));
+        newargv[0] = emu->context->box64path;
+        for (int j=0; j<i; ++j)
+            newargv[j+1] = argv[j];
+        if(self) newargv[1] = emu->context->fullpath;
+        printf_log(LOG_DEBUG, " => posix_spawnp(%p, \"%s\", %p, %p, %p [\"%s\", \"%s\"...:%d], %p)\n", pid, newargv[0], actions, attrp, newargv, newargv[1], i?newargv[2]:"", i, envp);
+        int ret = posix_spawnp(pid, newargv[0], actions, attrp, newargv, envp);
+        printf_log(LOG_DEBUG, "posix_spawnp returned %d\n", ret);
+        //free(newargv);
+        return ret;
+    }
+    // fullpath is gone, so the search will only be on PATH, not on BOX86_PATH (is that an issue?)
+    return posix_spawnp(pid, path, actions, attrp, argv, envp);
+}
+
+EXPORT void my__Jv_RegisterClasses() {}
+
+EXPORT int32_t my___cxa_thread_atexit_impl(x64emu_t* emu, void* dtor, void* obj, void* dso)
+{
+    printf_log(LOG_INFO, "Warning, call to __cxa_thread_atexit_impl(%p, %p, %p) ignored\n", dtor, obj, dso);
+    return 0;
+}
+
+extern void __chk_fail();
+EXPORT unsigned long int my___fdelt_chk (unsigned long int d)
+{
+  if (d >= FD_SETSIZE)
+    __chk_fail ();
+
+  return d / __NFDBITS;
+}
+
+EXPORT int32_t my_getrandom(x64emu_t* emu, void* buf, uint32_t buflen, uint32_t flags)
+{
+    // not always implemented on old linux version...
+    library_t* lib = my_lib;
+    if(!lib) return 0;
+    void* f = dlsym(lib->priv.w.lib, "getrandom");
+    if(f)
+        return ((iFpuu_t)f)(buf, buflen, flags);
+    // do what should not be done, but it's better then nothing....
+    FILE * rnd = fopen("/dev/urandom", "rb");
+    uint32_t r = fread(buf, 1, buflen, rnd);
+    fclose(rnd);
+    return r;
+}
+
+EXPORT int32_t my_recvmmsg(x64emu_t* emu, int32_t fd, void* msgvec, uint32_t vlen, uint32_t flags, void* timeout)
+{
+    // Implemented starting glibc 2.12+
+    library_t* lib = my_lib;
+    if(!lib) return 0;
+    void* f = dlsym(lib->priv.w.lib, "recvmmsg");
+    if(f)
+        return ((iFipuup_t)f)(fd, msgvec, vlen, flags, timeout);
+    // Use the syscall
+    return syscall(__NR_recvmmsg, fd, msgvec, vlen, flags, timeout);
+}
+
+EXPORT int32_t my___sendmmsg(x64emu_t* emu, int32_t fd, void* msgvec, uint32_t vlen, uint32_t flags)
+{
+    // Implemented starting glibc 2.14+
+    library_t* lib = my_lib;
+    if(!lib) return 0;
+    void* f = dlsym(lib->priv.w.lib, "__sendmmsg");
+    if(f)
+        return ((iFipuu_t)f)(fd, msgvec, vlen, flags);
+    // Use the syscall
+    return syscall(__NR_sendmmsg, fd, msgvec, vlen, flags);
+}
+
+EXPORT int32_t my___register_atfork(x64emu_t *emu, void* prepare, void* parent, void* child, void* handle)
+{
+    // this is partly incorrect, because the emulated funcionts 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));
+    }
+    my_context->atforks[my_context->atfork_sz].prepare = (uintptr_t)prepare;
+    my_context->atforks[my_context->atfork_sz].parent = (uintptr_t)parent;
+    my_context->atforks[my_context->atfork_sz].child = (uintptr_t)child;
+    my_context->atforks[my_context->atfork_sz].handle = handle;
+    return 0;
+}
+
+EXPORT uint64_t my___umoddi3(uint64_t a, uint64_t b)
+{
+    return a%b;
+}
+EXPORT uint64_t my___udivdi3(uint64_t a, uint64_t b)
+{
+    return a/b;
+}
+EXPORT int64_t my___divdi3(int64_t a, int64_t b)
+{
+    return a/b;
+}
+
+EXPORT int32_t my___poll_chk(void* a, uint32_t b, int c, int l)
+{
+    return poll(a, b, c);   // no check...
+}
+
+EXPORT int32_t my_fcntl64(x64emu_t* emu, int32_t a, int32_t b, uint32_t d1, uint32_t d2, uint32_t d3, uint32_t d4, uint32_t d5, uint32_t d6)
+{
+    // Implemented starting glibc 2.14+
+    library_t* lib = my_lib;
+    if(!lib) return 0;
+    iFiiV_t f = dlsym(lib->priv.w.lib, "fcntl64");
+    if(b==F_SETFL)
+        d1 = of_convert(d1);
+    if(b==F_GETLK64 || b==F_SETLK64 || b==F_SETLKW64)
+    {
+        my_flock64_t fl;
+        AlignFlock64(&fl, (void*)d1);
+        int ret = f?f(a, b, &fl):fcntl(a, b, &fl);
+        UnalignFlock64((void*)d1, &fl);
+        return ret;
+    }
+    //TODO: check if better to use the syscall or regular fcntl?
+    //return syscall(__NR_fcntl64, a, b, d1);   // should be enough
+    int ret = f?f(a, b, d1):fcntl(a, b, d1);
+
+    if(b==F_GETFL && ret!=-1)
+        ret = of_unconvert(ret);
+
+    return ret;
+}
+
+EXPORT int32_t my_fcntl(x64emu_t* emu, int32_t a, int32_t b, uint32_t d1, uint32_t d2, uint32_t d3, uint32_t d4, uint32_t d5, uint32_t d6)
+{
+    if(b==F_SETFL && d1==0xFFFFF7FF) {
+        // special case for ~O_NONBLOCK...
+        int flags = fcntl(a, F_GETFL);
+        if(flags&O_NONBLOCK) {
+            flags &= ~O_NONBLOCK;
+            return fcntl(a, b, flags);
+        }
+        return 0;
+    }
+    if(b==F_SETFL)
+        d1 = of_convert(d1);
+    if(b==F_GETLK64 || b==F_SETLK64 || b==F_SETLKW64)
+    {
+        my_flock64_t fl;
+        AlignFlock64(&fl, (void*)d1);
+        int ret = fcntl(a, b, &fl);
+        UnalignFlock64((void*)d1, &fl);
+        return ret;
+    }
+    int ret = fcntl(a, b, d1);
+    if(b==F_GETFL && ret!=-1)
+        ret = of_unconvert(ret);
+    
+    return ret;    
+}
+EXPORT int32_t my___fcntl(x64emu_t* emu, int32_t a, int32_t b, uint32_t d1, uint32_t d2, uint32_t d3, uint32_t d4, uint32_t d5, uint32_t d6) __attribute__((alias("my_fcntl")));
+
+EXPORT int32_t my_preadv64(x64emu_t* emu, int32_t fd, void* v, int32_t c, int64_t o)
+{
+    library_t* lib = my_lib;
+    if(!lib) return 0;
+    void* f = dlsym(lib->priv.w.lib, "preadv64");
+    if(f)
+        return ((iFipiI_t)f)(fd, v, c, o);
+    return syscall(__NR_preadv, fd, v, c,(uint32_t)(o&0xffffffff), (uint32_t)((o>>32)&0xffffffff));
+}
+
+EXPORT int32_t my_pwritev64(x64emu_t* emu, int32_t fd, void* v, int32_t c, int64_t o)
+{
+    library_t* lib = my_lib;
+    if(!lib) return 0;
+    void* f = dlsym(lib->priv.w.lib, "pwritev64");
+    if(f)
+        return ((iFipiI_t)f)(fd, v, c, o);
+    #ifdef __arm__
+    return syscall(__NR_pwritev, fd, v, c, 0, (uint32_t)(o&0xffffffff), (uint32_t)((o>>32)&0xffffffff));
+    // on arm, 64bits args needs to be on even/odd register, so need to put a 0 for aligment
+    #else
+    return syscall(__NR_pwritev, fd, v, c,(uint32_t)(o&0xffffffff), (uint32_t)((o>>32)&0xffffffff));
+    #endif
+}
+
+EXPORT int32_t my_accept4(x64emu_t* emu, int32_t fd, void* a, void* l, int32_t flags)
+{
+    library_t* lib = my_lib;
+    if(!lib) return 0;
+    void* f = dlsym(lib->priv.w.lib, "accept4");
+    if(f)
+        return ((iFippi_t)f)(fd, a, l, flags);
+    if(!flags)
+        return accept(fd, a, l);
+    return syscall(__NR_accept4, fd, a, l, flags);
+}
+
+EXPORT  int32_t my_fallocate64(int fd, int mode, int64_t offs, int64_t len)
+{
+    iFiiII_t f = NULL;
+    static int done = 0;
+    if(!done) {
+        library_t* lib = my_lib;
+        f = (iFiiII_t)dlsym(lib->priv.w.lib, "fallocate64");
+        done = 1;
+    }
+    if(f)
+        return f(fd, mode, offs, len);
+    else
+        return syscall(__NR_fallocate, fd, mode, (uint32_t)(offs&0xffffffff), (uint32_t)((offs>>32)&0xffffffff), (uint32_t)(len&0xffffffff), (uint32_t)((len>>32)&0xffffffff));
+        //return posix_fallocate64(fd, offs, len);
+}
+
+EXPORT struct __processor_model
+{
+  unsigned int __cpu_vendor;
+  unsigned int __cpu_type;
+  unsigned int __cpu_subtype;
+  unsigned int __cpu_features[1];
+} my___cpu_model;
+
+#include "cpu_info.h"
+void InitCpuModel()
+{
+    // some pseudo random cpu info...
+    my___cpu_model.__cpu_vendor = VENDOR_INTEL;
+    my___cpu_model.__cpu_type = INTEL_PENTIUM_M;
+    my___cpu_model.__cpu_subtype = 0; // N/A
+    my___cpu_model.__cpu_features[0] = (1<<FEATURE_CMOV) 
+                                     | (1<<FEATURE_MMX) 
+                                     | (1<<FEATURE_SSE) 
+                                     | (1<<FEATURE_SSE2) 
+                                     | (1<<FEATURE_SSE3)
+                                     | (1<<FEATURE_SSSE3)
+                                     | (1<<FEATURE_MOVBE)
+                                     | (1<<FEATURE_ADX);
+}
+#endif
+EXPORT const unsigned short int *my___ctype_b;
+EXPORT const int32_t *my___ctype_tolower;
+EXPORT const int32_t *my___ctype_toupper;
+
+void ctSetup()
+{
+    my___ctype_b = *(__ctype_b_loc());
+    my___ctype_toupper = *(__ctype_toupper_loc());
+    my___ctype_tolower = *(__ctype_tolower_loc());
+}
+
+EXPORT void* my___libc_stack_end;
+void stSetup(box64context_t* context)
+{
+    my___libc_stack_end = context->stack;   // is this the end, or should I add stasz?
+}
+
+EXPORT void my___register_frame_info(void* a, void* b)
+{
+    // nothing
+}
+EXPORT void* my___deregister_frame_info(void* a)
+{
+    return NULL;
+}
+
+EXPORT void* my____brk_addr = NULL;
+#if 0
+// longjmp / setjmp
+typedef struct jump_buff_i386_s {
+ uint32_t save_ebx;
+ uint32_t save_esi;
+ uint32_t save_edi;
+ uint32_t save_ebp;
+ uint32_t save_esp;
+ uint32_t save_eip;
+} jump_buff_i386_t;
+
+typedef struct __jmp_buf_tag_s {
+    jump_buff_i386_t __jmpbuf;
+    int              __mask_was_saved;
+    __sigset_t       __saved_mask;
+} __jmp_buf_tag_t;
+
+void EXPORT my_longjmp(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p, int32_t __val)
+{
+    jump_buff_i386_t *jpbuff = &((__jmp_buf_tag_t*)p)->__jmpbuf;
+    //restore  regs
+    R_EBX = jpbuff->save_ebx;
+    R_ESI = jpbuff->save_esi;
+    R_EDI = jpbuff->save_edi;
+    R_EBP = jpbuff->save_ebp;
+    R_ESP = jpbuff->save_esp;
+    // jmp to saved location, plus restore val to eax
+    R_EAX = __val;
+    R_EIP = jpbuff->save_eip;
+    if(emu->quitonlongjmp) {
+        emu->longjmp = 1;
+        emu->quit = 1;
+    }
+}
+
+EXPORT int32_t my_setjmp(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p)
+{
+    jump_buff_i386_t *jpbuff = &((__jmp_buf_tag_t*)p)->__jmpbuf;
+    // save the buffer
+    jpbuff->save_ebx = R_EBX;
+    jpbuff->save_esi = R_ESI;
+    jpbuff->save_edi = R_EDI;
+    jpbuff->save_ebp = R_EBP;
+    jpbuff->save_esp = R_ESP+4; // include "return address"
+    jpbuff->save_eip = *(uint32_t*)(R_ESP);
+    // and that's it.. Nothing more for now
+    return 0;
+}
+
+EXPORT void my___explicit_bzero_chk(x64emu_t* emu, void* dst, uint32_t len, uint32_t dstlen)
+{
+    memset(dst, 0, len);
+}
+
+EXPORT void* my_realpath(x64emu_t* emu, void* path, void* resolved_path)
+{
+
+    if(isProcSelf(path, "exe")) {
+        return realpath(emu->context->fullpath, resolved_path);
+    }
+        return realpath(path, resolved_path);
+}
+
+EXPORT void* my_mmap(x64emu_t* emu, void *addr, unsigned long length, int prot, int flags, int fd, int offset)
+{
+    if(prot&PROT_WRITE) 
+        prot|=PROT_READ;    // PROT_READ is implicit with PROT_WRITE on i386
+    if(box64_log<LOG_DEBUG) {dynarec_log(LOG_DEBUG, "mmap(%p, %lu, 0x%x, 0x%x, %d, %d) =>", addr, length, prot, flags, fd, offset);}
+    void* ret = mmap(addr, length, prot, flags, fd, offset);
+    if(box64_log<LOG_DEBUG) {dynarec_log(LOG_DEBUG, "%p\n", ret);}
+    #ifdef DYNAREC
+    if(box64_dynarec && ret!=(void*)-1) {
+        if(flags&0x100000 && addr!=ret)
+        {
+            // program used MAP_FIXED_NOREPLACE but the host linux didn't support it
+            // and responded with a different address, so ignore it
+        } else {
+            if(prot& PROT_EXEC)
+                addDBFromAddressRange((uintptr_t)ret, length);
+            else
+                cleanDBFromAddressRange((uintptr_t)ret, length, prot?0:1);
+        }
+    } 
+    #endif
+    if(ret!=(void*)-1)
+        setProtection((uintptr_t)ret, length, prot);
+    return ret;
+}
+
+EXPORT void* my_mmap64(x64emu_t* emu, void *addr, unsigned long length, int prot, int flags, int fd, int64_t offset)
+{
+    if(prot&PROT_WRITE) 
+        prot|=PROT_READ;    // PROT_READ is implicit with PROT_WRITE on i386
+    if(box64_log<LOG_DEBUG) {dynarec_log(LOG_DEBUG, "mmap64(%p, %lu, 0x%x, 0x%x, %d, %lld) =>", addr, length, prot, flags, fd, offset);}
+    void* ret = mmap64(addr, length, prot, flags, fd, offset);
+    if(box64_log<LOG_DEBUG) {dynarec_log(LOG_DEBUG, "%p\n", ret);}
+    #ifdef DYNAREC
+    if(box64_dynarec && ret!=(void*)-1) {
+        if(flags&0x100000 && addr!=ret)
+        {
+            // program used MAP_FIXED_NOREPLACE but the host linux didn't support it
+            // and responded with a different address, so ignore it
+        } else {
+            if(prot& PROT_EXEC)
+                addDBFromAddressRange((uintptr_t)ret, length);
+            else
+                cleanDBFromAddressRange((uintptr_t)ret, length, prot?0:1);
+        }
+    }
+    #endif
+    if(ret!=(void*)-1)
+        setProtection((uintptr_t)ret, length, prot);
+    return ret;
+}
+
+EXPORT void* my_mremap(x64emu_t* emu, void* old_addr, size_t old_size, size_t new_size, int flags, void* new_addr)
+{
+    dynarec_log(/*LOG_DEBUG*/LOG_NONE, "mremap(%p, %u, %u, %d, %p)=>", old_addr, old_size, new_size, flags, new_addr);
+    void* ret = mremap(old_addr, old_size, new_size, flags, new_addr);
+    if(ret==(void*)-1)
+        return ret; // failed...
+    uint32_t prot = getProtection((uintptr_t)old_addr)&~PROT_DYNAREC;
+    if(ret==old_addr) {
+        if(old_size && old_size<new_size) {
+            setProtection((uintptr_t)ret+old_size, new_size-old_size, prot);
+            #ifdef DYNAREC
+            if(box64_dynarec)
+                addDBFromAddressRange((uintptr_t)ret+old_size, new_size-old_size);
+            #endif
+        } else if(old_size && new_size<old_size) {
+            setProtection((uintptr_t)ret+new_size, old_size-new_size, 0);
+            #ifdef DYNAREC
+            if(box64_dynarec)
+                cleanDBFromAddressRange((uintptr_t)ret+new_size, new_size-old_size, 1);
+            #endif
+        } else if(!old_size) {
+            setProtection((uintptr_t)ret, new_size, prot);
+            #ifdef DYNAREC
+            if(box64_dynarec)
+                addDBFromAddressRange((uintptr_t)ret, new_size);
+            #endif
+        }
+    } else {
+        if(old_size
+        #ifdef MREMAP_DONTUNMAP
+        && flags&MREMAP_DONTUNMAP==0
+        #endif
+        ) {
+            setProtection((uintptr_t)old_addr, old_size, 0);
+            #ifdef DYNAREC
+            if(box64_dynarec)
+                cleanDBFromAddressRange((uintptr_t)old_addr, old_size, 1);
+            #endif
+        }
+        setProtection((uintptr_t)ret, new_size, prot); // should copy the protection from old block
+        #ifdef DYNAREC
+        if(box64_dynarec)
+            addDBFromAddressRange((uintptr_t)ret, new_size);
+        #endif
+    }
+    return ret;
+}
+
+EXPORT int my_munmap(x64emu_t* emu, void* addr, unsigned long length)
+{
+    dynarec_log(LOG_DEBUG, "munmap(%p, %lu)\n", addr, length);
+    #ifdef DYNAREC
+    if(box64_dynarec) {
+        cleanDBFromAddressRange((uintptr_t)addr, length, 1);
+    }
+    #endif
+    int ret = munmap(addr, length);
+    if(!ret)
+        setProtection((uintptr_t)addr, length, 0);
+    return ret;
+}
+
+EXPORT int my_mprotect(x64emu_t* emu, void *addr, unsigned long len, int prot)
+{
+    dynarec_log(LOG_DEBUG, "mprotect(%p, %lu, 0x%x)\n", addr, len, prot);
+    if(prot&PROT_WRITE) 
+        prot|=PROT_READ;    // PROT_READ is implicit with PROT_WRITE on i386
+    int ret = mprotect(addr, len, prot);
+    #ifdef DYNAREC
+    if(box64_dynarec) {
+        if(prot& PROT_EXEC)
+            addDBFromAddressRange((uintptr_t)addr, len);
+        else
+            cleanDBFromAddressRange((uintptr_t)addr, len, 0);
+    }
+    #endif
+    if(!ret)
+        updateProtection((uintptr_t)addr, len, prot);
+    return ret;
+}
+
+typedef struct my_cookie_s {
+    uintptr_t r, w, s, c;
+    void* cookie;
+} my_cookie_t;
+
+static ssize_t my_cookie_read(void *p, char *buf, size_t size)
+{
+    my_cookie_t* cookie = (my_cookie_t*)p;
+    return (ssize_t)RunFunction(my_context, cookie->r, 3, cookie->cookie, buf, size);
+}
+static ssize_t my_cookie_write(void *p, const char *buf, size_t size)
+{
+    my_cookie_t* cookie = (my_cookie_t*)p;
+    return (ssize_t)RunFunction(my_context, cookie->w, 3, cookie->cookie, buf, size);
+}
+static int my_cookie_seek(void *p, off64_t *offset, int whence)
+{
+    my_cookie_t* cookie = (my_cookie_t*)p;
+    return RunFunction(my_context, cookie->s, 3, cookie->cookie, offset, whence);
+}
+static int my_cookie_close(void *p)
+{
+    my_cookie_t* cookie = (my_cookie_t*)p;
+    int ret = 0;
+    if(cookie->c)
+        ret = RunFunction(my_context, cookie->c, 1, cookie->cookie);
+    free(cookie);
+    return ret;
+}
+EXPORT void* my_fopencookie(x64emu_t* emu, void* cookie, void* mode, void* read, void* write, void* seek, void* close)
+{
+    cookie_io_functions_t io_funcs = {read?my_cookie_read:NULL, write?my_cookie_write:NULL, seek?my_cookie_seek:NULL, my_cookie_close};
+    my_cookie_t *cb = (my_cookie_t*)calloc(1, sizeof(my_cookie_t));
+    cb->r = (uintptr_t)read;
+    cb->w = (uintptr_t)write;
+    cb->s = (uintptr_t)seek;
+    cb->c = (uintptr_t)close;
+    cb->cookie = cookie;
+    return fopencookie(cb, mode, io_funcs);
+}
+
+EXPORT long my_prlimit64(void* pid, uint32_t res, void* new_rlim, void* old_rlim)
+{
+    return syscall(__NR_prlimit64, pid, res, new_rlim, old_rlim);
+}
+
+EXPORT void* my_reallocarray(void* ptr, size_t nmemb, size_t size)
+{
+    return realloc(ptr, nmemb*size);
+}
+
+#ifndef __OPEN_NEEDS_MODE
+# define __OPEN_NEEDS_MODE(oflag) \
+  (((oflag) & O_CREAT) != 0)
+// || ((oflag) & __O_TMPFILE) == __O_TMPFILE)
+#endif
+EXPORT int my___open_nocancel(x64emu_t* emu, void* file, int oflag, int* b)
+{
+    int mode = 0;
+    if (__OPEN_NEEDS_MODE (oflag))
+        mode = b[0];
+    return openat(AT_FDCWD, file, oflag, mode);
+}
+
+EXPORT int my___libc_alloca_cutoff(x64emu_t* emu, size_t size)
+{
+    // not always implemented on old linux version...
+    library_t* lib = my_lib;
+    if(!lib) return 0;
+    void* f = dlsym(lib->priv.w.lib, "__libc_alloca_cutoff");
+    if(f)
+        return ((iFL_t)f)(size);
+    // approximate version but it's better than nothing....
+    return (size<=(65536*4));
+}
+
+// DL functions from wrappedlibdl.c
+void* my_dlopen(x64emu_t* emu, void *filename, int flag);
+int my_dlclose(x64emu_t* emu, void *handle);
+void* my_dlsym(x64emu_t* emu, void *handle, void *symbol);
+EXPORT int my___libc_dlclose(x64emu_t* emu, void* handle)
+{
+    return my_dlclose(emu, handle);
+}
+EXPORT void* my___libc_dlopen_mode(x64emu_t* emu, void* name, int mode)
+{
+    return my_dlopen(emu, name, mode);
+}
+EXPORT void* my___libc_dlsym(x64emu_t* emu, void* handle, void* name)
+{
+    return my_dlsym(emu, handle, name);
+}
+
+// all obstack function defined in obstack.c file
+void obstackSetup();
+
+EXPORT int my_nanosleep(const struct timespec *req, struct timespec *rem)
+{
+    if(!req)
+        return 0;   // workaround for some strange calls
+    return nanosleep(req, rem);
+}
+
+#ifndef NOALIGN
+// wrapped malloc using calloc, it seems x86 malloc set alloc'd block to zero somehow
+EXPORT void* my_malloc(unsigned long size)
+{
+    return calloc(1, size);
+}
+#endif
+
+#ifdef PANDORA
+#define RENAME_NOREPLACE	(1 << 0)
+#define RENAME_EXCHANGE		(1 << 1)
+#define RENAME_WHITEOUT		(1 << 2)
+EXPORT int my_renameat2(int olddirfd, void* oldpath, int newdirfd, void* newpath, uint32_t flags)
+{
+    // simulate that function, but
+    if(flags&RENAME_NOREPLACE) {
+        if(FileExist(newpath, -1)) {
+            errno = EEXIST;
+            return -1;
+        }
+        flags &= ~RENAME_NOREPLACE;
+    }
+    if(!flags) return renameat(olddirfd, oldpath, newdirfd, newpath);
+    if(flags&RENAME_WHITEOUT) {
+        errno = EINVAL;
+        return -1;  // not handling that
+    }
+    if((flags&RENAME_EXCHANGE) && (olddirfd==-1) && (newdirfd==-1)) {
+        // cannot do atomically...
+        char* tmp = (char*)malloc(strlen(oldpath)+10); // create a temp intermediary
+        tmp = strcat(oldpath, ".tmp");
+        int ret = renameat(-1, oldpath, -1, tmp);
+        if(ret==-1) return -1;
+        ret = renameat(-1, newpath, -1, oldpath);
+        if(ret==-1) return -1;
+        ret = renameat(-1, tmp, -1, newpath);
+        free(tmp);
+        return ret;
+    }
+    return -1; // unknown flags
+}
+#endif
+
+#ifndef __NR_memfd_create
+#define MFD_CLOEXEC		    0x0001U
+#define MFD_ALLOW_SEALING	0x0002U
+EXPORT int my_memfd_create(x64emu_t* emu, void* name, uint32_t flags)
+{
+    // try to simulate that function
+    uint32_t fl = O_RDWR | O_CREAT;
+    if(flags&MFD_CLOEXEC)
+        fl |= O_CLOEXEC;
+    int tmp = shm_open(name, fl, S_IRWXU);
+    if(tmp<0) return -1;
+    shm_unlink(name);    // remove the shm file, but it will still exist because it's currently in use
+    return tmp;
+}
+#endif
+
+#ifndef GRND_RANDOM
+#define GRND_RANDOM	0x0002
+#endif
+EXPORT int my_getentropy(x64emu_t* emu, void* buffer, size_t length)
+{
+    library_t* lib = my_lib;
+    if(!lib) return 0;
+    void* f = dlsym(lib->priv.w.lib, "getentropy");
+    if(f)
+        return ((iFpL_t)f)(buffer, length);
+    // custom implementation
+    if(length>256) {
+        errno = EIO;
+        return -1;
+    }
+    int ret = my_getrandom(emu, buffer, length, GRND_RANDOM);
+    if(ret!=length) {
+        errno = EIO;
+        return -1;
+    }
+    return 0;
+}
+
+EXPORT void my_mcount(void* frompc, void* selfpc)
+{
+    // stub doing nothing...
+    return;
+}
+
+union semun {
+  int              val;    /* Value for SETVAL */
+  struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
+  unsigned short  *array;  /* Array for GETALL, SETALL */
+  struct seminfo  *__buf;  /* Buffer for IPC_INFO
+                              (Linux-specific) */
+};
+
+EXPORT int my_semctl(x64emu_t* emu, int semid, int semnum, int cmd, union semun b)
+{
+  iFiiiV_t f = semctl;
+  return  ((iFiiiV_t)f)(semid, semnum, cmd, b);
+}
+#endif
+
+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;
+EXPORT char* my_program_invocation_name = NULL;
+EXPORT char* my_program_invocation_short_name = NULL;
+
+#define PRE_INIT\
+    if(box64_tcmalloc_minimal)                                      \
+        lib->priv.w.lib = dlopen(NULL, RTLD_LAZY | RTLD_GLOBAL);    \
+    else
+
+#define CUSTOM_INIT         \
+    box64->libclib = lib;   \
+    my_lib = lib;           \
+    /*InitCpuModel();*/         \
+    ctSetup();              \
+    stSetup(box64);         \
+    /*obstackSetup();*/         \
+    my_environ = my__environ = my___environ = box64->envv;                      \
+    my___progname_full = my_program_invocation_name = box64->argv[0];           \
+    my___progname = my_program_invocation_short_name =                          \
+        strrchr(box64->argv[0], '/');                                           \
+    lib->priv.w.p2 = getLIBCMy(lib);                                            \
+    lib->priv.w.needed = 3;                                                     \
+    lib->priv.w.neededlibs = (char**)calloc(lib->priv.w.needed, sizeof(char*)); \
+    lib->priv.w.neededlibs[0] = strdup("ld-linux-x86-64.so.2");                 \
+    lib->priv.w.neededlibs[1] = strdup("libpthread.so.0");                      \
+    lib->priv.w.neededlibs[2] = strdup("librt.so.1");
+
+#define CUSTOM_FINI \
+    freeLIBCMy(lib->priv.w.p2); \
+    free(lib->priv.w.p2);       \
+    my_lib = NULL;
+
+#include "wrappedlib_init.h"
diff --git a/src/wrapped/wrappedlibc_private.h b/src/wrapped/wrappedlibc_private.h
new file mode 100755
index 00000000..4efac07b
--- /dev/null
+++ b/src/wrapped/wrappedlibc_private.h
@@ -0,0 +1,2238 @@
+#if !(defined(GO) && defined(GOM) && defined(GO2) && defined(DATA) && defined(GOS))
+#error Meh...
+#endif
+
+//GO(a64l, 
+//GO(abort, 
+//DATAB(__abort_msg, 
+//GO(abs, 
+//GO(accept, 
+//GO(accept4, 
+//GOW(access, 
+//GO(acct, 
+//GOW(addmntent, 
+//GOW(addseverity, 
+//GOW(adjtime, 
+//GO(__adjtimex, 
+//GOW(adjtimex, 
+//GOW(advance, 
+//GO(alarm, 
+//GOW(aligned_alloc, 
+//GOW(alphasort, 
+//GOW(alphasort64, 
+//GO(__arch_prctl, 
+//GOW(arch_prctl, 
+//DATA(argp_err_exit_status, 
+//GOW(argp_error, 
+//GOW(argp_failure, 
+//GOW(argp_help, 
+//GOW(argp_parse, 
+//DATAB(argp_program_bug_address, 
+//DATAB(argp_program_version, 
+//DATAB(argp_program_version_hook, 
+//GOW(argp_state_help, 
+//GOW(argp_usage, 
+//GOW(argz_add, 
+//GOW(argz_add_sep, 
+//GOW(argz_append, 
+//GO(__argz_count, 
+//GOW(argz_count, 
+//GOW(argz_create, 
+//GOW(argz_create_sep, 
+//GO(argz_delete, 
+//GOW(argz_extract, 
+//GOW(argz_insert, 
+//GO(__argz_next, 
+//GOW(argz_next, 
+//GOW(argz_replace, 
+//GO(__argz_stringify, 
+//GOW(argz_stringify, 
+//GO(asctime, 
+//GOW(asctime_r, 
+//GO(__asprintf, 
+//GOW(asprintf, 
+//GO(__asprintf_chk, 
+//GO(__assert, 
+//GO(__assert_fail, 
+//GO(__assert_perror_fail, 
+//GO(atof, 
+//GO(atoi, 
+//GO(atol, 
+//GO(atoll, 
+//GO(authdes_create, 
+//GO(authdes_getucred, 
+//GO(authdes_pk_create, 
+//GO(_authenticate, 
+//GO(authnone_create, 
+//GO(authunix_create, 
+//GO(authunix_create_default, 
+//GO(__backtrace, 
+//GOW(backtrace, 
+//GO(__backtrace_symbols, 
+//GOW(backtrace_symbols, 
+//GO(__backtrace_symbols_fd, 
+//GOW(backtrace_symbols_fd, 
+//GOW(basename, 
+//GO(bcopy, 
+//GO(bdflush, 
+//GOW(bind, 
+//GO(bindresvport, 
+//GOW(bindtextdomain, 
+//GOW(bind_textdomain_codeset, 
+//GOW(brk, 
+//GO(__bsd_getpgrp, 
+//GOW(bsd_signal, 
+//GO(bsearch, 
+//GOW(btowc, 
+//GO(__bzero, 
+//GOW(bzero, 
+//GO(c16rtomb, 
+//GOW(c32rtomb, 
+//GOW(calloc, 
+//GO(callrpc, 
+//GO(__call_tls_dtors, 
+//GOW(canonicalize_file_name, 
+//GO(capget, 
+//GO(capset, 
+//GO(catclose, 
+//GO(catgets, 
+//GO(catopen, 
+//GO(cbc_crypt, 
+//GO(cfgetispeed, 
+//GO(cfgetospeed, 
+//GO(cfmakeraw, 
+//GO(cfree, 
+//GO(cfsetispeed, 
+//GO(cfsetospeed, 
+//GO(cfsetspeed, 
+//GOW(chdir, 
+//DATA(__check_rhosts_file, 
+//GO(chflags, 
+//GO(__chk_fail, 
+//GOW(chmod, 
+//GOW(chown, 
+//GO(chroot, 
+//GOW(clearenv, 
+//GO(clearerr, 
+//GO(clearerr_unlocked, 
+//GO(clnt_broadcast, 
+//GO(clnt_create, 
+//GO(clnt_pcreateerror, 
+//GO(clnt_perrno, 
+//GO(clnt_perror, 
+//GO(clntraw_create, 
+//GO(clnt_spcreateerror, 
+//GO(clnt_sperrno, 
+//GO(clnt_sperror, 
+//GO(clnttcp_create, 
+//GO(clntudp_bufcreate, 
+//GO(clntudp_create, 
+//GO(clntunix_create, 
+//GO(clock, 
+//GO(clock_adjtime, 
+//GO(__clock_getcpuclockid, 
+//GOW(clock_getcpuclockid, 
+//GO(__clock_getres, 
+//GOW(clock_getres, 
+//GO(__clock_gettime, 
+//GOW(clock_gettime, 
+//GO(__clock_nanosleep, 
+//GOW(clock_nanosleep, 
+//GO(__clock_settime, 
+//GOW(clock_settime, 
+//GO(__clone, 
+//GOW(clone, 
+//GO(__close, 
+//GOW(close, 
+//GOW(closedir, 
+//GO(closelog, 
+//GO(__close_nocancel, 
+//GO(__cmsg_nxthdr, 
+//GO(confstr, 
+//GO(__confstr_chk, 
+//GOW(__connect, 
+//GOW(connect, 
+//GO(copy_file_range, 
+//GO(__copy_grp, 
+//GOW(copysign, 
+//GOW(copysignf, 
+//GOW(copysignl, 
+//GOW(creat, 
+//GOW(creat64, 
+//GO(create_module, 
+//GO(ctermid, 
+//GO(ctime, 
+//GO(ctime_r, 
+//DATA(__ctype32_b, 
+//DATA(__ctype32_tolower, 
+//DATA(__ctype32_toupper, 
+//DATA(__ctype_b, 
+//GO(__ctype_b_loc, 
+//GOW(__ctype_get_mb_cur_max, 
+//GO(__ctype_init, 
+//DATA(__ctype_tolower, 
+//GO(__ctype_tolower_loc, 
+//DATA(__ctype_toupper, 
+//GO(__ctype_toupper_loc, 
+//DATAB(__curbrk, 
+//GO(cuserid, 
+//GO(__cxa_atexit, 
+//GO(__cxa_at_quick_exit, 
+//GO(__cxa_finalize, 
+//GO(__cxa_thread_atexit_impl, 
+//GO(__cyg_profile_func_enter, 
+//GO(__cyg_profile_func_exit, 
+//GO(daemon, 
+//DATAB(__daylight, 
+//GO(__dcgettext, 
+//GOW(dcgettext, 
+//GOW(dcngettext, 
+//GO(__default_morecore, 
+//GO(delete_module, 
+//GO(des_setparity, 
+//GO(__dgettext, 
+//GOW(dgettext, 
+//GO(difftime, 
+//GO(dirfd, 
+//GO(dirname, 
+//GO(div, 
+//GO(_dl_addr, 
+//GO(_dl_catch_error, 
+//GO(_dl_catch_exception, 
+//GOW(dl_iterate_phdr, 
+//GO(_dl_mcount_wrapper, 
+//GO(_dl_mcount_wrapper_check, 
+//DATAB(_dl_open_hook, 
+//DATAB(_dl_open_hook2, 
+//GO(_dl_signal_error, 
+//GO(_dl_signal_exception, 
+//GO(_dl_sym, 
+//GO(_dl_vsym, 
+//GOW(dngettext, 
+//GO(dprintf, 
+//GO(__dprintf_chk, 
+//GO(drand48, 
+//GO(drand48_r, 
+//GOW(dup, 
+//GO(__dup2, 
+//GOW(dup2, 
+//GOW(dup3, 
+//GO(__duplocale, 
+//GOW(duplocale, 
+//GO(dysize, 
+//GOW(eaccess, 
+//GO(ecb_crypt, 
+//GO(ecvt, 
+//GOW(ecvt_r, 
+//GO(endaliasent, 
+//GO(endfsent, 
+//GO(endgrent, 
+//GO(endhostent, 
+//GO(__endmntent, 
+//GOW(endmntent, 
+//GO(endnetent, 
+//GO(endnetgrent, 
+//GO(endprotoent, 
+//GO(endpwent, 
+//GO(endrpcent, 
+//GO(endservent, 
+//GO(endsgent, 
+//GO(endspent, 
+//GOW(endttyent, 
+//GO(endusershell, 
+//GOW(endutent, 
+//GO(endutxent, 
+//DATAB(__environ, 
+//GO(envz_add, 
+//GO(envz_entry, 
+//GO(envz_get, 
+//GO(envz_merge, 
+//GO(envz_remove, 
+//GO(envz_strip, 
+//GO(epoll_create, 
+//GO(epoll_create1, 
+//GO(epoll_ctl, 
+//GO(epoll_pwait, 
+//GO(epoll_wait, 
+//GO(erand48, 
+//GOW(erand48_r, 
+//GO(err, 
+//DATAB(errno, 
+//GO(__errno_location, 
+//GOW(error, 
+//GOW(error_at_line, 
+//DATAB(error_message_count, 
+//DATAB(error_one_per_line, 
+//DATAB(error_print_progname, 
+//GO(errx, 
+//GO(ether_aton, 
+//GO(ether_aton_r, 
+//GO(ether_hostton, 
+//GO(ether_line, 
+//GO(ether_ntoa, 
+//GO(ether_ntoa_r, 
+//GO(ether_ntohost, 
+//GOW(euidaccess, 
+//GO(eventfd, 
+//GO(eventfd_read, 
+//GO(eventfd_write, 
+//GO(execl, 
+//GO(execle, 
+//GO(execlp, 
+//GO(execv, 
+//GOW(execve, 
+//GO(execvp, 
+//GOW(execvpe, 
+//GO(_exit, 
+//GO(exit, 
+//GOW(_Exit, 
+//GO(explicit_bzero, 
+//GO(__explicit_bzero_chk, 
+//GO(faccessat, 
+//GOW(fallocate, 
+//GO(fallocate64, 
+//GO(fanotify_init, 
+//GO(fanotify_mark, 
+//GO(fattach, 
+//GO(__fbufsize, 
+//GOW(fchdir, 
+//GO(fchflags, 
+//GOW(fchmod, 
+//GO(fchmodat, 
+//GOW(fchown, 
+//GO(fchownat, 
+//GO(fclose, 
+//GOW(fcloseall, 
+//GOW(__fcntl, 
+//GOW(fcntl, 
+//GOW(fcntl64, 
+//GO(fcvt, 
+//GOW(fcvt_r, 
+//GO(fdatasync, 
+//GO(__fdelt_chk, 
+//GO(__fdelt_warn, 
+//GO(fdetach, 
+//GO(fdopen, 
+//GOW(fdopendir, 
+//GO(__fentry__, 
+//GOW(feof, 
+//GOW(feof_unlocked, 
+//GOW(ferror, 
+//GOW(ferror_unlocked, 
+//GO(fexecve, 
+//GOW(fflush, 
+//GOW(fflush_unlocked, 
+//GO(__ffs, 
+//GO(ffs, 
+//GOW(ffsl, 
+//GO(ffsll, 
+//GOW(fgetc, 
+//GOW(fgetc_unlocked, 
+//GO(fgetgrent, 
+//GOW(fgetgrent_r, 
+//GO(fgetpos, 
+//GO(fgetpos64, 
+//GO(fgetpwent, 
+//GOW(fgetpwent_r, 
+//GOW(fgets, 
+//GO(__fgets_chk, 
+//GO(fgetsgent, 
+//GOW(fgetsgent_r, 
+//GO(fgetspent, 
+//GOW(fgetspent_r, 
+//GOW(fgets_unlocked, 
+//GO(__fgets_unlocked_chk, 
+//GOW(fgetwc, 
+//GOW(fgetwc_unlocked, 
+//GO(fgetws, 
+//GO(__fgetws_chk, 
+//GO(fgetws_unlocked, 
+//GO(__fgetws_unlocked_chk, 
+//GO(fgetxattr, 
+//GOW(fileno, 
+//GOW(fileno_unlocked, 
+//GO(__finite, 
+//GOW(finite, 
+//GO(__finitef, 
+//GOW(finitef, 
+//GO(__finitel, 
+//GOW(finitel, 
+//GO(__flbf, 
+//GO(flistxattr, 
+//GOW(flock, 
+//GOW(flockfile, 
+//GOW(_flushlbf, 
+//GO(fmemopen, 
+//GO(fmemopen, 
+//GO(fmtmsg, 
+//GO(fnmatch, 
+//GO(fopen, 
+//GOW(fopen64, 
+//GO(fopencookie, 
+//GO(__fork, 
+//GOW(fork, 
+//GO(__fortify_fail, 
+//GOW(fpathconf, 
+//GO(__fpending, 
+//GO(fprintf, 
+//GO(__fprintf_chk, 
+//DATA(__fpu_control, 
+//GO(__fpurge, 
+//GO(fputc, 
+//GO(fputc_unlocked, 
+//GOW(fputs, 
+//GOW(fputs_unlocked, 
+//GO(fputwc, 
+//GO(fputwc_unlocked, 
+//GO(fputws, 
+//GO(fputws_unlocked, 
+//GOW(fread, 
+//GO(__freadable, 
+//GO(__fread_chk, 
+//GO(__freading, 
+//GOW(fread_unlocked, 
+//GO(__fread_unlocked_chk, 
+//GO(free, 
+//GO(freeaddrinfo, 
+//GOW(freeifaddrs, 
+//GO(__freelocale, 
+//GOW(freelocale, 
+//GO(fremovexattr, 
+//GO(freopen, 
+//GO(freopen64, 
+//GOW(frexp, 
+//GOW(frexpf, 
+//GOW(frexpl, 
+//GO(fscanf, 
+//GO(fseek, 
+//GOW(fseeko, 
+//GO(__fseeko64, 
+//GOW(fseeko64, 
+//GO(__fsetlocking, 
+//GO(fsetpos, 
+//GO(fsetpos64, 
+//GO(fsetxattr, 
+//GOW(fstatfs, 
+//GOW(fstatfs64, 
+//GOW(fstatvfs, 
+//GOW(fstatvfs64, 
+//GO(fsync, 
+//GOW(ftell, 
+//GOW(ftello, 
+//GO(__ftello64, 
+//GOW(ftello64, 
+//GO(ftime, 
+//GO(ftok, 
+//GOW(ftruncate, 
+//GOW(ftruncate64, 
+//GOW(ftrylockfile, 
+//GOW(fts64_children, 
+//GOW(fts64_close, 
+//GOW(fts64_open, 
+//GOW(fts64_read, 
+//GOW(fts64_set, 
+//GO(fts_children, 
+//GO(fts_close, 
+//GO(fts_open, 
+//GO(fts_read, 
+//GO(fts_set, 
+//GO(ftw, 
+//GOW(ftw64, 
+//GOW(funlockfile, 
+//GO(futimens, 
+//GOW(futimes, 
+//GO(futimesat, 
+//GO(fwide, 
+//GOW(fwprintf, 
+//GO(__fwprintf_chk, 
+//GO(__fwritable, 
+//GOW(fwrite, 
+//GO(fwrite_unlocked, 
+//GO(__fwriting, 
+//GO(fwscanf, 
+//GO(__fxstat, 
+//GO(__fxstat64, 
+//GO(__fxstatat, 
+//GO(__fxstatat64, 
+//GO(__gai_sigqueue, 
+//GO(gai_strerror, 
+//GO(__gconv_get_alias_db, 
+//GO(__gconv_get_cache, 
+//GO(__gconv_get_modules_db, 
+//GO(__gconv_transliterate, 
+//GO(gcvt, 
+//GO(getaddrinfo, 
+//GO(getaliasbyname, 
+//GO(getaliasbyname_r, 
+//GO(getaliasent, 
+//GO(getaliasent_r, 
+//GO(__getauxval, 
+//GOW(getauxval, 
+//GOW(get_avphys_pages, 
+//GOW(getc, 
+//GO(getchar, 
+//GO(getchar_unlocked, 
+//GOW(getcontext, 
+//GOW(getc_unlocked, 
+//GO(get_current_dir_name, 
+//GOW(getcwd, 
+//GO(__getcwd_chk, 
+//GO(getdate, 
+//DATAB(getdate_err, 
+//GOW(getdate_r, 
+//GOW(__getdelim, 
+//GOW(getdelim, 
+//GOW(getdirentries, 
+//GO(getdirentries64, 
+//GO(getdomainname, 
+//GO(__getdomainname_chk, 
+//GOW(getdtablesize, 
+//GOW(getegid, 
+//GO(getentropy, 
+//GO(getenv, 
+//GOW(geteuid, 
+//GO(getfsent, 
+//GO(getfsfile, 
+//GO(getfsspec, 
+//GOW(getgid, 
+//GO(getgrent, 
+//GO(getgrent_r, 
+//GO(getgrgid, 
+//GO(getgrgid_r, 
+//GO(getgrnam, 
+//GO(getgrnam_r, 
+//GO(getgrouplist, 
+//GOW(getgroups, 
+//GO(__getgroups_chk, 
+//GO(gethostbyaddr, 
+//GO(gethostbyaddr_r, 
+//GO(gethostbyname, 
+//GO(gethostbyname2, 
+//GO(gethostbyname2_r, 
+//GO(gethostbyname_r, 
+//GO(gethostent, 
+//GO(gethostent_r, 
+//GO(gethostid, 
+//GOW(gethostname, 
+//GO(__gethostname_chk, 
+//GOW(getifaddrs, 
+//GO(getipv4sourcefilter, 
+//GOW(getitimer, 
+//GO(get_kernel_syms, 
+//GOW(getline, 
+//GO(getloadavg, 
+//GO(getlogin, 
+//GOW(getlogin_r, 
+//GO(__getlogin_r_chk, 
+//GO(getmntent, 
+//GO(__getmntent_r, 
+//GOW(getmntent_r, 
+//GO(getmsg, 
+//GO(get_myaddress, 
+//GO(getnameinfo, 
+//GO(getnetbyaddr, 
+//GO(getnetbyaddr_r, 
+//GO(getnetbyname, 
+//GO(getnetbyname_r, 
+//GO(getnetent, 
+//GO(getnetent_r, 
+//GO(getnetgrent, 
+//GOW(getnetgrent_r, 
+//GO(getnetname, 
+//GOW(get_nprocs, 
+//GOW(get_nprocs_conf, 
+//GO(getopt, 
+//GO(getopt_long, 
+//GO(getopt_long_only, 
+//GO(__getpagesize, 
+//GOW(getpagesize, 
+//GO(getpass, 
+//GOW(getpeername, 
+//GO(__getpgid, 
+//GOW(getpgid, 
+//GO(getpgrp, 
+//GOW(get_phys_pages, 
+//GO(__getpid, 
+//GOW(getpid, 
+//GO(getpmsg, 
+//GOW(getppid, 
+//GOW(getpriority, 
+//GO(getprotobyname, 
+//GO(getprotobyname_r, 
+//GO(getprotobynumber, 
+//GO(getprotobynumber_r, 
+//GO(getprotoent, 
+//GO(getprotoent_r, 
+//GOW(getpt, 
+//GO(getpublickey, 
+//GOW(getpw, 
+//GO(getpwent, 
+//GO(getpwent_r, 
+//GO(getpwnam, 
+//GO(getpwnam_r, 
+//GO(getpwuid, 
+//GO(getpwuid_r, 
+//GO(getrandom, 
+//GO(getresgid, 
+//GO(getresuid, 
+//GO(__getrlimit, 
+//GOW(getrlimit, 
+//GOW(getrlimit64, 
+//GO(getrpcbyname, 
+//GO(getrpcbyname_r, 
+//GO(getrpcbynumber, 
+//GO(getrpcbynumber_r, 
+//GO(getrpcent, 
+//GO(getrpcent_r, 
+//GO(getrpcport, 
+//GOW(getrusage, 
+//GOW(gets, 
+//GO(__gets_chk, 
+//GO(getsecretkey, 
+//GO(getservbyname, 
+//GO(getservbyname_r, 
+//GO(getservbyport, 
+//GO(getservbyport_r, 
+//GO(getservent, 
+//GO(getservent_r, 
+//GO(getsgent, 
+//GO(getsgent_r, 
+//GO(getsgnam, 
+//GO(getsgnam_r, 
+//GO(getsid, 
+//GOW(getsockname, 
+//GOW(getsockopt, 
+//GO(getsourcefilter, 
+//GO(getspent, 
+//GO(getspent_r, 
+//GO(getspnam, 
+//GO(getspnam_r, 
+//GO(getsubopt, 
+//GOW(gettext, 
+//GOW(getttyent, 
+//GOW(getttynam, 
+//GOW(getuid, 
+//GO(getusershell, 
+//GOW(getutent, 
+//GOW(getutent_r, 
+//GOW(getutid, 
+//GOW(getutid_r, 
+//GOW(getutline, 
+//GOW(getutline_r, 
+//GO(getutmp, 
+//GO(getutmpx, 
+//GO(getutxent, 
+//GO(getutxid, 
+//GO(getutxline, 
+//GO(getw, 
+//GOW(getwc, 
+//GO(getwchar, 
+//GO(getwchar_unlocked, 
+//GOW(getwc_unlocked, 
+//GO(getwd, 
+//GO(__getwd_chk, 
+//GO(getxattr, 
+//GO(glob, 
+//GO(glob, 
+//GO(glob64, 
+//GO(glob64, 
+//GO(globfree, 
+//GOW(globfree64, 
+//GOW(glob_pattern_p, 
+//GO(gmtime, 
+//GO(__gmtime_r, 
+//GOW(gmtime_r, 
+//GOW(gnu_dev_major, 
+//GOW(gnu_dev_makedev, 
+//GOW(gnu_dev_minor, 
+//GOW(gnu_get_libc_release, 
+//GOW(gnu_get_libc_version, 
+//GO(grantpt, 
+//GOW(group_member, 
+//GOW(gsignal, 
+//GO(gtty, 
+//GOW(hasmntopt, 
+//GO(hcreate, 
+//GOW(hcreate_r, 
+//GOW(hdestroy, 
+//GOW(hdestroy_r, 
+//DATA(h_errlist, 
+//DATAB(__h_errno, 
+//GO(__h_errno_location, 
+//GO(herror, 
+//GO(host2netname, 
+//GO(hsearch, 
+//GOW(hsearch_r, 
+//GO(hstrerror, 
+//GO(htonl, 
+//GO(htons, 
+//GO(iconv, 
+//GO(iconv_close, 
+//GO(iconv_open, 
+//GO(__idna_from_dns_encoding, 
+//GO(__idna_to_dns_encoding, 
+//GOW(if_freenameindex, 
+//GOW(if_indextoname, 
+//GOW(if_nameindex, 
+//GOW(if_nametoindex, 
+//GOW(imaxabs, 
+//GOW(imaxdiv, 
+//GO(inet6_opt_append, 
+//GO(inet6_opt_find, 
+//GO(inet6_opt_finish, 
+//GO(inet6_opt_get_val, 
+//GO(inet6_opt_init, 
+//GO(inet6_option_alloc, 
+//GO(inet6_option_append, 
+//GO(inet6_option_find, 
+//GO(inet6_option_init, 
+//GO(inet6_option_next, 
+//GO(inet6_option_space, 
+//GO(inet6_opt_next, 
+//GO(inet6_opt_set_val, 
+//GO(inet6_rth_add, 
+//GO(inet6_rth_getaddr, 
+//GO(inet6_rth_init, 
+//GO(inet6_rth_reverse, 
+//GO(inet6_rth_segments, 
+//GO(inet6_rth_space, 
+//GO(__inet6_scopeid_pton, 
+//GOW(inet_addr, 
+//GOW(inet_aton, 
+//GO(__inet_aton_exact, 
+//GO(inet_lnaof, 
+//GOW(inet_makeaddr, 
+//GO(inet_netof, 
+//GO(inet_network, 
+//GO(inet_nsap_addr, 
+//GO(inet_nsap_ntoa, 
+//GO(inet_ntoa, 
+//GO(inet_ntop, 
+//GOW(inet_pton, 
+//GO(__inet_pton_length, 
+//GO(initgroups, 
+//GO(init_module, 
+//GOW(initstate, 
+//GOW(initstate_r, 
+//GO(innetgr, 
+//GO(inotify_add_watch, 
+//GO(inotify_init, 
+//GO(inotify_init1, 
+//GO(inotify_rm_watch, 
+//GO(insque, 
+//GO(__internal_endnetgrent, 
+//GO(__internal_getnetgrent_r, 
+//GO(__internal_setnetgrent, 
+//DATA(_IO_2_1_stderr_, 
+//DATA(_IO_2_1_stdin_, 
+//DATA(_IO_2_1_stdout_, 
+//GO(_IO_adjust_column, 
+//GO(_IO_adjust_wcolumn, 
+//GOW(ioctl, 
+//GO(_IO_default_doallocate, 
+//GO(_IO_default_finish, 
+//GO(_IO_default_pbackfail, 
+//GO(_IO_default_uflow, 
+//GO(_IO_default_xsgetn, 
+//GO(_IO_default_xsputn, 
+//GO(_IO_doallocbuf, 
+//GO(_IO_do_write, 
+//GO(_IO_enable_locks, 
+//GO(_IO_fclose, 
+//GO(_IO_fdopen, 
+//GO(_IO_feof, 
+//GO(_IO_ferror, 
+//GO(_IO_fflush, 
+//GO(_IO_fgetpos, 
+//GO(_IO_fgetpos64, 
+//GO(_IO_fgets, 
+//GO(_IO_file_attach, 
+//GO(_IO_file_close, 
+//GO(_IO_file_close_it, 
+//GO(_IO_file_doallocate, 
+//GO(_IO_file_finish, 
+//GO(_IO_file_fopen, 
+//GO(_IO_file_init, 
+//DATA(_IO_file_jumps, 
+//GO(_IO_file_open, 
+//GO(_IO_file_overflow, 
+//GO(_IO_file_read, 
+//GO(_IO_file_seek, 
+//GO(_IO_file_seekoff, 
+//GO(_IO_file_setbuf, 
+//GO(_IO_file_stat, 
+//GO(_IO_file_sync, 
+//GO(_IO_file_underflow, 
+//GO(_IO_file_write, 
+//GO(_IO_file_xsputn, 
+//GO(_IO_flockfile, 
+//GO(_IO_flush_all, 
+//GO(_IO_flush_all_linebuffered, 
+//GO(_IO_fopen, 
+//GOW(_IO_fprintf, 
+//GO(_IO_fputs, 
+//GO(_IO_fread, 
+//GO(_IO_free_backup_area, 
+//GO(_IO_free_wbackup_area, 
+//GO(_IO_fsetpos, 
+//GO(_IO_fsetpos64, 
+//GO(_IO_ftell, 
+//GO(_IO_ftrylockfile, 
+//GO(_IO_funlockfile, 
+//GO(_IO_fwrite, 
+//GO(_IO_getc, 
+//GO(_IO_getline, 
+//GO(_IO_getline_info, 
+//GO(_IO_gets, 
+//GO(_IO_init, 
+//GO(_IO_init_marker, 
+//GO(_IO_init_wmarker, 
+//GO(_IO_iter_begin, 
+//GO(_IO_iter_end, 
+//GO(_IO_iter_file, 
+//GO(_IO_iter_next, 
+//GO(_IO_least_wmarker, 
+//GO(_IO_link_in, 
+//DATA(_IO_list_all, 
+//GO(_IO_list_lock, 
+//GO(_IO_list_resetlock, 
+//GO(_IO_list_unlock, 
+//GO(_IO_marker_delta, 
+//GO(_IO_marker_difference, 
+//GO(_IO_padn, 
+//GO(_IO_peekc_locked, 
+//GO(ioperm, 
+//GO(iopl, 
+//GO(_IO_popen, 
+//GO(_IO_printf, 
+//GO(_IO_proc_close, 
+//GO(_IO_proc_open, 
+//GO(_IO_putc, 
+//GO(_IO_puts, 
+//GO(_IO_remove_marker, 
+//GO(_IO_seekmark, 
+//GO(_IO_seekoff, 
+//GO(_IO_seekpos, 
+//GO(_IO_seekwmark, 
+//GO(_IO_setb, 
+//GO(_IO_setbuffer, 
+//GO(_IO_setvbuf, 
+//GO(_IO_sgetn, 
+//GO(_IO_sprintf, 
+//GO(_IO_sputbackc, 
+//GO(_IO_sputbackwc, 
+//GO(_IO_sscanf, 
+//GO(_IO_str_init_readonly, 
+//GO(_IO_str_init_static, 
+//GO(_IO_str_overflow, 
+//GO(_IO_str_pbackfail, 
+//GO(_IO_str_seekoff, 
+//GO(_IO_str_underflow, 
+//GO(_IO_sungetc, 
+//GO(_IO_sungetwc, 
+//GO(_IO_switch_to_get_mode, 
+//GO(_IO_switch_to_main_wget_area, 
+//GO(_IO_switch_to_wbackup_area, 
+//GO(_IO_switch_to_wget_mode, 
+//GO(_IO_ungetc, 
+//GO(_IO_un_link, 
+//GO(_IO_unsave_markers, 
+//GO(_IO_unsave_wmarkers, 
+//GO(_IO_vfprintf, 
+//GO(_IO_vfscanf, 
+//GO(_IO_vsprintf, 
+//GO(_IO_wdefault_doallocate, 
+//GO(_IO_wdefault_finish, 
+//GO(_IO_wdefault_pbackfail, 
+//GO(_IO_wdefault_uflow, 
+//GO(_IO_wdefault_xsgetn, 
+//GO(_IO_wdefault_xsputn, 
+//GO(_IO_wdoallocbuf, 
+//GO(_IO_wdo_write, 
+//DATA(_IO_wfile_jumps, 
+//GO(_IO_wfile_overflow, 
+//GO(_IO_wfile_seekoff, 
+//GO(_IO_wfile_sync, 
+//GO(_IO_wfile_underflow, 
+//GO(_IO_wfile_xsputn, 
+//GO(_IO_wmarker_delta, 
+//GO(_IO_wsetb, 
+//GO(iruserok, 
+//GO(iruserok_af, 
+//GO(isalnum, 
+//GO(__isalnum_l, 
+//GOW(isalnum_l, 
+//GO(isalpha, 
+//GO(__isalpha_l, 
+//GOW(isalpha_l, 
+//GO(isascii, 
+//GOW(__isascii_l, 
+//GO(isastream, 
+//GOW(isatty, 
+//GO(isblank, 
+//GO(__isblank_l, 
+//GOW(isblank_l, 
+//GO(iscntrl, 
+//GO(__iscntrl_l, 
+//GOW(iscntrl_l, 
+//GO(__isctype, 
+//GOW(isctype, 
+//GO(isdigit, 
+//GO(__isdigit_l, 
+//GOW(isdigit_l, 
+//GO(isfdtype, 
+//GO(isgraph, 
+//GO(__isgraph_l, 
+//GOW(isgraph_l, 
+//GO(__isinf, 
+//GOW(isinf, 
+//GO(__isinff, 
+//GOW(isinff, 
+//GO(__isinfl, 
+//GOW(isinfl, 
+//GO(islower, 
+//GO(__islower_l, 
+//GOW(islower_l, 
+//GO(__isnan, 
+//GOW(isnan, 
+//GO(__isnanf, 
+//GOW(isnanf, 
+//GO(__isnanl, 
+//GOW(isnanl, 
+//GO(__isoc99_fscanf, 
+//GO(__isoc99_fwscanf, 
+//GO(__isoc99_scanf, 
+//GO(__isoc99_sscanf, 
+//GO(__isoc99_swscanf, 
+//GO(__isoc99_vfscanf, 
+//GO(__isoc99_vfwscanf, 
+//GO(__isoc99_vscanf, 
+//GO(__isoc99_vsscanf, 
+//GO(__isoc99_vswscanf, 
+//GO(__isoc99_vwscanf, 
+//GO(__isoc99_wscanf, 
+//GO(isprint, 
+//GO(__isprint_l, 
+//GOW(isprint_l, 
+//GO(ispunct, 
+//GO(__ispunct_l, 
+//GOW(ispunct_l, 
+//GO(isspace, 
+//GO(__isspace_l, 
+//GOW(isspace_l, 
+//GO(isupper, 
+//GO(__isupper_l, 
+//GOW(isupper_l, 
+//GOW(iswalnum, 
+//GO(__iswalnum_l, 
+//GOW(iswalnum_l, 
+//GOW(iswalpha, 
+//GO(__iswalpha_l, 
+//GOW(iswalpha_l, 
+//GOW(iswblank, 
+//GO(__iswblank_l, 
+//GOW(iswblank_l, 
+//GOW(iswcntrl, 
+//GO(__iswcntrl_l, 
+//GOW(iswcntrl_l, 
+//GO(__iswctype, 
+//GOW(iswctype, 
+//GO(__iswctype_l, 
+//GOW(iswctype_l, 
+//GOW(iswdigit, 
+//GO(__iswdigit_l, 
+//GOW(iswdigit_l, 
+//GOW(iswgraph, 
+//GO(__iswgraph_l, 
+//GOW(iswgraph_l, 
+//GOW(iswlower, 
+//GO(__iswlower_l, 
+//GOW(iswlower_l, 
+//GOW(iswprint, 
+//GO(__iswprint_l, 
+//GOW(iswprint_l, 
+//GOW(iswpunct, 
+//GO(__iswpunct_l, 
+//GOW(iswpunct_l, 
+//GOW(iswspace, 
+//GO(__iswspace_l, 
+//GOW(iswspace_l, 
+//GOW(iswupper, 
+//GO(__iswupper_l, 
+//GOW(iswupper_l, 
+//GOW(iswxdigit, 
+//GO(__iswxdigit_l, 
+//GOW(iswxdigit_l, 
+//GO(isxdigit, 
+//GO(__isxdigit_l, 
+//GOW(isxdigit_l, 
+//GO(__ivaliduser, 
+//GO(jrand48, 
+//GOW(jrand48_r, 
+//GO(key_decryptsession, 
+//GO(key_decryptsession_pk, 
+//DATAB(__key_decryptsession_pk_LOCAL, 
+//GO(key_encryptsession, 
+//GO(key_encryptsession_pk, 
+//DATAB(__key_encryptsession_pk_LOCAL, 
+//GO(key_gendes, 
+//DATAB(__key_gendes_LOCAL, 
+//GO(key_get_conv, 
+//GO(key_secretkey_is_set, 
+//GO(key_setnet, 
+//GO(key_setsecret, 
+//GOW(kill, 
+//GO(killpg, 
+//GO(klogctl, 
+//GO(l64a, 
+//GO(labs, 
+//GO(lchmod, 
+//GOW(lchown, 
+//GOW(lckpwdf, 
+//GO(lcong48, 
+//GOW(lcong48_r, 
+//GOW(ldexp, 
+//GOW(ldexpf, 
+//GOW(ldexpl, 
+//GO(ldiv, 
+//GO(lfind, 
+//GO(lgetxattr, 
+//GO(__libc_alloca_cutoff, 
+//GO(__libc_allocate_once_slow, 
+//GO(__libc_allocate_rtsig, 
+//GO(__libc_allocate_rtsig_private, 
+//GO(__libc_alloc_buffer_alloc_array, 
+//GO(__libc_alloc_buffer_allocate, 
+//GO(__libc_alloc_buffer_copy_bytes, 
+//GO(__libc_alloc_buffer_copy_string, 
+//GO(__libc_alloc_buffer_create_failure, 
+//GO(__libc_calloc, 
+//GO(__libc_clntudp_bufcreate, 
+//GO(__libc_current_sigrtmax, 
+//GO(__libc_current_sigrtmax_private, 
+//GO(__libc_current_sigrtmin, 
+//GO(__libc_current_sigrtmin_private, 
+//GO(__libc_dlclose, 
+//GO(__libc_dlopen_mode, 
+//GO(__libc_dlsym, 
+//GO(__libc_dlvsym, 
+//GO(__libc_dynarray_at_failure, 
+//GO(__libc_dynarray_emplace_enlarge, 
+//GO(__libc_dynarray_finalize, 
+//GO(__libc_dynarray_resize, 
+//GO(__libc_dynarray_resize_clear, 
+//GO(__libc_fatal, 
+//GO(__libc_fcntl64, 
+//GO(__libc_fork, 
+//GO(__libc_free, 
+//GO(__libc_freeres, 
+//GO(__libc_ifunc_impl_list, 
+//GO(__libc_init_first, 
+//GO(__libc_longjmp, 
+//GO(__libc_mallinfo, 
+//GO(__libc_malloc, 
+//GO(__libc_mallopt, 
+//GO(__libc_memalign, 
+//GO(__libc_msgrcv, 
+//GO(__libc_msgsnd, 
+//GO(__libc_pread, 
+//GO(__libc_pthread_init, 
+//GO(__libc_pvalloc, 
+//GO(__libc_pwrite, 
+//GO(__libc_readline_unlocked, 
+//GO(__libc_realloc, 
+//GO(__libc_reallocarray, 
+//GO(__libc_rpc_getport, 
+//GO(__libc_sa_len, 
+//GO(__libc_scratch_buffer_grow, 
+//GO(__libc_scratch_buffer_grow_preserve, 
+//GO(__libc_scratch_buffer_set_array_size, 
+//GOW(__libc_secure_getenv, 
+//GO(__libc_siglongjmp, 
+//GO(__libc_start_main, 
+//GO(__libc_system, 
+//GO(__libc_thread_freeres, 
+//GO(__libc_valloc, 
+//GO(__libc_vfork, 
+//GOW(link, 
+//GO(linkat, 
+//GOW(listen, 
+//GO(listxattr, 
+//GO(llabs, 
+//GO(lldiv, 
+//GO(llistxattr, 
+//GO(llseek, 
+//DATAB(loc1, 
+//DATAB(loc2, 
+//GO(localeconv, 
+//GO(localtime, 
+//GOW(localtime_r, 
+//GO(lockf, 
+//GOW(lockf64, 
+//DATAB(locs, 
+//GOW(_longjmp, 
+//GOW(longjmp, 
+//GO(__longjmp_chk, 
+//GO(lrand48, 
+//GO(lrand48_r, 
+//GO(lremovexattr, 
+//GO(lsearch, 
+//GO(__lseek, 
+//GOW(lseek, 
+//GOW(lseek64, 
+//GO(lsetxattr, 
+//GO(lutimes, 
+//GO(__lxstat, 
+//GO(__lxstat64, 
+//GO(__madvise, 
+//GOW(madvise, 
+//GOW(makecontext, 
+//GOW(mallinfo, 
+//GO(malloc, 
+//GO(malloc_get_state, 
+//GOW(malloc_info, 
+//GO(malloc_set_state, 
+//GOW(malloc_stats, 
+//GOW(malloc_trim, 
+//GOW(malloc_usable_size, 
+//GOW(mallopt, 
+//DATAB(mallwatch, 
+//GO(mblen, 
+//GO(__mbrlen, 
+//GOW(mbrlen, 
+//GO(mbrtoc16, 
+//GOW(mbrtoc32, 
+//GO(__mbrtowc, 
+//GOW(mbrtowc, 
+//GOW(mbsinit, 
+//GOW(mbsnrtowcs, 
+//GO(__mbsnrtowcs_chk, 
+//GOW(mbsrtowcs, 
+//GO(__mbsrtowcs_chk, 
+//GO(mbstowcs, 
+//GO(__mbstowcs_chk, 
+//GO(mbtowc, 
+//GO(mcheck, 
+//GO(mcheck_check_all, 
+//GO(mcheck_pedantic, 
+//GO(_mcleanup, 
+//GO(_mcount, 
+//GOW(mcount, 
+//GOW(memalign, 
+//GOW(memccpy, 
+//GO(memcpy, 
+//GO(memfd_create, 
+//GO(memfrob, 
+//GOW(memmem, 
+//GO(__mempcpy_small, 
+//GO(__merge_grp, 
+//GO(mincore, 
+//GOW(mkdir, 
+//GO(mkdirat, 
+//GO(mkdtemp, 
+//GO(mkfifo, 
+//GO(mkfifoat, 
+//GO(mkostemp, 
+//GOW(mkostemp64, 
+//GO(mkostemps, 
+//GOW(mkostemps64, 
+//GO(mkstemp, 
+//GOW(mkstemp64, 
+//GO(mkstemps, 
+//GOW(mkstemps64, 
+//GO(__mktemp, 
+//GOW(mktemp, 
+//GO(mktime, 
+//GO(mlock, 
+//GO(mlock2, 
+//GO(mlockall, 
+//GO(__mmap, 
+//GOW(mmap, 
+//GOW(mmap64, 
+//GOW(modf, 
+//GOW(modff, 
+//GOW(modfl, 
+//GOW(modify_ldt, 
+//GOW(moncontrol, 
+//GO(__monstartup, 
+//GOW(monstartup, 
+//DATA(__morecore, 
+//GOW(mount, 
+//GO(mprobe, 
+//GO(__mprotect, 
+//GOW(mprotect, 
+//GO(mrand48, 
+//GO(mrand48_r, 
+//GOW(mremap, 
+//GO(msgctl, 
+//GO(msgget, 
+//GOW(msgrcv, 
+//GOW(msgsnd, 
+//GO(msync, 
+//GO(mtrace, 
+//GO(munlock, 
+//GO(munlockall, 
+//GO(__munmap, 
+//GOW(munmap, 
+//GO(muntrace, 
+GO(name_to_handle_at, iFipppi)
+//GO(__nanosleep, 
+//GOW(nanosleep, 
+//GO(__nanosleep_nocancel, 
+//GO(__netlink_assert_response, 
+//GO(netname2host, 
+//GO(netname2user, 
+//GO(__newlocale, 
+//GOW(newlocale, 
+//GO(nfsservctl, 
+//GO(nftw, 
+//GO(nftw, 
+//GO(nftw64, 
+//GO(nftw64, 
+//GOW(ngettext, 
+//GO(nice, 
+//DATAB(_nl_domain_bindings, 
+//GO(nl_langinfo, 
+//GO(__nl_langinfo_l, 
+//GOW(nl_langinfo_l, 
+//DATAB(_nl_msg_cat_cntr, 
+//GO(nrand48, 
+//GOW(nrand48_r, 
+//GO(__nss_configure_lookup, 
+//GO(__nss_database_lookup, 
+//GO(__nss_disable_nscd, 
+//GO(_nss_files_parse_grent, 
+//GO(_nss_files_parse_pwent, 
+//GO(_nss_files_parse_sgent, 
+//GO(_nss_files_parse_spent, 
+//GO(__nss_group_lookup, 
+//GO(__nss_group_lookup2, 
+//GO(__nss_hash, 
+//GO(__nss_hostname_digits_dots, 
+//GO(__nss_hosts_lookup, 
+//GO(__nss_hosts_lookup2, 
+//GO(__nss_lookup, 
+//GO(__nss_lookup_function, 
+//GO(__nss_next, 
+//GO(__nss_next2, 
+//GO(__nss_passwd_lookup, 
+//GO(__nss_passwd_lookup2, 
+//GO(__nss_services_lookup2, 
+//GOW(ntohl, 
+//GOW(ntohs, 
+//GOW(ntp_adjtime, 
+//GO(ntp_gettime, 
+//GO(ntp_gettimex, 
+//DATAB(_null_auth, 
+//DATAB(_obstack, 
+//GO(_obstack_allocated_p, 
+//DATA(obstack_alloc_failed_handler, 
+//GO(_obstack_begin, 
+//GO(_obstack_begin_1, 
+//DATA(obstack_exit_failure, 
+//GO(_obstack_free, 
+//GO(obstack_free, 
+//GO(_obstack_memory_used, 
+//GO(_obstack_newchunk, 
+//GOW(obstack_printf, 
+//GO(__obstack_printf_chk, 
+//GOW(obstack_vprintf, 
+//GO(__obstack_vprintf_chk, 
+//GOW(on_exit, 
+//GOW(__open, 
+//GOW(open, 
+//GO(__open_2, 
+//GOW(__open64, 
+//GOW(open64, 
+//GO(__open64_2, 
+//GO(__open64_nocancel, 
+//GOW(openat, 
+//GO(__openat_2, 
+//GOW(openat64, 
+//GO(__openat64_2, 
+//GO(open_by_handle_at, 
+//GO(__open_catalog, 
+//GOW(opendir, 
+//GO(openlog, 
+//GOW(open_memstream, 
+//GO(__open_nocancel, 
+//GO(open_wmemstream, 
+//DATAB(optarg, 
+//DATA(opterr, 
+//DATA(optind, 
+//DATA(optopt, 
+//GO(__overflow, 
+//GO(parse_printf_format, 
+//GO(passwd2des, 
+//GOW(pathconf, 
+//GOW(pause, 
+//GO(__pause_nocancel, 
+//GO(pclose, 
+//GO(perror, 
+//GOW(personality, 
+//GO(__pipe, 
+//GOW(pipe, 
+//GOW(pipe2, 
+//GO(pivot_root, 
+//GO(pkey_alloc, 
+//GO(pkey_free, 
+//GO(pkey_get, 
+//GO(pkey_mprotect, 
+//GO(pkey_set, 
+//GO(pmap_getmaps, 
+//GO(pmap_getport, 
+//GO(pmap_rmtcall, 
+//GO(pmap_set, 
+//GO(pmap_unset, 
+//GO(__poll, 
+//GOW(poll, 
+//GO(__poll_chk, 
+//GO(popen, 
+//GO(posix_fadvise, 
+//GOW(posix_fadvise64, 
+//GO(posix_fallocate, 
+//GO(posix_fallocate64, 
+//GO(__posix_getopt, 
+//GO(posix_madvise, 
+//GOW(posix_memalign, 
+//GOW(posix_openpt, 
+//GO(posix_spawn, 
+//GO(posix_spawn, 
+//GO(posix_spawnattr_destroy, 
+//GO(posix_spawnattr_getflags, 
+//GO(posix_spawnattr_getpgroup, 
+//GO(posix_spawnattr_getschedparam, 
+//GO(posix_spawnattr_getschedpolicy, 
+//GO(posix_spawnattr_getsigdefault, 
+//GO(posix_spawnattr_getsigmask, 
+//GO(posix_spawnattr_init, 
+//GO(posix_spawnattr_setflags, 
+//GO(posix_spawnattr_setpgroup, 
+//GO(posix_spawnattr_setschedparam, 
+//GO(posix_spawnattr_setschedpolicy, 
+//GO(posix_spawnattr_setsigdefault, 
+//GO(posix_spawnattr_setsigmask, 
+//GO(posix_spawn_file_actions_addclose, 
+//GO(posix_spawn_file_actions_adddup2, 
+//GO(posix_spawn_file_actions_addopen, 
+//GO(posix_spawn_file_actions_destroy, 
+//GO(posix_spawn_file_actions_init, 
+//GO(posix_spawnp, 
+//GO(posix_spawnp, 
+//GO(ppoll, 
+//GO(__ppoll_chk, 
+//GOW(prctl, 
+//GOW(pread, 
+//GOW(__pread64, 
+//GOW(pread64, 
+//GO(__pread64_chk, 
+//GO(__pread_chk, 
+//GO(preadv, 
+//GO(preadv2, 
+//GO(preadv64, 
+//GO(preadv64v2, 
+//GO(printf, 
+//GO(__printf_chk, 
+//GO(__printf_fp, 
+//GO(printf_size, 
+//GO(printf_size_info, 
+//GO(prlimit, 
+//GOW(prlimit64, 
+//GO(process_vm_readv, 
+//GO(process_vm_writev, 
+//GOW(profil, 
+//GO(__profile_frequency, 
+//DATA(__progname, 
+//DATA(__progname_full, 
+//GOW(pselect, 
+//GO(psiginfo, 
+//GO(psignal, 
+//GO(pthread_attr_destroy, 
+//GO(pthread_attr_getdetachstate, 
+//GO(pthread_attr_getinheritsched, 
+//GO(pthread_attr_getschedparam, 
+//GO(pthread_attr_getschedpolicy, 
+//GO(pthread_attr_getscope, 
+//GO(pthread_attr_init, 
+//GO(pthread_attr_setdetachstate, 
+//GO(pthread_attr_setinheritsched, 
+//GO(pthread_attr_setschedparam, 
+//GO(pthread_attr_setschedpolicy, 
+//GO(pthread_attr_setscope, 
+//GO(pthread_condattr_destroy, 
+//GO(pthread_condattr_init, 
+//GO(pthread_cond_broadcast, 
+//GO(pthread_cond_broadcast, 
+//GO(pthread_cond_destroy, 
+//GO(pthread_cond_destroy, 
+//GO(pthread_cond_init, 
+//GO(pthread_cond_init, 
+//GO(pthread_cond_signal, 
+//GO(pthread_cond_signal, 
+//GO(pthread_cond_timedwait, 
+//GO(pthread_cond_timedwait, 
+//GO(pthread_cond_wait, 
+//GO(pthread_cond_wait, 
+//GO(pthread_equal, 
+//GO(pthread_exit, 
+//GO(pthread_getschedparam, 
+//GO(pthread_mutex_destroy, 
+//GO(pthread_mutex_init, 
+//GO(pthread_mutex_lock, 
+//GO(pthread_mutex_unlock, 
+//GO(pthread_self, 
+//GO(pthread_setcancelstate, 
+//GO(pthread_setcanceltype, 
+//GO(pthread_setschedparam, 
+//GO(ptrace, 
+//GO(ptsname, 
+//GOW(ptsname_r, 
+//GO(__ptsname_r_chk, 
+//GOW(putc, 
+//GO(putchar, 
+//GO(putchar_unlocked, 
+//GOW(putc_unlocked, 
+//GO(putenv, 
+//GO(putgrent, 
+//GO(putmsg, 
+//GO(putpmsg, 
+//GO(putpwent, 
+//GOW(puts, 
+//GO(putsgent, 
+//GO(putspent, 
+//GOW(pututline, 
+//GO(pututxline, 
+//GO(putw, 
+//GO(putwc, 
+//GO(putwchar, 
+//GO(putwchar_unlocked, 
+//GO(putwc_unlocked, 
+//GOW(pvalloc, 
+//GOW(pwrite, 
+//GOW(__pwrite64, 
+//GOW(pwrite64, 
+//GO(pwritev, 
+//GO(pwritev2, 
+//GO(pwritev64, 
+//GO(pwritev64v2, 
+//GO(qecvt, 
+//GOW(qecvt_r, 
+//GO(qfcvt, 
+//GOW(qfcvt_r, 
+//GO(qgcvt, 
+//GO(qsort, 
+//GOW(qsort_r, 
+//GO(query_module, 
+//GO(quick_exit, 
+//GO(quick_exit, 
+//GO(quotactl, 
+//GO(raise, 
+//GO(rand, 
+//GOW(random, 
+//GOW(random_r, 
+//GO(rand_r, 
+//GO(rcmd, 
+//GO(rcmd_af, 
+//DATAB(__rcmd_errstr, 
+//GO(__read, 
+//GO(read, 
+//GOW(readahead, 
+//GO(__read_chk, 
+//GOW(readdir, 
+//GOW(readdir64, 
+//GOW(readdir64_r, 
+//GOW(readdir_r, 
+//GOW(readlink, 
+//GO(readlinkat, 
+//GO(__readlinkat_chk, 
+//GO(__readlink_chk, 
+//GO(__read_nocancel, 
+//GOW(readv, 
+//GO(realloc, 
+//GOW(reallocarray, 
+//GO(realpath, 
+//GO(realpath, 
+//GO(__realpath_chk, 
+//GO(reboot, 
+//GOW(re_comp, 
+//GOW(re_compile_fastmap, 
+//GOW(re_compile_pattern, 
+//GOW(__recv, 
+//GOW(recv, 
+//GO(__recv_chk, 
+//GOW(recvfrom, 
+//GO(__recvfrom_chk, 
+//GO(recvmmsg, 
+//GOW(recvmsg, 
+//GOW(re_exec, 
+//GOW(regcomp, 
+//GOW(regerror, 
+//GO(regexec, 
+//GO(regexec, 
+//GOW(regfree, 
+//GO(__register_atfork, 
+//GOW(register_printf_function, 
+//GOW(register_printf_modifier, 
+//GOW(register_printf_specifier, 
+//GOW(register_printf_type, 
+//GO(registerrpc, 
+//GOW(remap_file_pages, 
+//GOW(re_match, 
+//GOW(re_match_2, 
+//DATA(re_max_failures, 
+//GO(remove, 
+//GO(removexattr, 
+//GO(remque, 
+//GO(rename, 
+//GOW(renameat, 
+//GOW(renameat2, 
+//DATAB(_res, 
+//GOW(re_search, 
+//GOW(re_search_2, 
+//GOW(re_set_registers, 
+//GOW(re_set_syntax, 
+//DATAB(_res_hconf, 
+//GO(__res_iclose, 
+//GO(__res_init, 
+//GO(__res_nclose, 
+//GO(__res_ninit, 
+//GO(__resolv_context_get, 
+//GO(__resolv_context_get_override, 
+//GO(__resolv_context_get_preinit, 
+//GO(__resolv_context_put, 
+//DATA(__resp, 
+//GO(__res_randomid, 
+//GO(__res_state, 
+//DATAB(re_syntax_options, 
+//GOW(revoke, 
+//GO(rewind, 
+//GOW(rewinddir, 
+//GO(rexec, 
+//GO(rexec_af, 
+//DATAB(rexecoptions, 
+//GOW(rmdir, 
+//DATAB(rpc_createerr, 
+//GO(_rpc_dtablesize, 
+//GO(__rpc_thread_createerr, 
+//GO(__rpc_thread_svc_fdset, 
+//GO(__rpc_thread_svc_max_pollfd, 
+//GO(__rpc_thread_svc_pollfd, 
+//GO(rpmatch, 
+//GO(rresvport, 
+//GO(rresvport_af, 
+//GO(rtime, 
+//GO(ruserok, 
+//GO(ruserok_af, 
+//GO(ruserpass, 
+//GO(__sbrk, 
+//GOW(sbrk, 
+//GOW(scalbn, 
+//GOW(scalbnf, 
+//GOW(scalbnl, 
+//GOW(scandir, 
+//GOW(scandir64, 
+//GOW(scandirat, 
+//GO(scandirat64, 
+//GO(scanf, 
+//GO(__sched_cpualloc, 
+//GO(__sched_cpufree, 
+//GO(sched_getaffinity, 
+//GO(sched_getaffinity, 
+//GO(sched_getcpu, 
+//GO(__sched_getparam, 
+//GOW(sched_getparam, 
+//GO(__sched_get_priority_max, 
+//GOW(sched_get_priority_max, 
+//GO(__sched_get_priority_min, 
+//GOW(sched_get_priority_min, 
+//GO(__sched_getscheduler, 
+//GOW(sched_getscheduler, 
+//GOW(sched_rr_get_interval, 
+//GO(sched_setaffinity, 
+//GO(sched_setaffinity, 
+//GOW(sched_setparam, 
+//GO(__sched_setscheduler, 
+//GOW(sched_setscheduler, 
+//GO(__sched_yield, 
+//GOW(sched_yield, 
+//GOW(__secure_getenv, 
+//GOW(secure_getenv, 
+//GO(seed48, 
+//GOW(seed48_r, 
+//GO(seekdir, 
+//GO(__select, 
+//GOW(select, 
+//GO(semctl, 
+//GO(semget, 
+//GO(semop, 
+//GO(semtimedop, 
+//GO(__send, 
+//GOW(send, 
+//GO(sendfile, 
+//GOW(sendfile64, 
+//GO(__sendmmsg, 
+//GOW(sendmmsg, 
+//GOW(sendmsg, 
+//GOW(sendto, 
+//GO(setaliasent, 
+//GO(setbuf, 
+//GOW(setbuffer, 
+//GOW(setcontext, 
+//GO(setdomainname, 
+//GO(setegid, 
+//GOW(setenv, 
+//GO(_seterr_reply, 
+//GO(seteuid, 
+//GO(setfsent, 
+//GO(setfsgid, 
+//GO(setfsuid, 
+//GOW(setgid, 
+//GO(setgrent, 
+//GO(setgroups, 
+//GO(sethostent, 
+//GO(sethostid, 
+//GO(sethostname, 
+//GO(setipv4sourcefilter, 
+//GOW(setitimer, 
+//GO(_setjmp, 
+//GO(setjmp, 
+//GO(setlinebuf, 
+//GO(setlocale, 
+//GO(setlogin, 
+//GO(setlogmask, 
+//GO(__setmntent, 
+//GOW(setmntent, 
+//GO(setnetent, 
+//GO(setnetgrent, 
+//GO(setns, 
+//GO(__setpgid, 
+//GOW(setpgid, 
+//GO(setpgrp, 
+//GOW(setpriority, 
+//GO(setprotoent, 
+//GO(setpwent, 
+//GOW(setregid, 
+//GOW(setresgid, 
+//GOW(setresuid, 
+//GOW(setreuid, 
+//GOW(setrlimit, 
+//GOW(setrlimit64, 
+//GO(setrpcent, 
+//GO(setservent, 
+//GO(setsgent, 
+//GOW(setsid, 
+//GOW(setsockopt, 
+//GO(setsourcefilter, 
+//GO(setspent, 
+//GOW(setstate, 
+//GOW(setstate_r, 
+//GOW(settimeofday, 
+//GOW(setttyent, 
+//GOW(setuid, 
+//GO(setusershell, 
+//GOW(setutent, 
+//GO(setutxent, 
+//GOW(setvbuf, 
+//GO(setxattr, 
+//GO(sgetsgent, 
+//GOW(sgetsgent_r, 
+//GO(sgetspent, 
+//GOW(sgetspent_r, 
+//GO(shmat, 
+//GO(shmctl, 
+//GO(shmdt, 
+//GO(shmget, 
+//GOW(shutdown, 
+//GOW(__sigaction, 
+//GOW(sigaction, 
+//GO(__sigaddset, 
+//GO(sigaddset, 
+//GOW(sigaltstack, 
+//GO(sigandset, 
+//GOW(sigblock, 
+//GO(__sigdelset, 
+//GO(sigdelset, 
+//GO(sigemptyset, 
+//GO(sigfillset, 
+//GO(siggetmask, 
+//GO(sighold, 
+//GO(sigignore, 
+//GO(siginterrupt, 
+//GO(sigisemptyset, 
+//GO(__sigismember, 
+//GO(sigismember, 
+//GOW(siglongjmp, 
+//GOW(signal, 
+//GO(signalfd, 
+//GO(__signbit, 
+//GO(__signbitf, 
+//GO(__signbitl, 
+//GO(sigorset, 
+//GO(__sigpause, 
+//GOW(sigpause, 
+//GO(sigpending, 
+//GOW(sigprocmask, 
+//GOW(sigqueue, 
+//GO(sigrelse, 
+//GOW(sigreturn, 
+//GO(sigset, 
+//GO(__sigsetjmp, 
+//GOW(sigsetmask, 
+//GO(sigstack, 
+//GO(__sigsuspend, 
+//GOW(sigsuspend, 
+//GO(__sigtimedwait, 
+//GOW(sigtimedwait, 
+//GO(sigvec, 
+//GOW(sigwait, 
+//GOW(sigwaitinfo, 
+//GOW(sleep, 
+//GO(__snprintf, 
+//GOW(snprintf, 
+//GO(__snprintf_chk, 
+//GO(sockatmark, 
+//GO(__socket, 
+//GOW(socket, 
+//GOW(socketpair, 
+//GO(splice, 
+//GO(sprintf, 
+//GO(__sprintf_chk, 
+//GOW(sprofil, 
+//GOW(srand, 
+//GO(srand48, 
+//GOW(srand48_r, 
+//GOW(srandom, 
+//GOW(srandom_r, 
+//GO(sscanf, 
+//GOW(ssignal, 
+//GO(sstk, 
+GOM(__stack_chk_fail, vFE)
+//GO(__statfs, 
+//GOW(statfs, 
+//GOW(statfs64, 
+//GOW(statvfs, 
+//GOW(statvfs64, 
+//GO(statx, 
+//DATA(stderr, 
+//DATA(stdin, 
+//DATA(stdout, 
+//GOW(step, 
+//GO(stime, 
+//GO(__stpcpy_chk, 
+//GO(__stpcpy_small, 
+//GO(__stpncpy_chk, 
+//GO(__strcasestr, 
+//GOW(strcasestr, 
+//GO(__strcat_chk, 
+//GO(strcoll, 
+//GO(__strcoll_l, 
+//GOW(strcoll_l, 
+//GO(__strcpy_chk, 
+//GO(__strcpy_small, 
+//GO(__strcspn_c1, 
+//GO(__strcspn_c2, 
+//GO(__strcspn_c3, 
+//GO(__strdup, 
+//GOW(strdup, 
+//GO(strerror, 
+//GO(strerror_l, 
+//GO(__strerror_r, 
+//GOW(strerror_r, 
+//GO(strfmon, 
+//GO(__strfmon_l, 
+//GOW(strfmon_l, 
+//GO(strfromd, 
+//GO(strfromf, 
+//GO(strfromf128, 
+//GOW(strfromf32, 
+//GOW(strfromf32x, 
+//GOW(strfromf64, 
+//GOW(strfromf64x, 
+//GO(strfroml, 
+//GO(strfry, 
+//GO(strftime, 
+//GO(__strftime_l, 
+//GOW(strftime_l, 
+//GO(__strncat_chk, 
+//GO(__strncpy_chk, 
+//GO(__strndup, 
+//GOW(strndup, 
+//GO(__strpbrk_c2, 
+//GO(__strpbrk_c3, 
+//GO(strptime, 
+//GOW(strptime_l, 
+//GOW(strsep, 
+//GO(__strsep_1c, 
+//GO(__strsep_2c, 
+//GO(__strsep_3c, 
+//GO(__strsep_g, 
+//GO(strsignal, 
+//GO(__strspn_c1, 
+//GO(__strspn_c2, 
+//GO(__strspn_c3, 
+//GO(strtod, 
+//GO(__strtod_internal, 
+//GO(__strtod_l, 
+//GOW(strtod_l, 
+//GO(__strtod_nan, 
+//GO(strtof, 
+//GO(strtof128, 
+//GO(__strtof128_internal, 
+//GOW(strtof128_l, 
+//GO(__strtof128_nan, 
+//GOW(strtof32, 
+//GOW(strtof32_l, 
+//GOW(strtof32x, 
+//GOW(strtof32x_l, 
+//GOW(strtof64, 
+//GOW(strtof64_l, 
+//GOW(strtof64x, 
+//GOW(strtof64x_l, 
+//GO(__strtof_internal, 
+//GO(__strtof_l, 
+//GOW(strtof_l, 
+//GO(__strtof_nan, 
+//GO(strtoimax, 
+//GO(strtok, 
+//GO(__strtok_r, 
+//GOW(strtok_r, 
+//GO(__strtok_r_1c, 
+//GOW(strtol, 
+//GO(strtold, 
+//GO(__strtold_internal, 
+//GO(__strtold_l, 
+//GOW(strtold_l, 
+//GO(__strtold_nan, 
+//GO(__strtol_internal, 
+//GO(__strtol_l, 
+//GOW(strtol_l, 
+//GOW(strtoll, 
+//GO(__strtoll_internal, 
+//GOW(__strtoll_l, 
+//GOW(strtoll_l, 
+//GOW(strtoq, 
+//GOW(strtoul, 
+//GO(__strtoul_internal, 
+//GO(__strtoul_l, 
+//GOW(strtoul_l, 
+//GOW(strtoull, 
+//GO(__strtoull_internal, 
+//GOW(__strtoull_l, 
+//GOW(strtoull_l, 
+//GO(strtoumax, 
+//GOW(strtouq, 
+//GO(__strverscmp, 
+//GOW(strverscmp, 
+//GO(strxfrm, 
+//GO(__strxfrm_l, 
+//GOW(strxfrm_l, 
+//GO(stty, 
+//DATAB(svcauthdes_stats, 
+//GO(svcerr_auth, 
+//GO(svcerr_decode, 
+//GO(svcerr_noproc, 
+//GO(svcerr_noprog, 
+//GO(svcerr_progvers, 
+//GO(svcerr_systemerr, 
+//GO(svcerr_weakauth, 
+//GO(svc_exit, 
+//GO(svcfd_create, 
+//DATAB(svc_fdset, 
+//GO(svc_getreq, 
+//GO(svc_getreq_common, 
+//GO(svc_getreq_poll, 
+//GO(svc_getreqset, 
+//DATAB(svc_max_pollfd, 
+//DATAB(svc_pollfd, 
+//GO(svcraw_create, 
+//GO(svc_register, 
+//GO(svc_run, 
+//GO(svc_sendreply, 
+//GO(svctcp_create, 
+//GO(svcudp_bufcreate, 
+//GO(svcudp_create, 
+//GO(svcudp_enablecache, 
+//GO(svcunix_create, 
+//GO(svcunixfd_create, 
+//GO(svc_unregister, 
+//GO(swab, 
+//GOW(swapcontext, 
+//GOW(swapoff, 
+//GOW(swapon, 
+//GO(swprintf, 
+//GO(__swprintf_chk, 
+//GO(swscanf, 
+//GOW(symlink, 
+//GO(symlinkat, 
+//GO(sync, 
+//GO(sync_file_range, 
+//GO(syncfs, 
+//GO(syscall, 
+//GO(__sysconf, 
+//GOW(sysconf, 
+//GO(__sysctl, 
+//GOW(sysctl, 
+//DATA(_sys_errlist, 
+//DATA(_sys_errlist, 
+//DATA(_sys_errlist, 
+//DATA(_sys_errlist, 
+//DATA(sys_errlist, 
+//DATA(sys_errlist, 
+//DATA(sys_errlist, 
+//DATA(sys_errlist, 
+//GOW(sysinfo, 
+//GO(syslog, 
+//GO(__syslog_chk, 
+//DATA(sys_sigabbrev, 
+//DATA(sys_sigabbrev, 
+//DATA(_sys_siglist, 
+//DATA(_sys_siglist, 
+//DATA(sys_siglist, 
+//DATA(sys_siglist, 
+//GOW(system, 
+//GO(__sysv_signal, 
+//GOW(sysv_signal, 
+//GOW(tcdrain, 
+//GO(tcflow, 
+//GO(tcflush, 
+//GOW(tcgetattr, 
+//GO(tcgetpgrp, 
+//GO(tcgetsid, 
+//GO(tcsendbreak, 
+//GO(tcsetattr, 
+//GO(tcsetpgrp, 
+//GO(__tdelete, 
+//GOW(tdelete, 
+//GOW(tdestroy, 
+//GO(tee, 
+//GO(telldir, 
+//GO(tempnam, 
+//GOW(textdomain, 
+//GO(__tfind, 
+//GOW(tfind, 
+//GO(thrd_current, 
+//GO(thrd_equal, 
+//GO(thrd_sleep, 
+//GO(thrd_yield, 
+//GO(timegm, 
+//GOW(timelocal, 
+//GO(timerfd_create, 
+//GO(timerfd_gettime, 
+//GO(timerfd_settime, 
+//GOW(times, 
+//GO(timespec_get, 
+//DATAB(__timezone, 
+//GO(tmpfile, 
+//GOW(tmpfile64, 
+//GO(tmpnam, 
+//GO(tmpnam_r, 
+//GO(toascii, 
+//GOW(__toascii_l, 
+//GO(_tolower, 
+//GO(tolower, 
+//GO(__tolower_l, 
+//GOW(tolower_l, 
+//GO(_toupper, 
+//GO(toupper, 
+//GO(__toupper_l, 
+//GOW(toupper_l, 
+//GO(__towctrans, 
+//GOW(towctrans, 
+//GO(__towctrans_l, 
+//GOW(towctrans_l, 
+//GOW(towlower, 
+//GO(__towlower_l, 
+//GOW(towlower_l, 
+//GOW(towupper, 
+//GO(__towupper_l, 
+//GOW(towupper_l, 
+//GO(tr_break, 
+//GOW(truncate, 
+//GOW(truncate64, 
+//GO(__tsearch, 
+//GOW(tsearch, 
+//GO(ttyname, 
+//GOW(ttyname_r, 
+//GO(__ttyname_r_chk, 
+//GO(ttyslot, 
+//GO(__twalk, 
+//GOW(twalk, 
+DATA(__tzname, 4)
+GOW(tzset, vFv)
+//GO(ualarm, 
+//GO(__uflow, 
+//GOW(ulckpwdf, 
+//GOW(ulimit, 
+//GOW(umask, 
+//GOW(umount, 
+//GOW(umount2, 
+//GOW(uname, 
+//GO(__underflow, 
+//GOW(ungetc, 
+//GO(ungetwc, 
+//GOW(unlink, 
+//GO(unlinkat, 
+//GO(unlockpt, 
+//GOW(unsetenv, 
+//GO(unshare, 
+//GOW(updwtmp, 
+//GO(updwtmpx, 
+//GO(uselib, 
+//GO(__uselocale, 
+//GOW(uselocale, 
+//GO(user2netname, 
+//GO(usleep, 
+//GO(ustat, 
+//GO(utime, 
+//GO(utimensat, 
+//GOW(utimes, 
+//GOW(utmpname, 
+//GO(utmpxname, 
+//GOW(valloc, 
+//GOW(vasprintf, 
+//GO(__vasprintf_chk, 
+//GOW(vdprintf, 
+//GO(__vdprintf_chk, 
+//GO(verr, 
+//GO(verrx, 
+//GOW(versionsort, 
+//GOW(versionsort64, 
+//GO(__vfork, 
+//GOW(vfork, 
+//GO(vfprintf, 
+//GO(__vfprintf_chk, 
+//GO(__vfscanf, 
+//GOW(vfscanf, 
+//GOW(vfwprintf, 
+//GO(__vfwprintf_chk, 
+//GOW(vfwscanf, 
+//GO(vhangup, 
+//GO(vlimit, 
+//GO(vmsplice, 
+//GO(vprintf, 
+//GO(__vprintf_chk, 
+//GOW(vscanf, 
+//GOW(__vsnprintf, 
+//GOW(vsnprintf, 
+//GO(__vsnprintf_chk, 
+//GOW(vsprintf, 
+//GO(__vsprintf_chk, 
+//GOW(__vsscanf, 
+//GOW(vsscanf, 
+//GOW(vswprintf, 
+//GO(__vswprintf_chk, 
+//GO(vswscanf, 
+//GO(vsyslog, 
+//GO(__vsyslog_chk, 
+//GO(vtimes, 
+//GO(vwarn, 
+//GO(vwarnx, 
+//GO(vwprintf, 
+//GO(__vwprintf_chk, 
+//GO(vwscanf, 
+//GOW(__wait, 
+//GOW(wait, 
+//GOW(wait3, 
+//GOW(wait4, 
+//GOW(waitid, 
+//GO(__waitpid, 
+//GOW(waitpid, 
+//GO(warn, 
+//GO(warnx, 
+//GOW(wcpcpy, 
+//GO(__wcpcpy_chk, 
+//GOW(wcpncpy, 
+//GO(__wcpncpy_chk, 
+//GOW(wcrtomb, 
+//GO(__wcrtomb_chk, 
+//GOW(wcscasecmp, 
+//GO(__wcscasecmp_l, 
+//GOW(wcscasecmp_l, 
+//GOW(wcscat, 
+//GO(__wcscat_chk, 
+//GOW(wcschrnul, 
+//GOW(wcscoll, 
+//GO(__wcscoll_l, 
+//GOW(wcscoll_l, 
+//GO(__wcscpy_chk, 
+//GO(wcscspn, 
+//GO(wcsdup, 
+//GO(wcsftime, 
+//GO(__wcsftime_l, 
+//GOW(wcsftime_l, 
+//GOW(wcsncasecmp, 
+//GO(__wcsncasecmp_l, 
+//GOW(wcsncasecmp_l, 
+//GO(wcsncat, 
+//GO(__wcsncat_chk, 
+//GOW(wcsncpy, 
+//GO(__wcsncpy_chk, 
+//GOW(wcsnrtombs, 
+//GO(__wcsnrtombs_chk, 
+//GO(wcspbrk, 
+//GOW(wcsrtombs, 
+//GO(__wcsrtombs_chk, 
+//GO(wcsspn, 
+//GO(wcsstr, 
+//GO(wcstod, 
+//GO(__wcstod_internal, 
+//GO(__wcstod_l, 
+//GOW(wcstod_l, 
+//GO(wcstof, 
+//GO(wcstof128, 
+//GO(__wcstof128_internal, 
+//GOW(wcstof128_l, 
+//GOW(wcstof32, 
+//GOW(wcstof32_l, 
+//GOW(wcstof32x, 
+//GOW(wcstof32x_l, 
+//GOW(wcstof64, 
+//GOW(wcstof64_l, 
+//GOW(wcstof64x, 
+//GOW(wcstof64x_l, 
+//GO(__wcstof_internal, 
+//GO(__wcstof_l, 
+//GOW(wcstof_l, 
+//GO(wcstoimax, 
+//GO(wcstok, 
+//GOW(wcstol, 
+//GO(wcstold, 
+//GO(__wcstold_internal, 
+//GO(__wcstold_l, 
+//GOW(wcstold_l, 
+//GO(__wcstol_internal, 
+//GO(__wcstol_l, 
+//GOW(wcstol_l, 
+//GOW(wcstoll, 
+//GO(__wcstoll_internal, 
+//GOW(__wcstoll_l, 
+//GOW(wcstoll_l, 
+//GO(wcstombs, 
+//GO(__wcstombs_chk, 
+//GOW(wcstoq, 
+//GOW(wcstoul, 
+//GO(__wcstoul_internal, 
+//GO(__wcstoul_l, 
+//GOW(wcstoul_l, 
+//GOW(wcstoull, 
+//GO(__wcstoull_internal, 
+//GOW(__wcstoull_l, 
+//GOW(wcstoull_l, 
+//GO(wcstoumax, 
+//GOW(wcstouq, 
+//GOW(wcswcs, 
+//GO(wcswidth, 
+//GO(wcsxfrm, 
+//GO(__wcsxfrm_l, 
+//GOW(wcsxfrm_l, 
+//GO(wctob, 
+//GO(wctomb, 
+//GO(__wctomb_chk, 
+//GOW(wctrans, 
+//GO(__wctrans_l, 
+//GOW(wctrans_l, 
+//GOW(wctype, 
+//GO(__wctype_l, 
+//GOW(wctype_l, 
+//GO(wcwidth, 
+//GOW(wmemcpy, 
+//GO(__wmemcpy_chk, 
+//GOW(wmemmove, 
+//GO(__wmemmove_chk, 
+//GOW(wmempcpy, 
+//GO(__wmempcpy_chk, 
+//GO(wordexp, 
+//GO(wordfree, 
+//GO(__woverflow, 
+//GO(wprintf, 
+//GO(__wprintf_chk, 
+//GOW(__write, 
+//GOW(write, 
+//GO(__write_nocancel, 
+//GOW(writev, 
+//GO(wscanf, 
+//GO(__wuflow, 
+//GO(__wunderflow, 
+//GO(xdecrypt, 
+//GO(xdr_accepted_reply, 
+//GO(xdr_array, 
+//GO(xdr_authdes_cred, 
+//GO(xdr_authdes_verf, 
+//GO(xdr_authunix_parms, 
+//GO(xdr_bool, 
+//GO(xdr_bytes, 
+//GO(xdr_callhdr, 
+//GO(xdr_callmsg, 
+//GO(xdr_char, 
+//GO(xdr_cryptkeyarg, 
+//GO(xdr_cryptkeyarg2, 
+//GO(xdr_cryptkeyres, 
+//GO(xdr_des_block, 
+//GO(xdr_double, 
+//GO(xdr_enum, 
+//GO(xdr_float, 
+//GO(xdr_free, 
+//GO(xdr_getcredres, 
+//GO(xdr_hyper, 
+//GO(xdr_int, 
+//GO(xdr_int16_t, 
+//GO(xdr_int32_t, 
+//GO(xdr_int64_t, 
+//GO(xdr_int8_t, 
+//GO(xdr_keybuf, 
+//GO(xdr_key_netstarg, 
+//GO(xdr_key_netstres, 
+//GO(xdr_keystatus, 
+//GO(xdr_long, 
+//GO(xdr_longlong_t, 
+//GO(xdrmem_create, 
+//GO(xdr_netnamestr, 
+//GO(xdr_netobj, 
+//GO(xdr_opaque, 
+//GO(xdr_opaque_auth, 
+//GO(xdr_pmap, 
+//GO(xdr_pmaplist, 
+//GO(xdr_pointer, 
+//GO(xdr_quad_t, 
+//GO(xdrrec_create, 
+//GO(xdrrec_endofrecord, 
+//GO(xdrrec_eof, 
+//GO(xdrrec_skiprecord, 
+//GO(xdr_reference, 
+//GO(xdr_rejected_reply, 
+//GO(xdr_replymsg, 
+//GO(xdr_rmtcall_args, 
+//GO(xdr_rmtcallres, 
+//GO(xdr_short, 
+//GO(xdr_sizeof, 
+//GO(xdrstdio_create, 
+//GO(xdr_string, 
+//GO(xdr_u_char, 
+//GO(xdr_u_hyper, 
+//GO(xdr_u_int, 
+//GO(xdr_uint16_t, 
+//GO(xdr_uint32_t, 
+//GO(xdr_uint64_t, 
+//GO(xdr_uint8_t, 
+//GO(xdr_u_long, 
+//GO(xdr_u_longlong_t, 
+//GO(xdr_union, 
+//GO(xdr_unixcred, 
+//GO(xdr_u_quad_t, 
+//GO(xdr_u_short, 
+//GO(xdr_vector, 
+//GO(xdr_void, 
+//GO(xdr_wrapstring, 
+//GO(xencrypt, 
+//GO(__xmknod, 
+//GO(__xmknodat, 
+//GO(__xpg_basename, 
+//GOW(__xpg_sigpause, 
+//GO(__xpg_strerror_r, 
+//GO(xprt_register, 
+//GO(xprt_unregister, 
+//GO(__xstat, 
+//GO(__xstat64, 
+
+GOM(__register_frame_info, vFpp)    // faked function
+GOM(__deregister_frame_info, pFp)
diff --git a/src/wrapped/wrappedlibdl.c b/src/wrapped/wrappedlibdl.c
new file mode 100755
index 00000000..95c23f7f
--- /dev/null
+++ b/src/wrapped/wrappedlibdl.c
@@ -0,0 +1,415 @@
+#define _GNU_SOURCE         /* See feature_test_macros(7) */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <elf.h>
+
+#include "wrappedlibs.h"
+
+#include "debug.h"
+#include "wrapper.h"
+#include "bridge.h"
+#include "librarian/library_private.h"
+#include "emu/x64emu_private.h"
+#include "library.h"
+#include "librarian.h"
+#include "box64context.h"
+#include "elfloader.h"
+#include "elfs/elfloader_private.h"
+
+typedef struct dlprivate_s {
+    library_t   **libs;
+    size_t      *count;
+    size_t      *dlopened;
+    size_t      lib_sz;
+    size_t      lib_cap;
+    char*       last_error;
+} dlprivate_t;
+
+dlprivate_t *NewDLPrivate() {
+    dlprivate_t* dl =  (dlprivate_t*)calloc(1, sizeof(dlprivate_t));
+    return dl;
+}
+void FreeDLPrivate(dlprivate_t **lib) {
+    free((*lib)->last_error);
+    free(*lib);
+}
+
+void* my_dlopen(x64emu_t* emu, void *filename, int flag) EXPORT;
+void* my_dlmopen(x64emu_t* emu, void* mlid, void *filename, int flag) EXPORT;
+char* my_dlerror(x64emu_t* emu) EXPORT;
+void* my_dlsym(x64emu_t* emu, void *handle, void *symbol) EXPORT;
+int my_dlclose(x64emu_t* emu, void *handle) EXPORT;
+int my_dladdr(x64emu_t* emu, void *addr, void *info) EXPORT;
+void* my_dlvsym(x64emu_t* emu, void *handle, void *symbol, void *version) EXPORT;
+int my_dlinfo(x64emu_t* emu, void* handle, int request, void* info) EXPORT;
+
+#define LIBNAME libdl
+const char* libdlName = "libdl.so.2";
+
+// define all standard library functions
+#include "wrappedlib_init.h"
+
+#define CLEARERR    if(dl->last_error) free(dl->last_error); dl->last_error = NULL;
+
+extern int box64_zoom;
+// Implementation
+void* my_dlopen(x64emu_t* emu, void *filename, int flag)
+{
+    //void *dlopen(const char *filename, int flag);
+    // TODO, handling special values for filename, like RTLD_SELF?
+    // TODO, handling flags?
+    library_t *lib = NULL;
+    dlprivate_t *dl = emu->context->dlprivate;
+    size_t dlopened = 0;
+    int is_local = (flag&0x100)?0:1;  // if not global, then local, and that means symbols are not put in the global "pot" for pther libs
+    CLEARERR
+    if(filename) {
+        char* rfilename = (char*)filename;
+        if(box64_zoom && strstr(rfilename, "/libturbojpeg.so")) {
+            void* sys = my_dlopen(emu, "libturbojpeg.so.0", flag);
+            if(sys)
+                return sys;
+        }
+        if(dlsym_error && box64_log<LOG_DEBUG) {
+            printf_log(LOG_NONE, "Call to dlopen(\"%s\"/%p, %X)\n", rfilename, filename, flag);
+        }
+        printf_log(LOG_DEBUG, "Call to dlopen(\"%s\"/%p, %X)\n", rfilename, filename, flag);
+        // check if alread dlopenned...
+        for (size_t i=0; i<dl->lib_sz; ++i) {
+            if(IsSameLib(dl->libs[i], rfilename)) {
+                if(dl->count[i]==0 && dl->dlopened[i]) {   // need to lauch init again!
+                    int idx = GetElfIndex(dl->libs[i]);
+                    if(idx!=-1) {
+                        if(dlsym_error || box64_log>=LOG_DEBUG) {
+                                printf_log(LOG_NONE, "dlopen: Recycling, calling Init for %p (%s)\n", (void*)(i+1), rfilename);
+                        }
+                        ReloadLibrary(dl->libs[i], emu);    // reset memory image, redo reloc, run inits
+                    }
+                }
+                dl->count[i] = dl->count[i]+1;
+                if(dlsym_error || box64_log>=LOG_DEBUG) {
+                        printf_log(LOG_NONE, "dlopen: Recycling %s/%p count=%ld (dlopened=%ld, elf_index=%d)\n", rfilename, (void*)(i+1), dl->count[i], dl->dlopened[i], GetElfIndex(dl->libs[i]));
+                }
+                return (void*)(i+1);
+            }
+        }
+        dlopened = (GetLibInternal(rfilename)==NULL);
+        // Then open the lib
+        if(AddNeededLib(NULL, NULL, is_local, rfilename, emu->context, emu)) {
+            printf_log(LOG_INFO, "Warning: Cannot dlopen(\"%s\"/%p, %X)\n", rfilename, filename, flag);
+            if(!dl->last_error)
+                dl->last_error = malloc(129);
+            snprintf(dl->last_error, 129, "Cannot dlopen(\"%s\"/%p, %X)\n", rfilename, filename, flag);
+            return NULL;
+        }
+        lib = GetLibInternal(rfilename);
+    } else {
+        // check if already dlopenned...
+        for (size_t i=0; i<dl->lib_sz; ++i) {
+            if(!dl->libs[i]) {
+                dl->count[i] = dl->count[i]+1;
+                return (void*)(i+1);
+            }
+        }
+        if(dlsym_error && box64_log<LOG_DEBUG) {
+            printf_log(LOG_NONE, "Call to dlopen(NULL, %X)\n", flag);
+        }
+        printf_log(LOG_DEBUG, "Call to dlopen(NULL, %X)\n", flag);
+    }
+    //get the lib and add it to the collection
+    
+    if(dl->lib_sz == dl->lib_cap) {
+        dl->lib_cap += 4;
+        dl->libs = (library_t**)realloc(dl->libs, sizeof(library_t*)*dl->lib_cap);
+        dl->count = (size_t*)realloc(dl->count, sizeof(size_t)*dl->lib_cap);
+        dl->dlopened = (size_t*)realloc(dl->dlopened, sizeof(size_t)*dl->lib_cap);
+        // memset count...
+        memset(dl->count+dl->lib_sz, 0, (dl->lib_cap-dl->lib_sz)*sizeof(size_t));
+    }
+    dl->libs[dl->lib_sz] = lib;
+    dl->count[dl->lib_sz] = dl->count[dl->lib_sz]+1;
+    dl->dlopened[dl->lib_sz] = dlopened;
+    if(dlsym_error || box64_log>=LOG_DEBUG) {
+        printf_log(LOG_NONE, "dlopen: New handle %p (%s), dlopened=%ld\n", (void*)(dl->lib_sz+1), (char*)filename, dlopened);
+    }
+    return (void*)(++dl->lib_sz);
+}
+void* my_dlmopen(x64emu_t* emu, void* lmid, void *filename, int flag)
+{
+    if(lmid) {
+        printf_log(LOG_INFO, "Warning, dlmopen(%p, %p(\"%s\"), 0x%x) called with lmid not LMID_ID_BASE (unsupported)\n", lmid, filename, filename?(char*)filename:"self", flag);
+    }
+    // lmid is ignored for now...
+    return my_dlopen(emu, filename, flag);
+}
+char* my_dlerror(x64emu_t* emu)
+{
+    dlprivate_t *dl = emu->context->dlprivate;
+    return dl->last_error;
+}
+
+KHASH_SET_INIT_INT(libs);
+
+int recursive_dlsym_lib(kh_libs_t* collection, library_t* lib, const char* rsymbol, uintptr_t *start, uintptr_t *end)
+{
+    if(!lib)
+        return 0;
+    khint_t k = kh_get(libs, collection, (uintptr_t)lib);
+    if(k != kh_end(collection))
+        return 0;
+    int ret;
+    kh_put(libs, collection, (uintptr_t)lib, &ret);
+    // look in the library itself
+    if(lib->get(lib, rsymbol, start, end))
+        return 1;
+    // look in other libs
+    int n = GetNeededLibN(lib);
+    for (int i=0; i<n; ++i) {
+        library_t *l = GetNeededLib(lib, i);
+        if(recursive_dlsym_lib(collection, l, rsymbol, start, end))
+            return 1;
+    }
+        
+    return 0;
+}
+
+int my_dlsym_lib(library_t* lib, const char* rsymbol, uintptr_t *start, uintptr_t *end)
+{
+    kh_libs_t *collection = kh_init(libs);
+    int ret = recursive_dlsym_lib(collection, lib, rsymbol, start, end);
+    kh_destroy(libs, collection);
+
+    return ret;
+}
+void* my_dlsym(x64emu_t* emu, void *handle, void *symbol)
+{
+    dlprivate_t *dl = emu->context->dlprivate;
+    uintptr_t start, end;
+    char* rsymbol = (char*)symbol;
+    CLEARERR
+    if(dlsym_error && box64_log<LOG_DEBUG) {
+        printf_log(LOG_NONE, "Call to dlsym(%p, %s) :", handle, rsymbol);
+    }
+    printf_log(LOG_DEBUG, "Call to dlsym(%p, \"%s\")\n", handle, rsymbol);
+    if(handle==NULL) {
+        // special case, look globably
+        if(GetGlobalSymbolStartEnd(emu->context->maplib, rsymbol, &start, &end)) {
+            if(dlsym_error && box64_log<LOG_DEBUG) {
+                printf_log(LOG_NONE, "%p\n", (void*)start);
+            }
+            return (void*)start;
+        }
+        if(!dl->last_error)
+            dl->last_error = malloc(129);
+        snprintf(dl->last_error, 129, "Symbol \"%s\" not found in %p)\n", rsymbol, handle);
+        if(dlsym_error && box64_log<LOG_DEBUG) {
+            printf_log(LOG_NONE, "%p\n", NULL);
+        }
+        return NULL;
+    }
+    if(handle==(void*)0xFFFFFFFF) {
+        // special case, look globably but no self (RTLD_NEXT)
+        elfheader_t *elf = FindElfAddress(emu->context, *(uint32_t*)R_RSP); // use return address to guess "self"
+        if(GetNoSelfSymbolStartEnd(emu->context->maplib, rsymbol, &start, &end, elf)) {
+            if(dlsym_error && box64_log<LOG_DEBUG) {
+                printf_log(LOG_NONE, "%p\n", (void*)start);
+            }
+            return (void*)start;
+        }
+        if(!dl->last_error)
+            dl->last_error = malloc(129);
+        snprintf(dl->last_error, 129, "Symbol \"%s\" not found in %p)\n", rsymbol, handle);
+        if(dlsym_error && box64_log<LOG_DEBUG) {
+            printf_log(LOG_NONE, "%p\n", NULL);
+        }
+        return NULL;
+    }
+    size_t nlib = (size_t)handle;
+    --nlib;
+    if(nlib<0 || nlib>=dl->lib_sz) {
+        if(!dl->last_error)
+            dl->last_error = malloc(129);
+        snprintf(dl->last_error, 129, "Bad handle %p)\n", handle);
+        if(dlsym_error && box64_log<LOG_DEBUG) {
+            printf_log(LOG_NONE, "%p\n", NULL);
+        }
+        return NULL;
+    }
+    if(dl->count[nlib]==0) {
+        if(!dl->last_error)
+            dl->last_error = malloc(129);
+        snprintf(dl->last_error, 129, "Bad handle %p (already closed))\n", handle);
+        if(dlsym_error && box64_log<LOG_DEBUG) {
+            printf_log(LOG_NONE, "%p\n", (void*)NULL);
+        }
+        return NULL;
+    }
+    if(dl->libs[nlib]) {
+        if(my_dlsym_lib(dl->libs[nlib], rsymbol, &start, &end)==0) {
+            // not found
+            if(dlsym_error && box64_log<LOG_DEBUG) {
+                printf_log(LOG_NONE, "%p\nCall to dlsym(%s, \"%s\") Symbol not found\n", NULL, GetNameLib(dl->libs[nlib]), rsymbol);
+            }
+            printf_log(LOG_DEBUG, " Symbol not found\n");
+            if(!dl->last_error)
+                dl->last_error = malloc(129);
+            snprintf(dl->last_error, 129, "Symbol \"%s\" not found in %p(%s)", rsymbol, handle, GetNameLib(dl->libs[nlib]));
+            return NULL;
+        }
+    } else {
+        // still usefull?
+        if(GetSymbolStartEnd(GetLocalSymbol(emu->context->maplib), rsymbol, &start, &end)) {
+            if(dlsym_error && box64_log<LOG_DEBUG) {
+                printf_log(LOG_NONE, "%p\n", (void*)start);
+            }
+            return (void*)start;
+        }
+        if(GetSymbolStartEnd(GetWeakSymbol(emu->context->maplib), rsymbol, &start, &end)) {
+            if(dlsym_error && box64_log<LOG_DEBUG) {
+                printf_log(LOG_NONE, "%p\n", (void*)start);
+            }
+            return (void*)start;
+        }
+        if(GetSymbolStartEnd(GetMapSymbol(emu->context->maplib), rsymbol, &start, &end)) {
+            if(dlsym_error && box64_log<LOG_DEBUG) {
+                printf_log(LOG_NONE, "%p\n", (void*)start);
+            }
+            return (void*)start;
+        }
+        // not found
+        if(dlsym_error && box64_log<LOG_DEBUG) {
+            printf_log(LOG_NONE, "%p\nCall to dlsym(%s, \"%s\") Symbol not found\n", NULL, "Self", rsymbol);
+        }
+        printf_log(LOG_DEBUG, " Symbol not found\n");
+        if(!dl->last_error)
+            dl->last_error = malloc(129);
+        snprintf(dl->last_error, 129, "Symbol \"%s\" not found in %p)\n", rsymbol, handle);
+        return NULL;
+    }
+    if(dlsym_error && box64_log<LOG_DEBUG) {
+        printf_log(LOG_NONE, "%p\n", (void*)start);
+    }
+    return (void*)start;
+}
+int my_dlclose(x64emu_t* emu, void *handle)
+{
+    if(dlsym_error || box64_log>=LOG_DEBUG) {
+            printf_log(LOG_NONE, "Call to dlclose(%p)\n", handle);
+    }
+    dlprivate_t *dl = emu->context->dlprivate;
+    CLEARERR
+    size_t nlib = (size_t)handle;
+    --nlib;
+    if(nlib<0 || nlib>=dl->lib_sz) {
+        if(!dl->last_error)
+            dl->last_error = malloc(129);
+        snprintf(dl->last_error, 129, "Bad handle %p)\n", handle);
+            if(dlsym_error || box64_log>=LOG_DEBUG) {
+                printf_log(LOG_NONE, "dlclose: %s\n", dl->last_error);
+            }
+        return -1;
+    }
+    if(dl->count[nlib]==0) {
+        if(!dl->last_error)
+            dl->last_error = malloc(129);
+        snprintf(dl->last_error, 129, "Bad handle %p (already closed))\n", handle);
+        if(dlsym_error || box64_log>=LOG_DEBUG) {
+            printf_log(LOG_NONE, "dlclose: %s\n", dl->last_error);
+        }
+        return -1;
+    }
+    dl->count[nlib] = dl->count[nlib]-1;
+    if(dl->count[nlib]==0 && dl->dlopened[nlib]) {   // need to call Fini...
+        int idx = GetElfIndex(dl->libs[nlib]);
+        if(idx!=-1) {
+            if(dlsym_error || box64_log>=LOG_DEBUG) {
+                printf_log(LOG_NONE, "dlclose: Call to Fini for %p\n", handle);
+            }
+            RunElfFini(emu->context->elfs[idx], emu);
+            InactiveLibrary(dl->libs[nlib]);
+        }
+    }
+    return 0;
+}
+int my_dladdr(x64emu_t* emu, void *addr, void *i)
+{
+    //int dladdr(void *addr, Dl_info *info);
+    dlprivate_t *dl = emu->context->dlprivate;
+    CLEARERR
+    Dl_info *info = (Dl_info*)i;
+    printf_log(LOG_DEBUG, "Warning: partially unimplement call to dladdr(%p, %p)\n", addr, info);
+    
+    //emu->quit = 1;
+    info->dli_saddr = NULL;
+    info->dli_fname = NULL;
+    info->dli_sname = FindSymbolName(emu->context->maplib, addr, &info->dli_saddr, NULL, &info->dli_fname, &info->dli_fbase);
+    printf_log(LOG_DEBUG, "     dladdr return saddr=%p, fname=\"%s\", sname=\"%s\"\n", info->dli_saddr, info->dli_sname?info->dli_sname:"", info->dli_fname?info->dli_fname:"");
+    return (info->dli_sname)?1:0;   // success is non-null here...
+}
+void* my_dlvsym(x64emu_t* emu, void *handle, void *symbol, void *version)
+{
+    dlprivate_t *dl = emu->context->dlprivate;
+    CLEARERR
+    //void *dlvsym(void *handle, char *symbol, char *version);
+    char* rsymbol = (char*)symbol;
+    char* rversion = (char*)version;
+    printf_log(LOG_INFO, "Warning: unimplement call to dlvsym(%p, %s, %s), fallback to dlsym\n", handle, rsymbol, rversion);
+
+    return my_dlsym(emu, handle, symbol);
+}
+
+typedef struct link_map_s {
+    uintptr_t   l_addr;
+    char*       l_name;
+    Elf64_Dyn*  l_ld;
+} link_map_t;
+
+int my_dlinfo(x64emu_t* emu, void* handle, int request, void* info)
+{
+    if(dlsym_error || box64_log>=LOG_DEBUG) {
+            printf_log(LOG_NONE, "Call to dlinfo(%p, %d, %p)\n", handle, request, info);
+    }
+    dlprivate_t *dl = emu->context->dlprivate;
+    CLEARERR
+    size_t nlib = (size_t)handle;
+    --nlib;
+    if(nlib<0 || nlib>=dl->lib_sz) {
+        if(!dl->last_error)
+            dl->last_error = malloc(129);
+        snprintf(dl->last_error, 129, "Bad handle %p)\n", handle);
+            if(dlsym_error || box64_log>=LOG_DEBUG) {
+                printf_log(LOG_NONE, "dlinfo: %s\n", dl->last_error);
+            }
+        return -1;
+    }
+    if(dl->count[nlib]==0) {
+        if(!dl->last_error)
+            dl->last_error = malloc(129);
+        snprintf(dl->last_error, 129, "Bad handle %p (already closed))\n", handle);
+        if(dlsym_error || box64_log>=LOG_DEBUG) {
+            printf_log(LOG_NONE, "dlinfo: %s\n", dl->last_error);
+        }
+        return -1;
+    }
+    library_t *lib = dl->libs[nlib];
+    elfheader_t *h = (GetElfIndex(lib)>-1)?my_context->elfs[GetElfIndex(lib)]:NULL;
+    switch(request) {
+        case 2: // RTLD_DI_LINKMAP
+            {
+                static link_map_t map = {0};   //cheating, creating a structure on demand...
+                *(link_map_t**)info = &map;
+                map.l_addr = h?h->delta:0;
+                map.l_name = lib->path;
+                map.l_ld = h?h->Dynamic:NULL;
+            }
+            return 0;
+        default:
+            printf_log(LOG_NONE, "Warning, unsupported call to dlinfo(%p, %d, %p)\n", handle, request, info);
+        if(!dl->last_error)
+            dl->last_error = malloc(129);
+        snprintf(dl->last_error, 129, "unsupported call to dlinfo request:%d\n", request);
+    }
+    return -1;
+}
\ No newline at end of file
diff --git a/src/wrapped/wrappedlibdl_private.h b/src/wrapped/wrappedlibdl_private.h
new file mode 100755
index 00000000..35a45d49
--- /dev/null
+++ b/src/wrapped/wrappedlibdl_private.h
@@ -0,0 +1,14 @@
+#if defined(GO) && defined(GOM) && defined(GO2) && defined(DATA)
+
+GOM(dladdr, iFEpp)
+// dladdr1
+GOM(dlclose, iFEp)
+GOM(dlerror, pFE)
+DATAB(_dlfcn_hook, 4)
+GOM(dlinfo, iFEpip)
+GOM(dlmopen, pFEppi)
+GOM(dlopen, pFEpi)
+GOM(dlsym, pFEpp)
+GOM(dlvsym, pFEppp)   // Weak
+
+#endif
\ No newline at end of file