From 58568f9102f39d219298cdbd09a316777d45f4f3 Mon Sep 17 00:00:00 2001 From: Moritz Angermann Date: Wed, 29 Nov 2023 13:50:24 +0800 Subject: [PATCH 01/57] Add aarch64-musl symbols --- cbits/symbols.aarch64-musl.c | 50 ++++++++++++++++++++++++++++++++++++ cbits/symbols.aarch64-musl.h | 1 + iserv-proxy.cabal | 2 ++ 3 files changed, 53 insertions(+) create mode 100644 cbits/symbols.aarch64-musl.c create mode 100644 cbits/symbols.aarch64-musl.h diff --git a/cbits/symbols.aarch64-musl.c b/cbits/symbols.aarch64-musl.c new file mode 100644 index 0000000..d544d44 --- /dev/null +++ b/cbits/symbols.aarch64-musl.c @@ -0,0 +1,50 @@ +#define SYM(s) extern void s(void); +#include "symbols.aarch64-musl.h" +#undef SYM + +extern void exit(int); +extern void printf(const char*, ...); + +#define MISSING_FUN(f) void (f)(void) { printf("Unknown call to `%s'\n", #f); exit(1); } + +MISSING_FUN(c_format_unix_time) +MISSING_FUN(c_format_unix_time_gmt) +MISSING_FUN(c_parse_unix_time) +MISSING_FUN(c_parse_unix_time_gmt) + +typedef void SymbolAddr; +typedef char SymbolName; + +typedef enum _SymStrength { + STRENGTH_NORMAL, + STRENGTH_WEAK, + STRENGTH_STRONG, +} SymStrength; + +typedef enum _SymType { + SYM_TYPE_CODE = 1 << 0, /* the symbol is a function and can be relocated via a jump island */ + SYM_TYPE_DATA = 1 << 1, /* the symbol is data */ + SYM_TYPE_INDIRECT_DATA = 1 << 2, /* see Note [_iob_func symbol] */ + 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. */ +} SymType; + +typedef struct _RtsSymbolVal { + const SymbolName* lbl; + SymbolAddr* addr; + SymStrength strength; + SymType type; +} RtsSymbolVal; + +#define SYM(x) { #x, (void*)(&x), STRENGTH_NORMAL, 1 }, +// typedef mode_t (*umask_func_ptr_t)(mode_t); + +RtsSymbolVal my_iserv_syms[] = { +#include "symbols.aarch64-musl.h" + { 0, 0, STRENGTH_NORMAL, 1 } /* sentinel */ +}; + +RtsSymbolVal* iserv_syms() { + return my_iserv_syms; +} \ No newline at end of file diff --git a/cbits/symbols.aarch64-musl.h b/cbits/symbols.aarch64-musl.h new file mode 100644 index 0000000..686d7fe --- /dev/null +++ b/cbits/symbols.aarch64-musl.h @@ -0,0 +1 @@ +SYM(fprintf) diff --git a/iserv-proxy.cabal b/iserv-proxy.cabal index 39e5cc6..9c4a026 100644 --- a/iserv-proxy.cabal +++ b/iserv-proxy.cabal @@ -102,6 +102,8 @@ Executable iserv-proxy-interpreter -- We need to pass -fkeep-cafs to ensure that the interpreter retains CAFs -- Iserv and GHC do something similar. ghc-options: -fkeep-cafs + includes: cbits/symbols.aarch64-musl.h + c-sources: cbits/symbols.aarch64-musl.c Build-Depends: base >= 4 && < 5, iserv-proxy From 38e16f7d2d23636068031a3018c2b29669ffdfce Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Tue, 13 Dec 2022 17:39:37 +1300 Subject: [PATCH 02/57] Add old `remote-iserv` command line code (cherry picked from commit 650ebfc2363ced3e102b7a32f2266655e31c4593) --- Interpreter.hs | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/Interpreter.hs b/Interpreter.hs index f6096a0..323449b 100644 --- a/Interpreter.hs +++ b/Interpreter.hs @@ -1,14 +1,30 @@ module Main where -import System.Environment -import IServ.Remote.Message -import IServ.Remote.Interpreter - -verbose :: Bool -verbose = False +import IServ.Remote.Interpreter (startInterpreter') +import System.Environment (getArgs, getProgName) +import System.Exit (die) main :: IO () -main = do - [portStr, storagePath] <- getArgs - let port = read portStr - startInterpreter' verbose storagePath port +main = getArgs >>= startSlave + +dieWithUsage :: IO a +dieWithUsage = do + prog <- getProgName + die $ msg prog + where + msg name = "usage: " ++ name ++ " /path/to/storage PORT [-v]" + +startSlave :: [String] -> IO () +startSlave args0 + | "--help" `elem` args0 = dieWithUsage + | otherwise = do + (path, port, rest) <- case args0 of + arg0:arg1:rest -> return (arg0, read arg1, rest) + _ -> dieWithUsage + + verbose <- case rest of + ["-v"] -> return True + [] -> return False + _ -> dieWithUsage + + startInterpreter' verbose path port \ No newline at end of file From a46dc2a81cdc35c37af0a0161ea17a5a4594cb5c Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Tue, 13 Dec 2022 17:40:01 +1300 Subject: [PATCH 03/57] Add Z drive for TH code (cherry picked from commit 4c58525d98c1b09b41a9dcba02e616987a8fea2e) --- Main.hs | 12 ++++++++++-- src/IServ/Remote/Interpreter.hs | 3 +++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Main.hs b/Main.hs index a4c0d04..7be069e 100644 --- a/Main.hs +++ b/Main.hs @@ -141,8 +141,16 @@ hook = return -- fwdTHMsg :: (Binary a) => Pipe -> THMessage a -> IO a fwdTHMsg local msg = do - writePipe local (putTHMessage msg) - readPipe local get + writePipe local (putTHMessage (fixAddDep msg)) + readPipe local get + where + fixAddDep (AddDependentFile fp) = AddDependentFile $ fixZ (map fixSlash fp) + fixAddDep m = m + fixZ ('Z':':':rest) = rest + fixZ ('/':'/':'?':'/':'Z':':':rest) = rest + fixZ fp = fp + fixSlash '\\' = '/' + fixSlash c = c -- | Fowarard a @Message@ call and handle @THMessages@. fwdTHCall :: (Binary a) => Bool -> Pipe -> Pipe -> Message a -> IO a diff --git a/src/IServ/Remote/Interpreter.hs b/src/IServ/Remote/Interpreter.hs index 9f8f88f..b50fa78 100644 --- a/src/IServ/Remote/Interpreter.hs +++ b/src/IServ/Remote/Interpreter.hs @@ -139,6 +139,9 @@ hook verbose base_path pipe m = case m of -- system libraries. Msg (LoadDLL path@('C':':':_)) -> do return m + -- When building on nix the /nix/store paths use Z: + Msg (LoadDLL path@('Z':':':_)) -> do + return m Msg (LoadDLL path) | isAbsolute path -> do when verbose $ trace ("Need DLL: " ++ (base_path path)) handleLoad pipe path (base_path path) From a1f3c50fa7a48ccf6fea4d733332199a952d04c7 Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Wed, 14 Dec 2022 15:08:12 +1300 Subject: [PATCH 04/57] Support for older GHC versions (cherry picked from commit 50d0abb3317ac439a4e7495b185a64af9b7b9300) --- src/IServ/Remote/Interpreter.hs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/IServ/Remote/Interpreter.hs b/src/IServ/Remote/Interpreter.hs index b50fa78..e5fe102 100644 --- a/src/IServ/Remote/Interpreter.hs +++ b/src/IServ/Remote/Interpreter.hs @@ -1,9 +1,13 @@ -{-# LANGUAGE ForeignFunctionInterface, GADTs, LambdaCase #-} +{-# LANGUAGE CPP, ForeignFunctionInterface, GADTs, LambdaCase #-} module IServ.Remote.Interpreter where import Network.Socket +#if MIN_VERSION_ghci(9,4,1) import IServ (serv) +#else +import Lib (serv) +#endif import IServ.Remote.Message import System.IO From d37cd95e060e02802a1dd9b3f9128320ccea37a2 Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Wed, 5 Jul 2023 12:09:19 +1200 Subject: [PATCH 05/57] libiserv is included in ghci from 9.8 (cherry picked from commit 5a545fd94dc19cb1ec1853ecb9bd313e56f34516) --- iserv-proxy.cabal | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/iserv-proxy.cabal b/iserv-proxy.cabal index 9c4a026..20256ab 100644 --- a/iserv-proxy.cabal +++ b/iserv-proxy.cabal @@ -80,8 +80,9 @@ Library directory >= 1.3 && < 1.4, network >= 2.6, filepath >= 1.4 && < 1.5, - ghci == 9.3, - libiserv == 9.3 + ghci + if impl(ghc < 9.8) + Build-Depends: libiserv Executable iserv-proxy Default-Language: Haskell2010 @@ -92,9 +93,10 @@ Executable iserv-proxy directory >= 1.3 && < 1.4, network >= 2.6, filepath >= 1.4 && < 1.5, - ghci == 9.3, - libiserv == 9.3, + ghci, iserv-proxy + if impl(ghc < 9.8) + Build-Depends: libiserv Executable iserv-proxy-interpreter Default-Language: Haskell2010 From 5e39e2a5a10b2043ba55e99feac1d8934f09954e Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Wed, 5 Jul 2023 12:27:41 +1200 Subject: [PATCH 06/57] libiserv is included in ghci from 9.8 (cherry picked from commit b3a865acd224e2773e3f16caceb83ad9b4100fc3) --- src/IServ/Remote/Interpreter.hs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/IServ/Remote/Interpreter.hs b/src/IServ/Remote/Interpreter.hs index e5fe102..6b1ce18 100644 --- a/src/IServ/Remote/Interpreter.hs +++ b/src/IServ/Remote/Interpreter.hs @@ -3,7 +3,9 @@ module IServ.Remote.Interpreter where import Network.Socket -#if MIN_VERSION_ghci(9,4,1) +#if MIN_VERSION_ghci(9,8,1) +import GHCi.Server (serv) +#elif MIN_VERSION_ghci(9,4,1) import IServ (serv) #else import Lib (serv) From 27bf2a518b88444d5ec33e038648f4abe17cf936 Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Wed, 5 Jul 2023 12:32:10 +1200 Subject: [PATCH 07/57] libiserv is included in ghci from 9.8 (cherry picked from commit 9151db2a9a61d7f5fe52ff8836f18bbd0fd8933c) --- src/IServ/Remote/Interpreter.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/IServ/Remote/Interpreter.hs b/src/IServ/Remote/Interpreter.hs index 6b1ce18..e15bb14 100644 --- a/src/IServ/Remote/Interpreter.hs +++ b/src/IServ/Remote/Interpreter.hs @@ -3,7 +3,7 @@ module IServ.Remote.Interpreter where import Network.Socket -#if MIN_VERSION_ghci(9,8,1) +#if MIN_VERSION_ghci(9,8,0) import GHCi.Server (serv) #elif MIN_VERSION_ghci(9,4,1) import IServ (serv) From 0ef42dcea27c8b68bb5a05f6a2278858d8011a4d Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Thu, 10 Aug 2023 14:31:36 +1200 Subject: [PATCH 08/57] Update deepseq upper bound (cherry picked from commit 43a979272d9addc29fbffc2e8542c5d96e993d73) --- iserv-proxy.cabal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iserv-proxy.cabal b/iserv-proxy.cabal index 20256ab..038333b 100644 --- a/iserv-proxy.cabal +++ b/iserv-proxy.cabal @@ -76,7 +76,7 @@ Library binary >= 0.7 && < 0.9, bytestring >= 0.10 && < 0.12, containers >= 0.5 && < 0.8, - deepseq >= 1.4 && < 1.5, + deepseq >= 1.4 && < 1.6, directory >= 1.3 && < 1.4, network >= 2.6, filepath >= 1.4 && < 1.5, From 7f665ecab0936ff2caab494e33fd2c3af8c098f9 Mon Sep 17 00:00:00 2001 From: Moritz Angermann Date: Wed, 29 Nov 2023 15:17:51 +0800 Subject: [PATCH 09/57] Sigh --- iserv-proxy.cabal | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/iserv-proxy.cabal b/iserv-proxy.cabal index 038333b..bfd8fc8 100644 --- a/iserv-proxy.cabal +++ b/iserv-proxy.cabal @@ -64,6 +64,8 @@ Description: Category: Development build-type: Simple cabal-version: >=1.10 +-- these aren't really headers. They are more like includable files. +extra-source-files: cbits/symbols.aarch64-musl.h Library Default-Language: Haskell2010 @@ -104,7 +106,6 @@ Executable iserv-proxy-interpreter -- We need to pass -fkeep-cafs to ensure that the interpreter retains CAFs -- Iserv and GHC do something similar. ghc-options: -fkeep-cafs - includes: cbits/symbols.aarch64-musl.h c-sources: cbits/symbols.aarch64-musl.c Build-Depends: base >= 4 && < 5, iserv-proxy From 454344450f03d2107972846f685177dc1c14da61 Mon Sep 17 00:00:00 2001 From: Moritz Angermann Date: Wed, 29 Nov 2023 15:26:05 +0800 Subject: [PATCH 10/57] [aarch64-musl] Add ptsname --- cbits/symbols.aarch64-musl.h | 1 + 1 file changed, 1 insertion(+) diff --git a/cbits/symbols.aarch64-musl.h b/cbits/symbols.aarch64-musl.h index 686d7fe..1b18841 100644 --- a/cbits/symbols.aarch64-musl.h +++ b/cbits/symbols.aarch64-musl.h @@ -1 +1,2 @@ SYM(fprintf) +SYM(ptsname) From 94fb984525299d650485b1fa44b2ba163e5f8162 Mon Sep 17 00:00:00 2001 From: Moritz Angermann Date: Wed, 29 Nov 2023 15:39:46 +0800 Subject: [PATCH 11/57] add more printf stuff --- cbits/symbols.aarch64-musl.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cbits/symbols.aarch64-musl.h b/cbits/symbols.aarch64-musl.h index 1b18841..555c013 100644 --- a/cbits/symbols.aarch64-musl.h +++ b/cbits/symbols.aarch64-musl.h @@ -1,2 +1,4 @@ SYM(fprintf) +SYM(snprintf) +SYM(vsnprintf) SYM(ptsname) From c00e3fbd306654cee2a58d959c7f32e9f9989ee3 Mon Sep 17 00:00:00 2001 From: Moritz Angermann Date: Wed, 29 Nov 2023 18:18:42 +0800 Subject: [PATCH 12/57] Only on aarch64-linux include aarch64-musl --- iserv-proxy.cabal | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/iserv-proxy.cabal b/iserv-proxy.cabal index bfd8fc8..e3f0fe5 100644 --- a/iserv-proxy.cabal +++ b/iserv-proxy.cabal @@ -106,7 +106,10 @@ Executable iserv-proxy-interpreter -- We need to pass -fkeep-cafs to ensure that the interpreter retains CAFs -- Iserv and GHC do something similar. ghc-options: -fkeep-cafs - c-sources: cbits/symbols.aarch64-musl.c + -- no idea how to check for musl :-/ + if os(linux) && arch(aarch64) + c-sources: cbits/symbols.aarch64-musl.c + Build-Depends: base >= 4 && < 5, iserv-proxy From 7cbb7e3518cfbe7a7b03f068064f5613491ffa21 Mon Sep 17 00:00:00 2001 From: Moritz Angermann Date: Thu, 30 Nov 2023 16:44:17 +0800 Subject: [PATCH 13/57] add closure_sizeW_ to symbols We only have this for windows in haskell.nix so far :sweat_smile: --- cbits/symbols.aarch64-musl.h | 1 + 1 file changed, 1 insertion(+) diff --git a/cbits/symbols.aarch64-musl.h b/cbits/symbols.aarch64-musl.h index 555c013..b5f6fd4 100644 --- a/cbits/symbols.aarch64-musl.h +++ b/cbits/symbols.aarch64-musl.h @@ -2,3 +2,4 @@ SYM(fprintf) SYM(snprintf) SYM(vsnprintf) SYM(ptsname) +SYM(closure_sizeW_) \ No newline at end of file From a90a789587408c5f2c49f77fa343056a663325e4 Mon Sep 17 00:00:00 2001 From: Moritz Angermann Date: Wed, 21 Feb 2024 10:41:13 +0000 Subject: [PATCH 14/57] Add more libc functions --- cbits/symbols.aarch64-musl.h | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/cbits/symbols.aarch64-musl.h b/cbits/symbols.aarch64-musl.h index b5f6fd4..589db97 100644 --- a/cbits/symbols.aarch64-musl.h +++ b/cbits/symbols.aarch64-musl.h @@ -2,4 +2,23 @@ SYM(fprintf) SYM(snprintf) SYM(vsnprintf) SYM(ptsname) -SYM(closure_sizeW_) \ No newline at end of file +SYM(closure_sizeW_) +SYM(__addtf3) +SYM(__divtf3) +SYM(__extenddftf2) +SYM(__fixtfsi) +SYM(__floatditf) +SYM(__floatsitf) +SYM(__getf2) +SYM(__gttf2) +SYM(__lttf2) +SYM(__multf3) +SYM(__subtf3) +SYM(__trunctfdf2) +SYM(__trunctfsf2) +SYM(__floatunsitf) +SYM(__extendsftf2) +SYM(__eqtf2) +SYM(__netf2) +SYM(__letf2) +SYM(__fixunstfsi) From 13a1adc657e01cd6506466942233eabe21a6da24 Mon Sep 17 00:00:00 2001 From: Moritz Angermann Date: Wed, 21 Feb 2024 10:41:28 +0000 Subject: [PATCH 15/57] Add getauxval (needed by e.g. libblst) --- cbits/symbols.aarch64-musl.h | 1 + 1 file changed, 1 insertion(+) diff --git a/cbits/symbols.aarch64-musl.h b/cbits/symbols.aarch64-musl.h index 589db97..d6ed934 100644 --- a/cbits/symbols.aarch64-musl.h +++ b/cbits/symbols.aarch64-musl.h @@ -22,3 +22,4 @@ SYM(__eqtf2) SYM(__netf2) SYM(__letf2) SYM(__fixunstfsi) +SYM(getauxval) \ No newline at end of file From 2f2a318fd8837f8063a0d91f329aeae29055fba9 Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Fri, 16 Feb 2024 09:56:43 +1300 Subject: [PATCH 16/57] Update bytestring and filepath upper bounds --- iserv-proxy.cabal | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/iserv-proxy.cabal b/iserv-proxy.cabal index e3f0fe5..5f1449a 100644 --- a/iserv-proxy.cabal +++ b/iserv-proxy.cabal @@ -76,12 +76,12 @@ Library Build-Depends: array >= 0.5 && < 0.6, base >= 4 && < 5, binary >= 0.7 && < 0.9, - bytestring >= 0.10 && < 0.12, + bytestring >= 0.10 && < 0.13, containers >= 0.5 && < 0.8, deepseq >= 1.4 && < 1.6, directory >= 1.3 && < 1.4, network >= 2.6, - filepath >= 1.4 && < 1.5, + filepath >= 1.4 && < 1.6, ghci if impl(ghc < 9.8) Build-Depends: libiserv @@ -91,10 +91,10 @@ Executable iserv-proxy Main-Is: Main.hs Build-Depends: base >= 4 && < 5, binary >= 0.7 && < 0.9, - bytestring >= 0.10 && < 0.12, + bytestring >= 0.10 && < 0.13, directory >= 1.3 && < 1.4, network >= 2.6, - filepath >= 1.4 && < 1.5, + filepath >= 1.4 && < 1.6, ghci, iserv-proxy if impl(ghc < 9.8) From 494c0f66af17d6e0fb955fcbd41f4fae33efc35b Mon Sep 17 00:00:00 2001 From: Moritz Angermann Date: Sat, 16 Mar 2024 12:25:12 +0800 Subject: [PATCH 17/57] Add malloc/free to aarch64-musl Without these, we'll end up with lots of > `getDirectoryContents:openDirStream: invalid argument (Invalid argument)` this is due to malloc failing (the malloc from the in-memory loaded libc). loading two libcs into the same process is never a good idea. --- cbits/symbols.aarch64-musl.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cbits/symbols.aarch64-musl.h b/cbits/symbols.aarch64-musl.h index d6ed934..a423c61 100644 --- a/cbits/symbols.aarch64-musl.h +++ b/cbits/symbols.aarch64-musl.h @@ -22,4 +22,6 @@ SYM(__eqtf2) SYM(__netf2) SYM(__letf2) SYM(__fixunstfsi) -SYM(getauxval) \ No newline at end of file +SYM(getauxval) +SYM(malloc) +SYM(free) From 50ea210590ab0519149bfd163d5ba199be925fb6 Mon Sep 17 00:00:00 2001 From: Moritz Angermann Date: Sat, 16 Mar 2024 17:35:58 +0800 Subject: [PATCH 18/57] Add pipe related things This is used by readCreateProcessWithExitCode. --- cbits/symbols.aarch64-musl.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cbits/symbols.aarch64-musl.h b/cbits/symbols.aarch64-musl.h index a423c61..b311a69 100644 --- a/cbits/symbols.aarch64-musl.h +++ b/cbits/symbols.aarch64-musl.h @@ -25,3 +25,11 @@ SYM(__fixunstfsi) SYM(getauxval) SYM(malloc) SYM(free) +SYM(pipe) +SYM(fcntl) +SYM(posix_spawn_file_actions_init) +SYM(posix_spawnattr_init) +SYM(posix_spawn_file_actions_destroy) +SYM(posix_spawn_file_actions_addopen) +SYM(posix_spawn_file_actions_adddup2) +SYM(posix_spawn_file_actions_addclose) From 2ed34002247213fc435d0062350b91bab920626e Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Tue, 4 Jun 2024 17:46:12 +1200 Subject: [PATCH 19/57] Add `--no-load-call` flag for wine cross compiles --- Interpreter.hs | 15 +++++++++------ Main.hs | 19 ++++++++++--------- src/IServ/Remote/Interpreter.hs | 14 +++++++------- 3 files changed, 26 insertions(+), 22 deletions(-) diff --git a/Interpreter.hs b/Interpreter.hs index 323449b..3b3ecc8 100644 --- a/Interpreter.hs +++ b/Interpreter.hs @@ -4,6 +4,8 @@ import IServ.Remote.Interpreter (startInterpreter') import System.Environment (getArgs, getProgName) import System.Exit (die) +import Control.Monad (when) + main :: IO () main = getArgs >>= startSlave @@ -12,7 +14,7 @@ dieWithUsage = do prog <- getProgName die $ msg prog where - msg name = "usage: " ++ name ++ " /path/to/storage PORT [-v]" + msg name = "usage: " ++ name ++ " /path/to/storage PORT [-v] [--no-load-call]" startSlave :: [String] -> IO () startSlave args0 @@ -22,9 +24,10 @@ startSlave args0 arg0:arg1:rest -> return (arg0, read arg1, rest) _ -> dieWithUsage - verbose <- case rest of - ["-v"] -> return True - [] -> return False - _ -> dieWithUsage + let verbose = "-v" `elem` rest + noLoadCall = "--no-load-call" `elem` rest + + when (any (not . (`elem` ["-v", "--no-load-call"])) rest) + dieWithUsage - startInterpreter' verbose path port \ No newline at end of file + startInterpreter' verbose noLoadCall path port diff --git a/Main.hs b/Main.hs index 7be069e..2eb5263 100644 --- a/Main.hs +++ b/Main.hs @@ -98,10 +98,11 @@ main = do return (wfd1, rfd2, ip, port, rest) _ -> dieWithUsage - verbose <- case rest of - ["-v"] -> return True - [] -> return False - _ -> dieWithUsage + let verbose = "-v" `elem` rest + noLoadCall = "--no-load-call" `elem` rest + + when (any (not . (`elem` ["-v", "--no-load-call"])) rest) + dieWithUsage when verbose $ printf "GHC iserv starting (in: %d; out: %d)\n" @@ -124,7 +125,7 @@ main = do when verbose $ trace "Starting proxy" - proxy verbose in_pipe out_pipe + proxy verbose noLoadCall in_pipe out_pipe -- | A hook, to transform outgoing (proxy -> interpreter) -- messages prior to sending them to the interpreter. @@ -207,7 +208,7 @@ fwdLoadCall verbose _ remote msg = do writePipe remote (put m) loopLoad :: IO () loopLoad = do - when verbose $ trace "fwdLoadCall: reading remote pipe" + when verbose $ trace "fwdLoadCall: X reading remote pipe" SomeProxyMessage msg' <- readPipe remote getProxyMessage when verbose $ trace ("| Sl Msg: proxy <- interpreter: " ++ show msg') @@ -227,8 +228,8 @@ fwdLoadCall verbose _ remote msg = do -- | The actual proxy. Conntect local and remote pipe, -- and does some message handling. -proxy :: Bool -> Pipe -> Pipe -> IO () -proxy verbose local remote = loop +proxy :: Bool -> Bool -> Pipe -> Pipe -> IO () +proxy verbose noLoadCall local remote = loop where fwdCall :: (Binary a, Show a) => Message a -> IO a fwdCall msg = do @@ -283,7 +284,7 @@ proxy verbose local remote = loop -- that are referenced in C:\ these are usually system libraries. LoadDLL path@('C':':':_) -> do fwdCall msg' >>= reply >> loop - LoadDLL path | isAbsolute path -> do + LoadDLL path | isAbsolute path && not noLoadCall -> do resp <- fwdLoadCall verbose local remote msg' reply resp loop diff --git a/src/IServ/Remote/Interpreter.hs b/src/IServ/Remote/Interpreter.hs index e15bb14..bb077e4 100644 --- a/src/IServ/Remote/Interpreter.hs +++ b/src/IServ/Remote/Interpreter.hs @@ -56,14 +56,14 @@ startInterpreter :: Bool -> Int -> CString -> IO () startInterpreter verbose port s = do base_path <- peekCString s trace $ "DocRoot: " ++ base_path - _ <- forkIO $ startInterpreter' verbose base_path (toEnum port) + _ <- forkIO $ startInterpreter' verbose True base_path (toEnum port) return () -- | @startInterpreter'@ provdes a blocking haskell interface, that -- the hosting application on the target can use to start the -- interpreter process. -startInterpreter' :: Bool -> String -> PortNumber -> IO () -startInterpreter' verbose base_path port = do +startInterpreter' :: Bool -> Bool -> String -> PortNumber -> IO () +startInterpreter' verbose noLoadCall base_path port = do hSetBuffering stdin LineBuffering hSetBuffering stdout LineBuffering @@ -85,7 +85,7 @@ startInterpreter' verbose base_path port = do when verbose $ trace "Opening socket" pipe <- acceptSocket sock >>= socketToPipe when verbose $ trace "Starting serv" - uninterruptibleMask $ serv verbose (hook verbose base_path pipe) pipe + uninterruptibleMask $ serv verbose (hook verbose noLoadCall base_path pipe) pipe when verbose $ trace "serv ended" return () @@ -124,8 +124,8 @@ handleLoad pipe path localPath = do -- | The hook we install in the @serv@ function from the -- iserv library, to request archives over the wire. -hook :: Bool -> String -> Pipe -> Msg -> IO Msg -hook verbose base_path pipe m = case m of +hook :: Bool -> Bool -> String -> Pipe -> Msg -> IO Msg +hook verbose noLoadCall base_path pipe m = case m of Msg (AddLibrarySearchPath p) -> do when verbose $ putStrLn ("Need Path: " ++ (base_path p)) createDirectoryIfMissing True (base_path p) @@ -148,7 +148,7 @@ hook verbose base_path pipe m = case m of -- When building on nix the /nix/store paths use Z: Msg (LoadDLL path@('Z':':':_)) -> do return m - Msg (LoadDLL path) | isAbsolute path -> do + Msg (LoadDLL path) | isAbsolute path && not noLoadCall -> do when verbose $ trace ("Need DLL: " ++ (base_path path)) handleLoad pipe path (base_path path) return $ Msg (LoadDLL (base_path path)) From 9fee3a1950c1a8ae2cfd7b7a080b431c342c00f1 Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Tue, 11 Feb 2025 14:29:16 +1300 Subject: [PATCH 20/57] Add other platforms --- cbits/symbols.aarch64-android.c | 327 +++++++++++++++++++++++ cbits/symbols.armv7a-android.c | 456 ++++++++++++++++++++++++++++++++ cbits/symbols.x86_64-musl.c | 318 ++++++++++++++++++++++ iserv-proxy.cabal | 15 +- 4 files changed, 1114 insertions(+), 2 deletions(-) create mode 100644 cbits/symbols.aarch64-android.c create mode 100644 cbits/symbols.armv7a-android.c create mode 100644 cbits/symbols.x86_64-musl.c diff --git a/cbits/symbols.aarch64-android.c b/cbits/symbols.aarch64-android.c new file mode 100644 index 0000000..a73a6fb --- /dev/null +++ b/cbits/symbols.aarch64-android.c @@ -0,0 +1,327 @@ +#define BIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// #include +// #include // this includes too many overloaded items. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// fnctl stubs, see above +extern void open(void); +extern void openat(void); +extern void creat(void); +extern void eventfd(void); +extern void eventfd_write(void); + +extern void futimes(void); +extern void lutimes(void); +extern void statx(void); + +extern void __stack_chk_fail(void); +extern void __vsprintf_chk(void); +extern void __open_2(void); +extern void __memcpy_chk(void); +extern void __memset_chk(void); +extern void __memmove_chk(void); +// GCC stuff +extern void __addtf3(void); +extern void __divtf3(void); +extern void __extenddftf2(void); +extern void __fixtfsi(void); +extern void __floatditf(void); +extern void __floatsitf(void); +extern void __getf2(void); +extern void __gttf2(void); +extern void __lttf2(void); +extern void __multf3(void); +extern void __subtf3(void); +extern void __trunctfdf2(void); + +extern void flock(void); +extern void times(void); + +#define MISSING_FUN(f) void (f)(void) { printf("Unknown call to `%s'\n", #f); exit(1); } + +MISSING_FUN(c_format_unix_time) +MISSING_FUN(c_format_unix_time_gmt) +MISSING_FUN(c_parse_unix_time) +MISSING_FUN(c_parse_unix_time_gmt) + +typedef void SymbolAddr; +typedef char SymbolName; + +typedef enum _SymStrength { + STRENGTH_NORMAL, + STRENGTH_WEAK, + STRENGTH_STRONG, +} SymStrength; + +typedef enum _SymType { + SYM_TYPE_CODE = 1 << 0, /* the symbol is a function and can be relocated via a jump island */ + SYM_TYPE_DATA = 1 << 1, /* the symbol is data */ + SYM_TYPE_INDIRECT_DATA = 1 << 2, /* see Note [_iob_func symbol] */ + 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. */ +} SymType; + +typedef struct _RtsSymbolVal { + const SymbolName* lbl; + SymbolAddr* addr; + SymStrength strength; + SymType type; +} RtsSymbolVal; + +#define SYM(x) { #x, (void*)(&x), STRENGTH_NORMAL, 1 } +typedef mode_t (*umask_func_ptr_t)(mode_t); + +RtsSymbolVal my_iserv_syms[] = { + // arpa/inet.h + SYM(htons), + SYM(ntohs), + SYM(htonl), + SYM(ntohl), + // sys/random.h + SYM(getentropy), + SYM(getrandom), + // sys/auxv.h + SYM(getauxval), + // sys/mman.h + SYM(madvise),SYM(mlock),SYM(mmap),SYM(mprotect),SYM(munmap), + SYM(mremap), + SYM(munlock), + // select.h + SYM(__FD_SET_chk), + // sys/socket + SYM(accept),SYM(bind),SYM(connect),SYM(getsockopt),SYM(listen), + SYM(setsockopt),SYM(socket),SYM(getsockname),SYM(select), + SYM(getpeername),SYM(__cmsg_nxthdr),SYM(recv),SYM(recvfrom), + SYM(recvmsg),SYM(send),SYM(sendmsg),SYM(sendto),SYM(writev), + SYM(accept4), + // pthread.h + SYM(pthread_equal),SYM(pthread_getspecific),SYM(pthread_key_create), + SYM(pthread_key_delete),SYM(pthread_once),SYM(pthread_rwlock_destroy), + SYM(pthread_rwlock_init),SYM(pthread_rwlock_rdlock),SYM(pthread_rwlock_unlock), + SYM(pthread_rwlock_wrlock),SYM(pthread_self),SYM(pthread_setspecific), + SYM(pthread_create),SYM(pthread_join),SYM(pthread_mutex_destroy), + SYM(pthread_mutex_init),SYM(pthread_mutex_lock),SYM(pthread_mutex_trylock), + SYM(pthread_mutex_unlock),SYM(pthread_mutexattr_destroy), + SYM(pthread_mutexattr_init),SYM(pthread_mutexattr_settype), + // chk.h + SYM(__read_chk),SYM(__write_chk), + // netdb.h + SYM(freeaddrinfo),SYM(gai_strerror),SYM(getaddrinfo),SYM(getnameinfo), + SYM(gethostbyname), + // dirent.h + SYM(readdir_r),SYM(readdir), + SYM(opendir),SYM(closedir), + // time.h + SYM(clock),SYM(gmtime_r), + // sys/time.h + SYM(gettimeofday),SYM(clock_getres),SYM(clock_gettime),SYM(localtime_r),SYM(tzset), + // unistd.h + SYM(readlink), + SYM(rename), + SYM(rmdir), + SYM(chown), + SYM(realpath), + SYM(fchdir), + SYM(fdopendir), + SYM(rewinddir), + SYM(futimens),SYM(futimes),SYM(lutimes), + SYM(mknod), + SYM(lchown), + SYM(symlink), + SYM(endgrent),SYM(endpwent), + SYM(pathconf), + SYM(truncate), + SYM(utimensat), + SYM(statx), + SYM(seekdir), + SYM(telldir), + SYM(clearenv), + SYM(chdir), + SYM(sleep), + SYM(stdout), + SYM(strftime), + SYM(utimes), + SYM(times), + SYM(setenv), + SYM(fpathconf), + SYM(exit), + SYM(environ), + SYM(ftruncate), + SYM(getenv), + SYM(putenv), + SYM(unsetenv), + SYM(read), + SYM(write), + SYM(isatty), + SYM(link), + SYM(pipe), + SYM(unlink), + SYM(execv),SYM(execve),SYM(execvp),SYM(execvpe), + SYM(syscall),SYM(sysconf), + // errno.h + SYM(__errno), + // math.h + SYM(sinhf), SYM(sinh), SYM(sinf), SYM(sin), + SYM(coshf), SYM(cosh), SYM(cosf), SYM(cos), + SYM(atanhf), SYM(atanh), SYM(atanf), SYM(atan), + SYM(asinhf), SYM(asinh), SYM(asinf), SYM(asin), + SYM(acoshf), SYM(acosh), SYM(acosf), SYM(acos), + SYM(log1pf), SYM(log1p), SYM(logf), SYM(log), + SYM(expm1f), SYM(expm1), + SYM(expf), SYM(exp), + SYM(ldexp), + SYM(powf), SYM(pow), + SYM(sqrtf), SYM(sqrt), + SYM(tanhf), SYM(tanh), SYM(tanf), SYM(tan), + // assert.h + SYM(__assert2), + // signal.h + SYM(signal),SYM(sigaction), + SYM(raise), SYM(sigaddset), SYM(sigemptyset), SYM(sigprocmask), + // sys/eventfd.h + SYM(eventfd), SYM(eventfd_write), + // sys/stat.h + SYM(fstat), + SYM(lstat), + SYM(stat), + SYM(chmod), + SYM(mkfifo), + // SYM(umask), + { "umask", (umask_func_ptr_t)(&umask), STRENGTH_NORMAL, 1 }, + // sys/wait.h + SYM(waitpid), + // sym/epoll.h + SYM(epoll_create), SYM(epoll_ctl), SYM(epoll_wait), + // poll.h + SYM(poll), + // fcntl.h + SYM(open), SYM(creat), SYM(fcntl), SYM(ioctl), + SYM(openat),SYM(__open_2), + // string.h + SYM(strerror), + SYM(strerror_r), + SYM(strcmp), + SYM(memchr),SYM(strcpy),SYM(strchr),SYM(strncpy),SYM(strrchr), + SYM(strcat),SYM(strncmp),SYM(strdup), + SYM(strtoul),SYM(strspn),SYM(strtol),SYM(strstr),SYM(strcspn), + SYM(__strncpy_chk2),SYM(__memcpy_chk), + // ctype.h + SYM(__ctype_get_mb_cur_max), + // wchar.h + SYM(mbrtowc), SYM(wcrtomb), + // stdlib.h + SYM(qsort), + // unistd.h + SYM(access), SYM(close), SYM(dup), SYM(dup2), SYM(fork), SYM(getpid), + SYM(lseek), + // utime.h + SYM(utime),SYM(time), + // ... + SYM(fileno), + SYM(__vsprintf_chk), + SYM(__strlen_chk), + SYM(__strchr_chk), + SYM(__memset_chk), + SYM(__memmove_chk), + SYM(__stack_chk_fail), + SYM(memmove), + SYM(memcmp), + SYM(memcpy), + SYM(memset), + SYM(stderr), + SYM(realloc), + SYM(calloc), + SYM(malloc), + SYM(free), + SYM(fprintf), + SYM(vfprintf), + SYM(fopen), SYM(fclose), + SYM(flock), + SYM(getegid),SYM(getgid), + SYM(getpwent), + SYM(getgrent), + SYM(getgroups), + SYM(getlogin), + SYM(getuid), + SYM(getgrgid_r),SYM(getgrnam_r),SYM(getpwnam_r),SYM(getpwuid_r), + SYM(setegid),SYM(seteuid),SYM(setgid),SYM(setgrent),SYM(setgroups), + SYM(setpwent),SYM(setuid), + SYM(fread), + SYM(abort), + SYM(strlen), + SYM(fwrite), + SYM(feof), + SYM(ferror), + SYM(fflush), + SYM(fgets),SYM(fputc),SYM(fputs), + SYM(puts), + SYM(fseek),SYM(ftell), + SYM(sscanf), + SYM(shutdown), + SYM(atoi), + SYM(stdin), + SYM(atexit), + SYM(usleep), + SYM(fchmod), + SYM(fchown), + SYM(fsync), + SYM(getcwd), + SYM(geteuid), + SYM(localtime), + SYM(lseek64), + SYM(mkdir), + SYM(mktime), + SYM(fdopen), + SYM(c_format_unix_time), + SYM(c_format_unix_time_gmt), + SYM(c_parse_unix_time), + SYM(c_parse_unix_time_gmt), + SYM(__addtf3), + SYM(__divtf3), + SYM(__extenddftf2), + SYM(__fixtfsi), + SYM(__floatditf), + SYM(__floatsitf), + SYM(__getf2), + SYM(__gttf2), + SYM(__lttf2), + SYM(__multf3), + SYM(__subtf3), + SYM(__trunctfdf2), + SYM(getrusage), + { 0, 0, STRENGTH_NORMAL, 1 } /* sentinel */ +}; + +RtsSymbolVal* iserv_syms() { + return my_iserv_syms; +} \ No newline at end of file diff --git a/cbits/symbols.armv7a-android.c b/cbits/symbols.armv7a-android.c new file mode 100644 index 0000000..1bcba1b --- /dev/null +++ b/cbits/symbols.armv7a-android.c @@ -0,0 +1,456 @@ +#include +#include +#include +#include +#include +#include + +extern void __aeabi_idiv(void); +extern void __aeabi_idivmod(void); +extern void __aeabi_memcpy(void); +extern void __aeabi_memclr(void); +extern void __aeabi_memclr4(void); +extern void __aeabi_ldivmod(void); +extern void __aeabi_memcpy4(void); +extern void __aeabi_memmove(void); +extern void __aeabi_memset4(void); +extern void __aeabi_uidiv(void); +extern void __aeabi_uidivmod(void); +extern void __aeabi_uldivmod(void); + +extern void eventfd_write(void); +extern void ioctl(void); +extern void close(void); +extern void epoll_wait(void); +// extern void expf(void); +extern void getpid(void); +extern void isatty(void); +extern void waitpid(void); + +extern void dup2(void); +extern void epoll_ctl(void); +extern void ftruncate64(void); +extern void link(void); +extern void pipe(void); + +extern void __assert2(void); +extern void dup(void); +extern void epoll_create(void); +extern void eventfd(void); +extern void fork(void); +extern void unlink(void); +extern void creat(void); +extern void fcntl(void); +extern void open(void); +extern void access(void); +extern void environ(void); +extern void lseek64(void); +extern void umask(void); +extern void poll(void); +extern void raise(void); +extern void mbrtowc(void); +extern void sigprocmask(void); +extern void sigaddset(void); +extern void sigemptyset(void); +extern void stat(void); +extern void utime(void); +extern void chmod(void); +extern void mkfifo(void); +extern void wcrtomb(void); +extern void lstat(void); +extern void fstat(void); +extern void write(void); +extern void read(void); +extern void __stack_chk_fail(void); +extern void __stack_chk_guard(void); +extern void __aeabi_memclr8(void); +extern void __aeabi_memcpy8(void); +extern void __aeabi_memmove4(void); +extern void __write_chk(void); +extern void time(void); +extern void uname(void); +extern void tzset(void); +extern void sysconf(void); +extern void socket(void); +extern void readdir(void); +extern void pthread_rwlock_init(void); +extern void __memset_chk(void); +extern void __memcpy_chk(void); +extern void gmtime_r(void); +extern void getauxval(void); +extern void clock_gettime(void); +extern void __aeabi_memset4(void); +extern void __aeabi_memset8(void); +extern void __aeabi_memset(void); +extern void __vsprintf_chk(void); +extern void usleep(void); +extern void setsockopt(void); +extern void __read_chk(void); +extern void opendir(void); +extern void mmap(void); +extern void pthread_rwlock_rdlock(void); +extern void __memmove_chk(void); +extern void localtime_r(void); +extern void getsockopt(void); +extern void getnameinfo(void); +extern void getentropy(void); +extern void clock_getres(void); +extern void __aeabi_d2lz(void); +extern void __aeabi_l2d(void); +extern void __aeabi_d2ulz(void); +extern void syscall(void); +extern void shutdown(void); +extern void pthread_rwlock_wrlock(void); +extern void mprotect(void); +extern void gettimeofday(void); +extern void gethostbyname(void); +extern void gai_strerror(void); +extern void fsync(void); +extern void connect(void); +extern void closedir(void); +extern void bind(void); +extern void sleep(void); +extern void pthread_rwlock_unlock(void); +extern void __open_2(void); +extern void mlock(void); +extern void listen(void); +extern void freeaddrinfo(void); +extern void clock(void); +extern void __aeabi_ul2d(void); +extern void accept(void); +extern void strftime(void); +extern void pthread_rwlock_destroy(void); +extern void madvise(void); +extern void getsockname(void); +extern void getaddrinfo(void); +extern void sigaction(void); +extern void pthread_once(void); +extern void munmap(void); +extern void __FD_SET_chk(void); +extern void __cmsg_nxthdr(void); +extern void pthread_key_create(void); +extern void select(void); +extern void sendmsg(void); +extern void signal(void); +extern void pthread_getspecific(void); +extern void pthread_setspecific(void); +extern void munlock(void); +extern void pthread_key_delete(void); +extern void pthread_key_create(void); +extern void pthread_mutexattr_init(void); +extern void pthread_self(void); +extern void pthread_mutexattr_settype(void); +extern void pthread_equal(void); +extern void pthread_mutex_init(void); +extern void pthread_mutexattr_destroy(void); +extern void pthread_mutex_destroy(void); +extern void pthread_mutex_lock(void); +extern void pthread_mutex_trylock(void); +extern void pthread_mutex_unlock(void); +extern void utimes(void); +extern void pthread_join(void); +extern void __aeabi_l2f(void); +extern void pthread_create(void); +extern void localtime(void); +extern void getcwd(void); +extern void fchmod(void); +extern void mkdir(void); +extern void rmdir(void); +extern void fchown(void); +extern void geteuid(void); +extern void mmap64(void); +extern void mremap(void); +extern void readlink(void); +extern void flock(void); +extern void times(void); +extern void getrusage(void); + +#define MISSING_FUN(f) void (f)(void) { printf("Unknown call to %s\n", #f); exit(1); } + +MISSING_FUN(c_format_unix_time) +MISSING_FUN(c_format_unix_time_gmt) +MISSING_FUN(c_parse_unix_time) +MISSING_FUN(c_parse_unix_time_gmt) + +typedef void SymbolAddr; +typedef char SymbolName; + +typedef enum _SymStrength { + STRENGTH_NORMAL, + STRENGTH_WEAK, + STRENGTH_STRONG, +} SymStrength; + +typedef enum _SymType { + SYM_TYPE_CODE = 1 << 0, /* the symbol is a function and can be relocated via a jump island */ + SYM_TYPE_DATA = 1 << 1, /* the symbol is data */ + SYM_TYPE_INDIRECT_DATA = 1 << 2, /* see Note [_iob_func symbol] */ + 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. */ +} SymType; + +typedef struct _RtsSymbolVal { + const SymbolName* lbl; + SymbolAddr* addr; + SymStrength strength; + SymType type; +} RtsSymbolVal; + +#define SYM(x) { #x, (void*)(&x), STRENGTH_NORMAL, 1 } +typedef mode_t (*umask_func_ptr_t)(mode_t); + +RtsSymbolVal my_iserv_syms[] = { + SYM(strlen), + SYM(__aeabi_idiv), + SYM(__aeabi_idivmod), + SYM(__aeabi_memcpy), + SYM(__aeabi_memclr), + SYM(__aeabi_memclr4), + SYM(__aeabi_ldivmod), + SYM(__aeabi_memcpy4), + SYM(__aeabi_memmove), + SYM(__aeabi_memset4), + SYM(__aeabi_uidiv), + SYM(__aeabi_uidivmod), + SYM(__aeabi_uldivmod), + SYM(calloc), + SYM(malloc), + SYM(free), + SYM(realloc), + SYM(abort), + SYM(close), + SYM(epoll_wait), + SYM(__errno), + SYM(eventfd_write), + SYM(expf), + SYM(fprintf), + SYM(getenv), + SYM(getpid), + SYM(ioctl), + SYM(isatty), + SYM(memcmp), + SYM(poll), + SYM(raise), + SYM(strcmp), + SYM(strerror), + SYM(setenv), + SYM(unsetenv), + SYM(waitpid), + SYM(dup2), + SYM(epoll_ctl), + SYM(ftruncate64), + SYM(ldexp), + SYM(link), + SYM(log1pf), + SYM(mbrtowc), + SYM(pipe), + SYM(putenv), + SYM(sigprocmask), + SYM(stderr), + SYM(__assert2), + SYM(dup), + SYM(epoll_create), + SYM(eventfd), + SYM(expm1f), + SYM(fork), + SYM(sigaddset), + SYM(stat), + SYM(wcrtomb), + SYM(__ctype_get_mb_cur_max), + SYM(fstat), + SYM(logf), + SYM(sigemptyset), + SYM(unlink), + SYM(creat), + SYM(lstat), + SYM(mkfifo), + SYM(qsort), + SYM(sinf), + SYM(chmod), + SYM(cosf), + SYM(fcntl), + SYM(open), + SYM(access), + SYM(environ), + SYM(tanf), + SYM(utime), + SYM(asinf), + SYM(lseek64), + SYM(umask), + SYM(acosf), + SYM(write), + SYM(atanf), + SYM(read), + SYM(sinhf), + SYM(coshf), + SYM(tanhf), + SYM(asinhf), + SYM(acoshf), + SYM(atanhf), + SYM(powf), + SYM(exp), + SYM(log1p), + SYM(expm1), + SYM(log), + SYM(sin), + SYM(cos), + SYM(tan), + SYM(asin), + SYM(acos), + SYM(atan), + SYM(sinh), + SYM(cosh), + SYM(tanh), + SYM(asinh), + SYM(acosh), + SYM(atanh), + SYM(pow), + SYM(__aeabi_memclr8), + SYM(__aeabi_memcpy8), + SYM(__aeabi_memmove4), + SYM(__aeabi_memset), + SYM(__aeabi_memset8), + SYM(clock_gettime), + SYM(fopen), + SYM(fwrite), + SYM(getauxval), + SYM(gmtime_r), + SYM(memchr), + SYM(__memcpy_chk), + SYM(memset), + SYM(__memset_chk), + SYM(pthread_rwlock_init), + SYM(readdir), + SYM(socket), + SYM(__stack_chk_fail), + SYM(__stack_chk_guard), + SYM(strchr), + SYM(__strchr_chk), + SYM(strcpy), + SYM(strdup), + SYM(__strlen_chk), + SYM(strncmp), + SYM(strncpy), + SYM(__strncpy_chk2), + SYM(strrchr), + SYM(strspn), + SYM(strstr), + SYM(strtoul), + SYM(sysconf), + SYM(time), + SYM(tzset), + SYM(uname), + SYM(vfprintf), + SYM(__write_chk), + SYM(__aeabi_d2lz), + SYM(__aeabi_l2d), + SYM(atexit), + SYM(atoi), + SYM(clock_getres), + SYM(fclose), + SYM(fileno), + SYM(fread), + SYM(fseek), + SYM(getentropy), + SYM(getnameinfo), + SYM(getsockopt), + SYM(localtime_r), + SYM(__memmove_chk), + SYM(mmap), + SYM(opendir), + SYM(pthread_rwlock_rdlock), + SYM(__read_chk), + SYM(setsockopt), + SYM(sscanf), + SYM(strcspn), + SYM(strtok), + SYM(strtol), + SYM(usleep), + SYM(__vsprintf_chk), + SYM(__aeabi_d2ulz), + SYM(bind), + SYM(closedir), + SYM(connect), + SYM(ferror), + SYM(fsync), + SYM(ftell), + SYM(gai_strerror), + SYM(gethostbyname), + SYM(gettimeofday), + SYM(mprotect), + SYM(pthread_rwlock_wrlock), + SYM(shutdown), + SYM(stdin), + SYM(syscall), + SYM(accept), + SYM(__aeabi_ul2d), + SYM(clock), + SYM(fgets), + SYM(fputs), + SYM(freeaddrinfo), + SYM(listen), + SYM(mlock), + SYM(__open_2), + SYM(pthread_rwlock_unlock), + SYM(sleep), + SYM(strcat), + SYM(feof), + SYM(fflush), + SYM(getaddrinfo), + SYM(getsockname), + SYM(madvise), + SYM(perror), + SYM(pthread_rwlock_destroy), + SYM(strftime), + SYM(__cmsg_nxthdr), + SYM(__FD_SET_chk), + SYM(fputc), + SYM(munmap), + SYM(pthread_once), + SYM(sigaction), + SYM(pthread_key_create), + SYM(select), + SYM(sendmsg), + SYM(signal), + SYM(stdout), + SYM(pthread_getspecific), + SYM(rename), + SYM(munlock), + SYM(pthread_setspecific), + SYM(pthread_key_delete), + SYM(pthread_mutexattr_init), + SYM(pthread_mutexattr_settype), + SYM(pthread_self), + SYM(pthread_equal), + SYM(pthread_mutex_init), + SYM(pthread_mutexattr_destroy), + SYM(pthread_mutex_destroy), + SYM(pthread_mutex_lock), + SYM(pthread_mutex_trylock), + SYM(pthread_mutex_unlock), + SYM(utimes), + SYM(pthread_join), + SYM(__aeabi_l2f), + SYM(pthread_create), + SYM(localtime), + SYM(getcwd), + SYM(fchmod), + SYM(mkdir), + SYM(rmdir), + SYM(fchown), + SYM(geteuid), + SYM(mmap64), + SYM(mremap), + SYM(readlink), + SYM(times), + SYM(strerror_r), + SYM(flock), + SYM(puts), + SYM(getrusage), + { 0, 0, STRENGTH_NORMAL, 1 } /* sentinel */ +}; + +RtsSymbolVal* iserv_syms() { + return my_iserv_syms; +} \ No newline at end of file diff --git a/cbits/symbols.x86_64-musl.c b/cbits/symbols.x86_64-musl.c new file mode 100644 index 0000000..2a8bca8 --- /dev/null +++ b/cbits/symbols.x86_64-musl.c @@ -0,0 +1,318 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// #include +// #include // this includes too many overloaded items. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// fnctl stubs, see above +extern void open(void); +extern void openat(void); +extern void creat(void); +extern void eventfd(void); +extern void eventfd_write(void); + +extern void futimes(void); +extern void lutimes(void); +extern void statx(void); + +extern void __stack_chk_fail(void); +extern void __vsprintf_chk(void); +extern void __open_2(void); +extern void __memcpy_chk(void); +extern void __memset_chk(void); +extern void __memmove_chk(void); +// GCC stuff +extern void __addtf3(void); +extern void __divtf3(void); +extern void __extenddftf2(void); +extern void __fixtfsi(void); +extern void __floatditf(void); +extern void __floatsitf(void); +extern void __getf2(void); +extern void __gttf2(void); +extern void __lttf2(void); +extern void __multf3(void); +extern void __subtf3(void); +extern void __trunctfdf2(void); + +#define MISSING_FUN(f) void (f)(void) { printf("Unknown call to `%s'\n", #f); exit(1); } + +MISSING_FUN(c_format_unix_time) +MISSING_FUN(c_format_unix_time_gmt) +MISSING_FUN(c_parse_unix_time) +MISSING_FUN(c_parse_unix_time_gmt) + +typedef void SymbolAddr; +typedef char SymbolName; + +typedef enum _SymStrength { + STRENGTH_NORMAL, + STRENGTH_WEAK, + STRENGTH_STRONG, +} SymStrength; + +typedef enum _SymType { + SYM_TYPE_CODE = 1 << 0, /* the symbol is a function and can be relocated via a jump island */ + SYM_TYPE_DATA = 1 << 1, /* the symbol is data */ + SYM_TYPE_INDIRECT_DATA = 1 << 2, /* see Note [_iob_func symbol] */ + 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. */ +} SymType; + +typedef struct _RtsSymbolVal { + const SymbolName* lbl; + SymbolAddr* addr; + SymStrength strength; + SymType type; +} RtsSymbolVal; + +#define SYM(x) { #x, (void*)(&x), STRENGTH_NORMAL, 1 } +typedef mode_t (*umask_func_ptr_t)(mode_t); + +RtsSymbolVal my_iserv_syms[] = { + // arpa/inet.h + SYM(htons), + SYM(ntohs), + SYM(htonl), + SYM(ntohl), + // sys/random.h + SYM(getentropy), + SYM(getrandom), + // sys/auxv.h + SYM(getauxval), + // sys/mman.h + SYM(madvise),SYM(mlock),SYM(mmap),SYM(mprotect),SYM(munmap), + SYM(mremap), + SYM(munlock), + // select.h + SYM(__FD_SET_chk), + // sys/socket + SYM(accept),SYM(bind),SYM(connect),SYM(getsockopt),SYM(listen), + SYM(setsockopt),SYM(socket),SYM(getsockname),SYM(select), + SYM(getpeername),SYM(__cmsg_nxthdr),SYM(recv),SYM(recvfrom), + SYM(recvmsg),SYM(send),SYM(sendmsg),SYM(sendto),SYM(writev), + SYM(accept4), + // pthread.h + SYM(pthread_equal),SYM(pthread_getspecific),SYM(pthread_key_create), + SYM(pthread_key_delete),SYM(pthread_once),SYM(pthread_rwlock_destroy), + SYM(pthread_rwlock_init),SYM(pthread_rwlock_rdlock),SYM(pthread_rwlock_unlock), + SYM(pthread_rwlock_wrlock),SYM(pthread_self),SYM(pthread_setspecific), + SYM(pthread_create),SYM(pthread_join),SYM(pthread_mutex_destroy), + SYM(pthread_mutex_init),SYM(pthread_mutex_lock),SYM(pthread_mutex_trylock), + SYM(pthread_mutex_unlock),SYM(pthread_mutexattr_destroy), + SYM(pthread_mutexattr_init),SYM(pthread_mutexattr_settype), + // chk.h + SYM(__read_chk),SYM(__write_chk), + // netdb.h + SYM(freeaddrinfo),SYM(gai_strerror),SYM(getaddrinfo),SYM(getnameinfo), + SYM(gethostbyname), + // dirent.h + SYM(readdir_r),SYM(readdir), + SYM(opendir),SYM(closedir), + // time.h + SYM(clock),SYM(gmtime_r), + // sys/time.h + SYM(gettimeofday),SYM(clock_getres),SYM(clock_gettime),SYM(localtime_r),SYM(tzset), + // unistd.h + SYM(readlink), + SYM(rename), + SYM(rmdir), + SYM(chown), + SYM(realpath), + SYM(fchdir), + SYM(fdopendir), + SYM(rewinddir), + SYM(futimens),SYM(futimes),SYM(lutimes), + SYM(mknod), + SYM(lchown), + SYM(symlink), + SYM(endgrent),SYM(endpwent), + SYM(pathconf), + SYM(truncate), + SYM(utimensat), + SYM(statx), + SYM(seekdir), + SYM(telldir), + SYM(clearenv), + SYM(chdir), + SYM(sleep), + SYM(stdout), + SYM(strftime), + SYM(utimes), + SYM(setenv), + SYM(fpathconf), + SYM(exit), + SYM(environ), + SYM(ftruncate), + SYM(getenv), + SYM(putenv), + SYM(unsetenv), + SYM(read), + SYM(write), + SYM(isatty), + SYM(link), + SYM(pipe), + SYM(unlink), + SYM(execv),SYM(execve),SYM(execvp),SYM(execvpe), + SYM(syscall),SYM(sysconf), + // errno.h + SYM(__errno), + // math.h + SYM(sinhf), SYM(sinh), SYM(sinf), SYM(sin), + SYM(coshf), SYM(cosh), SYM(cosf), SYM(cos), + SYM(atanhf), SYM(atanh), SYM(atanf), SYM(atan), + SYM(asinhf), SYM(asinh), SYM(asinf), SYM(asin), + SYM(acoshf), SYM(acosh), SYM(acosf), SYM(acos), + SYM(log1pf), SYM(log1p), SYM(logf), SYM(log), + SYM(expm1f), SYM(expm1), + SYM(expf), SYM(exp), + SYM(ldexp), + SYM(powf), SYM(pow), + SYM(sqrtf), SYM(sqrt), + SYM(tanhf), SYM(tanh), SYM(tanf), SYM(tan), + // assert.h + SYM(__assert2), + // signal.h + SYM(signal),SYM(sigaction), + SYM(raise), SYM(sigaddset), SYM(sigemptyset), SYM(sigprocmask), + // sys/eventfd.h + SYM(eventfd), SYM(eventfd_write), + // sys/stat.h + SYM(fstat), + SYM(lstat), + SYM(stat), + SYM(chmod), + SYM(mkfifo), + // SYM(umask), + { "umask", (umask_func_ptr_t)(&umask), STRENGTH_NORMAL, 1 }, + // sys/wait.h + SYM(waitpid), + // sym/epoll.h + SYM(epoll_create), SYM(epoll_ctl), SYM(epoll_wait), + // poll.h + SYM(poll), + // fcntl.h + SYM(open), SYM(creat), SYM(fcntl), SYM(ioctl), + SYM(openat),SYM(__open_2), + // string.h + SYM(strerror), + SYM(strcmp), + SYM(memchr),SYM(strcpy),SYM(strchr),SYM(strncpy),SYM(strrchr), + SYM(strcat),SYM(strncmp),SYM(strdup), + SYM(strtoul),SYM(strspn),SYM(strtol),SYM(strstr),SYM(strcspn), + SYM(__strncpy_chk2),SYM(__memcpy_chk), + // ctype.h + SYM(__ctype_get_mb_cur_max), + // wchar.h + SYM(mbrtowc), SYM(wcrtomb), + // stdlib.h + SYM(qsort), + // unistd.h + SYM(access), SYM(close), SYM(dup), SYM(dup2), SYM(fork), SYM(getpid), + SYM(lseek), + // utime.h + SYM(utime),SYM(time), + // ... + SYM(fileno), + SYM(__vsprintf_chk), + SYM(__strlen_chk), + SYM(__strchr_chk), + SYM(__memset_chk), + SYM(__memmove_chk), + SYM(__stack_chk_fail), + SYM(memmove), + SYM(memcmp), + SYM(memcpy), + SYM(memset), + SYM(stderr), + SYM(realloc), + SYM(calloc), + SYM(malloc), + SYM(free), + SYM(fprintf), + SYM(vfprintf), + SYM(fopen), SYM(fclose), + SYM(getegid),SYM(getgid), + SYM(getpwent), + SYM(getgrent), + SYM(getgroups), + SYM(getlogin), + SYM(getuid), + SYM(getgrgid_r),SYM(getgrnam_r),SYM(getpwnam_r),SYM(getpwuid_r), + SYM(setegid),SYM(seteuid),SYM(setgid),SYM(setgrent),SYM(setgroups), + SYM(setpwent),SYM(setuid), + SYM(fread), + SYM(abort), + SYM(strlen), + SYM(fwrite), + SYM(feof), + SYM(ferror), + SYM(fflush), + SYM(fgets),SYM(fputc),SYM(fputs), + SYM(fseek),SYM(ftell), + SYM(sscanf), + SYM(shutdown), + SYM(atoi), + SYM(stdin), + SYM(atexit), + SYM(usleep), + SYM(fchmod), + SYM(fchown), + SYM(fsync), + SYM(getcwd), + SYM(geteuid), + SYM(localtime), + SYM(lseek64), + SYM(mkdir), + SYM(mktime), + SYM(fdopen), + SYM(c_format_unix_time), + SYM(c_format_unix_time_gmt), + SYM(c_parse_unix_time), + SYM(c_parse_unix_time_gmt), + SYM(__addtf3), + SYM(__divtf3), + SYM(__extenddftf2), + SYM(__fixtfsi), + SYM(__floatditf), + SYM(__floatsitf), + SYM(__getf2), + SYM(__gttf2), + SYM(__lttf2), + SYM(__multf3), + SYM(__subtf3), + SYM(__trunctfdf2), + { 0, 0, STRENGTH_NORMAL, 1 } /* sentinel */ +}; + +RtsSymbolVal* iserv_syms() { + return my_iserv_syms; +} \ No newline at end of file diff --git a/iserv-proxy.cabal b/iserv-proxy.cabal index 5f1449a..24dd4e7 100644 --- a/iserv-proxy.cabal +++ b/iserv-proxy.cabal @@ -106,9 +106,20 @@ Executable iserv-proxy-interpreter -- We need to pass -fkeep-cafs to ensure that the interpreter retains CAFs -- Iserv and GHC do something similar. ghc-options: -fkeep-cafs + -- no idea how to check for musl :-/ - if os(linux) && arch(aarch64) - c-sources: cbits/symbols.aarch64-musl.c + -- we only build a linux iserv-proxy for musl builds + if os(linux) + if arch(aarch64) + c-sources: cbits/symbols.aarch64-musl.c + if arch(x86_64) + c-sources: cbits/symbols.x86_64-musl.c + + if os(android) + if arch(aarch64) + c-sources: cbits/symbols.aarch64-android.c + if arch(arm) + c-sources: cbits/symbols.armv7a-android.c Build-Depends: base >= 4 && < 5, iserv-proxy From 3890af9b0881dd63cbae805cdbf4f0c610e02085 Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Tue, 11 Feb 2025 14:38:25 +1300 Subject: [PATCH 21/57] Add i386 musl --- cbits/symbols.i386-musl.c | 318 ++++++++++++++++++++++++++++++++++++++ iserv-proxy.cabal | 2 + 2 files changed, 320 insertions(+) create mode 100644 cbits/symbols.i386-musl.c diff --git a/cbits/symbols.i386-musl.c b/cbits/symbols.i386-musl.c new file mode 100644 index 0000000..2a8bca8 --- /dev/null +++ b/cbits/symbols.i386-musl.c @@ -0,0 +1,318 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// #include +// #include // this includes too many overloaded items. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// fnctl stubs, see above +extern void open(void); +extern void openat(void); +extern void creat(void); +extern void eventfd(void); +extern void eventfd_write(void); + +extern void futimes(void); +extern void lutimes(void); +extern void statx(void); + +extern void __stack_chk_fail(void); +extern void __vsprintf_chk(void); +extern void __open_2(void); +extern void __memcpy_chk(void); +extern void __memset_chk(void); +extern void __memmove_chk(void); +// GCC stuff +extern void __addtf3(void); +extern void __divtf3(void); +extern void __extenddftf2(void); +extern void __fixtfsi(void); +extern void __floatditf(void); +extern void __floatsitf(void); +extern void __getf2(void); +extern void __gttf2(void); +extern void __lttf2(void); +extern void __multf3(void); +extern void __subtf3(void); +extern void __trunctfdf2(void); + +#define MISSING_FUN(f) void (f)(void) { printf("Unknown call to `%s'\n", #f); exit(1); } + +MISSING_FUN(c_format_unix_time) +MISSING_FUN(c_format_unix_time_gmt) +MISSING_FUN(c_parse_unix_time) +MISSING_FUN(c_parse_unix_time_gmt) + +typedef void SymbolAddr; +typedef char SymbolName; + +typedef enum _SymStrength { + STRENGTH_NORMAL, + STRENGTH_WEAK, + STRENGTH_STRONG, +} SymStrength; + +typedef enum _SymType { + SYM_TYPE_CODE = 1 << 0, /* the symbol is a function and can be relocated via a jump island */ + SYM_TYPE_DATA = 1 << 1, /* the symbol is data */ + SYM_TYPE_INDIRECT_DATA = 1 << 2, /* see Note [_iob_func symbol] */ + 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. */ +} SymType; + +typedef struct _RtsSymbolVal { + const SymbolName* lbl; + SymbolAddr* addr; + SymStrength strength; + SymType type; +} RtsSymbolVal; + +#define SYM(x) { #x, (void*)(&x), STRENGTH_NORMAL, 1 } +typedef mode_t (*umask_func_ptr_t)(mode_t); + +RtsSymbolVal my_iserv_syms[] = { + // arpa/inet.h + SYM(htons), + SYM(ntohs), + SYM(htonl), + SYM(ntohl), + // sys/random.h + SYM(getentropy), + SYM(getrandom), + // sys/auxv.h + SYM(getauxval), + // sys/mman.h + SYM(madvise),SYM(mlock),SYM(mmap),SYM(mprotect),SYM(munmap), + SYM(mremap), + SYM(munlock), + // select.h + SYM(__FD_SET_chk), + // sys/socket + SYM(accept),SYM(bind),SYM(connect),SYM(getsockopt),SYM(listen), + SYM(setsockopt),SYM(socket),SYM(getsockname),SYM(select), + SYM(getpeername),SYM(__cmsg_nxthdr),SYM(recv),SYM(recvfrom), + SYM(recvmsg),SYM(send),SYM(sendmsg),SYM(sendto),SYM(writev), + SYM(accept4), + // pthread.h + SYM(pthread_equal),SYM(pthread_getspecific),SYM(pthread_key_create), + SYM(pthread_key_delete),SYM(pthread_once),SYM(pthread_rwlock_destroy), + SYM(pthread_rwlock_init),SYM(pthread_rwlock_rdlock),SYM(pthread_rwlock_unlock), + SYM(pthread_rwlock_wrlock),SYM(pthread_self),SYM(pthread_setspecific), + SYM(pthread_create),SYM(pthread_join),SYM(pthread_mutex_destroy), + SYM(pthread_mutex_init),SYM(pthread_mutex_lock),SYM(pthread_mutex_trylock), + SYM(pthread_mutex_unlock),SYM(pthread_mutexattr_destroy), + SYM(pthread_mutexattr_init),SYM(pthread_mutexattr_settype), + // chk.h + SYM(__read_chk),SYM(__write_chk), + // netdb.h + SYM(freeaddrinfo),SYM(gai_strerror),SYM(getaddrinfo),SYM(getnameinfo), + SYM(gethostbyname), + // dirent.h + SYM(readdir_r),SYM(readdir), + SYM(opendir),SYM(closedir), + // time.h + SYM(clock),SYM(gmtime_r), + // sys/time.h + SYM(gettimeofday),SYM(clock_getres),SYM(clock_gettime),SYM(localtime_r),SYM(tzset), + // unistd.h + SYM(readlink), + SYM(rename), + SYM(rmdir), + SYM(chown), + SYM(realpath), + SYM(fchdir), + SYM(fdopendir), + SYM(rewinddir), + SYM(futimens),SYM(futimes),SYM(lutimes), + SYM(mknod), + SYM(lchown), + SYM(symlink), + SYM(endgrent),SYM(endpwent), + SYM(pathconf), + SYM(truncate), + SYM(utimensat), + SYM(statx), + SYM(seekdir), + SYM(telldir), + SYM(clearenv), + SYM(chdir), + SYM(sleep), + SYM(stdout), + SYM(strftime), + SYM(utimes), + SYM(setenv), + SYM(fpathconf), + SYM(exit), + SYM(environ), + SYM(ftruncate), + SYM(getenv), + SYM(putenv), + SYM(unsetenv), + SYM(read), + SYM(write), + SYM(isatty), + SYM(link), + SYM(pipe), + SYM(unlink), + SYM(execv),SYM(execve),SYM(execvp),SYM(execvpe), + SYM(syscall),SYM(sysconf), + // errno.h + SYM(__errno), + // math.h + SYM(sinhf), SYM(sinh), SYM(sinf), SYM(sin), + SYM(coshf), SYM(cosh), SYM(cosf), SYM(cos), + SYM(atanhf), SYM(atanh), SYM(atanf), SYM(atan), + SYM(asinhf), SYM(asinh), SYM(asinf), SYM(asin), + SYM(acoshf), SYM(acosh), SYM(acosf), SYM(acos), + SYM(log1pf), SYM(log1p), SYM(logf), SYM(log), + SYM(expm1f), SYM(expm1), + SYM(expf), SYM(exp), + SYM(ldexp), + SYM(powf), SYM(pow), + SYM(sqrtf), SYM(sqrt), + SYM(tanhf), SYM(tanh), SYM(tanf), SYM(tan), + // assert.h + SYM(__assert2), + // signal.h + SYM(signal),SYM(sigaction), + SYM(raise), SYM(sigaddset), SYM(sigemptyset), SYM(sigprocmask), + // sys/eventfd.h + SYM(eventfd), SYM(eventfd_write), + // sys/stat.h + SYM(fstat), + SYM(lstat), + SYM(stat), + SYM(chmod), + SYM(mkfifo), + // SYM(umask), + { "umask", (umask_func_ptr_t)(&umask), STRENGTH_NORMAL, 1 }, + // sys/wait.h + SYM(waitpid), + // sym/epoll.h + SYM(epoll_create), SYM(epoll_ctl), SYM(epoll_wait), + // poll.h + SYM(poll), + // fcntl.h + SYM(open), SYM(creat), SYM(fcntl), SYM(ioctl), + SYM(openat),SYM(__open_2), + // string.h + SYM(strerror), + SYM(strcmp), + SYM(memchr),SYM(strcpy),SYM(strchr),SYM(strncpy),SYM(strrchr), + SYM(strcat),SYM(strncmp),SYM(strdup), + SYM(strtoul),SYM(strspn),SYM(strtol),SYM(strstr),SYM(strcspn), + SYM(__strncpy_chk2),SYM(__memcpy_chk), + // ctype.h + SYM(__ctype_get_mb_cur_max), + // wchar.h + SYM(mbrtowc), SYM(wcrtomb), + // stdlib.h + SYM(qsort), + // unistd.h + SYM(access), SYM(close), SYM(dup), SYM(dup2), SYM(fork), SYM(getpid), + SYM(lseek), + // utime.h + SYM(utime),SYM(time), + // ... + SYM(fileno), + SYM(__vsprintf_chk), + SYM(__strlen_chk), + SYM(__strchr_chk), + SYM(__memset_chk), + SYM(__memmove_chk), + SYM(__stack_chk_fail), + SYM(memmove), + SYM(memcmp), + SYM(memcpy), + SYM(memset), + SYM(stderr), + SYM(realloc), + SYM(calloc), + SYM(malloc), + SYM(free), + SYM(fprintf), + SYM(vfprintf), + SYM(fopen), SYM(fclose), + SYM(getegid),SYM(getgid), + SYM(getpwent), + SYM(getgrent), + SYM(getgroups), + SYM(getlogin), + SYM(getuid), + SYM(getgrgid_r),SYM(getgrnam_r),SYM(getpwnam_r),SYM(getpwuid_r), + SYM(setegid),SYM(seteuid),SYM(setgid),SYM(setgrent),SYM(setgroups), + SYM(setpwent),SYM(setuid), + SYM(fread), + SYM(abort), + SYM(strlen), + SYM(fwrite), + SYM(feof), + SYM(ferror), + SYM(fflush), + SYM(fgets),SYM(fputc),SYM(fputs), + SYM(fseek),SYM(ftell), + SYM(sscanf), + SYM(shutdown), + SYM(atoi), + SYM(stdin), + SYM(atexit), + SYM(usleep), + SYM(fchmod), + SYM(fchown), + SYM(fsync), + SYM(getcwd), + SYM(geteuid), + SYM(localtime), + SYM(lseek64), + SYM(mkdir), + SYM(mktime), + SYM(fdopen), + SYM(c_format_unix_time), + SYM(c_format_unix_time_gmt), + SYM(c_parse_unix_time), + SYM(c_parse_unix_time_gmt), + SYM(__addtf3), + SYM(__divtf3), + SYM(__extenddftf2), + SYM(__fixtfsi), + SYM(__floatditf), + SYM(__floatsitf), + SYM(__getf2), + SYM(__gttf2), + SYM(__lttf2), + SYM(__multf3), + SYM(__subtf3), + SYM(__trunctfdf2), + { 0, 0, STRENGTH_NORMAL, 1 } /* sentinel */ +}; + +RtsSymbolVal* iserv_syms() { + return my_iserv_syms; +} \ No newline at end of file diff --git a/iserv-proxy.cabal b/iserv-proxy.cabal index 24dd4e7..3850e89 100644 --- a/iserv-proxy.cabal +++ b/iserv-proxy.cabal @@ -114,6 +114,8 @@ Executable iserv-proxy-interpreter c-sources: cbits/symbols.aarch64-musl.c if arch(x86_64) c-sources: cbits/symbols.x86_64-musl.c + if arch(i386) + c-sources: cbits/symbols.i386-musl.c if os(android) if arch(aarch64) From 756f4552822b70e077f7f7121f4439db250588a0 Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Tue, 11 Feb 2025 16:21:33 +1300 Subject: [PATCH 22/57] Update musl32 sysmbols --- cbits/symbols.i386-musl.c | 49 +++++++++++---------------------------- 1 file changed, 13 insertions(+), 36 deletions(-) diff --git a/cbits/symbols.i386-musl.c b/cbits/symbols.i386-musl.c index 2a8bca8..455e60e 100644 --- a/cbits/symbols.i386-musl.c +++ b/cbits/symbols.i386-musl.c @@ -32,22 +32,12 @@ #include // fnctl stubs, see above -extern void open(void); -extern void openat(void); -extern void creat(void); extern void eventfd(void); extern void eventfd_write(void); -extern void futimes(void); -extern void lutimes(void); extern void statx(void); extern void __stack_chk_fail(void); -extern void __vsprintf_chk(void); -extern void __open_2(void); -extern void __memcpy_chk(void); -extern void __memset_chk(void); -extern void __memmove_chk(void); // GCC stuff extern void __addtf3(void); extern void __divtf3(void); @@ -62,6 +52,9 @@ extern void __multf3(void); extern void __subtf3(void); extern void __trunctfdf2(void); +extern void __aio_close(void); +extern void __stack_chk_fail_local(void); + #define MISSING_FUN(f) void (f)(void) { printf("Unknown call to `%s'\n", #f); exit(1); } MISSING_FUN(c_format_unix_time) @@ -110,14 +103,11 @@ RtsSymbolVal my_iserv_syms[] = { SYM(getauxval), // sys/mman.h SYM(madvise),SYM(mlock),SYM(mmap),SYM(mprotect),SYM(munmap), - SYM(mremap), SYM(munlock), - // select.h - SYM(__FD_SET_chk), // sys/socket SYM(accept),SYM(bind),SYM(connect),SYM(getsockopt),SYM(listen), SYM(setsockopt),SYM(socket),SYM(getsockname),SYM(select), - SYM(getpeername),SYM(__cmsg_nxthdr),SYM(recv),SYM(recvfrom), + SYM(getpeername),SYM(recv),SYM(recvfrom), SYM(recvmsg),SYM(send),SYM(sendmsg),SYM(sendto),SYM(writev), SYM(accept4), // pthread.h @@ -129,8 +119,6 @@ RtsSymbolVal my_iserv_syms[] = { SYM(pthread_mutex_init),SYM(pthread_mutex_lock),SYM(pthread_mutex_trylock), SYM(pthread_mutex_unlock),SYM(pthread_mutexattr_destroy), SYM(pthread_mutexattr_init),SYM(pthread_mutexattr_settype), - // chk.h - SYM(__read_chk),SYM(__write_chk), // netdb.h SYM(freeaddrinfo),SYM(gai_strerror),SYM(getaddrinfo),SYM(getnameinfo), SYM(gethostbyname), @@ -150,7 +138,7 @@ RtsSymbolVal my_iserv_syms[] = { SYM(fchdir), SYM(fdopendir), SYM(rewinddir), - SYM(futimens),SYM(futimes),SYM(lutimes), + SYM(futimens), SYM(mknod), SYM(lchown), SYM(symlink), @@ -164,13 +152,11 @@ RtsSymbolVal my_iserv_syms[] = { SYM(clearenv), SYM(chdir), SYM(sleep), - SYM(stdout), SYM(strftime), SYM(utimes), SYM(setenv), SYM(fpathconf), SYM(exit), - SYM(environ), SYM(ftruncate), SYM(getenv), SYM(putenv), @@ -183,8 +169,6 @@ RtsSymbolVal my_iserv_syms[] = { SYM(unlink), SYM(execv),SYM(execve),SYM(execvp),SYM(execvpe), SYM(syscall),SYM(sysconf), - // errno.h - SYM(__errno), // math.h SYM(sinhf), SYM(sinh), SYM(sinf), SYM(sin), SYM(coshf), SYM(cosh), SYM(cosf), SYM(cos), @@ -194,12 +178,9 @@ RtsSymbolVal my_iserv_syms[] = { SYM(log1pf), SYM(log1p), SYM(logf), SYM(log), SYM(expm1f), SYM(expm1), SYM(expf), SYM(exp), - SYM(ldexp), SYM(powf), SYM(pow), SYM(sqrtf), SYM(sqrt), SYM(tanhf), SYM(tanh), SYM(tanf), SYM(tan), - // assert.h - SYM(__assert2), // signal.h SYM(signal),SYM(sigaction), SYM(raise), SYM(sigaddset), SYM(sigemptyset), SYM(sigprocmask), @@ -220,15 +201,13 @@ RtsSymbolVal my_iserv_syms[] = { // poll.h SYM(poll), // fcntl.h - SYM(open), SYM(creat), SYM(fcntl), SYM(ioctl), - SYM(openat),SYM(__open_2), + SYM(fcntl), // string.h SYM(strerror), SYM(strcmp), SYM(memchr),SYM(strcpy),SYM(strchr),SYM(strncpy),SYM(strrchr), SYM(strcat),SYM(strncmp),SYM(strdup), SYM(strtoul),SYM(strspn),SYM(strtol),SYM(strstr),SYM(strcspn), - SYM(__strncpy_chk2),SYM(__memcpy_chk), // ctype.h SYM(__ctype_get_mb_cur_max), // wchar.h @@ -242,17 +221,11 @@ RtsSymbolVal my_iserv_syms[] = { SYM(utime),SYM(time), // ... SYM(fileno), - SYM(__vsprintf_chk), - SYM(__strlen_chk), - SYM(__strchr_chk), - SYM(__memset_chk), - SYM(__memmove_chk), SYM(__stack_chk_fail), SYM(memmove), SYM(memcmp), SYM(memcpy), SYM(memset), - SYM(stderr), SYM(realloc), SYM(calloc), SYM(malloc), @@ -281,7 +254,6 @@ RtsSymbolVal my_iserv_syms[] = { SYM(sscanf), SYM(shutdown), SYM(atoi), - SYM(stdin), SYM(atexit), SYM(usleep), SYM(fchmod), @@ -290,7 +262,6 @@ RtsSymbolVal my_iserv_syms[] = { SYM(getcwd), SYM(geteuid), SYM(localtime), - SYM(lseek64), SYM(mkdir), SYM(mktime), SYM(fdopen), @@ -310,9 +281,15 @@ RtsSymbolVal my_iserv_syms[] = { SYM(__multf3), SYM(__subtf3), SYM(__trunctfdf2), + SYM(scalbn), + SYM(fma), + SYM(fmaf), + SYM(puts), + SYM(__aio_close), + SYM(__stack_chk_fail_local), { 0, 0, STRENGTH_NORMAL, 1 } /* sentinel */ }; RtsSymbolVal* iserv_syms() { return my_iserv_syms; -} \ No newline at end of file +} From 9095fc6606ab946a6eb49d77b5065aae1d81da1b Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Wed, 12 Feb 2025 10:38:30 +1300 Subject: [PATCH 23/57] Fix OS detection --- cbits/symbols.aarch64-android.c | 4 +++- cbits/symbols.aarch64-musl.c | 4 +++- cbits/symbols.armv7a-android.c | 4 +++- iserv-proxy.cabal | 8 +++----- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/cbits/symbols.aarch64-android.c b/cbits/symbols.aarch64-android.c index a73a6fb..ab30774 100644 --- a/cbits/symbols.aarch64-android.c +++ b/cbits/symbols.aarch64-android.c @@ -1,3 +1,4 @@ +#ifdef __ANDROID__ #define BIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD #include #include @@ -324,4 +325,5 @@ RtsSymbolVal my_iserv_syms[] = { RtsSymbolVal* iserv_syms() { return my_iserv_syms; -} \ No newline at end of file +} +#endif diff --git a/cbits/symbols.aarch64-musl.c b/cbits/symbols.aarch64-musl.c index d544d44..e0a5d30 100644 --- a/cbits/symbols.aarch64-musl.c +++ b/cbits/symbols.aarch64-musl.c @@ -1,3 +1,4 @@ +#ifndef __ANDROID__ #define SYM(s) extern void s(void); #include "symbols.aarch64-musl.h" #undef SYM @@ -47,4 +48,5 @@ RtsSymbolVal my_iserv_syms[] = { RtsSymbolVal* iserv_syms() { return my_iserv_syms; -} \ No newline at end of file +} +#endif diff --git a/cbits/symbols.armv7a-android.c b/cbits/symbols.armv7a-android.c index 1bcba1b..617879c 100644 --- a/cbits/symbols.armv7a-android.c +++ b/cbits/symbols.armv7a-android.c @@ -1,3 +1,4 @@ +#ifdef __ANDROID__ #include #include #include @@ -453,4 +454,5 @@ RtsSymbolVal my_iserv_syms[] = { RtsSymbolVal* iserv_syms() { return my_iserv_syms; -} \ No newline at end of file +} +#endif diff --git a/iserv-proxy.cabal b/iserv-proxy.cabal index 3850e89..4f651e1 100644 --- a/iserv-proxy.cabal +++ b/iserv-proxy.cabal @@ -109,17 +109,15 @@ Executable iserv-proxy-interpreter -- no idea how to check for musl :-/ -- we only build a linux iserv-proxy for musl builds - if os(linux) + -- also os(android) is not working (so using `#ifdef __ANDROID__` in the .c files) + if os(linux) || os(android) if arch(aarch64) c-sources: cbits/symbols.aarch64-musl.c + c-sources: cbits/symbols.aarch64-android.c if arch(x86_64) c-sources: cbits/symbols.x86_64-musl.c if arch(i386) c-sources: cbits/symbols.i386-musl.c - - if os(android) - if arch(aarch64) - c-sources: cbits/symbols.aarch64-android.c if arch(arm) c-sources: cbits/symbols.armv7a-android.c From b9711cc1ce1c70de4c5d3483eb3a8193c41e71ee Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Thu, 20 Feb 2025 16:18:07 +1300 Subject: [PATCH 24/57] Fix for armv7a --- cbits/symbols.armv7a-android.c | 3 ++- iserv-proxy.cabal | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cbits/symbols.armv7a-android.c b/cbits/symbols.armv7a-android.c index 617879c..a6d692f 100644 --- a/cbits/symbols.armv7a-android.c +++ b/cbits/symbols.armv7a-android.c @@ -1,4 +1,4 @@ -#ifdef __ANDROID__ +#if defined(__ANDROID__) && defined(__arm__) #include #include #include @@ -449,6 +449,7 @@ RtsSymbolVal my_iserv_syms[] = { SYM(flock), SYM(puts), SYM(getrusage), + SYM(__aeabi_memclr8), { 0, 0, STRENGTH_NORMAL, 1 } /* sentinel */ }; diff --git a/iserv-proxy.cabal b/iserv-proxy.cabal index 4f651e1..b8ef863 100644 --- a/iserv-proxy.cabal +++ b/iserv-proxy.cabal @@ -118,8 +118,7 @@ Executable iserv-proxy-interpreter c-sources: cbits/symbols.x86_64-musl.c if arch(i386) c-sources: cbits/symbols.i386-musl.c - if arch(arm) - c-sources: cbits/symbols.armv7a-android.c + c-sources: cbits/symbols.armv7a-android.c Build-Depends: base >= 4 && < 5, iserv-proxy From 89ae671b116c2797c485815af7837e71fba96312 Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Mon, 24 Feb 2025 16:44:10 +1300 Subject: [PATCH 25/57] Fix for aarch64-android --- cbits/symbols.aarch64-android.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cbits/symbols.aarch64-android.c b/cbits/symbols.aarch64-android.c index ab30774..8de49f7 100644 --- a/cbits/symbols.aarch64-android.c +++ b/cbits/symbols.aarch64-android.c @@ -32,6 +32,7 @@ #include #include #include +#include // fnctl stubs, see above extern void open(void); @@ -320,6 +321,8 @@ RtsSymbolVal my_iserv_syms[] = { SYM(__subtf3), SYM(__trunctfdf2), SYM(getrusage), + SYM(tcsetattr), + SYM(tcgetattr), { 0, 0, STRENGTH_NORMAL, 1 } /* sentinel */ }; From 531768c4be723e00eddb140ed76f433855d19809 Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Thu, 27 Feb 2025 12:01:09 +1300 Subject: [PATCH 26/57] Fixes for aarch64-android --- cbits/symbols.aarch64-android.c | 136 ++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) diff --git a/cbits/symbols.aarch64-android.c b/cbits/symbols.aarch64-android.c index 8de49f7..71f4aa1 100644 --- a/cbits/symbols.aarch64-android.c +++ b/cbits/symbols.aarch64-android.c @@ -68,12 +68,56 @@ extern void __trunctfdf2(void); extern void flock(void); extern void times(void); +extern void uname(void); +extern void sem_post(void); +extern void __gnu_strerror_r(void); +extern void async_safe_format_buffer(void); +extern void sem_trywait(void); +extern void sem_wait(void); +extern void sem_unlink(void); +extern void sem_close(void); +extern void sem_open(void); +extern void sem_getvalue(void); +extern void dlclose(void); +extern void dlerror(void); +extern void dlsym(void); +extern void dlopen(void); +extern void fallocate(void); +extern void posix_fallocate(void); +extern void __fadvise64(void); +extern void posix_fadvise(void); +extern void async_safe_fatal_no_abort(void); +extern void __vsnprintf_chk(void); +extern void openpty(void); +extern void __getpriority(void); +extern void * _Unwind_Resume; +extern void __emutls_get_address(void); +//extern void __sF(void); +extern void __sflush(void); +extern void __eqtf2(void); +extern void __ldtoa(void); +extern void __vfprintf(void); +//extern void _Unwind_SetGR(void); +//extern void _Unwind_SetIP(void); +//extern void _Unwind_GetLanguageSpecificData(void); +//extern void _Unwind_GetIP(void); +//extern void _Unwind_GetRegionStart(void); +void * __gxx_personality_v0; + #define MISSING_FUN(f) void (f)(void) { printf("Unknown call to `%s'\n", #f); exit(1); } MISSING_FUN(c_format_unix_time) MISSING_FUN(c_format_unix_time_gmt) MISSING_FUN(c_parse_unix_time) MISSING_FUN(c_parse_unix_time_gmt) +MISSING_FUN(abort_message) +//MISSING_FUN(__cxa_unexpected_handler) +MISSING_FUN(__cxa_begin_catch) +MISSING_FUN(_ZSt9terminatev) +//MISSING_FUN(_ZN10__cxxabiv130__aligned_malloc_with_fallbackEm) +//MISSING_FUN(_ZN10__cxxabiv119__getExceptionClassEPK17_Unwind_Exception) +//MISSING_FUN(_ZSt11__terminatePFvvE) +// MISSINF_FUN(__gxx_personality_v0) typedef void SymbolAddr; typedef char SymbolName; @@ -323,6 +367,98 @@ RtsSymbolVal my_iserv_syms[] = { SYM(getrusage), SYM(tcsetattr), SYM(tcgetattr), + SYM(setrlimit), + SYM(getrlimit), + SYM(uname), + SYM(fdatasync), + SYM(nanosleep), + SYM(kill), + SYM(killpg), + SYM(sigpending), + SYM(sigsuspend), + SYM(setitimer), + SYM(alarm), + SYM(sigismember), + SYM(sigfillset), + SYM(sigdelset), + SYM(__gnu_strerror_r), + SYM(async_safe_format_buffer), + SYM(android_get_application_target_sdk_version), + SYM(sem_post), + SYM(sem_trywait), + SYM(sem_wait), + SYM(sem_unlink), + SYM(sem_close), + SYM(sem_open), + SYM(sem_getvalue), + SYM(dlclose), + SYM(dlerror), + SYM(dlsym), + SYM(dlopen), + SYM(fallocate), + SYM(posix_fallocate), + SYM(__fadvise64), + SYM(posix_fadvise), + SYM(async_safe_fatal_no_abort), + SYM(arc4random_buf), + SYM(mkdtemp), + SYM(mkstemps), + SYM(mkstemp), + SYM(__vsnprintf_chk), + SYM(ttyname), + SYM(openpty), + SYM(ptsname), + SYM(ctermid), + SYM(getppid), + SYM(getpgid), + SYM(getpgrp), + SYM(setsid), + SYM(setpgid), + SYM(setpriority), + SYM(__getpriority), + SYM(getpriority), + SYM(tcgetpgrp), + SYM(tcsetpgrp), + SYM(tcflow), + SYM(tcflush), + SYM(tcdrain), + SYM(tcsendbreak), + SYM(cfsetospeed), + SYM(cfgetospeed), + SYM(cfsetispeed), + SYM(cfgetispeed), + SYM(_Unwind_Resume), +// SYM(posix_memalign), + SYM(__emutls_get_address), +// SYM(__sF), + SYM(__sflush), + SYM(__eqtf2), + SYM(__ldtoa), + SYM(__vfprintf), + SYM(vasprintf), + SYM(abort_message), +// SYM(__cxa_unexpected_handler), + SYM(_ZSt9terminatev), +// SYM(_ZN10__cxxabiv130__aligned_malloc_with_fallbackEm), + SYM(__cxa_begin_catch), +// SYM(_Unwind_SetGR), +// SYM(_Unwind_SetIP), +// SYM(_Unwind_GetLanguageSpecificData), +// SYM(_Unwind_GetIP), +// SYM(_Unwind_GetRegionStart), +// SYM(_ZN10__cxxabiv119__getExceptionClassEPK17_Unwind_Exception), +// SYM(_ZSt11__terminatePFvvE), + SYM(__gxx_personality_v0), + SYM(__fwrite_chk), + SYM(timezone), + SYM(sendmsg), + SYM(sendmmsg), + SYM(recvmmsg), + SYM(__strrchr_chk), +// SYM(__loader_add_thread_local_dtor), +// SYM(__cxa_thread_finalize), + SYM(pthread_exit), + SYM(__poll_chk), { 0, 0, STRENGTH_NORMAL, 1 } /* sentinel */ }; From 8cc5d879c5c6bf56cb316199fcdb191dcce24b3d Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Thu, 27 Feb 2025 17:42:17 +1300 Subject: [PATCH 27/57] More fixes for aarch64-android --- cbits/symbols.aarch64-android.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cbits/symbols.aarch64-android.c b/cbits/symbols.aarch64-android.c index 71f4aa1..42bb303 100644 --- a/cbits/symbols.aarch64-android.c +++ b/cbits/symbols.aarch64-android.c @@ -103,6 +103,8 @@ extern void __vfprintf(void); //extern void _Unwind_GetIP(void); //extern void _Unwind_GetRegionStart(void); void * __gxx_personality_v0; +extern void __cxa_guard_acquire(void); +extern void __cxa_guard_release(void); #define MISSING_FUN(f) void (f)(void) { printf("Unknown call to `%s'\n", #f); exit(1); } @@ -459,6 +461,9 @@ RtsSymbolVal my_iserv_syms[] = { // SYM(__cxa_thread_finalize), SYM(pthread_exit), SYM(__poll_chk), + SYM(pthread_cond_wait), + SYM(__cxa_guard_acquire), + SYM(__cxa_guard_release), { 0, 0, STRENGTH_NORMAL, 1 } /* sentinel */ }; From b93fe777d71409bc038478b6055a05d82f4e2e16 Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Thu, 27 Feb 2025 23:14:29 +1300 Subject: [PATCH 28/57] More fixes for aarch64-android --- cbits/symbols.aarch64-android.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cbits/symbols.aarch64-android.c b/cbits/symbols.aarch64-android.c index 42bb303..1eb38dd 100644 --- a/cbits/symbols.aarch64-android.c +++ b/cbits/symbols.aarch64-android.c @@ -464,6 +464,14 @@ RtsSymbolVal my_iserv_syms[] = { SYM(pthread_cond_wait), SYM(__cxa_guard_acquire), SYM(__cxa_guard_release), + SYM(pthread_cond_signal), + SYM(pthread_cond_broadcast), + SYM(pthread_cond_init), + SYM(pthread_cond_timedwait), + SYM(pthread_cond_destroy), + SYM(pthread_attr_init), + SYM(pthread_attr_setdetachstate), + SYM(pthread_attr_destroy), { 0, 0, STRENGTH_NORMAL, 1 } /* sentinel */ }; From d469d00f527f6e63f3c8327f8fe7732b26324684 Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Thu, 27 Feb 2025 23:15:46 +1300 Subject: [PATCH 29/57] armv7a fixes --- cbits/symbols.armv7a-android.c | 100 +++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/cbits/symbols.armv7a-android.c b/cbits/symbols.armv7a-android.c index a6d692f..1990d13 100644 --- a/cbits/symbols.armv7a-android.c +++ b/cbits/symbols.armv7a-android.c @@ -18,6 +18,22 @@ extern void __aeabi_memset4(void); extern void __aeabi_uidiv(void); extern void __aeabi_uidivmod(void); extern void __aeabi_uldivmod(void); +extern void __aeabi_d2f(void); +extern void __aeabi_d2iz(void); +extern void __aeabi_dadd(void); +extern void __aeabi_dcmpeq(void); +extern void __aeabi_dcmpge(void); +extern void __aeabi_dcmpgt(void); +extern void __aeabi_dcmple(void); +extern void __aeabi_dcmplt(void); +extern void __aeabi_ddiv(void); +extern void __aeabi_dmul(void); +extern void __aeabi_f2d(void); +extern void __aeabi_fcmpeq(void); +extern void __aeabi_fcmpge(void); +extern void __aeabi_fcmpgt(void); +extern void __aeabi_fcmple(void); +extern void __aeabi_i2d(void); extern void eventfd_write(void); extern void ioctl(void); @@ -74,6 +90,7 @@ extern void tzset(void); extern void sysconf(void); extern void socket(void); extern void readdir(void); +extern void readdir_r(void); extern void pthread_rwlock_init(void); extern void __memset_chk(void); extern void __memcpy_chk(void); @@ -165,6 +182,32 @@ extern void readlink(void); extern void flock(void); extern void times(void); extern void getrusage(void); +extern void openat(void); +extern void futimes(void); +extern void lutimes(void); +extern void dlclose(void); +extern void dlerror(void); +extern void dlsym(void); +extern void dlopen(void); +extern void execv(void); +extern void execve(void); +extern void execvp(void); +extern void execvpe(void); +extern void setrlimit(void); +extern void sigpending(void); +extern void getrlimit(void); +extern void fallocate(void); +extern void rewinddir(void); +extern void seekdir(void); +extern void telldir(void); +void * __gxx_personality_v0; +void * _Unwind_Resume; +extern void __atomic_load_4(void); +extern void __atomic_store_4(void); +extern void pthread_cond_wait(void); +extern void pthread_cond_broadcast(void); +extern void __cxa_guard_acquire(void); +extern void __cxa_guard_release(void); #define MISSING_FUN(f) void (f)(void) { printf("Unknown call to %s\n", #f); exit(1); } @@ -172,6 +215,8 @@ MISSING_FUN(c_format_unix_time) MISSING_FUN(c_format_unix_time_gmt) MISSING_FUN(c_parse_unix_time) MISSING_FUN(c_parse_unix_time_gmt) +MISSING_FUN(__cxa_begin_catch) +MISSING_FUN(_ZSt9terminatev) typedef void SymbolAddr; typedef char SymbolName; @@ -198,10 +243,17 @@ typedef struct _RtsSymbolVal { SymType type; } RtsSymbolVal; +// work around built-ins being referenced from libraries, and us not being able to &; instead +// wrap the built-in into a function. +//int32_t ___sync_val_compare_and_swap_1(volatile int32_t* ptr, int32_t oldval, int32_t newval) { +// return __sync_val_compare_and_swap_1(ptr, oldval, newval); +//} + #define SYM(x) { #x, (void*)(&x), STRENGTH_NORMAL, 1 } typedef mode_t (*umask_func_ptr_t)(mode_t); RtsSymbolVal my_iserv_syms[] = { + // { "__sync_val_compare_and_swap_1", (void*)(&___sync_val_compare_and_swap_1), STRENGTH_NORMAL, 1 }, SYM(strlen), SYM(__aeabi_idiv), SYM(__aeabi_idivmod), @@ -323,6 +375,7 @@ RtsSymbolVal my_iserv_syms[] = { SYM(__memset_chk), SYM(pthread_rwlock_init), SYM(readdir), + SYM(readdir_r), SYM(socket), SYM(__stack_chk_fail), SYM(__stack_chk_guard), @@ -450,6 +503,53 @@ RtsSymbolVal my_iserv_syms[] = { SYM(puts), SYM(getrusage), SYM(__aeabi_memclr8), + SYM(openat), + SYM(futimes), + SYM(lutimes), + SYM(android_get_application_target_sdk_version), + SYM(dlclose), + SYM(dlerror), + SYM(dlsym), + SYM(dlopen), + SYM(execv), + SYM(execve), + SYM(execvp), + SYM(execvpe), + SYM(setrlimit), + SYM(sigpending), + SYM(getrlimit), + SYM(fallocate), + SYM(rewinddir), + SYM(seekdir), + SYM(telldir), + SYM(__gxx_personality_v0), + SYM(__cxa_begin_catch), + SYM(_ZSt9terminatev), + SYM(_Unwind_Resume), + SYM(__aeabi_d2f), + SYM(__aeabi_d2iz), + SYM(__aeabi_dadd), + SYM(__aeabi_dcmpeq), + SYM(__aeabi_dcmpge), + SYM(__aeabi_dcmpgt), + SYM(__aeabi_dcmple), + SYM(__aeabi_dcmplt), + SYM(__aeabi_ddiv), + SYM(__aeabi_dmul), + SYM(__aeabi_f2d), + SYM(__aeabi_fcmpeq), + SYM(__aeabi_fcmpge), + SYM(__aeabi_fcmpgt), + SYM(__aeabi_fcmple), + SYM(__aeabi_i2d), + SYM(__atomic_load_4), + SYM(__atomic_store_4), + SYM(pthread_cond_wait), + SYM(vasprintf), + SYM(pthread_cond_broadcast), + SYM(__cxa_guard_acquire), + SYM(ceil), + SYM(__cxa_guard_release), { 0, 0, STRENGTH_NORMAL, 1 } /* sentinel */ }; From a438f0cf56eb445da30f2eb28bbebcbc3dbaa9e5 Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Mon, 3 Mar 2025 13:10:41 +1300 Subject: [PATCH 30/57] Add symbols for armv7a android --- cbits/symbols.armv7a-android.c | 139 +++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) diff --git a/cbits/symbols.armv7a-android.c b/cbits/symbols.armv7a-android.c index 1990d13..150b71f 100644 --- a/cbits/symbols.armv7a-android.c +++ b/cbits/symbols.armv7a-android.c @@ -208,6 +208,71 @@ extern void pthread_cond_wait(void); extern void pthread_cond_broadcast(void); extern void __cxa_guard_acquire(void); extern void __cxa_guard_release(void); +extern void getpeername(void); +extern void mktime(void); +extern void __poll_chk(void); +extern void pthread_attr_destroy(void); +extern void pthread_attr_init(void); +extern void pthread_attr_setdetachstate(void); +extern void pthread_cond_destroy(void); +extern void pthread_cond_init(void); +extern void pthread_cond_signal(void); +extern void pthread_cond_timedwait(void); +extern void pthread_exit(void); +extern void recvfrom(void); +extern void recvmmsg(void); +extern void sendmmsg(void); +extern void sendto(void); +extern void timezone(void); +extern void fdatasync(void); +extern void fdopendir(void); +extern void nanosleep(void); +extern void sigsuspend(void); +extern void __assert(void); +extern void _Z21__libc_shared_globalsv(void); +extern void __strcpy_chk(void); +extern void __cxa_thread_finalize(void); +extern void kill(void); +extern void sigismember(void); +extern void __vsnprintf_chk(void); +extern void setitimer(void); +extern void sigfillset(void); +extern void __readlink_chk(void); +extern void __libc_stdio_cleanup(void); +extern void sigdelset(void); +extern void writev(void); +extern void prctl(void); +extern void getuid(void); +extern void __fsetxattr(void); +extern void setxattr(void); +extern void setuid(void); +extern void setresuid(void); +extern void setgid(void); +extern void setresgid(void); +extern void getegid(void); +extern void getgid(void); +extern void setgroups(void); +extern void getgroups(void); +extern void chdir(void); +extern void __fstatfs64(void); +extern void __statfs64(void); +extern void fchownat(void); +extern void symlinkat(void); +extern void truncate64(void); +extern void mknodat(void); +extern void fallocate64(void); +extern void __arm_fadvise64_64(void); +extern void setsid(void); +//extern void _exit(void); +extern void fchdir(void); +extern void utimensat(void); +extern void getppid(void); +extern void getpgid(void); +extern void setpgid(void); +extern void setpriority(void); +extern void __getpriority(void); +extern void __emutls_get_address(void); +extern void __cxa_guard_abort(void); #define MISSING_FUN(f) void (f)(void) { printf("Unknown call to %s\n", #f); exit(1); } @@ -217,6 +282,9 @@ MISSING_FUN(c_parse_unix_time) MISSING_FUN(c_parse_unix_time_gmt) MISSING_FUN(__cxa_begin_catch) MISSING_FUN(_ZSt9terminatev) +MISSING_FUN(__loader_add_thread_local_dtor) +MISSING_FUN(__loader_remove_thread_local_dtor) +MISSING_FUN(__clang_call_terminate) typedef void SymbolAddr; typedef char SymbolName; @@ -550,6 +618,77 @@ RtsSymbolVal my_iserv_syms[] = { SYM(__cxa_guard_acquire), SYM(ceil), SYM(__cxa_guard_release), + SYM(getpeername), + SYM(mktime), + SYM(__poll_chk), + SYM(pthread_attr_destroy), + SYM(pthread_attr_init), + SYM(pthread_attr_setdetachstate), + SYM(pthread_cond_destroy), + SYM(pthread_cond_init), + SYM(pthread_cond_signal), + SYM(pthread_cond_timedwait), + SYM(pthread_exit), + SYM(recvfrom), + SYM(recvmmsg), + SYM(sendmmsg), + SYM(sendto), + SYM(timezone), + SYM(fdatasync), + SYM(fdopendir), + SYM(nanosleep), + SYM(sigsuspend), + SYM(__assert), + SYM(__strlcpy_chk), + SYM(_Z21__libc_shared_globalsv), + SYM(__strcpy_chk), + SYM(getline), + SYM(__loader_add_thread_local_dtor), + SYM(__loader_remove_thread_local_dtor), + SYM(__cxa_thread_finalize), + SYM(kill), + SYM(sigismember), + SYM(__vsnprintf_chk), + SYM(ctermid), + SYM(setitimer), + SYM(sigfillset), + SYM(__readlink_chk), + SYM(__libc_stdio_cleanup), + SYM(sigdelset), + SYM(writev), + SYM(prctl), + SYM(getuid), + SYM(__fsetxattr), + SYM(setxattr), + SYM(setuid), + SYM(setresuid), + SYM(setgid), + SYM(setresgid), + SYM(getegid), + SYM(getgid), + SYM(setgroups), + SYM(getgroups), + SYM(chdir), + SYM(__fstatfs64), + SYM(__statfs64), + SYM(fchownat), + SYM(symlinkat), + SYM(truncate64), + SYM(mknodat), + SYM(fallocate64), + SYM(__arm_fadvise64_64), + SYM(setsid), +// SYM(_exit), + SYM(fchdir), + SYM(utimensat), + SYM(getppid), + SYM(getpgid), + SYM(setpgid), + SYM(setpriority), + SYM(__getpriority), + SYM(__emutls_get_address), + SYM(__cxa_guard_abort), + SYM(__clang_call_terminate), { 0, 0, STRENGTH_NORMAL, 1 } /* sentinel */ }; From 0a34e4604d9f37dd25d8f034a484848a6f5586e7 Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Tue, 4 Mar 2025 10:52:42 +1300 Subject: [PATCH 31/57] Add _exit (needed for GHC 9.10) --- cbits/symbols.armv7a-android.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cbits/symbols.armv7a-android.c b/cbits/symbols.armv7a-android.c index 150b71f..d79892c 100644 --- a/cbits/symbols.armv7a-android.c +++ b/cbits/symbols.armv7a-android.c @@ -263,7 +263,7 @@ extern void mknodat(void); extern void fallocate64(void); extern void __arm_fadvise64_64(void); extern void setsid(void); -//extern void _exit(void); +extern void _exit(int) __attribute__((noreturn)); extern void fchdir(void); extern void utimensat(void); extern void getppid(void); @@ -678,7 +678,7 @@ RtsSymbolVal my_iserv_syms[] = { SYM(fallocate64), SYM(__arm_fadvise64_64), SYM(setsid), -// SYM(_exit), + SYM(_exit), SYM(fchdir), SYM(utimensat), SYM(getppid), From 49648aa3c0fae09959bb62deaa57b0a10c1d40f8 Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Tue, 4 Mar 2025 12:08:46 +1300 Subject: [PATCH 32/57] Disable iserv-proxy unresolved external fix code for now (needs updating) --- cbits/symbols.x86_64-musl.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cbits/symbols.x86_64-musl.c b/cbits/symbols.x86_64-musl.c index 2a8bca8..9d3ee0d 100644 --- a/cbits/symbols.x86_64-musl.c +++ b/cbits/symbols.x86_64-musl.c @@ -1,3 +1,7 @@ +// It looks like this file is probably incorrect. +// TODO enable iserv-proxy for musl64 tests and update this +// file to fix unresolved external issues. +#if 0 #include #include #include @@ -315,4 +319,5 @@ RtsSymbolVal my_iserv_syms[] = { RtsSymbolVal* iserv_syms() { return my_iserv_syms; -} \ No newline at end of file +} +#if 0 From 7ebe2356a005d4237d10df8793a0b61b467bcf32 Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Tue, 4 Mar 2025 18:46:25 +1300 Subject: [PATCH 33/57] Disable iserv-proxy unresolved external fix code for now (needs updating) --- cbits/symbols.x86_64-musl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cbits/symbols.x86_64-musl.c b/cbits/symbols.x86_64-musl.c index 9d3ee0d..388b1ca 100644 --- a/cbits/symbols.x86_64-musl.c +++ b/cbits/symbols.x86_64-musl.c @@ -320,4 +320,4 @@ RtsSymbolVal my_iserv_syms[] = { RtsSymbolVal* iserv_syms() { return my_iserv_syms; } -#if 0 +#endif From 7bd7f5b144f07e6d65297af2ab89743e4472d94d Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Wed, 5 Mar 2025 22:00:20 +1300 Subject: [PATCH 34/57] More symbols needed once libc.a is excluded from loadArchive --- cbits/symbols.armv7a-android.c | 83 ++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/cbits/symbols.armv7a-android.c b/cbits/symbols.armv7a-android.c index d79892c..a32aa02 100644 --- a/cbits/symbols.armv7a-android.c +++ b/cbits/symbols.armv7a-android.c @@ -273,6 +273,44 @@ extern void setpriority(void); extern void __getpriority(void); extern void __emutls_get_address(void); extern void __cxa_guard_abort(void); +extern void killpg(void); +extern void alarm(void); +extern void sem_post(void); +extern void sem_trywait(void); +extern void sem_wait(void); +extern void sem_unlink(void); +extern void sem_close(void); +extern void sem_open(void); +extern void sem_getvalue(void); +extern void getlogin(void); +extern void getgrent(void); +extern void setgrent(void); +extern void endgrent(void); +extern void getpwent(void); +extern void setpwent(void); +extern void endpwent(void); +extern void seteuid(void); +extern void setegid(void); +extern void getpwnam_r(void); +extern void getpwuid_r(void); +extern void getgrnam_r(void); +extern void getgrgid_r(void); +extern void pathconf(void); +extern void chown(void); +extern void lchown(void); +extern void symlink(void); +extern void mknod(void); +extern void posix_fallocate64(void); +extern void posix_fadvise64(void); +extern void ttyname(void); +extern void openpty(void); +extern void fpathconf(void); +extern void futimens(void); +extern void getpgrp(void); +extern void getpriority(void); +extern void nice(void); +extern void tcgetpgrp(void); +extern void tcsetpgrp(void); #define MISSING_FUN(f) void (f)(void) { printf("Unknown call to %s\n", #f); exit(1); } @@ -689,6 +727,51 @@ RtsSymbolVal my_iserv_syms[] = { SYM(__emutls_get_address), SYM(__cxa_guard_abort), SYM(__clang_call_terminate), + SYM(killpg), + SYM(alarm), + SYM(sem_post), + SYM(sem_trywait), + SYM(sem_wait), + SYM(sem_unlink), + SYM(sem_close), + SYM(sem_open), + SYM(sem_getvalue), + SYM(getlogin), + SYM(getgrent), + SYM(setgrent), + SYM(endgrent), + SYM(getpwent), + SYM(setpwent), + SYM(endpwent), + SYM(seteuid), + SYM(setegid), + SYM(getpwnam_r), + SYM(getpwuid_r), + SYM(getgrnam_r), + SYM(getgrgid_r), + SYM(pathconf), + SYM(chown), + SYM(lchown), + SYM(symlink), + SYM(mknod), + SYM(clearenv), + SYM(posix_fallocate64), + SYM(posix_fadvise64), + SYM(mkdtemp), + SYM(mkstemps), + SYM(mkstemp), + SYM(ttyname), + SYM(openpty), + SYM(ptsname), + SYM(fpathconf), + SYM(futimens), + SYM(getpgrp), + SYM(exit), + SYM(getpriority), + SYM(nice), + SYM(tcgetpgrp), + SYM(tcsetpgrp), + SYM(realpath), { 0, 0, STRENGTH_NORMAL, 1 } /* sentinel */ }; From c26dafb7b6549b9ba32aef4021e16abb7f21b8e0 Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Wed, 5 Mar 2025 23:12:04 +1300 Subject: [PATCH 35/57] More symbols needed once libc.a is excluded from loadArchive --- cbits/symbols.aarch64-android.c | 1 + 1 file changed, 1 insertion(+) diff --git a/cbits/symbols.aarch64-android.c b/cbits/symbols.aarch64-android.c index 1eb38dd..04d877f 100644 --- a/cbits/symbols.aarch64-android.c +++ b/cbits/symbols.aarch64-android.c @@ -472,6 +472,7 @@ RtsSymbolVal my_iserv_syms[] = { SYM(pthread_attr_init), SYM(pthread_attr_setdetachstate), SYM(pthread_attr_destroy), + SYM(nice), { 0, 0, STRENGTH_NORMAL, 1 } /* sentinel */ }; From 521964bf4726214e5ce044ebb850e6b2f7dba888 Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Fri, 7 Mar 2025 17:15:34 +1300 Subject: [PATCH 36/57] Add cbits/symbols.x86_64-windows.c --- cbits/symbols.x86_64-windows.c | 39 ++++++++++++++++++++++++++++++++++ iserv-proxy.cabal | 4 ++++ 2 files changed, 43 insertions(+) create mode 100644 cbits/symbols.x86_64-windows.c diff --git a/cbits/symbols.x86_64-windows.c b/cbits/symbols.x86_64-windows.c new file mode 100644 index 0000000..4d85509 --- /dev/null +++ b/cbits/symbols.x86_64-windows.c @@ -0,0 +1,39 @@ +#include + +#define MISSING_FUN(f) void (f)(void) { printf("Unknown call to `%s'\n", #f); exit(1); } + +typedef void SymbolAddr; +typedef char SymbolName; + +typedef enum _SymStrength { + STRENGTH_NORMAL, + STRENGTH_WEAK, + STRENGTH_STRONG, +} SymStrength; + +typedef enum _SymType { + SYM_TYPE_CODE = 1 << 0, /* the symbol is a function and can be relocated via a jump island */ + SYM_TYPE_DATA = 1 << 1, /* the symbol is data */ + SYM_TYPE_INDIRECT_DATA = 1 << 2, /* see Note [_iob_func symbol] */ + 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. */ +} SymType; + +typedef struct _RtsSymbolVal { + const SymbolName* lbl; + SymbolAddr* addr; + SymStrength strength; + SymType type; +} RtsSymbolVal; + +#define SYM(x) { #x, (void*)(&x), STRENGTH_NORMAL, 1 } + +RtsSymbolVal my_iserv_syms[] = { + SYM(log1pf), SYM(log1p), SYM(logf), SYM(log), + { 0, 0, STRENGTH_NORMAL, 1 } /* sentinel */ +}; + +RtsSymbolVal* iserv_syms() { + return my_iserv_syms; +} diff --git a/iserv-proxy.cabal b/iserv-proxy.cabal index b8ef863..3992eca 100644 --- a/iserv-proxy.cabal +++ b/iserv-proxy.cabal @@ -120,6 +120,10 @@ Executable iserv-proxy-interpreter c-sources: cbits/symbols.i386-musl.c c-sources: cbits/symbols.armv7a-android.c + if os(windows) + if arch(x86_64) + c-sources: cbits/symbols.x86_64-windows.c + Build-Depends: base >= 4 && < 5, iserv-proxy From a905515ebf7606bc4030ad4ee318dcdfc1b6432c Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Fri, 14 Mar 2025 20:45:39 +1300 Subject: [PATCH 37/57] Add support for GHC >=9.12 --- cbits/symbols.aarch64-android.c | 5 +++++ cbits/symbols.aarch64-musl.c | 5 +++++ cbits/symbols.armv7a-android.c | 5 +++++ cbits/symbols.i386-musl.c | 5 +++++ cbits/symbols.x86_64-musl.c | 5 +++++ cbits/symbols.x86_64-windows.c | 5 +++++ 6 files changed, 30 insertions(+) diff --git a/cbits/symbols.aarch64-android.c b/cbits/symbols.aarch64-android.c index 04d877f..ed1920a 100644 --- a/cbits/symbols.aarch64-android.c +++ b/cbits/symbols.aarch64-android.c @@ -479,4 +479,9 @@ RtsSymbolVal my_iserv_syms[] = { RtsSymbolVal* iserv_syms() { return my_iserv_syms; } + +// Name used in GHC >=9.12 +RtsSymbolVal* rtsExtraSyms() { + return my_iserv_syms; +} #endif diff --git a/cbits/symbols.aarch64-musl.c b/cbits/symbols.aarch64-musl.c index e0a5d30..a161cf5 100644 --- a/cbits/symbols.aarch64-musl.c +++ b/cbits/symbols.aarch64-musl.c @@ -49,4 +49,9 @@ RtsSymbolVal my_iserv_syms[] = { RtsSymbolVal* iserv_syms() { return my_iserv_syms; } + +// Name used in GHC >=9.12 +RtsSymbolVal* rtsExtraSyms() { + return my_iserv_syms; +} #endif diff --git a/cbits/symbols.armv7a-android.c b/cbits/symbols.armv7a-android.c index a32aa02..2211511 100644 --- a/cbits/symbols.armv7a-android.c +++ b/cbits/symbols.armv7a-android.c @@ -778,4 +778,9 @@ RtsSymbolVal my_iserv_syms[] = { RtsSymbolVal* iserv_syms() { return my_iserv_syms; } + +// Name used in GHC >=9.12 +RtsSymbolVal* rtsExtraSyms() { + return my_iserv_syms; +} #endif diff --git a/cbits/symbols.i386-musl.c b/cbits/symbols.i386-musl.c index 455e60e..b82fb68 100644 --- a/cbits/symbols.i386-musl.c +++ b/cbits/symbols.i386-musl.c @@ -293,3 +293,8 @@ RtsSymbolVal my_iserv_syms[] = { RtsSymbolVal* iserv_syms() { return my_iserv_syms; } + +// Name used in GHC >=9.12 +RtsSymbolVal* rtsExtraSyms() { + return my_iserv_syms; +} diff --git a/cbits/symbols.x86_64-musl.c b/cbits/symbols.x86_64-musl.c index 388b1ca..aa05b37 100644 --- a/cbits/symbols.x86_64-musl.c +++ b/cbits/symbols.x86_64-musl.c @@ -320,4 +320,9 @@ RtsSymbolVal my_iserv_syms[] = { RtsSymbolVal* iserv_syms() { return my_iserv_syms; } + +// Name used in GHC >=9.12 +RtsSymbolVal* rtsExtraSyms() { + return my_iserv_syms; +} #endif diff --git a/cbits/symbols.x86_64-windows.c b/cbits/symbols.x86_64-windows.c index 4d85509..ef34cf4 100644 --- a/cbits/symbols.x86_64-windows.c +++ b/cbits/symbols.x86_64-windows.c @@ -37,3 +37,8 @@ RtsSymbolVal my_iserv_syms[] = { RtsSymbolVal* iserv_syms() { return my_iserv_syms; } + +// Name used in GHC >=9.12 +RtsSymbolVal* rtsExtraSyms() { + return my_iserv_syms; +} From e9dc86ed6ad71f0368c16672081c8f26406c3a7e Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Sun, 16 Mar 2025 23:46:06 +1300 Subject: [PATCH 38/57] Add symbols for GHC 9.12 --- cbits/symbols.aarch64-android.c | 3 +++ cbits/symbols.armv7a-android.c | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/cbits/symbols.aarch64-android.c b/cbits/symbols.aarch64-android.c index ed1920a..f3c1903 100644 --- a/cbits/symbols.aarch64-android.c +++ b/cbits/symbols.aarch64-android.c @@ -473,6 +473,9 @@ RtsSymbolVal my_iserv_syms[] = { SYM(pthread_attr_setdetachstate), SYM(pthread_attr_destroy), SYM(nice), + SYM(unlinkat), + SYM(fchmodat), + SYM(fstatat), { 0, 0, STRENGTH_NORMAL, 1 } /* sentinel */ }; diff --git a/cbits/symbols.armv7a-android.c b/cbits/symbols.armv7a-android.c index 2211511..9695168 100644 --- a/cbits/symbols.armv7a-android.c +++ b/cbits/symbols.armv7a-android.c @@ -311,6 +311,9 @@ extern void getpriority(void); extern void nice(void); extern void tcgetpgrp(void); extern void tcsetpgrp(void); +extern void unlinkat(void); +extern void fchmodat(void); +extern void fstatat(void); #define MISSING_FUN(f) void (f)(void) { printf("Unknown call to %s\n", #f); exit(1); } @@ -772,6 +775,9 @@ RtsSymbolVal my_iserv_syms[] = { SYM(tcgetpgrp), SYM(tcsetpgrp), SYM(realpath), + SYM(unlinkat), + SYM(fchmodat), + SYM(fstatat), { 0, 0, STRENGTH_NORMAL, 1 } /* sentinel */ }; From dea34de4bde325aca22472c18d659bee7800b477 Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Mon, 12 May 2025 23:02:22 +1200 Subject: [PATCH 39/57] Add __strncpy_chk for android --- cbits/symbols.aarch64-android.c | 3 ++- cbits/symbols.armv7a-android.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/cbits/symbols.aarch64-android.c b/cbits/symbols.aarch64-android.c index f3c1903..7736df5 100644 --- a/cbits/symbols.aarch64-android.c +++ b/cbits/symbols.aarch64-android.c @@ -105,6 +105,7 @@ extern void __vfprintf(void); void * __gxx_personality_v0; extern void __cxa_guard_acquire(void); extern void __cxa_guard_release(void); +extern void __strncpy_chk(void); #define MISSING_FUN(f) void (f)(void) { printf("Unknown call to `%s'\n", #f); exit(1); } @@ -282,7 +283,7 @@ RtsSymbolVal my_iserv_syms[] = { SYM(memchr),SYM(strcpy),SYM(strchr),SYM(strncpy),SYM(strrchr), SYM(strcat),SYM(strncmp),SYM(strdup), SYM(strtoul),SYM(strspn),SYM(strtol),SYM(strstr),SYM(strcspn), - SYM(__strncpy_chk2),SYM(__memcpy_chk), + SYM(__strncpy_chk),SYM(__strncpy_chk2),SYM(__memcpy_chk), // ctype.h SYM(__ctype_get_mb_cur_max), // wchar.h diff --git a/cbits/symbols.armv7a-android.c b/cbits/symbols.armv7a-android.c index 9695168..f3fae68 100644 --- a/cbits/symbols.armv7a-android.c +++ b/cbits/symbols.armv7a-android.c @@ -314,6 +314,7 @@ extern void tcsetpgrp(void); extern void unlinkat(void); extern void fchmodat(void); extern void fstatat(void); +extern void __strncpy_chk(void); #define MISSING_FUN(f) void (f)(void) { printf("Unknown call to %s\n", #f); exit(1); } @@ -495,6 +496,7 @@ RtsSymbolVal my_iserv_syms[] = { SYM(__strlen_chk), SYM(strncmp), SYM(strncpy), + SYM(__strncpy_chk), SYM(__strncpy_chk2), SYM(strrchr), SYM(strspn), From 05a87bf1ed78bb334701b90638d23da474f017ed Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Thu, 5 Jun 2025 11:06:21 +1200 Subject: [PATCH 40/57] Fix for GHC HEAD --- Main.hs | 8 ++++++++ src/IServ/Remote/Interpreter.hs | 12 +++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/Main.hs b/Main.hs index 2eb5263..42124d2 100644 --- a/Main.hs +++ b/Main.hs @@ -110,8 +110,12 @@ main = do inh <- getGhcHandle rfd2 outh <- getGhcHandle wfd1 installSignalHandlers +#if MIN_VERSION_ghci(9,13,0) + in_pipe <- mkPipeFromHandles inh outh +#else lo_ref <- newIORef Nothing let in_pipe = Pipe{pipeRead = inh, pipeWrite = outh, pipeLeftovers = lo_ref} +#endif when verbose $ trace ("Trying to connect to " ++ host_ip ++ ":" ++ (show port)) @@ -316,5 +320,9 @@ socketToPipe sock = do hdl <- socketToHandle sock ReadWriteMode hSetBuffering hdl NoBuffering +#if MIN_VERSION_ghci(9,13,0) + mkPipeFromHandles hdl hdl +#else lo_ref <- newIORef Nothing pure Pipe{ pipeRead = hdl, pipeWrite = hdl, pipeLeftovers = lo_ref } +#endif diff --git a/src/IServ/Remote/Interpreter.hs b/src/IServ/Remote/Interpreter.hs index bb077e4..6ac2c8a 100644 --- a/src/IServ/Remote/Interpreter.hs +++ b/src/IServ/Remote/Interpreter.hs @@ -22,8 +22,11 @@ import System.FilePath (takeDirectory, (), dropTrailingPathSeparator, import GHCi.ResolvedBCO import Data.IORef -import GHCi.Message (Pipe(..), Msg(..), Message(..), readPipe, writePipe) - +import GHCi.Message (Pipe(..), Msg(..), Message(..), readPipe, writePipe +#if MIN_VERSION_ghci(9,13,0) + mkPipeFromHandles +#endif + ) import Foreign.C.String import Data.Binary @@ -160,9 +163,12 @@ socketToPipe :: Socket -> IO Pipe socketToPipe sock = do hdl <- socketToHandle sock ReadWriteMode hSetBuffering hdl NoBuffering - +#if MIN_VERSION_ghci(9,13,0) + mkPipeFromHandles hdl hdl +#else lo_ref <- newIORef Nothing pure Pipe{ pipeRead = hdl, pipeWrite = hdl, pipeLeftovers = lo_ref } +#endif acceptSocket :: Socket -> IO Socket acceptSocket = fmap fst . accept From 832b56c0ea37d8d372c2fddd879acd2f818d6818 Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Thu, 5 Jun 2025 11:10:11 +1200 Subject: [PATCH 41/57] Add missing `,` --- src/IServ/Remote/Interpreter.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/IServ/Remote/Interpreter.hs b/src/IServ/Remote/Interpreter.hs index 6ac2c8a..8ee56a1 100644 --- a/src/IServ/Remote/Interpreter.hs +++ b/src/IServ/Remote/Interpreter.hs @@ -24,7 +24,7 @@ import GHCi.ResolvedBCO import Data.IORef import GHCi.Message (Pipe(..), Msg(..), Message(..), readPipe, writePipe #if MIN_VERSION_ghci(9,13,0) - mkPipeFromHandles + , mkPipeFromHandles #endif ) import Foreign.C.String From c38db6f28808cf893ef8d391313c7d0d26ed9528 Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Fri, 6 Jun 2025 10:26:33 +1200 Subject: [PATCH 42/57] Fix for android --- cbits/symbols.aarch64-android.c | 1 + cbits/symbols.armv7a-android.c | 1 + 2 files changed, 2 insertions(+) diff --git a/cbits/symbols.aarch64-android.c b/cbits/symbols.aarch64-android.c index 7736df5..dd493f1 100644 --- a/cbits/symbols.aarch64-android.c +++ b/cbits/symbols.aarch64-android.c @@ -302,6 +302,7 @@ RtsSymbolVal my_iserv_syms[] = { SYM(__strchr_chk), SYM(__memset_chk), SYM(__memmove_chk), + SYM(__memchr_chk), SYM(__stack_chk_fail), SYM(memmove), SYM(memcmp), diff --git a/cbits/symbols.armv7a-android.c b/cbits/symbols.armv7a-android.c index f3fae68..1420151 100644 --- a/cbits/symbols.armv7a-android.c +++ b/cbits/symbols.armv7a-android.c @@ -522,6 +522,7 @@ RtsSymbolVal my_iserv_syms[] = { SYM(getsockopt), SYM(localtime_r), SYM(__memmove_chk), + SYM(__memchr_chk), SYM(mmap), SYM(opendir), SYM(pthread_rwlock_rdlock), From 6972fbc49574108cb48723bb94260e3ce17898f7 Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Fri, 6 Jun 2025 14:24:41 +1200 Subject: [PATCH 43/57] Fix for android --- cbits/symbols.aarch64-android.c | 1 + 1 file changed, 1 insertion(+) diff --git a/cbits/symbols.aarch64-android.c b/cbits/symbols.aarch64-android.c index dd493f1..f8c2a8e 100644 --- a/cbits/symbols.aarch64-android.c +++ b/cbits/symbols.aarch64-android.c @@ -478,6 +478,7 @@ RtsSymbolVal my_iserv_syms[] = { SYM(unlinkat), SYM(fchmodat), SYM(fstatat), + SYM(floor), { 0, 0, STRENGTH_NORMAL, 1 } /* sentinel */ }; From aff8850fa9fa363a0eebc87dba95b2e25c8dd9bc Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Mon, 9 Jun 2025 10:02:59 +1200 Subject: [PATCH 44/57] Use `-threaded` to fix Windows IO issue --- iserv-proxy.cabal | 2 ++ 1 file changed, 2 insertions(+) diff --git a/iserv-proxy.cabal b/iserv-proxy.cabal index 3992eca..eba703e 100644 --- a/iserv-proxy.cabal +++ b/iserv-proxy.cabal @@ -99,6 +99,7 @@ Executable iserv-proxy iserv-proxy if impl(ghc < 9.8) Build-Depends: libiserv + ghc-options: -threaded Executable iserv-proxy-interpreter Default-Language: Haskell2010 @@ -126,4 +127,5 @@ Executable iserv-proxy-interpreter Build-Depends: base >= 4 && < 5, iserv-proxy + ghc-options: -threaded From e40eddb1ca1e3e906e018c7e6b0d1e51c930ec9d Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Mon, 9 Jun 2025 16:31:51 +1200 Subject: [PATCH 45/57] Add `threaded` flag (so we can easily turn it off) --- iserv-proxy.cabal | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/iserv-proxy.cabal b/iserv-proxy.cabal index eba703e..81e5ab3 100644 --- a/iserv-proxy.cabal +++ b/iserv-proxy.cabal @@ -67,6 +67,10 @@ cabal-version: >=1.10 -- these aren't really headers. They are more like includable files. extra-source-files: cbits/symbols.aarch64-musl.h +flag threaded + default: True + manual: True + Library Default-Language: Haskell2010 Hs-Source-Dirs: src @@ -99,7 +103,8 @@ Executable iserv-proxy iserv-proxy if impl(ghc < 9.8) Build-Depends: libiserv - ghc-options: -threaded + if flag(threaded) + ghc-options: -threaded Executable iserv-proxy-interpreter Default-Language: Haskell2010 @@ -127,5 +132,6 @@ Executable iserv-proxy-interpreter Build-Depends: base >= 4 && < 5, iserv-proxy - ghc-options: -threaded + if flag(threaded) + ghc-options: -threaded From a53c57c9a8d22a66a2f0c4c969e806da03f08c28 Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Sun, 22 Jun 2025 10:01:13 +1200 Subject: [PATCH 46/57] Fix GHC 9.6 mingwW64 cross compile --- cbits/symbols.x86_64-windows.c | 45 +++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/cbits/symbols.x86_64-windows.c b/cbits/symbols.x86_64-windows.c index ef34cf4..a6c6378 100644 --- a/cbits/symbols.x86_64-windows.c +++ b/cbits/symbols.x86_64-windows.c @@ -1,3 +1,4 @@ +#include #include #define MISSING_FUN(f) void (f)(void) { printf("Unknown call to `%s'\n", #f); exit(1); } @@ -30,7 +31,49 @@ typedef struct _RtsSymbolVal { #define SYM(x) { #x, (void*)(&x), STRENGTH_NORMAL, 1 } RtsSymbolVal my_iserv_syms[] = { - SYM(log1pf), SYM(log1p), SYM(logf), SYM(log), + SYM(acos), + SYM(acosf), + SYM(acosh), + SYM(acoshf), + SYM(asin), + SYM(asinf), + SYM(asinh), + SYM(asinhf), + SYM(atan), + SYM(atanf), + SYM(atanh), + SYM(atanhf), + SYM(cos), + SYM(cosf), + SYM(cosh), + SYM(coshf), + SYM(erf), + SYM(erfc), + SYM(erfcf), + SYM(erff), + SYM(exp), + SYM(expf), + SYM(expm1), + SYM(expm1f), + SYM(log), + SYM(log1p), + SYM(log1pf), + SYM(logf), + SYM(memcmp), + SYM(memcpy), + SYM(memmove), + SYM(memset), + SYM(pow), + SYM(powf), + SYM(sin), + SYM(sinf), + SYM(sinh), + SYM(sinhf), + SYM(strlen), + SYM(tan), + SYM(tanf), + SYM(tanh), + SYM(tanhf), { 0, 0, STRENGTH_NORMAL, 1 } /* sentinel */ }; From 1383d199a2c64f522979005d112b4fbdee38dd92 Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Wed, 13 Aug 2025 11:17:14 +1200 Subject: [PATCH 47/57] Add upper bound to `network` See https://github.com/haskell/network/issues/604 --- iserv-proxy.cabal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iserv-proxy.cabal b/iserv-proxy.cabal index 81e5ab3..913179a 100644 --- a/iserv-proxy.cabal +++ b/iserv-proxy.cabal @@ -84,7 +84,7 @@ Library containers >= 0.5 && < 0.8, deepseq >= 1.4 && < 1.6, directory >= 1.3 && < 1.4, - network >= 2.6, + network >= 2.6 && < 3.2.8.0, filepath >= 1.4 && < 1.6, ghci if impl(ghc < 9.8) From 150605195cb7183a6fb7bed82f23fedf37c6f52a Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Fri, 15 Aug 2025 19:31:18 +1200 Subject: [PATCH 48/57] Fixes for android --- cbits/symbols.aarch64-android.c | 3 ++- cbits/symbols.armv7a-android.c | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/cbits/symbols.aarch64-android.c b/cbits/symbols.aarch64-android.c index f8c2a8e..dc7c75c 100644 --- a/cbits/symbols.aarch64-android.c +++ b/cbits/symbols.aarch64-android.c @@ -172,7 +172,7 @@ RtsSymbolVal my_iserv_syms[] = { SYM(setsockopt),SYM(socket),SYM(getsockname),SYM(select), SYM(getpeername),SYM(__cmsg_nxthdr),SYM(recv),SYM(recvfrom), SYM(recvmsg),SYM(send),SYM(sendmsg),SYM(sendto),SYM(writev), - SYM(accept4), + SYM(accept4),SYM(socketpair), // pthread.h SYM(pthread_equal),SYM(pthread_getspecific),SYM(pthread_key_create), SYM(pthread_key_delete),SYM(pthread_once),SYM(pthread_rwlock_destroy), @@ -283,6 +283,7 @@ RtsSymbolVal my_iserv_syms[] = { SYM(memchr),SYM(strcpy),SYM(strchr),SYM(strncpy),SYM(strrchr), SYM(strcat),SYM(strncmp),SYM(strdup), SYM(strtoul),SYM(strspn),SYM(strtol),SYM(strstr),SYM(strcspn), + SYM(strpbrk), SYM(__strncpy_chk),SYM(__strncpy_chk2),SYM(__memcpy_chk), // ctype.h SYM(__ctype_get_mb_cur_max), diff --git a/cbits/symbols.armv7a-android.c b/cbits/symbols.armv7a-android.c index 1420151..7375bfd 100644 --- a/cbits/symbols.armv7a-android.c +++ b/cbits/symbols.armv7a-android.c @@ -61,6 +61,7 @@ extern void fcntl(void); extern void open(void); extern void access(void); extern void environ(void); +extern void lseek(void); extern void lseek64(void); extern void umask(void); extern void poll(void); @@ -89,6 +90,7 @@ extern void uname(void); extern void tzset(void); extern void sysconf(void); extern void socket(void); +extern void socketpair(void); extern void readdir(void); extern void readdir_r(void); extern void pthread_rwlock_init(void); @@ -439,6 +441,7 @@ RtsSymbolVal my_iserv_syms[] = { SYM(tanf), SYM(utime), SYM(asinf), + SYM(lseek), SYM(lseek64), SYM(umask), SYM(acosf), @@ -487,6 +490,7 @@ RtsSymbolVal my_iserv_syms[] = { SYM(readdir), SYM(readdir_r), SYM(socket), + SYM(socketpair), SYM(__stack_chk_fail), SYM(__stack_chk_guard), SYM(strchr), @@ -498,6 +502,7 @@ RtsSymbolVal my_iserv_syms[] = { SYM(strncpy), SYM(__strncpy_chk), SYM(__strncpy_chk2), + SYM(strpbrk), SYM(strrchr), SYM(strspn), SYM(strstr), From e9cbfce33710a0180532a235ec9d62f5a51d3ae5 Mon Sep 17 00:00:00 2001 From: Alexandre Esteves Date: Sun, 5 Oct 2025 23:46:18 +0100 Subject: [PATCH 49/57] Fix iserv-proxy build on windows --- Main.hs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/Main.hs b/Main.hs index 42124d2..4db9590 100644 --- a/Main.hs +++ b/Main.hs @@ -88,14 +88,14 @@ main = do hSetBuffering stdout LineBuffering args <- getArgs - (wfd1, rfd2, host_ip, port, rest) <- + (outh, inh, host_ip, port, rest) <- case args of arg0:arg1:arg2:arg3:rest -> do - let wfd1 = read arg0 - rfd2 = read arg1 - ip = arg2 + outh <- readGhcHandle arg0 + inh <- readGhcHandle arg1 + let ip = arg2 port = read arg3 - return (wfd1, rfd2, ip, port, rest) + return (outh, inh, ip, port, rest) _ -> dieWithUsage let verbose = "-v" `elem` rest @@ -105,10 +105,7 @@ main = do dieWithUsage when verbose $ - printf "GHC iserv starting (in: %d; out: %d)\n" - (fromIntegral rfd2 :: Int) (fromIntegral wfd1 :: Int) - inh <- getGhcHandle rfd2 - outh <- getGhcHandle wfd1 + printf "GHC iserv starting (in: %s; out: %s)\n" (show inh) (show outh) installSignalHandlers #if MIN_VERSION_ghci(9,13,0) in_pipe <- mkPipeFromHandles inh outh From bbee090fc67bb5cc6ad4508fa5def560b7672591 Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Thu, 30 Oct 2025 18:17:52 +1300 Subject: [PATCH 50/57] Bump containers upper bound --- iserv-proxy.cabal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iserv-proxy.cabal b/iserv-proxy.cabal index 913179a..ad2e21d 100644 --- a/iserv-proxy.cabal +++ b/iserv-proxy.cabal @@ -81,7 +81,7 @@ Library base >= 4 && < 5, binary >= 0.7 && < 0.9, bytestring >= 0.10 && < 0.13, - containers >= 0.5 && < 0.8, + containers >= 0.5 && < 0.9, deepseq >= 1.4 && < 1.6, directory >= 1.3 && < 1.4, network >= 2.6 && < 3.2.8.0, From dc144516464d3b4f4107b1765873473758aae1dc Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Tue, 3 Feb 2026 22:55:16 +1300 Subject: [PATCH 51/57] Add symbols for armv7a-android --- cbits/symbols.armv7a-android.c | 48 ++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/cbits/symbols.armv7a-android.c b/cbits/symbols.armv7a-android.c index 7375bfd..c46f870 100644 --- a/cbits/symbols.armv7a-android.c +++ b/cbits/symbols.armv7a-android.c @@ -317,6 +317,30 @@ extern void unlinkat(void); extern void fchmodat(void); extern void fstatat(void); extern void __strncpy_chk(void); +extern void tcsetattr(void); +extern void tcgetattr(void); +extern void statx(void); +extern void tcflow(void); +extern void tcflush(void); +extern void tcdrain(void); +extern void tcsendbreak(void); +extern void cfsetospeed(void); +extern void cfgetospeed(void); +extern void cfsetispeed(void); +extern void cfgetispeed(void); +extern void pipe2(void); +extern void initgroups(void); +extern void posix_spawn_file_actions_init(void); +extern void posix_spawnattr_init(void); +extern void posix_spawn_file_actions_destroy(void); +extern void posix_spawn_file_actions_addopen(void); +extern void posix_spawn_file_actions_adddup2(void); +extern void posix_spawn_file_actions_addclose(void); +extern void posix_spawn_file_actions_addchdir_np(void); +extern void posix_spawnattr_destroy(void); +extern void posix_spawnattr_setflags(void); +extern void posix_spawnattr_setsigdefault(void); +extern void posix_spawnp(void); #define MISSING_FUN(f) void (f)(void) { printf("Unknown call to %s\n", #f); exit(1); } @@ -786,6 +810,30 @@ RtsSymbolVal my_iserv_syms[] = { SYM(unlinkat), SYM(fchmodat), SYM(fstatat), + SYM(tcsetattr), + SYM(tcgetattr), + SYM(statx), + SYM(tcflow), + SYM(tcflush), + SYM(tcdrain), + SYM(tcsendbreak), + SYM(cfsetospeed), + SYM(cfgetospeed), + SYM(cfsetispeed), + SYM(cfgetispeed), + SYM(pipe2), + SYM(initgroups), + SYM(posix_spawn_file_actions_init), + SYM(posix_spawnattr_init), + SYM(posix_spawn_file_actions_destroy), + SYM(posix_spawn_file_actions_addopen), + SYM(posix_spawn_file_actions_adddup2), + SYM(posix_spawn_file_actions_addclose), + SYM(posix_spawn_file_actions_addchdir_np), + SYM(posix_spawnattr_destroy), + SYM(posix_spawnattr_setflags), + SYM(posix_spawnattr_setsigdefault), + SYM(posix_spawnp), { 0, 0, STRENGTH_NORMAL, 1 } /* sentinel */ }; From 91ef7ffdeedfb141a4d69dcf9e550abe3e1160c6 Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Wed, 4 Feb 2026 16:04:18 +1300 Subject: [PATCH 52/57] Fix for GHC < 9.7 --- Main.hs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Main.hs b/Main.hs index 4db9590..2e7c229 100644 --- a/Main.hs +++ b/Main.hs @@ -82,6 +82,11 @@ dieWithUsage = do msg = "usage: iserv [-v]" #endif +#if !MIN_VERSION_ghci(9,7,0) +readGhcHandle :: String -> IO Handle +readGhcHandle = getGhcHandle . read +#endif + main :: IO () main = do hSetBuffering stdin LineBuffering From 3f7b2815307c20a0dfd816bdf4a39ab86af3e0d4 Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Wed, 8 Apr 2026 15:55:57 +1200 Subject: [PATCH 53/57] Add --stdio/--pipe modes for stdin/stdout communication TCP networking inside nix-linux-builder VMs is unreliable, causing iserv-proxy to hang or fail when connecting to the interpreter via sockets. This adds two new modes: - Interpreter --stdio: reads/writes protocol data on stdin/stdout instead of TCP. Uses hDuplicate/hDuplicateTo to redirect the Haskell stdout handle to stderr, preventing library code from corrupting the data channel. - Proxy --pipe : spawns the interpreter as a subprocess and communicates via its stdin/stdout pipes, bypassing TCP entirely. Both modes are opt-in; the original TCP mode is unchanged. Also redirects all diagnostic output (trace, hook messages) to stderr in both old and new code paths. --- Interpreter.hs | 20 ++++- Main.hs | 134 ++++++++++++++++++++++++-------- iserv-proxy.cabal | 1 + src/IServ/Remote/Interpreter.hs | 44 +++++++++-- 4 files changed, 155 insertions(+), 44 deletions(-) diff --git a/Interpreter.hs b/Interpreter.hs index 3b3ecc8..0d70cf1 100644 --- a/Interpreter.hs +++ b/Interpreter.hs @@ -1,6 +1,6 @@ module Main where -import IServ.Remote.Interpreter (startInterpreter') +import IServ.Remote.Interpreter (startInterpreter', startInterpreterStdio) import System.Environment (getArgs, getProgName) import System.Exit (die) @@ -14,11 +14,25 @@ dieWithUsage = do prog <- getProgName die $ msg prog where - msg name = "usage: " ++ name ++ " /path/to/storage PORT [-v] [--no-load-call]" + msg name = "usage: " ++ name ++ " /path/to/storage PORT [-v] [--no-load-call]\n" + ++ " " ++ name ++ " /path/to/storage --stdio [-v] [--no-load-call]" startSlave :: [String] -> IO () startSlave args0 | "--help" `elem` args0 = dieWithUsage + | "--stdio" `elem` args0 = do + let rest = filter (`notElem` ["--stdio"]) args0 + (path, flags) <- case rest of + arg0:flags -> return (arg0, flags) + _ -> dieWithUsage + + let verbose = "-v" `elem` flags + noLoadCall = "--no-load-call" `elem` flags + + when (any (`notElem` ["-v", "--no-load-call"]) flags) + dieWithUsage + + startInterpreterStdio verbose noLoadCall path | otherwise = do (path, port, rest) <- case args0 of arg0:arg1:rest -> return (arg0, read arg1, rest) @@ -27,7 +41,7 @@ startSlave args0 let verbose = "-v" `elem` rest noLoadCall = "--no-load-call" `elem` rest - when (any (not . (`elem` ["-v", "--no-load-call"])) rest) + when (any (`notElem` ["-v", "--no-load-call"]) rest) dieWithUsage startInterpreter' verbose noLoadCall path port diff --git a/Main.hs b/Main.hs index 2e7c229..ba79c97 100644 --- a/Main.hs +++ b/Main.hs @@ -26,7 +26,7 @@ somewhat clear: | GHC <--> proxy<+-----+> iserv | '----------------' ^ '----------' ^ | - | '-- communication via sockets + | '-- communication via sockets or pipes '--- communication via pipes For now, we won't support multiple concurrent @@ -61,6 +61,7 @@ import Text.Printf import GHC.Fingerprint (getFileHash) import System.Directory import System.FilePath (isAbsolute) +import System.Process import Data.Binary import qualified Data.ByteString as BS @@ -77,9 +78,11 @@ dieWithUsage = do die $ prog ++ ": " ++ msg where #if defined(WINDOWS) - msg = "usage: iserv [-v]" + msg = "usage: iserv [-v]\n" + ++ " iserv --pipe [args...] [-v]" #else - msg = "usage: iserv [-v]" + msg = "usage: iserv [-v]\n" + ++ " iserv --pipe [args...] [-v]" #endif #if !MIN_VERSION_ghci(9,7,0) @@ -93,45 +96,108 @@ main = do hSetBuffering stdout LineBuffering args <- getArgs - (outh, inh, host_ip, port, rest) <- - case args of - arg0:arg1:arg2:arg3:rest -> do - outh <- readGhcHandle arg0 - inh <- readGhcHandle arg1 - let ip = arg2 - port = read arg3 - return (outh, inh, ip, port, rest) - _ -> dieWithUsage - - let verbose = "-v" `elem` rest - noLoadCall = "--no-load-call" `elem` rest - - when (any (not . (`elem` ["-v", "--no-load-call"])) rest) - dieWithUsage + case args of + -- New --pipe mode: --pipe [args...] + (arg0:arg1:"--pipe":cmdArgs) | not (null cmdArgs) -> do + outh <- readGhcHandle arg0 + inh <- readGhcHandle arg1 - when verbose $ - printf "GHC iserv starting (in: %s; out: %s)\n" (show inh) (show outh) - installSignalHandlers + -- Extract proxy flags that appear before the command + let verbose = "-v" `elem` cmdArgs + noLoadCall = "--no-load-call" `elem` cmdArgs + + when verbose $ + trace ("Spawning interpreter: " ++ unwords cmdArgs) + + installSignalHandlers #if MIN_VERSION_ghci(9,13,0) - in_pipe <- mkPipeFromHandles inh outh + in_pipe <- mkPipeFromHandles inh outh #else - lo_ref <- newIORef Nothing - let in_pipe = Pipe{pipeRead = inh, pipeWrite = outh, pipeLeftovers = lo_ref} + lo_ref <- newIORef Nothing + let in_pipe = Pipe{pipeRead = inh, pipeWrite = outh, pipeLeftovers = lo_ref} #endif - when verbose $ - trace ("Trying to connect to " ++ host_ip ++ ":" ++ (show port)) + (out_pipe, ph) <- spawnInterpreter verbose cmdArgs + + when verbose $ + trace "Starting proxy" + E.finally + (proxy verbose noLoadCall in_pipe out_pipe) + (do when verbose $ trace "Terminating interpreter..." + terminateProcess ph + _ <- waitForProcess ph + return ()) + + -- Original TCP mode (backward compatible) + (arg0:arg1:arg2:arg3:rest) -> do + outh <- readGhcHandle arg0 + inh <- readGhcHandle arg1 + let ip = arg2 + port = read arg3 + + let verbose = "-v" `elem` rest + noLoadCall = "--no-load-call" `elem` rest + + when (any (not . (`elem` ["-v", "--no-load-call"])) rest) + dieWithUsage - out_pipe <- do - let go n = E.try (connectTo verbose host_ip port >>= socketToPipe) >>= \case - Left e | n == 0 -> E.throw (e :: E.SomeException) - | n > 0 -> threadDelay 500000 >> go (n - 1) - Right a -> return a - in go 120 -- wait for up to 60seconds (polling every 0.5s). + when verbose $ + printf "GHC iserv starting (in: %s; out: %s)\n" (show inh) (show outh) + installSignalHandlers +#if MIN_VERSION_ghci(9,13,0) + in_pipe <- mkPipeFromHandles inh outh +#else + lo_ref <- newIORef Nothing + let in_pipe = Pipe{pipeRead = inh, pipeWrite = outh, pipeLeftovers = lo_ref} +#endif + + when verbose $ + trace ("Trying to connect to " ++ ip ++ ":" ++ (show port)) + + out_pipe <- do + let go n = E.try (connectTo verbose ip port >>= socketToPipe) >>= \case + Left e | n == 0 -> E.throw (e :: E.SomeException) + | n > 0 -> threadDelay 500000 >> go (n - 1) + Right a -> return a + in go 120 -- wait for up to 60seconds (polling every 0.5s). + + when verbose $ + trace "Starting proxy" + proxy verbose noLoadCall in_pipe out_pipe + + _ -> dieWithUsage + + +-- | Spawn the interpreter as a child process and create a Pipe +-- from its stdin/stdout handles. +spawnInterpreter :: Bool -> [String] -> IO (Pipe, ProcessHandle) +spawnInterpreter verbose (cmd:args) = do + let cp = (proc cmd args) + { std_in = CreatePipe + , std_out = CreatePipe + , std_err = Inherit + } + (Just hIn, Just hOut, _, ph) <- createProcess cp when verbose $ - trace "Starting proxy" - proxy verbose noLoadCall in_pipe out_pipe + trace "Interpreter process spawned" + + hSetBuffering hIn NoBuffering + hSetBuffering hOut NoBuffering + hSetBinaryMode hIn True + hSetBinaryMode hOut True + + -- hIn is the child's stdin (we write to it) + -- hOut is the child's stdout (we read from it) +#if MIN_VERSION_ghci(9,13,0) + pipe <- mkPipeFromHandles hOut hIn +#else + lo_ref <- newIORef Nothing + let pipe = Pipe{ pipeRead = hOut, pipeWrite = hIn, pipeLeftovers = lo_ref } +#endif + return (pipe, ph) +spawnInterpreter _ [] = die "iserv-proxy: --pipe requires a command" + -- | A hook, to transform outgoing (proxy -> interpreter) -- messages prior to sending them to the interpreter. diff --git a/iserv-proxy.cabal b/iserv-proxy.cabal index ad2e21d..c89fdd1 100644 --- a/iserv-proxy.cabal +++ b/iserv-proxy.cabal @@ -99,6 +99,7 @@ Executable iserv-proxy directory >= 1.3 && < 1.4, network >= 2.6, filepath >= 1.4 && < 1.6, + process >= 1.6, ghci, iserv-proxy if impl(ghc < 9.8) diff --git a/src/IServ/Remote/Interpreter.hs b/src/IServ/Remote/Interpreter.hs index 8ee56a1..2a2efde 100644 --- a/src/IServ/Remote/Interpreter.hs +++ b/src/IServ/Remote/Interpreter.hs @@ -1,5 +1,5 @@ {-# LANGUAGE CPP, ForeignFunctionInterface, GADTs, LambdaCase #-} -module IServ.Remote.Interpreter where +module IServ.Remote.Interpreter (startInterpreter', startInterpreterStdio) where import Network.Socket @@ -36,9 +36,10 @@ import qualified Data.ByteString as BS import Text.Printf import System.Environment (getProgName) +import GHC.IO.Handle (hDuplicate, hDuplicateTo) trace :: String -> IO () -trace s = getProgName >>= \name -> printf "[%20s] %s\n" name s +trace s = getProgName >>= \name -> hPrintf stderr "[%20s] %s\n" name s dropLeadingPathSeparator :: FilePath -> FilePath dropLeadingPathSeparator p | isAbsolute p = joinPath (drop 1 (splitPath p)) @@ -62,9 +63,9 @@ startInterpreter verbose port s = do _ <- forkIO $ startInterpreter' verbose True base_path (toEnum port) return () --- | @startInterpreter'@ provdes a blocking haskell interface, that +-- | @startInterpreter'@ provides a blocking haskell interface, that -- the hosting application on the target can use to start the --- interpreter process. +-- interpreter process. Uses TCP sockets for communication. startInterpreter' :: Bool -> Bool -> String -> PortNumber -> IO () startInterpreter' verbose noLoadCall base_path port = do hSetBuffering stdin LineBuffering @@ -82,7 +83,7 @@ startInterpreter' verbose noLoadCall base_path port = do listen sock 1 actualPort <- socketPort sock - putStrLn $ "Listening on port " ++ show actualPort + hPutStrLn stderr $ "Listening on port " ++ show actualPort forever $ do when verbose $ trace "Opening socket" @@ -92,6 +93,35 @@ startInterpreter' verbose noLoadCall base_path port = do when verbose $ trace "serv ended" return () +-- | Start the interpreter in stdio mode. Reads protocol data from +-- stdin and writes to stdout, bypassing TCP entirely. All diagnostic +-- output goes to stderr. +startInterpreterStdio :: Bool -> Bool -> String -> IO () +startInterpreterStdio verbose noLoadCall base_path = do + -- Save the real stdout fd for protocol data, then redirect the + -- Haskell stdout handle to stderr. This ensures any library code + -- (including serv) that writes to stdout won't corrupt the data channel. + realStdout <- hDuplicate stdout + hDuplicateTo stderr stdout + + hSetBuffering stdin NoBuffering + hSetBuffering realStdout NoBuffering + hSetBinaryMode stdin True + hSetBinaryMode realStdout True + +#if MIN_VERSION_ghci(9,13,0) + pipe <- mkPipeFromHandles stdin realStdout +#else + lo_ref <- newIORef Nothing + let pipe = Pipe{ pipeRead = stdin, pipeWrite = realStdout, pipeLeftovers = lo_ref } +#endif + + when verbose $ trace $ "Starting serv (stdio mode), DocRoot: " ++ base_path + + uninterruptibleMask $ serv verbose (hook verbose noLoadCall base_path pipe) pipe + + when verbose $ trace "serv ended" + -- | The iserv library may need access to files, specifically -- archives and object files to be linked. If ghc and the interpreter -- are on the same host, this is trivial, as the underlying @@ -130,11 +160,11 @@ handleLoad pipe path localPath = do hook :: Bool -> Bool -> String -> Pipe -> Msg -> IO Msg hook verbose noLoadCall base_path pipe m = case m of Msg (AddLibrarySearchPath p) -> do - when verbose $ putStrLn ("Need Path: " ++ (base_path p)) + when verbose $ hPutStrLn stderr ("Need Path: " ++ (base_path p)) createDirectoryIfMissing True (base_path p) return $ Msg (AddLibrarySearchPath (base_path p)) Msg (LoadObj path) -> do - when verbose $ putStrLn ("Need Obj: " ++ (base_path path)) + when verbose $ hPutStrLn stderr ("Need Obj: " ++ (base_path path)) handleLoad pipe path (base_path path) return $ Msg (LoadObj (base_path path)) Msg (LoadArchive path) -> do From a31c4c4252994dc484d131f5ccbf166f72cdc18f Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Mon, 11 May 2026 11:54:22 +1200 Subject: [PATCH 54/57] armv7a-android: stub symbols missing from current NDK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dynamic linker fails to load this library when it sees unresolved references via the `SYM(...)` table. Provide `MISSING_FUN` stubs for the symbols our current armv7a NDK's bionic / libc++ don't ship; they're never expected to be invoked at runtime — if any actually does, the stub exits with a diagnostic. Symbols covered: posix_spawn{,attr}_{init,destroy,setflags, setsigdefault,addopen,adddup2,addclose,addchdir_np}, __cxa_guard_{abort,acquire,release}, __cxa_thread_finalize, __libc_{stdio_cleanup,shared_globals}, getentropy, statx, __fsetxattr, __arm_fadvise64_64. --- cbits/symbols.armv7a-android.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/cbits/symbols.armv7a-android.c b/cbits/symbols.armv7a-android.c index c46f870..071e7b7 100644 --- a/cbits/symbols.armv7a-android.c +++ b/cbits/symbols.armv7a-android.c @@ -353,6 +353,33 @@ MISSING_FUN(_ZSt9terminatev) MISSING_FUN(__loader_add_thread_local_dtor) MISSING_FUN(__loader_remove_thread_local_dtor) MISSING_FUN(__clang_call_terminate) +// Symbols absent from the armv7a Android NDK's bionic / libc++ as +// shipped with our current toolchain. The dynamic linker would +// otherwise fail to load this library when it sees the unresolved +// references via `SYM(...)` below. These stubs are never expected +// to be invoked at runtime; if a real call ever lands here we +// `exit(1)` with a diagnostic so the caller is visible instead of +// silently corrupting state. +MISSING_FUN(__arm_fadvise64_64) +MISSING_FUN(__cxa_guard_abort) +MISSING_FUN(__cxa_guard_acquire) +MISSING_FUN(__cxa_guard_release) +MISSING_FUN(__cxa_thread_finalize) +MISSING_FUN(__fsetxattr) +MISSING_FUN(__libc_stdio_cleanup) +MISSING_FUN(_Z21__libc_shared_globalsv) +MISSING_FUN(getentropy) +MISSING_FUN(posix_spawn_file_actions_addchdir_np) +MISSING_FUN(posix_spawn_file_actions_addclose) +MISSING_FUN(posix_spawn_file_actions_adddup2) +MISSING_FUN(posix_spawn_file_actions_addopen) +MISSING_FUN(posix_spawn_file_actions_destroy) +MISSING_FUN(posix_spawn_file_actions_init) +MISSING_FUN(posix_spawnattr_destroy) +MISSING_FUN(posix_spawnattr_init) +MISSING_FUN(posix_spawnattr_setflags) +MISSING_FUN(posix_spawnattr_setsigdefault) +MISSING_FUN(statx) typedef void SymbolAddr; typedef char SymbolName; From 8cdc446f8e2d91b120ecc075063e9475d387df52 Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Mon, 11 May 2026 11:57:16 +1200 Subject: [PATCH 55/57] armv7a-android: stub posix_spawnp too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A second pass surfaced this one too — same rationale as the previous commit. --- cbits/symbols.armv7a-android.c | 1 + 1 file changed, 1 insertion(+) diff --git a/cbits/symbols.armv7a-android.c b/cbits/symbols.armv7a-android.c index 071e7b7..8b6e40d 100644 --- a/cbits/symbols.armv7a-android.c +++ b/cbits/symbols.armv7a-android.c @@ -379,6 +379,7 @@ MISSING_FUN(posix_spawnattr_destroy) MISSING_FUN(posix_spawnattr_init) MISSING_FUN(posix_spawnattr_setflags) MISSING_FUN(posix_spawnattr_setsigdefault) +MISSING_FUN(posix_spawnp) MISSING_FUN(statx) typedef void SymbolAddr; From 6278b39451f6ddd81e1926389a99bfbcdb3f6c1c Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Thu, 13 Aug 2026 17:39:42 +1200 Subject: [PATCH 56/57] x86_64-windows: register fileno, strcasecmp, strncasecmp and __msvcrt_assert mingw-w64 14.0.0 added an `_assert` member to `libmingwex.a` (13.0.0 had none, so `_assert` came from the UCRT import library). That member calls `fileno` and imports `__msvcrt_assert`. wine's ucrtbase implements both but only exports the underscore spellings, so `GetProcAddress` returns NULL for the aliases. GHC's runtime linker loads every member of an archive, so the unresolvable `fileno` fails all of `libmingwex.a`, and template haskell then dies with libmingwex.a: unknown symbol `fileno' HSghc-bignum-...-inplace.o: unknown symbol `_assert' : error: unable to load unit `ghc-bignum-1.3' `strncasecmp` is the same story one level up, via unix-time's object. The extra symbol table is consulted before objects and DLLs and is in place before anything is loaded, so it is the right place for these: a `-l` archive is loaded only after `initLoaderState` has already resolved the command-line packages. `__imp___msvcrt_assert` gets an indirection entry (the shape of GHC's Note [_iob_func symbol]) pointing at a local implementation rather than at `_assert`, which is the caller here and would recurse. Verified on x86_64-linux with `--builders ""`: haskell.nix's ucrt64 th-dlls-minimal (all six variants) against GHC 9.6.7, 9.8.4, 9.10.3, 9.12.4 and 9.14.1, plus ucrt64 th-dlls, all of which the mingw-w64 14 bump had broken. Claude-Session: https://claude.ai/code/session_015iMn9nFmfb5DPqqW5a12co --- cbits/symbols.x86_64-windows.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/cbits/symbols.x86_64-windows.c b/cbits/symbols.x86_64-windows.c index a6c6378..6dee6f8 100644 --- a/cbits/symbols.x86_64-windows.c +++ b/cbits/symbols.x86_64-windows.c @@ -1,8 +1,30 @@ #include #include +#include +#include #define MISSING_FUN(f) void (f)(void) { printf("Unknown call to `%s'\n", #f); exit(1); } +/* mingw-w64 14.0.0 added an `_assert` member to `libmingwex.a` (13.0.0 had + none, so `_assert` came from the UCRT import library). That member calls + the CRT's assert through `__imp___msvcrt_assert`, and wine's ucrtbase does + not export that alias by name -- `GetProcAddress` returns NULL for it, so + the whole archive fails to resolve and every unit that needs a symbol from + it (ghc-bignum, ...) fails to load. Hand the linker the indirection + directly; same shape as GHC's Note [_iob_func symbol]. + + Do not point this at `_assert`: with libmingwex's member linked in that is + the caller, and it would recurse. */ +static void +iserv_msvcrt_assert (const char *expr, const char *file, unsigned int line) +{ + fprintf (stderr, "Assertion failed: %s, file %s, line %u\n", + expr ? expr : "(null)", file ? file : "(null)", line); + abort (); +} + +static const void *iserv_imp_msvcrt_assert = (const void *) &iserv_msvcrt_assert; + typedef void SymbolAddr; typedef char SymbolName; @@ -74,6 +96,17 @@ RtsSymbolVal my_iserv_syms[] = { SYM(tanf), SYM(tanh), SYM(tanhf), + /* POSIX-named CRT aliases. wine's ucrtbase implements them but only + exports the underscore spellings (`_fileno`, `_stricmp`, `_strnicmp`), + so `GetProcAddress` cannot find these and any object referencing them + fails to load: `fileno` is needed by libmingwex's `_assert` member (see + above), `strncasecmp` by unix-time. Taking their address here is fine: + the static link resolves it through mingw-w64's import library. */ + SYM(fileno), + SYM(strcasecmp), + SYM(strncasecmp), + { "__imp___msvcrt_assert", (void*)&iserv_imp_msvcrt_assert, + STRENGTH_NORMAL, SYM_TYPE_INDIRECT_DATA }, { 0, 0, STRENGTH_NORMAL, 1 } /* sentinel */ }; From 0e22186481bb960c42061bedc0c9c023ae8b90be Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Tue, 1 Sep 2026 01:32:16 +1200 Subject: [PATCH 57/57] aarch64-android: register nl_langinfo and the iconv trio TH evaluation for aarch64-android died with iserv-proxy-interpreter: Failed to lookup symbol: nl_langinfo iserv-proxy-interpreter: Failed to lookup symbol: iconv_open iserv-proxy-interpreter: Failed to lookup symbol: iconv iserv-proxy-interpreter: Failed to lookup symbol: iconv_close qemu: uncaught target signal 11 (Segmentation fault) - core dumped ghc-internal's GHC.Internal.IO.Encoding.Iconv implements the locale text encoding in terms of these four, so the object files loaded for a splice reference them. The interpreter is linked -optl-static for android (qemu user mode cannot run bionic's dynamic loader), and it never calls them itself, so they are absent from its symbol table and the runtime linker cannot resolve them. Under --optimistic-linking the load then "succeeds" with the relocations unresolved and the first call segfaults. Verified against the NDK we build with (r27, __ANDROID_API__ 35): all four resolve out of the static bionic libc, so taking their addresses here both keeps them in the binary and registers them for the linker. --- cbits/symbols.aarch64-android.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/cbits/symbols.aarch64-android.c b/cbits/symbols.aarch64-android.c index dc7c75c..0280950 100644 --- a/cbits/symbols.aarch64-android.c +++ b/cbits/symbols.aarch64-android.c @@ -107,6 +107,20 @@ extern void __cxa_guard_acquire(void); extern void __cxa_guard_release(void); extern void __strncpy_chk(void); +// Character-set conversion. `ghc-internal`'s GHC.Internal.IO.Encoding.Iconv +// binds these to implement the locale text encoding, so every object file +// loaded for a Template Haskell splice references them -- but the statically +// linked interpreter never calls them itself, so without an entry here the +// runtime linker cannot resolve them. With --optimistic-linking (which +// haskell.nix bakes in for GHC >= 9.14) the load then succeeds and the first +// call segfaults instead of failing at load time. +// bionic has had nl_langinfo since API 26 and iconv since API 28; the NDK we +// build against targets API 35. +extern void nl_langinfo(void); +extern void iconv_open(void); +extern void iconv(void); +extern void iconv_close(void); + #define MISSING_FUN(f) void (f)(void) { printf("Unknown call to `%s'\n", #f); exit(1); } MISSING_FUN(c_format_unix_time) @@ -480,6 +494,10 @@ RtsSymbolVal my_iserv_syms[] = { SYM(fchmodat), SYM(fstatat), SYM(floor), + SYM(nl_langinfo), + SYM(iconv_open), + SYM(iconv), + SYM(iconv_close), { 0, 0, STRENGTH_NORMAL, 1 } /* sentinel */ };