Skip to content
Robert O'Callahan edited this page Aug 20, 2024 · 29 revisions

Using rr in an IDE

rr implements the standard gdb server interface, and also can present the gdb command-line interface. This means it can be used in integrated development environments (IDEs) which support GUI debugging based on gdb/gdbserver.

Known to work:

If your IDE does not run on the same machine as the replay: see debugging from a different host.

Setting up Visual Studio Code

  1. Install Visual Studio Code
  2. Install the C/C++ extension (https://code.visualstudio.com/docs/languages/cpp)
  3. Open the directory where your source code reside.
  4. Create a debugging configuration from Debug view (Ctrl+Shift+D) and add the following configuration (this was for debugging firefox, adjust as per your requirements)
    {
        "name": "rr",
        "type": "cppdbg",
        "request": "launch",
        "program": "${workspaceRoot}/../obj-ff-dbg/dist/bin/firefox",
        "args": [],
        "miDebuggerServerAddress": "localhost:50505",
        "stopAtEntry": false,
        "cwd": "${workspaceRoot}/../obj-ff-dbg/dist/bin",
        "environment": [],
        "externalConsole": true,
        "linux": {
          "MIMode": "gdb",
          "setupCommands": [
            {
                "description": "Setup to resolve symbols",
                "text": "set sysroot /",
                "ignoreFailures": false
            }
          ]
        },
        "osx": {
          "MIMode": "gdb"
        },
        "windows": {
          "MIMode": "gdb"
        }
    }
  1. Install rr >= 5.0.
  2. Record something using rr.
  3. Start rr with rr replay -s 50505 -k
  4. Launch the rr debugging configuration in VS code
  5. To reverse-execute, open the Debugger Console tab (Shift+Ctrl+Y) and enter manual commands such as -exec reverse-continue (-exec rc), -exec reverse-step (-exec rs), etc
  6. When rewinding the code, the display isn't refreshed. Step-in in the code once will fix that.

You can set breakpoints like you would with a normal debugging session. To set hardware watchers, in the debug console enter the rr command preceded by -exec (like -exec watch -l mVar)

Setting up CLion

Use at CLion version 2017.1 or greater, with rr version 5.0 or greater.

  1. After you install rr, run the following to save a copy of the gdb initialization script for rr to your home directory. You should also re-run this after installing a new rr release.

    $ rr gdbinit > ~/.rr_gdbinit
  2. Add the following to the .gdbinit file in your home directory. Create a new one if it does not exist.

    # get around CLion/QtCreator not supporting target extended-remote
    define target remote
    target extended-remote $arg0
    end
    
    define target hook-extended-remote
    source ~/.rr_gdbinit
    end
    
    # optional: prevent gdb asking for confirmation
    # when invoking the run command in gdb
    set confirm off
    
    set remotetimeout 100000
    
  3. Record an rr trace from command line as usual. (You could perhaps add a Run configuration in CLion if you are doing this often.)

  4. Enter CLion.

  5. Open Run -> Edit Configurations

  6. Click the green + sign, and add a Embedded GDB Server configuration

  7. Fill in the executable binary with the project binary from the dropdown.

  8. Make the debugger "Bundled GDB".

  9. Under "Download executable" select "Never".

  10. Under target remote args, enter :50505, or another port of your choice

  11. Under "GDB Server", enter the path to the rr binary

  12. Under "GDB Server args", enter replay -s 50505 -k.

  13. Set a breakpoint in your program.

  14. Start debugging in CLion by clicking the debug button, making sure your new debug configuration is selected. If the first try fails with "writing to memory outside diversion session", just try clicking the debug button again.

Setting up QtCreator

Set up .gdbinit as for CLion, following steps 1-4 above. Then:

  1. Invoke rr:
    $ rr replay -s 50505 -k
  2. Enter QtCreator.
  3. Open Debug -> Start Debugging -> Attach to Running Debug Server...
  4. Set the field Server Port to 50505 and Override sever address to localhost.
  5. In the field named Local Executable, select the executable that you are running (it is located in the build directory). You can also use the hard link in the rr trace directory, if it is there:
    ~/.local/share/rr/latest-trace/mmap_hardlink_3_executable_name
  6. Start debugging by clicking the "Ok" button.

Setting up Eclipse

  1. Install the Eclipse CDT as usual.
  2. Install rr >= 5.0.
  3. Create a script somewhere like so, calling it e.g. rrgdb:
    #!/bin/bash
    exec rr replay -- "$@"
  4. Record something using rr.
  5. Create a debugging configuration specifying the debugger as rrgdb. Don't enable Eclipse's reverse debugging, it doesn't work with rr.
  6. Launch the debugging configuration. It should work. You may need to manually set a breakpoint at main and then continue to it.
  7. To reverse-execute, open the Debugger Console tab in the Console view and enter manual commands such as reverse-continue (rc), reverse-step (rs), etc

Setting up emacs

See this blog post:

you simply take the suggested command (gdb --fullname or gdb -i=mi), replace gdb with rr replay

Setting up gdbgui

  1. Install gdbgui
  2. Install rr master or >= 5.1.0 (not tested with earlier versions, but may work)
  3. Record something using rr
  4. Replay: gdbgui --gdb-cmd "rr replay --". Optionally specify the directory of the recording: gdbgui DIRECTORY --gdb-cmd "rr replay --"

View demo on YouTube.

Setting up NeoVim

  1. Install neovim
  2. Install the neovim plugin jonboh/nvim-dap-rr
  3. Install rr master or >= 5.6.0
  4. Generate a recording with rr record <path/to/binary>
  5. Start rr with rr replay -s 50505 -k
  6. Attach to the session in NeoVim using DAP
  7. Debug as with any other DAP compatible debugger

View demo

Setting up NeoVim for Rust.

  1. Install neovim and Rust
  2. Install the neovim plugin vlopes11/rrust.nvim
  3. Install rr master or >= 5.6.0 (not tested with earlier versions, but may work)
  4. Record: Position on a test and run :lua require('rrust').RustRRTestRecord()
  5. Replay: Run :lua require('rrust').RustRRTestReplay()

Demo GIF

Setting up seer

  1. Install Seer
  2. Install rr master or >= 5.1.0 (not tested with earlier versions, but may work)
  3. Record something using rr
    $ rr record -n --output-trace-dir=/path/to/rr/trace-directory  myprog arg1 arg2
  1. Run Seer. It will internally run 'rr replay'.
   $ seergdb --rr /path/to/rr/trace-directory

Check out Seer's RR Wiki.

https://github.com/epasveer/seer/wiki/RR-and-Seer

Debugging from a different host

As gdbserver binds to INADDR_ANY by default and rr binds to localhost by default, any debugging, including IDE based, by default only work from the same machine. To allow debugging from another machine follow the steps above, but start the replay with rr replay -h 0.0.0.0 (so other hosts may connect, too) and when attaching drop the sysroot part in the IDE. Note: GDB (on the local machine) will then read all binaries via the remote connection, which may take some time and network io.