Curious Windows GHCi linker behaviour .o vs. .dll
Herbert Valerio Riedel
hvriedel at gmail.com
Sat Oct 11 13:24:02 UTC 2014
Hello *,
I assume this is a well known issue to MSYS2/Windows developers, so I
hope somebody may be able to provide more insight for me to better
understand the underlying problem of
https://github.com/haskell/time/issues/2
So the prototype for tzset() is simply
void tzset(void);
and it's defined in `msvcrt.dll` as far as I can tell;
Consider the following trivial program:
module Main where
foreign import ccall unsafe "time.h tzset" c_tzset :: IO ()
main :: IO()
main = c_tzset
When compiled with GHC 7.8.3, the resulting executable works and has the
following tzset-symbols:
$ nm tz.o | grep tzset
U tzset
$ nm tz.exe | grep tzset
000000000050e408 I __imp_tzset
00000000004afc40 T tzset
However, when loaded into GHCi, the RTS linker fails to find `tzset`:
$ ghci tz.hs
WARNING: GHCi invoked via 'ghci.exe' in *nix-like shells (cygwin-bash, in particular)
doesn't handle Ctrl-C well; use the 'ghcii.sh' shell wrapper instead
GHCi, version 7.8.3: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
[1 of 1] Compiling Main ( tz.hs, interpreted )
ByteCodeLink: can't find label
During interactive linking, GHCi couldn't find the following symbol:
tzset
...
However, when I prefix a `_` to the symbol-name in the FFI import, i.e.
foreign import ccall unsafe "time.h tzset" c_tzset :: IO ()
Now, GHCi happily loads the module and is apparently able to resolve the
`tzset` symbol:
$ ghci tz.hs
WARNING: GHCi invoked via 'ghci.exe' in *nix-like shells (cygwin-bash, in particular)
doesn't handle Ctrl-C well; use the 'ghcii.sh' shell wrapper instead
GHCi, version 7.8.3: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
[1 of 1] Compiling Main ( tz.hs, interpreted )
Ok, modules loaded: Main.
*Main>
Moreover, compiling and running the program still works, and the
additional underscore is visible in `nm` as well:
$ nm tz.o | grep tzset
U _tzset
$ nm tz.exe | grep tzset
000000000050e558 I __imp__tzset
00000000004b8050 T _tzset
What's going on here? Why does one need to add an artificial underscore
to FFI imported symbols for GHCi to resolve symbols? Is this a bug?
Cheers,
hvr
More information about the ghc-devs
mailing list