[commit: ghc] master: Fix GHCi on Arm (#10375). (933adc0)

git at git.haskell.org git at git.haskell.org
Wed Oct 14 23:10:00 UTC 2015


Repository : ssh://git@git.haskell.org/ghc

On branch  : master
Link       : http://ghc.haskell.org/trac/ghc/changeset/933adc0f31164cb651d11ecfcfe612ac429f714f/ghc

>---------------------------------------------------------------

commit 933adc0f31164cb651d11ecfcfe612ac429f714f
Author: Erik de Castro Lopo <erikd at mega-nerd.com>
Date:   Sun Oct 11 16:48:11 2015 +1100

    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


>---------------------------------------------------------------

933adc0f31164cb651d11ecfcfe612ac429f714f
 aclocal.m4                          | 16 ++++++++++++----
 compiler/ghci/ByteCodeItbls.hs      | 10 +++++-----
 compiler/llvmGen/LlvmCodeGen/Ppr.hs |  2 +-
 rts/Linker.c                        |  5 +++++
 4 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/aclocal.m4 b/aclocal.m4
index 0c2633a..2282b99 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -568,10 +568,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 cd31acb..a01fcd8 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 1a9373b..d7ddf80 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 0a13e6f..355b33a 100644
--- a/rts/Linker.c
+++ b/rts/Linker.c
@@ -5564,6 +5564,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



More information about the ghc-commits mailing list