on iko/ghcjs-patch-master help sign in
Enable aarch64 builds (#1316)

* Adds small address space logic * no numa on android * Update comp-builder.nix * Adds android.nix * host And target. * Make android remote-iserv static * Add back mmap_next * Create rts-android-jemalloc-qemu.patch * Update bootstrap.nix * Some android modifications to ghc * Some modifications to the android overlay. * disable more hardening flags on android * Adds stack-protector-symbols.patch * Adds libraries-prim-os-android.patch * Adds support for CONDBR relocations * Adds undef+weak symbol support. * calloc takes 3 not 2 args :-( * Adds getauxval * Needs enable static now * Fix android cross

commiteb7e669d63c8a83a85ca38e7af1f8a545ffe17f3 authorMoritz Angermann <moritz.angermann@gmail.com> dateSun 9 Jan 2022, 06:36 (5 years ago) parent59799a2
17 files changed+586−12
builder/comp-builder.nix+4−2 compiler/ghc/configured-src.nix+3−1 compiler/ghc/default.nix+17−4 flake.nix+3−2 lib/default.nix+2−2 overlays/android.nix+28 overlays/bootstrap.nix+9 overlays/default.nix+2 overlays/linux-cross.nix+1−1 overlays/patches/ghc/android-base-needs-iconv.patch+14 overlays/patches/ghc/ghc-8.10.7-linker-weak-and-common.patch+189 overlays/patches/ghc/ghc-rts-linker-condbr.patch+73 overlays/patches/ghc/libc-memory-symbols.patch+43 overlays/patches/ghc/libraries-prim-os-android.patch+13 overlays/patches/ghc/mmap-next.patch+70 overlays/patches/ghc/rts-android-jemalloc-qemu.patch+48 overlays/patches/ghc/stack-protector-symbols.patch+67
builder/comp-builder.nix+4−2
@@ -82,6 +82,7 @@ let self =
8282
8383# LLVM
8484, useLLVM ? ghc.useLLVM
85+, smallAddressSpace ? false
8586
8687}@drvArgs:
8788
@@ -98,7 +99,8 @@ let
9899 && !stdenv.hostPlatform.isMusl
99100 && builtins.compareVersions defaults.ghc.version "8.10.2" >= 0;
100101
101− ghc = if enableDWARF then defaults.ghc.dwarf else defaults.ghc;
102+ ghc = if enableDWARF then defaults.ghc.dwarf else
103+ if smallAddressSpace then defaults.ghc.smallAddressSpace else defaults.ghc;
102104 setup = if enableDWARF then drvArgs.setup.dwarf else drvArgs.setup;
103105
104106 # TODO fix cabal wildcard support so hpack wildcards can be mapped to cabal wildcards
@@ -176,7 +178,7 @@ let
176178 [ "--with-gcc=${stdenv.cc.targetPrefix}cc"
177179 ] ++
178180 # BINTOOLS
179− (if stdenv.hostPlatform.isLinux
181+ (if stdenv.hostPlatform.isLinux && !stdenv.hostPlatform.isAndroid # might be better check to see if cc is clang/llvm?
180182 # use gold as the linker on linux to improve link times
181183 then [
182184 "--with-ld=${stdenv.cc.bintools.targetPrefix}ld.gold"
compiler/ghc/configured-src.nix+3−1
@@ -10,7 +10,7 @@
1010, targetCC
1111, enableIntegerSimple, targetGmp
1212, enableDWARF, elfutils
13−, ncurses, targetLibffi, libiconv
13+, ncurses, targetLibffi, libiconv, targetIconv
1414, disableLargeAddressSpace
1515, buildMK
1616}:
@@ -105,6 +105,8 @@ stdenv.mkDerivation (rec {
105105 "--with-gmp-includes=${targetGmp.dev}/include" "--with-gmp-libraries=${targetGmp.out}/lib"
106106 ] ++ lib.optional (targetPlatform == hostPlatform && hostPlatform.libc != "glibc" && !targetPlatform.isWindows) [
107107 "--with-iconv-includes=${libiconv}/include" "--with-iconv-libraries=${libiconv}/lib"
108+ ] ++ lib.optional (targetPlatform != hostPlatform) [
109+ "--with-iconv-includes=${targetIconv}/include" "--with-iconv-libraries=${targetIconv}/lib"
108110 ] ++ lib.optionals (targetPlatform != hostPlatform) [
109111 "--enable-bootstrap-with-devel-snapshot"
110112 ] ++ lib.optionals (disableLargeAddressSpace) [
compiler/ghc/default.nix+17−4
@@ -44,6 +44,9 @@ let self =
4444, # Whether to build terminfo. Musl fails to build terminfo as ncurses seems to be linked to glibc
4545 enableTerminfo ? !stdenv.targetPlatform.isWindows && !stdenv.targetPlatform.isMusl
4646
47+, # Wheter to build in NUMA support
48+ enableNUMA ? true
49+
4750, # What flavour to build. An empty string indicates no
4851 # specific flavour and falls back to ghc default values.
4952 ghcFlavour ? lib.optionalString haskell-nix.haskellLib.isCrossTarget (
@@ -85,6 +88,8 @@ let
8588
8689 targetGmp = targetPackages.gmp or gmp;
8790
91+ targetIconv = targetPackages.libiconv or libiconv;
92+
8893 # TODO(@Ericson2314) Make unconditional
8994 targetPrefix = lib.optionalString
9095 (targetPlatform != hostPlatform)
@@ -121,13 +126,16 @@ let
121126 ''
122127 # musl doesn't have a system-linker. Only on x86, and on x86 we need it, as
123128 # our elf linker for x86_64 is broken.
124− + lib.optionalString (targetPlatform.isMusl && !targetPlatform.isx86) ''
129+ + lib.optionalString (targetPlatform.isAndroid || (targetPlatform.isMusl && !targetPlatform.isx86)) ''
125130 compiler_CONFIGURE_OPTS += --flags=-dynamic-system-linker
126131 ''
127132 # While split sections are now enabled by default in ghc 8.8 for windows,
128133 # the seem to lead to `too many sections` errors when building base for
129134 # profiling.
130− + lib.optionalString targetPlatform.isWindows ''
135+ #
136+ # It appears that loading split sections through iserv on qemu-aarch64, is
137+ # particularly slow. Let's disable them for now.
138+ + lib.optionalString (targetPlatform.isWindows || targetPlatform.isAndroid) ''
131139 SplitSections = NO
132140 '' + lib.optionalString (!enableLibraryProfiling) ''
133141 BUILD_PROF_LIBS = NO
@@ -138,7 +146,7 @@ let
138146 ++ [targetLibffi]
139147 ++ lib.optional (!enableIntegerSimple) gmp
140148 ++ lib.optional (platform.libc != "glibc" && !targetPlatform.isWindows) libiconv
141− ++ lib.optional (platform.isLinux && !platform.isAarch32) numactl;
149+ ++ lib.optional (enableNUMA && platform.isLinux && !platform.isAarch32 && !platform.isAndroid) numactl;
142150
143151 toolsForTarget =
144152 if hostPlatform == buildPlatform then
@@ -161,7 +169,7 @@ let
161169 targetCC
162170 enableIntegerSimple targetGmp
163171 enableDWARF elfutils
164− ncurses targetLibffi libiconv
172+ ncurses targetLibffi libiconv targetIconv
165173 disableLargeAddressSpace
166174 buildMK
167175 ;
@@ -331,6 +339,11 @@ stdenv.mkDerivation (rec {
331339 enableDWARF = stdenv.targetPlatform.isLinux
332340 && builtins.compareVersions ghc-version "8.10.2" >= 0;
333341 });
342+
343+ # The same GHC, but without the large (1TB) address space reservation
344+ smallAddressSpace = lib.makeOverridable self (args // {
345+ disableLargeAddressSpace = true;
346+ });
334347 } // extra-passthru;
335348
336349 meta = {
flake.nix+3−2
@@ -57,7 +57,7 @@
5757 };
5858 };
5959
60− outputs = { self, nixpkgs, nixpkgs-unstable, flake-utils, ... }@inputs:
60+ outputs = { self, nixpkgs, nixpkgs-unstable, nixpkgs-2105, flake-utils, ... }@inputs:
6161 let compiler = "ghc884";
6262 config = import ./config.nix;
6363 in {
@@ -110,8 +110,9 @@
110110 # supported by haskell.nix, e.g. with remote builders, in order to check this flake.
111111 # If you want to run the tests for just your platform, run `./test/tests.sh` or
112112 # `nix-build -A checks.$PLATFORM`
113− } // flake-utils.lib.eachSystem [ "x86_64-linux" "x86_64-darwin" ] (system: {
113+ } // flake-utils.lib.eachSystem [ "x86_64-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin" ] (system: {
114114 legacyPackages = (self.internal.compat { inherit system; }).pkgs;
115+ legacyPackagesUnstable = (self.internal.compat { inherit system; }).pkgs-unstable;
115116
116117 # FIXME: Currently `nix flake check` requires `--impure` because coverage-golden
117118 # (and maybe other tests) import projects that use builtins.currentSystem
lib/default.nix+2−2
@@ -251,10 +251,10 @@ in {
251251 # In most cases we do not want to treat musl as a cross compiler.
252252 # For instance when building ghc we want to include ghci.
253253 isCrossHost = stdenv.hostPlatform != stdenv.buildPlatform
254− && !(stdenv.buildPlatform.isLinux && stdenv.hostPlatform.isMusl && stdenv.buildPlatform.isx86 && stdenv.hostPlatform.isx86);
254+ && !(stdenv.buildPlatform.isLinux && stdenv.hostPlatform.isMusl && stdenv.buildPlatform.linuxArch == stdenv.hostPlatform.linuxArch);
255255 # This is the same as isCrossHost but for use when building ghc itself
256256 isCrossTarget = stdenv.targetPlatform != stdenv.hostPlatform
257− && !(stdenv.hostPlatform.isLinux && stdenv.targetPlatform.isMusl && stdenv.hostPlatform.isx86 && stdenv.targetPlatform.isx86);
257+ && !(stdenv.hostPlatform.isLinux && stdenv.targetPlatform.isMusl && stdenv.hostPlatform.linuxArch == stdenv.targetPlatform.linuxArch);
258258 # Native musl build-host-target combo
259259 isNativeMusl = stdenv.hostPlatform.isMusl
260260 && stdenv.buildPlatform == stdenv.hostPlatform
overlays/android.nixnew file+28
@@ -0,0 +1,28 @@
1+final: prev: prev.lib.optionalAttrs prev.stdenv.hostPlatform.isAndroid ({
2+ # we really only want the static one.
3+ libiconv = (prev.libiconv.override { enableStatic = true; enableShared = false; }).overrideAttrs(_: {
4+ hardeningDisable = [ "fortify" "stackprotector" "format" ];
5+ # For some reason building libiconv with nixpgks android setup produces
6+ # LANGINFO_CODESET to be found, which is not compatible with android sdk 23;
7+ # so we'll patch up iconv to not include that.
8+ postConfigure = ''
9+ echo "#undef HAVE_LANGINFO_CODESET" >> libcharset/config.h
10+ echo "#undef HAVE_LANGINFO_CODESET" >> lib/config.h
11+ '';
12+ # my current thinking is that this is due to the android toolchain using r23, api30.
13+ });
14+ libffi = prev.libffi.overrideAttrs (_: {
15+ dontDisableStatic = true;
16+
17+ hardeningDisable = [ "fortify" "stackprotector" "format" ];
18+ # see libiconv. We want to target a lower minsdk
19+ postConfigure = ''
20+ echo "#undef HAVE_MEMFD_CREATE" >> aarch64-unknown-linux-android/fficonfig.h
21+ '';
22+ });
23+ gmp6 = (prev.gmp6.override { withStatic = true; }).overrideAttrs(_: {
24+ hardeningDisable = [ "fortify" "stackprotector" "format" ];
25+ });
26+}) // prev.lib.optionalAttrs prev.stdenv.targetPlatform.isAndroid ({
27+ bionic = prev.bionic.override { enableStatic = true; };
28+})
overlays/bootstrap.nix+9
@@ -192,6 +192,15 @@ in {
192192 ++ fromUntil "8.10" "8.10.8" ./patches/ghc/MR6595-nonmoving-mutvar.patch # https://gitlab.haskell.org/ghc/ghc/-/merge_requests/6595
193193 ++ fromUntil "8.10" "8.11" ./patches/ghc/ghc-8.10-global-unique-counters-in-rts.patch # backport of https://gitlab.haskell.org/ghc/ghc/-/commit/9a28680d2e23e7b25dd7254a439aea31dfae32d5
194194 ++ fromUntil "8.10" "8.10.8" ./patches/ghc/issue-18708.patch # https://gitlab.haskell.org/ghc/ghc/-/merge_requests/6554
195+ # the following is a partial reversal of https://gitlab.haskell.org/ghc/ghc/-/merge_requests/4391, to address haskell.nix#1227
196+ ++ final.lib.optional (versionAtLeast "8.10" && versionLessThan "9.0" && final.targetPlatform.isAarch64) ./patches/ghc/mmap-next.patch
197+ ++ final.lib.optional (versionAtLeast "8.10" && versionLessThan "9.0" && final.targetPlatform.isAndroid) ./patches/ghc/rts-android-jemalloc-qemu.patch
198+ ++ final.lib.optional (versionAtLeast "8.10" && versionLessThan "9.0" && final.targetPlatform.isAndroid) ./patches/ghc/stack-protector-symbols.patch
199+ ++ final.lib.optional (versionAtLeast "8.10" && versionLessThan "9.0" && final.targetPlatform.isAndroid) ./patches/ghc/libraries-prim-os-android.patch
200+ ++ final.lib.optional (versionAtLeast "8.10" && versionLessThan "9.0" && final.targetPlatform.isAndroid) ./patches/ghc/ghc-rts-linker-condbr.patch
201+ ++ final.lib.optional (versionAtLeast "8.10" && versionLessThan "9.0" && final.targetPlatform.isAndroid) ./patches/ghc/ghc-8.10.7-linker-weak-and-common.patch
202+ ++ final.lib.optional (versionAtLeast "8.10" && versionLessThan "9.0" && final.targetPlatform.isAndroid) ./patches/ghc/libc-memory-symbols.patch
203+ ++ final.lib.optional (versionAtLeast "8.10" && versionLessThan "9.0" && final.targetPlatform.isAndroid) ./patches/ghc/android-base-needs-iconv.patch
195204 ;
196205 in ({
197206 ghc844 = final.callPackage ../compiler/ghc {
overlays/default.nix+2
@@ -14,6 +14,7 @@ let
1414 windows = import ./windows.nix;
1515 armv6l-linux = import ./armv6l-linux.nix;
1616 musl = import ./musl.nix;
17+ android = import ./android.nix;
1718 tools = import ./tools.nix;
1819 emscripten = import ./emscripten.nix;
1920 nix-prefetch-git-minimal = import ./nix-prefetch-git-minimal.nix;
@@ -47,6 +48,7 @@ let
4748 windows
4849 armv6l-linux
4950 musl
51+ android
5052 tools
5153 emscripten
5254 nix-prefetch-git-minimal
overlays/linux-cross.nix+1−1
@@ -35,7 +35,7 @@ let
3535 unset configureFlags
3636 PORT=$((5000 + $RANDOM % 5000))
3737 (>&2 echo "---> Starting remote-iserv on port $PORT")
38− ${qemu}/bin/qemu-${qemuSuffix} ${remote-iserv}/bin/remote-iserv tmp $PORT &
38+ ${qemu}/bin/qemu-${qemuSuffix} ${remote-iserv.override (lib.optionalAttrs hostPlatform.isAndroid { setupBuildFlags = ["--ghc-option=-optl-static" ];})}/bin/remote-iserv tmp $PORT &
3939 (>&2 echo "---| remote-iserv should have started on $PORT")
4040 RISERV_PID="$!"
4141 ${iserv-proxy}/bin/iserv-proxy $@ 127.0.0.1 "$PORT"
overlays/patches/ghc/android-base-needs-iconv.patchnew file+14
@@ -0,0 +1,14 @@
1+diff --git a/libraries/base/base.cabal b/libraries/base/base.cabal
2+index d0ffe1b..d5b8552 100644
3+--- a/libraries/base/base.cabal
4++++ b/libraries/base/base.cabal
5+@@ -410,6 +410,9 @@ Library
6+ if os(freebsd)
7+ cc-options: -DLIBICONV_PLUG
8+
9++ if os(android)
10++ extra-libraries: iconv
11++
12+ -- We need to set the unit id to base (without a version number)
13+ -- as it's magic.
14+ ghc-options: -this-unit-id base
overlays/patches/ghc/ghc-8.10.7-linker-weak-and-common.patchnew file+189
@@ -0,0 +1,189 @@
1+diff --git a/rts/Linker.c b/rts/Linker.c
2+index 10b0764..7d473f8 100644
3+--- a/rts/Linker.c
4++++ b/rts/Linker.c
5+@@ -273,7 +273,7 @@ int ghciInsertSymbolTable(
6+ RtsSymbolInfo *pinfo = lookupStrHashTable(table, key);
7+ if (!pinfo) /* new entry */
8+ {
9+- pinfo = stgMallocBytes(sizeof (*pinfo), "ghciInsertToSymbolTable");
10++ pinfo = stgCallocBytes(1, sizeof (*pinfo), "ghciInsertToSymbolTable");
11+ pinfo->value = data;
12+ pinfo->owner = owner;
13+ pinfo->weak = weak;
14+@@ -1329,7 +1329,7 @@ mkOc( pathchar *path, char *image, int imageSize,
15+ ObjectCode* oc;
16+
17+ IF_DEBUG(linker, debugBelch("mkOc: start\n"));
18+- oc = stgMallocBytes(sizeof(ObjectCode), "mkOc(oc)");
19++ oc = stgCallocBytes(1, sizeof(ObjectCode), "mkOc(oc)");
20+
21+ oc->info = NULL;
22+
23+@@ -1496,12 +1496,12 @@ preloadObjectFile (pathchar *path)
24+ // reading the file, and then we misalign image on purpose so
25+ // that the actual sections end up aligned again.
26+ misalignment = machoGetMisalignment(f);
27+- image = stgMallocBytes(fileSize + misalignment, "loadObj(image)");
28++ image = stgCallocBytes(1, fileSize + misalignment, "loadObj(image)");
29+ image += misalignment;
30+
31+ # else /* !defined(darwin_HOST_OS) */
32+
33+- image = stgMallocBytes(fileSize, "loadObj(image)");
34++ image = stgCallocBytes(1, fileSize, "loadObj(image)");
35+
36+ #endif
37+
38+diff --git a/rts/LinkerInternals.h b/rts/LinkerInternals.h
39+index f326a84..a846bf5 100644
40+--- a/rts/LinkerInternals.h
41++++ b/rts/LinkerInternals.h
42+@@ -209,6 +209,10 @@ typedef struct _ObjectCode {
43+ int n_segments;
44+ Segment *segments;
45+
46++ // COMMON section
47++ void * common_mem;
48++ unsigned long common_size;
49++
50+ //
51+ // Garbage collection fields
52+ //
53+diff --git a/rts/linker/Elf.c b/rts/linker/Elf.c
54+index fdfe87a..c3f9110 100644
55+--- a/rts/linker/Elf.c
56++++ b/rts/linker/Elf.c
57+@@ -325,6 +325,15 @@ ocDeinit_ELF(ObjectCode * oc)
58+ stgFree(oc->info);
59+ oc->info = NULL;
60+ }
61++ if(NULL != oc->common_mem) {
62++#if RTS_LINKER_USE_MMAP
63++ munmap(oc->common_mem, oc->common_size);
64++#else
65++ stgFree(oc->common_mem);
66++#endif
67++ }
68++ oc->common_mem = NULL;
69++ oc->common_size = 0;
70+ }
71+
72+ /*
73+@@ -861,14 +870,17 @@ ocGetNames_ELF ( ObjectCode* oc )
74+ for (size_t j = 0; j < symTab->n_symbols; j++) {
75+ ElfSymbol *symbol = &symTab->symbols[j];
76+ if (SHN_COMMON == symTab->symbols[j].elf_sym->st_shndx) {
77+- common_size += symbol->elf_sym->st_size;
78++ // st_value holds the alignment. Adding alignment always
79++ // should give us some wiggle room to get alignment right.
80++ common_size += symbol->elf_sym->st_size + symbol->elf_sym->st_value;
81+ }
82+ }
83+ }
84+- void * common_mem = NULL;
85++ oc->common_mem = NULL;
86++ oc->common_size = common_size;
87+ if(common_size > 0) {
88+- common_mem = mmapAnonForLinker(common_size);
89+- if (common_mem == NULL) {
90++ oc->common_mem = mmapAnonForLinker(common_size);
91++ if (oc->common_mem == NULL) {
92+ barf("ocGetNames_ELF: Failed to allocate memory for SHN_COMMONs");
93+ }
94+ }
95+@@ -909,9 +921,10 @@ ocGetNames_ELF ( ObjectCode* oc )
96+ if (shndx == SHN_COMMON) {
97+ isLocal = false;
98+ ASSERT(common_used < common_size);
99+- ASSERT(common_mem);
100+- symbol->addr = (void*)((uintptr_t)common_mem + common_used);
101+- common_used += symbol->elf_sym->st_size;
102++ ASSERT(oc->common_mem);
103++ int alignment = symbol->elf_sym->st_value-1;
104++ symbol->addr = (void*)(((uintptr_t)oc->common_mem + common_used + alignment) & ~alignment);
105++ common_used = (uintptr_t)symbol->addr - (uintptr_t)oc->common_mem + symbol->elf_sym->st_size;
106+ ASSERT(common_used <= common_size);
107+
108+ IF_DEBUG(linker,
109+@@ -925,7 +938,9 @@ ocGetNames_ELF ( ObjectCode* oc )
110+ || ELF_ST_BIND(symbol->elf_sym->st_info) == STB_WEAK
111+ )
112+ /* and not an undefined symbol */
113+- && shndx != SHN_UNDEF
114++ && (shndx != SHN_UNDEF
115++ /* unless it's weak */
116++ || (shndx == SHN_UNDEF && ELF_ST_BIND(symbol->elf_sym->st_info) == STB_WEAK))
117+ /* and not in a "special section" */
118+ && (shndx < SHN_LORESERVE
119+ #if defined(SHN_XINDEX)
120+@@ -963,33 +978,20 @@ ocGetNames_ELF ( ObjectCode* oc )
121+ isWeak = ELF_ST_BIND(symbol->elf_sym->st_info)
122+ == STB_WEAK;
123+ }
124+- }
125+-
126+- /* And the decision is ... */
127+-
128+- if (symbol->addr != NULL) {
129+- ASSERT(nm != NULL);
130+- /* Acquire! */
131+- if (!isLocal) {
132+-
133+- if (isWeak == HS_BOOL_TRUE) {
134+- setWeakSymbol(oc, nm);
135+- }
136+- if (!ghciInsertSymbolTable(oc->fileName, symhash,
137+- nm, symbol->addr, isWeak, oc)
138+- ) {
139+- goto fail;
140+- }
141+- oc->symbols[curSymbol++].name = nm;
142+- oc->symbols[curSymbol].addr = symbol->addr;
143+- }
144+- } else {
145+- /* Skip. */
146++ } else if (ELF_ST_BIND(symbol->elf_sym->st_info) == STB_WEAK
147++ && shndx == SHN_UNDEF
148++ && (ELF_ST_TYPE(symbol->elf_sym->st_info) == STT_FUNC
149++ || ELF_ST_TYPE(symbol->elf_sym->st_info) == STT_OBJECT
150++ || ELF_ST_TYPE(symbol->elf_sym->st_info) == STT_NOTYPE)) {
151++ symbol->addr = NULL;
152++ isLocal = false;
153++ isWeak = true;
154++ } else {
155++ /* skip this symbol */
156+ IF_DEBUG(linker,
157+ debugBelch("skipping `%s'\n",
158+ nm)
159+ );
160+-
161+ /*
162+ debugBelch(
163+ "skipping bind = %d, type = %d, secno = %d `%s'\n",
164+@@ -999,7 +1001,24 @@ ocGetNames_ELF ( ObjectCode* oc )
165+ nm
166+ );
167+ */
168+- }
169++ continue;
170++ }
171++
172++ /* And the decision is ... */
173++ ASSERT(nm != NULL);
174++ /* Acquire! */
175++ if (!isLocal) {
176++
177++ if (isWeak == HS_BOOL_TRUE) {
178++ setWeakSymbol(oc, nm);
179++ }
180++ if (!ghciInsertSymbolTable(oc->fileName, symhash,
181++ nm, symbol->addr, isWeak, oc)) {
182++ goto fail;
183++ }
184++ oc->symbols[curSymbol++].name = nm;
185++ oc->symbols[curSymbol].addr = symbol->addr;
186++ }
187+ }
188+ }
189+ }
overlays/patches/ghc/ghc-rts-linker-condbr.patchnew file+73
@@ -0,0 +1,73 @@
1+diff --git a/rts/linker/elf_plt_aarch64.c b/rts/linker/elf_plt_aarch64.c
2+index 11354a6..6b27a2c 100644
3+--- a/rts/linker/elf_plt_aarch64.c
4++++ b/rts/linker/elf_plt_aarch64.c
5+@@ -25,6 +25,7 @@ const size_t stubSizeAarch64 = 5 * 4;
6+ */
7+ bool needStubForRelAarch64(Elf_Rel * rel) {
8+ switch(ELF64_R_TYPE(rel->r_info)) {
9++ case COMPAT_R_AARCH64_CONDBR19:
10+ case COMPAT_R_AARCH64_CALL26:
11+ case COMPAT_R_AARCH64_JUMP26:
12+ return true;
13+@@ -34,6 +35,7 @@ bool needStubForRelAarch64(Elf_Rel * rel) {
14+ }
15+ bool needStubForRelaAarch64(Elf_Rela * rela) {
16+ switch(ELF64_R_TYPE(rela->r_info)) {
17++ case COMPAT_R_AARCH64_CONDBR19:
18+ case COMPAT_R_AARCH64_CALL26:
19+ case COMPAT_R_AARCH64_JUMP26:
20+ return true;
21+diff --git a/rts/linker/elf_reloc_aarch64.c b/rts/linker/elf_reloc_aarch64.c
22+index 0e11585..9d93369 100644
23+--- a/rts/linker/elf_reloc_aarch64.c
24++++ b/rts/linker/elf_reloc_aarch64.c
25+@@ -104,8 +104,24 @@ encodeAddendAarch64(Section * section, Elf_Rel * rel, int64_t addend) {
26+ break;
27+ }
28+ /* - control flow relocations */
29++ case COMPAT_R_AARCH64_CONDBR19: { /* relocate b.* ... */
30++ // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
31++ // 0 1 0 1 0 1 0 0 [ imm19 ...
32++ //
33++ // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
34++ // ... imm19 ] 0 [ cond ]
35++ assert(isInt64(19+2, addend));
36++ *(inst_t *)P = (*(inst_t *)P & 0xff00001f)
37++ | ((uint32_t)(addend << (5-2)) & 0x00ffffe0);
38++ break;
39++ }
40+ case COMPAT_R_AARCH64_JUMP26: /* relocate b ... */
41+ case COMPAT_R_AARCH64_CALL26: { /* relocate bl ... */
42++ // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
43++ // 0|1 0 0 1 0 1 [ imm26 ...
44++
45++ // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
46++ // ... imm26 ]
47+ assert(isInt64(26+2, addend)); /* X in range */
48+ *(inst_t *)P = (*(inst_t *)P & 0xfc000000) /* keep upper 6 (32-6)
49+ * bits */
50+@@ -221,6 +237,23 @@ computeAddend(ObjectCode * oc, Section * section, Elf_Rel * rel,
51+ case COMPAT_R_AARCH64_ADD_ABS_LO12_NC:
52+ /* type: static, class: aarch64, op: S + A */
53+ return (S + A) & 0xfff;
54++ case COMPAT_R_AARCH64_CONDBR19: {
55++ int64_t V = S + A - P;
56++ if(!isInt64(19+2, V)) {
57++ /* need a stub */
58++ /* check if we already have that stub */
59++ if(findStub(section, (void**)&S, 0)) {
60++ /* did not find it. Crete a new stub. */
61++ if(makeStub(section, (void**)&S, 0)) {
62++ abort(/* could not find or make stub */);
63++ }
64++ }
65++
66++ V = S + A -P;
67++ assert(isInt64(19+2, V));
68++ }
69++ return V;
70++ }
71+ case COMPAT_R_AARCH64_JUMP26:
72+ case COMPAT_R_AARCH64_CALL26: {
73+ // S+A-P
overlays/patches/ghc/libc-memory-symbols.patchnew file+43
@@ -0,0 +1,43 @@
1+diff --git a/rts/Linker.c b/rts/Linker.c
2+index 062159f..727fe74 100644
3+--- a/rts/Linker.c
4++++ b/rts/Linker.c
5+@@ -340,6 +340,20 @@ int ghciInsertSymbolTable(
6+ call this function again to trigger the duplicate error. */
7+ return 1;
8+ }
9++ else if(strncmp(key, "fprintf", 7) == 0
10++ || strncmp(key, "printf", 6) == 0
11++ || strncmp(key, "sprintf", 7) == 0
12++ || strncmp(key, "snprintf", 8) == 0
13++ || strncmp(key, "getauxval", 9) == 0
14++ || strncmp(key, "free", 4) == 0
15++ || strncmp(key, "malloc", 6) == 0
16++ || strncmp(key, "calloc", 6) == 0
17++ || strncmp(key, "realloc", 7) == 0
18++ || strncmp(key, "reallocarray", 12) == 0
19++ ) {
20++ /* symbols we link aginst the libc we link ghc or iserv against */
21++ return 1;
22++ }
23+
24+ pathchar* archiveName = NULL;
25+ debugBelch(
26+diff --git a/rts/RtsSymbols.c b/rts/RtsSymbols.c
27+index 2acd634..b86b516 100644
28+--- a/rts/RtsSymbols.c
29++++ b/rts/RtsSymbols.c
30+@@ -1039,7 +1039,12 @@
31+ SymI_HasProto(printf) \
32+ SymI_HasProto(fprintf) \
33+ SymI_HasProto(sprintf) \
34+- SymI_HasProto(snprintf)
35++ SymI_HasProto(snprintf) \
36++ SymI_HasProto(free) \
37++ SymI_HasProto(malloc) \
38++ SymI_HasProto(calloc) \
39++ SymI_HasProto(realloc) \
40++ SymI_HasProto(reallocarray)
41+ #else
42+ #define RTS_STACK_PROTECTOR_SYMBOLS
43+ #define RTS_LIBC_SYMBOLS
overlays/patches/ghc/libraries-prim-os-android.patchnew file+13
@@ -0,0 +1,13 @@
1+diff --git a/libraries/ghc-prim/ghc-prim.cabal b/libraries/ghc-prim/ghc-prim.cabal
2+index 2bd51c0..aeaeacc 100644
3+--- a/libraries/ghc-prim/ghc-prim.cabal
4++++ b/libraries/ghc-prim/ghc-prim.cabal
5+@@ -67,7 +67,7 @@ Library
6+ -- on Windows. Required because of mingw32.
7+ extra-libraries: user32, mingw32, mingwex
8+
9+- if os(linux)
10++ if os(linux) || os(android) || os(linux-android)
11+ -- we need libm, but for musl and other's we might need libc, as libm
12+ -- is just an empty shell.
13+ extra-libraries: gcc, c, m
overlays/patches/ghc/mmap-next.patchnew file+70
@@ -0,0 +1,70 @@
1+diff --git a/rts/Linker.c b/rts/Linker.c
2+index f1c0db7c92..fa3bb41292 100644
3+--- a/rts/Linker.c
4++++ b/rts/Linker.c
5+@@ -1004,6 +1004,42 @@ resolveSymbolAddr (pathchar* buffer, int size,
6+ }
7+
8+ #if RTS_LINKER_USE_MMAP
9++
10++/* -----------------------------------------------------------------------------
11++ Occationally we depend on mmap'd region being close to already mmap'd regions.
12++
13++ Our static in-memory linker may be restricted by the architectures relocation
14++ range. E.g. aarch64 has a +-4GB range for PIC code, thus we'd preferrably
15++ get memory for the linker close to existing mappings. mmap on it's own is
16++ free to return any memory location, independent of what the preferred
17++ location argument indicates.
18++
19++ For example mmap (via qemu) might give you addresses all over the available
20++ memory range if the requested location is already occupied.
21++
22++ mmap_next will do a linear search from the start page upwards to find a
23++ suitable location that is as close as possible to the locations (proivded
24++ via the first argument).
25++ -------------------------------------------------------------------------- */
26++
27++void*
28++mmap_next(void *addr, size_t length, int prot, int flags, int fd, off_t offset) {
29++ if(addr == NULL) return mmap(addr, length, prot, flags, fd, offset);
30++ // we are going to look for up to pageSize * 1024 * 1024 (4GB) from the
31++ // address.
32++ size_t pageSize = getPageSize();
33++ for(int i = (uintptr_t)addr & (pageSize-1) ? 1 : 0; i < 1024*1024; i++) {
34++ void *target = (void*)(((uintptr_t)addr & ~(pageSize-1))+(i*pageSize));
35++ void *mem = mmap(target, length, prot, flags, fd, offset);
36++ if(mem == NULL) return mem;
37++ if(mem == target) return mem;
38++ munmap(mem, length);
39++ IF_DEBUG(linker && (i % 1024 == 0),
40++ debugBelch("mmap_next failed to find suitable space in %p - %p\n", addr, target));
41++ }
42++ return NULL;
43++}
44++
45+ //
46+ // Returns NULL on failure.
47+ //
48+@@ -1035,8 +1071,8 @@ mmap_again:
49+ debugBelch("mmapForLinker: \tflags %#0x\n",
50+ MAP_PRIVATE | tryMap32Bit | fixed | flags));
51+
52+- result = mmap(map_addr, size, prot,
53+- MAP_PRIVATE|tryMap32Bit|fixed|flags, fd, offset);
54++ result = mmap_next(map_addr, size, prot,
55++ MAP_PRIVATE|tryMap32Bit|fixed|flags, fd, offset);
56+
57+ if (result == MAP_FAILED) {
58+ sysErrorBelch("mmap %" FMT_Word " bytes at %p",(W_)size,map_addr);
59+diff --git a/rts/LinkerInternals.h b/rts/LinkerInternals.h
60+index f326a840b5..ef7918588d 100644
61+--- a/rts/LinkerInternals.h
62++++ b/rts/LinkerInternals.h
63+@@ -14,6 +14,7 @@
64+
65+ #if RTS_LINKER_USE_MMAP
66+ #include <sys/mman.h>
67++void* mmap_next(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
68+ #endif
69+
70+ #include "BeginPrivate.h"
overlays/patches/ghc/rts-android-jemalloc-qemu.patchnew file+48
@@ -0,0 +1,48 @@
1+diff --git a/rts/Hpc.c b/rts/Hpc.c
2+index abf8543..fd4a153 100644
3+--- a/rts/Hpc.c
4++++ b/rts/Hpc.c
5+@@ -137,7 +137,7 @@ readTix(void) {
6+ tmpModule -> hashNo = (unsigned int)expectWord64();
7+ ws();
8+ tmpModule -> tickCount = (int)expectWord64();
9+- tmpModule -> tixArr = (StgWord64 *)calloc(tmpModule->tickCount,sizeof(StgWord64));
10++ tmpModule -> tixArr = (StgWord64 *)stgCallocBytes(tmpModule->tickCount,sizeof(StgWord64), "Hpc.readTix");
11+ ws();
12+ expect('[');
13+ ws();
14+diff --git a/rts/RtsUtils.c b/rts/RtsUtils.c
15+index b9ddb2a..c7a4a5a 100644
16+--- a/rts/RtsUtils.c
17++++ b/rts/RtsUtils.c
18+@@ -106,6 +106,11 @@ stgCallocBytes (size_t count, size_t size, char *msg)
19+ rtsConfig.mallocFailHook((W_) count*size, msg);
20+ stg_exit(EXIT_INTERNAL_ERROR);
21+ }
22++ // If we run under qemu with jemalloc, calloc is not guaranteed
23++ // to zero memory.
24++ // - https://giters.com/jemalloc/jemalloc/issues/1844
25++ // - https://lists.nongnu.org/archive/html/qemu-devel/2020-05/msg03119.html
26++ memset(space, 0, count*size);
27+ return space;
28+ }
29+
30+diff --git a/rts/linker/elf_plt.c b/rts/linker/elf_plt.c
31+index 9cd42ef..70817d8 100644
32+--- a/rts/linker/elf_plt.c
33++++ b/rts/linker/elf_plt.c
34+@@ -1,4 +1,5 @@
35+ #include "Rts.h"
36++#include "RtsUtils.h"
37+ #include "elf_plt.h"
38+
39+ #include <stdbool.h>
40+@@ -51,7 +52,7 @@ makeStub(Section * section,
41+ void* * addr,
42+ uint8_t flags) {
43+
44+- Stub * s = calloc(1, sizeof(Stub));
45++ Stub * s = stgCallocBytes(1, sizeof(Stub), "makeStub");
46+ ASSERT(s != NULL);
47+ s->target = *addr;
48+ s->flags = flags;
overlays/patches/ghc/stack-protector-symbols.patchnew file+67
@@ -0,0 +1,67 @@
1+diff --git a/rts/RtsSymbols.c b/rts/RtsSymbols.c
2+index edb9385..2acd634 100644
3+--- a/rts/RtsSymbols.c
4++++ b/rts/RtsSymbols.c
5+@@ -32,6 +32,9 @@
6+ #include <elf.h> /* _DYNAMIC */
7+ #endif
8+
9++#include <sys/auxv.h>
10++#include <stdio.h>
11++
12+ /* -----------------------------------------------------------------------------
13+ * Symbols to be inserted into the RTS symbol table.
14+ */
15+@@ -1025,6 +1028,23 @@
16+ #define RTS_LINKER_SYMBOLS
17+ #endif
18+
19++#if !defined(DYNAMIC)
20++#define RTS_STACK_PROTECTOR_SYMBOLS \
21++ SymI_NeedsProto(__stack_chk_fail) \
22++ SymI_HasProto(pthread_atfork) \
23++ SymI_HasProto_redirect(__stack_chk_fail_local, __stack_chk_fail, true)
24++#define RTS_LIBC_SYMBOLS \
25++ SymI_NeedsProto(abort) \
26++ SymI_HasProto(getauxval) \
27++ SymI_HasProto(printf) \
28++ SymI_HasProto(fprintf) \
29++ SymI_HasProto(sprintf) \
30++ SymI_HasProto(snprintf)
31++#else
32++#define RTS_STACK_PROTECTOR_SYMBOLS
33++#define RTS_LIBC_SYMBOLS
34++#endif
35++
36+ /* entirely bogus claims about types of these symbols */
37+ #define SymI_NeedsProto(vvv) extern void vvv(void);
38+ #define SymI_NeedsDataProto(vvv) extern StgWord vvv[];
39+@@ -1054,6 +1074,8 @@ RTS_OPENBSD_ONLY_SYMBOLS
40+ RTS_LIBGCC_SYMBOLS
41+ RTS_LIBFFI_SYMBOLS
42+ RTS_LINKER_SYMBOLS
43++RTS_STACK_PROTECTOR_SYMBOLS
44++RTS_LIBC_SYMBOLS
45+ #undef SymI_NeedsProto
46+ #undef SymI_NeedsDataProto
47+ #undef SymI_HasProto
48+@@ -1107,6 +1129,8 @@ RtsSymbolVal rtsSyms[] = {
49+ RTS_LIBGCC_SYMBOLS
50+ RTS_LIBFFI_SYMBOLS
51+ RTS_LINKER_SYMBOLS
52++ RTS_STACK_PROTECTOR_SYMBOLS
53++ RTS_LIBC_SYMBOLS
54+ SymI_HasDataProto(nonmoving_write_barrier_enabled)
55+ #if defined(darwin_HOST_OS) && defined(i386_HOST_ARCH)
56+ // dyld stub code contains references to this,
57+@@ -1114,6 +1138,10 @@ RtsSymbolVal rtsSyms[] = {
58+ // lazy pointers as nonlazy.
59+ { "dyld_stub_binding_helper", (void*)0xDEADBEEF, false },
60+ #endif
61++ { "__loader_add_thread_local_dtor", (void*)(&RTS_DYNAMIC), false },
62++ { "__loader_remove_thread_local_dtor", (void*)(&RTS_DYNAMIC), false },
63++ { "__rela_iplt_start", (void*)(&RTS_DYNAMIC), false },
64++ { "__rela_iplt_end", (void*)(&RTS_DYNAMIC), false },
65+ { "_DYNAMIC", (void*)(&RTS_DYNAMIC), false },
66+ { 0, 0, false } /* sentinel */
67+ };