summaryrefslogtreecommitdiff
path: root/rts/Linker.c
diff options
context:
space:
mode:
Diffstat (limited to 'rts/Linker.c')
-rw-r--r--rts/Linker.c141
1 files changed, 112 insertions, 29 deletions
diff --git a/rts/Linker.c b/rts/Linker.c
index 585d1e8451..81a267db1b 100644
--- a/rts/Linker.c
+++ b/rts/Linker.c
@@ -156,6 +156,10 @@ static /*Str*/HashTable *stablehash;
/* List of currently loaded objects */
ObjectCode *objects = NULL; /* initially empty */
+/* List of objects that have been unloaded via unloadObj(), but are waiting
+ to be actually freed via checkUnload() */
+ObjectCode *unloaded_objects = NULL; /* initially empty */
+
static HsInt loadOc( ObjectCode* oc );
static ObjectCode* mkOc( pathchar *path, char *image, int imageSize,
char *archiveMemberName
@@ -229,6 +233,8 @@ static void machoInitSymbolsWithoutUnderscore( void );
#endif
#endif
+static void freeProddableBlocks (ObjectCode *oc);
+
/* on x86_64 we have a problem with relocating symbol references in
* code that was compiled without -fPIC. By default, the small memory
* model is used, which assumes that symbol references can fit in a
@@ -321,7 +327,7 @@ typedef struct _RtsSymbolVal {
#define Maybe_Stable_Names SymI_HasProto(stg_mkWeakzh) \
SymI_HasProto(stg_mkWeakNoFinalizzerzh) \
- SymI_HasProto(stg_mkWeakForeignEnvzh) \
+ SymI_HasProto(stg_addCFinalizzerToWeakzh) \
SymI_HasProto(stg_makeStableNamezh) \
SymI_HasProto(stg_finalizzeWeakzh)
@@ -901,8 +907,10 @@ typedef struct _RtsSymbolVal {
SymI_NeedsProto(top_ct) \
\
SymI_HasProto(ENT_VIA_NODE_ctr) \
- SymI_HasProto(ENT_STATIC_THK_ctr) \
- SymI_HasProto(ENT_DYN_THK_ctr) \
+ SymI_HasProto(ENT_STATIC_THK_SINGLE_ctr) \
+ SymI_HasProto(ENT_STATIC_THK_MANY_ctr) \
+ SymI_HasProto(ENT_DYN_THK_SINGLE_ctr) \
+ SymI_HasProto(ENT_DYN_THK_MANY_ctr) \
SymI_HasProto(ENT_STATIC_FUN_DIRECT_ctr) \
SymI_HasProto(ENT_DYN_FUN_DIRECT_ctr) \
SymI_HasProto(ENT_STATIC_CON_ctr) \
@@ -970,8 +978,6 @@ typedef struct _RtsSymbolVal {
SymI_HasProto(UPD_NEW_PERM_IND_ctr) \
SymI_HasProto(UPD_OLD_IND_ctr) \
SymI_HasProto(UPD_OLD_PERM_IND_ctr) \
- SymI_HasProto(UPD_BH_UPDATABLE_ctr) \
- SymI_HasProto(UPD_BH_SINGLE_ENTRY_ctr) \
SymI_HasProto(UPD_CAF_BH_UPDATABLE_ctr) \
SymI_HasProto(UPD_CAF_BH_SINGLE_ENTRY_ctr) \
SymI_HasProto(GC_SEL_ABANDONED_ctr) \
@@ -1058,6 +1064,7 @@ typedef struct _RtsSymbolVal {
SymI_HasProto(stg_yield_to_interpreter) \
SymI_HasProto(stg_block_noregs) \
SymI_HasProto(stg_block_takemvar) \
+ SymI_HasProto(stg_block_readmvar) \
SymI_HasProto(stg_block_putmvar) \
MAIN_CAP_SYM \
SymI_HasProto(MallocFailHook) \
@@ -1067,7 +1074,6 @@ typedef struct _RtsSymbolVal {
SymI_HasProto(addDLL) \
SymI_HasProto(__int_encodeDouble) \
SymI_HasProto(__word_encodeDouble) \
- SymI_HasProto(__2Int_encodeDouble) \
SymI_HasProto(__int_encodeFloat) \
SymI_HasProto(__word_encodeFloat) \
SymI_HasProto(stg_atomicallyzh) \
@@ -1106,9 +1112,9 @@ typedef struct _RtsSymbolVal {
SymI_HasProto(getOrSetSystemEventThreadIOManagerThreadStore) \
SymI_HasProto(getOrSetSystemTimerThreadEventManagerStore) \
SymI_HasProto(getOrSetSystemTimerThreadIOManagerThreadStore) \
+ SymI_HasProto(getOrSetLibHSghcFastStringTable) \
SymI_HasProto(getGCStats) \
SymI_HasProto(getGCStatsEnabled) \
- SymI_HasProto(genSymZh) \
SymI_HasProto(genericRaise) \
SymI_HasProto(getProgArgv) \
SymI_HasProto(getFullProgArgv) \
@@ -1281,12 +1287,6 @@ typedef struct _RtsSymbolVal {
SymI_HasProto(stg_ap_7_upd_info) \
SymI_HasProto(stg_exit) \
SymI_HasProto(stg_sel_0_upd_info) \
- SymI_HasProto(stg_sel_10_upd_info) \
- SymI_HasProto(stg_sel_11_upd_info) \
- SymI_HasProto(stg_sel_12_upd_info) \
- SymI_HasProto(stg_sel_13_upd_info) \
- SymI_HasProto(stg_sel_14_upd_info) \
- SymI_HasProto(stg_sel_15_upd_info) \
SymI_HasProto(stg_sel_1_upd_info) \
SymI_HasProto(stg_sel_2_upd_info) \
SymI_HasProto(stg_sel_3_upd_info) \
@@ -1296,13 +1296,37 @@ typedef struct _RtsSymbolVal {
SymI_HasProto(stg_sel_7_upd_info) \
SymI_HasProto(stg_sel_8_upd_info) \
SymI_HasProto(stg_sel_9_upd_info) \
+ SymI_HasProto(stg_sel_10_upd_info) \
+ SymI_HasProto(stg_sel_11_upd_info) \
+ SymI_HasProto(stg_sel_12_upd_info) \
+ SymI_HasProto(stg_sel_13_upd_info) \
+ SymI_HasProto(stg_sel_14_upd_info) \
+ SymI_HasProto(stg_sel_15_upd_info) \
+ SymI_HasProto(stg_sel_0_noupd_info) \
+ SymI_HasProto(stg_sel_1_noupd_info) \
+ SymI_HasProto(stg_sel_2_noupd_info) \
+ SymI_HasProto(stg_sel_3_noupd_info) \
+ SymI_HasProto(stg_sel_4_noupd_info) \
+ SymI_HasProto(stg_sel_5_noupd_info) \
+ SymI_HasProto(stg_sel_6_noupd_info) \
+ SymI_HasProto(stg_sel_7_noupd_info) \
+ SymI_HasProto(stg_sel_8_noupd_info) \
+ SymI_HasProto(stg_sel_9_noupd_info) \
+ SymI_HasProto(stg_sel_10_noupd_info) \
+ SymI_HasProto(stg_sel_11_noupd_info) \
+ SymI_HasProto(stg_sel_12_noupd_info) \
+ SymI_HasProto(stg_sel_13_noupd_info) \
+ SymI_HasProto(stg_sel_14_noupd_info) \
+ SymI_HasProto(stg_sel_15_noupd_info) \
SymI_HasProto(stg_upd_frame_info) \
SymI_HasProto(stg_bh_upd_frame_info) \
SymI_HasProto(suspendThread) \
SymI_HasProto(stg_takeMVarzh) \
+ SymI_HasProto(stg_readMVarzh) \
SymI_HasProto(stg_threadStatuszh) \
SymI_HasProto(stg_tryPutMVarzh) \
SymI_HasProto(stg_tryTakeMVarzh) \
+ SymI_HasProto(stg_tryReadMVarzh) \
SymI_HasProto(stg_unmaskAsyncExceptionszh) \
SymI_HasProto(unloadObj) \
SymI_HasProto(stg_unsafeThawArrayzh) \
@@ -1500,6 +1524,9 @@ initLinker( void )
linker_init_done = 1;
}
+ objects = NULL;
+ unloaded_objects = NULL;
+
#if defined(THREADED_RTS) && (defined(OBJFORMAT_ELF) || defined(OBJFORMAT_MACHO))
initMutex(&dl_mutex);
#endif
@@ -2026,6 +2053,40 @@ mmap_again:
}
#endif // USE_MMAP
+
+void freeObjectCode (ObjectCode *oc)
+{
+ int pagesize, size, r;
+
+#ifdef USE_MMAP
+
+ pagesize = getpagesize();
+ size = ROUND_UP(oc->fileSize, pagesize);
+
+ r = munmap(oc->image, size);
+ if (r == -1) {
+ sysErrorBelch("munmap");
+ }
+
+ if (!USE_CONTIGUOUS_MMAP)
+ {
+ munmap(oc->symbol_extras,
+ ROUND_UP(sizeof(SymbolExtra) * oc->n_symbol_extras, pagesize));
+ }
+
+#else
+
+ stgFree(oc->image);
+ stgFree(oc->symbol_extras);
+
+#endif
+
+ stgFree(oc->fileName);
+ stgFree(oc->archiveMemberName);
+ stgFree(oc);
+}
+
+
static ObjectCode*
mkOc( pathchar *path, char *image, int imageSize,
char *archiveMemberName
@@ -2728,7 +2789,7 @@ resolveObjs( void )
HsInt
unloadObj( pathchar *path )
{
- ObjectCode *oc, *prev;
+ ObjectCode *oc, *prev, *next;
HsBool unloadedAnyObj = HS_BOOL_FALSE;
ASSERT(symhash != NULL);
@@ -2736,8 +2797,12 @@ unloadObj( pathchar *path )
initLinker();
+ IF_DEBUG(linker, debugBelch("unloadObj: %s\n", path));
+
prev = NULL;
- for (oc = objects; oc; prev = oc, oc = oc->next) {
+ for (oc = objects; oc; prev = oc, oc = next) {
+ next = oc->next;
+
if (!pathcmp(oc->fileName,path)) {
/* Remove all the mappings for the symbols within this
@@ -2757,22 +2822,27 @@ unloadObj( pathchar *path )
} else {
prev->next = oc->next;
}
+ oc->next = unloaded_objects;
+ unloaded_objects = oc;
- // We're going to leave this in place, in case there are
- // any pointers from the heap into it:
- // #ifdef mingw32_HOST_OS
- // If uncommenting, note that currently oc->image is
- // not the right address to free on Win64, as we added
- // 4 bytes of padding at the start
- // VirtualFree(oc->image);
- // #else
- // stgFree(oc->image);
- // #endif
- stgFree(oc->fileName);
- stgFree(oc->archiveMemberName);
+ // The data itself and a few other bits (oc->fileName,
+ // oc->archiveMemberName) are kept until freeObjectCode(),
+ // which is only called when it has been determined that
+ // it is safe to unload the object.
stgFree(oc->symbols);
- stgFree(oc->sections);
- stgFree(oc);
+
+ {
+ Section *s, *nexts;
+
+ for (s = oc->sections; s != NULL; s = nexts) {
+ nexts = s->next;
+ stgFree(s);
+ }
+ }
+
+ freeProddableBlocks(oc);
+
+ oc->status = OBJECT_UNLOADED;
/* This could be a member of an archive so continue
* unloading other members. */
@@ -2822,6 +2892,17 @@ checkProddableBlock (ObjectCode *oc, void *addr, size_t size )
barf("checkProddableBlock: invalid fixup in runtime linker: %p", addr);
}
+static void freeProddableBlocks (ObjectCode *oc)
+{
+ ProddableBlock *pb, *next;
+
+ for (pb = oc->proddables; pb != NULL; pb = next) {
+ next = pb->next;
+ stgFree(pb);
+ }
+ oc->proddables = NULL;
+}
+
/* -----------------------------------------------------------------------------
* Section management.
*/
@@ -2910,6 +2991,7 @@ static int ocAllocateSymbolExtras( ObjectCode* oc, int count, int first )
memcpy(new, oc->image, oc->fileSize);
munmap(oc->image, n);
oc->image = new;
+ oc->fileSize = n + (sizeof(SymbolExtra) * count);
oc->symbol_extras = (SymbolExtra *) (oc->image + n);
}
else
@@ -4941,6 +5023,7 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
// Generate veneer
SymbolExtra *extra = makeArmSymbolExtra(oc, ELF_R_SYM(info), S+imm+4, 1, is_target_thm);
offset = (StgWord32) &extra->jumpIsland - P - 4;
+ sign = offset >> 31;
to_thm = 1;
} else if (!is_target_thm && ELF_R_TYPE(info) == R_ARM_THM_CALL) {
offset &= ~0x3;