Commit 04e83666 authored by Simon Marlow's avatar Simon Marlow

ELF/x86_64: map object file sections separately into the low 2GB

On 64-bit ELF we need to link object files into the low 2GB due to the
small memory model.  Previously we would map the entire object file
using MAP_32BIT, but the object file can consist of 75% or more
symbols, which only need to be present during linking, so this is
wasteful.  In our particular application, we're already running out of
space here.

This patch changes the way we load object files on ELF platforms so
that the object is first mapped above the 2GB boundary, parsed, and
then the important sections are re-mapped into the low 2GB area.

Test Plan:
validate
(also needs testing on OS X & Windows, preferably 32 & 64 bit)

Reviewers: Phyx, trommler, bgamari, austin

Subscribers: hsyl20, thomie, bgamari

Differential Revision: https://phabricator.haskell.org/D975
parent 20e30d5f
...@@ -40,15 +40,21 @@ ...@@ -40,15 +40,21 @@
static void checkAddress (HashTable *addrs, void *addr) static void checkAddress (HashTable *addrs, void *addr)
{ {
ObjectCode *oc; ObjectCode *oc;
int i;
if (!lookupHashTable(addrs, (W_)addr)) { if (!lookupHashTable(addrs, (W_)addr)) {
insertHashTable(addrs, (W_)addr, addr); insertHashTable(addrs, (W_)addr, addr);
for (oc = unloaded_objects; oc; oc = oc->next) { for (oc = unloaded_objects; oc; oc = oc->next) {
if ((W_)addr >= (W_)oc->image && for (i = 0; i < oc->n_sections; i++) {
(W_)addr < (W_)oc->image + oc->fileSize) { if (oc->sections[i].kind != SECTIONKIND_OTHER) {
oc->referenced = 1; if ((W_)addr >= (W_)oc->sections[i].start &&
break; (W_)addr < (W_)oc->sections[i].start
+ oc->sections[i].size) {
oc->referenced = 1;
return;
}
}
} }
} }
} }
......
This diff is collapsed.
...@@ -27,16 +27,31 @@ typedef ...@@ -27,16 +27,31 @@ typedef
SECTIONKIND_NOINFOAVAIL } SECTIONKIND_NOINFOAVAIL }
SectionKind; SectionKind;
typedef typedef
enum { SECTION_NOMEM,
SECTION_M32,
SECTION_MMAP,
SECTION_MALLOC,
}
SectionAlloc;
typedef
struct _Section { struct _Section {
void* start; void* start; /* actual start of section in memory */
void* end; StgWord size; /* actual size of section in memory */
SectionKind kind; SectionKind kind;
struct _Section* next; SectionAlloc alloc;
}
/*
* The following fields are relevant for SECTION_MMAP sections only
*/
StgWord mapped_offset; /* offset from the image of mapped_start */
void* mapped_start; /* start of mmap() block */
StgWord mapped_size; /* size of mmap() block */
}
Section; Section;
typedef typedef
struct _ProddableBlock { struct _ProddableBlock {
void* start; void* start;
int size; int size;
...@@ -55,6 +70,10 @@ typedef struct ForeignExportStablePtr_ { ...@@ -55,6 +70,10 @@ typedef struct ForeignExportStablePtr_ {
struct ForeignExportStablePtr_ *next; struct ForeignExportStablePtr_ *next;
} ForeignExportStablePtr; } ForeignExportStablePtr;
#if powerpc_HOST_ARCH || x86_64_HOST_ARCH || arm_HOST_ARCH
#define NEED_SYMBOL_EXTRAS 1
#endif
/* Jump Islands are sniplets of machine code required for relative /* Jump Islands are sniplets of machine code required for relative
* address relocations on the PowerPC, x86_64 and ARM. * address relocations on the PowerPC, x86_64 and ARM.
*/ */
...@@ -80,7 +99,7 @@ typedef struct { ...@@ -80,7 +99,7 @@ typedef struct {
typedef struct _ObjectCode { typedef struct _ObjectCode {
OStatus status; OStatus status;
pathchar *fileName; pathchar *fileName;
int fileSize; int fileSize; /* also mapped image size when using mmap() */
char* formatName; /* eg "ELF32", "DLL", "COFF", etc. */ char* formatName; /* eg "ELF32", "DLL", "COFF", etc. */
/* If this object is a member of an archive, archiveMemberName is /* If this object is a member of an archive, archiveMemberName is
...@@ -95,8 +114,10 @@ typedef struct _ObjectCode { ...@@ -95,8 +114,10 @@ typedef struct _ObjectCode {
char** symbols; char** symbols;
int n_symbols; int n_symbols;
/* ptr to malloc'd lump of memory holding the obj file */ /* ptr to mem containing the object file image */
char* image; char* image;
/* non-zero if the object file was mmap'd, otherwise malloc'd */
int imageMapped;
/* flag used when deciding whether to unload an object file */ /* flag used when deciding whether to unload an object file */
int referenced; int referenced;
...@@ -109,6 +130,7 @@ typedef struct _ObjectCode { ...@@ -109,6 +130,7 @@ typedef struct _ObjectCode {
/* The section-kind entries for this object module. Linked /* The section-kind entries for this object module. Linked
list. */ list. */
int n_sections;
Section* sections; Section* sections;
/* Allow a chain of these things */ /* Allow a chain of these things */
...@@ -125,7 +147,7 @@ typedef struct _ObjectCode { ...@@ -125,7 +147,7 @@ typedef struct _ObjectCode {
unsigned int pltIndex; unsigned int pltIndex;
#endif #endif
#if powerpc_HOST_ARCH || x86_64_HOST_ARCH || arm_HOST_ARCH #if NEED_SYMBOL_EXTRAS
SymbolExtra *symbol_extras; SymbolExtra *symbol_extras;
unsigned long first_symbol_extra; unsigned long first_symbol_extra;
unsigned long n_symbol_extras; unsigned long n_symbol_extras;
......
...@@ -43,7 +43,7 @@ test('ghcilink006', ...@@ -43,7 +43,7 @@ test('ghcilink006',
test('T3333', test('T3333',
[extra_clean(['T3333.o']), [extra_clean(['T3333.o']),
unless(doing_ghci, skip), unless(doing_ghci, skip),
unless(opsys('linux') or ghci_dynamic(), expect_broken(3333))], unless(opsys('linux') or opsys('darwin') or ghci_dynamic(), expect_broken(3333))],
run_command, run_command,
['$MAKE -s --no-print-directory T3333']) ['$MAKE -s --no-print-directory T3333'])
...@@ -51,12 +51,12 @@ int main (int argc, char *argv[]) ...@@ -51,12 +51,12 @@ int main (int argc, char *argv[])
for (i=0; i < ITERATIONS; i++) { for (i=0; i < ITERATIONS; i++) {
r = loadObj(obj); r = loadObj(obj);
if (!r) { if (!r) {
debugBelch("loadObj(%s) failed", obj); debugBelch("loadObj(%s) failed\n", obj);
continue; continue;
} }
r = resolveObjs(); r = resolveObjs();
if (!r) { if (!r) {
debugBelch("resolveObjs failed"); debugBelch("resolveObjs failed\n");
unloadObj(obj); unloadObj(obj);
continue; continue;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment