summaryrefslogtreecommitdiff
path: root/rts/linker
diff options
context:
space:
mode:
authorZejun Wu <watashi@fb.com>2018-10-15 13:52:53 -0400
committerBen Gamari <ben@smart-cactus.org>2018-10-15 19:24:17 -0400
commit8306141397d6e47a169dbe4b7ff1b3319a502aa7 (patch)
tree4397939b9508e4d2e06ced33d6568dd837784dfc /rts/linker
parent104599f3f157613589e78627c915e4dc20ee54b4 (diff)
downloadhaskell-8306141397d6e47a169dbe4b7ff1b3319a502aa7.tar.gz
Allocate bss section within proper range of other sections
Allocate bss section within proper range of other sections: * when `+RTS -xp` is passed, allocate it contiguously as we did for jump islands * when we mmap the code to lower 2Gb, we should allocate bss section there too This depends on {D5195} Test Plan: 1. `./validate` 2. with ``` DYNAMIC_GHC_PROGRAMS = NO DYNAMIC_BY_DEFAULT = NO ``` `TEST="T15729" make test` passed in both linux and macos. 3. Also test in a use case where we used to encouter error like: ``` ghc-iserv-prof: R_X86_64_PC32 relocation out of range: (noname) = b90282ba ``` and now, everything works fine. Reviewers: simonmar, bgamari, angerman, erikd Reviewed By: simonmar Subscribers: rwbarton, carter GHC Trac Issues: #15729 Differential Revision: https://phabricator.haskell.org/D5219
Diffstat (limited to 'rts/linker')
-rw-r--r--rts/linker/Elf.c73
-rw-r--r--rts/linker/Elf.h2
-rw-r--r--rts/linker/MachO.c27
-rw-r--r--rts/linker/MachO.h2
-rw-r--r--rts/linker/PEi386.c2
-rw-r--r--rts/linker/PEi386.h2
-rw-r--r--rts/linker/SymbolExtras.c31
-rw-r--r--rts/linker/SymbolExtras.h2
8 files changed, 77 insertions, 64 deletions
diff --git a/rts/linker/Elf.c b/rts/linker/Elf.c
index fe87aed0b0..0a7ffaec21 100644
--- a/rts/linker/Elf.c
+++ b/rts/linker/Elf.c
@@ -579,7 +579,7 @@ ocVerifyImage_ELF ( ObjectCode* oc )
/* Figure out what kind of section it is. Logic derived from
Figure 1.14 ("Special Sections") of the ELF document
("Portable Formats Specification, Version 1.1"). */
-static int getSectionKind_ELF( Elf_Shdr *hdr, int *is_bss )
+static SectionKind getSectionKind_ELF( Elf_Shdr *hdr, int *is_bss )
{
*is_bss = false;
@@ -681,23 +681,31 @@ ocGetNames_ELF ( ObjectCode* oc )
StgWord mapped_size = 0, mapped_offset = 0;
StgWord size = shdr[i].sh_size;
StgWord offset = shdr[i].sh_offset;
+ StgWord align = shdr[i].sh_addralign;
if (is_bss && size > 0) {
/* This is a non-empty .bss section. Allocate zeroed space for
it, and set its .sh_offset field such that
ehdrC + .sh_offset == addr_of_zeroed_space. */
-#if defined(NEED_GOT)
- /* always use mmap if we use GOT slots. Otherwise the malloced
- * address might be out of range for sections that are mmaped.
- */
- alloc = SECTION_MMAP;
- start = mmap(NULL, size,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_ANON | MAP_PRIVATE,
- -1, 0);
- mapped_start = start;
- mapped_offset = 0;
- mapped_size = roundUpToPage(size);
+#if defined(NEED_GOT) || RTS_LINKER_USE_MMAP
+ if (USE_CONTIGUOUS_MMAP || RtsFlags.MiscFlags.linkerAlwaysPic) {
+ /* The space for bss sections is already preallocated */
+ ASSERT(oc->bssBegin != NULL);
+ alloc = SECTION_NOMEM;
+ start =
+ oc->image + roundUpToAlign(oc->bssBegin - oc->image, align);
+ oc->bssBegin = (char*)start + size;
+ ASSERT(oc->bssBegin <= oc->bssEnd);
+ } else {
+ /* Use mmapForLinker to allocate .bss, otherwise the malloced
+ * address might be out of range for sections that are mmaped.
+ */
+ alloc = SECTION_MMAP;
+ start = mmapForLinker(size, MAP_ANONYMOUS, -1, 0);
+ mapped_start = start;
+ mapped_offset = 0;
+ mapped_size = roundUpToPage(size);
+ }
#else
alloc = SECTION_MALLOC;
start = stgCallocBytes(1, size, "ocGetNames_ELF(BSS)");
@@ -1873,22 +1881,27 @@ int ocRunInit_ELF( ObjectCode *oc )
#if defined(NEED_SYMBOL_EXTRAS)
-int ocAllocateSymbolExtras_ELF( ObjectCode *oc )
+int ocAllocateExtras_ELF( ObjectCode *oc )
{
- Elf_Ehdr *ehdr;
- Elf_Shdr* shdr;
- Elf_Word i, shnum;
-
- ehdr = (Elf_Ehdr *) oc->image;
- shdr = (Elf_Shdr *) ( ((char *)oc->image) + ehdr->e_shoff );
-
- shnum = elf_shnum(ehdr);
-
- for( i = 0; i < shnum; i++ )
- if( shdr[i].sh_type == SHT_SYMTAB )
- break;
+ Elf_Ehdr *ehdr = (Elf_Ehdr *) oc->image;
+ Elf_Shdr* shdr = (Elf_Shdr *) ( ((char *)oc->image) + ehdr->e_shoff );
+ Elf_Shdr* symtab = NULL;
+ Elf_Word shnum = elf_shnum(ehdr);
+ int bssSize = 0;
+
+ for (Elf_Word i = 0; i < shnum; ++i) {
+ if(shdr[i].sh_type == SHT_SYMTAB) {
+ symtab = &shdr[i];
+ } else {
+ int isBss = 0;
+ getSectionKind_ELF(&shdr[i], &isBss);
+ if (isBss && shdr[i].sh_size > 0) {
+ bssSize += roundUpToAlign(shdr[i].sh_size, shdr[i].sh_addralign);
+ }
+ }
+ }
- if( i == shnum )
+ if (symtab == NULL)
{
// Not having a symbol table is not in principle a problem.
// When an object file has no symbols then the 'strip' program
@@ -1898,15 +1911,15 @@ int ocAllocateSymbolExtras_ELF( ObjectCode *oc )
return 1;
}
- if( shdr[i].sh_entsize != sizeof( Elf_Sym ) )
+ if( symtab->sh_entsize != sizeof( Elf_Sym ) )
{
errorBelch( "The entry size (%d) of the symtab isn't %d\n",
- (int) shdr[i].sh_entsize, (int) sizeof( Elf_Sym ) );
+ (int) symtab->sh_entsize, (int) sizeof( Elf_Sym ) );
return 0;
}
- return ocAllocateSymbolExtras( oc, shdr[i].sh_size / sizeof( Elf_Sym ), 0 );
+ return ocAllocateExtras(oc, symtab->sh_size / sizeof( Elf_Sym ), 0, bssSize);
}
#endif /* NEED_SYMBOL_EXTRAS */
diff --git a/rts/linker/Elf.h b/rts/linker/Elf.h
index b0d6638e6a..30c993b98c 100644
--- a/rts/linker/Elf.h
+++ b/rts/linker/Elf.h
@@ -13,6 +13,6 @@ int ocVerifyImage_ELF ( ObjectCode* oc );
int ocGetNames_ELF ( ObjectCode* oc );
int ocResolve_ELF ( ObjectCode* oc );
int ocRunInit_ELF ( ObjectCode* oc );
-int ocAllocateSymbolExtras_ELF( ObjectCode *oc );
+int ocAllocateExtras_ELF ( ObjectCode *oc );
#include "EndPrivate.h"
diff --git a/rts/linker/MachO.c b/rts/linker/MachO.c
index ff8ef7a1e4..7d5ff32276 100644
--- a/rts/linker/MachO.c
+++ b/rts/linker/MachO.c
@@ -186,10 +186,10 @@ resolveImports(
#if NEED_SYMBOL_EXTRAS
#if defined(powerpc_HOST_ARCH)
int
-ocAllocateSymbolExtras_MachO(ObjectCode* oc)
+ocAllocateExtras_MachO(ObjectCode* oc)
{
- IF_DEBUG(linker, debugBelch("ocAllocateSymbolExtras_MachO: start\n"));
+ IF_DEBUG(linker, debugBelch("ocAllocateExtras_MachO: start\n"));
// Find out the first and last undefined external
// symbol, so we don't have to allocate too many
@@ -218,28 +218,31 @@ ocAllocateSymbolExtras_MachO(ObjectCode* oc)
}
if (max >= min) {
- return ocAllocateSymbolExtras(oc, max - min + 1, min);
+ return ocAllocateExtras(oc, max - min + 1, min, 0);
}
- return ocAllocateSymbolExtras(oc,0,0);
+ return ocAllocateExtras(oc, 0, 0, 0);
}
#elif defined(x86_64_HOST_ARCH) || defined(aarch64_HOST_ARCH)
int
-ocAllocateSymbolExtras_MachO(ObjectCode* oc)
+ocAllocateExtras_MachO(ObjectCode* oc)
{
- IF_DEBUG(linker, debugBelch("ocAllocateSymbolExtras_MachO: start\n"));
+ IF_DEBUG(linker, debugBelch("ocAllocateExtras_MachO: start\n"));
if (NULL != oc->info->symCmd) {
- IF_DEBUG(linker, debugBelch("ocAllocateSymbolExtras_MachO: allocate %d symbols\n", oc->info->symCmd->nsyms));
- IF_DEBUG(linker, debugBelch("ocAllocateSymbolExtras_MachO: done\n"));
- return ocAllocateSymbolExtras(oc, oc->info->symCmd->nsyms, 0);
+ IF_DEBUG(linker,
+ debugBelch("ocAllocateExtras_MachO: allocate %d symbols\n",
+ oc->info->symCmd->nsyms));
+ IF_DEBUG(linker, debugBelch("ocAllocateExtras_MachO: done\n"));
+ return ocAllocateExtras(oc, oc->info->symCmd->nsyms, 0, 0);
}
- IF_DEBUG(linker, debugBelch("ocAllocateSymbolExtras_MachO: allocated no symbols\n"));
- IF_DEBUG(linker, debugBelch("ocAllocateSymbolExtras_MachO: done\n"));
- return ocAllocateSymbolExtras(oc,0,0);
+ IF_DEBUG(linker,
+ debugBelch("ocAllocateExtras_MachO: allocated no symbols\n"));
+ IF_DEBUG(linker, debugBelch("ocAllocateExtras_MachO: done\n"));
+ return ocAllocateExtras(oc, 0, 0, 0);
}
#else
diff --git a/rts/linker/MachO.h b/rts/linker/MachO.h
index b495c2b9b1..4fb58e8668 100644
--- a/rts/linker/MachO.h
+++ b/rts/linker/MachO.h
@@ -13,7 +13,7 @@ int ocGetNames_MachO ( ObjectCode* oc );
int ocResolve_MachO ( ObjectCode* oc );
int ocRunInit_MachO ( ObjectCode* oc );
int machoGetMisalignment( FILE * );
-int ocAllocateSymbolExtras_MachO ( ObjectCode* oc );
+int ocAllocateExtras_MachO ( ObjectCode* oc );
#if defined(powerpc_HOST_ARCH)
void machoInitSymbolsWithoutUnderscore( void );
diff --git a/rts/linker/PEi386.c b/rts/linker/PEi386.c
index ab4583da7c..bf642d8b23 100644
--- a/rts/linker/PEi386.c
+++ b/rts/linker/PEi386.c
@@ -1777,7 +1777,7 @@ ocGetNames_PEi386 ( ObjectCode* oc )
* so simply set correct pointer here.
*/
bool
-ocAllocateSymbolExtras_PEi386 ( ObjectCode* oc )
+ocAllocateExtras_PEi386 ( ObjectCode* oc )
{
/* If the ObjectCode was unloaded we don't need a trampoline, it's likely
an import library so we're discarding it earlier. */
diff --git a/rts/linker/PEi386.h b/rts/linker/PEi386.h
index eb5bec8b78..538f132ab5 100644
--- a/rts/linker/PEi386.h
+++ b/rts/linker/PEi386.h
@@ -57,7 +57,7 @@ bool ocRunInit_PEi386 ( ObjectCode *oc );
bool ocGetNames_PEi386 ( ObjectCode* oc );
bool ocVerifyImage_PEi386 ( ObjectCode* oc );
SymbolAddr *lookupSymbol_PEi386(SymbolName *lbl);
-bool ocAllocateSymbolExtras_PEi386 ( ObjectCode* oc );
+bool ocAllocateExtras_PEi386 ( ObjectCode* oc );
SymbolAddr *lookupSymbolInDLLs ( const SymbolName* lbl );
/* See Note [mingw-w64 name decoration scheme] */
/* We use myindex to calculate array addresses, rather than
diff --git a/rts/linker/SymbolExtras.c b/rts/linker/SymbolExtras.c
index 4c40b10877..a9e4c37967 100644
--- a/rts/linker/SymbolExtras.c
+++ b/rts/linker/SymbolExtras.c
@@ -31,10 +31,11 @@
#endif /* RTS_LINKER_USE_MMAP */
/*
- ocAllocateSymbolExtras
+ ocAllocateExtras
Allocate additional space at the end of the object file image to make room
- for jump islands (powerpc, x86_64, arm) and GOT entries (x86_64).
+ for jump islands (powerpc, x86_64, arm), GOT entries (x86_64) and
+ bss sections.
PowerPC relative branch instructions have a 24 bit displacement field.
As PPC code is always 4-byte-aligned, this yields a +-32MB range.
@@ -49,12 +50,11 @@
filled in by makeSymbolExtra below.
*/
-int ocAllocateSymbolExtras( ObjectCode* oc, int count, int first )
+int ocAllocateExtras(ObjectCode* oc, int count, int first, int bssSize)
{
- size_t n;
void* oldImage = oc->image;
- if (count > 0) {
+ if (count > 0 || bssSize > 0) {
if (!RTS_LINKER_USE_MMAP) {
// round up to the nearest 4
@@ -65,16 +65,15 @@ int ocAllocateSymbolExtras( ObjectCode* oc, int count, int first )
oc->image = stgReallocBytes( oc->image,
misalignment +
aligned + sizeof (SymbolExtra) * count,
- "ocAllocateSymbolExtras" );
+ "ocAllocateExtras" );
oc->image += misalignment;
oc->symbol_extras = (SymbolExtra *) (oc->image + aligned);
} else if (USE_CONTIGUOUS_MMAP || RtsFlags.MiscFlags.linkerAlwaysPic) {
- n = roundUpToPage(oc->fileSize);
-
- /* Keep image and symbol_extras contiguous */
-
- size_t allocated_size = n + (sizeof(SymbolExtra) * count);
+ /* Keep image, bssExtras and symbol_extras contiguous */
+ size_t n = roundUpToPage(oc->fileSize);
+ bssSize = roundUpToAlign(bssSize, 8);
+ size_t allocated_size = n + bssSize + (sizeof(SymbolExtra) * count);
void *new = mmapForLinker(allocated_size, MAP_ANONYMOUS, -1, 0);
if (new) {
memcpy(new, oc->image, oc->fileSize);
@@ -83,12 +82,10 @@ int ocAllocateSymbolExtras( ObjectCode* oc, int count, int first )
}
oc->image = new;
oc->imageMapped = true;
- oc->fileSize = n + (sizeof(SymbolExtra) * count);
- oc->symbol_extras = (SymbolExtra *) (oc->image + n);
- if (mprotect(new, allocated_size,
- PROT_READ | PROT_WRITE | PROT_EXEC) != 0) {
- sysErrorBelch("unable to protect memory");
- }
+ oc->fileSize = allocated_size;
+ oc->symbol_extras = (SymbolExtra *) (oc->image + n + bssSize);
+ oc->bssBegin = oc->image + n;
+ oc->bssEnd = oc->image + n + bssSize;
}
else {
oc->symbol_extras = NULL;
diff --git a/rts/linker/SymbolExtras.h b/rts/linker/SymbolExtras.h
index 4974c06e7d..af828e66fa 100644
--- a/rts/linker/SymbolExtras.h
+++ b/rts/linker/SymbolExtras.h
@@ -7,7 +7,7 @@
#if defined(NEED_SYMBOL_EXTRAS)
-int ocAllocateSymbolExtras( ObjectCode* oc, int count, int first );
+int ocAllocateExtras(ObjectCode* oc, int count, int first, int bssSize);
#if defined(arm_HOST_ARCH)
SymbolExtra* makeArmSymbolExtra( ObjectCode const* oc,