summaryrefslogtreecommitdiff
path: root/rts/linker/Elf.c
diff options
context:
space:
mode:
authorBen Gamari <ben@well-typed.com>2019-01-30 01:06:12 -0500
committerBen Gamari <ben@well-typed.com>2019-01-30 01:06:12 -0500
commit76c8fd674435a652c75a96c85abbf26f1f221876 (patch)
treeb02a6f5307a20efc25ddb27c58977069b48972b6 /rts/linker/Elf.c
parent7cdcd3e12a5c3a337e36fa80c64bd72e5ef79b24 (diff)
downloadhaskell-76c8fd674435a652c75a96c85abbf26f1f221876.tar.gz
Batch merge
Diffstat (limited to 'rts/linker/Elf.c')
-rw-r--r--rts/linker/Elf.c112
1 files changed, 55 insertions, 57 deletions
diff --git a/rts/linker/Elf.c b/rts/linker/Elf.c
index 9ea10d443f..b647d207cb 100644
--- a/rts/linker/Elf.c
+++ b/rts/linker/Elf.c
@@ -53,11 +53,13 @@
* SILENTLY generate crashing code for data references. This hack is
* enabled by X86_64_ELF_NONPIC_HACK.
*
- * One workaround is to use shared Haskell libraries. This is
- * coming. Another workaround is to keep the static libraries but
- * compile them with -fPIC, because that will generate PIC references
- * to data which can be relocated. The PIC code is still too green to
- * do this systematically, though.
+ * One workaround is to use shared Haskell libraries. This is the case
+ * when dynamically-linked GHCi is used.
+ *
+ * Another workaround is to keep the static libraries but compile them
+ * with -fPIC -fexternal-dynamic-refs, because that will generate PIC
+ * references to data which can be relocated. This is the case when
+ * +RTS -xp is passed.
*
* See bug #781
* See thread http://www.haskell.org/pipermail/cvs-ghc/2007-September/038458.html
@@ -74,7 +76,7 @@
* Sym*_NeedsProto: the symbol is undefined and we add a dummy
* default proto extern void sym(void);
*/
-#define X86_64_ELF_NONPIC_HACK 1
+#define X86_64_ELF_NONPIC_HACK (!RtsFlags.MiscFlags.linkerAlwaysPic)
#if defined(sparc_HOST_ARCH)
# define ELF_TARGET_SPARC /* Used inside <elf.h> */
@@ -169,6 +171,8 @@ get_shndx_table(Elf_Ehdr* ehdr)
void
ocInit_ELF(ObjectCode * oc)
{
+ ocDeinit_ELF(oc);
+
oc->info = (struct ObjectCodeFormatInfo*)stgCallocBytes(
1, sizeof *oc->info,
"ocInit_Elf(ObjectCodeFormatInfo)");
@@ -318,6 +322,7 @@ ocDeinit_ELF(ObjectCode * oc)
}
stgFree(oc->info);
+ oc->info = NULL;
}
}
@@ -576,7 +581,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;
@@ -678,23 +683,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)");
@@ -754,7 +767,7 @@ ocGetNames_ELF ( ObjectCode* oc )
start = mem;
mapped_start = mem;
#else
- if (USE_CONTIGUOUS_MMAP) {
+ if (USE_CONTIGUOUS_MMAP || RtsFlags.MiscFlags.linkerAlwaysPic) {
// already mapped.
start = oc->image + offset;
alloc = SECTION_NOMEM;
@@ -1585,9 +1598,6 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
case COMPAT_R_X86_64_PC32:
{
-#if defined(ALWAYS_PIC)
- barf("R_X86_64_PC32 relocation, but ALWAYS_PIC.");
-#else
StgInt64 off = value - P;
if (off != (Elf64_Sword)off && X86_64_ELF_NONPIC_HACK) {
StgInt64 pltAddress =
@@ -1604,7 +1614,6 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
}
Elf64_Sword payload = off;
memcpy((void*)P, &payload, sizeof(payload));
-#endif
break;
}
@@ -1617,9 +1626,6 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
case COMPAT_R_X86_64_32:
{
-#if defined(ALWAYS_PIC)
- barf("R_X86_64_32 relocation, but ALWAYS_PIC.");
-#else
if (value != (Elf64_Word)value && X86_64_ELF_NONPIC_HACK) {
StgInt64 pltAddress =
(StgInt64) &makeSymbolExtra(oc, ELF_R_SYM(info), S)
@@ -1635,15 +1641,11 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
}
Elf64_Word payload = value;
memcpy((void*)P, &payload, sizeof(payload));
-#endif
break;
}
case COMPAT_R_X86_64_32S:
{
-#if defined(ALWAYS_PIC)
- barf("R_X86_64_32S relocation, but ALWAYS_PIC.");
-#else
if ((StgInt64)value != (Elf64_Sword)value && X86_64_ELF_NONPIC_HACK) {
StgInt64 pltAddress =
(StgInt64) &makeSymbolExtra(oc, ELF_R_SYM(info), S)
@@ -1659,7 +1661,6 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
}
Elf64_Sword payload = value;
memcpy((void*)P, &payload, sizeof(payload));
-#endif
break;
}
case COMPAT_R_X86_64_REX_GOTPCRELX:
@@ -1681,9 +1682,6 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
#if defined(dragonfly_HOST_OS)
case COMPAT_R_X86_64_GOTTPOFF:
{
-#if defined(ALWAYS_PIC)
- barf("R_X86_64_GOTTPOFF relocation, but ALWAYS_PIC.");
-#else
/* determine the offset of S to the current thread's tls
area
XXX: Move this to the beginning of function */
@@ -1701,16 +1699,12 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
}
Elf64_SWord payload = off;
memcpy((void*)P, &payload, sizeof(payload));
-#endif
break;
}
#endif
case COMPAT_R_X86_64_PLT32:
{
-#if defined(ALWAYS_PIC)
- barf("R_X86_64_PLT32 relocation, but ALWAYS_PIC.");
-#else
StgInt64 off = value - P;
if (off != (Elf64_Sword)off) {
StgInt64 pltAddress = (StgInt64) &makeSymbolExtra(oc, ELF_R_SYM(info), S)
@@ -1725,7 +1719,6 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
}
Elf64_Sword payload = off;
memcpy((void*)P, &payload, sizeof(payload));
-#endif
break;
}
#endif
@@ -1891,22 +1884,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
@@ -1916,15 +1914,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 */