summaryrefslogtreecommitdiff
path: root/rts/Linker.c
diff options
context:
space:
mode:
authorGHC GitLab CI <ghc-ci@gitlab-haskell.org>2021-10-08 11:34:48 +0000
committerMarge Bot <ben+marge-bot@smart-cactus.org>2021-10-12 01:41:04 -0400
commit2c06720e45efaf4d3a8e957f3ea7613d1ea311a8 (patch)
treef794e15618f9b50f9b4ab7fe199b72c73e55ea88 /rts/Linker.c
parent2e0c13ab50b28d3e2ad5bfeed2b6651096921c9d (diff)
downloadhaskell-2c06720e45efaf4d3a8e957f3ea7613d1ea311a8.tar.gz
rts/Linker: Fix __dso_handle handling
Previously the linker's handling of __dso_handle was quite wrong. Not only did we claim that __dso_handle could be NULL when statically linking (which it can not), we didn't even implement this mislead theory faithfully and instead resolved the symbol to a random pointer. This lead to the failing relocations on AArch64 noted in #20493. Here we try to implement __dso_handle as a dynamic linker would do, choosing an address within the loaded object (specifically its start address) to serve as the object's handle.
Diffstat (limited to 'rts/Linker.c')
-rw-r--r--rts/Linker.c37
1 files changed, 27 insertions, 10 deletions
diff --git a/rts/Linker.c b/rts/Linker.c
index 2641a677be..d297f3a8ff 100644
--- a/rts/Linker.c
+++ b/rts/Linker.c
@@ -450,16 +450,6 @@ initLinker_ (int retain_cafs)
IF_DEBUG(linker, debugBelch("initLinker: inserting rts symbol %s, %p\n", sym->lbl, sym->addr));
}
- /* GCC defines a special symbol __dso_handle which is resolved to NULL if
- referenced from a statically linked module. We need to mimic this, but
- we cannot use NULL because we use it to mean nonexistent symbols. So we
- use an arbitrary (hopefully unique) address here.
- */
- if (! ghciInsertSymbolTable(WSTR("(GHCi special symbols)"),
- symhash, "__dso_handle", (void *)0x12345687, HS_BOOL_FALSE, NULL)) {
- barf("ghciInsertSymbolTable failed");
- }
-
// Redirect newCAF to newRetainedCAF if retain_cafs is true.
if (! ghciInsertSymbolTable(WSTR("(GHCi built-in symbols)"), symhash,
MAYBE_LEADING_UNDERSCORE_STR("newCAF"),
@@ -865,6 +855,17 @@ SymbolAddr* lookupDependentSymbol (SymbolName* lbl, ObjectCode *dependent)
ASSERT(symhash != NULL);
RtsSymbolInfo *pinfo;
+ /* See Note [Resolving __dso_handle] */
+ if (strcmp(lbl, "__dso_handle") == 0) {
+ if (dependent) {
+ return dependent->image;
+ } else {
+ // In the case that we don't know which object the reference lives
+ // in we return a random symbol from the executable image.
+ return &lookupDependentSymbol;
+ }
+ }
+
if (!ghciLookupSymbolInfo(symhash, lbl, &pinfo)) {
IF_DEBUG(linker, debugBelch("lookupSymbol: symbol '%s' not found, trying dlsym\n", lbl));
@@ -900,6 +901,22 @@ SymbolAddr* lookupDependentSymbol (SymbolName* lbl, ObjectCode *dependent)
}
#endif /* OBJFORMAT_PEi386 */
+/* Note [Resolving __dso_handle]
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * This symbol, which is defined by the C++ ABI, would typically be defined by
+ * the system's dynamic linker to act as a "handle", identifying a particular
+ * loaded dynamic object to the C++ standard library for the purpose of running
+ * destructors on unload. Here we behave the same way that the dynamic linker
+ * would, using some address (here the start address) of the loaded object as
+ * its handle.
+ *
+ * Note that references to __dso_handle may be relocated using
+ * relocations of bounded displacement and therefore __dso_handle must not be
+ * too far from the loaded object's code (hence using its start address).
+ *
+ * See #20493.
+ */
+
/*
* Load and relocate the object code for a symbol as necessary.
* Symbol name only used for diagnostics output.