From b9bc04c331e0776e135679bbce0dd4f51ef3efd5 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Thu, 8 May 2025 19:13:00 +0800 Subject: [PATCH 1/2] [ENV] Refactored file-mapping handling --- src/tools/env.c | 6 ++++ src/tools/pe_tools.c | 75 +++++++++++++-------------------------- src/tools/wine_tools.c | 16 ++++----- src/wrapped/wrappedlibc.c | 12 +------ 4 files changed, 38 insertions(+), 71 deletions(-) diff --git a/src/tools/env.c b/src/tools/env.c index c21a368790..21fc08f5ac 100644 --- a/src/tools/env.c +++ b/src/tools/env.c @@ -13,6 +13,8 @@ #include "fileutils.h" #include "box64context.h" #include "rbtree.h" +#include "wine_tools.h" +#include "pe_tools.h" box64env_t box64env = { 0 }; @@ -614,6 +616,10 @@ void RecordEnvMappings(uintptr_t addr, size_t length, int fd) mapping_t* mapping = NULL; khint_t k = kh_get(mapping_entry, mapping_entries, lowercase_filename); if(k == kh_end(mapping_entries)) { + // First time we see this file + if (box64_wine && BOX64ENV(unityplayer)) DetectUnityPlayer(lowercase_filename); + if (box64_wine && BOX64ENV(dynarec_volatile_metadata)) ParseVolatileMetadata(fullname, (void*)addr); + mapping = box_calloc(1, sizeof(mapping_t)); mapping->filename = box_strdup(lowercase_filename); mapping->fullname = box_strdup(fullname); diff --git a/src/tools/pe_tools.c b/src/tools/pe_tools.c index 5d8bc2b432..6afee6c6ab 100644 --- a/src/tools/pe_tools.c +++ b/src/tools/pe_tools.c @@ -187,19 +187,9 @@ typedef struct _IMAGE_VOLATILE_RANGE_METADATA { KHASH_SET_INIT_STR(string); KHASH_SET_INIT_INT64(volatileopcode); -static kh_string_t* dllNames = NULL; // never freed static kh_volatileopcode_t* volatileOpcodes = NULL; // never freed - static rbtree_t* volatileRanges = NULL; // never freed -static int HasSuffix(const char* str, const char* suffix) -{ - size_t lenstr = strlen(str); - size_t lensuffix = strlen(suffix); - if (lensuffix > lenstr) return 0; - return strcmp(str + lenstr - lensuffix, suffix) == 0; -} - DWORD RVAToFileOffset(PIMAGE_SECTION_HEADER sections, DWORD numberOfSections, DWORD rva, BYTE* fileBuffer, size_t fileSize) { for (DWORD i = 0; i < numberOfSections; i++) { @@ -216,12 +206,6 @@ DWORD RVAToFileOffset(PIMAGE_SECTION_HEADER sections, DWORD numberOfSections, DW void ParseVolatileMetadata(char* filename, void* addr) { - if (!filename) return; - if (!HasSuffix(filename, ".dll")) { - return; - } - - if (!dllNames) dllNames = kh_init(string); if (!volatileOpcodes) volatileOpcodes = kh_init(volatileopcode); if (!volatileRanges) volatileRanges = rbtree_init("volatileRanges"); @@ -231,14 +215,31 @@ void ParseVolatileMetadata(char* filename, void* addr) else baseName++; - khint_t k = kh_get(string, dllNames, baseName); - if (k != kh_end(dllNames)) return; + IMAGE_DOS_HEADER* dosHeader = (IMAGE_DOS_HEADER*)addr; + if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) return; + + PIMAGE_NT_HEADERS64 ntHeaders64 = (PIMAGE_NT_HEADERS64)(addr + dosHeader->e_lfanew); + if (ntHeaders64->Signature != IMAGE_NT_SIGNATURE || ntHeaders64->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) return; + + int numberOfSections = ntHeaders64->FileHeader.NumberOfSections; + if (numberOfSections <= 0) { + return; + } + IMAGE_DATA_DIRECTORY loadConfigDir = ntHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG]; + if (loadConfigDir.VirtualAddress == 0 || loadConfigDir.Size == 0) { + return; + } - int ret; - k = kh_put(string, dllNames, strdup(baseName), &ret); + PIMAGE_SECTION_HEADER sectionHeaders = (PIMAGE_SECTION_HEADER)((void*)ntHeaders64 + sizeof(IMAGE_NT_HEADERS64)); // immediately follows the optional header, if any. + DWORD loadConfigOffset = RVAToFileOffset(sectionHeaders, numberOfSections, loadConfigDir.VirtualAddress, (BYTE*)addr, ntHeaders64->OptionalHeader.SizeOfImage); + if (loadConfigOffset == 0) { + return; + } FILE* file = fopen(filename, "rb"); - if (!file) return; + if (!file) { + return; + } fseek(file, 0, SEEK_END); long size = ftell(file); @@ -257,36 +258,6 @@ void ParseVolatileMetadata(char* filename, void* addr) } fclose(file); - IMAGE_DOS_HEADER* dosHeader = (IMAGE_DOS_HEADER*)buffer; - if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) { - free(buffer); - return; - } - - PIMAGE_NT_HEADERS64 ntHeaders64 = (PIMAGE_NT_HEADERS64)(buffer + dosHeader->e_lfanew); - if (ntHeaders64->Signature != IMAGE_NT_SIGNATURE || ntHeaders64->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) { - free(buffer); - return; - } - - int numberOfSections = ntHeaders64->FileHeader.NumberOfSections; - if (numberOfSections <= 0) { - free(buffer); - return; - } - IMAGE_DATA_DIRECTORY loadConfigDir = ntHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG]; - if (loadConfigDir.VirtualAddress == 0 || loadConfigDir.Size == 0) { - free(buffer); - return; - } - - PIMAGE_SECTION_HEADER sectionHeaders = (PIMAGE_SECTION_HEADER)((void*)ntHeaders64 + sizeof(IMAGE_NT_HEADERS64)); // immediately follows the optional header, if any. - DWORD loadConfigOffset = RVAToFileOffset(sectionHeaders, numberOfSections, loadConfigDir.VirtualAddress, (BYTE*)buffer, ntHeaders64->OptionalHeader.SizeOfImage); - if (loadConfigOffset == 0) { - free(buffer); - return; - } - PIMAGE_LOAD_CONFIG_DIRECTORY64 loadConfig = (PIMAGE_LOAD_CONFIG_DIRECTORY64)(buffer + loadConfigOffset); if (loadConfig->Size < offsetof(IMAGE_LOAD_CONFIG_DIRECTORY64, VolatileMetadataPointer) + sizeof(ULONGLONG)) { free(buffer); @@ -342,6 +313,8 @@ void ParseVolatileMetadata(char* filename, void* addr) printf_log(LOG_DEBUG, "Volatile range metadata [%d]: %08lX-%08lX\n", i, rva, rva + size); } } + free(buffer); + return; } int VolatileRangesContains(uintptr_t addr) diff --git a/src/tools/wine_tools.c b/src/tools/wine_tools.c index 86a9159802..bde9505583 100644 --- a/src/tools/wine_tools.c +++ b/src/tools/wine_tools.c @@ -139,16 +139,14 @@ void dynarec_wine_prereserve() void DetectUnityPlayer(char* filename) { static int unityplayer_detected = 0; - if (!filename && BOX64ENV(unityplayer) && !unityplayer_detected) { - if (strlen(filename) > strlen("UnityPlayer.dll") && !strcasecmp(filename + strlen(filename) - strlen("UnityPlayer.dll"), "UnityPlayer.dll")) { - printf_log(LOG_NONE, "Detected UnityPlayer.dll\n"); + if (filename && BOX64ENV(unityplayer) && !unityplayer_detected && !strcasecmp(filename, "unityplayer.dll")) { + printf_log(LOG_NONE, "Detected UnityPlayer.dll\n"); #ifdef DYNAREC - if (!BOX64ENV(dynarec_strongmem)) { - SET_BOX64ENV(dynarec_strongmem, 1); - PrintEnvVariables(&box64env, LOG_INFO); - } -#endif - unityplayer_detected = 1; + if (!BOX64ENV(dynarec_strongmem)) { + SET_BOX64ENV(dynarec_strongmem, 1); + PrintEnvVariables(&box64env, LOG_INFO); } +#endif + unityplayer_detected = 1; } } diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c index fbfc9b2125..631b270c85 100644 --- a/src/wrapped/wrappedlibc.c +++ b/src/wrapped/wrappedlibc.c @@ -3032,17 +3032,7 @@ EXPORT void* my_mmap64(x64emu_t* emu, void *addr, size_t length, int prot, int f } #endif if(ret!=MAP_FAILED) { - if(emu && !(flags&MAP_ANONYMOUS) && (fd>0)) { - if ((box64_wine && BOX64ENV(dynarec_volatile_metadata)) || BOX64ENV(unityplayer)) { - char filename[4096]; - char buf[128]; - sprintf(buf, "/proc/self/fd/%d", fd); - ssize_t r = readlink(buf, filename, sizeof(filename) - 1); - if (r != -1) filename[r] = 0; - - if (BOX64ENV(unityplayer)) DetectUnityPlayer(filename); - if (box64_wine && BOX64ENV(dynarec_volatile_metadata)) ParseVolatileMetadata(filename, addr); - } + if (emu && !(flags & MAP_ANONYMOUS) && (fd > 0)) { // the last_mmap will allow mmap created by wine, even those that have hole, to be fully tracked as one single mmap if((ret>=last_mmap_addr[0]) && ret+length<(last_mmap_addr[0]+last_mmap_len[0])) RecordEnvMappings((uintptr_t)last_mmap_addr[0], last_mmap_len[0], fd); From 1a4931fc1571442ef2c74c2db9208cb094606a8d Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Thu, 8 May 2025 19:40:18 +0800 Subject: [PATCH 2/2] fix --- src/tools/env.c | 2 +- src/tools/wine_tools.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tools/env.c b/src/tools/env.c index 21fc08f5ac..16c4b1948f 100644 --- a/src/tools/env.c +++ b/src/tools/env.c @@ -617,7 +617,7 @@ void RecordEnvMappings(uintptr_t addr, size_t length, int fd) khint_t k = kh_get(mapping_entry, mapping_entries, lowercase_filename); if(k == kh_end(mapping_entries)) { // First time we see this file - if (box64_wine && BOX64ENV(unityplayer)) DetectUnityPlayer(lowercase_filename); + if (box64_wine && BOX64ENV(unityplayer)) DetectUnityPlayer(lowercase_filename+1); if (box64_wine && BOX64ENV(dynarec_volatile_metadata)) ParseVolatileMetadata(fullname, (void*)addr); mapping = box_calloc(1, sizeof(mapping_t)); diff --git a/src/tools/wine_tools.c b/src/tools/wine_tools.c index bde9505583..e1fb72afc8 100644 --- a/src/tools/wine_tools.c +++ b/src/tools/wine_tools.c @@ -139,8 +139,8 @@ void dynarec_wine_prereserve() void DetectUnityPlayer(char* filename) { static int unityplayer_detected = 0; - if (filename && BOX64ENV(unityplayer) && !unityplayer_detected && !strcasecmp(filename, "unityplayer.dll")) { - printf_log(LOG_NONE, "Detected UnityPlayer.dll\n"); + if (filename && BOX64ENV(unityplayer) && !unityplayer_detected && !strcmp(filename, "unityplayer.dll")) { + printf_log(LOG_INFO, "Detected UnityPlayer.dll\n"); #ifdef DYNAREC if (!BOX64ENV(dynarec_strongmem)) { SET_BOX64ENV(dynarec_strongmem, 1);