diff options
author | Ben Gamari <ben@smart-cactus.org> | 2022-02-09 14:41:04 -0500 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2022-04-06 16:25:25 -0400 |
commit | ff625218d9d7c17f1c6117991d1d2a28f9e4497a (patch) | |
tree | bef3fd674832692ed5a2ec319236f20eb7754393 /rts/linker | |
parent | 7e8cc293702354bec350c4d3c784a70cd8f7ffe4 (diff) | |
download | haskell-ff625218d9d7c17f1c6117991d1d2a28f9e4497a.tar.gz |
rts/PEi386: Move allocateBytes to MMap.c
Diffstat (limited to 'rts/linker')
-rw-r--r-- | rts/linker/MMap.c | 93 | ||||
-rw-r--r-- | rts/linker/PEi386.c | 101 | ||||
-rw-r--r-- | rts/linker/PEi386.h | 8 |
3 files changed, 92 insertions, 110 deletions
diff --git a/rts/linker/MMap.c b/rts/linker/MMap.c index 1ecfbc6c7f..c506100816 100644 --- a/rts/linker/MMap.c +++ b/rts/linker/MMap.c @@ -72,6 +72,97 @@ static struct MemoryRegion allMemory = { #if defined(mingw32_HOST_OS) +/* A wrapper for VirtualQuery() providing useful debug output */ +static int virtualQuery(void *baseAddr, PMEMORY_BASIC_INFORMATION info) +{ + int res = VirtualQuery (baseAddr, info, sizeof (*info)); + IF_DEBUG(linker_verbose, + debugBelch("Probing region 0x%p (0x%p) - 0x%p (%" FMT_SizeT ") [%ld] with base 0x%p\n", + baseAddr, + info->BaseAddress, + (uint8_t *) info->BaseAddress + info->RegionSize, + info->RegionSize, info->State, + info->AllocationBase)); + if (!res) { + IF_DEBUG(linker_verbose, debugBelch("Querying 0x%p failed. Aborting..\n", baseAddr)); + return 1; + } + return 0; +} + +static inline uintptr_t round_up(uintptr_t num, uint64_t factor) +{ + return num + factor - 1 - (num + factor - 1) % factor; +} + +/* + * Try and find a location in the VMMAP to allocate SZ bytes starting at + * BASEADDR. If successful then location to use is returned and the amount of + * bytes you *must* allocate is returned in REQ. You are free to use less but + * you must allocate the amount given in REQ. If not successful NULL. + */ +static void *allocateBytes(void* baseAddr, size_t sz, size_t *req) +{ + SYSTEM_INFO sys; + GetSystemInfo(&sys); + const uint64_t max_range = 4294967296UL; + IF_DEBUG(linker_verbose, debugBelch("Base Address 0x%p\n", baseAddr)); + IF_DEBUG(linker_verbose, debugBelch("Requesting mapping of %" FMT_SizeT " bytes within range %" + PRId64 " bytes\n", sz, max_range)); + + MEMORY_BASIC_INFORMATION info; + IF_DEBUG(linker_verbose, debugBelch("Initial query @ 0x%p...\n", baseAddr)); + int res = virtualQuery(baseAddr, &info); + if (res) { + return NULL; + } + + uint8_t *endAddr = (uint8_t *) baseAddr + max_range; + uint8_t *initialAddr = info.AllocationBase; + uint8_t *region = NULL; + while (!region + && (uint64_t) llabs(initialAddr - endAddr) <= max_range + && (void *) initialAddr < sys.lpMaximumApplicationAddress) + { + res = virtualQuery(initialAddr, &info); + if (res) { + return NULL; + } + + if ((info.State & MEM_FREE) == MEM_FREE) { + IF_DEBUG(linker_verbose, debugBelch("Free range at 0x%p of %zu bytes\n", + info.BaseAddress, info.RegionSize)); + + MEMORY_BASIC_INFORMATION info2; + res = virtualQuery(endAddr+1, &info2); + if (info.RegionSize >= sz) { + if (info.AllocationBase == 0) { + size_t needed_sz = round_up (sz, sys.dwAllocationGranularity); + if (info.RegionSize >= needed_sz) { + IF_DEBUG(linker_verbose, debugBelch("Range is unmapped, Allocation " + "required by granule...\n")); + *req = needed_sz; + region + = (void*)(uintptr_t)round_up ((uintptr_t)initialAddr, + sys.dwAllocationGranularity); + IF_DEBUG(linker_verbose, debugBelch("Requested %" PRId64 ", rounded: %" + PRId64 ".\n", sz, *req)); + IF_DEBUG(linker_verbose, debugBelch("Aligned region claimed 0x%p -> " + "0x%p.\n", initialAddr, region)); + } + } else { + IF_DEBUG(linker_verbose, debugBelch("Range is usable for us, claiming...\n")); + *req = sz; + region = initialAddr; + } + } + } + initialAddr = (uint8_t *) info.BaseAddress + info.RegionSize; + } + + return region; +} + static DWORD memoryAccessToProt(MemoryAccess access) { @@ -96,7 +187,7 @@ mmapAnonForLinker (size_t bytes) /* For linking purposes we want to load code within a 4GB range from the load address of the application. As such we need to find a location to allocate at. */ - void* region = allocaLocalBytes (bytes, &size); + void* region = allocateBytes (GetModuleHandleW (NULL), bytes, &size); if (region == NULL) { return NULL; } diff --git a/rts/linker/PEi386.c b/rts/linker/PEi386.c index 64e26a174c..3a9caf1b80 100644 --- a/rts/linker/PEi386.c +++ b/rts/linker/PEi386.c @@ -386,107 +386,6 @@ const int default_alignment = 8; the pointer as a redirect. Essentially it's a DATA DLL reference. */ const void* __rts_iob_func = (void*)&__acrt_iob_func; -/******************************************** - * Memory Management functions - ********************************************/ - -static inline uintptr_t round_up(uintptr_t num, uint64_t factor) -{ - return num + factor - 1 - (num + factor - 1) % factor; -} - -/* A wrapper for VirtualQuery() providing useful debug output */ -static int virtualQuery(void *baseAddr, PMEMORY_BASIC_INFORMATION info) -{ - int res = VirtualQuery (baseAddr, info, sizeof (*info)); - IF_DEBUG(linker_verbose, - debugBelch("Probing region 0x%p (0x%p) - 0x%p (%" FMT_SizeT ") [%ld] with base 0x%p\n", - baseAddr, - info->BaseAddress, - (uint8_t *) info->BaseAddress + info->RegionSize, - info->RegionSize, info->State, - info->AllocationBase)); - if (!res) { - IF_DEBUG(linker_verbose, debugBelch("Querying 0x%p failed. Aborting..\n", baseAddr)); - return 1; - } - return 0; -} - - -/* - * Try and find a location in the VMMAP to allocate SZ bytes starting at - * BASEADDR. If successful then location to use is returned and the amount of - * bytes you *must* allocate is returned in REQ. You are free to use less but - * you must allocate the amount given in REQ. If not successful NULL. - */ -static void *allocateBytes(void* baseAddr, size_t sz, size_t *req) -{ - SYSTEM_INFO sys; - GetSystemInfo(&sys); - const uint64_t max_range = 4294967296UL; - IF_DEBUG(linker_verbose, debugBelch("Base Address 0x%p\n", baseAddr)); - IF_DEBUG(linker_verbose, debugBelch("Requesting mapping of %" FMT_SizeT " bytes within range %" - PRId64 " bytes\n", sz, max_range)); - - MEMORY_BASIC_INFORMATION info; - IF_DEBUG(linker_verbose, debugBelch("Initial query @ 0x%p...\n", baseAddr)); - int res = virtualQuery(baseAddr, &info); - if (res) { - return NULL; - } - - uint8_t *endAddr = (uint8_t *) baseAddr + max_range; - uint8_t *initialAddr = info.AllocationBase; - uint8_t *region = NULL; - while (!region - && (uint64_t) llabs(initialAddr - endAddr) <= max_range - && (void *) initialAddr < sys.lpMaximumApplicationAddress) - { - res = virtualQuery(initialAddr, &info); - if (res) { - return NULL; - } - - if ((info.State & MEM_FREE) == MEM_FREE) { - IF_DEBUG(linker_verbose, debugBelch("Free range at 0x%p of %zu bytes\n", - info.BaseAddress, info.RegionSize)); - - MEMORY_BASIC_INFORMATION info2; - res = virtualQuery(endAddr+1, &info2); - if (info.RegionSize >= sz) { - if (info.AllocationBase == 0) { - size_t needed_sz = round_up (sz, sys.dwAllocationGranularity); - if (info.RegionSize >= needed_sz) { - IF_DEBUG(linker_verbose, debugBelch("Range is unmapped, Allocation " - "required by granule...\n")); - *req = needed_sz; - region - = (void*)(uintptr_t)round_up ((uintptr_t)initialAddr, - sys.dwAllocationGranularity); - IF_DEBUG(linker_verbose, debugBelch("Requested %" PRId64 ", rounded: %" - PRId64 ".\n", sz, *req)); - IF_DEBUG(linker_verbose, debugBelch("Aligned region claimed 0x%p -> " - "0x%p.\n", initialAddr, region)); - } - } else { - IF_DEBUG(linker_verbose, debugBelch("Range is usable for us, claiming...\n")); - *req = sz; - region = initialAddr; - } - } - } - initialAddr = (uint8_t *) info.BaseAddress + info.RegionSize; - } - - return region; -} - -void *allocaLocalBytes(size_t sz, size_t *req) -{ - return allocateBytes (GetModuleHandleW (NULL), sz, req); -} - void initLinker_PEi386() { if (!ghciInsertSymbolTable(WSTR("(GHCi/Ld special symbols)"), diff --git a/rts/linker/PEi386.h b/rts/linker/PEi386.h index 2624ff6832..c5c88459a6 100644 --- a/rts/linker/PEi386.h +++ b/rts/linker/PEi386.h @@ -166,12 +166,4 @@ because we have no stdcall convention on 64 bits. See #9218 */ -/******************************************** - * Memory Management functions - ********************************************/ - -/* Same as the above, but use the current process's load address as the starting - point for memory allocations. */ -void *allocaLocalBytes(size_t sz, size_t *req); - #include "EndPrivate.h" |