This package provides a graphical interface to the GDB debugger. It is intended to be fast and intuitive.
It was made as a drop-in replacement for the builtin package gdb-mi (check this question for the reason behind rewriting the entire package from scratch).
- Fast
- Instead of parsing the GDB/MI output in Elisp, I’ve created a dynamic module in C, which makes it run fast like a bullet!
- Easy to use
- The keybindings, which were inspired by Visual Studio and Qt Creator, were chosen to be easy to memorize and to provide the best interaction possible without much putting much strain on your fingers.
- Does what you meant
- Each command tries its best to infer what you meant when you run them.
- Organized
- You can change which buffer is displayed in each window, and even pop buffers to their own separate frames!
- Simultaneous sessions
- You can debug multiple programs at the same time, with different GDB sessions; each session creates its own frame.
- Debug remotely
- You may debug programs remotely over TRAMP!
- Threads
- Stack frames
- Breakpoints
- Automatic variables
- Watchers
- Registers
- Disassembly (of the selected stack frame)
- Inferior I/O
- GDB command shell (please read this question before going crazy!)
- GCC or Clang to compile the dynamic module
- The module is automatically compiled as soon as possible
- GDB (surprise, surprise) is needed to debug programs; I’ve only tested version 8.2, but will probably work on older ones
- Emacs package Hydra is needed for the buffer switcher
This package intentionally uses the name gdb-mi
in order to shadow the builtin package, as it could be
confusing to have two packages with the same purpose installed.
The easiest way to install it is by using Quelpa, which builds the packages for you from any source you want.
In order to install, give Quelpa the following package recipe:
'(gdb-mi :fetcher git
:url "https://github.com/weirdNox/emacs-gdb.git"
:files ("*.el" "*.c" "*.h" "Makefile"))
It is highly recommended that you delete the autoloaded definitions from the builtin package in order to prevent confusion:
(fmakunbound 'gdb)
(fmakunbound 'gdb-enable-debug)
Here is an example configuration using use-package
:
(use-package gdb-mi :quelpa (gdb-mi :fetcher git
:url "https://github.com/weirdNox/emacs-gdb.git"
:files ("*.el" "*.c" "*.h" "Makefile"))
:init
(fmakunbound 'gdb)
(fmakunbound 'gdb-enable-debug))
You may also do everything manually or use another package manager that supports Git repos. Example for
straight.el
:
(use-package gdb-mi
:straight (:host github :repo "weirdNox/emacs-gdb" :files ("*.el" "*.c" "*.h" "Makefile"))
:init
(fmakunbound 'gdb)
(fmakunbound 'gdb-enable-debug))
After the installation is complete, you may start a debugging session.
If you want to debug an executable, run gdb-executable
. You may also use this command to change the
executable being debugged.
If you want another type of target, you may try running gdb-create-session
and then inserting the
commands manually in the shell buffer. I’ve not tested this, so I don’t know how well it works.
The main way to interact with this package is by using the global minor mode gdb-keys-mode
, which
enables the usual keybindings you expect in a debugger, inspired by Visual Studio and Qt Creator:
Keybinding | Description |
---|---|
F5 | Run or continue |
C-F5 | (Re)Start and break at main |
S-F5 | Kill inferior |
F6 | Stop |
F8 | Create watcher |
C-F8 | Evaluate expression once |
F9 | Create or delete breakpoint |
F10 | Step over (instruction wise with M-) |
C-F10 | Run until cursor |
F11 | Step into (instruction wise with M-) |
C-F11 | Advance to cursor |
S-F11 | Step out |
F12 | Switch buffer or pop to frame |
Nevertheless, even without the global minor mode, every buffer has some keybindings associated with it:
Keybinding | Description |
---|---|
SPC | Select thread |
c | Continue thread |
s | Stop thread |
Keybinding | Description |
---|---|
SPC | Select frame |
c | Continue thread |
Keybinding | Description |
---|---|
d or ⌫ or DEL | Delete breakpoint |
SPC | Enable/disable breakpoint |
Keybinding | Description |
---|---|
SPC | Create watcher (prompt with Shift ) |
RET | Create watcher and select window (prompt with Shift ) |
Keybinding | Description |
---|---|
a | Add new expression |
RET | Assign to expression |
e | Edit expression under cursor |
f | Change format |
d | Duplicate |
h | Toggle frame holding |
t | Toggle access specifiers |
SPC or TAB | Toggle children |
⌫ or DEL | Delete watcher |
Keybinding | Description |
---|---|
f | Change format |
SPC | Create watcher (prompt with Shift ) |
RET | Create watcher and select window (prompt with Shift ) |
Keybinding | Description |
---|---|
f | Change format |
F | Change flavor |
gdb-mi
:
- When I wanted to use it, I ended up having to modify and rewrite many functions in order to have predictable functionality
- In some cases, the parsing would be so slow that I could not use it at all (when disassembling a big function and then stepping, for example)
- It felt weird that it changed all my windows instead of opening in a new frame
- Other reasons I’ve forgotten
- I like C, Elisp, and a good challenge: I couldn’t find a package that used dynamic modules and it seemed like the perfect chance to do something I would use, as I couldn’t find a debugger for Linux that I could say I liked.
Well, if you use Emacs, both this and the builtin package are great because you never need to leave the environment you use the rest of the day.
If you don’t use Emacs (but are willing to try it) and you can’t find a good graphical debugger for Linux, this could be it!
If you are already happy with what you have, then there isn’t much to see here. ☺
You may send any GDB command you want.However, keep in mind that if:
- the command does not use the background form (eg.
continue&
), it will block GDB until it finishes what it is doing, so you won’t be able to interact with it! If you want to interrupt it, runcomint-interrupt-subjob
in the command shell buffer (bound to C-c C-c ). - the command does not cause GDB to notify the interface of the changes it made, the interface may become out of sync and start giving errors
- This package uses the library GDBWIRE for parsing the GDB/MI output.
- The original Emacs GDB interface was my main inspiration, so thanks Nick Roberts!