[http://users.snap.net.nz/~nickrob/#GDBMI gdb-mi] is a package by Nick
Roberts which makes Emacs use GDB/MI interface to talk with the GNU
Debugger. gdb-mi is currently in Emacs trunk, replacing
the old gdb-ui package in GNU Emacs.
= GSoC 2009 =
«[https://www.google-melange.com/gsoc/project/details/google/gsoc2009/dzhus/5649050225344512
Emacs GDB/MI migration]» is one of two Emacs-related projects which were
[http://socghop.appspot.com/org/home/google/gsoc2009/karlberry accepted] for
GoogleSummerOfCode 2009 program.
The goal of this project is to migrate the GDB graphical interface in
Emacs to completely use GDB's Machine Interface (GDB/MI). This will
make GDB support in Emacs more robust and will allow using of GDB
features available only with MI.
The development is carried out by //Dmitry Dzhus// under mentorship of
//Nick Roberts//.
See this package stats at [https://www.ohloh.net/p/emacs-gdb-mi Ohloh]!
= What's new? =
This section provides an overview of new user-visible features
implemented during Google Summer of Code. This draft serves as a base
for updated section of the Emacs manual (see «GDB Graphical Interface»).
Note that the development version of *GDB 7.0* is needed for this
package to work (-thread-info command, non-stop debugging
support).
=== Stateless debugging ===
With MI, the notion of «current thread» is not so important as it
provides means to query information for any thread without actually
selecting it. This means that much more current thread selection logic
may be implemented in the frontend without relying on the internal
state of the debugger.
It's now possible to observe information for several threads
simultaneously (in addition to buffers which show information for
currently selected thread). Select threads buffer by clicking
«Threads» button or using gdb-display-threads-buffer
command. Now you can ask Emacs to show information for thread under
point using these keybindings, either using the current frame or creating a new one:
; d: gdb-display-disassembly-for-thread
; f: gdb-display-stack-for-thread
; l: gdb-display-locals-for-thread
; r: gdb-display-registers-for-thread
; D: gdb-frame-disassembly-for-thread
; F: gdb-frame-stack-for-thread
; L: gdb-frame-locals-for-thread
; R: gdb-frame-registers-for-thread
(Typing C-h m in threads list buffer will also give you this list.)
When you create a buffer showing information about some specific
thread, it becomes «bound» to that thread and keeps showing actual
information while you debug your program.
=== Non-stop debugging ===
; All-stop debugging: When one thread stops (hitting a breakpoint or
recieving a signal), all threads stop.
; Non-stop debugging: When one thread stops, the rest continue
running.
Non-stop debugging is much less intrusive.
To activate non-stop mode, set gdb-non-stop-setting
customization variables to t. Note that changing this
while debugging a program has no effect.
By default, when a thread stops in non-stop mode, Emacs automatically
switches to that thread.
It may be undesirable to let Emacs switch current thread when you
already have some other stopped thread selected. Set
gdb-switch-when-another-stopped to nil to
prevent this.
Emacs can decide whether or not to switch to stopped thread depending
on the reason which caused the stop. Customize
gdb-switch-reasons to select stop reasons which make
Emacs switch thread.
gdb-stopped-hooks hook variable allows you to execute
your functions whenever some thread stops. For example:
{{{
(defun my-gdb-stopped-hook (record)
(with-current-buffer (get-buffer-create "*debug-stop-log*")
(insert
(format "%s stopped in %s (%s)\n"
(gdb-get-field record 'thread-id)
(gdb-get-field record 'frame 'func)
(gdb-get-field record 'reason)))))
(add-to-list 'gdb-stopped-hooks #'my-gdb-stopped-hook)
}}}
In non-stop mode, you can switch between different modes for GUD
execution control commands.
; Non-stop/A: When gdb-gud-control-all-threads is
t (that's default), interruption & continuation
commands apply to //all// threads, so you can halt or continue all
your threads with one command (gud-stop-subjob and
gud-cont, respectively). Go button is shown on the
toolbar when at least one thread is stopped, whereas Stop button is
shown when at least one thread is running.
; Non-stop/T: Nil gdb-gud-control-all-threads value means
that only current thread is stopped/continued. Go/Stop buttons on
the GUD toolbar are shown depending on the state of current thread.
Stepping commands always apply to current thread.
=== Fine thread control ===
In non-stop mode, you can interrupt/continue your threads without
selecting them. Hitting i in threads list buffer
interrupts thread under point, c continues it,
s steps through. More commands may be added in the
future.
Note that when you interrupt a thread, it stops with «Signal received»
reason. If that reason is included in your
gdb-switch-reasons (it is by default), Emacs will switch
to that thread.
Given that you can create bound buffers for any thread, this allows
you to observe state of many threads in the same time.
See the annotated
[http://www.flickr.com/photos/nothingpersonal/3733686206/ screenshot]
showing how Emacs works with non-stop GDB:
http://farm3.static.flickr.com/2606/3733686206_a84a8b398c.jpg
You can customize what fields are included in stack frames list and
threads list by changing options in gdb-buffers
customization group.
== Development plan ==
The following has been done for gdb-mi.el during Summer of Code 2009.
Implemented buffers for:
# Threads
# Disassembly
# Program memory sections
Major goals:
# Made it possible watch information for several threads simultaneously
# Added non-stop debugging support
Internals (you don't want to read this):
# Got closer to MVC (gdb-buf-publisher provides a cleaner way to ask buffers to update; we maintain gdb-breakpoints-list and gdb-threads-list; we're still tied to «one buffer — one handler» model)
# Most of code now uses JSON parser instead of regular expressions to parse MI responses.
# Handle all MI async records
== Related public discussions ==
* «[http://thread.gmane.org/gmane.comp.gdb.devel/25753 GDB frontends, MI-speak and object notation]» @ gdb: Working with MI responses in an object-like manner. Redundancies in GDB/MI output syntax.
* «[http://thread.gmane.org/gmane.emacs.devel/111635 fadr]» @ emacs-devel: Why fadr.el is a bad idea
** «[http://groups.google.com/group/comp.lang.lisp/browse_frm/thread/5c6247038a229755/4ddce0bdb7be088b What makes different things lispy or unlispy?]» @ c.l.l: Related discussion.
* «[http://thread.gmane.org/gmane.comp.gdb.devel/26025 Learn function name by its address]» @ gdb: -symbol-info-symbol and unimplemented MI commands.
* «[http://emacsbugs.donarmstrong.com/cgi-bin/bugreport.cgi?bug=3794 Error in json from gdb-ui]» @ emacs-bugs: Broken output in -break-list causes JSON parser to suffer *fixed*. RET behaviour in GUD buffer *fixed*. GDB shell command and GUD buffer *fixed*. Killing GDB buffer does not send detach command. while/if misbehaving. Completion.
* «[http://thread.gmane.org/gmane.emacs.help/66312 Problems with gdb and program files in another directory than current working directory]» @ emacs-help: No source file named . problem *fixed*.
* «[http://thread.gmane.org/gmane.emacs.help/66357 gdb in Emacs 23]» @ emacs-help: RET behavour (second report).
* «[http://article.gmane.org/gmane.emacs.help/66465 M-x gdb doesn't work anymore with Emacs 23.1.50.1]» @ emacs-help: No source file named . (second report). Shell aliases are ignored when running GDB under Emacs
== Force gdb-mi not to set windows as dedicated ==
gdb-mi.el sets all its windows to be dedicated by default which means that if one tries to switch-buffer in one of gdb-mi.el's dedicated windows the buffer will appear in a different window instead. This can be rather annoying, so here's a quick fix using advice to override gdb-mi.el's window dedication.
{{{
;; Force gdb-mi to not dedicate any windows
(advice-add 'gdb-display-buffer
:around (lambda (orig-fun &rest r)
(let ((window (apply orig-fun r)))
(set-window-dedicated-p window nil)
window)))
(advice-add 'gdb-set-window-buffer
:around (lambda (orig-fun name &optional ignore-dedicated window)
(funcall orig-fun name ignore-dedicated window)
(set-window-dedicated-p window nil)))
}}}