David Eichmann pushed to branch wip/27162/rts-explicit-dllimport at Glasgow Haskell Compiler / GHC Commits: 5a6ba22b by Duncan Coutts at 2026-04-30T11:40:09+01:00 Use __attribute__((dllimport)) for external RTS symbol declarations This is needed to be hygenic about DLL symbol imports and exports. The attribute is ignored on platforms other than Windows. Use of the attribute however means that external data symbols do not have a compile-time constant address (they are loaded using an indirection). This means we have to adjust the rtsSyms initial linker table so that it is a local constant in a function, rather than a global constant. We now define it within a function that pre-populates the symbol table with the RTS symbols. - - - - - 6833e03c by Duncan Coutts at 2026-04-30T11:40:09+01:00 Fix the rts linker declarations for a few data symbols and ensure that the (windows only) rts_IOManagerIsWin32Native data symbol is marked as externally visible. - - - - - 793008fb by David Eichmann at 2026-04-30T11:40:09+01:00 Hadrian: Disable runtime pseudo relocations for RTS on windows hosts - - - - - 7 changed files: - hadrian/src/Settings/Packages.hs - rts/IOManager.h - rts/Linker.c - rts/LinkerInternals.h - rts/RtsSymbols.c - rts/RtsSymbols.h - rts/linker/Elf.c Changes: ===================================== hadrian/src/Settings/Packages.hs ===================================== @@ -321,6 +321,7 @@ rtsPackageArgs = package rts ? do , Profiling `wayUnit` way ? arg "-DPROFILING" , Threaded `wayUnit` way ? arg "-DTHREADED_RTS" , notM targetSupportsSMP ? arg "-optc-DNOSMP" + , isWinHost ? arg "-optl-Wl,--disable-runtime-pseudo-reloc" -- See Note [AutoApply.cmm for vectors] in genapply/Main.hs -- ===================================== rts/IOManager.h ===================================== @@ -21,6 +21,15 @@ #include "sm/GC.h" // for evac_fn +#if defined(mingw32_HOST_OS) +/* Global var (only on Windows) that is exported (hence before BeginPrivate.h) + * to be shared with the I/O code in the base library to tell us which style + * of I/O manager we are using: one that uses the Windows native API HANDLEs, + * or one that uses Posix style fds. + */ +extern bool rts_IOManagerIsWin32Native; +#endif + #include "BeginPrivate.h" /* The ./configure gives us a set of CPP flags, one for each named I/O manager: @@ -160,14 +169,6 @@ typedef enum { /* Global var to tell us which I/O manager impl we are using */ extern IOManagerType iomgr_type; -#if defined(mingw32_HOST_OS) -/* Global var (only on Windows) that is exported to be shared with the I/O code - * in the base library to tell us which style of I/O manager we are using: one - * that uses the Windows native API HANDLEs, or one that uses Posix style fds. - */ -extern bool rts_IOManagerIsWin32Native; -#endif - /* The CapIOManager is the per-capability data structure belonging to the I/O * manager. It is defined in full in IOManagerInternals.h. The opaque forward ===================================== rts/Linker.c ===================================== @@ -478,16 +478,7 @@ initLinker_ (int retain_cafs) symhash = allocStrHashTable(); /* populate the symbol table with stuff from the RTS */ - IF_DEBUG(linker, debugBelch("populating linker symbol table with built-in RTS symbols\n")); - for (const RtsSymbolVal *sym = rtsSyms; sym->lbl != NULL; sym++) { - IF_DEBUG(linker, debugBelch("initLinker: inserting rts symbol %s, %p\n", sym->lbl, sym->addr)); - if (! ghciInsertSymbolTable(WSTR("(GHCi built-in symbols)"), - symhash, sym->lbl, sym->addr, - sym->strength, sym->type, 0, NULL)) { - barf("ghciInsertSymbolTable failed"); - } - } - IF_DEBUG(linker, debugBelch("done with built-in RTS symbols\n")); + initLinkerRtsSyms(symhash); /* Add extra symbols. rtsExtraSyms() is a weakly defined symbol in the rts, * that can be overrided by linking in an object with a corresponding ===================================== rts/LinkerInternals.h ===================================== @@ -502,4 +502,6 @@ ObjectCode* mkOc( ObjectType type, pathchar *path, char *image, int imageSize, void initSegment(Segment *s, void *start, size_t size, SegmentProt prot, int n_sections); void freeSegments(ObjectCode *oc); +void initLinkerRtsSyms(StrHashTable *symhash); + #include "EndPrivate.h" ===================================== rts/RtsSymbols.c ===================================== @@ -9,6 +9,8 @@ #include "ghcplatform.h" #include "Rts.h" #include "RtsSymbols.h" +#include "LinkerInternals.h" +#include "PathUtils.h" #include "TopHandler.h" #include "HsFFI.h" @@ -51,6 +53,20 @@ extern char **environ; /* ----------------------------------------------------------------------------- * Symbols to be inserted into the RTS symbol table. + * + * Note [Naming Scheme for Symbol Macros] + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * SymI_*: symbol is internal to the RTS. It resides in an object + * file/library that is linked into the RTS library (as a static + * archive or dynamic shared library). + * SymE_*: symbol is external to the RTS library. It might be linked + * dynamically. + * + * Sym*_HasProto : the symbol prototype is imported in an include file + * or defined explicitly + * Sym*_NeedsProto: the symbol is undefined and we add a dummy + * default proto extern void sym(void); */ #define Maybe_Stable_Names SymI_HasProto(stg_mkWeakzh) \ @@ -162,7 +178,7 @@ extern char **environ; SymI_HasProto(stg_asyncWritezh) \ SymI_HasProto(stg_asyncDoProczh) \ SymI_HasProto(rts_InstallConsoleEvent) \ - SymI_HasProto(rts_IOManagerIsWin32Native) \ + SymI_HasDataProto(rts_IOManagerIsWin32Native) \ SymI_HasProto(rts_ConsoleHandlerDone) \ SymI_NeedsProto(__mingw_module_is_dll) \ RTS_WIN64_ONLY(SymI_NeedsProto(___chkstk_ms)) \ @@ -913,7 +929,7 @@ extern char **environ; SymI_HasProto(freeExecPage) \ SymI_HasProto(getAllocations) \ SymI_HasProto(revertCAFs) \ - SymI_HasProto(RtsFlags) \ + SymI_HasDataProto(RtsFlags) \ SymI_NeedsDataProto(rts_breakpoint_io_action) \ SymI_NeedsDataProto(rts_stop_next_breakpoint) \ SymI_NeedsDataProto(rts_stop_on_exception) \ @@ -924,9 +940,9 @@ extern char **environ; SymI_NeedsProto(rts_enableStopAfterReturn) \ SymI_NeedsProto(rts_disableStopAfterReturn) \ SymI_HasProto(stopTimer) \ - SymI_HasProto(n_capabilities) \ - SymI_HasProto(max_n_capabilities) \ - SymI_HasProto(enabled_capabilities) \ + SymI_HasDataProto(n_capabilities) \ + SymI_HasDataProto(max_n_capabilities) \ + SymI_HasDataProto(enabled_capabilities) \ SymI_HasDataProto(stg_traceEventzh) \ SymI_HasDataProto(stg_traceMarkerzh) \ SymI_HasDataProto(stg_traceBinaryEventzh) \ @@ -1144,12 +1160,27 @@ extern char **environ; SymI_HasProto(hs_word2float64) -/* entirely bogus claims about types of these symbols */ -#define SymI_NeedsProto(vvv) extern void vvv(void); -#define SymI_NeedsDataProto(vvv) extern StgWord vvv[]; -#define SymE_NeedsProto(vvv) SymI_NeedsProto(vvv); -#define SymE_NeedsDataProto(vvv) SymI_NeedsDataProto(vvv); -#define SymE_HasProto(vvv) SymI_HasProto(vvv); +/* Declare prototypes for the symbols that need it, so we can refer + * to them in the rtsSyms table below. + * + * In particular, for the external ones (SymE_*) we use the dllimport attribute + * to indicate that (on Windows) they come from external DLLs. This attribute + * is ignored on other platforms. + * + * The claims about the types of these symbols are entirely bogus. + */ +#if defined(mingw32_HOST_OS) && defined(DYNAMIC) +#define DLLIMPORT __attribute__((dllimport)) +#else +#define DLLIMPORT /**/ +#endif + +#define SymI_NeedsProto(vvv) extern void vvv(void); +#define SymI_NeedsDataProto(vvv) extern StgWord vvv[]; +#define SymE_NeedsProto(vvv) extern DLLIMPORT void vvv(void); +#define SymE_NeedsDataProto(vvv) extern DLLIMPORT StgWord vvv[]; + +#define SymE_HasProto(vvv) /**/ #define SymI_HasProto(vvv) /**/ #define SymI_HasDataProto(vvv) /**/ #define SymI_HasProto_redirect(vvv,xxx,strength,ty) /**/ @@ -1178,6 +1209,8 @@ RTS_SYMBOLS_PRIM #undef SymE_NeedsProto #undef SymE_NeedsDataProto +/* See Note [Naming Scheme for Symbol Macros] */ + #define SymI_HasProto(vvv) { MAYBE_LEADING_UNDERSCORE_STR(#vvv), \ (void*)(&(vvv)), STRENGTH_NORMAL, SYM_TYPE_CODE }, #define SymI_HasDataProto(vvv) { MAYBE_LEADING_UNDERSCORE_STR(#vvv), \ @@ -1198,7 +1231,16 @@ RTS_SYMBOLS_PRIM { MAYBE_LEADING_UNDERSCORE_STR(#vvv), \ (void*)(&(xxx)), strength, ty }, -RtsSymbolVal rtsSyms[] = { + + +/* Initialize (if not already initialized) and return an array of symbols with stuff from the RTS. */ +void initLinkerRtsSyms (StrHashTable *symhash) { + /* The address of data symbols with the dllimport attribute are not + * compile-time constants and so cannot be used in constant initialisers. + * For this reason, rtsSyms is a local variable within this function + * rather than a global constant (as it was historically). + */ + const RtsSymbolVal rtsSyms[] = { RTS_SYMBOLS RTS_RET_SYMBOLS RTS_POSIX_ONLY_SYMBOLS @@ -1213,7 +1255,20 @@ RtsSymbolVal rtsSyms[] = { RTS_SYMBOLS_PRIM SymI_HasDataProto(nonmoving_write_barrier_enabled) { 0, 0, STRENGTH_NORMAL, SYM_TYPE_CODE } /* sentinel */ -}; + }; + + IF_DEBUG(linker, debugBelch("populating linker symbol table with built-in RTS symbols\n")); + for (const RtsSymbolVal *sym = rtsSyms; sym->lbl != NULL; sym++) { + IF_DEBUG(linker, debugBelch("initLinker: inserting rts symbol %s, %p\n", sym->lbl, sym->addr)); + if (! ghciInsertSymbolTable(WSTR("(GHCi built-in symbols)"), + symhash, sym->lbl, sym->addr, + sym->strength, sym->type, 0, NULL)) { + barf("ghciInsertSymbolTable failed"); + } + } + IF_DEBUG(linker, debugBelch("done with built-in RTS symbols\n")); +} + // Note [Extra RTS symbols] ===================================== rts/RtsSymbols.h ===================================== @@ -46,8 +46,6 @@ typedef struct _RtsSymbolVal { SymType type; } RtsSymbolVal; -extern RtsSymbolVal rtsSyms[]; - extern RtsSymbolVal* __attribute__((weak)) rtsExtraSyms(void); /* See Note [_iob_func symbol]. */ ===================================== rts/linker/Elf.c ===================================== @@ -76,18 +76,6 @@ * * See bug #781 * See thread http://www.haskell.org/pipermail/cvs-ghc/2007-September/038458.html - * - * Naming Scheme for Symbol Macros - * - * SymI_*: symbol is internal to the RTS. It resides in an object - * file/library that is statically. - * SymE_*: symbol is external to the RTS library. It might be linked - * dynamically. - * - * Sym*_HasProto : the symbol prototype is imported in an include file - * or defined explicitly - * Sym*_NeedsProto: the symbol is undefined and we add a dummy - * default proto extern void sym(void); */ #define X86_64_ELF_NONPIC_HACK (!RtsFlags.MiscFlags.linkerAlwaysPic) View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/b3b923fb7d54c9b41221f026cc64339... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/b3b923fb7d54c9b41221f026cc64339... You're receiving this email because of your account on gitlab.haskell.org.
participants (1)
-
David Eichmann (@DavidEichmann)