Opened 4 years ago

Closed 4 years ago

#4036 closed bug (duplicate)

Compiled FFI static imports are invalid when imported in GHCI

Reported by: jmillikin Owned by:
Priority: normal Milestone:
Component: Compiler (FFI) Version: 6.12.1
Keywords: Cc:
Operating System: Linux Architecture: x86_64 (amd64)
Type of failure: Incorrect result at runtime Difficulty:
Test Case: Blocked By:
Blocking: Related Tickets:

Description

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

Change History (2)

comment:1 Changed 4 years ago by jmillikin

(sorry; hit enter too soon)

I thought this might be related to the somewhat complex type of sys_siglist, but it also occurs even if I just have a simple C function which returns char*.

Additionally, if all* of the code is compiled, the program works as expected. It's only if some is compiled and some is interpreted that errors occur:

$ ghc --make Main.hs
$ ./Main
siglist_a = 0x0000000000683260
siglist_b = 0x0000000000683260
siglist_main = 0x0000000000683260
siglist_a [2] = Just "Interrupt"
siglist_b [2] = Just "Interrupt"
siglist_main[2] = Just "Interrupt"

comment:2 Changed 4 years ago by simonmar

  • Resolution set to duplicate
  • Status changed from new to closed

Thanks for the report; this is a known bug (#781) that is hard to fix. You can compile your code with -fPIC to work around it.

Note: See TracTickets for help on using tickets.