diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2025-06-19 11:07:21 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2025-06-19 11:07:30 +0200 |
| commit | 725316a5386eb713438625220b561bcd3710c8bc (patch) | |
| tree | 3535222fdd3ec0c8b601df98006fa1736e9fb047 /src/tools/env.c | |
| parent | cc9ed708379b9b03e7a9b86f040f06f178606aef (diff) | |
| download | box64-725316a5386eb713438625220b561bcd3710c8bc.tar.gz box64-725316a5386eb713438625220b561bcd3710c8bc.zip | |
[DYNACACHE] Introduced DynaCache for ARM64 (disabled by default)
Diffstat (limited to 'src/tools/env.c')
| -rw-r--r-- | src/tools/env.c | 587 |
1 files changed, 581 insertions, 6 deletions
diff --git a/src/tools/env.c b/src/tools/env.c index b279a988..ec9da3c8 100644 --- a/src/tools/env.c +++ b/src/tools/env.c @@ -5,6 +5,10 @@ #include <fcntl.h> #include <string.h> #include <inttypes.h> +#if defined(DYNAREC) && !defined(WIN32) +#include <sys/types.h> +#include <dirent.h> +#endif #include "os.h" #include "env.h" @@ -24,6 +28,18 @@ static kh_box64env_entry_t* box64env_entries_gen = NULL; mmaplist_t* NewMmaplist(); void DelMmaplist(mmaplist_t* list); +#ifdef DYNAREC +int MmaplistHasNew(mmaplist_t* list, int clear); +int MmaplistIsDirty(mmaplist_t* list); +int MmaplistNBlocks(mmaplist_t* list); +size_t MmaplistTotalAlloc(mmaplist_t* list); +void MmaplistFillBlocks(mmaplist_t* list, DynaCacheBlock_t* blocks); +void MmaplistAddNBlocks(mmaplist_t* list, int nblocks); +int MmaplistAddBlock(mmaplist_t* list, int fd, off_t offset, void* orig, size_t size, intptr_t delta_map, uintptr_t mapping_start); +int nLockAddressRange(uintptr_t start, size_t size); +void getLockAddressRange(uintptr_t start, size_t size, uintptr_t addrs[]); +void addLockAddress(uintptr_t addr); +#endif static rbtree_t* envmap = NULL; @@ -658,6 +674,11 @@ typedef struct mapping_s { KHASH_MAP_INIT_STR(mapping_entry, mapping_t*); static kh_mapping_entry_t* mapping_entries = NULL; +#if defined(DYNAREC) && !defined(WIN32) +void MmapDynaCache(mapping_t* mapping); +#endif + + void RecordEnvMappings(uintptr_t addr, size_t length, int fd) { #ifndef _WIN32 @@ -698,6 +719,13 @@ void RecordEnvMappings(uintptr_t addr, size_t length, int fd) mapping->env = &kh_value(box64env_entries, k); } dynarec_log(LOG_INFO, "Mapping %s (%s) in %p-%p\n", fullname, lowercase_filename, (void*)addr, (void*)(addr+length)); + #if defined(DYNAREC) && !defined(WIN32) + int dynacache = box64env.dynacache; + if(mapping->env && mapping->env->is_dynacache_overridden) + dynacache = mapping->env->dynacache; + if(dynacache) + MmapDynaCache(mapping); + #endif } else mapping = kh_value(mapping_entries, k); @@ -722,6 +750,525 @@ void RecordEnvMappings(uintptr_t addr, size_t length, int fd) #endif } +#ifdef DYNAREC +const char* GetDynacacheFolder(mapping_t* mapping) +{ + if(mapping && mapping->env && mapping->env->is_dynacache_folder_overridden && mapping->env->dynacache_folder) { + if(FileExist(mapping->env->dynacache_folder, 0)) + return mapping->env->dynacache_folder; // folder exist + if(MakeDir(mapping->env->dynacache_folder)) + return mapping->env->dynacache_folder; + } + if(box64env.dynacache_folder) { + if(FileExist(box64env.dynacache_folder, 0)) + return box64env.dynacache_folder; // folder exist + if(MakeDir(box64env.dynacache_folder)) + return box64env.dynacache_folder; + } + static char folder[4096] = {0}; + static int default_folder = 0; + if(default_folder) + return folder; + if(GetEnv("XDG_CACHE_HOME")) + strcpy(folder, GetEnv("XDG_CACHE_HOME")); + else if(GetEnv(HOME)) { + strcpy(folder, GetEnv(HOME)); + strcat(folder, PATHSEP); + strcat(folder, ".cache"); + if(!FileExist(folder, 0)) + if(!MakeDir(folder)) + return NULL; + } + else return NULL; + strcat(folder, PATHSEP); + strcat(folder, "box64"); + if(!FileExist(folder, 0)) + if(!MakeDir(folder)) + return NULL; + strcat(folder, PATHSEP); + return folder; +} + +/* + There is 3 version to change when evoling things, depending on what is changed:actual_malloc_usable_size + 1. FILE_VERSION for the DynaCache infrastructure + 2. DYNAREC_VERSION for dynablock_t changes and other global dynarec change + 3. ARCH_VERSION for the architecture specific changes (and there is one per arch) + + An ARCH_VERSION of 0 means Unsupported and disable DynaCache. + Dynacache will ignore any DynaCache file not exactly matching those 3 version. + `box64 --dynacache-clean` can be used from command line to purge obsolete DyaCache files +*/ + +#define HEADER_VERSION 1 +#define HEADER_SIGN "DynaCache" +#define SET_VERSION(MAJ, MIN, REV) (((MAJ)<<24)|((MIN)<<16)|(REV)) +#ifdef ARM64 +#define ARCH_VERSION SET_VERSION(0, 0, 1) +#elif defined(RV64) +#define ARCH_VERSION SET_VERSION(0, 0, 0) +#elif defined(LA64) +#define ARCH_VERSION SET_VERSION(0, 0, 0) +#else +#error meh! +#endif +#define DYNAREC_VERSION SET_VERSION(0, 0, 1) + +typedef struct DynaCacheHeader_s { + char sign[10]; //"DynaCache\0" + uint64_t file_version:16; + uint64_t dynarec_version:24; + uint64_t arch_version:24; + uint64_t cpuext; + uint64_t dynarec_settings; + size_t pagesize; + size_t codesize; + uintptr_t map_addr; + size_t map_len; + size_t file_length; + uint32_t filename_length; + uint32_t nblocks; + uint32_t nLockAddresses; + char filename[]; +} DynaCacheHeader_t; + +#define DYNAREC_SETTINGS() \ + DS_GO(BOX64_DYNAREC_ALIGNED_ATOMICS, dynarec_aligned_atomics, 1) \ + DS_GO(BOX64_DYNAREC_BIGBLOCK, dynarec_bigblock, 2) \ + DS_GO(BOX64_DYNAREC_CALLRET, dynarec_callret, 2) \ + DS_GO(BOX64_DYNAREC_DF, dynarec_df, 1) \ + DS_GO(BOX64_DYNAREC_DIRTY, dynarec_dirty, 2) \ + DS_GO(BOX64_DYNAREC_DIV0, dynarec_div0, 1) \ + DS_GO(BOX64_DYNAREC_FASTNAN, dynarec_fastnan, 1) \ + DS_GO(BOX64_DYNAREC_FASTROUND, dynarec_fastround, 2) \ + DS_GO(BOX64_DYNAREC_FORWARD, dynarec_forward, 10) \ + DS_GO(BOX64_DYNAREC_NATIVEFLAGS, dynarec_nativeflags, 1) \ + DS_GO(BOX64_DYNAREC_SAFEFLAGS, dynarec_safeflags, 2) \ + DS_GO(BOX64_DYNAREC_STRONGMEM, dynarec_strongmem, 2) \ + DS_GO(BOX64_DYNAREC_VOLATILE_METADATA, dynarec_volatile_metadata, 1)\ + DS_GO(BOX64_DYNAREC_WEAKBARRIER, dynarec_weakbarrier, 2) \ + DS_GO(BOX64_DYNAREC_X87DOUBLE, dynarec_x87double, 2) \ + DS_GO(BOX64_SHAEXT, shaext, 1) \ + DS_GO(BOX64_SSE42, sse42, 1) \ + DS_GO(BOX64_AVX, avx, 2) \ + DS_GO(BOX64_X87_NO80BITS, x87_no80bits, 1) \ + DS_GO(BOX64_RDTSC_1GHZ, rdtsc_1ghz, 1) \ + DS_GO(BOX64_SSE_FLUSHTO0, sse_flushto0, 1) \ + +#define DS_GO(A, B, C) uint64_t B:C; +typedef union dynarec_settings_s { + struct { + DYNAREC_SETTINGS() + }; + uint64_t x; +} dynarec_settings_t; +#undef DS_GO +uint64_t GetDynSetting(mapping_t* mapping) +{ + dynarec_settings_t settings = {0}; + #define DS_GO(A, B, C) settings.B = (mapping->env && mapping->env->is_##B##_overridden)?mapping->env->B:box64env.B; + DYNAREC_SETTINGS() + #undef DS_GO + return settings.x; +} +void PrintDynfSettings(int level, uint64_t s) +{ + dynarec_settings_t settings = {0}; + settings.x = s; + #define DS_GO(A, B, C) if(settings.B) printf_log_prefix(0, level, "\t\t" #A "=%d\n", settings.B); + DYNAREC_SETTINGS() + #undef DS_GO +} +#undef DYNAREC_SETTINGS + +char* MmaplistName(const char* filename, uint64_t dynarec_settings, const char* fullname) +{ + // names are FOLDER/filename-YYYYY-XXXXX.box64 + // Where XXXXX is the hash of the full name + // and YYYY is the Dynarec optim (in hex) + static char mapname[4096]; + snprintf(mapname, 4095-6, "%s-%llx-%u", filename, dynarec_settings, __ac_X31_hash_string(fullname)); + strcat(mapname, ".box64"); + return mapname; +} + +char* GetMmaplistName(mapping_t* mapping) +{ + return MmaplistName(mapping->filename+1, GetDynSetting(mapping), mapping->fullname); +} + +const char* NicePrintSize(size_t sz) +{ + static char buf[256]; + const char* units[] = {"", "kb", "Mb", "Gb"}; + size_t u, d; + int idx = 0; + size_t ratio = 0; + while(idx<sizeof(units)/sizeof(units[0]) && (1<<(ratio+10))<sz) { + ratio+=10; + ++idx; + } + if(ratio && (sz>>ratio)<50) { + snprintf(buf, 255, "%zd.%zd%s", sz>>ratio, (sz>>(ratio-1))%10, units[idx]); + } else { + snprintf(buf, 255, "%zd%s", sz>>ratio, units[idx]); + } + return buf; +} + +void SerializeMmaplist(mapping_t* mapping) +{ + if(!DYNAREC_VERSION) + return; + if(!box64env.dynacache) + return; + if(mapping->env && mapping->env->is_dynacache_overridden && !mapping->env->dynacache) + return; + const char* folder = GetDynacacheFolder(mapping); + if(!folder) return; // no folder, no serialize... + const char* name = GetMmaplistName(mapping); + if(!name) return; + char mapname[strlen(folder)+strlen(name)+1]; + strcpy(mapname, folder); + strcat(mapname, name); + size_t filesize = FileSize(mapping->fullname); + if(!filesize) { + dynarec_log(LOG_INFO, "DynaCache will not serialize cache for %s because filesize is 0\n", mapping->fullname); + return; // mmaped file as a 0 size... + } + // prepare header + int nblocks = MmaplistNBlocks(mapping->mmaplist); + if(!nblocks) { + dynarec_log(LOG_INFO, "DynaCache will not serialize cache for %s because nblocks is 0\n", mapping->fullname); + return; //How??? + } + size_t map_len = SizeFileMapped(mapping->start); + size_t nLockAddresses = nLockAddressRange(mapping->start, map_len); + size_t total = sizeof(DynaCacheHeader_t) + strlen(mapping->fullname) + 1 + nblocks*sizeof(DynaCacheBlock_t) + nLockAddresses*sizeof(uintptr_t); + total = (total + box64_pagesize-1)&~(box64_pagesize-1); // align on pagesize + uint8_t all_header[total]; + memset(all_header, 0, total); + void* p = all_header; + DynaCacheHeader_t* header = p; + strcpy(header->sign, HEADER_SIGN); + header->file_version = HEADER_VERSION; + header->dynarec_version = DYNAREC_VERSION; + header->arch_version = ARCH_VERSION; + header->dynarec_settings = GetDynSetting(mapping); + header->cpuext = cpuext.x; + header->pagesize = box64_pagesize; + header->codesize = MmaplistTotalAlloc(mapping->mmaplist); + header->map_addr = mapping->start; + header->file_length = filesize; + header->filename_length = strlen(mapping->fullname); + header->nblocks = MmaplistNBlocks(mapping->mmaplist); + header->map_len = map_len; + header->nLockAddresses = nLockAddresses; + size_t dynacache_min = box64env.dynacache_min; + if(mapping->env && mapping->env->is_dynacache_min_overridden) + dynacache_min = mapping->env->dynacache_min; + if(dynacache_min*1024>header->codesize) { + dynarec_log(LOG_INFO, "DynaCache will not serialize cache for %s because there is not enough usefull code (%s)\n", mapping->fullname, NicePrintSize(header->codesize)); + return; // not enugh code, do no write + } + p += sizeof(DynaCacheHeader_t); // fullname + strcpy(p, mapping->fullname); + p += strlen(p) + 1; // blocks + DynaCacheBlock_t* blocks = p; + MmaplistFillBlocks(mapping->mmaplist, blocks); + p += nblocks*sizeof(DynaCacheBlock_t); + uintptr_t* lockAddresses = p; + getLockAddressRange(mapping->start, map_len, lockAddresses); + // all done, now just create the file and write all this down... + #ifndef WIN32 + unlink(mapname); + FILE* f = fopen(mapname, "wbx"); + if(!f) { + dynarec_log(LOG_INFO, "Cannot create cache file %s\n", mapname); + return; + } + if(fwrite(all_header, total, 1, f)!=1) { + dynarec_log(LOG_INFO, "Error writing Cache file (disk full?)\n"); + return; + } + for(int i=0; i<nblocks; ++i) { + if(fwrite(blocks[i].block, blocks[i].size, 1, f)!=1) { + dynarec_log(LOG_INFO, "Error writing Cache file (disk full?)\n"); + return; + } + } + fclose(f); + #else + // TODO? + #endif +} + +#define DCERR_OK 0 +#define DCERR_NEXIST 1 +#define DCERR_TOOSMALL 2 +#define DCERR_FERROR 3 +#define DCERR_BADHEADER 4 +#define DCERR_FILEVER 5 +#define DCERR_DYNVER 6 +#define DCERR_DYNARCHVER 7 +#define DCERR_PAGESIZE 8 +#define DCERR_MAPNEXIST 9 +#define DCERR_MAPCHG 10 +#define DCERR_RELOC 11 +#define DCERR_BADNAME 12 + +#ifndef WIN32 +int ReadDynaCache(const char* folder, const char* name, mapping_t* mapping, int verbose) +{ + char filename[strlen(folder)+strlen(name)+1]; + strcpy(filename, folder); + strcat(filename, name); + if(verbose) printf_log(LOG_NONE, "File %s:\t", name); + if(!FileExist(filename, IS_FILE)) { + if(verbose) printf_log_prefix(0, LOG_NONE, "Invalid file\n"); + return DCERR_NEXIST; + } + size_t filesize = FileSize(filename); + if(filesize<sizeof(DynaCacheHeader_t)) { + if(verbose) printf_log_prefix(0, LOG_NONE, "Invalid side: %zd\n", filesize); + return DCERR_TOOSMALL; + } + FILE *f = fopen(filename, "rb"); + if(!f) { + if(verbose) printf_log_prefix(0, LOG_NONE, "Cannot open file\n"); + return DCERR_FERROR; + } + DynaCacheHeader_t header = {0}; + if(fread(&header, sizeof(header), 1, f)!=1) { + if(verbose) printf_log_prefix(0, LOG_NONE, "Cannot read header\n"); + fclose(f); + return DCERR_FERROR; + } + if(strcmp(header.sign, HEADER_SIGN)) { + if(verbose) printf_log_prefix(0, LOG_NONE, "Bad header\n"); + fclose(f); + return DCERR_BADHEADER; + } + if(header.file_version!=HEADER_VERSION) { + if(verbose) printf_log_prefix(0, LOG_NONE, "Incompatible File Version\n"); + fclose(f); + return DCERR_FILEVER; + } + if(header.dynarec_version!=DYNAREC_VERSION) { + if(verbose) printf_log_prefix(0, LOG_NONE, "Incompatible Dynarec Version\n"); + fclose(f); + return DCERR_DYNVER; + } + if(header.arch_version!=ARCH_VERSION) { + if(verbose) printf_log_prefix(0, LOG_NONE, "Incompatible Dynarec Arch Version\n"); + fclose(f); + return DCERR_DYNARCHVER; + } + if(header.arch_version!=ARCH_VERSION) { + if(verbose) printf_log_prefix(0, LOG_NONE, "Incompatible Dynarec Arch Version\n"); + fclose(f); + return DCERR_DYNVER; + } + if(header.pagesize!=box64_pagesize) { + if(verbose) printf_log_prefix(0, LOG_NONE, "Bad pagesize\n"); + fclose(f); + return DCERR_PAGESIZE; + } + char map_filename[header.filename_length+1]; + if(fread(map_filename, header.filename_length+1, 1, f)!=1) { + if(verbose) printf_log_prefix(0, LOG_NONE, "Cannot read filename\n"); + fclose(f); + return DCERR_FERROR; + } + if(!FileExist(map_filename, IS_FILE)) { + if(verbose) printf_log_prefix(0, LOG_NONE, "Mapfiled does not exists\n"); + fclose(f); + return DCERR_MAPNEXIST; + } + if(FileSize(map_filename)!=header.file_length) { + if(verbose) printf_log_prefix(0, LOG_NONE, "File changed\n"); + fclose(f); + return DCERR_MAPCHG; + } + DynaCacheBlock_t blocks[header.nblocks]; + if(fread(blocks, sizeof(DynaCacheBlock_t), header.nblocks, f)!=header.nblocks) { + if(verbose) printf_log_prefix(0, LOG_NONE, "Cannot read blocks\n"); + fclose(f); + return DCERR_FERROR; + } + uintptr_t lockAddresses[header.nLockAddresses]; + if(fread(lockAddresses, sizeof(uintptr_t), header.nLockAddresses, f)!=header.nLockAddresses) { + if(verbose) printf_log_prefix(0, LOG_NONE, "Cannot read lockAddresses\n"); + fclose(f); + return DCERR_FERROR; + } + off_t p = ftell(f); + p = (p+box64_pagesize-1)&~(box64_pagesize-1); + if(fseek(f, p, SEEK_SET)<0) { + if(verbose) printf_log_prefix(0, LOG_NONE, "Error reading a block\n"); + fclose(f); + return DCERR_FERROR; + } + if(!mapping) { + // check the blocks can be read without reading... + for(int i=0; i<header.nblocks; ++i) { + p+=blocks[i].size; + if(fseek(f, blocks[i].size, SEEK_CUR)<0 || ftell(f)!=p) { + if(verbose) printf_log_prefix(0, LOG_NONE, "Error reading a block\n"); + fclose(f); + return DCERR_FERROR; + } + } + char* short_name = strrchr(map_filename, '/'); + if(short_name) + ++short_name; + else + short_name = map_filename; + short_name = LowerCase(short_name); + const char* file_name = MmaplistName(short_name, header.dynarec_settings, map_filename); + box_free(short_name); + if(strcmp(file_name, name)) { + if(verbose) printf_log_prefix(0, LOG_NONE, "Invalid cache name\n"); + return DCERR_BADNAME; + } + if(verbose) { + // check if name is coherent + // file is valid, gives informations: + printf_log_prefix(0, LOG_NONE, "%s (%s)\n", map_filename, NicePrintSize(filesize)); + printf_log_prefix(0, LOG_NONE, "\tDynarec Settings:\n"); + PrintDynfSettings(LOG_NONE, header.dynarec_settings); + size_t total_blocks = 0, total_free = 0; + size_t total_code = header.codesize; + for(int i=0; i<header.nblocks; ++i) { + total_blocks += blocks[i].size; + total_free += blocks[i].free_size; + } + printf_log_prefix(0, LOG_NONE, "\tHas %d blocks for a total of %s", header.nblocks, NicePrintSize(total_blocks)); + printf_log_prefix(0, LOG_NONE, " with %s still free", NicePrintSize(total_free)); + printf_log_prefix(0, LOG_NONE, " and %s non-canceled blocks (mapped at %p-%p, with %zu lock addresses)\n", NicePrintSize(total_code), (void*)header.map_addr, (void*)header.map_addr+header.map_len, header.nLockAddresses); + } + } else { + // actually reading! + int fd = fileno(f); + intptr_t delta_map = mapping->start - header.map_addr; + dynarec_log(LOG_INFO, "Trying to load DynaCache for %s, with a delta_map=%zx\n", mapping->fullname, delta_map); + if(!mapping->mmaplist) + mapping->mmaplist = NewMmaplist(); + MmaplistAddNBlocks(mapping->mmaplist, header.nblocks); + for(int i=0; i<header.nblocks; ++i) { + if(MmaplistAddBlock(mapping->mmaplist, fd, p, blocks[i].block, blocks[i].size, delta_map, mapping->start)) { + printf_log(LOG_NONE, "Error while doing relocation on a DynaCache (block %d)\n", i); + fclose(f); + return DCERR_RELOC; + } + p+=blocks[i].size; + } + for(size_t i=0; i<header.nLockAddresses; ++i) + addLockAddress(lockAddresses[i]+delta_map); + dynarec_log(LOG_INFO, "Loaded DynaCache for %s, with %d blocks\n", mapping->fullname, header.nblocks); + } + fclose(f); + return DCERR_OK; +} +#endif + +void DynaCacheList(const char* filter) +{ + #ifndef WIN32 + const char* folder = GetDynacacheFolder(NULL); + if(!folder) { + printf_log(LOG_NONE, "DynaCache folder not found\n"); + return; + } + DIR* dir = opendir(folder); + if(!dir) { + printf_log(LOG_NONE, "Cannot open DynaCache folder\n"); + } + struct dirent* d = NULL; + int need_filter = (filter && strlen(filter)); + while(d = readdir(dir)) { + size_t l = strlen(d->d_name); + if(l>6 && !strcmp(d->d_name+l-6, ".box64")) { + if(need_filter && !strstr(d->d_name, filter)) + continue; + ReadDynaCache(folder, d->d_name, NULL, 1); + printf_log_prefix(0, LOG_NONE, "\n"); + } + } + closedir(dir); + #endif +} +void DynaCacheClean() +{ + #ifndef WIN32 + const char* folder = GetDynacacheFolder(NULL); + if(!folder) { + printf_log(LOG_NONE, "DynaCache folder not found\n"); + return; + } + DIR* dir = opendir(folder); + if(!dir) { + printf_log(LOG_NONE, "Cannot open DynaCache folder\n"); + } + struct dirent* d = NULL; + while(d = readdir(dir)) { + size_t l = strlen(d->d_name); + if(l>6 && !strcmp(d->d_name+l-6, ".box64")) { + int ret = ReadDynaCache(folder, d->d_name, NULL, 0); + if(ret) { + char filename[strlen(folder)+strlen(d->d_name)+1]; + strcpy(filename, folder); + strcat(filename, d->d_name); + size_t filesize = FileSize(filename); + if(!unlink(filename)) { + printf_log(LOG_NONE, "Removed %s for %s\n", d->d_name, NicePrintSize(filesize)); + } else { + printf_log(LOG_NONE, "Could not remove %d\n", d->d_name); + } + } + } + } + closedir(dir); + #endif +} +#ifndef WIN32 +void MmapDynaCache(mapping_t* mapping) +{ + if(!DYNAREC_VERSION) + return; + if(!box64env.dynacache) + return; + if(mapping->env && mapping->env->is_dynacache_overridden && !mapping->env->dynacache) + return; + const char* folder = GetDynacacheFolder(mapping); + if(!folder) return; + const char* name = GetMmaplistName(mapping); + if(!name) return; + dynarec_log(LOG_DEBUG, "Looking for DynaCache %s in %s\n", name, folder); + ReadDynaCache(folder, name, mapping, 0); +} +#endif +#else +void SerializeMmaplist(mapping_t* mapping) {} +void DynaCacheList() { printf_log(LOG_NONE, "Dynarec not enable\n"); } +void DynaCacheClean() {} +#endif + +void WillRemoveMapping(uintptr_t addr, size_t length) +{ + #ifdef DYNAREC + if(!envmap) return; + mapping_t* mapping = (mapping_t*)rb_get_64(envmap, addr); + if(mapping) { + if(MmaplistHasNew(mapping->mmaplist, 1)) { + mutex_lock(&my_context->mutex_dyndump); + SerializeMmaplist(mapping); + mutex_unlock(&my_context->mutex_dyndump); + } + } + #endif +} + void RemoveMapping(uintptr_t addr, size_t length) { if(!envmap) return; @@ -756,6 +1303,19 @@ void RemoveMapping(uintptr_t addr, size_t length) } } +void SerializeAllMapping() +{ +#ifdef DYNAREC + mapping_t* mapping; + mutex_lock(&my_context->mutex_dyndump); + kh_foreach_value(mapping_entries, mapping, + if(MmaplistHasNew(mapping->mmaplist, 1)) + SerializeMmaplist(mapping); + ); + mutex_unlock(&my_context->mutex_dyndump); +#endif +} + box64env_t* GetCurEnvByAddr(uintptr_t addr) { if (!envmap) return &box64env; @@ -811,17 +1371,32 @@ size_t SizeFileMapped(uintptr_t addr) int IsAddrNeedReloc(uintptr_t addr) { box64env_t* env = GetCurEnvByAddr(addr); - if(env->nodynarec) - return 0; - if(!env->dynacache) + // TODO: this seems quite wrong and should be refactored + int test = env->is_dynacache_overridden?env->dynacache:box64env.dynacache; + if(!test) return 0; - if(env->nodynarec_end && addr>=env->nodynarec_start && addr<env->nodynarec_end) + uintptr_t end = env->nodynarec_end?env->nodynarec_end:box64env.nodynarec_end; + uintptr_t start = env->nodynarec_start?env->nodynarec_start:box64env.nodynarec_start; + if(end && addr>=start && addr<end) return 0; #ifdef HAVE_TRACE - if(env->dynarec_test_end && addr>=env->dynarec_test_start && addr<env->dynarec_test_end) + end = env->dynarec_test_end?env->dynarec_test_end:box64env.dynarec_test_end; + start = env->dynarec_test_start?env->dynarec_test_start:box64env.dynarec_test_start; + if(end && addr>=start && addr<end) return 0; - if(env->dynarec_trace && trace_end && addr>=trace_start && addr<trace_end) + test = env->is_dynarec_trace_overridden?env->dynarec_trace:box64env.dynarec_trace; + if(test && trace_end && addr>=trace_start && addr<trace_end) return 0; #endif return 1; +} + +int IsAddrMappingLoadAndClean(uintptr_t addr) +{ + if(!envmap) return 0; + mapping_t* mapping = ((mapping_t*)rb_get_64(envmap, addr)); + if(!mapping) return 0; + if(!mapping->mmaplist) return 0; + if(MmaplistIsDirty(mapping->mmaplist)) return 0; + return 1; } \ No newline at end of file |