diff options
| -rw-r--r-- | rts/Linker.c | 52 |
1 files changed, 50 insertions, 2 deletions
diff --git a/rts/Linker.c b/rts/Linker.c index 4ae9193a11..2d7e7d78a7 100644 --- a/rts/Linker.c +++ b/rts/Linker.c @@ -1588,9 +1588,32 @@ static OpenedDLL* opened_dlls = NULL; # if defined(OBJFORMAT_ELF) || defined(OBJFORMAT_MACHO) +/* Suppose in ghci we load a temporary SO for a module containing + f = 1 + and then modify the module, recompile, and load another temporary + SO with + f = 2 + Then as we don't unload the first SO, dlsym will find the + f = 1 + symbol whereas we want the + f = 2 + symbol. We therefore need to keep our own SO handle list, and + try SOs in the right order. */ + +typedef + struct _OpenedSO { + struct _OpenedSO* next; + void *handle; + } + OpenedSO; + +/* A list thereof. */ +static OpenedSO* openedSOs = NULL; + static const char * internal_dlopen(const char *dll_name) { + OpenedSO* o_so; void *hdl; const char *errmsg; char *errmsg_copy; @@ -1618,11 +1641,36 @@ internal_dlopen(const char *dll_name) strcpy(errmsg_copy, errmsg); errmsg = errmsg_copy; } + o_so = stgMallocBytes(sizeof(OpenedSO), "addDLL"); + o_so->handle = hdl; + o_so->next = openedSOs; + openedSOs = o_so; + RELEASE_LOCK(&dl_mutex); //--------------- End critical section ------------------- return errmsg; } + +static void * +internal_dlsym(void *hdl, const char *symbol) { + OpenedSO* o_so; + void *v; + + // We acquire dl_mutex as concurrent dl* calls may alter dlerror + ACQUIRE_LOCK(&dl_mutex); + dlerror(); + for (o_so = openedSOs; o_so != NULL; o_so = o_so->next) { + v = dlsym(o_so->handle, symbol); + if (dlerror() == NULL) { + RELEASE_LOCK(&dl_mutex); + return v; + } + } + v = dlsym(hdl, symbol) + RELEASE_LOCK(&dl_mutex); + return v; +} # endif const char * @@ -1798,7 +1846,7 @@ lookupSymbol( char *lbl ) if (val == NULL) { IF_DEBUG(linker, debugBelch("lookupSymbol: symbol not found\n")); # if defined(OBJFORMAT_ELF) - return dlsym(dl_prog_handle, lbl); + return internal_dlsym(dl_prog_handle, lbl); # elif defined(OBJFORMAT_MACHO) # if HAVE_DLFCN_H /* On OS X 10.3 and later, we use dlsym instead of the old legacy @@ -1812,7 +1860,7 @@ lookupSymbol( char *lbl ) */ IF_DEBUG(linker, debugBelch("lookupSymbol: looking up %s with dlsym\n", lbl)); ASSERT(lbl[0] == '_'); - return dlsym(dl_prog_handle, lbl + 1); + return internal_dlsym(dl_prog_handle, lbl + 1); # else if (NSIsSymbolNameDefined(lbl)) { NSSymbol symbol = NSLookupAndBindSymbol(lbl); |
