diff options
-rw-r--r-- | rts/Linker.c | 12 | ||||
-rw-r--r-- | rts/LinkerInternals.h | 1 | ||||
-rw-r--r-- | rts/linker/Elf.c | 19 | ||||
-rw-r--r-- | rts/linker/LoadArchive.c | 4 | ||||
-rw-r--r-- | rts/linker/M32Alloc.c | 13 | ||||
-rw-r--r-- | rts/linker/MachO.c | 9 | ||||
-rw-r--r-- | rts/linker/SymbolExtras.c | 2 | ||||
-rw-r--r-- | rts/linker/elf_got.c | 7 |
8 files changed, 41 insertions, 26 deletions
diff --git a/rts/Linker.c b/rts/Linker.c index ef08a282dc..6873b1a9b7 100644 --- a/rts/Linker.c +++ b/rts/Linker.c @@ -1080,7 +1080,7 @@ mmap_again: fixed = MAP_FIXED; goto mmap_again; #else - errorBelch("loadObj: failed to mmap() memory below 2Gb; " + errorBelch("mmapForLinker: failed to mmap() memory below 2Gb; " "asked for %lu bytes at %p. " "Try specifying an address with +RTS -xm<addr> -RTS", size, map_addr); @@ -1140,6 +1140,16 @@ mmap_again: return result; } +/* + * Map read/write pages in low memory. Returns NULL on failure. + */ +void * +mmapAnonForLinker (size_t bytes) +{ + return mmapForLinker (bytes, PROT_READ|PROT_WRITE, MAP_ANONYMOUS, -1, 0); +} + + /* Note [Memory protection in the linker] * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * For many years the linker would simply map all of its memory diff --git a/rts/LinkerInternals.h b/rts/LinkerInternals.h index 27ca52f0e3..954c36764e 100644 --- a/rts/LinkerInternals.h +++ b/rts/LinkerInternals.h @@ -362,6 +362,7 @@ void exitLinker( void ); void freeObjectCode (ObjectCode *oc); SymbolAddr* loadSymbol(SymbolName *lbl, RtsSymbolInfo *pinfo); +void *mmapAnonForLinker (size_t bytes); void *mmapForLinker (size_t bytes, uint32_t prot, uint32_t flags, int fd, int offset); void mmapForLinkerMarkExecutable (void *start, size_t len); diff --git a/rts/linker/Elf.c b/rts/linker/Elf.c index b70eab0916..050de23dac 100644 --- a/rts/linker/Elf.c +++ b/rts/linker/Elf.c @@ -714,7 +714,11 @@ ocGetNames_ELF ( ObjectCode* oc ) * address might be out of range for sections that are mmaped. */ alloc = SECTION_MMAP; - start = mmapForLinker(size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS, -1, 0); + start = mmapAnonForLinker(size); + if (start == NULL) { + barf("failed to mmap memory for bss. " + "errno = %d", errno); + } mapped_start = start; mapped_offset = 0; mapped_size = roundUpToPage(size); @@ -756,9 +760,9 @@ ocGetNames_ELF ( ObjectCode* oc ) unsigned nstubs = numberOfStubsForSection(oc, i); unsigned stub_space = STUB_SIZE * nstubs; - void * mem = mmapForLinker(size+stub_space, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0); + void * mem = mmapAnonForLinker(size+stub_space); - if( mem == MAP_FAILED ) { + if( mem == NULL ) { barf("failed to mmap allocated memory to load section %d. " "errno = %d", i, errno); } @@ -865,11 +869,10 @@ ocGetNames_ELF ( ObjectCode* oc ) } void * common_mem = NULL; if(common_size > 0) { - common_mem = mmapForLinker(common_size, - PROT_READ | PROT_WRITE, - MAP_ANON | MAP_PRIVATE, - -1, 0); - CHECK(common_mem != NULL); + common_mem = mmapAnonForLinker(common_size); + if (common_mem == NULL) { + barf("ocGetNames_ELF: Failed to allocate memory for SHN_COMMONs"); + } } //TODO: we ignore local symbols anyway right? So we can use the diff --git a/rts/linker/LoadArchive.c b/rts/linker/LoadArchive.c index 55081489f5..9dda0e99e8 100644 --- a/rts/linker/LoadArchive.c +++ b/rts/linker/LoadArchive.c @@ -489,7 +489,7 @@ static HsInt loadArchive_ (pathchar *path) #if defined(darwin_HOST_OS) || defined(ios_HOST_OS) if (RTS_LINKER_USE_MMAP) - image = mmapForLinker(memberSize, PROT_READ | PROT_WRITE, MAP_ANONYMOUS, -1, 0); + image = mmapAnonForLinker(memberSize); else { /* See loadObj() */ misalignment = machoGetMisalignment(f); @@ -549,7 +549,7 @@ while reading filename from `%" PATH_FMT "'", path); } DEBUG_LOG("Found GNU-variant file index\n"); #if RTS_LINKER_USE_MMAP - gnuFileIndex = mmapForLinker(memberSize + 1, PROT_READ | PROT_WRITE, MAP_ANONYMOUS, -1, 0); + gnuFileIndex = mmapAnonForLinker(memberSize + 1); #else gnuFileIndex = stgMallocBytes(memberSize + 1, "loadArchive(image)"); #endif diff --git a/rts/linker/M32Alloc.c b/rts/linker/M32Alloc.c index 3adb8d934d..f1440e093c 100644 --- a/rts/linker/M32Alloc.c +++ b/rts/linker/M32Alloc.c @@ -263,8 +263,8 @@ m32_alloc_page(void) * pages. */ const size_t pgsz = getPageSize(); - char *chunk = mmapForLinker(pgsz * M32_MAP_PAGES, PROT_READ | PROT_WRITE, MAP_ANONYMOUS, -1, 0); - if (chunk > (char *) 0xffffffff) { + uint8_t *chunk = mmapAnonForLinker(pgsz * M32_MAP_PAGES); + if (chunk > (uint8_t *) 0xffffffff) { barf("m32_alloc_page: failed to get allocation in lower 32-bits"); } @@ -407,7 +407,14 @@ m32_alloc(struct m32_allocator_t *alloc, size_t size, size_t alignment) if (m32_is_large_object(size,alignment)) { // large object size_t alsize = ROUND_UP(sizeof(struct m32_page_t), alignment); - struct m32_page_t *page = mmapForLinker(alsize+size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS,-1,0); + struct m32_page_t *page = mmapAnonForLinker(alsize+size); + if (page == NULL) { + sysErrorBelch("m32_alloc: Failed to map pages for %zd bytes", size); + return NULL; + } else if (page > (struct m32_page_t *) 0xffffffff) { + debugBelch("m32_alloc: warning: Allocation of %zd bytes resulted in pages above 4GB (%p)", + size, page); + } page->filled_page.size = alsize + size; m32_allocator_push_filled_list(&alloc->unprotected_list, (struct m32_page_t *) page); return (char*) page + alsize; diff --git a/rts/linker/MachO.c b/rts/linker/MachO.c index d3da3ebdcf..e39379fd7e 100644 --- a/rts/linker/MachO.c +++ b/rts/linker/MachO.c @@ -507,11 +507,8 @@ makeGot(ObjectCode * oc) { if(got_slots > 0) { oc->info->got_size = got_slots * sizeof(void*); - oc->info->got_start = mmapForLinker(oc->info->got_size, - PROT_READ | PROT_WRITE, - MAP_ANON | MAP_PRIVATE, - -1, 0); - if( oc->info->got_start == MAP_FAILED ) { + oc->info->got_start = mmapAnonForLinker(oc->info->got_size); + if( oc->info->got_start == NULL ) { barf("MAP_FAILED. errno=%d", errno ); return EXIT_FAILURE; } @@ -1113,7 +1110,7 @@ ocBuildSegments_MachO(ObjectCode *oc) return 1; } - mem = mmapForLinker(size_compound, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0); + mem = mmapAnonForLinker(size_compound); if (NULL == mem) return 0; IF_DEBUG(linker, debugBelch("ocBuildSegments: allocating %d segments\n", n_activeSegments)); diff --git a/rts/linker/SymbolExtras.c b/rts/linker/SymbolExtras.c index 7f77d5120a..9d4eb89400 100644 --- a/rts/linker/SymbolExtras.c +++ b/rts/linker/SymbolExtras.c @@ -81,7 +81,7 @@ int ocAllocateExtras(ObjectCode* oc, int count, int first, int bssSize) // symbol_extras is aligned to a page boundary so it can be mprotect'd. bssSize = roundUpToPage(bssSize); size_t allocated_size = n + bssSize + extras_size; - void *new = mmapForLinker(allocated_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS, -1, 0); + void *new = mmapAnonForLinker(allocated_size); if (new) { memcpy(new, oc->image, oc->fileSize); if (oc->imageMapped) { diff --git a/rts/linker/elf_got.c b/rts/linker/elf_got.c index 1aca219f9b..4b014dac50 100644 --- a/rts/linker/elf_got.c +++ b/rts/linker/elf_got.c @@ -48,11 +48,8 @@ makeGot(ObjectCode * oc) { } if(got_slots > 0) { oc->info->got_size = got_slots * sizeof(void *); - void * mem = mmapForLinker(oc->info->got_size, - PROT_READ | PROT_WRITE, - MAP_ANON | MAP_PRIVATE, - -1, 0); - if (mem == MAP_FAILED) { + void * mem = mmapAnonForLinker(oc->info->got_size); + if (mem == NULL) { errorBelch("MAP_FAILED. errno=%d", errno); return EXIT_FAILURE; } |