Skip to content

Commit

Permalink
[ghc linker] fix hidden symbols (#2164)
Browse files Browse the repository at this point in the history
* Backport support for hidden symbols for windows to 8.10

---------

Co-authored-by: Hamish Mackenzie <[email protected]>
  • Loading branch information
angerman and hamishmack authored Feb 24, 2024
1 parent 1aba987 commit 1aa9e3c
Show file tree
Hide file tree
Showing 4 changed files with 378 additions and 1 deletion.
3 changes: 3 additions & 0 deletions overlays/bootstrap.nix
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,9 @@ in {
# Fix the bad fixups: https://gitlab.haskell.org/ghc/ghc/-/commit/2adc050857a9c1b992040fbfd55fbe65b2851b19
++ final.lib.optional (versionAtLeast "9.6" && versionLessThan "9.6.4" && final.stdenv.targetPlatform.isAarch64) ./patches/ghc/2adc050857a9c1b992040fbfd55fbe65b2851b19.patch
++ final.lib.optional (versionAtLeast "8.10.7" && versionLessThan "9.0" && final.stdenv.targetPlatform.isAarch64 && final.stdenv.targetPlatform.isMusl && final.stdenv.targetPlatform != final.stdenv.hostPlatform) ./patches/ghc/ghc-8.10-aarch64-musl-gettimeofday.patch
# These two patches are needed for libblst, which has now hidden symbols, which the linker doesn't know how to deal with.
++ final.lib.optional (versionAtLeast "8.10" && versionLessThan "8.11") ./patches/ghc/ghc-8.10-0006-Adds-support-for-Hidden-symbols.patch
++ final.lib.optional (versionAtLeast "8.10" && versionLessThan "8.11") ./patches/ghc/ghc-8.10-0006-Adds-support-for-Hidden-symbols-2.patch
;
in ({
ghc865 = final.callPackage ../compiler/ghc (traceWarnOld "8.6" {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
diff --git a/rts/Linker.c b/rts/Linker.c
index 5b3421d..7a6e3b6 100644
--- a/rts/Linker.c
+++ b/rts/Linker.c
@@ -267,10 +267,12 @@ int ghciInsertSymbolTable(
HashTable *table,
const SymbolName* key,
SymbolAddr* data,
- HsBool weak,
- HsBool hidden,
+ int flags,
ObjectCode *owner)
{
+ HsBool weak = flags & 1;
+ HsBool hidden = flags & 2;
+
RtsSymbolInfo *pinfo = lookupStrHashTable(table, key);
if (!pinfo) /* new entry */
{
@@ -352,7 +354,6 @@ int ghciInsertSymbolTable(
pinfo->hidden = hidden;
return 1;
}
-
pathchar* archiveName = NULL;
debugBelch(
"GHC runtime linker: fatal error: I found a duplicate definition for symbol\n"
@@ -467,7 +468,7 @@ initLinker_ (int retain_cafs)
for (sym = rtsSyms; sym->lbl != NULL; sym++) {
if (! ghciInsertSymbolTable(WSTR("(GHCi built-in symbols)"),
symhash, sym->lbl, sym->addr,
- sym->weak, HS_BOOL_FALSE, NULL)) {
+ sym->weak | (HS_BOOL_FALSE << 1), NULL)) {
barf("ghciInsertSymbolTable failed");
}
IF_DEBUG(linker, debugBelch("initLinker: inserting rts symbol %s, %p\n", sym->lbl, sym->addr));
@@ -479,7 +480,7 @@ initLinker_ (int retain_cafs)
use an arbitrary (hopefully unique) address here.
*/
if (! ghciInsertSymbolTable(WSTR("(GHCi special symbols)"),
- symhash, "__dso_handle", (void *)0x12345687, HS_BOOL_FALSE, HS_BOOL_FALSE, NULL)) {
+ symhash, "__dso_handle", (void *)0x12345687, HS_BOOL_FALSE | (HS_BOOL_FALSE << 1), NULL)) {
barf("ghciInsertSymbolTable failed");
}

@@ -487,7 +488,7 @@ initLinker_ (int retain_cafs)
if (! ghciInsertSymbolTable(WSTR("(GHCi built-in symbols)"), symhash,
MAYBE_LEADING_UNDERSCORE_STR("newCAF"),
retain_cafs ? newRetainedCAF : newGCdCAF,
- HS_BOOL_FALSE, HS_BOOL_FALSE, NULL)) {
+ HS_BOOL_FALSE | (HS_BOOL_FALSE << 1), NULL)) {
barf("ghciInsertSymbolTable failed");
}

@@ -860,8 +861,8 @@ HsBool removeLibrarySearchPath(HsPtr dll_path_index)
*/
HsInt insertSymbol(pathchar* obj_name, SymbolName* key, SymbolAddr* data)
{
- return ghciInsertSymbolTable(obj_name, symhash, key, data, HS_BOOL_FALSE,
- HS_BOOL_FALSE, NULL);
+ return ghciInsertSymbolTable(obj_name, symhash, key, data,
+ HS_BOOL_FALSE | (HS_BOOL_FALSE << 1), NULL);
}

/* -----------------------------------------------------------------------------
@@ -1715,8 +1716,8 @@ int ocTryLoad (ObjectCode* oc) {
if ( symbol.name
&& !ghciInsertSymbolTable(oc->fileName, symhash, symbol.name,
symbol.addr,
- isSymbolWeak(oc, symbol.name),
- HS_BOOL_FALSE, oc)) {
+ isSymbolWeak(oc, symbol.name) | (HS_BOOL_FALSE << 1),
+ oc)) {
return 0;
}
}
diff --git a/rts/LinkerInternals.h b/rts/LinkerInternals.h
index 1bc082c..b40d14e 100644
--- a/rts/LinkerInternals.h
+++ b/rts/LinkerInternals.h
@@ -334,8 +334,7 @@ int ghciInsertSymbolTable(
HashTable *table,
const SymbolName* key,
SymbolAddr* data,
- HsBool weak,
- HsBool hidden,
+ int flags,
ObjectCode *owner);

/* Lock-free version of lookupSymbol. When 'dependent' is not NULL, adds it as a
diff --git a/rts/linker/Elf.c b/rts/linker/Elf.c
index 4a53687..e166e20 100644
--- a/rts/linker/Elf.c
+++ b/rts/linker/Elf.c
@@ -976,8 +976,8 @@ ocGetNames_ELF ( ObjectCode* oc )
setWeakSymbol(oc, nm);
}
if (!ghciInsertSymbolTable(oc->fileName, symhash,
- nm, symbol->addr, isWeak,
- ELF_ST_VISIBILITY(symbol->elf_sym->st_other) == STV_HIDDEN,
+ nm, symbol->addr,
+ isWeak | ((ELF_ST_VISIBILITY(symbol->elf_sym->st_other) == STV_HIDDEN) << 1),
oc)
) {
goto fail;
diff --git a/rts/linker/MachO.c b/rts/linker/MachO.c
index 00b0dce..d633699 100644
--- a/rts/linker/MachO.c
+++ b/rts/linker/MachO.c
@@ -1336,7 +1336,7 @@ ocGetNames_MachO(ObjectCode* oc)
, symhash
, nm
, addr
- , HS_BOOL_FALSE
+ , HS_BOOL_FALSE | (HS_BOOL_FALSE << 1)
, oc);

oc->symbols[curSymbol].name = nm;
@@ -1376,7 +1376,7 @@ ocGetNames_MachO(ObjectCode* oc)

IF_DEBUG(linker, debugBelch("ocGetNames_MachO: inserting common symbol: %s\n", nm));
ghciInsertSymbolTable(oc->fileName, symhash, nm,
- (void*)commonCounter, HS_BOOL_FALSE, oc);
+ (void*)commonCounter, HS_BOOL_FALSE | (HS_BOOL_FALSE << 1), oc);
oc->symbols[curSymbol].name = nm;
oc->symbols[curSymbol].addr = oc->info->macho_symbols[i].addr;
curSymbol++;
diff --git a/rts/linker/PEi386.c b/rts/linker/PEi386.c
index 841faa8..d847d13 100644
--- a/rts/linker/PEi386.c
+++ b/rts/linker/PEi386.c
@@ -292,7 +292,7 @@ const void* __rts_iob_func = (void*)&__acrt_iob_func;
void initLinker_PEi386()
{
if (!ghciInsertSymbolTable(WSTR("(GHCi/Ld special symbols)"),
- symhash, "__image_base__", __image_base, HS_BOOL_TRUE, HS_BOOL_FALSE, NULL)) {
+ symhash, "__image_base__", __image_base, HS_BOOL_TRUE | (HS_BOOL_FALSE << 1), NULL)) {
barf("ghciInsertSymbolTable failed");
}

@@ -1541,7 +1541,7 @@ ocGetNames_PEi386 ( ObjectCode* oc )
sname = strdup (sname);
addr = strdup (addr);
if (!ghciInsertSymbolTable(oc->fileName, symhash, sname,
- addr, false, HS_BOOL_FALSE, oc)) {
+ addr, HS_BOOL_FALSE | (HS_BOOL_FALSE << 1), oc)) {
releaseOcInfo (oc);
stgFree (oc->image);
oc->image = NULL;
@@ -1759,8 +1759,8 @@ ocGetNames_PEi386 ( ObjectCode* oc )
stgFree(tmp);
sname = strdup (sname);
if (!ghciInsertSymbolTable(oc->fileName, symhash, sname,
- addr, false,
- section->info->props & IMAGE_SCN_LNK_COMDAT,
+ addr,
+ HS_BOOL_FALSE | ((secNumber == IMAGE_SYM_UNDEFINED) << 1),
oc))
return false;

@@ -1779,8 +1779,7 @@ ocGetNames_PEi386 ( ObjectCode* oc )
setWeakSymbol(oc, sname);
}
if (! ghciInsertSymbolTable(oc->fileName, symhash, sname, addr,
- isWeak,
- section->info->props & IMAGE_SCN_LNK_COMDAT,
+ isWeak | ((secNumber == IMAGE_SYM_UNDEFINED) << 1),
oc))
return false;
} else {
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
diff --git a/rts/Linker.c b/rts/Linker.c
index 10b0764..587f16a 100644
--- a/rts/Linker.c
+++ b/rts/Linker.c
@@ -268,6 +268,7 @@ int ghciInsertSymbolTable(
const SymbolName* key,
SymbolAddr* data,
HsBool weak,
+ HsBool hidden,
ObjectCode *owner)
{
RtsSymbolInfo *pinfo = lookupStrHashTable(table, key);
@@ -277,6 +278,7 @@ int ghciInsertSymbolTable(
pinfo->value = data;
pinfo->owner = owner;
pinfo->weak = weak;
+ pinfo->hidden = hidden;
insertStrHashTable(table, key, pinfo);
return 1;
}
@@ -340,11 +342,23 @@ int ghciInsertSymbolTable(
call this function again to trigger the duplicate error. */
return 1;
}
+ else if(pinfo->hidden && !hidden)
+ {
+ /* The existing symbol is hidden, let's replace it */
+ pinfo->value = data;
+ pinfo->owner = owner;
+ pinfo->weak = weak;
+
+ pinfo->hidden = hidden;
+ return 1;
+ }

pathchar* archiveName = NULL;
debugBelch(
"GHC runtime linker: fatal error: I found a duplicate definition for symbol\n"
" %s\n"
+ " new symbol is hidden: %d\n"
+ " old symbol is hidden: %d\n"
"whilst processing object file\n"
" %" PATH_FMT "\n"
"The symbol was previously defined in\n"
@@ -355,6 +369,8 @@ int ghciInsertSymbolTable(
" * An incorrect `package.conf' entry, causing some object to be\n"
" loaded twice.\n",
(char*)key,
+ hidden ? 1 : 0,
+ pinfo->hidden ? 1 : 0,
obj_name,
pinfo->owner == NULL ? WSTR("(GHCi built-in symbols)") :
pinfo->owner->archiveMemberName ? archiveName = mkPath(pinfo->owner->archiveMemberName)
@@ -451,7 +467,7 @@ initLinker_ (int retain_cafs)
for (sym = rtsSyms; sym->lbl != NULL; sym++) {
if (! ghciInsertSymbolTable(WSTR("(GHCi built-in symbols)"),
symhash, sym->lbl, sym->addr,
- sym->weak, NULL)) {
+ sym->weak, HS_BOOL_FALSE, NULL)) {
barf("ghciInsertSymbolTable failed");
}
IF_DEBUG(linker, debugBelch("initLinker: inserting rts symbol %s, %p\n", sym->lbl, sym->addr));
@@ -463,7 +479,7 @@ initLinker_ (int retain_cafs)
use an arbitrary (hopefully unique) address here.
*/
if (! ghciInsertSymbolTable(WSTR("(GHCi special symbols)"),
- symhash, "__dso_handle", (void *)0x12345687, HS_BOOL_FALSE, NULL)) {
+ symhash, "__dso_handle", (void *)0x12345687, HS_BOOL_FALSE, HS_BOOL_FALSE, NULL)) {
barf("ghciInsertSymbolTable failed");
}

@@ -471,7 +487,7 @@ initLinker_ (int retain_cafs)
if (! ghciInsertSymbolTable(WSTR("(GHCi built-in symbols)"), symhash,
MAYBE_LEADING_UNDERSCORE_STR("newCAF"),
retain_cafs ? newRetainedCAF : newGCdCAF,
- HS_BOOL_FALSE, NULL)) {
+ HS_BOOL_FALSE, HS_BOOL_FALSE, NULL)) {
barf("ghciInsertSymbolTable failed");
}

@@ -845,7 +861,7 @@ HsBool removeLibrarySearchPath(HsPtr dll_path_index)
HsInt insertSymbol(pathchar* obj_name, SymbolName* key, SymbolAddr* data)
{
return ghciInsertSymbolTable(obj_name, symhash, key, data, HS_BOOL_FALSE,
- NULL);
+ HS_BOOL_FALSE, NULL);
}

/* -----------------------------------------------------------------------------
@@ -1699,7 +1715,8 @@ int ocTryLoad (ObjectCode* oc) {
if ( symbol.name
&& !ghciInsertSymbolTable(oc->fileName, symhash, symbol.name,
symbol.addr,
- isSymbolWeak(oc, symbol.name), oc)) {
+ isSymbolWeak(oc, symbol.name),
+ HS_BOOL_FALSE, oc)) {
return 0;
}
}
diff --git a/rts/LinkerInternals.h b/rts/LinkerInternals.h
index f326a84..1bc082c 100644
--- a/rts/LinkerInternals.h
+++ b/rts/LinkerInternals.h
@@ -306,6 +306,7 @@ typedef struct _RtsSymbolInfo {
SymbolAddr* value;
ObjectCode *owner;
HsBool weak;
+ HsBool hidden;
} RtsSymbolInfo;

void exitLinker( void );
@@ -334,6 +335,7 @@ int ghciInsertSymbolTable(
const SymbolName* key,
SymbolAddr* data,
HsBool weak,
+ HsBool hidden,
ObjectCode *owner);

/* Lock-free version of lookupSymbol. When 'dependent' is not NULL, adds it as a
diff --git a/rts/linker/Elf.c b/rts/linker/Elf.c
index fdfe87a..4a53687 100644
--- a/rts/linker/Elf.c
+++ b/rts/linker/Elf.c
@@ -976,7 +976,9 @@ ocGetNames_ELF ( ObjectCode* oc )
setWeakSymbol(oc, nm);
}
if (!ghciInsertSymbolTable(oc->fileName, symhash,
- nm, symbol->addr, isWeak, oc)
+ nm, symbol->addr, isWeak,
+ ELF_ST_VISIBILITY(symbol->elf_sym->st_other) == STV_HIDDEN,
+ oc)
) {
goto fail;
}
diff --git a/rts/linker/ElfTypes.h b/rts/linker/ElfTypes.h
index e5333d7..0a8e44a 100644
--- a/rts/linker/ElfTypes.h
+++ b/rts/linker/ElfTypes.h
@@ -32,6 +32,9 @@
#define Elf_Sym Elf64_Sym
#define Elf_Rel Elf64_Rel
#define Elf_Rela Elf64_Rela
+#if !defined(ELF_ST_VISIBILITY)
+#define ELF_ST_VISIBILITY ELF64_ST_VISIBILITY
+#endif
#if !defined(ELF_ST_TYPE)
#define ELF_ST_TYPE ELF64_ST_TYPE
#endif
@@ -56,6 +59,9 @@
#define Elf_Sym Elf32_Sym
#define Elf_Rel Elf32_Rel
#define Elf_Rela Elf32_Rela
+#if !defined(ELF_ST_VISIBILITY)
+#define ELF_ST_VISIBILITY ELF32_ST_VISIBILITY
+#endif /* ELF_ST_VISIBILITY */
#if !defined(ELF_ST_TYPE)
#define ELF_ST_TYPE ELF32_ST_TYPE
#endif /* ELF_ST_TYPE */
diff --git a/rts/linker/PEi386.c b/rts/linker/PEi386.c
index 6d0d417..841faa8 100644
--- a/rts/linker/PEi386.c
+++ b/rts/linker/PEi386.c
@@ -292,7 +292,7 @@ const void* __rts_iob_func = (void*)&__acrt_iob_func;
void initLinker_PEi386()
{
if (!ghciInsertSymbolTable(WSTR("(GHCi/Ld special symbols)"),
- symhash, "__image_base__", __image_base, HS_BOOL_TRUE, NULL)) {
+ symhash, "__image_base__", __image_base, HS_BOOL_TRUE, HS_BOOL_FALSE, NULL)) {
barf("ghciInsertSymbolTable failed");
}

@@ -1541,7 +1541,7 @@ ocGetNames_PEi386 ( ObjectCode* oc )
sname = strdup (sname);
addr = strdup (addr);
if (!ghciInsertSymbolTable(oc->fileName, symhash, sname,
- addr, false, oc)) {
+ addr, false, HS_BOOL_FALSE, oc)) {
releaseOcInfo (oc);
stgFree (oc->image);
oc->image = NULL;
@@ -1759,7 +1759,9 @@ ocGetNames_PEi386 ( ObjectCode* oc )
stgFree(tmp);
sname = strdup (sname);
if (!ghciInsertSymbolTable(oc->fileName, symhash, sname,
- addr, false, oc))
+ addr, false,
+ section->info->props & IMAGE_SCN_LNK_COMDAT,
+ oc))
return false;

break;
@@ -1776,9 +1778,10 @@ ocGetNames_PEi386 ( ObjectCode* oc )
if (isWeak) {
setWeakSymbol(oc, sname);
}
-
if (! ghciInsertSymbolTable(oc->fileName, symhash, sname, addr,
- isWeak, oc))
+ isWeak,
+ section->info->props & IMAGE_SCN_LNK_COMDAT,
+ oc))
return false;
} else {
/* We're skipping the symbol, but if we ever load this
2 changes: 1 addition & 1 deletion overlays/patches/ghc/win-linker-no-ucrt.patch
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ index c404992..fd060e4 100644
/* debugBelch("look in %ls for %s\n", o_dll->name, lbl); */

+ if (wcsncmp(o_dll->name,WSTR("ucrtbase.dll"),wcslen(WSTR("ucrtbase.dll"))) == 0) {
+ IF_DEBUG(linker, debugBelch("warning: ignoring %s\n", o_dll->name));
+ IF_DEBUG(linker, debugBelch("warning: ignoring " PATH_FMT "\n", o_dll->name));
+ continue;
+ }
+
Expand Down

0 comments on commit 1aa9e3c

Please sign in to comment.