summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2022-05-11 15:51:36 -0400
committerMatthew Pickering <matthewtpickering@gmail.com>2022-06-20 12:21:49 +0100
commit20a0163b4081d6439a5621b50ef3bb1f90a8d4c8 (patch)
treec674ce0e4bd6ec12113b09aec2b7ae164667cbdb
parentd23e91bdb6ba17974537e1e4cbb53a6cf530e7de (diff)
downloadhaskell-20a0163b4081d6439a5621b50ef3bb1f90a8d4c8.tar.gz
rts/PEi386: Fix handling of weak symbols
Previously we would flag the symbol as weak but failed to set its address, which must be computed from an "auxiliary" symbol entry the follows the weak symbol. Fixes #21556. (cherry picked from commit 53b3fa1c782b251076707a024f55276d4ccb0a6c)
-rw-r--r--rts/linker/PEi386.c7
-rw-r--r--rts/linker/PEi386.h6
-rw-r--r--testsuite/tests/ghci/linking/all.T2
3 files changed, 13 insertions, 2 deletions
diff --git a/rts/linker/PEi386.c b/rts/linker/PEi386.c
index 82eaaaf226..f6e87dd0e6 100644
--- a/rts/linker/PEi386.c
+++ b/rts/linker/PEi386.c
@@ -1657,6 +1657,13 @@ ocGetNames_PEi386 ( ObjectCode* oc )
}
else if (symStorageClass == IMAGE_SYM_CLASS_WEAK_EXTERNAL) {
isWeak = true;
+ CHECK(getSymNumberOfAuxSymbols (info, sym) == 1);
+ CHECK(symValue == 0);
+ COFF_symbol_aux_weak_external *aux = (COFF_symbol_aux_weak_external *) (sym+1);
+ COFF_symbol* targetSym = &oc->info->symbols[aux->TagIndex];
+ int32_t targetSecNumber = getSymSectionNumber (info, targetSym);
+ Section *targetSection = targetSecNumber > 0 ? &oc->sections[targetSecNumber-1] : NULL;
+ addr = (SymbolAddr*) ((size_t) targetSection->start + getSymValue(info, targetSym));
}
else if ( secNumber == IMAGE_SYM_UNDEFINED && symValue > 0) {
/* This symbol isn't in any section at all, ie, global bss.
diff --git a/rts/linker/PEi386.h b/rts/linker/PEi386.h
index c5c88459a6..cde5974d54 100644
--- a/rts/linker/PEi386.h
+++ b/rts/linker/PEi386.h
@@ -117,6 +117,12 @@ union _COFF_symbol {
COFF_symbol_ex ex;
} COFF_symbol;
+typedef
+struct {
+ uint32_t TagIndex;
+ uint32_t Characteristics;
+} COFF_symbol_aux_weak_external;
+
/* A record for storing handles into DLLs. */
typedef
struct _OpenedDLL {
diff --git a/testsuite/tests/ghci/linking/all.T b/testsuite/tests/ghci/linking/all.T
index b4564f0237..197500c039 100644
--- a/testsuite/tests/ghci/linking/all.T
+++ b/testsuite/tests/ghci/linking/all.T
@@ -42,8 +42,6 @@ test('ghcilink006',
test('T3333',
[unless(doing_ghci, skip),
- unless(opsys('linux') or opsys('darwin') or ghc_dynamic(),
- expect_broken(3333)),
when(unregisterised(), fragile(17018))],
makefile_test, ['T3333'])