diff options
Diffstat (limited to 'rts/Linker.c')
| -rw-r--r-- | rts/Linker.c | 49 |
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 |
