Skip to content

Commit 563e18c

Browse files
authored
Unbreak Aarch32 cross-compilation (#411)
* Use quick-cross for cross-compilation to avoid qemu crashes * Bring over patches from my old fork of iohk-nix * Expand Aarch32 patches to ghc-8.6.5 * Turn off shared builds when cross-compilging for linux ARM * Update compiler/ghc/default.nix
1 parent 1f744d1 commit 563e18c

File tree

7 files changed

+152
-5
lines changed

7 files changed

+152
-5
lines changed

compiler/ghc/default.nix

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
, # What flavour to build. An empty string indicates no
4242
# specific flavour and falls back to ghc default values.
4343
ghcFlavour ? stdenv.lib.optionalString (stdenv.targetPlatform != stdenv.hostPlatform)
44-
(if useLLVM then "perf-cross" else "perf-cross-ncg")
44+
(if useLLVM then "quick-cross" else "perf-cross-ncg")
4545

4646
, # Whether to disable the large address space allocator
4747
# necessary fix for iOS: https://www.reddit.com/r/haskell/comments/4ttdz1/building_an_osxi386_to_iosarm64_cross_compiler/d5qvd67/
@@ -330,4 +330,4 @@ in let configured-src = stdenv.mkDerivation (rec {
330330
noAuditTmpdir = true;
331331
});
332332

333-
in drv
333+
in drv

overlays/bootstrap.nix

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ in {
9999
++ self.lib.optional (version == "8.6.4") ./patches/ghc/ghc-8.6.4-better-plusSimplCountErrors.patch
100100
++ self.lib.optional (versionAtLeast "8.6.4" && self.stdenv.isDarwin) ./patches/ghc/ghc-macOS-loadArchive-fix.patch
101101
++ self.lib.optional (versionAtLeast "8.4.4" && self.stdenv.isDarwin) ./patches/ghc/ghc-darwin-gcc-version-fix.patch
102+
++ self.lib.optional (versionAtLeast "8.6.4" && versionOlder "8.8") ./patches/ghc/ghc-8.6.4-prim-no-arm-atomics.patch
103+
++ self.lib.optional (versionAtLeast "8.6.4" && versionOlder "8.8") ./patches/ghc/global-offset-table.patch
104+
++ self.lib.optional (versionAtLeast "8.6.4" && versionOlder "8.8") ./patches/ghc/global-offset-table-2.patch
102105
;
103106
in ({
104107
ghc844 = self.callPackage ../compiler/ghc {

overlays/ghc.nix

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ self: super: with super;
44
ghcPkgOverrides = {
55
enableShared = super.stdenv.targetPlatform == super.stdenv.hostPlatform;
66
enableIntegerSimple = false;
7+
} // lib.optionalAttrs self.stdenv.hostPlatform.isAarch32 {
8+
enableRelocatableStaticLibs = false;
79
};
810
ghcDrvOverrides = drv: {
9-
hardeningDisable = (drv.hardeningDisable or []) ++ [ "stackprotector" "format" ];
11+
hardeningDisable = (drv.hardeningDisable or []) ++ [ "stackprotector" "format" ] ++ lib.optionals super.stdenv.hostPlatform.isAarch32 [ "pic" "pie" ];
1012
};
1113
in {
1214
haskell-nix = let
@@ -28,4 +30,4 @@ self: super: with super;
2830
compiler = lib.mapAttrs (_name: overrideCompiler)
2931
(lib.filterAttrs (name: _value: needsPatches name) super.haskell-nix.compiler);
3032
};
31-
}
33+
}

overlays/linux-cross.nix

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,6 @@ let
6969
echo "================================================================="
7070
'';
7171

72-
in { inherit preCheck postCheck configureFlags setupBuildFlags testFlags; }
72+
enableShared = lib.mkDefault (!isLinuxCross);
73+
74+
in { inherit preCheck postCheck configureFlags setupBuildFlags testFlags enableShared; }
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
diff --git a/libraries/ghc-prim/cbits/atomic.c b/libraries/ghc-prim/cbits/atomic.c
2+
index 0a471b31ad..ea9612060c 100644
3+
--- a/libraries/ghc-prim/cbits/atomic.c
4+
+++ b/libraries/ghc-prim/cbits/atomic.c
5+
@@ -1,3 +1,4 @@
6+
+#if !defined(arm_HOST_ARCH)
7+
#include "Rts.h"
8+
9+
// Fallbacks for atomic primops on byte arrays. The builtins used
10+
@@ -418,3 +419,4 @@ hs_atomicwrite64(StgWord x, StgWord64 val)
11+
while (!__sync_bool_compare_and_swap((StgWord64 *) x, *(StgWord64 *) x, (StgWord64) val));
12+
#endif
13+
}
14+
+#endif
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
From 358b0f69c752464c7a6d75ce44c95ff3d0ddcdea Mon Sep 17 00:00:00 2001
2+
From: Edward Amsden <[email protected]>
3+
Date: Thu, 16 May 2019 19:41:30 -0400
4+
Subject: [PATCH] Lookup _GLOBAL_OFFSET_TABLE by symbol->addr when doing
5+
relocations
6+
7+
---
8+
rts/linker/Elf.c | 2 +-
9+
1 file changed, 1 insertion(+), 1 deletion(-)
10+
11+
diff --git a/rts/linker/Elf.c b/rts/linker/Elf.c
12+
index c6f82af72a..349de86227 100644
13+
--- a/rts/linker/Elf.c
14+
+++ b/rts/linker/Elf.c
15+
@@ -1064,7 +1064,7 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
16+
} else {
17+
symbol = &stab->symbols[ELF_R_SYM(info)];
18+
/* First see if it is a local symbol. */
19+
- if (ELF_ST_BIND(symbol->elf_sym->st_info) == STB_LOCAL) {
20+
+ if (ELF_ST_BIND(symbol->elf_sym->st_info) == STB_LOCAL || strncmp(symbol->name, "_GLOBAL_OFFSET_TABLE_", 21) == 0) {
21+
S = (Elf_Addr)symbol->addr;
22+
} else {
23+
S_tmp = lookupSymbol_( symbol->name );
24+
--
25+
2.17.1
26+
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
From 8e2c350f870f8cd99122c62efd023820e563e935 Mon Sep 17 00:00:00 2001
2+
From: Moritz Angermann <[email protected]>
3+
Date: Thu, 16 May 2019 13:35:31 +0800
4+
Subject: [PATCH] Add _GLOBAL_OFFSET_TABLE_ support
5+
6+
This adds lookup logic for _GLOBAL_OFFSET_TABLE_ as well as
7+
relocation logic for R_ARM_BASE_PREL and R_ARM_GOT_BREL which
8+
the gnu toolchain (gas, gcc, ...) prefers to produce. Apparently
9+
recent llvm toolchains will produce those as well.
10+
---
11+
rts/linker/Elf.c | 33 +++++++++++++++++++++++++++++++--
12+
rts/linker/elf_got.c | 10 +++++++---
13+
2 files changed, 38 insertions(+), 5 deletions(-)
14+
15+
diff --git a/rts/linker/Elf.c b/rts/linker/Elf.c
16+
index b647d207cb..c6f82af72a 100644
17+
--- a/rts/linker/Elf.c
18+
+++ b/rts/linker/Elf.c
19+
@@ -1023,6 +1023,19 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
20+
return 1;
21+
}
22+
23+
+ /* The following nomenclature is used for the operation:
24+
+ * - S -- (when used on its own) is the address of the symbol.
25+
+ * - A -- is the addend for the relocation.
26+
+ * - P -- is the address of the place being relocated (derived from r_offset).
27+
+ * - Pa - is the adjusted address of the place being relocated, defined as (P & 0xFFFFFFFC).
28+
+ * - T -- is 1 if the target symbol S has type STT_FUNC and the symbol addresses a Thumb instruction; it is 0 otherwise.
29+
+ * - B(S) is the addressing origin of the output segment defining the symbol S. The origin is not required to be the
30+
+ * base address of the segment. This value must always be word-aligned.
31+
+ * - GOT_ORG is the addressing origin of the Global Offset Table (the indirection table for imported data addresses).
32+
+ * This value must always be word-aligned. See §4.6.1.8, Proxy generating relocations.
33+
+ * - GOT(S) is the address of the GOT entry for the symbol S.
34+
+ */
35+
+
36+
for (j = 0; j < nent; j++) {
37+
Elf_Addr offset = rtab[j].r_offset;
38+
Elf_Addr info = rtab[j].r_info;
39+
@@ -1117,19 +1130,35 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
40+
# endif
41+
42+
# ifdef arm_HOST_ARCH
43+
- case COMPAT_R_ARM_ABS32:
44+
+ case COMPAT_R_ARM_ABS32: /* (S + A) | T */
45+
// Specified by Linux ARM ABI to be equivalent to ABS32
46+
case COMPAT_R_ARM_TARGET1:
47+
*(Elf32_Word *)P += S;
48+
*(Elf32_Word *)P |= T;
49+
break;
50+
51+
- case COMPAT_R_ARM_REL32:
52+
+ case COMPAT_R_ARM_REL32: /* ((S + A) | T) – P */
53+
*(Elf32_Word *)P += S;
54+
*(Elf32_Word *)P |= T;
55+
*(Elf32_Word *)P -= P;
56+
break;
57+
58+
+ case COMPAT_R_ARM_BASE_PREL: /* B(S) + A – P */
59+
+ {
60+
+ int32_t A = *pP;
61+
+ // bfd used to encode sb (B(S)) as 0.
62+
+ *(uint32_t *)P += 0 + A - P;
63+
+ break;
64+
+ }
65+
+
66+
+ case COMPAT_R_ARM_GOT_BREL: /* GOT(S) + A – GOT_ORG */
67+
+ {
68+
+ int32_t A = *pP;
69+
+ void* GOT_S = symbol->got_addr;
70+
+ *(uint32_t *)P = (uint32_t) GOT_S + A - (uint32_t) oc->info->got_start;
71+
+ break;
72+
+ }
73+
+
74+
case COMPAT_R_ARM_CALL:
75+
case COMPAT_R_ARM_JUMP24:
76+
{
77+
diff --git a/rts/linker/elf_got.c b/rts/linker/elf_got.c
78+
index 10ea25b98b..162fff3161 100644
79+
--- a/rts/linker/elf_got.c
80+
+++ b/rts/linker/elf_got.c
81+
@@ -83,9 +83,13 @@ fillGot(ObjectCode * oc) {
82+
if(0x0 == symbol->addr) {
83+
symbol->addr = lookupSymbol_(symbol->name);
84+
if(0x0 == symbol->addr) {
85+
- errorBelch("Failed to lookup symbol: %s\n",
86+
- symbol->name);
87+
- return EXIT_FAILURE;
88+
+ if(0 == strncmp(symbol->name,"_GLOBAL_OFFSET_TABLE_",21)) {
89+
+ symbol->addr = oc->info->got_start;
90+
+ } else {
91+
+ errorBelch("Failed to lookup symbol: %s\n",
92+
+ symbol->name);
93+
+ return EXIT_FAILURE;
94+
+ }
95+
}
96+
} else {
97+
// we already have the address.
98+
--
99+
2.21.0
100+

0 commit comments

Comments
 (0)