diff options
author | GHC GitLab CI <ghc-ci@gitlab-haskell.org> | 2021-10-08 11:34:48 +0000 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2021-10-12 01:41:04 -0400 |
commit | 2c06720e45efaf4d3a8e957f3ea7613d1ea311a8 (patch) | |
tree | f794e15618f9b50f9b4ab7fe199b72c73e55ea88 /rts/Linker.c | |
parent | 2e0c13ab50b28d3e2ad5bfeed2b6651096921c9d (diff) | |
download | haskell-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.c | 37 |
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. |