From 20a0163b4081d6439a5621b50ef3bb1f90a8d4c8 Mon Sep 17 00:00:00 2001
From: Ben Gamari <ben@smart-cactus.org>
Date: Wed, 11 May 2022 15:51:36 -0400
Subject: [PATCH] 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)
---
 rts/linker/PEi386.c                | 7 +++++++
 rts/linker/PEi386.h                | 6 ++++++
 testsuite/tests/ghci/linking/all.T | 2 --
 3 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/rts/linker/PEi386.c b/rts/linker/PEi386.c
index 82eaaaf2261d..f6e87dd0e65d 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 c5c88459a6c5..cde5974d5408 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 b4564f02373f..197500c0390b 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'])
 
-- 
GitLab