summaryrefslogtreecommitdiff
path: root/rts/Linker.c
diff options
context:
space:
mode:
Diffstat (limited to 'rts/Linker.c')
-rw-r--r--rts/Linker.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/rts/Linker.c b/rts/Linker.c
index 31f60c09ac..7334a806af 100644
--- a/rts/Linker.c
+++ b/rts/Linker.c
@@ -1116,6 +1116,7 @@ typedef struct _RtsSymbolVal {
SymI_HasProto(getProgArgv) \
SymI_HasProto(getFullProgArgv) \
SymI_HasProto(getStablePtr) \
+ SymI_HasProto(foreignExportStablePtr) \
SymI_HasProto(hs_init) \
SymI_HasProto(hs_exit) \
SymI_HasProto(hs_set_argv) \
@@ -1948,6 +1949,37 @@ lookupSymbol( char *lbl )
}
/* -----------------------------------------------------------------------------
+ Create a StablePtr for a foeign export. This is normally called by
+ a C function with __attribute__((constructor)), which is generated
+ by GHC and linked into the module.
+
+ If the object code is being loaded dynamically, then we remember
+ which StablePtrs were allocated by the constructors and free them
+ again in unloadObj().
+ -------------------------------------------------------------------------- */
+
+static ObjectCode *loading_obj = NULL;
+
+StgStablePtr foreignExportStablePtr (StgPtr p)
+{
+ ForeignExportStablePtr *fe_sptr;
+ StgStablePtr *sptr;
+
+ sptr = getStablePtr(p);
+
+ if (loading_obj != NULL) {
+ fe_sptr = stgMallocBytes(sizeof(ForeignExportStablePtr),
+ "foreignExportStablePtr");
+ fe_sptr->stable_ptr = sptr;
+ fe_sptr->next = loading_obj->stable_ptrs;
+ loading_obj->stable_ptrs = fe_sptr;
+ }
+
+ return sptr;
+}
+
+
+/* -----------------------------------------------------------------------------
* Debugging aid: look in GHCi's object symbol tables for symbols
* within DELTA bytes of the specified address, and show their names.
*/
@@ -2143,6 +2175,7 @@ mkOc( pathchar *path, char *image, int imageSize,
oc->symbols = NULL;
oc->sections = NULL;
oc->proddables = NULL;
+ oc->stable_ptrs = NULL;
#ifndef USE_MMAP
#ifdef darwin_HOST_OS
@@ -2786,6 +2819,8 @@ resolveObjs( void )
if (!r) { return r; }
// run init/init_array/ctors/mod_init_func
+
+ loading_obj = oc; // tells foreignExportStablePtr what to do
#if defined(OBJFORMAT_ELF)
r = ocRunInit_ELF ( oc );
#elif defined(OBJFORMAT_PEi386)
@@ -2795,6 +2830,8 @@ resolveObjs( void )
#else
barf("resolveObjs: initializers not implemented on this platform");
#endif
+ loading_obj = NULL;
+
if (!r) { return r; }
oc->status = OBJECT_RESOLVED;
@@ -2863,6 +2900,18 @@ unloadObj( pathchar *path )
freeProddableBlocks(oc);
+ // Release any StablePtrs that were created when this
+ // object module was initialized.
+ {
+ ForeignExportStablePtr *fe_ptr, *next;
+
+ for (fe_ptr = oc->stable_ptrs; fe_ptr != NULL; fe_ptr = next) {
+ next = fe_ptr->next;
+ freeStablePtr(fe_ptr->stable_ptr);
+ stgFree(fe_ptr);
+ }
+ }
+
oc->status = OBJECT_UNLOADED;
/* This could be a member of an archive so continue