[Git][ghc/ghc][master] RTS linker: add support for hidden symbols (#25191)
Marge Bot (@marge-bot)
gitlab at gitlab.haskell.org
Tue Sep 10 14:47:05 UTC 2024
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
9ca15506 by doyougnu at 2024-09-10T10:46:38-04:00
RTS linker: add support for hidden symbols (#25191)
Add linker support for hidden symbols. We basically treat them as weak
symbols.
Patch upstreamed from haskell.nix
Co-authored-by: Sylvain Henry <sylvain at haskus.fr>
Co-authored-by: Moritz Angermann <moritz.angermann at gmail.com>
- - - - -
11 changed files:
- rts/Linker.c
- rts/LinkerInternals.h
- rts/linker/Elf.c
- rts/linker/ElfTypes.h
- rts/linker/PEi386.c
- testsuite/tests/rts/linker/Makefile
- + testsuite/tests/rts/linker/T25191.hs
- + testsuite/tests/rts/linker/T25191.stdout
- + testsuite/tests/rts/linker/T25191_foo1.c
- + testsuite/tests/rts/linker/T25191_foo2.c
- testsuite/tests/rts/linker/all.T
Changes:
=====================================
rts/Linker.c
=====================================
@@ -232,11 +232,11 @@ static void ghciRemoveSymbolTable(StrHashTable *table, const SymbolName* key,
static const char *
symbolTypeString (SymType type)
{
- switch (type & ~SYM_TYPE_DUP_DISCARD) {
+ switch (type & ~(SYM_TYPE_DUP_DISCARD | SYM_TYPE_HIDDEN)) {
case SYM_TYPE_CODE: return "code";
case SYM_TYPE_DATA: return "data";
case SYM_TYPE_INDIRECT_DATA: return "indirect-data";
- default: barf("symbolTypeString: unknown symbol type");
+ default: barf("symbolTypeString: unknown symbol type (%d)", type);
}
}
@@ -283,10 +283,19 @@ int ghciInsertSymbolTable(
}
else if (pinfo->type ^ type)
{
+ if(pinfo->type & SYM_TYPE_HIDDEN)
+ {
+ /* The existing symbol is hidden, let's replace it */
+ pinfo->value = data;
+ pinfo->owner = owner;
+ pinfo->strength = strength;
+ pinfo->type = type;
+ return 1;
+ }
/* We were asked to discard the symbol on duplicates, do so quietly. */
- if (!(type & SYM_TYPE_DUP_DISCARD))
+ if (!(type & (SYM_TYPE_DUP_DISCARD | SYM_TYPE_HIDDEN)))
{
- debugBelch("Symbol type mismatch.\n");
+ debugBelch("Symbol type mismatch (existing %d, new %d).\n", pinfo->type, type);
debugBelch("Symbol %s was defined by %" PATH_FMT " to be a %s symbol.\n",
key, obj_name, symbolTypeString(type));
debugBelch(" yet was defined by %" PATH_FMT " to be a %s symbol.\n",
=====================================
rts/LinkerInternals.h
=====================================
@@ -64,6 +64,8 @@ typedef enum _SymType {
SYM_TYPE_DUP_DISCARD = 1 << 3, /* the symbol is a symbol in a BFD import library
however if a duplicate is found with a mismatching
SymType then discard this one. */
+ SYM_TYPE_HIDDEN = 1 << 4, /* the symbol is hidden and should not be exported */
+
} SymType;
=====================================
rts/linker/Elf.c
=====================================
@@ -1073,6 +1073,9 @@ ocGetNames_ELF ( ObjectCode* oc )
} else {
sym_type = SYM_TYPE_DATA;
}
+ if(ELF_ST_VISIBILITY(symbol->elf_sym->st_other) == STV_HIDDEN) {
+ sym_type |= SYM_TYPE_HIDDEN;
+ }
/* And the decision is ... */
=====================================
rts/linker/ElfTypes.h
=====================================
@@ -33,6 +33,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
@@ -57,6 +60,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 */
=====================================
rts/linker/PEi386.c
=====================================
@@ -1891,6 +1891,9 @@ ocGetNames_PEi386 ( ObjectCode* oc )
sname[size-start]='\0';
stgFree(tmp);
sname = strdup (sname);
+ if(secNumber == IMAGE_SYM_UNDEFINED)
+ type |= SYM_TYPE_HIDDEN;
+
if (!ghciInsertSymbolTable(oc->fileName, symhash, sname,
addr, false, type, oc))
return false;
@@ -1905,6 +1908,8 @@ ocGetNames_PEi386 ( ObjectCode* oc )
&& (!section || (section && section->kind != SECTIONKIND_IMPORT))) {
/* debugBelch("addSymbol %p `%s' Weak:%lld \n", addr, sname, isWeak); */
sname = strdup (sname);
+ if(secNumber == IMAGE_SYM_UNDEFINED)
+ type |= SYM_TYPE_HIDDEN;
IF_DEBUG(linker_verbose, debugBelch("addSymbol %p `%s'\n", addr, sname));
ASSERT(i < (uint32_t)oc->n_symbols);
oc->symbols[i].name = sname;
@@ -1936,7 +1941,7 @@ static size_t
makeSymbolExtra_PEi386( ObjectCode* oc, uint64_t index STG_UNUSED, size_t s, char* symbol STG_UNUSED, SymType type )
{
SymbolExtra *extra;
- switch(type & ~SYM_TYPE_DUP_DISCARD) {
+ switch(type & ~(SYM_TYPE_DUP_DISCARD | SYM_TYPE_HIDDEN)) {
case SYM_TYPE_CODE: {
// jmp *-14(%rip)
extra = m32_alloc(oc->rx_m32, sizeof(SymbolExtra), 8);
=====================================
testsuite/tests/rts/linker/Makefile
=====================================
@@ -145,3 +145,10 @@ reloc-none:
"$(TEST_HC)" load-object.c -o load-object -no-hs-main -debug
"$(TEST_HC)" -c reloc-none.c -o reloc-none.o
./load-object reloc-none.o
+
+.PHONY: T25191
+T25191:
+ "$(TEST_HC)" -c T25191_foo1.c -o foo1.o -v0
+ "$(TEST_HC)" -c T25191_foo2.c -o foo2.o -v0
+ "$(TEST_HC)" T25191.hs -v0
+ ./T25191
=====================================
testsuite/tests/rts/linker/T25191.hs
=====================================
@@ -0,0 +1,29 @@
+{-# LANGUAGE ForeignFunctionInterface, CPP #-}
+import Foreign.C.String
+import Control.Monad
+import System.FilePath
+import Foreign.Ptr
+
+-- Type of paths is different on Windows
+#if defined(mingw32_HOST_OS)
+type PathString = CWString
+withPathString = withCWString
+#else
+type PathString = CString
+withPathString = withCString
+#endif
+
+main = do
+ initLinker
+ r1 <- withPathString "foo1.o" loadObj
+ when (r1 /= 1) $ error "loadObj failed"
+ r2 <- withPathString "foo2.o" loadObj
+ when (r2 /= 1) $ error "loadObj failed"
+ r <- resolveObjs
+ when (r /= 1) $ error "resolveObj failed"
+ putStrLn "success"
+
+foreign import ccall "initLinker" initLinker :: IO ()
+foreign import ccall "addDLL" addDLL :: PathString -> IO CString
+foreign import ccall "loadObj" loadObj :: PathString -> IO Int
+foreign import ccall "resolveObjs" resolveObjs :: IO Int
=====================================
testsuite/tests/rts/linker/T25191.stdout
=====================================
@@ -0,0 +1 @@
+success
=====================================
testsuite/tests/rts/linker/T25191_foo1.c
=====================================
@@ -0,0 +1,10 @@
+#include <stdio.h>
+
+void __attribute__ ((__visibility__ ("hidden"))) foo(void) {
+ printf("HIDDEN FOO\n");
+}
+
+void bar(void) {
+ printf("BAR\n");
+ foo();
+}
=====================================
testsuite/tests/rts/linker/T25191_foo2.c
=====================================
@@ -0,0 +1,8 @@
+#include <stdio.h>
+
+extern void bar(void);
+
+void foo(void) {
+ printf("VISIBLE FOO\n");
+ bar();
+}
=====================================
testsuite/tests/rts/linker/all.T
=====================================
@@ -168,3 +168,11 @@ test('reloc-none',
unless(opsys('linux'), skip),
req_rts_linker],
makefile_test, ['reloc-none'])
+
+test('T25191',
+ [req_rts_linker,
+ extra_files(['T25191_foo1.c','T25191_foo2.c']),
+ when(opsys('darwin'), expect_broken(25191)), # not supported in the MachO linker yet
+ when(opsys('mingw32'), expect_broken(25191)) # not supported in the PE linker yet
+ ],
+ makefile_test, ['T25191'])
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/9ca155065b39968d784846902ec1e0bcbe60ee40
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/9ca155065b39968d784846902ec1e0bcbe60ee40
You're receiving this email because of your account on gitlab.haskell.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20240910/fedc2ba6/attachment-0001.html>
More information about the ghc-commits
mailing list