summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2020-11-23 14:35:56 -0500
committerMarge Bot <ben+marge-bot@smart-cactus.org>2020-12-01 19:58:17 -0500
commitadd0aeaefd4d823d31315564e924ce8c018fb69e (patch)
tree4fc39929885b53bd774d7a8eedde70917cd37bfe
parentd66660ba4c491f9937a1a959b009d90f08a4fbee (diff)
downloadhaskell-add0aeaefd4d823d31315564e924ce8c018fb69e.tar.gz
rts: Introduce mmapAnonForLinker
Previously most of the uses of mmapForLinker were mapping anonymous memory, resulting in a great deal of unnecessary repetition. Factor this out into a new helper. Also fixes a few places where error checking was missing or suboptimal.
-rw-r--r--rts/Linker.c12
-rw-r--r--rts/LinkerInternals.h1
-rw-r--r--rts/linker/Elf.c19
-rw-r--r--rts/linker/LoadArchive.c4
-rw-r--r--rts/linker/M32Alloc.c13
-rw-r--r--rts/linker/MachO.c9
-rw-r--r--rts/linker/SymbolExtras.c2
-rw-r--r--rts/linker/elf_got.c7
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;
}