diff options
| author | Yang Liu <liuyang22@iscas.ac.cn> | 2025-04-11 18:26:51 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-04-11 12:26:51 +0200 |
| commit | 6c46e3d9b15be3e5c6227bb97fd542a4100ec4d2 (patch) | |
| tree | bf7552c358c240e44e53c176db44bad11a415de3 /src | |
| parent | fa85d4d900c3e03b69bdea65204b51151fc62114 (diff) | |
| download | box64-6c46e3d9b15be3e5c6227bb97fd542a4100ec4d2.tar.gz box64-6c46e3d9b15be3e5c6227bb97fd542a4100ec4d2.zip | |
[WOW64] Splitted freq and cleanup functions from x64emu (#2521)
Diffstat (limited to 'src')
| -rw-r--r-- | src/core.c | 2 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_0f.c | 4 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_0f.c | 2 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_0f.c | 2 | ||||
| -rw-r--r-- | src/elfs/elfloader.c | 45 | ||||
| -rw-r--r-- | src/emu/x64emu.c | 200 | ||||
| -rw-r--r-- | src/emu/x64run0f.c | 1 | ||||
| -rw-r--r-- | src/emu/x64run_private.c | 2 | ||||
| -rw-r--r-- | src/include/cleanup.h | 13 | ||||
| -rw-r--r-- | src/include/freq.h | 9 | ||||
| -rw-r--r-- | src/include/x64emu.h | 7 | ||||
| -rw-r--r-- | src/os/freq_linux.c | 137 | ||||
| -rw-r--r-- | src/os/freq_wine.c | 17 | ||||
| -rw-r--r-- | src/tools/cleanup.c | 68 | ||||
| -rw-r--r-- | src/tools/my_cpuid.c | 33 | ||||
| -rw-r--r-- | src/wrapped/wrappedlibc.c | 7 | ||||
| -rwxr-xr-x | src/wrapped32/wrappedlibc.c | 25 |
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) |