Skip to content

Compiled FFI static imports are invalid when imported in GHCI

When I try to use the FFI syntax for static storage, only modules running in interpreted mode (ie GHCI) work properly. Compiled modules have invalid pointers, and do not work. I asked in #haskell, and tommd suggested that this might be an architecture-dependent error in GHC.

Here's the code used to reproduce the problem. I'm using sys_siglist declared in <signal.h>, since it's similar to how I originally found the problem, but I suspect this will occur for any static data.

Given the following modules:

-- A.hs
{-# LANGUAGE ForeignFunctionInterface #-}
module A where
import Foreign
import Foreign.C

foreign import ccall "&sys_siglist"
    siglist_a :: Ptr CString
-- B.hs
{-# LANGUAGE ForeignFunctionInterface #-}
module B where
import Foreign
import Foreign.C

foreign import ccall "&sys_siglist"
    siglist_b :: Ptr CString
-- Main.hs
{-# LANGUAGE ForeignFunctionInterface #-}
module Main where
import Foreign
import Foreign.C
import A
import B

foreign import ccall "&sys_siglist"
    siglist_main :: Ptr CString

main = do
    putStrLn $ "siglist_a    = " ++ show siglist_a
    putStrLn $ "siglist_b    = " ++ show siglist_b
    putStrLn $ "siglist_main = " ++ show siglist_main

    peekSiglist "a   " siglist_a
    peekSiglist "b   " siglist_b
    peekSiglist "main" siglist_main

peekSiglist name siglist = do
    ptr <- peekElemOff siglist 2
    str <- maybePeek peekCString ptr
    putStrLn $ "siglist_" ++ name ++ "[2] = " ++ show str

Running the application via GHCI gives correct output:

$ runhaskell Main.hs 
siglist_a    = 0x00007f53a948fe00
siglist_b    = 0x00007f53a948fe00
siglist_main = 0x00007f53a948fe00
siglist_a   [2] = Just "Interrupt"
siglist_b   [2] = Just "Interrupt"
siglist_main[2] = Just "Interrupt"

However, if one of them is compiled, its pointer will be invalid:

$ ghc -c A.hs
$ runhaskell Main.hs 
siglist_a    = 0x0000000040378918
siglist_b    = 0x00007fe7c029ce00
siglist_main = 0x00007fe7c029ce00
siglist_a   [2] = Nothing
siglist_b   [2] = Just "Interrupt"
siglist_main[2] = Just "Interrupt"

I thought this might be related to

Trac metadata
Trac field Value
Version 6.12.1
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler (FFI)
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information