summaryrefslogtreecommitdiff
path: root/rts/Linker.c
diff options
context:
space:
mode:
authorTamar Christina <tamar@zhox.com>2018-12-04 00:29:08 +0000
committerTamar Christina <tamar@zhox.com>2018-12-04 07:15:26 +0000
commita8b7cef4d45a5003bf7584e06912f0f632116c71 (patch)
tree545d2e40786f0fc83186fd4d8d8f5fe396d13458 /rts/Linker.c
parent924026e0405396a3f559f163e829b88f30cca49e (diff)
downloadhaskell-a8b7cef4d45a5003bf7584e06912f0f632116c71.tar.gz
linker: store entire link map and use it.
Summary: This fixes a corner case in which we have seen the symbol multiple times in different static libraries, but due to a depencency we end up loading the symbol from a library other than the first one. Previously the runtime linker would only track symbols from the first library and did not store the full link map. In this case it was unable to find the address for the symbols in the second library during delay loading. This change stores the address of all symbols seen so a full link map is generated, such that when we make a different decision later than what was expected we're able to still correctly load the library. Test Plan: ./validate, new testcase T15894 Reviewers: angerman, bgamari, erikd, simonmar Reviewed By: bgamari Subscribers: rwbarton, carter GHC Trac Issues: #15894 Differential Revision: https://phabricator.haskell.org/D5353
Diffstat (limited to 'rts/Linker.c')
-rw-r--r--rts/Linker.c23
1 files changed, 13 insertions, 10 deletions
diff --git a/rts/Linker.c b/rts/Linker.c
index 826269738b..5b10b798ec 100644
--- a/rts/Linker.c
+++ b/rts/Linker.c
@@ -964,7 +964,7 @@ void ghci_enquire(SymbolAddr* addr)
for (oc = objects; oc; oc = oc->next) {
for (i = 0; i < oc->n_symbols; i++) {
- sym = oc->symbols[i];
+ sym = oc->symbols[i].name;
if (sym == NULL) continue;
a = NULL;
if (a == NULL) {
@@ -1106,8 +1106,8 @@ static void removeOcSymbols (ObjectCode *oc)
// Remove all the mappings for the symbols within this object..
int i;
for (i = 0; i < oc->n_symbols; i++) {
- if (oc->symbols[i] != NULL) {
- ghciRemoveSymbolTable(symhash, oc->symbols[i], oc);
+ if (oc->symbols[i].name != NULL) {
+ ghciRemoveSymbolTable(symhash, oc->symbols[i].name, oc);
}
}
@@ -1576,18 +1576,21 @@ int ocTryLoad (ObjectCode* oc) {
are to be loaded by this call.
This call is intended to have no side-effects when a non-duplicate
- symbol is re-inserted.
+ symbol is re-inserted. A symbol is only a duplicate if the object file
+ it is defined in has had it's relocations resolved. A resolved object
+ file means the symbols inside it are required.
- We set the Address to NULL since that is not used to distinguish
- symbols. Duplicate symbols are distinguished by name and oc.
+ The symbol address is not used to distinguish symbols. Duplicate symbols
+ are distinguished by name, oc and attributes (weak symbols etc).
*/
int x;
- SymbolName* symbol;
+ Symbol_t symbol;
for (x = 0; x < oc->n_symbols; x++) {
symbol = oc->symbols[x];
- if ( symbol
- && !ghciInsertSymbolTable(oc->fileName, symhash, symbol, NULL,
- isSymbolWeak(oc, symbol), oc)) {
+ if ( symbol.name
+ && !ghciInsertSymbolTable(oc->fileName, symhash, symbol.name,
+ symbol.addr,
+ isSymbolWeak(oc, symbol.name), oc)) {
return 0;
}
}