1. Dumping out compiler intermediate structures
I think the order in which the options are listed is along the same line as the real order of the passes.
For example, ghc -ddump-to-file -ddump-asm a.hs would dump the assembly to file a.dump-asm.
The option "-ddump-to-file" tells ghc to dump to a file, instead of to stdout. This feature does not seem to be documented.
2. The runtime system
GHC compiles Haskell source code down to native code, and then links in necessary Haskell libraries (written in Haskell) and RTS (written in C and C--). To see what libraries are linked in, pass -v to ghc.
Therefore, the lifetime of a Haskell program roughly looks like this:
The C Runtime (CRT) gets started first, which passes control to main. For C programs, main is defined by programmers; while for Haskell programs, main is defined by RTS in rts/Main.c. Next, RTS is initialized by calling startupHaskell in RtsStartup.c. Eventually, the computation that resides in mainIO_closure (a macro defined in Prelude.h that resolves to &ZCMain_main_closure) is kicked off from real_main. The closure data structure is defined as StgClosure/HaskellObj in includes/RtsAPI.h and includes/Closures.h.
In fact, because RTS is C code, you can play with its Makefile to produce a libHSrts.a with debugging information in it. Then you can link your Haskell program with this library to walk through the source of RTS in gdb.
3. Static linking vs dynamic linking
The Haskell libraries are statically linked by default. In fact, shared Haskell libraries are only supported on Mac OS X. There are good reasons for that.
The C libraries are not statically linked by default. To produce a completely static binary, run ghc -optl-static -optl-pthread a.hs. Any string following "-optl" is passed to gcc for the final linking step. Without "-optl-pthread", you get errors like this:
wh5a@flitwick:/tmp$ ghc -optl-static a.hs
compilation IS NOT required
/usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../lib/librt.a(timer_create.o): In function `timer_create':
(.text+0x111): undefined reference to `pthread_once'
/usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../lib/librt.a(timer_create.o): In function `timer_create':
(.text+0x165): undefined reference to `pthread_attr_init'
/usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../lib/librt.a(timer_create.o): In function `timer_create':
(.text+0x1ab): undefined reference to `pthread_attr_setdetachstate'
/usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../lib/librt.a(timer_routines.o): In function `__start_helper_thread':
(.text+0x49): undefined reference to `pthread_attr_init'
/usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../lib/librt.a(timer_routines.o): In function `__start_helper_thread':
(.text+0x5c): undefined reference to `pthread_attr_setstacksize'
/usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../lib/librt.a(timer_routines.o): In function `__start_helper_thread':
(.text+0xab): undefined reference to `pthread_create'
/usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../lib/librt.a(timer_routines.o): In function `__start_helper_thread':
(.text+0xde): undefined reference to `pthread_attr_destroy'
/usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../lib/librt.a(timer_routines.o): In function `__start_helper_thread':
(.text+0xfa): undefined reference to `pthread_atfork'
/usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../lib/librt.a(timer_routines.o): In function `timer_helper_thread':
(.text+0x19d): undefined reference to `pthread_exit'
/usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../lib/librt.a(timer_routines.o): In function `timer_helper_thread':
(.text+0x1e5): undefined reference to `pthread_create'
/usr/lib/gcc/i486-linux-gnu/4.2.3/libgcc_eh.a(unwind-dw2.o): In function `uw_init_context_1':
(.text+0x1904): undefined reference to `pthread_once'
collect2: ld returned 1 exit status