summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rts/Linker.c18
-rw-r--r--rts/LinkerInternals.h7
2 files changed, 25 insertions, 0 deletions
diff --git a/rts/Linker.c b/rts/Linker.c
index 0672873a2d..1faff3b371 100644
--- a/rts/Linker.c
+++ b/rts/Linker.c
@@ -855,6 +855,12 @@ SymbolAddr* lookupDependentSymbol (SymbolName* lbl, ObjectCode *dependent, SymTy
return &lookupDependentSymbol;
}
}
+ if (strcmp(lbl, MAYBE_LEADING_UNDERSCORE_STR("__cxa_atexit")) == 0 && dependent) {
+ dependent->cxa_finalize = (cxa_finalize_fn) lookupDependentSymbol(
+ MAYBE_LEADING_UNDERSCORE_STR("__cxa_finalize"),
+ dependent,
+ NULL);
+ }
if (!ghciLookupSymbolInfo(symhash, lbl, &pinfo)) {
IF_DEBUG(linker_verbose, debugBelch("lookupSymbol: symbol '%s' not found, trying dlsym\n", lbl));
@@ -937,7 +943,13 @@ SymbolAddr* lookupDependentSymbol (SymbolName* lbl, ObjectCode *dependent, SymTy
* relocations of bounded displacement and therefore __dso_handle must not be
* too far from the loaded object's code (hence using its start address).
*
+ * Finally, when we see a reference to __cxa_atexit in an object we take care
+ * to lookup and record the address of __cxa_finalize (largely to ensure that
+ * the symbol dependency is recorded) and call it with the appropriate handle
+ * when the object is unloaded.
+ *
* See #20493.
+ * See section 3.3.5 of the Itanium C++ ABI, version 1.83.
*/
/*
@@ -1150,6 +1162,11 @@ void freeObjectCode (ObjectCode *oc)
#endif
}
+ // See Note [Resolving __dso_handle]
+ if (oc->cxa_finalize) {
+ oc->cxa_finalize(oc->image);
+ }
+
if (oc->type == DYNAMIC_OBJECT) {
#if defined(OBJFORMAT_ELF)
ACQUIRE_LOCK(&dl_mutex);
@@ -1300,6 +1317,7 @@ mkOc( ObjectType type, pathchar *path, char *image, int imageSize,
oc->imageMapped = mapped;
oc->misalignment = misalignment;
+ oc->cxa_finalize = NULL;
oc->extraInfos = NULL;
/* chain it onto the list of objects */
diff --git a/rts/LinkerInternals.h b/rts/LinkerInternals.h
index 5370c86357..bafd7f0543 100644
--- a/rts/LinkerInternals.h
+++ b/rts/LinkerInternals.h
@@ -239,6 +239,8 @@ typedef enum {
DYNAMIC_OBJECT,
} ObjectType;
+typedef void (*cxa_finalize_fn)(void *);
+
/* Top-level structure for an object module. One of these is allocated
* for each object file in use.
*/
@@ -276,6 +278,11 @@ struct _ObjectCode {
after allocation, so that we can use realloc */
int misalignment;
+ /* The address of __cxa_finalize; set when at least one finalizer was
+ * register and therefore we must call __cxa_finalize before unloading.
+ * See Note [Resolving __dso_handle]. */
+ cxa_finalize_fn cxa_finalize;
+
/* The section-kind entries for this object module. An array. */
int n_sections;
Section* sections;