summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik de Castro Lopo <erikd@mega-nerd.com>2015-10-11 16:48:11 +1100
committerBen Gamari <ben@smart-cactus.org>2015-10-22 14:26:46 +0200
commit6149b1e3c86c3d56a2c3f2eac71a1dfc5f856573 (patch)
treed099d4a96b0e42a0aed22a0e93182c003b5aaaf5
parent05c350606fe6f73a6aa7c4d141f4059d4c209384 (diff)
downloadhaskell-6149b1e3c86c3d56a2c3f2eac71a1dfc5f856573.tar.gz
Fix GHCi on Arm (#10375).
Arm has two instruction sets, Arm and Thumb, and an execution mode for each. Executing Arm code in Thumb mode or vice-versa will likely result in an Illegal instruction exception. Furthermore, Haskell code compiled via LLVM was generating Arm instructions while C code compiled via GCC was generating Thumb code by default. When these two object code types were being linked by the system linker, all was fine, because the system linker knows how to jump and call from one instruction set to the other. The first problem was with GHCi's object code loader which did not know about Thumb vs Arm. When loading an object file `StgCRun` would jump into the loaded object which could change the mode causing a crash after it returned. This was fixed by forcing all C code to generate Arm instructions by passing `-marm` to GCC. The second problem was the `mkJumpToAddr` function which was generating Thumb instructions. Changing that to generate Arm instructions instead results in a working GHCi on Arm. Test Plan: validate on x86_64 and arm Reviewers: bgamari, austin, hvr Subscribers: thomie Differential Revision: https://phabricator.haskell.org/D1323 GHC Trac Issues: #10375
-rw-r--r--aclocal.m416
-rw-r--r--compiler/ghci/ByteCodeItbls.hs10
-rw-r--r--compiler/llvmGen/LlvmCodeGen/Ppr.hs2
-rw-r--r--rts/Linker.c5
4 files changed, 23 insertions, 10 deletions
diff --git a/aclocal.m4 b/aclocal.m4
index c17a7d512b..d19a66e79a 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -565,10 +565,18 @@ AC_DEFUN([FPTOOLS_SET_C_LD_FLAGS],
$3="$$3 -D_HPUX_SOURCE"
$5="$$5 -D_HPUX_SOURCE"
;;
- arm*linux* | \
- aarch64*linux* )
- # On arm/linux, aarch64/linux, arm/android and aarch64/android, tell
- # gcc to link using the gold linker.
+ arm*linux*)
+ # On arm/linux and arm/android, tell gcc to generate Arm
+ # instructions (ie not Thumb) and to link using the gold linker.
+ # Forcing LD to be ld.gold is done in FIND_LD m4 macro.
+ $2="$$2 -marm"
+ $3="$$3 -fuse-ld=gold -Wl,-z,noexecstack"
+ $4="$$4 -z noexecstack"
+ ;;
+
+ aarch64*linux*)
+ # On aarch64/linux and aarch64/android, tell gcc to link using the
+ # gold linker.
# Forcing LD to be ld.gold is done in FIND_LD m4 macro.
$3="$$3 -fuse-ld=gold -Wl,-z,noexecstack"
$4="$$4 -z noexecstack"
diff --git a/compiler/ghci/ByteCodeItbls.hs b/compiler/ghci/ByteCodeItbls.hs
index 5cc537a21a..fee50ee5db 100644
--- a/compiler/ghci/ByteCodeItbls.hs
+++ b/compiler/ghci/ByteCodeItbls.hs
@@ -219,17 +219,17 @@ mkJumpToAddr dflags a = case platformArch (targetPlatform dflags) of
, fromIntegral ((w64 `shiftR` 32) .&. 0x0000FFFF) ]
ArchARM { } ->
- -- Generates Thumb sequence,
+ -- Generates Arm sequence,
-- ldr r1, [pc, #0]
-- bx r1
--
-- which looks like:
-- 00000000 <.addr-0x8>:
- -- 0: 4900 ldr r1, [pc] ; 8 <.addr>
- -- 4: 4708 bx r1
+ -- 0: 00109fe5 ldr r1, [pc] ; 8 <.addr>
+ -- 4: 11ff2fe1 bx r1
let w32 = fromIntegral (funPtrToInt a) :: Word32
- in Left [ 0x49, 0x00
- , 0x47, 0x08
+ in Left [ 0x00, 0x10, 0x9f, 0xe5
+ , 0x11, 0xff, 0x2f, 0xe1
, byte0 w32, byte1 w32, byte2 w32, byte3 w32]
arch ->
diff --git a/compiler/llvmGen/LlvmCodeGen/Ppr.hs b/compiler/llvmGen/LlvmCodeGen/Ppr.hs
index 5dd27ab33b..97e4393674 100644
--- a/compiler/llvmGen/LlvmCodeGen/Ppr.hs
+++ b/compiler/llvmGen/LlvmCodeGen/Ppr.hs
@@ -52,7 +52,7 @@ moduleLayout = sdocWithPlatform $ \platform ->
$+$ text "target triple = \"x86_64-linux-gnu\""
Platform { platformArch = ArchARM {}, platformOS = OSLinux } ->
text "target datalayout = \"e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:64:128-a0:0:64-n32\""
- $+$ text "target triple = \"arm-unknown-linux-gnueabi\""
+ $+$ text "target triple = \"armv6-unknown-linux-gnueabihf\""
Platform { platformArch = ArchARM {}, platformOS = OSAndroid } ->
text "target datalayout = \"e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:64:128-a0:0:64-n32\""
$+$ text "target triple = \"arm-unknown-linux-androideabi\""
diff --git a/rts/Linker.c b/rts/Linker.c
index 343719a9b5..68f1f59dd4 100644
--- a/rts/Linker.c
+++ b/rts/Linker.c
@@ -5569,6 +5569,11 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
#ifdef arm_HOST_ARCH
// Thumb instructions have bit 0 of symbol's st_value set
is_target_thm = S & 0x1;
+
+ if (is_target_thm)
+ errorBelch( "Symbol `%s' requires Thumb linkage which is not "
+ "currently supported.\n", symbol );
+
T = sym.st_info & STT_FUNC && is_target_thm;
// Make sure we clear bit 0. Strictly speaking we should have done