about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorYang Liu <liuyang22@iscas.ac.cn>2025-04-11 18:26:51 +0800
committerGitHub <noreply@github.com>2025-04-11 12:26:51 +0200
commit6c46e3d9b15be3e5c6227bb97fd542a4100ec4d2 (patch)
treebf7552c358c240e44e53c176db44bad11a415de3 /src
parentfa85d4d900c3e03b69bdea65204b51151fc62114 (diff)
downloadbox64-6c46e3d9b15be3e5c6227bb97fd542a4100ec4d2.tar.gz
box64-6c46e3d9b15be3e5c6227bb97fd542a4100ec4d2.zip
[WOW64] Splitted freq and cleanup functions from x64emu (#2521)
Diffstat (limited to 'src')
-rw-r--r--src/core.c2
-rw-r--r--src/dynarec/arm64/dynarec_arm64_0f.c4
-rw-r--r--src/dynarec/la64/dynarec_la64_0f.c2
-rw-r--r--src/dynarec/rv64/dynarec_rv64_0f.c2
-rw-r--r--src/elfs/elfloader.c45
-rw-r--r--src/emu/x64emu.c200
-rw-r--r--src/emu/x64run0f.c1
-rw-r--r--src/emu/x64run_private.c2
-rw-r--r--src/include/cleanup.h13
-rw-r--r--src/include/freq.h9
-rw-r--r--src/include/x64emu.h7
-rw-r--r--src/os/freq_linux.c137
-rw-r--r--src/os/freq_wine.c17
-rw-r--r--src/tools/cleanup.c68
-rw-r--r--src/tools/my_cpuid.c33
-rw-r--r--src/wrapped/wrappedlibc.c7
-rwxr-xr-xsrc/wrapped32/wrappedlibc.c25
17 files changed, 313 insertions, 261 deletions
diff --git a/src/core.c b/src/core.c
index 0ad75b73..7d76d2fe 100644
--- a/src/core.c
+++ b/src/core.c
@@ -45,6 +45,8 @@
 #include "library.h"
 #include "core.h"
 #include "env.h"
+#include "cleanup.h"
+#include "freq.h"
 
 box64context_t *my_context = NULL;
 extern box64env_t box64env;
diff --git a/src/dynarec/arm64/dynarec_arm64_0f.c b/src/dynarec/arm64/dynarec_arm64_0f.c
index c5519584..7071d5d2 100644
--- a/src/dynarec/arm64/dynarec_arm64_0f.c
+++ b/src/dynarec/arm64/dynarec_arm64_0f.c
@@ -14,9 +14,9 @@
 #include "x64trace.h"

 #include "dynarec_native.h"

 #include "my_cpuid.h"

+#include "freq.h"

 #include "emu/x87emu_private.h"

 #include "emu/x64shaext.h"

-

 #include "arm64_printer.h"

 #include "dynarec_arm64_private.h"

 #include "dynarec_arm64_functions.h"

@@ -1938,7 +1938,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                         }

                         if(BOX64ENV(sse_flushto0)) {

                             // try to sync mxcsr with fpsr on the flag side

-                            /* mapping is 

+                            /* mapping is

                                 ARM -> X86

                                 0 -> 0  // Invalid operation

                                 1 -> 2  // Divide by 0

diff --git a/src/dynarec/la64/dynarec_la64_0f.c b/src/dynarec/la64/dynarec_la64_0f.c
index 4d0ea75e..18714f81 100644
--- a/src/dynarec/la64/dynarec_la64_0f.c
+++ b/src/dynarec/la64/dynarec_la64_0f.c
@@ -18,7 +18,7 @@
 #include "emu/x87emu_private.h"
 #include "emu/x64shaext.h"
 #include "bitutils.h"
-
+#include "freq.h"
 #include "la64_printer.h"
 #include "dynarec_la64_private.h"
 #include "dynarec_la64_functions.h"
diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c
index f12f7a39..f3798cb4 100644
--- a/src/dynarec/rv64/dynarec_rv64_0f.c
+++ b/src/dynarec/rv64/dynarec_rv64_0f.c
@@ -17,7 +17,7 @@
 #include "emu/x87emu_private.h"
 #include "emu/x64shaext.h"
 #include "bitutils.h"
-
+#include "freq.h"
 #include "rv64_printer.h"
 #include "dynarec_rv64_private.h"
 #include "dynarec_rv64_functions.h"
diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c
index 4302f275..c12f29b9 100644
--- a/src/elfs/elfloader.c
+++ b/src/elfs/elfloader.c
@@ -36,6 +36,7 @@
 #include "wine_tools.h"
 #include "dictionnary.h"
 #include "symbols.h"
+#include "cleanup.h"
 #ifdef DYNAREC
 #include "dynablock.h"
 #endif
@@ -68,12 +69,12 @@ elfheader_t* LoadAndCheckElfHeader(FILE* f, const char* name, int exec)
         h->path = (char*)box_malloc(1);
         h->path[0] = '\0';
     }
-    
+
     h->refcnt = 0;
 
     h->file = f;
     h->fileno = fileno(f);
-    
+
     return h;
 }
 
@@ -127,7 +128,7 @@ int CalcLoadAddr(elfheader_t* head)
                     head->vaddr = (uintptr_t)head->PHEntries._64[i].p_vaddr;
             }
     }
-    
+
     if(head->vaddr==~(uintptr_t)0 || head->paddr==~(uintptr_t)0) {
         printf_log(LOG_NONE, "Error: v/p Addr for Elf Load not set\n");
         return 1;
@@ -223,7 +224,7 @@ int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin)
 
     head->multiblock_n = 0; // count PHEntrie with LOAD
     uintptr_t max_align = head->align-1;
-    for (size_t i=0; i<head->numPHEntries; ++i) 
+    for (size_t i=0; i<head->numPHEntries; ++i)
         if(head->PHEntries._64[i].p_type == PT_LOAD && head->PHEntries._64[i].p_flags) {
             ++head->multiblock_n;
         }
@@ -314,8 +315,8 @@ int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin)
             if(try_mmap) {
                 printf_dump(log_level, "Mmaping 0x%lx(0x%lx) bytes @%p for Elf \"%s\"\n", head->multiblocks[n].size, head->multiblocks[n].asize, (void*)head->multiblocks[n].paddr, head->name);
                 void* p = mmap64(
-                    (void*)head->multiblocks[n].paddr, 
-                    head->multiblocks[n].size, 
+                    (void*)head->multiblocks[n].paddr,
+                    head->multiblocks[n].size,
                     prot,
                     MAP_PRIVATE|MAP_FIXED, //((prot&PROT_WRITE)?MAP_SHARED:MAP_PRIVATE)|MAP_FIXED,
                     head->fileno,
@@ -373,7 +374,7 @@ int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin)
                             p = (void*)paddr;
                     } else {
                         p = (void*)paddr;
-                        printf_dump(log_level, "Will read 0x%zx @%p for Elf \"%s\"\n", e->p_filesz, (void*)head->multiblocks[n].paddr, head->name);    
+                        printf_dump(log_level, "Will read 0x%zx @%p for Elf \"%s\"\n", e->p_filesz, (void*)head->multiblocks[n].paddr, head->name);
                     }
                 }
                 if(p==MAP_FAILED || p!=(void*)paddr) {
@@ -489,7 +490,7 @@ static elfheader_t* FindElfSymbol(box64context_t *context, Elf64_Sym* sym)
     for (int i=0; i<context->elfsize; ++i)
         if(IsSymInElfSpace(context->elfs[i], sym))
             return context->elfs[i];
-    
+
     return NULL;
 }
 
@@ -685,8 +686,8 @@ static int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int
             case R_X86_64_GLOB_DAT:
                 if(GetSymbolStartEnd(my_context->globdata, symname, &globoffs, &globend, version, vername, 1, veropt)) {
                     globp = (uint64_t*)globoffs;
-                    printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT with R_X86_64_COPY @%p/%p (%p/%p -> %p/%p) size=%zd on sym=%s (%sver=%d/%s) \n", 
-                        BindSym(bind), p, globp, (void*)(p?(*p):0), 
+                    printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT with R_X86_64_COPY @%p/%p (%p/%p -> %p/%p) size=%zd on sym=%s (%sver=%d/%s) \n",
+                        BindSym(bind), p, globp, (void*)(p?(*p):0),
                         (void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, sym->st_size, symname, veropt?"opt":"", version, vername?vername:"(none)");
                     sym_elf = my_context->elfs[0];
                     *p = globoffs;
@@ -704,9 +705,9 @@ static int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int
             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 
-                  || ((symname && strstr(symname, "g_cclosure_marshal_")==symname)) 
-                  || ((symname && strstr(symname, "__pthread_unwind_next")==symname)) 
+                if (bind==STB_LOCAL
+                  || ((symname && strstr(symname, "g_cclosure_marshal_")==symname))
+                  || ((symname && strstr(symname, "__pthread_unwind_next")==symname))
                   || !tmp
                   || !((tmp>=head->plt && tmp<head->plt_end) || (tmp>=head->gotplt && tmp<head->gotplt_end))
                   || !need_resolv
@@ -722,7 +723,7 @@ static int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int
                         // return -1;
                     } else {
                         if(p) {
-                            printf_dump(LOG_NEVER, "Apply %s R_X86_64_JUMP_SLOT @%p with sym=%s (%p -> %p / %s (%sver=%d / %s))\n", 
+                            printf_dump(LOG_NEVER, "Apply %s R_X86_64_JUMP_SLOT @%p with sym=%s (%p -> %p / %s (%sver=%d / %s))\n",
                                 BindSym(bind), p, symname, *(void**)p, (void*)(offs+rela[i].r_addend), sym_elf?sym_elf->name:"native", veropt?"opt":"", version, vername?vername:"(none)");
                             *p = offs + rela[i].r_addend;
                             if(sym_elf && sym_elf!=last_elf && sym_elf!=head) last_elf = checkElfLib(head, sym_elf->lib);
@@ -731,7 +732,7 @@ static int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int
                         }
                     }
                 } else {
-                    printf_dump(LOG_NEVER, "Preparing (if needed) %s R_X86_64_JUMP_SLOT @%p (0x%lx->0x%0lx) with sym=%s to be apply later (addend=%ld)\n", 
+                    printf_dump(LOG_NEVER, "Preparing (if needed) %s R_X86_64_JUMP_SLOT @%p (0x%lx->0x%0lx) with sym=%s to be apply later (addend=%ld)\n",
                         BindSym(bind), p, *p, *p+head->delta, symname, rela[i].r_addend);
                     *p += head->delta;
                     *need_resolv = 1;
@@ -750,7 +751,7 @@ static int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int
                     if(bind==STB_GLOBAL)
                         ret_ok = 1;
                 } else {
-                    printf_dump(LOG_NEVER, "Apply %s R_X86_64_64 @%p with sym=%s (%sver=%d/%s) addend=0x%lx (%p -> %p)\n", 
+                    printf_dump(LOG_NEVER, "Apply %s R_X86_64_64 @%p with sym=%s (%sver=%d/%s) addend=0x%lx (%p -> %p)\n",
                         BindSym(bind), p, symname, veropt?"opt":"", version, vername?vername:"(none)", rela[i].r_addend, *(void**)p, (void*)(offs+rela[i].r_addend/*+*(uint64_t*)p*/));
                     *p /*+*/= offs+rela[i].r_addend;
                     if(sym_elf && sym_elf!=last_elf && sym_elf!=head) last_elf = checkElfLib(head, sym_elf->lib);
@@ -933,7 +934,7 @@ int RelocateElfPlt64(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbi
             }
         }
     }
-   
+
     return 0;
 }
 int RelocateElfPlt(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head)
@@ -1310,7 +1311,7 @@ int IsAddressInElfSpace(const elfheader_t* h, uintptr_t addr)
         uintptr_t end = (uintptr_t)h->multiblocks[i].p + h->multiblocks[i].asize - 1;
         if(base && addr>=base && addr<=end)
             return 1;
-        
+
     }
     return 0;
 }
@@ -1319,7 +1320,7 @@ elfheader_t* FindElfAddress(box64context_t *context, uintptr_t addr)
     for (int i=0; i<context->elfsize; ++i)
         if(IsAddressInElfSpace(context->elfs[i], addr))
             return context->elfs[i];
-    
+
     return NULL;
 }
 
@@ -1518,7 +1519,7 @@ EXPORT int my32_dl_iterate_phdr(x64emu_t *emu, void* F, void *data)
 #ifdef BOX32
 ;
 #else
-{ 
+{
     return -1;
 }
 #endif
@@ -1836,9 +1837,9 @@ void* GetNativeSymbolUnversioned(void* lib, const char* name)
     search_symbol_t s;
     s.name = name;
     s.addr = NULL;
-    if(lib) 
+    if(lib)
         s.lib = lib;
-    else 
+    else
         s.lib = my_context->box64lib;
     printf_log(LOG_INFO, "Look for %s in loaded elfs\n", name);
     dl_iterate_phdr(dl_iterate_phdr_findsymbol, &s);
diff --git a/src/emu/x64emu.c b/src/emu/x64emu.c
index a2117176..c4a90a11 100644
--- a/src/emu/x64emu.c
+++ b/src/emu/x64emu.c
@@ -3,9 +3,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
-#include <sys/syscall.h>
-#include <sys/time.h>
-#include <sys/mman.h>
 
 #include "os.h"
 #include "debug.h"
@@ -19,7 +16,6 @@
 #include "x64run_private.h"
 #include "callback.h"
 #include "bridge.h"
-#include "elfs/elfloader_private.h"
 #ifdef HAVE_TRACE
 #include "x64trace.h"
 #endif
@@ -32,12 +28,6 @@
 #warning Architecture cannot follow SSE Flush to 0 flag
 #endif
 
-typedef struct cleanup_s {
-    void*       f;
-    int         arg;
-    void*       a;
-} cleanup_t;
-
 static uint32_t x86emu_parity_tab[8] =
 {
     0x96696996,
@@ -111,7 +101,7 @@ x64emu_t *NewX64EmuFromStack(x64emu_t* emu, box64context_t *context, uintptr_t s
     printf_log(LOG_DEBUG, "New X86_64 Emu from stack, with EIP=%p and Stack=%p/0x%X\n", (void*)start, (void*)stack, stacksize);
 
     internalX64Setup(emu, context, start, stack, stacksize, 0);
-    
+
     return emu;
 }
 
@@ -147,61 +137,6 @@ void SetTraceEmu(uintptr_t start, uintptr_t end)
 }
 #endif
 
-void AddCleanup(x64emu_t *emu, void *p)
-{
-    (void)emu;
-    
-    if(my_context->clean_sz == my_context->clean_cap) {
-        my_context->clean_cap += 32;
-        my_context->cleanups = (cleanup_t*)box_realloc(my_context->cleanups, sizeof(cleanup_t)*my_context->clean_cap);
-    }
-    my_context->cleanups[my_context->clean_sz].arg = 0;
-    my_context->cleanups[my_context->clean_sz].a = NULL;
-    my_context->cleanups[my_context->clean_sz++].f = p;
-}
-
-void AddCleanup1Arg(x64emu_t *emu, void *p, void* a, elfheader_t* h)
-{
-    (void)emu;
-    if(!h)
-        return;
-    
-    if(h->clean_sz == h->clean_cap) {
-        h->clean_cap += 32;
-        h->cleanups = (cleanup_t*)box_realloc(h->cleanups, sizeof(cleanup_t)*h->clean_cap);
-    }
-    h->cleanups[h->clean_sz].arg = 1;
-    h->cleanups[h->clean_sz].a = a;
-    h->cleanups[h->clean_sz++].f = p;
-}
-
-void CallCleanup(x64emu_t *emu, elfheader_t* h)
-{
-    printf_log(LOG_DEBUG, "Calling atexit registered functions for elf: %p/%s\n", h, h?h->name:"(nil)");
-    if(!h)
-        return;
-    for(int i=h->clean_sz-1; i>=0; --i) {
-        printf_log(LOG_DEBUG, "Call cleanup #%d (args:%d, arg:%p)\n", i, h->cleanups[i].arg, h->cleanups[i].a);
-        RunFunctionWithEmu(emu, 0, (uintptr_t)(h->cleanups[i].f), h->cleanups[i].arg, h->cleanups[i].a );
-        // now remove the cleanup
-        if(i!=h->clean_sz-1)
-            memmove(h->cleanups+i, h->cleanups+i+1, (h->clean_sz-i-1)*sizeof(cleanup_t));
-        --h->clean_sz;
-    }
-}
-
-void CallAllCleanup(x64emu_t *emu)
-{
-    printf_log(LOG_DEBUG, "Calling atexit registered functions\n");
-    for(int i=my_context->clean_sz-1; i>=0; --i) {
-        printf_log(LOG_DEBUG, "Call cleanup #%d\n", i);
-        --my_context->clean_sz;
-        RunFunctionWithEmu(emu, 0, (uintptr_t)(my_context->cleanups[i].f), my_context->cleanups[i].arg, my_context->cleanups[i].a );
-    }
-    box_free(my_context->cleanups);
-    my_context->cleanups = NULL;
-}
-
 static void internalFreeX64(x64emu_t* emu)
 {
     if(emu && emu->stack2free)
@@ -534,7 +469,7 @@ const char* DumpCPURegs(x64emu_t* emu, uintptr_t ip, int is32bits)
                 } else {
                     strcat(buff, "\n");
                 }
-            } 
+            }
     }
     if(is32bits)
         sprintf(tmp, "EIP=%08lx ", ip);
@@ -584,8 +519,8 @@ void UnimpOpcode(x64emu_t* emu, int is32bits)
 {
     R_RIP = emu->old_ip;
 
-    int tid = syscall(SYS_gettid);
-    printf_log(LOG_INFO, "%04d|%p: Unimplemented %sOpcode (%02X %02X %02X %02X) %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", 
+    int tid = GetTID();
+    printf_log(LOG_INFO, "%04d|%p: Unimplemented %sOpcode (%02X %02X %02X %02X) %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
         tid, (void*)emu->old_ip, is32bits?"32bits ":"",
         Peek(emu, -4), Peek(emu, -3), Peek(emu, -2), Peek(emu, -1),
         Peek(emu, 0), Peek(emu, 1), Peek(emu, 2), Peek(emu, 3),
@@ -645,133 +580,6 @@ void EmuCall(x64emu_t* emu, uintptr_t addr)
     }
 }
 
-#if defined(RV64)
-static size_t readBinarySizeFromFile(const char* fname)
-{
-    if (access(fname, R_OK) != 0) return -1;
-    FILE* fp = fopen(fname, "r");
-    if (fp == NULL) return -1;
-
-    char b[sizeof(uint64_t)] = { 0 }, tmp;
-    ssize_t n = fread(b, 1, sizeof(b), fp);
-    if (n <= 0) return -1;
-
-    for (ssize_t i = 0; i < n / 2; i++) {
-        tmp = b[n - i - 1];
-        b[n - i - 1] = b[i];
-        b[i] = tmp;
-    }
-    return *(uint64_t*)b;
-}
-
-static inline uint64_t readCycleCounter()
-{
-    uint64_t val;
-    asm volatile("rdtime %0"
-                 : "=r"(val));
-    return val;
-}
-
-static inline uint64_t readFreq()
-{
-    static size_t val = -1;
-
-    val = readBinarySizeFromFile("/sys/firmware/devicetree/base/cpus/timebase-frequency");
-    if (val != (size_t)-1) return val;
-
-    // fallback to rdtime + sleep
-    struct timespec ts;
-    ts.tv_sec = 0;
-    ts.tv_nsec = 50000000; // 50 milliseconds
-    uint64_t cycles = readCycleCounter();
-    nanosleep(&ts, NULL);
-    // round to MHz
-    val = (size_t)round(((double)(readCycleCounter() - cycles) * 20) / 1e6) * 1e6;
-    return (uint64_t)val;
-}
-#elif defined(ARM64)
-static inline uint64_t readCycleCounter()
-{
-    uint64_t val;
-    asm volatile("mrs %0, cntvct_el0"
-                 : "=r"(val));
-    return val;
-}
-static inline uint64_t readFreq()
-{
-    uint64_t val;
-    asm volatile("mrs %0, cntfrq_el0"
-                 : "=r"(val));
-    return val;
-}
-#elif defined(LA64)
-static inline uint64_t readCycleCounter()
-{
-    uint64_t val;
-    asm volatile("rdtime.d %0, %1"
-                 : "=r"(val) : "r"(0));
-    return val;
-}
-
-static inline uint64_t readFreq()
-{
-    static size_t val = -1;
-
-    FILE* f = popen("cat /proc/cpuinfo | grep -i \"CPU MHz\" | head -n 1 | sed -r 's/CPU MHz.+:\\s{1,}//g'", "r");
-    if(f) {
-        char tmp[200] = "";
-        ssize_t s = fread(tmp, 1, 200, f);
-        pclose(f);
-        if (s > 0) return (uint64_t)atof(tmp) * 1e6;
-    }
-    
-    // fallback to rdtime + sleep
-    struct timespec ts;
-    ts.tv_sec = 0;
-    ts.tv_nsec = 50000000; // 50 milliseconds
-    uint64_t cycles = readCycleCounter();
-    nanosleep(&ts, NULL);
-    // round to MHz
-    val = (size_t)round(((double)(readCycleCounter() - cycles) * 20) / 1e6) * 1e6;
-    return (uint64_t)val;
-}
-#endif
-
-uint64_t ReadTSC(x64emu_t* emu)
-{
-    (void)emu;
-    
-    // Hardware counter, per architecture
-#if defined(ARM64) || defined(RV64) || defined(LA64)
-    if (!box64_rdtsc) return readCycleCounter();
-#endif
-    // fall back to gettime...
-#if !defined(NOGETCLOCK)
-    struct timespec ts;
-    clock_gettime(CLOCK_MONOTONIC_COARSE, &ts);
-    return (uint64_t)(ts.tv_sec) * 1000000000LL + ts.tv_nsec;
-#else
-    struct timeval tv;
-    gettimeofday(&tv, NULL);
-    return (uint64_t)(tv.tv_sec) * 1000000 + tv.tv_usec;
-#endif
-}
-
-uint64_t ReadTSCFrequency(x64emu_t* emu)
-{
-    (void)emu;
-    // Hardware counter, per architecture
-#if defined(ARM64) || defined(RV64) || defined(LA64)
-    if (!box64_rdtsc) return readFreq();
-#endif
-    // fall back to get time
-#if !defined(NOGETCLOCK)
-    return 1000000000LL;
-#else
-    return 1000000;
-#endif
-}
-
 void ResetSegmentsCache(x64emu_t *emu)
 {
     if(!emu)
diff --git a/src/emu/x64run0f.c b/src/emu/x64run0f.c
index 94cd858a..2fc6633c 100644
--- a/src/emu/x64run0f.c
+++ b/src/emu/x64run0f.c
@@ -24,6 +24,7 @@
 #include "bridge.h"

 #include "emit_signals.h"

 #include "x64shaext.h"

+#include "freq.h"

 #ifdef DYNAREC

 #include "custommem.h"

 #include "../dynarec/native_lock.h"

diff --git a/src/emu/x64run_private.c b/src/emu/x64run_private.c
index f9eec5c6..36d72642 100644
--- a/src/emu/x64run_private.c
+++ b/src/emu/x64run_private.c
@@ -1221,7 +1221,7 @@ void PrintTrace(x64emu_t* emu, uintptr_t ip, int dynarec)
     if(!BOX64ENV(start_cnt) && my_context->dec && (
             (trace_end == 0)
             || ((ip >= trace_start) && (ip < trace_end))) ) {
-        int tid = syscall(SYS_gettid);
+        int tid = GetTID();
         mutex_lock(&my_context->mutex_trace);
 #ifdef DYNAREC
         if((my_context->trace_tid != tid) || (my_context->trace_dynarec!=dynarec)) {
diff --git a/src/include/cleanup.h b/src/include/cleanup.h
new file mode 100644
index 00000000..99c13b36
--- /dev/null
+++ b/src/include/cleanup.h
@@ -0,0 +1,13 @@
+#ifndef __CLEANUP_H_
+#define __CLEANUP_H_
+
+#include "elfloader.h"
+
+typedef struct x64emu_s x64emu_t;
+
+void AddCleanup(x64emu_t *emu, void *p);
+void AddCleanup1Arg(x64emu_t *emu, void *p, void* a, elfheader_t* h);
+void CallCleanup(x64emu_t *emu, elfheader_t* h);
+void CallAllCleanup(x64emu_t *emu);
+
+#endif // __CLEANUP_H_
\ No newline at end of file
diff --git a/src/include/freq.h b/src/include/freq.h
new file mode 100644
index 00000000..2f3a2427
--- /dev/null
+++ b/src/include/freq.h
@@ -0,0 +1,9 @@
+#ifndef __FREQ_H_
+#define __FREQ_H_
+
+typedef struct x64emu_s x64emu_t;
+
+uint64_t ReadTSC(x64emu_t* emu);
+uint64_t ReadTSCFrequency(x64emu_t* emu);
+
+#endif // __FREQ_H_
\ No newline at end of file
diff --git a/src/include/x64emu.h b/src/include/x64emu.h
index 4b88f6ae..d4311c77 100644
--- a/src/include/x64emu.h
+++ b/src/include/x64emu.h
@@ -20,15 +20,8 @@ void ResetFlags(x64emu_t *emu);
 void ResetSegmentsCache(x64emu_t *emu);
 const char* DumpCPURegs(x64emu_t* emu, uintptr_t ip, int is32bits);
 
-void AddCleanup(x64emu_t *emu, void *p);
-void AddCleanup1Arg(x64emu_t *emu, void *p, void* a, elfheader_t* h);
-void CallCleanup(x64emu_t *emu, elfheader_t* h);
-void CallAllCleanup(x64emu_t *emu);
 void UnimpOpcode(x64emu_t* emu, int is32bits);
 
-uint64_t ReadTSC(x64emu_t* emu);
-uint64_t ReadTSCFrequency(x64emu_t* emu);
-
 double FromLD(void* ld);        // long double (80bits pointer) -> double
 long double LD2localLD(void* ld);        // long double (80bits pointer) -> long double (80 or 128bits)
 void LD2D(void* ld, void* d);   // long double (80bits) -> double (64bits)
diff --git a/src/os/freq_linux.c b/src/os/freq_linux.c
new file mode 100644
index 00000000..6bdca050
--- /dev/null
+++ b/src/os/freq_linux.c
@@ -0,0 +1,137 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <math.h>
+
+#include "freq.h"
+#include "debug.h"
+
+#if defined(RV64)
+static size_t readBinarySizeFromFile(const char* fname)
+{
+    if (access(fname, R_OK) != 0) return -1;
+    FILE* fp = fopen(fname, "r");
+    if (fp == NULL) return -1;
+
+    char b[sizeof(uint64_t)] = { 0 }, tmp;
+    ssize_t n = fread(b, 1, sizeof(b), fp);
+    if (n <= 0) return -1;
+
+    for (ssize_t i = 0; i < n / 2; i++) {
+        tmp = b[n - i - 1];
+        b[n - i - 1] = b[i];
+        b[i] = tmp;
+    }
+    return *(uint64_t*)b;
+}
+
+static inline uint64_t readCycleCounter()
+{
+    uint64_t val;
+    asm volatile("rdtime %0"
+                 : "=r"(val));
+    return val;
+}
+
+static inline uint64_t readFreq()
+{
+    static size_t val = -1;
+
+    val = readBinarySizeFromFile("/sys/firmware/devicetree/base/cpus/timebase-frequency");
+    if (val != (size_t)-1) return val;
+
+    // fallback to rdtime + sleep
+    struct timespec ts;
+    ts.tv_sec = 0;
+    ts.tv_nsec = 50000000; // 50 milliseconds
+    uint64_t cycles = readCycleCounter();
+    nanosleep(&ts, NULL);
+    // round to MHz
+    val = (size_t)round(((double)(readCycleCounter() - cycles) * 20) / 1e6) * 1e6;
+    return (uint64_t)val;
+}
+#elif defined(ARM64)
+static inline uint64_t readCycleCounter()
+{
+    uint64_t val;
+    asm volatile("mrs %0, cntvct_el0"
+                 : "=r"(val));
+    return val;
+}
+static inline uint64_t readFreq()
+{
+    uint64_t val;
+    asm volatile("mrs %0, cntfrq_el0"
+                 : "=r"(val));
+    return val;
+}
+#elif defined(LA64)
+static inline uint64_t readCycleCounter()
+{
+    uint64_t val;
+    asm volatile("rdtime.d %0, %1"
+                 : "=r"(val) : "r"(0));
+    return val;
+}
+
+static inline uint64_t readFreq()
+{
+    static size_t val = -1;
+
+    FILE* f = popen("cat /proc/cpuinfo | grep -i \"CPU MHz\" | head -n 1 | sed -r 's/CPU MHz.+:\\s{1,}//g'", "r");
+    if(f) {
+        char tmp[200] = "";
+        ssize_t s = fread(tmp, 1, 200, f);
+        pclose(f);
+        if (s > 0) return (uint64_t)atof(tmp) * 1e6;
+    }
+
+    // fallback to rdtime + sleep
+    struct timespec ts;
+    ts.tv_sec = 0;
+    ts.tv_nsec = 50000000; // 50 milliseconds
+    uint64_t cycles = readCycleCounter();
+    nanosleep(&ts, NULL);
+    // round to MHz
+    val = (size_t)round(((double)(readCycleCounter() - cycles) * 20) / 1e6) * 1e6;
+    return (uint64_t)val;
+}
+#endif
+
+uint64_t ReadTSC(x64emu_t* emu)
+{
+    (void)emu;
+
+    // Hardware counter, per architecture
+#if defined(ARM64) || defined(RV64) || defined(LA64)
+    if (!box64_rdtsc) return readCycleCounter();
+#endif
+    // fall back to gettime...
+#if !defined(NOGETCLOCK)
+    struct timespec ts;
+    clock_gettime(CLOCK_MONOTONIC_COARSE, &ts);
+    return (uint64_t)(ts.tv_sec) * 1000000000LL + ts.tv_nsec;
+#else
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+    return (uint64_t)(tv.tv_sec) * 1000000 + tv.tv_usec;
+#endif
+}
+
+uint64_t ReadTSCFrequency(x64emu_t* emu)
+{
+    (void)emu;
+    // Hardware counter, per architecture
+#if defined(ARM64) || defined(RV64) || defined(LA64)
+    if (!box64_rdtsc) return readFreq();
+#endif
+    // fall back to get time
+#if !defined(NOGETCLOCK)
+    return 1000000000LL;
+#else
+    return 1000000;
+#endif
+}
diff --git a/src/os/freq_wine.c b/src/os/freq_wine.c
new file mode 100644
index 00000000..6b2a9dc4
--- /dev/null
+++ b/src/os/freq_wine.c
@@ -0,0 +1,17 @@
+#incldue "freq.h"
+
+// TODO: box64_rdtsc?
+
+uint64_t ReadTSC(x64emu_t* emu) {
+    uint64_t val;
+    asm volatile("mrs %0, cntvct_el0"
+                 : "=r"(val));
+    return val;
+}
+
+uint64_t ReadTSCFrequency(x64emu_t* emu) {
+    uint64_t val;
+    asm volatile("mrs %0, cntfrq_el0"
+                 : "=r"(val));
+    return val;
+}
\ No newline at end of file
diff --git a/src/tools/cleanup.c b/src/tools/cleanup.c
new file mode 100644
index 00000000..79ac3451
--- /dev/null
+++ b/src/tools/cleanup.c
@@ -0,0 +1,68 @@
+#include <string.h>
+
+#include "cleanup.h"
+#include "elfs/elfloader_private.h"
+#include "box64context.h"
+#include "debug.h"
+#include "callback.h"
+
+typedef struct cleanup_s {
+    void*       f;
+    int         arg;
+    void*       a;
+} cleanup_t;
+
+void AddCleanup(x64emu_t *emu, void *p)
+{
+    (void)emu;
+
+    if(my_context->clean_sz == my_context->clean_cap) {
+        my_context->clean_cap += 32;
+        my_context->cleanups = (cleanup_t*)box_realloc(my_context->cleanups, sizeof(cleanup_t)*my_context->clean_cap);
+    }
+    my_context->cleanups[my_context->clean_sz].arg = 0;
+    my_context->cleanups[my_context->clean_sz].a = NULL;
+    my_context->cleanups[my_context->clean_sz++].f = p;
+}
+
+void AddCleanup1Arg(x64emu_t *emu, void *p, void* a, elfheader_t* h)
+{
+    (void)emu;
+    if(!h)
+        return;
+
+    if(h->clean_sz == h->clean_cap) {
+        h->clean_cap += 32;
+        h->cleanups = (cleanup_t*)box_realloc(h->cleanups, sizeof(cleanup_t)*h->clean_cap);
+    }
+    h->cleanups[h->clean_sz].arg = 1;
+    h->cleanups[h->clean_sz].a = a;
+    h->cleanups[h->clean_sz++].f = p;
+}
+
+void CallCleanup(x64emu_t *emu, elfheader_t* h)
+{
+    printf_log(LOG_DEBUG, "Calling atexit registered functions for elf: %p/%s\n", h, h?h->name:"(nil)");
+    if(!h)
+        return;
+    for(int i=h->clean_sz-1; i>=0; --i) {
+        printf_log(LOG_DEBUG, "Call cleanup #%d (args:%d, arg:%p)\n", i, h->cleanups[i].arg, h->cleanups[i].a);
+        RunFunctionWithEmu(emu, 0, (uintptr_t)(h->cleanups[i].f), h->cleanups[i].arg, h->cleanups[i].a );
+        // now remove the cleanup
+        if(i!=h->clean_sz-1)
+            memmove(h->cleanups+i, h->cleanups+i+1, (h->clean_sz-i-1)*sizeof(cleanup_t));
+        --h->clean_sz;
+    }
+}
+
+void CallAllCleanup(x64emu_t *emu)
+{
+    printf_log(LOG_DEBUG, "Calling atexit registered functions\n");
+    for(int i=my_context->clean_sz-1; i>=0; --i) {
+        printf_log(LOG_DEBUG, "Call cleanup #%d\n", i);
+        --my_context->clean_sz;
+        RunFunctionWithEmu(emu, 0, (uintptr_t)(my_context->cleanups[i].f), my_context->cleanups[i].arg, my_context->cleanups[i].a );
+    }
+    box_free(my_context->cleanups);
+    my_context->cleanups = NULL;
+}
\ No newline at end of file
diff --git a/src/tools/my_cpuid.c b/src/tools/my_cpuid.c
index 5c97c7bc..df505ac0 100644
--- a/src/tools/my_cpuid.c
+++ b/src/tools/my_cpuid.c
@@ -1,4 +1,4 @@
-#define _GNU_SOURCE 
+#define _GNU_SOURCE
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -8,6 +8,7 @@
 #include "../emu/x64emu_private.h"
 #include "debug.h"
 #include "x64emu.h"
+#include "freq.h"
 
 int get_cpuMhz()
 {
@@ -36,7 +37,7 @@ int get_cpuMhz()
             fclose(f);
             ++cpucore;
         }
-        else 
+        else
             cpucore = -1;
     }
     #ifndef STATICBUILD
@@ -268,7 +269,7 @@ void my_cpuid(x64emu_t* emu, uint32_t tmp32u)
                 if(cpu<0) cpu=0;
                 R_EAX |= cpu<<24;
             }*/
-            R_EDX =   1         // fpu 
+            R_EDX =   1         // fpu
                     | 1<<1      // vme
                     | 1<<2      // debugging extension
                     | 1<<3      // pse
@@ -311,7 +312,7 @@ void my_cpuid(x64emu_t* emu, uint32_t tmp32u)
                     | BOX64ENV(avx)<<29 // F16C
                     | BOX64ENV(avx2)<<30     // RDRAND
                     | 0<<31     // Hypervisor guest running
-                    ; 
+                    ;
             break;
         case 0x2:
             if(BOX64ENV(cputype)) {
@@ -325,7 +326,7 @@ void my_cpuid(x64emu_t* emu, uint32_t tmp32u)
                 R_EDX = 0x007A7000;
             }
             break;
-        
+
         case 0x4:
             if(BOX64ENV(cputype)) {
                 // reserved
@@ -381,8 +382,8 @@ void my_cpuid(x64emu_t* emu, uint32_t tmp32u)
             // extended bits...
             if(R_ECX==0) {
                 R_EAX = 0;
-                R_EBX = 
-                        BOX64ENV(avx)<<3 |  // BMI1 
+                R_EBX =
+                        BOX64ENV(avx)<<3 |  // BMI1
                         BOX64ENV(avx2)<<5 |  //AVX2
                         (BOX64ENV(cputype)?0:1)<<6 | // FDP_EXCPTN_ONLY
                         1<<7 | // SMEP
@@ -396,7 +397,7 @@ void my_cpuid(x64emu_t* emu, uint32_t tmp32u)
                         1<<24 | // CLWB
                         BOX64ENV(shaext)<<29|  // SHA extension
                         0;
-                R_RCX = 
+                R_RCX =
                         BOX64ENV(avx)<<9   | //VAES
                         BOX64ENV(avx2)<<10 | //VPCLMULQDQ.
                         1<<22 | // RDPID
@@ -460,7 +461,7 @@ void my_cpuid(x64emu_t* emu, uint32_t tmp32u)
             } else {
                 //L3 Cache
                 switch(R_ECX) {
-                    case 0: 
+                    case 0:
                         R_EAX = 0;
                         R_EBX = 0; // maximum range of RMID of physical processor
                         R_ECX = 0;
@@ -543,8 +544,8 @@ void my_cpuid(x64emu_t* emu, uint32_t tmp32u)
                         //| 1<<10     // IBS
                         //| 1<<11     // XOP
                         //| 1<<16     // FMA4
-                        ; 
-                R_EDX =   1         // fpu 
+                        ;
+                R_EDX =   1         // fpu
                         | 1<<2      // debugging extension
                         | 1<<3      // pse
                         | 1<<4      // rdtsc
@@ -573,11 +574,11 @@ void my_cpuid(x64emu_t* emu, uint32_t tmp32u)
             } else {
                 R_EAX = 0;  // reserved
                 R_EBX = 0;  // reserved
-                R_ECX = (1<<0)  // LAHF_LM 
+                R_ECX = (1<<0)  // LAHF_LM
                     | (1<<5)    // LZCNT
                     | (1<<8)   // PREFETCHW
                     ;
-                R_EDX = 1       // x87 FPU 
+                R_EDX = 1       // x87 FPU
                     | (1<<8)    // cx8: cmpxchg8b opcode
                     | (1<<11)   // syscall
                     | (1<<15)   // cmov: FCMOV opcodes
@@ -605,7 +606,7 @@ void my_cpuid(x64emu_t* emu, uint32_t tmp32u)
             R_EBX = ((uint32_t*)branding)[9];
             R_ECX = ((uint32_t*)branding)[10];
             R_EDX = ((uint32_t*)branding)[11];
-            break;  
+            break;
         case 0x80000005:
             if(BOX64ENV(cputype)) {
                 //L1 cache and TLB
@@ -665,7 +666,7 @@ void my_cpuid(x64emu_t* emu, uint32_t tmp32u)
             break;
         case 0x8000000a:
             if(BOX64ENV(cputype)) {
-                // SVM Revision and Feature Identification 
+                // SVM Revision and Feature Identification
                 R_EAX = 0;
                 R_EBX = 0;
                 R_ECX = 0;
@@ -706,7 +707,7 @@ void my_cpuid(x64emu_t* emu, uint32_t tmp32u)
             R_EBX = 0;
             R_ECX = 0;
             R_EDX = 0;
-    }   
+    }
 }
 
 uint32_t helper_getcpu(x64emu_t* emu) {
diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c
index 20ced661..3d8d3e67 100644
--- a/src/wrapped/wrappedlibc.c
+++ b/src/wrapped/wrappedlibc.c
@@ -68,6 +68,7 @@
 #include "globalsymbols.h"
 #include "env.h"
 #include "wine_tools.h"
+#include "cleanup.h"
 #ifndef LOG_INFO
 #define LOG_INFO 1
 #endif
@@ -1782,9 +1783,9 @@ void CreateCPUInfoFile(int fd)
         sprintf(buff, "bogomips\t: %g\n", getBogoMips());
         P;
         sprintf(buff, "flags\t\t: fpu cx8 sep ht cmov clflush mmx sse sse2 syscall tsc lahf_lm ssse3 ht tm lm fxsr cpuid pclmulqdq cx16 aes movbe pni "\
-                      "sse4_1%s%s%s lzcnt popcnt%s%s%s%s%s%s%s%s%s\n", 
-                      BOX64ENV(sse42)?" sse4_2":"", BOX64ENV(avx)?" avx":"", BOX64ENV(shaext)?"sha_ni":"", 
-                      BOX64ENV(avx)?" bmi1":"", BOX64ENV(avx2)?" avx2":"", BOX64ENV(avx)?" bmi2":"", 
+                      "sse4_1%s%s%s lzcnt popcnt%s%s%s%s%s%s%s%s%s\n",
+                      BOX64ENV(sse42)?" sse4_2":"", BOX64ENV(avx)?" avx":"", BOX64ENV(shaext)?"sha_ni":"",
+                      BOX64ENV(avx)?" bmi1":"", BOX64ENV(avx2)?" avx2":"", BOX64ENV(avx)?" bmi2":"",
                       BOX64ENV(avx2)?" vaes":"", BOX64ENV(avx2)?" fma":"",
                       BOX64ENV(avx)?" xsave":"", BOX64ENV(avx)?" f16c":"", BOX64ENV(avx2)?" randr":"",
                       BOX64ENV(avx2)?" adx":""
diff --git a/src/wrapped32/wrappedlibc.c b/src/wrapped32/wrappedlibc.c
index c4b9f684..6c01e369 100755
--- a/src/wrapped32/wrappedlibc.c
+++ b/src/wrapped32/wrappedlibc.c
@@ -68,6 +68,7 @@
 #include "globalsymbols.h"
 #include "box32.h"
 #include "converter32.h"
+#include "cleanup.h"
 
 // need to undef all read / read64 stuffs!
 #undef pread
@@ -498,8 +499,8 @@ EXPORT int my32_fstatvfs(x64emu_t* emu, int fd, void* r)
 #ifdef ANDROID
 void my32___libc_init(x64emu_t* emu, void* raw_args , void (*onexit)(void) , int (*main)(int, char**, char**), void const * const structors );
 #else
-int32_t my32___libc_start_main(x64emu_t* emu, int *(main) (int, char * *, char * *), 
-    int argc, char * * ubp_av, void (*init) (void), void (*fini) (void), 
+int32_t my32___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 x64run_private.c
 #endif
 
@@ -586,7 +587,7 @@ pid_t EXPORT my32_fork(x64emu_t* emu)
     if(v<0) {
         printf_log(LOG_NONE, "BOX32: Warning, fork errored... (%d)\n", v);
         // error...
-    } else if(v>0) {  
+    } else if(v>0) {
         // execute atforks parent functions
         for (int i=0; i<my_context->atfork_sz; --i)
             if(my_context->atforks[i].parent)
@@ -1540,7 +1541,7 @@ EXPORT ssize_t my32_read(int fd, void* buf, size_t count)
             unprotectDB((uintptr_t)p, count-ret, 1);
             int l;
             do {
-                l = read(fd, p, count-ret); 
+                l = read(fd, p, count-ret);
                 if(l>0) {
                     p+=l; ret+=l;
                 }
@@ -2003,7 +2004,7 @@ EXPORT int my32_posix_spawn_file_actions_destroy(x64emu_t* emu, posix_spawn_file
     return ret;
 }
 
-EXPORT int32_t my32_posix_spawn(x64emu_t* emu, pid_t* pid, const char* fullpath, 
+EXPORT int32_t my32_posix_spawn(x64emu_t* emu, pid_t* pid, const char* fullpath,
     posix_spawn_file_actions_32_t *actions_s, const posix_spawnattr_t* attrp,  ptr_t const argv[], ptr_t const envp[])
 {
     posix_spawn_file_actions_t actions_l = {0};
@@ -2052,7 +2053,7 @@ EXPORT int32_t my32_posix_spawn(x64emu_t* emu, pid_t* pid, const char* fullpath,
     return posix_spawn(pid, fullpath, actions, attrp, newargv, newenvp);
 }
 
-EXPORT int32_t my32_posix_spawnp(x64emu_t* emu, pid_t* pid, const char* path, 
+EXPORT int32_t my32_posix_spawnp(x64emu_t* emu, pid_t* pid, const char* path,
     posix_spawn_file_actions_32_t *actions_s, const posix_spawnattr_t* attrp,  ptr_t const argv[], ptr_t const envp[])
 {
     posix_spawn_file_actions_t actions_l = {0};
@@ -2457,8 +2458,8 @@ EXPORT int32_t my32_fcntl(x64emu_t* emu, int32_t a, int32_t b, uint32_t d1, uint
     int ret = fcntl(a, b, d1);
     if(b==F_GETFL && ret!=-1)
         ret = of_unconvert32(ret);
-    
-    return ret;    
+
+    return ret;
 }
 EXPORT int32_t my32___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("my32_fcntl")));
 #if 0
@@ -2685,10 +2686,10 @@ void InitCpuModel()
     my32___cpu_model.__cpu_vendor = VENDOR_INTEL;
     my32___cpu_model.__cpu_type = INTEL_PENTIUM_M;
     my32___cpu_model.__cpu_subtype = 0; // N/A
-    my32___cpu_model.__cpu_features[0] = (1<<FEATURE_CMOV) 
-                                     | (1<<FEATURE_MMX) 
-                                     | (1<<FEATURE_SSE) 
-                                     | (1<<FEATURE_SSE2) 
+    my32___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)