Skip to content
Snippets Groups Projects

This set of libraries is progress towards implementing an way to interact with Haskell's RTS from another Haskell program.

For example, you could use this library to

  • Implement a memory profiler, written in Haskell
  • Precisely analyse other heap properties such as retainers

How does it work?

We call the process we want to debug the debuggee and the process which does the debugging the debugger. Whilst the debuggee is running it calls the C function start which creates a unix domain socket (/tmp/ghc-debug for now). The debugger starts and connects to the socket.

Once the debugger is connected it can send requests to the debuggee to control and inspect the RTS. The requests API is specified as follows:

-- | A request sent from the debugger to the debuggee parametrized on the result type.
data Request a where
    -- | Request protocol version
    RequestVersion :: Request Word64
    -- | Pause the debuggee.
    RequestPause :: Request ()
    -- | Resume the debuggee.
    RequestResume :: Request ()
    -- | Request the debuggee's root pointers.
    RequestRoots :: Request [ClosurePtr]
    -- | Request a set of closures.
    RequestClosures :: [ClosurePtr] -> Request [GenClosure InfoTablePtr ClosurePtr]
    -- | Request a set of info tables.
    RequestInfoTables :: [InfoTablePtr] -> Request [StgInfoTable]

So far only the version, pause and resume functions are tested (and work).

We will add some more functions to this interface, for example, a request to call findPtr and also a way to mark objects of interest so we can retrieve their addresses in the same manner as RequestRoots.

How do I use it?

In short, you don't, yet.

The project needs to built with a development version of GHC from this branch.

Then you can use normal cabal commands to build this library.

In order to make a process debuggable it needs to call the socket initialisation function start, see the test-debug executable for exactly how to do this.

Testing

There are two test executables test-debug and debugger which are used to test the library.

test-debug is an interruptable program which prints out an incrementing counter each second. debugger starts and immediately attaches to test-debug and makes some requests. So the way to test the library is to first start test-debug and then start debugger. There are lots of helpeful traces to see what's going on with each process.