summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGHC GitLab CI <ghc-ci@gitlab-haskell.org>2021-10-08 11:34:48 +0000
committerCheng Shao <cheng.shao@tweag.io>2021-10-28 17:28:18 +0000
commit26eb8324f99c04e54c23e4f43e2454d76df44452 (patch)
treecb0d51df7b79127b5092eac6c60a8b15f8f2d9bf
parenta3db355edd2fe7e44e66624bab22551e901128d6 (diff)
downloadhaskell-26eb8324f99c04e54c23e4f43e2454d76df44452.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. (cherry picked from commit 2c06720e45efaf4d3a8e957f3ea7613d1ea311a8)
-rw-r--r--rts/Linker.c37
1 files changed, 27 insertions, 10 deletions
diff --git a/rts/Linker.c b/rts/Linker.c
index f1c0db7c92..ae44aed4ca 100644
--- a/rts/Linker.c
+++ b/rts/Linker.c
@@ -457,16 +457,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"),
@@ -872,6 +862,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));
@@ -908,6 +909,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.