3

I have started using mozilla's rr (timetravelling debugger, github here) on the command line for debugging c++ code.

In emacs I can start it with gud-gdb and writing rr replay (as mentioned here or here).

I cannot start it with gdb followed by rr replay, which is how I usually start gdb in order to work in gdb many-window-mode. (which I have enabled as a setting).

When I try and start it that way I get these error messages to start off with:

Loaded symbols for /lib64/ld-linux-x86-64.so.2
0x00007f53bd89a6b0 in _start () from /lib64/ld-linux-x86-64.so.2
(rr) Undefined command: "1-inferior-tty-set".  Try "help".
(rr) Undefined command: "2-gdb-set".  Try "help".
(rr) Undefined command: "3-gdb-set".  Try "help".
(rr) Undefined command: "4-enable-pretty-printing".  Try "help".
(rr) Undefined command: "5-file-list-exec-source-files".  Try "help".
(rr) Undefined command: "6-file-list-exec-source-file".  Try "help".
(rr) Undefined command: "7-gdb-show".  Try "help".
(rr) Undefined command: "8-stack-info-frame".  Try "help".
(rr) Undefined command: "9-thread-info".  Try "help".
(rr) Undefined command: "10-break-list".  Try "help".
(rr) Undefined command: "11-thread-info".  Try "help".
(rr) Undefined command: "12-break-list".  Try "help".

followed by this error message when I try and run anything from within the gdb session:

(rr) continue
Undefined command: "-interpreter-exec".  Try "help".
(rr) run
Undefined command: "-interpreter-exec".  Try "help".
(rr) break
Undefined command: "-interpreter-exec".  Try "help".
(rr) 

Does anyone know if it is possible to run rr with emacs many-window-mode?

Mike H-R
  • 265
  • 1
  • 8
  • Timetravelling debugger? That sounds so cool! – PythonNut Feb 04 '16 at 16:21
  • It is quite cool. You can run a full application until it crashes with rr tracing the execution. Then run it in gdb until it crashes, set a breakpoint at a function where you think it went wrong and reverse continue and then you're at the last time the function was called before you crashed! – Mike H-R Feb 04 '16 at 17:43

1 Answers1

2

TL;DR wrap gdb in a script that has been put in your path like so:

#!/bin/bash
gdb -i=mi "$@"

then call it with

M-x gdb
rr replay -d name_of_script_i_just_created

If that doesn't work either address the error message in rr to stop it complaining, or patch gdb.el as mentioned below. Long version below.

Alright, I figured it out. It does, (currently) require a bit of a patch to gdb.el and requires an extra bash file.

rr is able to specify the debugger it uses with -d so first you create a wrapped gdb with -i=mi like so:

#!/bin/bash
gdb -i=mi "$@"

which we have called something like gdb-rr-emacs (and which we have added to our path). You can then specify that rr uses that by doing rr replay -d gdb-rr-emacs

If however we have enabled gdb-many-windows and then try and do this we get an error message saying:

Error: you did not specify -i=mi on GDB's command line!

along with a bunch of junk showing that we definitely did specify -i=mi.

This only happens when an error message is displayed at the start of running rr like so:

rr: Warning: Your CPU frequency governor is 'ondemand'. rr strongly recommends that you use the 'performance' governor. Not using the 'performance' governor can cause rr to be at least 2x slower on laptops.

On Fedora-based systems, you can enable the 'performance' governor
by running the following commands:

$ sudo dnf install kernel-tools
$ sudo cpupower frequency-set -g performance

so you can either disable this warning, (as suggested) or do some code-diving (see below).

So when we do some code-diving we find that this error message comes from a function gdb--check-interpreter.

Looking at this function we see it looks like this:

(defun gdb--check-interpreter (filter proc string)
  (unless (zerop (length string))
    (remove-function (process-filter proc) #'gdb--check-interpreter)
    (unless (memq (aref string 0) '(?^ ?~ ?@ ?& ?* ?=))
      ;; Apparently we're not running with -i=mi.
      (let ((msg "Error: you did not specify -i=mi on GDB's command line!"))
        (message msg)
        (setq string (concat (propertize msg 'font-lock-face 'error)
                             "\n" string)))
      ;; Use the old gud-gbd filter, not because it works, but because it
      ;; will properly display GDB's answers rather than hanging waiting for
      ;; answers that aren't coming.
      (set (make-local-variable 'gud-marker-filter) #'gud-gdb-marker-filter)
            )
    (funcall filter proc string)))

if we change it to look like this:

(defun gdb--check-interpreter (filter proc string)
  (unless (zerop (length string))
(remove-function (process-filter proc) #'gdb--check-interpreter)
(unless (memq (aref string 0) '(?^ ?~ ?@ ?& ?* ?=))
  ;; Apparently we're not running with -i=mi.
  (let ((msg "Error: you did not specify -i=mi on GDB's command line! Luckily I don't care!"))
    (message msg)
    (setq string (concat (propertize msg 'font-lock-face 'error)
             "\n" string))))
(funcall filter proc string)))

or similar we will then be able to start our rr session in gdb-many-window mode with:

M-x gdb
rr replay -d gdb-rr-emacs
Mike H-R
  • 265
  • 1
  • 8