diff options
Diffstat (limited to 'rts/Linker.c')
-rw-r--r-- | rts/Linker.c | 56 |
1 files changed, 46 insertions, 10 deletions
diff --git a/rts/Linker.c b/rts/Linker.c index c79f184f23..6468e7818d 100644 --- a/rts/Linker.c +++ b/rts/Linker.c @@ -1008,6 +1008,17 @@ resolveSymbolAddr (pathchar* buffer, int size, #endif /* OBJFORMAT_PEi386 */ } +static const char *memoryAccessDescription(MemoryAccess mode) +{ + switch (mode) { + case MEM_NO_ACCESS: return "no-access"; + case MEM_READ_ONLY: return "read-only"; + case MEM_READ_WRITE: return "read-write"; + case MEM_READ_EXECUTE: return "read-execute"; + default: barf("invalid MemoryAccess"); + } +} + #if defined(mingw32_HOST_OS) // @@ -1028,16 +1039,29 @@ munmapForLinker (void *addr, size_t bytes, const char *caller) } } +/** + * Change the allowed access modes of a region of memory previously allocated + * with mmapAnonForLinker. + */ void -mmapForLinkerMarkExecutable(void *start, size_t len) +mprotectForLinker(void *start, size_t len, MemoryAccess mode) { DWORD old; if (len == 0) { return; } - if (VirtualProtect(start, len, PAGE_EXECUTE_READ, &old) == 0) { - sysErrorBelch("mmapForLinkerMarkExecutable: failed to protect %zd bytes at %p", - len, start); + DWORD prot; + switch (mode) { + case MEM_NO_ACCESS: prot = PAGE_NOACCESS; break; + case MEM_READ_ONLY: prot = PAGE_READONLY; break; + case MEM_READ_WRITE: prot = PAGE_READWRITE; break; + case MEM_READ_EXECUTE: prot = PAGE_EXECUTE_READ; break; + default: barf("invalid MemoryAccess"); + } + + if (VirtualProtect(start, len, prot, &old) == 0) { + sysErrorBelch("mprotectForLinker: failed to protect %zd bytes at %p as %s", + len, start, memoryAccessDescription(mode)); ASSERT(false); } } @@ -1189,7 +1213,7 @@ void munmapForLinker (void *addr, size_t bytes, const char *caller) * * Consequently mmapForLinker now maps its memory with PROT_READ|PROT_WRITE. * After the linker has finished filling/relocating the mapping it must then - * call mmapForLinkerMarkExecutable on the sections of the mapping which + * call mprotectForLinker on the sections of the mapping which * contain executable code. * * Note that the m32 allocator handles protection of its allocations. For this @@ -1205,16 +1229,28 @@ void munmapForLinker (void *addr, size_t bytes, const char *caller) * Mark an portion of a mapping previously reserved by mmapForLinker * as executable (but not writable). */ -void mmapForLinkerMarkExecutable(void *start, size_t len) +void mprotectForLinker(void *start, size_t len, MemoryAccess mode) { if (len == 0) { return; } IF_DEBUG(linker_verbose, - debugBelch("mmapForLinkerMarkExecutable: protecting %" FMT_Word - " bytes starting at %p\n", (W_)len, start)); - if (mprotect(start, len, PROT_READ|PROT_EXEC) == -1) { - barf("mmapForLinkerMarkExecutable: mprotect: %s\n", strerror(errno)); + debugBelch("mprotectForLinker: protecting %" FMT_Word + " bytes starting at %p as %s\n", + (W_)len, start, memoryAccessDescription(mode))); + + int prot; + switch (mode) { + case MEM_NO_ACCESS: prot = 0; break; + case MEM_READ_ONLY: prot = PROT_READ; break; + case MEM_READ_WRITE: prot = PROT_READ | PROT_WRITE; break; + case MEM_READ_EXECUTE: prot = PROT_READ | PROT_EXEC; break; + default: barf("invalid MemoryAccess"); + } + + if (mprotect(start, len, prot) == -1) { + sysErrorBelch("mprotectForLinker: failed to protect %zd bytes at %p as %s", + len, start, memoryAccessDescription(mode)); } } #endif |