Cheng Shao pushed to branch wip/wasm-dyld-pie at Glasgow Haskell Compiler / GHC

Commits:

8 changed files:

Changes:

  • compiler/GHC/StgToJS/Linker/Linker.hs
    ... ... @@ -2,6 +2,7 @@
    2 2
     {-# LANGUAGE TupleSections     #-}
    
    3 3
     {-# LANGUAGE LambdaCase        #-}
    
    4 4
     {-# LANGUAGE BlockArguments    #-}
    
    5
    +{-# LANGUAGE MultiWayIf        #-}
    
    5 6
     
    
    6 7
     -----------------------------------------------------------------------------
    
    7 8
     -- |
    
    ... ... @@ -666,12 +667,19 @@ renderLinkerStats s =
    666 667
     
    
    667 668
     
    
    668 669
     getPackageArchives :: StgToJSConfig -> UnitEnv -> [UnitId] -> IO [FilePath]
    
    669
    -getPackageArchives cfg unit_env units =
    
    670
    -  filterM doesFileExist [ ST.unpack p </> "lib" ++ ST.unpack l ++ profSuff <.> "a"
    
    671
    -                        | u <- units
    
    672
    -                        , p <- getInstalledPackageLibDirs ue_state u
    
    673
    -                        , l <- getInstalledPackageHsLibs  ue_state u
    
    674
    -                        ]
    
    670
    +getPackageArchives cfg unit_env units = do
    
    671
    +  fmap concat $ forM units $ \u -> do
    
    672
    +    let archives = [ ST.unpack p </> "lib" ++ ST.unpack l ++ profSuff <.> "a"
    
    673
    +                   | p <- getInstalledPackageLibDirs ue_state u
    
    674
    +                   , l <- getInstalledPackageHsLibs  ue_state u
    
    675
    +                   ]
    
    676
    +    foundArchives <- filterM doesFileExist archives
    
    677
    +    if | not (null archives)
    
    678
    +       , null foundArchives
    
    679
    +       -> do
    
    680
    +         throwGhcExceptionIO (InstallationError $ "Could not find any library archives for unit-id: " <> (renderWithContext (csContext cfg) $ ppr u))
    
    681
    +       | otherwise
    
    682
    +       -> pure foundArchives
    
    675 683
       where
    
    676 684
         ue_state = ue_homeUnitState unit_env
    
    677 685
     
    

  • hadrian/src/Rules/Gmp.hs
    ... ... @@ -11,7 +11,7 @@ import Target
    11 11
     import Utilities
    
    12 12
     import Hadrian.BuildPath
    
    13 13
     import Hadrian.Expression
    
    14
    -import Settings.Builders.Common (cArgs, getStagedCCFlags)
    
    14
    +import Settings.Builders.Common (getStagedCCFlags)
    
    15 15
     
    
    16 16
     -- | Build in-tree GMP library objects (if GmpInTree flag is set) and return
    
    17 17
     -- their paths.
    
    ... ... @@ -125,8 +125,7 @@ gmpRules = do
    125 125
                 cFlags <-
    
    126 126
                     interpretInContext ctx $
    
    127 127
                     mconcat
    
    128
    -                    [ cArgs
    
    129
    -                    , getStagedCCFlags
    
    128
    +                    [ getStagedCCFlags
    
    130 129
                         -- gmp symbols are only used by bignum logic in
    
    131 130
                         -- ghc-internal and shouldn't be exported by the
    
    132 131
                         -- ghc-internal shared library.
    

  • hadrian/src/Rules/Libffi.hs
    ... ... @@ -130,17 +130,14 @@ fixLibffiMakefile top =
    130 130
     configureEnvironment :: Stage -> Action [CmdOption]
    
    131 131
     configureEnvironment stage = do
    
    132 132
         context <- libffiContext stage
    
    133
    -    cFlags  <- interpretInContext context $ mconcat
    
    134
    -               [ cArgs
    
    135
    -               , getStagedCCFlags ]
    
    136
    -    ldFlags <- interpretInContext context ldArgs
    
    133
    +    cFlags  <- interpretInContext context getStagedCCFlags
    
    137 134
         sequence [ builderEnvironment "CC" $ Cc CompileC stage
    
    138 135
                  , builderEnvironment "CXX" $ Cc CompileC stage
    
    139
    -             , builderEnvironment "AR" (Ar Unpack stage)
    
    136
    +             , builderEnvironment "AR" $ Ar Unpack stage
    
    140 137
                  , builderEnvironment "NM" Nm
    
    141 138
                  , builderEnvironment "RANLIB" Ranlib
    
    142 139
                  , return . AddEnv  "CFLAGS" $ unwords  cFlags ++ " -w"
    
    143
    -             , return . AddEnv "LDFLAGS" $ unwords ldFlags ++ " -w" ]
    
    140
    +             , return . AddEnv "LDFLAGS" $ "-w" ]
    
    144 141
     
    
    145 142
     -- Need the libffi archive and `trackAllow` all files in the build directory.
    
    146 143
     -- See [Libffi indicating inputs].
    

  • hadrian/src/Settings/Builders/Cabal.hs
    ... ... @@ -188,18 +188,16 @@ configureArgs cFlags' ldFlags' = do
    188 188
                 values <- unwords <$> expr
    
    189 189
                 not (null values) ?
    
    190 190
                     arg ("--configure-option=" ++ key ++ "=" ++ values)
    
    191
    -        cFlags   = mconcat [ remove ["-Werror"] cArgs
    
    192
    -                           , getStagedCCFlags
    
    191
    +        cFlags   = mconcat [ getStagedCCFlags
    
    193 192
                                -- See https://github.com/snowleopard/hadrian/issues/523
    
    194 193
                                , arg $ "-iquote"
    
    195 194
     
    
    196 195
                                , arg $ top -/- pkgPath pkg
    
    197 196
                                , cFlags'
    
    198 197
                                ]
    
    199
    -        ldFlags  = ldArgs <> ldFlags'
    
    200 198
         mconcat
    
    201 199
             [ conf "CFLAGS"   cFlags
    
    202
    -        , conf "LDFLAGS"  ldFlags
    
    200
    +        , conf "LDFLAGS"  ldFlags'
    
    203 201
             , conf "--with-iconv-includes"    $ arg =<< getSetting IconvIncludeDir
    
    204 202
             , conf "--with-iconv-libraries"   $ arg =<< getSetting IconvLibDir
    
    205 203
             , conf "--with-gmp-includes"      $ arg =<< getSetting GmpIncludeDir
    

  • hadrian/src/Settings/Builders/Common.hs
    ... ... @@ -5,7 +5,7 @@ module Settings.Builders.Common (
    5 5
         module Oracles.Setting,
    
    6 6
         module Settings,
    
    7 7
         module UserSettings,
    
    8
    -    cIncludeArgs, ldArgs, cArgs, cppArgs, cWarnings,
    
    8
    +    cIncludeArgs, cWarnings,
    
    9 9
         packageDatabaseArgs, bootPackageDatabaseArgs,
    
    10 10
         getStagedCCFlags, wayCcArgs
    
    11 11
         ) where
    
    ... ... @@ -38,15 +38,6 @@ cIncludeArgs = do
    38 38
                 , pure [ "-I" ++ pkgPath pkg -/- dir | dir <- incDirs ]
    
    39 39
                 , pure [ "-I" ++       unifyPath dir | dir <- depDirs ] ]
    
    40 40
     
    
    41
    -ldArgs :: Args
    
    42
    -ldArgs = mempty
    
    43
    -
    
    44
    -cArgs :: Args
    
    45
    -cArgs = mempty
    
    46
    -
    
    47
    -cppArgs :: Args
    
    48
    -cppArgs = mempty
    
    49
    -
    
    50 41
     -- TODO: should be in a different file
    
    51 42
     cWarnings :: Args
    
    52 43
     cWarnings = mconcat
    

  • hadrian/src/Settings/Builders/DeriveConstants.hs
    ... ... @@ -40,8 +40,7 @@ includeCcArgs :: Args
    40 40
     includeCcArgs = do
    
    41 41
         stage <- getStage
    
    42 42
         rtsPath <- expr $ rtsBuildPath stage
    
    43
    -    mconcat [ cArgs
    
    44
    -            , cWarnings
    
    43
    +    mconcat [ cWarnings
    
    45 44
                 , prgFlags . ccProgram . tgtCCompiler <$> expr (targetStage Stage1)
    
    46 45
                 , queryTargetTarget tgtUnregisterised ? arg "-DUSE_MINIINTERPRETER"
    
    47 46
                 , arg "-Irts"
    

  • hadrian/src/Settings/Builders/Hsc2Hs.hs
    ... ... @@ -50,7 +50,7 @@ getCFlags = do
    50 50
         autogen <- expr $ autogenPath context
    
    51 51
         let cabalMacros = autogen -/- "cabal_macros.h"
    
    52 52
         expr $ need [cabalMacros]
    
    53
    -    mconcat [ remove ["-O"] (cArgs <> getStagedCCFlags)
    
    53
    +    mconcat [ remove ["-O"] getStagedCCFlags
    
    54 54
                 -- Either "-E" is not part of the configured cpp args, or we can't add those args to invocations of things like this
    
    55 55
                 -- ROMES:TODO: , prgFlags . cppProgram . tgtCPreprocessor <$> getStagedTargetConfig
    
    56 56
                 , cIncludeArgs
    
    ... ... @@ -64,6 +64,5 @@ getCFlags = do
    64 64
     getLFlags :: Expr [String]
    
    65 65
     getLFlags =
    
    66 66
         mconcat [ prgFlags . ccLinkProgram . tgtCCompilerLink <$> getStagedTarget
    
    67
    -            , ldArgs
    
    68 67
                 , getContextData ldOpts
    
    69 68
                 , getContextData depLdOpts ]

  • utils/jsffi/dyld.mjs
    ... ... @@ -834,6 +834,27 @@ class DyLD {
    834 834
           );
    
    835 835
         }
    
    836 836
     
    
    837
    +    // Both wasi implementations we use provide
    
    838
    +    // wasi.initialize(instance) to initialize a wasip1 reactor
    
    839
    +    // module. However, instance does not really need to be a
    
    840
    +    // WebAssembly.Instance object; the wasi implementations only need
    
    841
    +    // to access instance.exports.memory for the wasi syscalls to
    
    842
    +    // work.
    
    843
    +    //
    
    844
    +    // Given we'll reuse the same wasi object across different
    
    845
    +    // WebAssembly.Instance objects anyway and
    
    846
    +    // wasi.initialize(instance) can't be called more than once, we
    
    847
    +    // use this simple trick and pass a fake instance object that
    
    848
    +    // contains just enough info for the wasi implementation to
    
    849
    +    // initialize its internal state. Later when we load each wasm
    
    850
    +    // shared library, we can just manually invoke their
    
    851
    +    // initialization functions.
    
    852
    +    this.#wasi.initialize({
    
    853
    +      exports: {
    
    854
    +        memory: this.#memory,
    
    855
    +      },
    
    856
    +    });
    
    857
    +
    
    837 858
         // Keep this in sync with rts/wasm/Wasm.S!
    
    838 859
         for (let i = 1; i <= 10; ++i) {
    
    839 860
           this.#regs[`__R${i}`] = new WebAssembly.Global({
    
    ... ... @@ -930,10 +951,15 @@ class DyLD {
    930 951
       async loadDLLs(packed) {
    
    931 952
         // Normalize input to an array of strings. When called from Haskell
    
    932 953
         // we pass a single JSString containing NUL-separated paths.
    
    933
    -    const paths = (typeof packed === "string"
    
    934
    -      ? (packed.length === 0 ? [] : packed.split("\0"))
    
    935
    -      : [packed] // tolerate an accidental single path object
    
    936
    -    ).filter((s) => s.length > 0).reverse();
    
    954
    +    const paths = (
    
    955
    +      typeof packed === "string"
    
    956
    +        ? packed.length === 0
    
    957
    +          ? []
    
    958
    +          : packed.split("\0")
    
    959
    +        : [packed]
    
    960
    +    ) // tolerate an accidental single path object
    
    961
    +      .filter((s) => s.length > 0)
    
    962
    +      .reverse();
    
    937 963
     
    
    938 964
         // Compute a single downsweep plan for the whole batch.
    
    939 965
         // Note: #downsweep mutates #loadedSos to break cycles and dedup.
    
    ... ... @@ -1154,22 +1180,6 @@ class DyLD {
    1154 1180
             throw new Error(`cannot handle export ${k} ${v}`);
    
    1155 1181
           }
    
    1156 1182
     
    
    1157
    -      // We call wasi.initialize when loading libc.so, then reuse the
    
    1158
    -      // wasi instance globally. When loading later .so files, just
    
    1159
    -      // manually invoke _initialize().
    
    1160
    -      if (soname === "libc.so") {
    
    1161
    -        instance.exports.__wasm_apply_data_relocs();
    
    1162
    -        // wasm-ld forbits --export-memory with --shared, I don't know
    
    1163
    -        // why but this is sufficient to make things work
    
    1164
    -        this.#wasi.initialize({
    
    1165
    -          exports: {
    
    1166
    -            memory: this.#memory,
    
    1167
    -            _initialize: instance.exports._initialize,
    
    1168
    -          },
    
    1169
    -        });
    
    1170
    -        continue;
    
    1171
    -      }
    
    1172
    -
    
    1173 1183
           // See
    
    1174 1184
           // https://gitlab.haskell.org/haskell-wasm/llvm-project/-/blob/release/21.x/lld/wasm/Writer.cpp#L1451,
    
    1175 1185
           // __wasm_apply_data_relocs is now optional so only call it if
    
    ... ... @@ -1180,7 +1190,7 @@ class DyLD {
    1180 1190
           // been called upon instantiation, see
    
    1181 1191
           // Writer::createStartFunction().
    
    1182 1192
           if (instance.exports.__wasm_apply_data_relocs) {
    
    1183
    -          instance.exports.__wasm_apply_data_relocs();
    
    1193
    +        instance.exports.__wasm_apply_data_relocs();
    
    1184 1194
           }
    
    1185 1195
     
    
    1186 1196
           instance.exports._initialize();