Opened 5 years ago

Closed 8 months ago

#2841 closed bug (worksforme)

Ghci + foreign export declarations result in undefined symbols

Reported by: fasta Owned by: ezyang
Priority: normal Milestone:
Component: Compiler (FFI) Version: 6.10.1
Keywords: Cc:
Operating System: Linux Architecture: Unknown/Multiple
Type of failure: None/Unknown Difficulty: Unknown
Test Case: Blocked By:
Blocking: Related Tickets:

Description

When using ghci and foreign export declarations, calling any function, _even_ test, will result in an unknown symbol error.

Another bug is that the compiler is not purely functional in the sense that without history (see below) it is possible for it to work in one instance, but even then it doesn't. GHCi should have the property that if X works in a state S of the OS (collection of files, etc), then it should work in all states S', obtained by adding extra stuff to S, but not modifying anything. Currently, GHCi is breaking this fundamental property.

$ ghci New.hs
*Main> foo 1
<interactive>: New_stub.o: unknown symbol `Main_zdffoozuavi_closure'
{-# LANGUAGE ForeignFunctionInterface #-}

-- save in a file New.hs

foreign export ccall foo :: Int -> IO Int -- add this line and ghci will return something like New_stub.o: unknown symbol `Main_zdffoozuaIc_closure'

-- if you first try without the line, it works. If you still have stub files in the current directory, it will fail with the same message as before. 

foo :: Int -> IO Int
foo = return . length .  f

f :: Int -> [Int]
f 0 = []
f n = n:(f (n-1))

test = 1

Attachments (1)

0001-Implement-.init-.init_array-support-for-ELF.patch (4.2 KB) - added by ezyang 8 months ago.
Patch for ELF

Download all attachments as: .zip

Change History (10)

comment:1 Changed 5 years ago by igloo

  • Difficulty set to Unknown
  • Milestone set to _|_

This is documented as not working:

but I can't find a bug report for it, so I'll leave this one open.

comment:2 Changed 5 years ago by fasta

From the FAQ

Unfortunately not. We haven't implemented it yet. Please compile any offending modules by hand before loading them into GHCi.

This information is not correct. Recompiling the offending modules by hand and then loading them in ghci does work, but calling one of the exported functions results in unknown symbol `_GLOBAL_OFFSET_TABLE_'.

comment:3 Changed 5 years ago by simonmar

please create a new ticket describing exactly the sequence of actions that lead to the error. I haven't been able to reproduce the error you mentioned from the information you give above.

~/scratch > cat 2841.hs
{-# LANGUAGE ForeignFunctionInterface #-}
module M2841 where

-- save in a file New.hs

foreign export ccall foo :: Int -> IO Int -- add this line and ghci will return something like New_stub.o: unknown symbol `Main_zdffoozuaIc_closure'

-- if you first try without the line, it works. If you still have stub files in the current directory, it will fail with the same message as before. 

foo :: Int -> IO Int
foo = return . length .  f

f :: Int -> [Int]
f 0 = []
f n = n:(f (n-1))

test = 1
~/scratch > ghc -c 2841.hs
compilation IS NOT required
~/scratch > ghci 2841.hs
GHCi, version 6.10.1: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer ... linking ... done.
Loading package base ... linking ... done.
$HOME/.ghci
Ok, modules loaded: M2841.
Prelude M2841> foo 3
3
Prelude M2841> f 1
[1]
Prelude M2841> test
1
Prelude M2841> 

comment:4 Changed 5 years ago by fasta

I wrongly assumed that one only needs the stub files in a compiled state. If one has <module>.o then indeed the workaround works.

comment:5 Changed 8 months ago by ezyang

  • Owner set to ezyang
  • Type of failure set to None/Unknown

It's not explicitly stated anywhere, but the reason why foreign exports are listed as not working under GHCi is because foreign exports are implemented using __attribute__(constructor), but GHC's linker doesn't run the functions in init/init_array. #7746 is related (profiling uses init as well). I believe this should work fine if you use dynamic objects, in which case the system dynamic linker will properly handle this invocation for you.

Last edited 8 months ago by ezyang (previous) (diff)

Changed 8 months ago by ezyang

Patch for ELF

comment:6 Changed 8 months ago by ezyang

I don't have a Mac or Windows GHC build machine handy, so I haven't attempted to do it for those platforms, but it should be quite similar.

comment:7 Changed 8 months ago by ezyang

  • Blocking 8199 added

comment:8 Changed 8 months ago by simonmar

Awesome! Does this fix #5435?

comment:9 Changed 8 months ago by ezyang

  • Blocking 8199 removed
  • Resolution set to worksforme
  • Status changed from new to closed

Actually, looking at the original bug here, it seems unrelated to the patchset I'm working on, and #5435 seems to be the right place to hang these patches. I can't reproduce the original symbol error, so I'm going to close this worksforme.

Note: See TracTickets for help on using tickets.