Skip to content

Commit

Permalink
Fix linker_unload now that we are running constructors in the linker …
Browse files Browse the repository at this point in the history
…(#8291)

See also #5435.

Now we have to remember the the StablePtrs that get created by the
module initializer so that we can free them again in unloadObj().
  • Loading branch information
simonmar committed Sep 23, 2013
1 parent f5879ac commit 1908195
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 1 deletion.
2 changes: 1 addition & 1 deletion compiler/deSugar/DsForeign.lhs
Original file line number Diff line number Diff line change
Expand Up @@ -676,7 +676,7 @@ foreignExportInitialiser hs_fn =
[ text "static void stginit_export_" <> ppr hs_fn
<> text "() __attribute__((constructor));"
, text "static void stginit_export_" <> ppr hs_fn <> text "()"
, braces (text "getStablePtr"
, braces (text "foreignExportStablePtr"
<> parens (text "(StgPtr) &" <> ppr hs_fn <> text "_closure")
<> semi)
]
Expand Down
3 changes: 3 additions & 0 deletions includes/rts/Linker.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,7 @@ HsInt resolveObjs( void );
/* load a dynamic library */
const char *addDLL( pathchar* dll_name );

/* called by the initialization code for a module, not a user API */
StgStablePtr foreignExportStablePtr (StgPtr p);

#endif /* RTS_LINKER_H */
49 changes: 49 additions & 0 deletions rts/Linker.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) \
Expand Down Expand Up @@ -1947,6 +1948,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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand Down
13 changes: 13 additions & 0 deletions rts/LinkerInternals.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down Expand Up @@ -120,6 +131,8 @@ typedef struct _ObjectCode {
unsigned long n_symbol_extras;
#endif

ForeignExportStablePtr *stable_ptrs;

} ObjectCode;

#define OC_INFORMATIVE_FILENAME(OC) \
Expand Down

0 comments on commit 1908195

Please sign in to comment.