diff options
Diffstat (limited to 'rts')
| -rw-r--r-- | rts/Linker.c | 49 | ||||
| -rw-r--r-- | rts/LinkerInternals.h | 13 |
2 files changed, 62 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 diff --git a/rts/LinkerInternals.h b/rts/LinkerInternals.h index b788ea7022..e1942bc8ae 100644 --- a/rts/LinkerInternals.h +++ b/rts/LinkerInternals.h @@ -44,6 +44,17 @@ typedef } ProddableBlock; +/* + * We must keep track of the StablePtrs that are created for foreign + * exports by constructor functions when the module is loaded, so that + * we can free them again when the module is unloaded. If we don't do + * this, then the StablePtr will keep the module alive indefinitely. + */ +typedef struct ForeignExportStablePtr_ { + StgStablePtr stable_ptr; + struct ForeignExportStablePtr_ *next; +} ForeignExportStablePtr; + /* Jump Islands are sniplets of machine code required for relative * address relocations on the PowerPC, x86_64 and ARM. */ @@ -120,6 +131,8 @@ typedef struct _ObjectCode { unsigned long n_symbol_extras; #endif + ForeignExportStablePtr *stable_ptrs; + } ObjectCode; #define OC_INFORMATIVE_FILENAME(OC) \ |
