diff --git a/dll/kernel32.cpp b/dll/kernel32.cpp index f02dd03..a92f834 100644 --- a/dll/kernel32.cpp +++ b/dll/kernel32.cpp @@ -1171,6 +1171,10 @@ namespace kernel32 { void *mem = 0; posix_memalign(&mem, 0x1000, dwSize); memset(mem, 0, dwSize); + + // Windows only fences off the lower 2GB of the 32-bit address space for the private use of processes. + assert(mem < (void*)0x80000000); + DEBUG_LOG("-> %p\n", mem); return mem; } else { diff --git a/main.cpp b/main.cpp index 4f5f999..41296f5 100644 --- a/main.cpp +++ b/main.cpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include uint32_t wibo::lastError = 0; char *wibo::commandLine; @@ -233,6 +235,42 @@ int main(int argc, char **argv) { exec.loadPE(f); fclose(f); + // 32-bit windows only reserves the lowest 2GB of memory for use by a process (https://www.tenouk.com/WinVirtualAddressSpace.html) + // Linux, on the other hand, will happily allow nearly the entire 4GB address space to be used. + // In order to prevent windows programs from being very confused as to why it's being handed + // addresses in "invalid" memory, let's map the upper 2GB of memory to ensure libc can't allocate + // anything there. + std::ifstream procMap("/proc/self/maps"); + std::string procLine; + unsigned int lastMapEnd = 0; + + const unsigned int FILL_MEMORY_ABOVE = 0x80000000; // 2GB + + while (getline(procMap, procLine)) { + std::size_t idx = 0; + unsigned int mapStart = std::stoul(procLine, &idx, 16); + unsigned int mapEnd = std::stoul(procLine.substr(idx + 1), nullptr, 16); + + // The empty space we want to map out is now between lastMapEnd and mapStart + unsigned int holdingMapStart = lastMapEnd; + unsigned int holdingMapEnd = mapStart; + + if ((holdingMapEnd - holdingMapStart) != 0 && holdingMapEnd > FILL_MEMORY_ABOVE) { + holdingMapStart = std::max(holdingMapStart, FILL_MEMORY_ABOVE); + + void* holdingMap = mmap((void*) holdingMapStart, holdingMapEnd - holdingMapStart, PROT_READ, MAP_ANONYMOUS|MAP_FIXED|MAP_PRIVATE, -1, 0); + + if (holdingMap == MAP_FAILED) { + perror("Failed to create holding map"); + return 1; + } + } + + lastMapEnd = mapEnd; + } + + procMap.close(); + uint16_t tibSegment = (tibDesc.entry_number << 3) | 7; // Invoke the damn thing asm(