In this instalment of gdbWatchPoint, we're looking at how to do less typing. If you're lazy like me, you'll want to do as little typing as possible; so while GDB is a command line tool and it can be quite verbose, you can abbreviate things quite nicely.
These are some examples of doing less typing in GDB which I find very useful.
Often you start debugging by typing 'run' and putting a breakpoint at main. Instead of this, you can do:
...which runs the program but also puts a temporary breakpoint at main.
Short versions of commands
Once your program has hit a breakpoint and waiting for instruction, you'll navigate around using next, continue, step and other commands. All of these can be abbreviated.
And, if you're doing reversible debugging, you can use
rsi. (It makes me laugh that
rsi helps you have less RSI! Hehe!)
These are preset abbreviations but you can also type just enough of a command to be unambiguous and GDB will complete it for you. For example,
isn't unambiguous enough:
But if you type
thr it completes to
You can explore the commands yourself. (Incidentally,
starti is interesting so there's a little extra at the bottom of the post on that.)
Temporary breakpoints save you a bit of typing to delete the breakpoint after it's been hit. For example, you might create a temporary breakpoint on main with:
Using the command history - up/down arrows
The up and down arrows cycle up and down the command history as they do on the linux command line. So if I type the up key, I go back through all the commands in the command history; and if I type down, I go back through them.
The up and down arrows are mirrored in
ctrl-p for previous (instead of up) and
ctrl-n for next (instead of down).
This is important to know because in TUI mode (the Text User Interface), the up and down arrows are hijacked by TUI to move up and down the source code but not the command history. So in TUI mode, you need to use
ctrl-n to navigate your command history and save you some typing.
Searching your history - ctrl-r
if you use bash or similar, you may be familiar with searching your command history with
ctrl-r. To use this, hit
ctrl-r and type part of the line you're searching for.
For example, if you had a non-trivial line like this in your history you might type
ctrl-r lon to find it:
p *(long*)($sp + 28)
If you type
ctrl-r repeatedly, you'll cycle through all the commands which match what you've searched for.
GDB has a few convenience variables such as
$sp for the stack pointer (in x86-64 it's also aliased to $rsp):
Whenever you print something in GDB, you get a convenience variable of the format
$n (where n is an integer). You can use these directly so you can take things you've printed before and manipulate them.
Global history vs local history
If you have set history save on in your GDB config file
~/.gdbinit then something really useful happens: your history is persisted across GDB sessions which allows you to search through them. So when you go up and down the history or search the history, you'll be searching everything you've done in GDB in that project.
This history is stored in the current working directory (so, quite likely the root of your project) in
.gdb_history which you can browse with:
If you want to share your GDB history across all your projects and invocations of GDB, you just have to add this line to your GDB config file
set history file /home/[you]/gdbhistory
Of course, that path can be anything you like.
If you do this, you'll to have a common history across all projects which will save you time if you find yourself running the same debugging commands often. So when you go up and down the history and search it, you'll be looking at everything you've done in all GDB sessions across all your projects.
Bonus tip: starti
starti is interesting. This command starts the program and takes me to the first instruction in the program which is cool for exploring the instructions which are run before 'main', but also if your binary is stripped or doesn't have a 'main' function.