Currently I'm getting some test failures for WAY=dyn. I'm not posting the full list at the moment as I'm not convinced it's quite accurate. I'll post an update later.
I've investigated ffi002. This test ffi exports a Haskell foo function and calls it from a C main function. Two things go wrong when building this with -dynamic. 1. We do not compile the _stub.c with -fPIC. Let's first be clear what is happening: compile ffi002.hs -> ffi002.o with -dynamic compile ffi002_c.c -> ffi002_c.o without any special options compile ffi002_stub.c -> ffi002_stub.o without any special options link ffi002.o ffi002_c.o ffi002_stub.o with libHSrts.so, etc to make a binary. The symbol "main" lives in ffi002_c.c. When compiling the .hs to a .o we have to use -dynamic otherwise the final binary does not link. When ghc calls gcc to compile ffi002_stub.c it does not use -fPIC. When we do this then in the final link we end up with a bad reference to a symbol from the base lib: dynamic variable `base_GHCziTopHandler_runIO_closure' is zero size ffi002_stub.o(.text+0x44): unresolvable R_X86_64_32 relocation against symbol `base_GHCziTopHandler_runIO_closure' I'm not sure why this happens. However if we compile ffi002_stub.c using -fPIC or even -fPIE (or -fpic or -fpie) then it all links fine. On the other hand it doesn't seem to matter at all that we compile ffi002_c.c without -fPIC/-fpie even though it also references symbols from the rts shared lib. The only difference is that base_GHCziTopHandler_runIO_closure is a symbol to data rather than to a function. So, it'd be good if we understood what is going on, but the solution looks fairly simple, we just have ghc compile the _stub.c file using -fPIC when ghc itself is invoked with -dynamic (it already does in the case of -fPIC). 2. The main symbol lives in the libHSrts.so which fails if we're using a C main function The C main() function lives in the rts. It initialises the rts and calls the Haskell Main.main function (that is, the rts embeds a reference to a symbol that will be found in code we compile and link later). Now ghc also supports -no-hs-main. That lets us link using ghc but have main() in a C file that we wrote. Normally with static libs everything works out ok. That's because the linker picks the main symbol from our local .o file and ignores the main from the rts. In fact it doesn't even include the main from the rts into the final binary. That works perfectly because if it did, then there would be undefined symbols because remember that the main in the rts refers to the Haskell Main.main which doesn't necessarily exist. But, with shared libs we can't just not include the main from the rts into the final binary. The libHSrts.so was linked already and we us the whole thing rather than copying bits out of it as we do with .a static libs. So now we have the problem that the rts.so refers to the Haskell Main.main which really does not exist. And so we cannot link our program (if we try and cheat the static linker then we just get caught by the dynamic linker, which is fair enough, after all the dynamic linker doesn't know that nobody is ever going to call the main in the rts.). So we need another approach for where to put main. Ian suggests that we put it in the object file for the Main module when compiling it. Or we could do what gcc does which is to keep a special .o file around which contains just the initialisation code (the real OS entry point that goes on to call main) and link that in unless using -no-hs-main. This not just a problem for the rare programs where we want a C main. It also means we cannot have Haskell shared libs that we load up as plugins in other program (unless we make a dummy Main.main). So this is something I'll be trying to solve. Suggestions welcome. Duncan _______________________________________________ Cvs-ghc mailing list [email protected] http://www.haskell.org/mailman/listinfo/cvs-ghc
